From a6bde0943e7feda25eba15e23a2307227de87d4e Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Thu, 14 Feb 2019 22:01:09 +0000 Subject: Implement proper FFmpeg version checking Three routes to determine FFmpeg version: 1) Grab the 'ffmpeg version x.y' from from the -version output. This should work for all pre-built binaries. 2) Compare the library versions against known contents of FFmpeg versions. This is fallback aimed at custom builds. 3) Compare libavcodec version to determine if newer than latest known release. This suggests user is running within latest/HEAD/master build. --- .../Encoder/EncoderValidator.cs | 188 ++++++++++++++++++++- 1 file changed, 181 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 262772959..275062df5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Globalization; +using System.Collections.ObjectModel; using System.Linq; using System.Text.RegularExpressions; using MediaBrowser.Model.Diagnostics; @@ -8,6 +8,71 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { + public class FFmpegVersion + { + private int _version; + private int _multi => 100; + private const int _unknown = 0; + private const int _experimental = -1; + + public FFmpegVersion(int p1) + { + _version = p1; + } + + public FFmpegVersion(string p1) + { + var match = Regex.Match(p1, @"(?\d+)\.(?\d+)"); + + if (match.Groups["major"].Success && match.Groups["minor"].Success) + { + int major = int.Parse(match.Groups["major"].Value); + int minor = int.Parse(match.Groups["minor"].Value); + _version = (major * _multi) + minor; + } + } + + public override string ToString() + { + switch (_version) + { + case _unknown: + return "Unknown"; + case _experimental: + return "Experimental"; + default: + string major = Convert.ToString(_version / _multi); + string minor = Convert.ToString(_version % _multi); + return string.Concat(major, ".", minor); + } + } + + public bool Unknown() + { + return _version == _unknown; + } + + public int Version() + { + return _version; + } + + public bool Experimental() + { + return _version == _experimental; + } + + public bool Below(FFmpegVersion checkAgainst) + { + return (_version > 0) && (_version < checkAgainst._version); + } + + public bool Suitable(FFmpegVersion checkAgainst) + { + return (_version > 0) && (_version >= checkAgainst._version); + } + } + public class EncoderValidator { private readonly ILogger _logger; @@ -58,18 +123,127 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - output = " " + output + " "; + // The minimum FFmpeg version required to run jellyfin successfully + FFmpegVersion required = new FFmpegVersion("4.0"); + + // Work out what the version under test is + FFmpegVersion underTest = GetFFmpegVersion(output); - for (var i = 2013; i <= 2015; i++) + if (logOutput) { - var yearString = i.ToString(CultureInfo.InvariantCulture); - if (output.IndexOf(" " + yearString + " ", StringComparison.OrdinalIgnoreCase) != -1) + if (underTest.Unknown()) + { + _logger.LogWarning("FFmpeg validation: Unknown version"); + } + else if (underTest.Below(required)) { - return false; + _logger.LogWarning("FFmpeg validation: Found version {0} which is below the minimum recommended of {1}", + underTest.ToString(), required.ToString()); } + else if (underTest.Experimental()) + { + _logger.LogWarning("FFmpeg validation: Unknown version: {0}?", underTest.ToString()); + } + else + { + _logger.LogInformation("FFmpeg validation: Detected version {0}", underTest.ToString()); + } + } + + return underTest.Suitable(required); + } + + /// + /// Using the output from "ffmpeg -version" work out the FFmpeg version. + /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy + /// to parse. If this is not available, then we try to match known library versions to FFmpeg versions. + /// If that fails then we use one of the main libraries to determine if it's new/older than the latest + /// we have stored. + /// + /// + /// + static private FFmpegVersion GetFFmpegVersion(string output) + { + // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output + var match = Regex.Match(output, @"ffmpeg version (\d+\.\d+)"); + + if (match.Success) + { + return new FFmpegVersion(match.Groups[1].Value); + } + else + { + // Try and use the individual library versions to determine a FFmpeg version + // This lookup table is to be maintained with the following command line: + // $ ./ffmpeg.exe -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' + ReadOnlyDictionary lut = new ReadOnlyDictionary + (new Dictionary + { + { new FFmpegVersion("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," }, + { new FFmpegVersion("4.0"), "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1," }, + { new FFmpegVersion("3.4"), "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7," }, + { new FFmpegVersion("3.3"), "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5," }, + { new FFmpegVersion("3.2"), "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1," }, + { new FFmpegVersion("2.8"), "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3," } + }); + + // Create a reduced version string and lookup key from dictionary + var reducedVersion = GetVersionString(output); + var found = lut.FirstOrDefault(x => x.Value == reducedVersion).Key; + + if (found != null) + { + return found; + } + else + { + // Unknown version. Test the main libavcoder version in the candidate with the + // latest from the dictionary. If candidate is greater than dictionary chances are + // the user if running HEAD/master ffmpeg build (which is probably ok) + var firstElement = lut.FirstOrDefault(); + + var reqVer = Regex.Match(firstElement.Value, @"libavcodec=(\d+\.\d+)"); + var gotVer = Regex.Match(reducedVersion, @"libavcodec=(\d+\.\d+)"); + + if (reqVer.Success && gotVer.Success) + { + var req = new FFmpegVersion(reqVer.Groups[1].Value); + var got = new FFmpegVersion(gotVer.Groups[1].Value); + + // The library versions are not comparable with the FFmpeg version so must check + // candidate (got) against value from dictionary (req). Return Experimental if suitable + if( got.Suitable(req) ) + { + return new FFmpegVersion(-1); + + } + } + } + } + + // Default to return Unknown + return new FFmpegVersion(0); + } + + /// + /// Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output + /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc." + /// + /// + /// + static private string GetVersionString(string output) + { + string pattern = @"((?lib\w+)\s+(?\d+)\.\s*(?\d+))"; + RegexOptions options = RegexOptions.Multiline; + + string rc = null; + + foreach (Match m in Regex.Matches(output, pattern, options)) + { + rc += string.Concat(m.Groups["name"], '=', m.Groups["major"], '.', m.Groups["minor"], ','); } - return true; + return rc; } private static readonly string[] requiredDecoders = new[] -- cgit v1.2.3 From d8d237f6f295990c54bb2b0e36e0be04bacbdc3b Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Fri, 15 Feb 2019 23:51:22 +0000 Subject: Review comments Addressed review comments from JustAMan. Removed code to determine experimental version. Store major and minor as two ints. Allow control of a min and max recommended version. --- .../Encoder/EncoderValidator.cs | 110 ++++++++------------- 1 file changed, 42 insertions(+), 68 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 275062df5..ad777a9aa 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -10,15 +10,10 @@ namespace MediaBrowser.MediaEncoding.Encoder { public class FFmpegVersion { - private int _version; - private int _multi => 100; - private const int _unknown = 0; - private const int _experimental = -1; + private readonly int _major; + private readonly int _minor; - public FFmpegVersion(int p1) - { - _version = p1; - } + private const int _unknown = 0; public FFmpegVersion(string p1) { @@ -26,50 +21,50 @@ namespace MediaBrowser.MediaEncoding.Encoder if (match.Groups["major"].Success && match.Groups["minor"].Success) { - int major = int.Parse(match.Groups["major"].Value); - int minor = int.Parse(match.Groups["minor"].Value); - _version = (major * _multi) + minor; + _major = int.Parse(match.Groups["major"].Value); + _minor = int.Parse(match.Groups["minor"].Value); + } + else + { + _major = _unknown; + _minor = _unknown; } } public override string ToString() { - switch (_version) + switch (_major) { case _unknown: return "Unknown"; - case _experimental: - return "Experimental"; default: - string major = Convert.ToString(_version / _multi); - string minor = Convert.ToString(_version % _multi); - return string.Concat(major, ".", minor); + return string.Format("{0}.{1}",_major,_minor); } } public bool Unknown() { - return _version == _unknown; + return _major == _unknown; } - public int Version() + public bool Below(FFmpegVersion checkAgainst) { - return _version; + return ToScalar() < checkAgainst.ToScalar(); } - public bool Experimental() + public bool Above(FFmpegVersion checkAgainst) { - return _version == _experimental; + return ToScalar() > checkAgainst.ToScalar(); } - public bool Below(FFmpegVersion checkAgainst) + public bool Same(FFmpegVersion checkAgainst) { - return (_version > 0) && (_version < checkAgainst._version); + return ToScalar() == checkAgainst.ToScalar(); } - public bool Suitable(FFmpegVersion checkAgainst) + private int ToScalar() { - return (_version > 0) && (_version >= checkAgainst._version); + return (_major * 1000) + _minor; } } @@ -123,34 +118,43 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - // The minimum FFmpeg version required to run jellyfin successfully - FFmpegVersion required = new FFmpegVersion("4.0"); + // The min and max FFmpeg versions required to run jellyfin successfully + FFmpegVersion minRequired = new FFmpegVersion("4.0"); + FFmpegVersion maxRequired = new FFmpegVersion("4.0"); // Work out what the version under test is FFmpegVersion underTest = GetFFmpegVersion(output); if (logOutput) { + _logger.LogInformation("FFmpeg validation: Found ffmpeg version {0}", underTest.ToString()); + if (underTest.Unknown()) { - _logger.LogWarning("FFmpeg validation: Unknown version"); + if (minRequired.Same(maxRequired)) + { + _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", minRequired.ToString()); + } + else + { + _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", minRequired.ToString(), maxRequired.ToString()); + } } - else if (underTest.Below(required)) + else if (underTest.Below(minRequired)) { - _logger.LogWarning("FFmpeg validation: Found version {0} which is below the minimum recommended of {1}", - underTest.ToString(), required.ToString()); + _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", minRequired.ToString()); } - else if (underTest.Experimental()) + else if (underTest.Above(maxRequired)) { - _logger.LogWarning("FFmpeg validation: Unknown version: {0}?", underTest.ToString()); + _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", maxRequired.ToString()); } else { - _logger.LogInformation("FFmpeg validation: Detected version {0}", underTest.ToString()); + // Version is ok so no warning required } } - return underTest.Suitable(required); + return !underTest.Below(minRequired) && !underTest.Above(maxRequired); } /// @@ -176,7 +180,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Try and use the individual library versions to determine a FFmpeg version // This lookup table is to be maintained with the following command line: // $ ./ffmpeg.exe -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' - ReadOnlyDictionary lut = new ReadOnlyDictionary + var lut = new ReadOnlyDictionary (new Dictionary { { new FFmpegVersion("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," }, @@ -191,38 +195,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var reducedVersion = GetVersionString(output); var found = lut.FirstOrDefault(x => x.Value == reducedVersion).Key; - if (found != null) - { - return found; - } - else - { - // Unknown version. Test the main libavcoder version in the candidate with the - // latest from the dictionary. If candidate is greater than dictionary chances are - // the user if running HEAD/master ffmpeg build (which is probably ok) - var firstElement = lut.FirstOrDefault(); - - var reqVer = Regex.Match(firstElement.Value, @"libavcodec=(\d+\.\d+)"); - var gotVer = Regex.Match(reducedVersion, @"libavcodec=(\d+\.\d+)"); - - if (reqVer.Success && gotVer.Success) - { - var req = new FFmpegVersion(reqVer.Groups[1].Value); - var got = new FFmpegVersion(gotVer.Groups[1].Value); - - // The library versions are not comparable with the FFmpeg version so must check - // candidate (got) against value from dictionary (req). Return Experimental if suitable - if( got.Suitable(req) ) - { - return new FFmpegVersion(-1); - - } - } - } + return found ?? new FFmpegVersion("Unknown"); } - - // Default to return Unknown - return new FFmpegVersion(0); } /// -- cgit v1.2.3 From 69ea15f73a053e2526457b0eec757fb6f1ca1cd7 Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Sat, 16 Feb 2019 00:47:38 +0000 Subject: Use string interpolation Two further review comments from JustAMan. --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index ad777a9aa..be33ea58e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.MediaEncoding.Encoder case _unknown: return "Unknown"; default: - return string.Format("{0}.{1}",_major,_minor); + return $"{_major}.{_minor}"; } } @@ -150,7 +150,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - // Version is ok so no warning required + _logger.LogInformation("FFmpeg validation: Found suitable ffmpeg version"); } } -- cgit v1.2.3 From a23f04623ed2738ab1205717674614e9eed6b548 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sat, 16 Feb 2019 12:39:53 +0100 Subject: Remove IEncryptionManager --- Emby.Server.Implementations/ApplicationHost.cs | 4 +- .../Security/EncryptionManager.cs | 57 ---------------------- .../Security/IEncryptionManager.cs | 19 -------- .../Subtitles/OpenSubtitleDownloader.cs | 19 ++++---- 4 files changed, 11 insertions(+), 88 deletions(-) delete mode 100644 Emby.Server.Implementations/Security/EncryptionManager.cs delete mode 100644 MediaBrowser.Controller/Security/IEncryptionManager.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 8daba0585..dcf2098d4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -739,10 +739,8 @@ namespace Emby.Server.Implementations TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager); serviceCollection.AddSingleton(TVSeriesManager); - var encryptionManager = new EncryptionManager(); - serviceCollection.AddSingleton(encryptionManager); - DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager); + serviceCollection.AddSingleton(DeviceManager); MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); diff --git a/Emby.Server.Implementations/Security/EncryptionManager.cs b/Emby.Server.Implementations/Security/EncryptionManager.cs deleted file mode 100644 index fa8872ccc..000000000 --- a/Emby.Server.Implementations/Security/EncryptionManager.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Text; -using MediaBrowser.Controller.Security; - -namespace Emby.Server.Implementations.Security -{ - public class EncryptionManager : IEncryptionManager - { - /// - /// Encrypts the string. - /// - /// The value. - /// System.String. - /// value - public string EncryptString(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - return EncryptStringUniversal(value); - } - - /// - /// Decrypts the string. - /// - /// The value. - /// System.String. - /// value - public string DecryptString(string value) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - return DecryptStringUniversal(value); - } - - private static string EncryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Encoding.UTF8.GetBytes(value); - return Convert.ToBase64String(bytes); - } - - private static string DecryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Convert.FromBase64String(value); - return Encoding.UTF8.GetString(bytes, 0, bytes.Length); - } - } -} diff --git a/MediaBrowser.Controller/Security/IEncryptionManager.cs b/MediaBrowser.Controller/Security/IEncryptionManager.cs deleted file mode 100644 index 68680fdf3..000000000 --- a/MediaBrowser.Controller/Security/IEncryptionManager.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace MediaBrowser.Controller.Security -{ - public interface IEncryptionManager - { - /// - /// Encrypts the string. - /// - /// The value. - /// System.String. - string EncryptString(string value); - - /// - /// Decrypts the string. - /// - /// The value. - /// System.String. - string DecryptString(string value); - } -} diff --git a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs index 6a5162b8d..c76ff3fed 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -29,17 +30,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; - private readonly IEncryptionManager _encryption; private readonly IJsonSerializer _json; private readonly IFileSystem _fileSystem; - public OpenSubtitleDownloader(ILoggerFactory loggerFactory, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json, IFileSystem fileSystem) + public OpenSubtitleDownloader(ILoggerFactory loggerFactory, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem) { _logger = loggerFactory.CreateLogger(GetType().Name); _httpClient = httpClient; _config = config; - _encryption = encryption; _json = json; _fileSystem = fileSystem; @@ -63,16 +62,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) && !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) { - options.OpenSubtitlesPasswordHash = EncryptPassword(options.OpenSubtitlesPasswordHash); + options.OpenSubtitlesPasswordHash = ToBase64EncodedString(options.OpenSubtitlesPasswordHash); } } - private string EncryptPassword(string password) + private static string ToBase64EncodedString(string password) { - return PasswordHashPrefix + _encryption.EncryptString(password); + var bytes = Encoding.UTF8.GetBytes(password); + return PasswordHashPrefix + bytes; } - private string DecryptPassword(string password) + private static string DecodeBase64EncodedString(string password) { if (password == null || !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) @@ -80,7 +80,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles return string.Empty; } - return _encryption.DecryptString(password.Substring(2)); + var bytes = Convert.FromBase64String(password.Substring(2)); + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); } public string Name => "Open Subtitles"; @@ -186,7 +187,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var options = GetOptions(); var user = options.OpenSubtitlesUsername ?? string.Empty; - var password = DecryptPassword(options.OpenSubtitlesPasswordHash); + var password = DecodeBase64EncodedString(options.OpenSubtitlesPasswordHash); var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From 1e2050f1065551222bbd053473830b2c1a950793 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sat, 16 Feb 2019 12:44:17 +0100 Subject: Rename functions to match functionality --- MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs index c76ff3fed..dde4ee7ad 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs @@ -62,17 +62,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) && !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) { - options.OpenSubtitlesPasswordHash = ToBase64EncodedString(options.OpenSubtitlesPasswordHash); + options.OpenSubtitlesPasswordHash = EncodePassword(options.OpenSubtitlesPasswordHash); } } - private static string ToBase64EncodedString(string password) + private static string EncodePassword(string password) { var bytes = Encoding.UTF8.GetBytes(password); return PasswordHashPrefix + bytes; } - private static string DecodeBase64EncodedString(string password) + private static string DecodePassword(string password) { if (password == null || !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) @@ -187,7 +187,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var options = GetOptions(); var user = options.OpenSubtitlesUsername ?? string.Empty; - var password = DecodeBase64EncodedString(options.OpenSubtitlesPasswordHash); + var password = DecodePassword(options.OpenSubtitlesPasswordHash); var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From 139807719c9f7a0176eeacf7a64c95dc070850bc Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sat, 16 Feb 2019 17:21:42 +0100 Subject: Add missing base64 conversion --- MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs index dde4ee7ad..a7e3f6197 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private static string EncodePassword(string password) { var bytes = Encoding.UTF8.GetBytes(password); - return PasswordHashPrefix + bytes; + return PasswordHashPrefix + Convert.ToBase64String(bytes); } private static string DecodePassword(string password) -- cgit v1.2.3 From aafed63c3f635ccac82be41b5a8f272121397b79 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Sun, 24 Feb 2019 16:33:05 +0100 Subject: Set EnableRaisingEvents to true for processes that require it --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d922f1068..7f29c06b4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -694,7 +694,8 @@ namespace MediaBrowser.MediaEncoding.Encoder FileName = FFMpegPath, Arguments = args, IsHidden = true, - ErrorDialog = false + ErrorDialog = false, + EnableRaisingEvents = true }); _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -816,7 +817,8 @@ namespace MediaBrowser.MediaEncoding.Encoder FileName = FFMpegPath, Arguments = args, IsHidden = true, - ErrorDialog = false + ErrorDialog = false, + EnableRaisingEvents = true }); _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments); -- cgit v1.2.3 From 7668ecf9c95fe7deb8211704c24266d5b17f6c8c Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Wed, 27 Feb 2019 18:20:48 +0000 Subject: Use Version Class to ease comparisons --- .../Encoder/EncoderValidator.cs | 105 +++++---------------- 1 file changed, 23 insertions(+), 82 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index be33ea58e..5ebd189ac 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -8,66 +8,6 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { - public class FFmpegVersion - { - private readonly int _major; - private readonly int _minor; - - private const int _unknown = 0; - - public FFmpegVersion(string p1) - { - var match = Regex.Match(p1, @"(?\d+)\.(?\d+)"); - - if (match.Groups["major"].Success && match.Groups["minor"].Success) - { - _major = int.Parse(match.Groups["major"].Value); - _minor = int.Parse(match.Groups["minor"].Value); - } - else - { - _major = _unknown; - _minor = _unknown; - } - } - - public override string ToString() - { - switch (_major) - { - case _unknown: - return "Unknown"; - default: - return $"{_major}.{_minor}"; - } - } - - public bool Unknown() - { - return _major == _unknown; - } - - public bool Below(FFmpegVersion checkAgainst) - { - return ToScalar() < checkAgainst.ToScalar(); - } - - public bool Above(FFmpegVersion checkAgainst) - { - return ToScalar() > checkAgainst.ToScalar(); - } - - public bool Same(FFmpegVersion checkAgainst) - { - return ToScalar() == checkAgainst.ToScalar(); - } - - private int ToScalar() - { - return (_major * 1000) + _minor; - } - } - public class EncoderValidator { private readonly ILogger _logger; @@ -119,19 +59,19 @@ namespace MediaBrowser.MediaEncoding.Encoder } // The min and max FFmpeg versions required to run jellyfin successfully - FFmpegVersion minRequired = new FFmpegVersion("4.0"); - FFmpegVersion maxRequired = new FFmpegVersion("4.0"); + var minRequired = new Version(4, 0); + var maxRequired = new Version(4, 0); // Work out what the version under test is - FFmpegVersion underTest = GetFFmpegVersion(output); + var underTest = GetFFmpegVersion(output); if (logOutput) { - _logger.LogInformation("FFmpeg validation: Found ffmpeg version {0}", underTest.ToString()); + _logger.LogInformation("FFmpeg validation: Found ffmpeg version {0}", underTest != null ? underTest.ToString() : "unknown"); - if (underTest.Unknown()) + if (underTest == null) // Version is unknown { - if (minRequired.Same(maxRequired)) + if (minRequired.Equals(maxRequired)) { _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", minRequired.ToString()); } @@ -140,21 +80,22 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", minRequired.ToString(), maxRequired.ToString()); } } - else if (underTest.Below(minRequired)) + else if (underTest.CompareTo(minRequired) < 0) // Version is below what we recommend { _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", minRequired.ToString()); } - else if (underTest.Above(maxRequired)) + else if (underTest.CompareTo(maxRequired) > 0) // Version is above what we recommend { _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", maxRequired.ToString()); } - else + else // Version is ok { _logger.LogInformation("FFmpeg validation: Found suitable ffmpeg version"); } } - return !underTest.Below(minRequired) && !underTest.Above(maxRequired); + // underTest shall be null if versions is unknown + return (underTest == null) ? false : !(underTest.CompareTo(minRequired) < 0) && !(underTest.CompareTo(maxRequired) > 0); } /// @@ -166,36 +107,36 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - static private FFmpegVersion GetFFmpegVersion(string output) + static private Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output var match = Regex.Match(output, @"ffmpeg version (\d+\.\d+)"); if (match.Success) { - return new FFmpegVersion(match.Groups[1].Value); + return new Version(match.Groups[1].Value); } else { // Try and use the individual library versions to determine a FFmpeg version // This lookup table is to be maintained with the following command line: // $ ./ffmpeg.exe -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' - var lut = new ReadOnlyDictionary - (new Dictionary + var lut = new ReadOnlyDictionary + (new Dictionary { - { new FFmpegVersion("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," }, - { new FFmpegVersion("4.0"), "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1," }, - { new FFmpegVersion("3.4"), "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7," }, - { new FFmpegVersion("3.3"), "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5," }, - { new FFmpegVersion("3.2"), "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1," }, - { new FFmpegVersion("2.8"), "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3," } + { new Version("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," }, + { new Version("4.0"), "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1," }, + { new Version("3.4"), "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7," }, + { new Version("3.3"), "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5," }, + { new Version("3.2"), "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1," }, + { new Version("2.8"), "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3," } }); // Create a reduced version string and lookup key from dictionary var reducedVersion = GetVersionString(output); - var found = lut.FirstOrDefault(x => x.Value == reducedVersion).Key; - return found ?? new FFmpegVersion("Unknown"); + // Try to lookup the string and return Key, otherwise if not found returns null + return lut.FirstOrDefault(x => x.Value == reducedVersion).Key; } } -- cgit v1.2.3 From f1086a72bf1ebf486464c877efb66bb4f87771fe Mon Sep 17 00:00:00 2001 From: Vasily Date: Thu, 28 Feb 2019 15:58:41 +0000 Subject: Improve logic when determining return value Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 5ebd189ac..f725d2c01 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // underTest shall be null if versions is unknown - return (underTest == null) ? false : !(underTest.CompareTo(minRequired) < 0) && !(underTest.CompareTo(maxRequired) > 0); + return (underTest == null) ? false : (underTest.CompareTo(minRequired) >= 0 && underTest.CompareTo(maxRequired) <= 0); } /// -- cgit v1.2.3 From 20775116f76b12bf77672fa37c4ea5f82b69f157 Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Fri, 8 Feb 2019 13:35:26 +0000 Subject: Reworked FFmpeg path discovery and always display to user 1) Reworked FFmpeg and FFprobe path discovery (CLI switch, Custom xml, system $PATH, UI update trigger). Removed FFMpeg folder from Emby.Server.Implementations. All path discovery now in MediaEncoder. 2) Always display FFmpeg path to user in Transcode page. 3) Allow user to remove a Custome FFmpeg path and return to using system $PATH (or --ffmpeg if available). 4) Remove unused code associated with 'prebuilt' FFmpeg. 5) Much improved logging during path discovery. --- Emby.Server.Implementations/ApplicationHost.cs | 72 +--- Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs | 24 -- .../FFMpeg/FFMpegInstallInfo.cs | 17 - Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs | 132 ------- .../Encoder/EncoderValidator.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 433 ++++++++++----------- .../Configuration/EncodingOptions.cs | 3 +- 7 files changed, 212 insertions(+), 471 deletions(-) delete mode 100644 Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs delete mode 100644 Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs delete mode 100644 Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 94d2cd5da..2c0d0e746 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -28,7 +28,6 @@ using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Devices; using Emby.Server.Implementations.Diagnostics; using Emby.Server.Implementations.Dto; -using Emby.Server.Implementations.FFMpeg; using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer.Security; using Emby.Server.Implementations.IO; @@ -792,7 +791,8 @@ namespace Emby.Server.Implementations ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); serviceCollection.AddSingleton(ChapterManager); - RegisterMediaEncoder(serviceCollection); + MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(LoggerFactory, JsonSerializer, StartupOptions.FFmpegPath, StartupOptions.FFprobePath, ServerConfigurationManager, FileSystemManager, () => SubtitleEncoder, () => MediaSourceManager, ProcessFactory, 5000); + serviceCollection.AddSingleton(MediaEncoder); EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); serviceCollection.AddSingleton(EncodingManager); @@ -908,83 +908,25 @@ namespace Emby.Server.Implementations return new ImageProcessor(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); } - protected virtual FFMpegInstallInfo GetFfmpegInstallInfo() - { - var info = new FFMpegInstallInfo(); - - // Windows builds: http://ffmpeg.zeranoe.com/builds/ - // Linux builds: http://johnvansickle.com/ffmpeg/ - // OS X builds: http://ffmpegmac.net/ - // OS X x64: http://www.evermeet.cx/ffmpeg/ - - if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Linux) - { - info.FFMpegFilename = "ffmpeg"; - info.FFProbeFilename = "ffprobe"; - info.ArchiveType = "7z"; - info.Version = "20170308"; - } - else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) - { - info.FFMpegFilename = "ffmpeg.exe"; - info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20170308"; - info.ArchiveType = "7z"; - } - else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX) - { - info.FFMpegFilename = "ffmpeg"; - info.FFProbeFilename = "ffprobe"; - info.ArchiveType = "7z"; - info.Version = "20170308"; - } - - return info; - } - - protected virtual FFMpegInfo GetFFMpegInfo() - { - return new FFMpegLoader(ApplicationPaths, FileSystemManager, GetFfmpegInstallInfo()) - .GetFFMpegInfo(StartupOptions); - } - /// /// Registers the media encoder. /// /// Task. - private void RegisterMediaEncoder(IServiceCollection serviceCollection) + private void RegisterMediaEncoder(IAssemblyInfo assemblyInfo) { - string encoderPath = null; - string probePath = null; - - var info = GetFFMpegInfo(); - - encoderPath = info.EncoderPath; - probePath = info.ProbePath; - var hasExternalEncoder = string.Equals(info.Version, "external", StringComparison.OrdinalIgnoreCase); - - var mediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( + MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( LoggerFactory, JsonSerializer, - encoderPath, - probePath, - hasExternalEncoder, + StartupOptions.FFmpegPath, + StartupOptions.FFprobePath, ServerConfigurationManager, FileSystemManager, - LiveTvManager, - IsoManager, - LibraryManager, - ChannelManager, - SessionManager, () => SubtitleEncoder, () => MediaSourceManager, - HttpClient, - ZipClient, ProcessFactory, 5000); - MediaEncoder = mediaEncoder; - serviceCollection.AddSingleton(MediaEncoder); + RegisterSingleInstance(MediaEncoder); } /// diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs b/Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs deleted file mode 100644 index 60cd7b3d7..000000000 --- a/Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Emby.Server.Implementations.FFMpeg -{ - /// - /// Class FFMpegInfo - /// - public class FFMpegInfo - { - /// - /// Gets or sets the path. - /// - /// The path. - public string EncoderPath { get; set; } - /// - /// Gets or sets the probe path. - /// - /// The probe path. - public string ProbePath { get; set; } - /// - /// Gets or sets the version. - /// - /// The version. - public string Version { get; set; } - } -} diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs b/Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs deleted file mode 100644 index fa9cb5e01..000000000 --- a/Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Emby.Server.Implementations.FFMpeg -{ - public class FFMpegInstallInfo - { - public string Version { get; set; } - public string FFMpegFilename { get; set; } - public string FFProbeFilename { get; set; } - public string ArchiveType { get; set; } - - public FFMpegInstallInfo() - { - Version = "Path"; - FFMpegFilename = "ffmpeg"; - FFProbeFilename = "ffprobe"; - } - } -} diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs deleted file mode 100644 index bbf51dd24..000000000 --- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.IO; - -namespace Emby.Server.Implementations.FFMpeg -{ - public class FFMpegLoader - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - private readonly FFMpegInstallInfo _ffmpegInstallInfo; - - public FFMpegLoader(IApplicationPaths appPaths, IFileSystem fileSystem, FFMpegInstallInfo ffmpegInstallInfo) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - _ffmpegInstallInfo = ffmpegInstallInfo; - } - - public FFMpegInfo GetFFMpegInfo(IStartupOptions options) - { - var customffMpegPath = options.FFmpegPath; - var customffProbePath = options.FFprobePath; - - if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath)) - { - return new FFMpegInfo - { - ProbePath = customffProbePath, - EncoderPath = customffMpegPath, - Version = "external" - }; - } - - var downloadInfo = _ffmpegInstallInfo; - - var prebuiltFolder = _appPaths.ProgramSystemPath; - var prebuiltffmpeg = Path.Combine(prebuiltFolder, downloadInfo.FFMpegFilename); - var prebuiltffprobe = Path.Combine(prebuiltFolder, downloadInfo.FFProbeFilename); - if (File.Exists(prebuiltffmpeg) && File.Exists(prebuiltffprobe)) - { - return new FFMpegInfo - { - ProbePath = prebuiltffprobe, - EncoderPath = prebuiltffmpeg, - Version = "external" - }; - } - - var version = downloadInfo.Version; - - if (string.Equals(version, "0", StringComparison.OrdinalIgnoreCase)) - { - return new FFMpegInfo(); - } - - var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg"); - var versionedDirectoryPath = Path.Combine(rootEncoderPath, version); - - var info = new FFMpegInfo - { - ProbePath = Path.Combine(versionedDirectoryPath, downloadInfo.FFProbeFilename), - EncoderPath = Path.Combine(versionedDirectoryPath, downloadInfo.FFMpegFilename), - Version = version - }; - - Directory.CreateDirectory(versionedDirectoryPath); - - var excludeFromDeletions = new List { versionedDirectoryPath }; - - if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath)) - { - // ffmpeg not present. See if there's an older version we can start with - var existingVersion = GetExistingVersion(info, rootEncoderPath); - - // No older version. Need to download and block until complete - if (existingVersion == null) - { - return new FFMpegInfo(); - } - else - { - info = existingVersion; - versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath); - excludeFromDeletions.Add(versionedDirectoryPath); - } - } - - // Allow just one of these to be overridden, if desired. - if (!string.IsNullOrWhiteSpace(customffMpegPath)) - { - info.EncoderPath = customffMpegPath; - } - if (!string.IsNullOrWhiteSpace(customffProbePath)) - { - info.ProbePath = customffProbePath; - } - - return info; - } - - private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath) - { - var encoderFilename = Path.GetFileName(info.EncoderPath); - var probeFilename = Path.GetFileName(info.ProbePath); - - foreach (var directory in _fileSystem.GetDirectoryPaths(rootEncoderPath)) - { - var allFiles = _fileSystem.GetFilePaths(directory, true).ToList(); - - var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase)); - var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase)); - - if (!string.IsNullOrWhiteSpace(encoder) && - !string.IsNullOrWhiteSpace(probe)) - { - return new FFMpegInfo - { - EncoderPath = encoder, - ProbePath = probe, - Version = Path.GetFileName(Path.GetDirectoryName(probe)) - }; - } - } - - return null; - } - } -} diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f725d2c01..1eeea87a0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _processFactory = processFactory; } - public (IEnumerable decoders, IEnumerable encoders) Validate(string encoderPath) + public (IEnumerable decoders, IEnumerable encoders) GetAvailableCoders(string encoderPath) { _logger.LogInformation("Validating media encoder at {EncoderPath}", encoderPath); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7f29c06b4..36d72cad9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -7,13 +7,9 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Session; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Diagnostics; @@ -32,323 +28,288 @@ namespace MediaBrowser.MediaEncoding.Encoder public class MediaEncoder : IMediaEncoder, IDisposable { /// - /// The _logger - /// - private readonly ILogger _logger; - - /// - /// Gets the json serializer. + /// Gets the encoder path. /// - /// The json serializer. - private readonly IJsonSerializer _jsonSerializer; + /// The encoder path. + public string EncoderPath => FFmpegPath; /// - /// The _thumbnail resource pool + /// External: path supplied via command line + /// Custom: coming from UI or config/encoding.xml file + /// System: FFmpeg found in system $PATH + /// null: No FFmpeg found /// - private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); - - public string FFMpegPath { get; private set; } - - public string FFProbePath { get; private set; } + public string EncoderLocationType { get; private set; } + private readonly ILogger _logger; + private readonly IJsonSerializer _jsonSerializer; + private string FFmpegPath { get; set; } + private string FFprobePath { get; set; } protected readonly IServerConfigurationManager ConfigurationManager; protected readonly IFileSystem FileSystem; - protected readonly ILiveTvManager LiveTvManager; - protected readonly IIsoManager IsoManager; - protected readonly ILibraryManager LibraryManager; - protected readonly IChannelManager ChannelManager; - protected readonly ISessionManager SessionManager; protected readonly Func SubtitleEncoder; protected readonly Func MediaSourceManager; - private readonly IHttpClient _httpClient; - private readonly IZipClient _zipClient; private readonly IProcessFactory _processFactory; + private readonly int DefaultImageExtractionTimeoutMs; + private readonly string StartupOptionFFmpegPath; + private readonly string StartupOptionFFprobePath; + private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); private readonly List _runningProcesses = new List(); - private readonly bool _hasExternalEncoder; - private readonly string _originalFFMpegPath; - private readonly string _originalFFProbePath; - private readonly int DefaultImageExtractionTimeoutMs; public MediaEncoder( ILoggerFactory loggerFactory, IJsonSerializer jsonSerializer, - string ffMpegPath, - string ffProbePath, - bool hasExternalEncoder, + string startupOptionsFFmpegPath, + string startupOptionsFFprobePath, IServerConfigurationManager configurationManager, IFileSystem fileSystem, - ILiveTvManager liveTvManager, - IIsoManager isoManager, - ILibraryManager libraryManager, - IChannelManager channelManager, - ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager, - IHttpClient httpClient, - IZipClient zipClient, IProcessFactory processFactory, int defaultImageExtractionTimeoutMs) { _logger = loggerFactory.CreateLogger(nameof(MediaEncoder)); _jsonSerializer = jsonSerializer; + StartupOptionFFmpegPath = startupOptionsFFmpegPath; + StartupOptionFFprobePath = startupOptionsFFprobePath; ConfigurationManager = configurationManager; FileSystem = fileSystem; - LiveTvManager = liveTvManager; - IsoManager = isoManager; - LibraryManager = libraryManager; - ChannelManager = channelManager; - SessionManager = sessionManager; SubtitleEncoder = subtitleEncoder; - MediaSourceManager = mediaSourceManager; - _httpClient = httpClient; - _zipClient = zipClient; _processFactory = processFactory; DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs; - FFProbePath = ffProbePath; - FFMpegPath = ffMpegPath; - _originalFFProbePath = ffProbePath; - _originalFFMpegPath = ffMpegPath; - _hasExternalEncoder = hasExternalEncoder; } - public string EncoderLocationType + /// + /// Run at startup or if the user removes a Custom path from transcode page. + /// Sets global variables FFmpegPath and EncoderLocationType. + /// If startup options --ffprobe is given then FFprobePath is set too. + /// + public void Init() { - get + // 1) If given, use the --ffmpeg CLI switch + if (ValidatePathFFmpeg("From CLI Switch", StartupOptionFFmpegPath)) { - if (_hasExternalEncoder) - { - return "External"; - } - - if (string.IsNullOrWhiteSpace(FFMpegPath)) - { - return null; - } - - if (IsSystemInstalledPath(FFMpegPath)) - { - return "System"; - } - - return "Custom"; + _logger.LogInformation("FFmpeg: Using path from command line switch --ffmpeg"); + EncoderLocationType = "External"; } - } - private bool IsSystemInstalledPath(string path) - { - if (path.IndexOf("/", StringComparison.Ordinal) == -1 && path.IndexOf("\\", StringComparison.Ordinal) == -1) + // 2) Try Custom path stroed in config/encoding xml file under tag + else if (ValidatePathFFmpeg("From Config File", ConfigurationManager.GetConfiguration("encoding").EncoderAppPathCustom)) { - return true; + _logger.LogInformation("FFmpeg: Using path from config/encoding.xml file"); + EncoderLocationType = "Custom"; } - return false; - } - - public void Init() - { - InitPaths(); - - if (!string.IsNullOrWhiteSpace(FFMpegPath)) + // 3) Search system $PATH environment variable for valid FFmpeg + else if (ValidatePathFFmpeg("From $PATH", ExistsOnSystemPath("ffmpeg"))) { - var result = new EncoderValidator(_logger, _processFactory).Validate(FFMpegPath); - - SetAvailableDecoders(result.decoders); - SetAvailableEncoders(result.encoders); + _logger.LogInformation("FFmpeg: Using system $PATH for FFmpeg"); + EncoderLocationType = "System"; + } + else + { + _logger.LogError("FFmpeg: No suitable executable found"); + FFmpegPath = null; + EncoderLocationType = null; } - } - - private void InitPaths() - { - ConfigureEncoderPaths(); - if (_hasExternalEncoder) + // If given, use the --ffprobe CLI switch + if (ValidatePathFFprobe("CLI Switch", StartupOptionFFprobePath)) { - LogPaths(); - return; + _logger.LogInformation("FFprobe: Using path from command line switch --ffprobe"); + } + else + { + // FFprobe path from command line is no good, so set to null and let ReInit() try + // and set using the FFmpeg path. + FFprobePath = null; } - // If the path was passed in, save it into config now. - var encodingOptions = GetEncodingOptions(); - var appPath = encodingOptions.EncoderAppPath; + ReInit(); + } - var valueToSave = FFMpegPath; + /// + /// Writes the currently used FFmpeg to config/encoding.xml file. + /// Sets the FFprobe path if not currently set. + /// Interrogates the FFmpeg tool to identify what encoders/decodres are available. + /// + private void ReInit() + { + // Write the FFmpeg path to the config/encoding.xml file so it appears in UI + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPath = FFmpegPath ?? string.Empty; + ConfigurationManager.SaveConfiguration("encoding", config); - if (!string.IsNullOrWhiteSpace(valueToSave)) + // Only if mpeg path is set, try and set path to probe + if (FFmpegPath != null) { - // if using system variable, don't save this. - if (IsSystemInstalledPath(valueToSave) || _hasExternalEncoder) + // Probe would be null here if no valid --ffprobe path was given + // at startup, or we're performing ReInit following mpeg path update from UI + if (FFprobePath == null) { - valueToSave = null; + // Use the mpeg path to create a probe path + if (ValidatePathFFprobe("Copied from FFmpeg:", GetProbePathFromEncoderPath(FFmpegPath))) + { + _logger.LogInformation("FFprobe: Using FFprobe in same folders as FFmpeg"); + } + else + { + _logger.LogError("FFprobe: No suitable executable found"); + } } - } - if (!string.Equals(valueToSave, appPath, StringComparison.Ordinal)) - { - encodingOptions.EncoderAppPath = valueToSave; - ConfigurationManager.SaveConfiguration("encoding", encodingOptions); + // Interrogate to understand what coders it supports + var result = new EncoderValidator(_logger, _processFactory).GetAvailableCoders(FFmpegPath); + + SetAvailableDecoders(result.decoders); + SetAvailableEncoders(result.encoders); } + + // Stamp FFmpeg paths to the log file + LogPaths(); } + /// + /// Triggered from the Settings > Trascoding UI page when users sumits Custom FFmpeg path to use. + /// + /// + /// public void UpdateEncoderPath(string path, string pathType) { - if (_hasExternalEncoder) - { - return; - } - _logger.LogInformation("Attempting to update encoder path to {0}. pathType: {1}", path ?? string.Empty, pathType ?? string.Empty); - Tuple newPaths; - - if (string.Equals(pathType, "system", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase)) { - path = "ffmpeg"; - - newPaths = TestForInstalledVersions(); + throw new ArgumentException("Unexpected pathType value"); } - else if (string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase)) + else { if (string.IsNullOrWhiteSpace(path)) { - throw new ArgumentNullException(nameof(path)); - } + // User had cleared the cutom path in UI. Clear the Custom config + // setting and peform full Init to relook any CLI switches and system $PATH + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPathCustom = string.Empty; + ConfigurationManager.SaveConfiguration("encoding", config); - if (!File.Exists(path) && !Directory.Exists(path)) + Init(); + } + else if (!File.Exists(path) && !Directory.Exists(path)) { + // Given path is neither file or folder throw new ResourceNotFoundException(); } - newPaths = GetEncoderPaths(path); - } - else - { - throw new ArgumentException("Unexpected pathType value"); - } - - if (string.IsNullOrWhiteSpace(newPaths.Item1)) - { - throw new ResourceNotFoundException("ffmpeg not found"); - } - if (string.IsNullOrWhiteSpace(newPaths.Item2)) - { - throw new ResourceNotFoundException("ffprobe not found"); - } - - path = newPaths.Item1; + else + { + // Supplied path could be either file path or folder path. + // Resolve down to file path and validate + path = GetEncoderPath(path); - if (!ValidateVersion(path, true)) - { - throw new ResourceNotFoundException("ffmpeg version 3.0 or greater is required."); - } + if (path == null) + { + throw new ResourceNotFoundException("FFmpeg not found"); + } + else if (!ValidatePathFFmpeg("New From UI", path)) + { + throw new ResourceNotFoundException("Failed validation checks. Version 4.0 or greater is required"); + } + else + { + EncoderLocationType = "Custom"; - var config = GetEncodingOptions(); - config.EncoderAppPath = path; - ConfigurationManager.SaveConfiguration("encoding", config); + // Write the validated mpeg path to the xml as + // This ensures its not lost on new startup + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPathCustom = FFmpegPath; + ConfigurationManager.SaveConfiguration("encoding", config); - Init(); - } + FFprobePath = null; // Clear probe path so it gets relooked in ReInit() - private bool ValidateVersion(string path, bool logOutput) - { - return new EncoderValidator(_logger, _processFactory).ValidateVersion(path, logOutput); + ReInit(); + } + } + } } - private void ConfigureEncoderPaths() + private bool ValidatePath(string type, string path) { - if (_hasExternalEncoder) + if (!string.IsNullOrEmpty(path)) { - return; - } - - var appPath = GetEncodingOptions().EncoderAppPath; + if (File.Exists(path)) + { + var valid = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true); - if (string.IsNullOrWhiteSpace(appPath)) - { - appPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg"); + if (valid == true) + { + return true; + } + else + { + _logger.LogError("{0}: Failed validation checks. Version 4.0 or greater is required: {1}", type, path); + } + } + else + { + _logger.LogError("{0}: File not found: {1}", type, path); + } } - var newPaths = GetEncoderPaths(appPath); - if (string.IsNullOrWhiteSpace(newPaths.Item1) || string.IsNullOrWhiteSpace(newPaths.Item2) || IsSystemInstalledPath(appPath)) - { - newPaths = TestForInstalledVersions(); - } + return false; + } - if (!string.IsNullOrWhiteSpace(newPaths.Item1) && !string.IsNullOrWhiteSpace(newPaths.Item2)) + private bool ValidatePathFFmpeg(string comment, string path) + { + if (ValidatePath("FFmpeg: " + comment, path) == true) { - FFMpegPath = newPaths.Item1; - FFProbePath = newPaths.Item2; + FFmpegPath = path; + return true; } - LogPaths(); + return false; } - private Tuple GetEncoderPaths(string configuredPath) + private bool ValidatePathFFprobe(string comment, string path) { - var appPath = configuredPath; - - if (!string.IsNullOrWhiteSpace(appPath)) + if (ValidatePath("FFprobe: " + comment, path) == true) { - if (Directory.Exists(appPath)) - { - return GetPathsFromDirectory(appPath); - } - - if (File.Exists(appPath)) - { - return new Tuple(appPath, GetProbePathFromEncoderPath(appPath)); - } + FFprobePath = path; + return true; } - return new Tuple(null, null); + return false; } - private Tuple TestForInstalledVersions() + private string GetEncoderPath(string path) { - string encoderPath = null; - string probePath = null; - - if (_hasExternalEncoder && ValidateVersion(_originalFFMpegPath, true)) + if (Directory.Exists(path)) { - encoderPath = _originalFFMpegPath; - probePath = _originalFFProbePath; + return GetEncoderPathFromDirectory(path); } - if (string.IsNullOrWhiteSpace(encoderPath)) + if (File.Exists(path)) { - if (ValidateVersion("ffmpeg", true) && ValidateVersion("ffprobe", false)) - { - encoderPath = "ffmpeg"; - probePath = "ffprobe"; - } + return path; } - return new Tuple(encoderPath, probePath); + return null; } - private Tuple GetPathsFromDirectory(string path) + private string GetEncoderPathFromDirectory(string path) { - // Since we can't predict the file extension, first try directly within the folder - // If that doesn't pan out, then do a recursive search - var files = FileSystem.GetFilePaths(path); - - var excludeExtensions = new[] { ".c" }; - - var ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); - var ffprobePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); - - if (string.IsNullOrWhiteSpace(ffmpegPath) || !File.Exists(ffmpegPath)) + try { - files = FileSystem.GetFilePaths(path, true); + var files = FileSystem.GetFilePaths(path); - ffmpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); + var excludeExtensions = new[] { ".c" }; - if (!string.IsNullOrWhiteSpace(ffmpegPath)) - { - ffprobePath = GetProbePathFromEncoderPath(ffmpegPath); - } + return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); + } + catch (Exception) + { + // Trap all exceptions, like DirNotExists, and return null + return null; } - - return new Tuple(ffmpegPath, ffprobePath); } private string GetProbePathFromEncoderPath(string appPath) @@ -357,15 +318,31 @@ namespace MediaBrowser.MediaEncoding.Encoder .FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase)); } - private void LogPaths() + /// + /// Search the system $PATH environment variable looking for given filename. + /// + /// + /// + private string ExistsOnSystemPath(string fileName) { - _logger.LogInformation("FFMpeg: {0}", FFMpegPath ?? "not found"); - _logger.LogInformation("FFProbe: {0}", FFProbePath ?? "not found"); + var values = Environment.GetEnvironmentVariable("PATH"); + + foreach (var path in values.Split(Path.PathSeparator)) + { + var candidatePath = GetEncoderPathFromDirectory(path); + + if (ValidatePath("Found on PATH", candidatePath)) + { + return candidatePath; + } + } + return null; } - private EncodingOptions GetEncodingOptions() + private void LogPaths() { - return ConfigurationManager.GetConfiguration("encoding"); + _logger.LogInformation("FFMpeg: {0}", FFmpegPath ?? "not found"); + _logger.LogInformation("FFProbe: {0}", FFprobePath ?? "not found"); } private List _encoders = new List(); @@ -412,12 +389,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return true; } - /// - /// Gets the encoder path. - /// - /// The encoder path. - public string EncoderPath => FFMpegPath; - /// /// Gets the media info. /// @@ -489,7 +460,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Must consume both or ffmpeg may hang due to deadlocks. See comments below. RedirectStandardOutput = true, - FileName = FFProbePath, + FileName = FFprobePath, Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(), IsHidden = true, @@ -691,7 +662,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFMpegPath, + FileName = FFmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, @@ -814,7 +785,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFMpegPath, + FileName = FFmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 8584bd3dd..ff697437a 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -8,7 +8,8 @@ namespace MediaBrowser.Model.Configuration public bool EnableThrottling { get; set; } public int ThrottleDelaySeconds { get; set; } public string HardwareAccelerationType { get; set; } - public string EncoderAppPath { get; set; } + public string EncoderAppPathCustom { get; set; } // FFmpeg path as set by the user via the UI + public string EncoderAppPath { get; set; } // The current FFmpeg path being used by the system public string VaapiDevice { get; set; } public int H264Crf { get; set; } public string H264Preset { get; set; } -- cgit v1.2.3 From ed69e690b89e6a3e6e22bbf448af08a25c38e71b Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Tue, 12 Feb 2019 22:05:42 +0000 Subject: Review comments Address review comments from JustAMan, Bond-009 and cvium. --- Emby.Server.Implementations/ApplicationHost.cs | 35 +-- .../MediaEncoding/IMediaEncoder.cs | 3 +- .../Encoder/EncoderValidator.cs | 8 + MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 247 ++++++++++----------- MediaBrowser.Model/System/SystemInfo.cs | 17 +- 5 files changed, 150 insertions(+), 160 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 2c0d0e746..dd29f2ade 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -791,7 +791,17 @@ namespace Emby.Server.Implementations ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); serviceCollection.AddSingleton(ChapterManager); - MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(LoggerFactory, JsonSerializer, StartupOptions.FFmpegPath, StartupOptions.FFprobePath, ServerConfigurationManager, FileSystemManager, () => SubtitleEncoder, () => MediaSourceManager, ProcessFactory, 5000); + MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( + LoggerFactory, + JsonSerializer, + StartupOptions.FFmpegPath, + StartupOptions.FFprobePath, + ServerConfigurationManager, + FileSystemManager, + () => SubtitleEncoder, + () => MediaSourceManager, + ProcessFactory, + 5000); serviceCollection.AddSingleton(MediaEncoder); EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); @@ -908,27 +918,6 @@ namespace Emby.Server.Implementations return new ImageProcessor(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); } - /// - /// Registers the media encoder. - /// - /// Task. - private void RegisterMediaEncoder(IAssemblyInfo assemblyInfo) - { - MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - LoggerFactory, - JsonSerializer, - StartupOptions.FFmpegPath, - StartupOptions.FFprobePath, - ServerConfigurationManager, - FileSystemManager, - () => SubtitleEncoder, - () => MediaSourceManager, - ProcessFactory, - 5000); - - RegisterSingleInstance(MediaEncoder); - } - /// /// Gets the user repository. /// @@ -1404,7 +1393,7 @@ namespace Emby.Server.Implementations ServerName = FriendlyName, LocalAddress = localAddress, SupportsLibraryMonitor = true, - EncoderLocationType = MediaEncoder.EncoderLocationType, + EncoderLocation = MediaEncoder.EncoderLocation, SystemArchitecture = EnvironmentInfo.SystemArchitecture, SystemUpdateLevel = SystemUpdateLevel, PackageName = StartupOptions.PackageName diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 057e43910..8852dac05 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.System; namespace MediaBrowser.Controller.MediaEncoding { @@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// public interface IMediaEncoder : ITranscoderSupport { - string EncoderLocationType { get; } + FFmpegLocation EncoderLocation { get; } /// /// Gets the encoder path. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 1eeea87a0..3eed891cb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -48,6 +48,10 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.IsNullOrWhiteSpace(output)) { + if (logOutput) + { + _logger.LogError("FFmpeg validation: The process returned no result"); + } return false; } @@ -55,6 +59,10 @@ namespace MediaBrowser.MediaEncoding.Encoder if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1) { + if (logOutput) + { + _logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported"); + } return false; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 36d72cad9..9aad67ec7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -18,6 +19,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder @@ -34,17 +36,16 @@ namespace MediaBrowser.MediaEncoding.Encoder public string EncoderPath => FFmpegPath; /// - /// External: path supplied via command line - /// Custom: coming from UI or config/encoding.xml file - /// System: FFmpeg found in system $PATH - /// null: No FFmpeg found + /// The location of the discovered FFmpeg tool. /// - public string EncoderLocationType { get; private set; } + public FFmpegLocation EncoderLocation { get; private set; } + + private FFmpegLocation ProbeLocation; private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; - private string FFmpegPath { get; set; } - private string FFprobePath { get; set; } + private string FFmpegPath; + private string FFprobePath; protected readonly IServerConfigurationManager ConfigurationManager; protected readonly IFileSystem FileSystem; protected readonly Func SubtitleEncoder; @@ -54,6 +55,11 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string StartupOptionFFmpegPath; private readonly string StartupOptionFFprobePath; + /// + /// Enum to identify the two types of FF utilities of interest. + /// + private enum FFtype { Mpeg, Probe }; + private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); private readonly List _runningProcesses = new List(); @@ -82,48 +88,24 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Run at startup or if the user removes a Custom path from transcode page. - /// Sets global variables FFmpegPath and EncoderLocationType. - /// If startup options --ffprobe is given then FFprobePath is set too. + /// Sets global variables FFmpegPath. + /// Precedence is: Config > CLI > $PATH /// public void Init() { - // 1) If given, use the --ffmpeg CLI switch - if (ValidatePathFFmpeg("From CLI Switch", StartupOptionFFmpegPath)) - { - _logger.LogInformation("FFmpeg: Using path from command line switch --ffmpeg"); - EncoderLocationType = "External"; - } - - // 2) Try Custom path stroed in config/encoding xml file under tag - else if (ValidatePathFFmpeg("From Config File", ConfigurationManager.GetConfiguration("encoding").EncoderAppPathCustom)) - { - _logger.LogInformation("FFmpeg: Using path from config/encoding.xml file"); - EncoderLocationType = "Custom"; - } - - // 3) Search system $PATH environment variable for valid FFmpeg - else if (ValidatePathFFmpeg("From $PATH", ExistsOnSystemPath("ffmpeg"))) + // 1) Custom path stored in config/encoding xml file under tag takes precedence + if (!ValidatePath(FFtype.Mpeg, ConfigurationManager.GetConfiguration("encoding").EncoderAppPathCustom, FFmpegLocation.Custom)) { - _logger.LogInformation("FFmpeg: Using system $PATH for FFmpeg"); - EncoderLocationType = "System"; - } - else - { - _logger.LogError("FFmpeg: No suitable executable found"); - FFmpegPath = null; - EncoderLocationType = null; - } - - // If given, use the --ffprobe CLI switch - if (ValidatePathFFprobe("CLI Switch", StartupOptionFFprobePath)) - { - _logger.LogInformation("FFprobe: Using path from command line switch --ffprobe"); - } - else - { - // FFprobe path from command line is no good, so set to null and let ReInit() try - // and set using the FFmpeg path. - FFprobePath = null; + // 2) Check if the --ffmpeg CLI switch has been given + if (!ValidatePath(FFtype.Mpeg, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + { + // 3) Search system $PATH environment variable for valid FFmpeg + if (!ValidatePath(FFtype.Mpeg, ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) + { + EncoderLocation = FFmpegLocation.NotFound; + FFmpegPath = null; + } + } } ReInit(); @@ -136,27 +118,27 @@ namespace MediaBrowser.MediaEncoding.Encoder /// private void ReInit() { - // Write the FFmpeg path to the config/encoding.xml file so it appears in UI + // Write the FFmpeg path to the config/encoding.xml file as so it appears in UI var config = ConfigurationManager.GetConfiguration("encoding"); config.EncoderAppPath = FFmpegPath ?? string.Empty; ConfigurationManager.SaveConfiguration("encoding", config); + // Clear probe settings in case probe validation fails + ProbeLocation = FFmpegLocation.NotFound; + FFprobePath = null; + // Only if mpeg path is set, try and set path to probe if (FFmpegPath != null) { - // Probe would be null here if no valid --ffprobe path was given - // at startup, or we're performing ReInit following mpeg path update from UI - if (FFprobePath == null) + if (EncoderLocation == FFmpegLocation.Custom || StartupOptionFFprobePath == null) { - // Use the mpeg path to create a probe path - if (ValidatePathFFprobe("Copied from FFmpeg:", GetProbePathFromEncoderPath(FFmpegPath))) - { - _logger.LogInformation("FFprobe: Using FFprobe in same folders as FFmpeg"); - } - else - { - _logger.LogError("FFprobe: No suitable executable found"); - } + // If mpeg was read from config, or CLI switch not given, try and set probe from mpeg path + ValidatePath(FFtype.Probe, GetProbePathFromEncoderPath(FFmpegPath), EncoderLocation); + } + else + { + // Else try and set probe path from CLI switch + ValidatePath(FFtype.Probe, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument); } // Interrogate to understand what coders it supports @@ -183,108 +165,95 @@ namespace MediaBrowser.MediaEncoding.Encoder { throw new ArgumentException("Unexpected pathType value"); } - else + + if (string.IsNullOrWhiteSpace(path)) { - if (string.IsNullOrWhiteSpace(path)) - { - // User had cleared the cutom path in UI. Clear the Custom config - // setting and peform full Init to relook any CLI switches and system $PATH - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathCustom = string.Empty; - ConfigurationManager.SaveConfiguration("encoding", config); + // User had cleared the custom path in UI. Clear the Custom config + // setting and perform full Init to reinspect any CLI switches and system $PATH + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPathCustom = string.Empty; + ConfigurationManager.SaveConfiguration("encoding", config); - Init(); - } - else if (!File.Exists(path) && !Directory.Exists(path)) + Init(); + } + else if (!File.Exists(path) && !Directory.Exists(path)) + { + // Given path is neither file or folder + throw new ResourceNotFoundException(); + } + else + { + // Supplied path could be either file path or folder path. + // Resolve down to file path and validate + if (!ValidatePath(FFtype.Mpeg, GetEncoderPath(path), FFmpegLocation.Custom)) { - // Given path is neither file or folder - throw new ResourceNotFoundException(); + throw new ResourceNotFoundException("Failed validation checks."); } else { - // Supplied path could be either file path or folder path. - // Resolve down to file path and validate - path = GetEncoderPath(path); - - if (path == null) - { - throw new ResourceNotFoundException("FFmpeg not found"); - } - else if (!ValidatePathFFmpeg("New From UI", path)) - { - throw new ResourceNotFoundException("Failed validation checks. Version 4.0 or greater is required"); - } - else - { - EncoderLocationType = "Custom"; - - // Write the validated mpeg path to the xml as - // This ensures its not lost on new startup - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathCustom = FFmpegPath; - ConfigurationManager.SaveConfiguration("encoding", config); - - FFprobePath = null; // Clear probe path so it gets relooked in ReInit() + // Write the validated mpeg path to the xml as + // This ensures its not lost on new startup + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPathCustom = FFmpegPath; + ConfigurationManager.SaveConfiguration("encoding", config); - ReInit(); - } + ReInit(); } } } - private bool ValidatePath(string type, string path) + /// + /// Validates the supplied FQPN to ensure it is a FFxxx utility. + /// If checks pass, global variable FFmpegPath (or FFprobePath) and + /// EncoderLocation (or ProbeLocation) are updated. + /// + /// Either mpeg or probe + /// FQPN to test + /// Location (External, Custom, System) of tool + /// + private bool ValidatePath(FFtype type, string path, FFmpegLocation location) { + bool rc = false; + if (!string.IsNullOrEmpty(path)) { if (File.Exists(path)) { - var valid = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true); + rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, false); - if (valid == true) + // Only update the global variables if the checks passed + if (rc) { - return true; + if (type == FFtype.Mpeg) + { + FFmpegPath = path; + EncoderLocation = location; + } + else + { + FFprobePath = path; + ProbeLocation = location; + } } else { - _logger.LogError("{0}: Failed validation checks. Version 4.0 or greater is required: {1}", type, path); + _logger.LogError("{0}: {1}: Failed version check: {2}", type.ToString(), location.ToString(), path); } } else { - _logger.LogError("{0}: File not found: {1}", type, path); + _logger.LogError("{0}: {1}: File not found: {2}", type.ToString(), location.ToString(), path); } } - return false; - } - - private bool ValidatePathFFmpeg(string comment, string path) - { - if (ValidatePath("FFmpeg: " + comment, path) == true) - { - FFmpegPath = path; - return true; - } - - return false; - } - - private bool ValidatePathFFprobe(string comment, string path) - { - if (ValidatePath("FFprobe: " + comment, path) == true) - { - FFprobePath = path; - return true; - } - - return false; + return rc; } private string GetEncoderPath(string path) { if (Directory.Exists(path)) { - return GetEncoderPathFromDirectory(path); + return GetEncoderPathFromDirectory(path, "ffmpeg"); } if (File.Exists(path)) @@ -295,7 +264,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return null; } - private string GetEncoderPathFromDirectory(string path) + private string GetEncoderPathFromDirectory(string path, string filename) { try { @@ -303,7 +272,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var excludeExtensions = new[] { ".c" }; - return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase) && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); + return files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), filename, StringComparison.OrdinalIgnoreCase) + && !excludeExtensions.Contains(Path.GetExtension(i) ?? string.Empty)); } catch (Exception) { @@ -314,8 +284,15 @@ namespace MediaBrowser.MediaEncoding.Encoder private string GetProbePathFromEncoderPath(string appPath) { - return FileSystem.GetFilePaths(Path.GetDirectoryName(appPath)) - .FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase)); + if (!string.IsNullOrEmpty(appPath)) + { + string pattern = @"[^\/\\]+?(\.[^\/\\\n.]+)?$"; + string substitution = @"ffprobe$1"; + + return Regex.Replace(appPath, pattern, substitution); + } + + return null; } /// @@ -323,15 +300,15 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - private string ExistsOnSystemPath(string fileName) + private string ExistsOnSystemPath(string filename) { var values = Environment.GetEnvironmentVariable("PATH"); foreach (var path in values.Split(Path.PathSeparator)) { - var candidatePath = GetEncoderPathFromDirectory(path); + var candidatePath = GetEncoderPathFromDirectory(path, filename); - if (ValidatePath("Found on PATH", candidatePath)) + if (!string.IsNullOrEmpty(candidatePath)) { return candidatePath; } @@ -341,8 +318,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private void LogPaths() { - _logger.LogInformation("FFMpeg: {0}", FFmpegPath ?? "not found"); - _logger.LogInformation("FFProbe: {0}", FFprobePath ?? "not found"); + _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty); + _logger.LogInformation("FFprobe: {0}: {1}", ProbeLocation.ToString(), FFprobePath ?? string.Empty); } private List _encoders = new List(); diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 581a1069c..6482f2c84 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -4,6 +4,21 @@ using MediaBrowser.Model.Updates; namespace MediaBrowser.Model.System { + /// + /// Enum describing the location of the FFmpeg tool. + /// + public enum FFmpegLocation + { + /// No path to FFmpeg found. + NotFound, + /// Path supplied via command line using switch --ffmpeg. + SetByArgument, + /// User has supplied path via Transcoding UI page. + Custom, + /// FFmpeg tool found on system $PATH. + System + }; + /// /// Class SystemInfo /// @@ -122,7 +137,7 @@ namespace MediaBrowser.Model.System /// true if this instance has update available; otherwise, false. public bool HasUpdateAvailable { get; set; } - public string EncoderLocationType { get; set; } + public FFmpegLocation EncoderLocation { get; set; } public Architecture SystemArchitecture { get; set; } -- cgit v1.2.3 From 8104e739d5b83d0d6563bb685f910697e60d6c12 Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Wed, 27 Feb 2019 16:33:08 +0000 Subject: Address review comments from Bond --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 10 ++++++++-- MediaBrowser.Model/Configuration/EncodingOptions.cs | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9aad67ec7..265c043b9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -282,12 +282,18 @@ namespace MediaBrowser.MediaEncoding.Encoder } } + /// + /// With the given path string, replaces the filename with ffprobe, taking case + /// of any file extension (like .exe on windows). + /// + /// + /// private string GetProbePathFromEncoderPath(string appPath) { if (!string.IsNullOrEmpty(appPath)) { - string pattern = @"[^\/\\]+?(\.[^\/\\\n.]+)?$"; - string substitution = @"ffprobe$1"; + const string pattern = @"[^\/\\]+?(\.[^\/\\\n.]+)?$"; + const string substitution = @"ffprobe$1"; return Regex.Replace(appPath, pattern, substitution); } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index ff697437a..7fc985ba0 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -8,8 +8,14 @@ namespace MediaBrowser.Model.Configuration public bool EnableThrottling { get; set; } public int ThrottleDelaySeconds { get; set; } public string HardwareAccelerationType { get; set; } - public string EncoderAppPathCustom { get; set; } // FFmpeg path as set by the user via the UI - public string EncoderAppPath { get; set; } // The current FFmpeg path being used by the system + /// + /// FFmpeg path as set by the user via the UI + /// + public string EncoderAppPathCustom { get; set; } + /// + /// The current FFmpeg path being used by the system + /// + public string EncoderAppPath { get; set; } public string VaapiDevice { get; set; } public int H264Crf { get; set; } public string H264Preset { get; set; } -- cgit v1.2.3 From 656bffbbb291dc9b58443bb36c8ed7d3688f6c1b Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Thu, 28 Feb 2019 22:06:56 +0000 Subject: Remove --ffprobe logic --- Jellyfin.Server/StartupOptions.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 185 ++++++--------------- .../Configuration/EncodingOptions.cs | 6 +- 3 files changed, 58 insertions(+), 137 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 5d3f7b171..c8cdb984d 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -20,10 +20,10 @@ namespace Jellyfin.Server [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")] public string LogDir { get; set; } - [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH. Must be specified along with --ffprobe.")] + [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")] public string FFmpegPath { get; set; } - [Option("ffprobe", Required = false, HelpText = "Path to external FFprobe executable to use in place of default found in PATH. Must be specified along with --ffmpeg.")] + [Option("ffprobe", Required = false, HelpText = "(deprecated) Option has no effect and shall be removed in next release.")] public string FFprobePath { get; set; } [Option("service", Required = false, HelpText = "Run as headless service.")] diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 265c043b9..51b4f6e39 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -40,8 +40,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// public FFmpegLocation EncoderLocation { get; private set; } - private FFmpegLocation ProbeLocation; - private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; private string FFmpegPath; @@ -55,11 +53,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string StartupOptionFFmpegPath; private readonly string StartupOptionFFprobePath; - /// - /// Enum to identify the two types of FF utilities of interest. - /// - private enum FFtype { Mpeg, Probe }; - private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); private readonly List _runningProcesses = new List(); @@ -93,14 +86,20 @@ namespace MediaBrowser.MediaEncoding.Encoder /// public void Init() { - // 1) Custom path stored in config/encoding xml file under tag takes precedence - if (!ValidatePath(FFtype.Mpeg, ConfigurationManager.GetConfiguration("encoding").EncoderAppPathCustom, FFmpegLocation.Custom)) + // ToDo - Finalise removal of the --ffprobe switch + if (!string.IsNullOrEmpty(StartupOptionFFprobePath)) + { + _logger.LogWarning("--ffprobe switch is deprecated and shall be removed in the next release"); + } + + // 1) Custom path stored in config/encoding xml file under tag takes precedence + if (!ValidatePath(ConfigurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) { // 2) Check if the --ffmpeg CLI switch has been given - if (!ValidatePath(FFtype.Mpeg, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + if (!ValidatePath(StartupOptionFFmpegPath, FFmpegLocation.SetByArgument)) { // 3) Search system $PATH environment variable for valid FFmpeg - if (!ValidatePath(FFtype.Mpeg, ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) + if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) { EncoderLocation = FFmpegLocation.NotFound; FFmpegPath = null; @@ -108,110 +107,80 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - ReInit(); - } - - /// - /// Writes the currently used FFmpeg to config/encoding.xml file. - /// Sets the FFprobe path if not currently set. - /// Interrogates the FFmpeg tool to identify what encoders/decodres are available. - /// - private void ReInit() - { - // Write the FFmpeg path to the config/encoding.xml file as so it appears in UI + // Write the FFmpeg path to the config/encoding.xml file as so it appears in UI var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPath = FFmpegPath ?? string.Empty; + config.EncoderAppPathDisplay = FFmpegPath ?? string.Empty; ConfigurationManager.SaveConfiguration("encoding", config); - // Clear probe settings in case probe validation fails - ProbeLocation = FFmpegLocation.NotFound; - FFprobePath = null; - // Only if mpeg path is set, try and set path to probe if (FFmpegPath != null) { - if (EncoderLocation == FFmpegLocation.Custom || StartupOptionFFprobePath == null) - { - // If mpeg was read from config, or CLI switch not given, try and set probe from mpeg path - ValidatePath(FFtype.Probe, GetProbePathFromEncoderPath(FFmpegPath), EncoderLocation); - } - else - { - // Else try and set probe path from CLI switch - ValidatePath(FFtype.Probe, StartupOptionFFmpegPath, FFmpegLocation.SetByArgument); - } + // Determine a probe path from the mpeg path + FFprobePath = Regex.Replace(FFmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); - // Interrogate to understand what coders it supports + // Interrogate to understand what coders are supported var result = new EncoderValidator(_logger, _processFactory).GetAvailableCoders(FFmpegPath); SetAvailableDecoders(result.decoders); SetAvailableEncoders(result.encoders); } - // Stamp FFmpeg paths to the log file - LogPaths(); + _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty); } /// - /// Triggered from the Settings > Trascoding UI page when users sumits Custom FFmpeg path to use. + /// Triggered from the Settings > Transcoding UI page when users submits Custom FFmpeg path to use. + /// Only write the new path to xml if it exists. Do not perform validation checks on ffmpeg here. /// /// /// public void UpdateEncoderPath(string path, string pathType) { + string newPath; + _logger.LogInformation("Attempting to update encoder path to {0}. pathType: {1}", path ?? string.Empty, pathType ?? string.Empty); if (!string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Unexpected pathType value"); } - - if (string.IsNullOrWhiteSpace(path)) + else if (string.IsNullOrWhiteSpace(path)) { - // User had cleared the custom path in UI. Clear the Custom config - // setting and perform full Init to reinspect any CLI switches and system $PATH - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathCustom = string.Empty; - ConfigurationManager.SaveConfiguration("encoding", config); - - Init(); + // User had cleared the custom path in UI + newPath = string.Empty; } - else if (!File.Exists(path) && !Directory.Exists(path)) + else if (File.Exists(path)) { - // Given path is neither file or folder - throw new ResourceNotFoundException(); + newPath = path; + } + else if (Directory.Exists(path)) + { + // Given path is directory, so resolve down to filename + newPath = GetEncoderPathFromDirectory(path, "ffmpeg"); } else { - // Supplied path could be either file path or folder path. - // Resolve down to file path and validate - if (!ValidatePath(FFtype.Mpeg, GetEncoderPath(path), FFmpegLocation.Custom)) - { - throw new ResourceNotFoundException("Failed validation checks."); - } - else - { - // Write the validated mpeg path to the xml as - // This ensures its not lost on new startup - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathCustom = FFmpegPath; - ConfigurationManager.SaveConfiguration("encoding", config); - - ReInit(); - } + throw new ResourceNotFoundException(); } + + // Write the new ffmpeg path to the xml as + // This ensures its not lost on next startup + var config = ConfigurationManager.GetConfiguration("encoding"); + config.EncoderAppPath = newPath; + ConfigurationManager.SaveConfiguration("encoding", config); + + // Trigger Init so we validate the new path and setup probe path + Init(); } /// - /// Validates the supplied FQPN to ensure it is a FFxxx utility. - /// If checks pass, global variable FFmpegPath (or FFprobePath) and - /// EncoderLocation (or ProbeLocation) are updated. + /// Validates the supplied FQPN to ensure it is a ffmpeg utility. + /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. /// - /// Either mpeg or probe /// FQPN to test /// Location (External, Custom, System) of tool /// - private bool ValidatePath(FFtype type, string path, FFmpegLocation location) + private bool ValidatePath(string path, FFmpegLocation location) { bool rc = false; @@ -219,51 +188,28 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (File.Exists(path)) { - rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, false); + rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true); - // Only update the global variables if the checks passed - if (rc) + if (!rc) { - if (type == FFtype.Mpeg) - { - FFmpegPath = path; - EncoderLocation = location; - } - else - { - FFprobePath = path; - ProbeLocation = location; - } - } - else - { - _logger.LogError("{0}: {1}: Failed version check: {2}", type.ToString(), location.ToString(), path); + _logger.LogWarning("FFmpeg: {0}: Failed version check: {1}", location.ToString(), path); } + + // ToDo - Enable the ffmpeg validator. At the moment any version can be used. + rc = true; + + FFmpegPath = path; + EncoderLocation = location; } else { - _logger.LogError("{0}: {1}: File not found: {2}", type.ToString(), location.ToString(), path); + _logger.LogWarning("FFmpeg: {0}: File not found: {1}", location.ToString(), path); } } return rc; } - private string GetEncoderPath(string path) - { - if (Directory.Exists(path)) - { - return GetEncoderPathFromDirectory(path, "ffmpeg"); - } - - if (File.Exists(path)) - { - return path; - } - - return null; - } - private string GetEncoderPathFromDirectory(string path, string filename) { try @@ -282,25 +228,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - /// - /// With the given path string, replaces the filename with ffprobe, taking case - /// of any file extension (like .exe on windows). - /// - /// - /// - private string GetProbePathFromEncoderPath(string appPath) - { - if (!string.IsNullOrEmpty(appPath)) - { - const string pattern = @"[^\/\\]+?(\.[^\/\\\n.]+)?$"; - const string substitution = @"ffprobe$1"; - - return Regex.Replace(appPath, pattern, substitution); - } - - return null; - } - /// /// Search the system $PATH environment variable looking for given filename. /// @@ -322,12 +249,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return null; } - private void LogPaths() - { - _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty); - _logger.LogInformation("FFprobe: {0}: {1}", ProbeLocation.ToString(), FFprobePath ?? string.Empty); - } - private List _encoders = new List(); public void SetAvailableEncoders(IEnumerable list) { diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 7fc985ba0..285ff4ba5 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -11,11 +11,11 @@ namespace MediaBrowser.Model.Configuration /// /// FFmpeg path as set by the user via the UI /// - public string EncoderAppPathCustom { get; set; } + public string EncoderAppPath { get; set; } /// - /// The current FFmpeg path being used by the system + /// The current FFmpeg path being used by the system and displayed on the transcode page /// - public string EncoderAppPath { get; set; } + public string EncoderAppPathDisplay { get; set; } public string VaapiDevice { get; set; } public int H264Crf { get; set; } public string H264Preset { get; set; } -- cgit v1.2.3 From 2617a49b78c99f72ba36e53a4c97c4e042116a53 Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Thu, 28 Feb 2019 22:47:56 +0000 Subject: Renamed Init() to SetFFmpegPath() --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index dd29f2ade..325df3293 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -534,7 +534,7 @@ namespace Emby.Server.Implementations ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated; - MediaEncoder.Init(); + MediaEncoder.SetFFmpegPath(); //if (string.IsNullOrWhiteSpace(MediaEncoder.EncoderPath)) //{ diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 8852dac05..d4ac3b7c3 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// System.String. string EscapeSubtitleFilterPath(string path); - void Init(); + void SetFFmpegPath(); void UpdateEncoderPath(string path, string pathType); bool SupportsEncoder(string encoder); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 51b4f6e39..292457788 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Sets global variables FFmpegPath. /// Precedence is: Config > CLI > $PATH /// - public void Init() + public void SetFFmpegPath() { // ToDo - Finalise removal of the --ffprobe switch if (!string.IsNullOrEmpty(StartupOptionFFprobePath)) @@ -169,8 +169,8 @@ namespace MediaBrowser.MediaEncoding.Encoder config.EncoderAppPath = newPath; ConfigurationManager.SaveConfiguration("encoding", config); - // Trigger Init so we validate the new path and setup probe path - Init(); + // Trigger SetFFmpegPath so we validate the new path and setup probe path + SetFFmpegPath(); } /// -- cgit v1.2.3 From ffd6dac03a94bb99387e84b447aa22ca92cf9465 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 2 Feb 2019 16:12:16 +0100 Subject: Remove useless comments --- Emby.Dlna/Main/DlnaEntryPoint.cs | 2 +- .../Parsers/BaseItemXmlParser.cs | 33 +- .../Probing/ProbeResultNormalizer.cs | 69 ++-- .../TV/TheTVDB/TvdbEpisodeProvider.cs | 2 + .../TV/TheTVDB/TvdbPrescanTask.cs | 396 --------------------- .../TV/TheTVDB/TvdbSeriesProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 161 ++++----- .../Parsers/EpisodeNfoParser.cs | 63 ++-- .../Parsers/MovieNfoParser.cs | 11 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 1 - 10 files changed, 157 insertions(+), 583 deletions(-) delete mode 100644 MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 1339ba9e4..be2eb5313 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -257,7 +257,7 @@ namespace Emby.Dlna.Main var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address.ToString()); + _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address); var descriptorUri = "/dlna/" + udn + "/description.xml"; var uri = new Uri(_appHost.GetLocalApiUrl(address) + descriptorUri); diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 23b974576..59c8f4da5 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -99,29 +99,24 @@ namespace MediaBrowser.LocalMetadata.Parsers item.ResetPeople(); using (var fileStream = File.OpenRead(metadataFile)) + using (var streamReader = new StreamReader(fileStream, encoding)) + using (var reader = XmlReader.Create(streamReader, settings)) { - using (var streamReader = new StreamReader(fileStream, encoding)) + reader.MoveToContent(); + reader.Read(); + + // Loop through each element + while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader, settings)) + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + else { - reader.MoveToContent(); reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (reader.NodeType == XmlNodeType.Element) - { - FetchDataFromXmlNode(reader, item); - } - else - { - reader.Read(); - } - } } } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 5099ccb2a..2cca410a8 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -246,52 +246,49 @@ namespace MediaBrowser.MediaEncoding.Probing // \n\n\n\n\tcast\n\t\n\t\t\n\t\t\tname\n\t\t\tBlender Foundation\n\t\t\n\t\t\n\t\t\tname\n\t\t\tJanus Bager Kristensen\n\t\t\n\t\n\tdirectors\n\t\n\t\t\n\t\t\tname\n\t\t\tSacha Goedegebure\n\t\t\n\t\n\tstudio\n\tBlender Foundation\n\n\n using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml))) + using (var streamReader = new StreamReader(stream)) { - using (var streamReader = new StreamReader(stream)) + try { - try + using (var reader = XmlReader.Create(streamReader)) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader)) - { - reader.MoveToContent(); - reader.Read(); + reader.MoveToContent(); + reader.Read(); - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) + // Loop through each element + while (!reader.EOF && reader.ReadState == ReadState.Interactive) + { + if (reader.NodeType == XmlNodeType.Element) { - if (reader.NodeType == XmlNodeType.Element) + switch (reader.Name) { - switch (reader.Name) - { - case "dict": - if (reader.IsEmptyElement) - { - reader.Read(); - continue; - } - using (var subtree = reader.ReadSubtree()) - { - ReadFromDictNode(subtree, info); - } - break; - default: - reader.Skip(); - break; - } - } - else - { - reader.Read(); + case "dict": + if (reader.IsEmptyElement) + { + reader.Read(); + continue; + } + using (var subtree = reader.ReadSubtree()) + { + ReadFromDictNode(subtree, info); + } + break; + default: + reader.Skip(); + break; } } + else + { + reader.Read(); + } } } - catch (XmlException) - { - // I've seen probe examples where the iTunMOVI value is just "<" - // So we should not allow this to fail the entire probing operation - } + } + catch (XmlException) + { + // I've seen probe examples where the iTunMOVI value is just "<" + // So we should not allow this to fail the entire probing operation } } } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index b256f2667..5474a7c39 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -192,6 +192,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB Type = PersonType.Director }); } + foreach (var person in episode.GuestStars) { var index = person.IndexOf('('); @@ -212,6 +213,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB Role = role }); } + foreach (var writer in episode.Writers) { result.AddPerson(new PersonInfo diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs deleted file mode 100644 index c8ae58574..000000000 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs +++ /dev/null @@ -1,396 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Providers.TV.TheTVDB; -using Microsoft.Extensions.Logging; - -namespace MediaBrowser.Providers.TV -{ - /// - /// Class TvdbPrescanTask - /// - public class TvdbPrescanTask : ILibraryPostScanTask - { - public const string TvdbBaseUrl = "https://thetvdb.com/"; - - /// - /// The server time URL - /// - private const string ServerTimeUrl = TvdbBaseUrl + "api/Updates.php?type=none"; - - /// - /// The updates URL - /// - private const string UpdatesUrl = TvdbBaseUrl + "api/Updates.php?type=all&time={0}"; - - /// - /// The _HTTP client - /// - private readonly IHttpClient _httpClient; - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _config - /// - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The HTTP client. - /// The config. - public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager) - { - _logger = logger; - _httpClient = httpClient; - _config = config; - _fileSystem = fileSystem; - _libraryManager = libraryManager; - } - - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - /// - /// Runs the specified progress. - /// - /// The progress. - /// The cancellation token. - /// Task. - public async Task Run(IProgress progress, CancellationToken cancellationToken) - { - var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths); - - Directory.CreateDirectory(path); - - var timestampFile = Path.Combine(path, "time.txt"); - - var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile); - - // Don't check for tvdb updates anymore frequently than 24 hours - if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1) - { - return; - } - - // Find out the last time we queried tvdb for updates - var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty; - - string newUpdateTime; - - var existingDirectories = _fileSystem.GetDirectoryPaths(path) - .Select(Path.GetFileName) - .ToList(); - - var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true, - GroupByPresentationUniqueKey = false, - DtoOptions = new DtoOptions(false) - { - EnableImages = false - } - - }).Cast() - .ToList(); - - var seriesIdsInLibrary = seriesList - .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb))) - .Select(i => i.GetProviderId(MetadataProviders.Tvdb)) - .ToList(); - - var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase) - .ToList(); - - var enableInternetProviders = seriesList.Count == 0 ? false : seriesList[0].IsMetadataFetcherEnabled(_libraryManager.GetLibraryOptions(seriesList[0]), TvdbSeriesProvider.Current.Name); - if (!enableInternetProviders) - { - progress.Report(100); - return; - } - - // If this is our first time, update all series - if (string.IsNullOrEmpty(lastUpdateTime)) - { - // First get tvdb server time - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = ServerTimeUrl, - CancellationToken = cancellationToken, - EnableHttpCompression = true, - BufferContent = false - - }, "GET").ConfigureAwait(false)) - { - // First get tvdb server time - using (var stream = response.Content) - { - newUpdateTime = GetUpdateTime(stream); - } - } - - existingDirectories.AddRange(missingSeries); - - await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false); - } - else - { - var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false); - - newUpdateTime = seriesToUpdate.Item2; - - long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out var lastUpdateValue); - - var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue; - - var listToUpdate = seriesToUpdate.Item1.ToList(); - listToUpdate.AddRange(missingSeries); - - await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false); - } - - File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8); - progress.Report(100); - } - - /// - /// Gets the update time. - /// - /// The response. - /// System.String. - private string GetUpdateTime(Stream response) - { - // Use XmlReader for best performance - var settings = new XmlReaderSettings() - { - ValidationType = ValidationType.None, - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true - }; - - using (var streamReader = new StreamReader(response, Encoding.UTF8)) - using (var reader = XmlReader.Create(streamReader, settings)) - { - reader.MoveToContent(); - reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Time": - { - return (reader.ReadElementContentAsString() ?? string.Empty).Trim(); - } - default: - reader.Skip(); - break; - } - } - else - { - reader.Read(); - } - } - } - - return null; - } - - /// - /// Gets the series ids to update. - /// - /// The existing series ids. - /// The last update time. - /// The cancellation token. - /// Task{IEnumerable{System.String}}. - private async Task, string>> GetSeriesIdsToUpdate(IEnumerable existingSeriesIds, string lastUpdateTime, CancellationToken cancellationToken) - { - // First get last time - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = string.Format(UpdatesUrl, lastUpdateTime), - CancellationToken = cancellationToken, - EnableHttpCompression = true, - BufferContent = false - - }, "GET").ConfigureAwait(false)) - { - using (var stream = response.Content) - { - var data = GetUpdatedSeriesIdList(stream); - - var existingDictionary = existingSeriesIds.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - var seriesList = data.ids - .Where(i => !string.IsNullOrWhiteSpace(i) && existingDictionary.ContainsKey(i)); - - return new Tuple, string>(seriesList, data.updateTime); - } - } - } - - private (List ids, string updateTime) GetUpdatedSeriesIdList(Stream stream) - { - string updateTime = null; - var idList = new List(); - - // Use XmlReader for best performance - var settings = new XmlReaderSettings() - { - ValidationType = ValidationType.None, - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true - }; - - using (var streamReader = new StreamReader(stream, Encoding.UTF8)) - using (var reader = XmlReader.Create(streamReader, settings)) - { - reader.MoveToContent(); - reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Time": - { - updateTime = (reader.ReadElementContentAsString() ?? string.Empty).Trim(); - break; - } - case "Series": - { - var id = (reader.ReadElementContentAsString() ?? string.Empty).Trim(); - idList.Add(id); - break; - } - default: - reader.Skip(); - break; - } - } - else - { - reader.Read(); - } - } - } - - return (idList, updateTime); - } - - /// - /// Updates the series. - /// - /// The series ids. - /// The series data path. - /// The last tv db update time. - /// The progress. - /// The cancellation token. - /// Task. - private async Task UpdateSeries(List seriesIds, string seriesDataPath, long? lastTvDbUpdateTime, IProgress progress, CancellationToken cancellationToken) - { - var numComplete = 0; - - var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true, - GroupByPresentationUniqueKey = false, - DtoOptions = new DtoOptions(false) - { - EnableImages = false - } - - }).Cast(); - - // Gather all series into a lookup by tvdb id - var allSeries = seriesList - .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb))) - .ToLookup(i => i.GetProviderId(MetadataProviders.Tvdb)); - - foreach (var seriesId in seriesIds) - { - // Find the preferred language(s) for the movie in the library - var languages = allSeries[seriesId] - .Select(i => i.GetPreferredMetadataLanguage()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - - foreach (var language in languages) - { - try - { - await UpdateSeries(seriesId, seriesDataPath, lastTvDbUpdateTime, language, cancellationToken).ConfigureAwait(false); - } - catch (HttpException ex) - { - _logger.LogError(ex, "Error updating tvdb series id {ID}, language {Language}", seriesId, language); - - // Already logged at lower levels, but don't fail the whole operation, unless timed out - // We have to fail this to make it run again otherwise new episode data could potentially be missing - if (ex.IsTimedOut) - { - throw; - } - } - } - - numComplete++; - double percent = numComplete; - percent /= seriesIds.Count; - percent *= 100; - - progress.Report(percent); - } - } - - /// - /// Updates the series. - /// - /// The id. - /// The series data path. - /// The last tv db update time. - /// The preferred metadata language. - /// The cancellation token. - /// Task. - private Task UpdateSeries(string id, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken) - { - _logger.LogInformation("Updating series from tvdb " + id + ", language " + preferredMetadataLanguage); - - seriesDataPath = Path.Combine(seriesDataPath, id); - - Directory.CreateDirectory(seriesDataPath); - - return TvdbSeriesProvider.Current.DownloadSeriesZip(id, MetadataProviders.Tvdb.ToString(), null, null, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken); - } - } -} diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index 09b056c0c..5ea73dfbf 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -145,6 +145,7 @@ namespace MediaBrowser.Providers.TV.TheTVDB private async Task GetSeriesByRemoteId(string id, string idType, string language, CancellationToken cancellationToken) { + TvDbResponse result = null; try @@ -333,7 +334,6 @@ namespace MediaBrowser.Providers.TV.TheTVDB result.ResultLanguage = metadataLanguage; series.AirDays = TVUtils.GetAirDays(tvdbSeries.AirsDayOfWeek); series.AirTime = tvdbSeries.AirsTime; - series.CommunityRating = (float?)tvdbSeries.SiteRating; series.SetProviderId(MetadataProviders.Imdb, tvdbSeries.ImdbId); series.SetProviderId(MetadataProviders.Zap2It, tvdbSeries.Zap2itId); diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index aa5313eb7..5896497ab 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -62,14 +62,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers throw new ArgumentException("The metadata file was empty or null.", nameof(metadataFile)); } - var settings = new XmlReaderSettings() - { - ValidationType = ValidationType.None, - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true - }; - _validProviderIds = _validProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); var idInfos = ProviderManager.GetExternalIdInfos(item.Item); @@ -88,7 +80,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers _validProviderIds.Add("tmdbcolid", "TmdbCollection"); _validProviderIds.Add("imdb_id", "Imdb"); - Fetch(item, metadataFile, settings, cancellationToken); + Fetch(item, metadataFile, GetXmlReaderSettings(), cancellationToken); } protected virtual bool SupportsUrlAfterClosingXmlTag => false; @@ -105,31 +97,26 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!SupportsUrlAfterClosingXmlTag) { using (var fileStream = File.OpenRead(metadataFile)) + using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) + using (var reader = XmlReader.Create(streamReader, settings)) { - using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) - { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader, settings)) - { - item.ResetPeople(); + item.ResetPeople(); - reader.MoveToContent(); - reader.Read(); + reader.MoveToContent(); + reader.Read(); - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - cancellationToken.ThrowIfCancellationRequested(); + // Loop through each element + while (!reader.EOF && reader.ReadState == ReadState.Interactive) + { + cancellationToken.ThrowIfCancellationRequested(); - if (reader.NodeType == XmlNodeType.Element) - { - FetchDataFromXmlNode(reader, item); - } - else - { - reader.Read(); - } - } + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + else + { + reader.Read(); } } } @@ -137,81 +124,76 @@ namespace MediaBrowser.XbmcMetadata.Parsers } using (var fileStream = File.OpenRead(metadataFile)) + using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { - using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) - { - item.ResetPeople(); + item.ResetPeople(); - // Need to handle a url after the xml data - // http://kodi.wiki/view/NFO_files/movies + // Need to handle a url after the xml data + // http://kodi.wiki/view/NFO_files/movies - var xml = streamReader.ReadToEnd(); + var xml = streamReader.ReadToEnd(); - // Find last closing Tag - // Need to do this in two steps to account for random > characters after the closing xml - var index = xml.LastIndexOf(@" characters after the closing xml + var index = xml.LastIndexOf(@"', index); - } - - if (index != -1) - { - var endingXml = xml.Substring(index); + // If closing tag exists, move to end of Tag + if (index != -1) + { + index = xml.IndexOf('>', index); + } - ParseProviderLinks(item.Item, endingXml); + if (index != -1) + { + var endingXml = xml.Substring(index); - // If the file is just an imdb url, don't go any further - if (index == 0) - { - return; - } + ParseProviderLinks(item.Item, endingXml); - xml = xml.Substring(0, index + 1); - } - else + // If the file is just an imdb url, don't go any further + if (index == 0) { - // If the file is just an Imdb url, handle that - - ParseProviderLinks(item.Item, xml); - return; } - // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions - try + xml = xml.Substring(0, index + 1); + } + else + { + // If the file is just an Imdb url, handle that + + ParseProviderLinks(item.Item, xml); + + return; + } + + // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions + try + { + using (var stringReader = new StringReader(xml)) + using (var reader = XmlReader.Create(stringReader, settings)) { - using (var stringReader = new StringReader(xml)) + reader.MoveToContent(); + reader.Read(); + + // Loop through each element + while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(stringReader, settings)) + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + else { - reader.MoveToContent(); reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (reader.NodeType == XmlNodeType.Element) - { - FetchDataFromXmlNode(reader, item); - } - else - { - reader.Read(); - } - } } } } - catch (XmlException) - { + } + catch (XmlException) + { - } } } } @@ -916,6 +898,15 @@ namespace MediaBrowser.XbmcMetadata.Parsers }; } + internal XmlReaderSettings GetXmlReaderSettings() + => new XmlReaderSettings() + { + ValidationType = ValidationType.None, + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true + }; + /// /// Used to split names of comma or pipe delimeted genres and people /// diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index 7f68ba256..7f4224076 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -27,53 +27,48 @@ namespace MediaBrowser.XbmcMetadata.Parsers protected override void Fetch(MetadataResult item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken) { using (var fileStream = File.OpenRead(metadataFile)) + using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) { - using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) - { - item.ResetPeople(); + item.ResetPeople(); - var xml = streamReader.ReadToEnd(); + var xml = streamReader.ReadToEnd(); - var srch = ""; - var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase); + var srch = ""; + var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase); - if (index != -1) - { - xml = xml.Substring(0, index + srch.Length); - } + if (index != -1) + { + xml = xml.Substring(0, index + srch.Length); + } - // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions - try + // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions + try + { + using (var stringReader = new StringReader(xml)) + using (var reader = XmlReader.Create(stringReader, settings)) { - using (var stringReader = new StringReader(xml)) + reader.MoveToContent(); + reader.Read(); + + // Loop through each element + while (!reader.EOF && reader.ReadState == ReadState.Interactive) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(stringReader, settings)) + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + else { - reader.MoveToContent(); reader.Read(); - - // Loop through each element - while (!reader.EOF && reader.ReadState == ReadState.Interactive) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (reader.NodeType == XmlNodeType.Element) - { - FetchDataFromXmlNode(reader, item); - } - else - { - reader.Read(); - } - } } } } - catch (XmlException) - { + } + catch (XmlException) + { - } } } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 526cc62b0..0c4de9f33 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -122,18 +122,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers using (var stringReader = new StringReader("" + xml + "")) { // These are not going to be valid xml so no sense in causing the provider to fail and spamming the log with exceptions - var settings = new XmlReaderSettings() - { - ValidationType = ValidationType.None, - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true - }; - try { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(stringReader, settings)) + using (var reader = XmlReader.Create(stringReader, GetXmlReaderSettings())) { reader.MoveToContent(); reader.Read(); diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 3d33b1541..3ae72c472 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -964,7 +964,6 @@ namespace MediaBrowser.XbmcMetadata.Savers private void AddCustomTags(string path, List xmlTagsUsed, XmlWriter writer, ILogger logger, IFileSystem fileSystem) { - // Use XmlReader for best performance var settings = new XmlReaderSettings() { ValidationType = ValidationType.None, -- cgit v1.2.3 From 37ea50a572e8bd00aad39c193087228a5d3a3433 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 24 Feb 2019 15:47:59 +0100 Subject: Reduce the amount of exceptions thrown --- Emby.Dlna/PlayTo/Device.cs | 9 +- .../Diagnostics/CommonProcess.cs | 2 +- .../Library/LibraryManager.cs | 27 +- .../LiveTv/EmbyTV/EmbyTV.cs | 4 +- .../LiveTv/EmbyTV/ItemDataProvider.cs | 26 +- .../MediaEncoder/EncodingManager.cs | 4 + MediaBrowser.Api/ApiEntryPoint.cs | 5 + .../MediaEncoding/IMediaEncoder.cs | 2 +- .../Images/InternalMetadataFolderImageProvider.cs | 16 +- .../Encoder/EncodingUtils.cs | 6 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 64 +-- .../MediaInfo/SubtitleResolver.cs | 13 +- SocketHttpListener/Net/HttpConnection.cs | 532 +++++++++++++++++++++ 13 files changed, 630 insertions(+), 80 deletions(-) create mode 100644 SocketHttpListener/Net/HttpConnection.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index b62c5e1d4..0c5ddee65 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -1126,6 +1126,11 @@ namespace Emby.Dlna.PlayTo private void OnPlaybackStart(uBaseObject mediaInfo) { + if (string.IsNullOrWhiteSpace(mediaInfo.Url)) + { + return; + } + PlaybackStart?.Invoke(this, new PlaybackStartEventArgs { MediaInfo = mediaInfo @@ -1134,8 +1139,7 @@ namespace Emby.Dlna.PlayTo private void OnPlaybackProgress(uBaseObject mediaInfo) { - var mediaUrl = mediaInfo.Url; - if (string.IsNullOrWhiteSpace(mediaUrl)) + if (string.IsNullOrWhiteSpace(mediaInfo.Url)) { return; } @@ -1148,7 +1152,6 @@ namespace Emby.Dlna.PlayTo private void OnPlaybackStop(uBaseObject mediaInfo) { - PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs { MediaInfo = mediaInfo diff --git a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs index 78b22bda3..2c4ef170d 100644 --- a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs +++ b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs @@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.Diagnostics public void Dispose() { - _process.Dispose(); + _process?.Dispose(); } } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 3c2272b56..6591d54c5 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -278,6 +278,7 @@ namespace Emby.Server.Implementations.Library { throw new ArgumentNullException(nameof(item)); } + if (item is IItemByName) { if (!(item is MusicArtist)) @@ -285,18 +286,7 @@ namespace Emby.Server.Implementations.Library return; } } - - else if (item.IsFolder) - { - //if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder)) - //{ - // if (item.SourceType != SourceType.Library) - // { - // return; - // } - //} - } - else + else if (!item.IsFolder) { if (!(item is Video) && !(item is LiveTvChannel)) { @@ -371,19 +361,20 @@ namespace Emby.Server.Implementations.Library foreach (var metadataPath in GetMetadataPaths(item, children)) { - _logger.LogDebug("Deleting path {0}", metadataPath); + if (!Directory.Exists(metadataPath)) + { + continue; + } + + _logger.LogDebug("Deleting path {MetadataPath}", metadataPath); try { Directory.Delete(metadataPath, true); - } - catch (IOException) - { - } catch (Exception ex) { - _logger.LogError(ex, "Error deleting {metadataPath}", metadataPath); + _logger.LogError(ex, "Error deleting {MetadataPath}", metadataPath); } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index fceb82ba1..f424bdf5c 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -105,8 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _mediaSourceManager = mediaSourceManager; _streamHelper = streamHelper; - _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger); + _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers.json")); + _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers.json"), _logger); _timerProvider.TimerFired += _timerProvider_TimerFired; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index a2ac60b31..9c45ee36a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -32,32 +31,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (_items == null) { + if (!File.Exists(_dataPath)) + { + return new List(); + } + Logger.LogInformation("Loading live tv data from {0}", _dataPath); _items = GetItemsFromFile(_dataPath); } + return _items.ToList(); } } private List GetItemsFromFile(string path) { - var jsonFile = path + ".json"; - - if (!File.Exists(jsonFile)) - { - return new List(); - } - try { - return _jsonSerializer.DeserializeFromFile>(jsonFile) ?? new List(); - } - catch (IOException) - { + return _jsonSerializer.DeserializeFromFile>(path); } catch (Exception ex) { - Logger.LogError(ex, "Error deserializing {jsonFile}", jsonFile); + Logger.LogError(ex, "Error deserializing {Path}", path); } return new List(); @@ -70,12 +65,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new ArgumentNullException(nameof(newList)); } - var file = _dataPath + ".json"; - Directory.CreateDirectory(Path.GetDirectoryName(file)); + Directory.CreateDirectory(Path.GetDirectoryName(_dataPath)); lock (_fileDataLock) { - _jsonSerializer.SerializeToFile(newList, file); + _jsonSerializer.SerializeToFile(newList, _dataPath); _items = newList; } } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index e68046f6d..52d07d784 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -202,6 +202,10 @@ namespace Emby.Server.Implementations.MediaEncoder private static List GetSavedChapterImages(Video video, IDirectoryService directoryService) { var path = GetChapterImagesPath(video); + if (!Directory.Exists(path)) + { + return new List(); + } try { diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index ceff6b02e..700cbb943 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -172,6 +172,11 @@ namespace MediaBrowser.Api { var path = _config.ApplicationPaths.GetTranscodingTempPath(); + if (!Directory.Exists(path)) + { + return; + } + foreach (var file in _fileSystem.GetFilePaths(path, true)) { _fileSystem.DeleteFile(file); diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d4ac3b7c3..d032a849e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// The input files. /// The protocol. /// System.String. - string GetInputArgument(string[] inputFiles, MediaProtocol protocol); + string GetInputArgument(IReadOnlyList inputFiles, MediaProtocol protocol); /// /// Gets the time parameter. diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index c0706ceeb..25a8ad596 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.IO; +using Microsoft.Extensions.Logging; namespace MediaBrowser.LocalMetadata.Images { @@ -12,11 +13,16 @@ namespace MediaBrowser.LocalMetadata.Images { private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; - public InternalMetadataFolderImageProvider(IServerConfigurationManager config, IFileSystem fileSystem) + public InternalMetadataFolderImageProvider( + IServerConfigurationManager config, + IFileSystem fileSystem, + ILogger logger) { _config = config; _fileSystem = fileSystem; + _logger = logger; } public string Name => "Internal Images"; @@ -53,12 +59,18 @@ namespace MediaBrowser.LocalMetadata.Images { var path = item.GetInternalMetadataPath(); + if (!Directory.Exists(path)) + { + return new List(); + } + try { return new LocalImageProvider(_fileSystem).GetImages(item, path, false, directoryService); } - catch (IOException) + catch (IOException ex) { + _logger.LogError(ex, "Error while getting images for {Library}", item.Name); return new List(); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 44e62446b..d4aede572 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -6,11 +6,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { public static class EncodingUtils { - public static string GetInputArgument(List inputFiles, MediaProtocol protocol) + public static string GetInputArgument(IReadOnlyList inputFiles, MediaProtocol protocol) { if (protocol != MediaProtocol.File) { - var url = inputFiles.First(); + var url = inputFiles[0]; return string.Format("\"{0}\"", url); } @@ -29,7 +29,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // If there's more than one we'll need to use the concat command if (inputFiles.Count > 1) { - var files = string.Join("|", inputFiles.Select(NormalizePath).ToArray()); + var files = string.Join("|", inputFiles.Select(NormalizePath)); return string.Format("concat:\"{0}\"", files); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 292457788..f6ff719d5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -334,10 +334,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The protocol. /// System.String. /// Unrecognized InputType - public string GetInputArgument(string[] inputFiles, MediaProtocol protocol) - { - return EncodingUtils.GetInputArgument(inputFiles.ToList(), protocol); - } + public string GetInputArgument(IReadOnlyList inputFiles, MediaProtocol protocol) + => EncodingUtils.GetInputArgument(inputFiles, protocol); /// /// Gets the media info internal. @@ -354,8 +352,9 @@ namespace MediaBrowser.MediaEncoding.Encoder CancellationToken cancellationToken) { var args = extractChapters - ? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format" - : "{0} -i {1} -threads 0 -v info -print_format json -show_streams -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"; + args = string.Format(args, probeSizeArgument, inputPath).Trim(); var process = _processFactory.Create(new ProcessOptions { @@ -364,8 +363,10 @@ namespace MediaBrowser.MediaEncoding.Encoder // Must consume both or ffmpeg may hang due to deadlocks. See comments below. RedirectStandardOutput = true, + FileName = FFprobePath, - Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(), + Arguments = args, + IsHidden = true, ErrorDialog = false, @@ -383,43 +384,44 @@ namespace MediaBrowser.MediaEncoding.Encoder using (var processWrapper = new ProcessWrapper(process, this, _logger)) { + _logger.LogDebug("Starting ffprobe with args {Args}", args); StartProcess(processWrapper); + InternalMediaInfoResult result; try { - //process.BeginErrorReadLine(); + result = await _jsonSerializer.DeserializeFromStreamAsync(process.StandardOutput.BaseStream).ConfigureAwait(false); + } + catch + { + StopProcess(processWrapper, 100); - var result = await _jsonSerializer.DeserializeFromStreamAsync(process.StandardOutput.BaseStream).ConfigureAwait(false); + throw; + } - if (result == null || (result.streams == null && result.format == null)) - { - throw new Exception("ffprobe failed - streams and format are both null."); - } + if (result == null || (result.streams == null && result.format == null)) + { + throw new Exception("ffprobe failed - streams and format are both null."); + } - if (result.streams != null) + if (result.streams != null) + { + // Normalize aspect ratio if invalid + foreach (var stream in result.streams) { - // Normalize aspect ratio if invalid - foreach (var stream in result.streams) + if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) - { - stream.display_aspect_ratio = string.Empty; - } - if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) - { - stream.sample_aspect_ratio = string.Empty; - } + stream.display_aspect_ratio = string.Empty; } - } - return new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + { + stream.sample_aspect_ratio = string.Empty; + } + } } - catch - { - StopProcess(processWrapper, 100); - throw; - } + return new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index cd026b39b..8195591e1 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ILocalizationManager _localization; private readonly IFileSystem _fileSystem; - private string[] SubtitleExtensions = new[] + private static readonly HashSet SubtitleExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) { ".srt", ".ssa", @@ -49,9 +49,16 @@ namespace MediaBrowser.Providers.MediaInfo startIndex += streams.Count; + string folder = video.GetInternalMetadataPath(); + + if (!Directory.Exists(folder)) + { + return streams; + } + try { - AddExternalSubtitleStreams(streams, video.GetInternalMetadataPath(), video.Path, startIndex, directoryService, clearCache); + AddExternalSubtitleStreams(streams, folder, video.Path, startIndex, directoryService, clearCache); } catch (IOException) { @@ -105,7 +112,7 @@ namespace MediaBrowser.Providers.MediaInfo { var extension = Path.GetExtension(fullName); - if (!SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!SubtitleExtensions.Contains(extension)) { continue; } diff --git a/SocketHttpListener/Net/HttpConnection.cs b/SocketHttpListener/Net/HttpConnection.cs new file mode 100644 index 000000000..5beea5f22 --- /dev/null +++ b/SocketHttpListener/Net/HttpConnection.cs @@ -0,0 +1,532 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Cryptography; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.System; +using Microsoft.Extensions.Logging; +namespace SocketHttpListener.Net +{ + sealed class HttpConnection + { + private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead); + const int BufferSize = 8192; + Socket _socket; + Stream _stream; + HttpEndPointListener _epl; + MemoryStream _memoryStream; + byte[] _buffer; + HttpListenerContext _context; + StringBuilder _currentLine; + ListenerPrefix _prefix; + HttpRequestStream _requestStream; + HttpResponseStream _responseStream; + bool _chunked; + int _reuses; + bool _contextBound; + bool secure; + IPEndPoint local_ep; + HttpListener _lastListener; + X509Certificate cert; + SslStream ssl_stream; + + private readonly ILogger _logger; + private readonly ICryptoProvider _cryptoProvider; + private readonly IStreamHelper _streamHelper; + private readonly IFileSystem _fileSystem; + private readonly IEnvironmentInfo _environment; + + public HttpConnection(ILogger logger, Socket socket, HttpEndPointListener epl, bool secure, + X509Certificate cert, ICryptoProvider cryptoProvider, IStreamHelper streamHelper, IFileSystem fileSystem, + IEnvironmentInfo environment) + { + _logger = logger; + this._socket = socket; + this._epl = epl; + this.secure = secure; + this.cert = cert; + _cryptoProvider = cryptoProvider; + _streamHelper = streamHelper; + _fileSystem = fileSystem; + _environment = environment; + + if (secure == false) + { + _stream = new SocketStream(_socket, false); + } + else + { + ssl_stream = new SslStream(new SocketStream(_socket, false), false, (t, c, ch, e) => + { + if (c == null) + { + return true; + } + + //var c2 = c as X509Certificate2; + //if (c2 == null) + //{ + // c2 = new X509Certificate2(c.GetRawCertData()); + //} + + //_clientCert = c2; + //_clientCertErrors = new int[] { (int)e }; + return true; + }); + + _stream = ssl_stream; + } + } + + public Stream Stream => _stream; + + public async Task Init() + { + if (ssl_stream != null) + { + var enableAsync = true; + if (enableAsync) + { + await ssl_stream.AuthenticateAsServerAsync(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false).ConfigureAwait(false); + } + else + { + ssl_stream.AuthenticateAsServer(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false); + } + } + + InitInternal(); + } + + private void InitInternal() + { + _contextBound = false; + _requestStream = null; + _responseStream = null; + _prefix = null; + _chunked = false; + _memoryStream = new MemoryStream(); + _position = 0; + _inputState = InputState.RequestLine; + _lineState = LineState.None; + _context = new HttpListenerContext(this); + } + + public bool IsClosed => (_socket == null); + + public int Reuses => _reuses; + + public IPEndPoint LocalEndPoint + { + get + { + if (local_ep != null) + return local_ep; + + local_ep = (IPEndPoint)_socket.LocalEndPoint; + return local_ep; + } + } + + public IPEndPoint RemoteEndPoint => _socket.RemoteEndPoint as IPEndPoint; + + public bool IsSecure => secure; + + public ListenerPrefix Prefix + { + get => _prefix; + set => _prefix = value; + } + + private void OnTimeout(object unused) + { + //_logger.LogInformation("HttpConnection timer fired"); + CloseSocket(); + Unbind(); + } + + public void BeginReadRequest() + { + if (_buffer == null) + { + _buffer = new byte[BufferSize]; + } + + try + { + _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this); + } + catch + { + CloseSocket(); + Unbind(); + } + } + + public HttpRequestStream GetRequestStream(bool chunked, long contentlength) + { + if (_requestStream == null) + { + byte[] buffer = _memoryStream.GetBuffer(); + int length = (int)_memoryStream.Length; + _memoryStream = null; + if (chunked) + { + _chunked = true; + //_context.Response.SendChunked = true; + _requestStream = new ChunkedInputStream(_context, _stream, buffer, _position, length - _position); + } + else + { + _requestStream = new HttpRequestStream(_stream, buffer, _position, length - _position, contentlength); + } + } + return _requestStream; + } + + public HttpResponseStream GetResponseStream(bool isExpect100Continue = false) + { + // TODO: can we get this _stream before reading the input? + if (_responseStream == null) + { + var supportsDirectSocketAccess = !_context.Response.SendChunked && !isExpect100Continue && !secure; + + _responseStream = new HttpResponseStream(_stream, _context.Response, false, _streamHelper, _socket, supportsDirectSocketAccess, _environment, _fileSystem, _logger); + } + return _responseStream; + } + + private static void OnRead(IAsyncResult ares) + { + var cnc = (HttpConnection)ares.AsyncState; + cnc.OnReadInternal(ares); + } + + private void OnReadInternal(IAsyncResult ares) + { + int nread = -1; + try + { + nread = _stream.EndRead(ares); + _memoryStream.Write(_buffer, 0, nread); + if (_memoryStream.Length > 32768) + { + SendError("Bad Request", 400); + Close(true); + return; + } + } + catch + { + if (_memoryStream != null && _memoryStream.Length > 0) + { + SendError(); + } + + if (_socket != null) + { + CloseSocket(); + Unbind(); + } + return; + } + + if (nread == 0) + { + CloseSocket(); + Unbind(); + return; + } + + if (ProcessInput(_memoryStream)) + { + if (!_context.HaveError) + _context.Request.FinishInitialization(); + + if (_context.HaveError) + { + SendError(); + Close(true); + return; + } + + if (!_epl.BindContext(_context)) + { + const int NotFoundErrorCode = 404; + SendError(HttpStatusDescription.Get(NotFoundErrorCode), NotFoundErrorCode); + Close(true); + return; + } + HttpListener listener = _epl.Listener; + if (_lastListener != listener) + { + RemoveConnection(); + listener.AddConnection(this); + _lastListener = listener; + } + + _contextBound = true; + listener.RegisterContext(_context); + return; + } + _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this); + } + + private void RemoveConnection() + { + if (_lastListener == null) + _epl.RemoveConnection(this); + else + _lastListener.RemoveConnection(this); + } + + private enum InputState + { + RequestLine, + Headers + } + + private enum LineState + { + None, + CR, + LF + } + + InputState _inputState = InputState.RequestLine; + LineState _lineState = LineState.None; + int _position; + + // true -> done processing + // false -> need more input + private bool ProcessInput(MemoryStream ms) + { + byte[] buffer = ms.GetBuffer(); + int len = (int)ms.Length; + int used = 0; + string line; + + while (true) + { + if (_context.HaveError) + return true; + + if (_position >= len) + break; + + try + { + line = ReadLine(buffer, _position, len - _position, ref used); + _position += used; + } + catch + { + _context.ErrorMessage = "Bad request"; + _context.ErrorStatus = 400; + return true; + } + + if (line == null) + break; + + if (line == "") + { + if (_inputState == InputState.RequestLine) + continue; + _currentLine = null; + ms = null; + return true; + } + + if (_inputState == InputState.RequestLine) + { + _context.Request.SetRequestLine(line); + _inputState = InputState.Headers; + } + else + { + try + { + _context.Request.AddHeader(line); + } + catch (Exception e) + { + _context.ErrorMessage = e.Message; + _context.ErrorStatus = 400; + return true; + } + } + } + + if (used == len) + { + ms.SetLength(0); + _position = 0; + } + return false; + } + + private string ReadLine(byte[] buffer, int offset, int len, ref int used) + { + if (_currentLine == null) + _currentLine = new StringBuilder(128); + int last = offset + len; + used = 0; + for (int i = offset; i < last && _lineState != LineState.LF; i++) + { + used++; + byte b = buffer[i]; + if (b == 13) + { + _lineState = LineState.CR; + } + else if (b == 10) + { + _lineState = LineState.LF; + } + else + { + _currentLine.Append((char)b); + } + } + + string result = null; + if (_lineState == LineState.LF) + { + _lineState = LineState.None; + result = _currentLine.ToString(); + _currentLine.Length = 0; + } + + return result; + } + + public void SendError(string msg, int status) + { + try + { + HttpListenerResponse response = _context.Response; + response.StatusCode = status; + response.ContentType = "text/html"; + string description = HttpStatusDescription.Get(status); + string str; + if (msg != null) + str = string.Format("

{0} ({1})

", description, msg); + else + str = string.Format("

{0}

", description); + + byte[] error = Encoding.UTF8.GetBytes(str); + response.Close(error, false); + } + catch + { + // response was already closed + } + } + + public void SendError() + { + SendError(_context.ErrorMessage, _context.ErrorStatus); + } + + private void Unbind() + { + if (_contextBound) + { + _epl.UnbindContext(_context); + _contextBound = false; + } + } + + public void Close() + { + Close(false); + } + + private void CloseSocket() + { + if (_socket == null) + return; + + try + { + _socket.Close(); + } + catch { } + finally + { + _socket = null; + } + + RemoveConnection(); + } + + internal void Close(bool force) + { + if (_socket != null) + { + Stream st = GetResponseStream(); + if (st != null) + st.Close(); + + _responseStream = null; + } + + if (_socket != null) + { + force |= !_context.Request.KeepAlive; + if (!force) + { + force = string.Equals(_context.Response.Headers["connection"], "close", StringComparison.OrdinalIgnoreCase); + } + + if (!force && _context.Request.FlushInput()) + { + if (_chunked && _context.Response.ForceCloseChunked == false) + { + // Don't close. Keep working. + _reuses++; + Unbind(); + InitInternal(); + BeginReadRequest(); + return; + } + + _reuses++; + Unbind(); + InitInternal(); + BeginReadRequest(); + return; + } + + Socket s = _socket; + _socket = null; + try + { + s?.Shutdown(SocketShutdown.Both); + } + catch + { + } + finally + { + try + { + s?.Close(); + } + catch { } + } + Unbind(); + RemoveConnection(); + return; + } + } + } +} -- cgit v1.2.3 From ab9859ecefa7ec28b38cc807226b3df31fdf3e93 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 7 Mar 2019 13:12:37 +0100 Subject: Address comment --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f6ff719d5..94beda3db 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -390,7 +390,8 @@ namespace MediaBrowser.MediaEncoding.Encoder InternalMediaInfoResult result; try { - result = await _jsonSerializer.DeserializeFromStreamAsync(process.StandardOutput.BaseStream).ConfigureAwait(false); + result = await _jsonSerializer.DeserializeFromStreamAsync( + process.StandardOutput.BaseStream).ConfigureAwait(false); } catch { -- cgit v1.2.3 From 715ddbb3b08cab2ff64919f577d5f72d9af5ea22 Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 11 Mar 2019 18:10:31 -0700 Subject: remove open subtitles from the server --- .../Emby.Server.Implementations.csproj | 1 - .../MediaBrowser.MediaEncoding.csproj | 1 - .../Subtitles/ConfigurationExtension.cs | 29 - .../Subtitles/OpenSubtitleDownloader.cs | 347 --- MediaBrowser.sln | 2 - OpenSubtitlesHandler/Console/OSHConsole.cs | 92 - OpenSubtitlesHandler/Interfaces/IMethodResponse.cs | 71 - .../Interfaces/MethodResponseAttr.cs | 40 - .../Languages/DetectLanguageResult.cs | 31 - .../MethodResponses/MethodResponseAddComment.cs | 32 - .../MethodResponses/MethodResponseAddRequest.cs | 35 - .../MethodResponses/MethodResponseAutoUpdate.cs | 59 - .../MethodResponseCheckMovieHash.cs | 37 - .../MethodResponseCheckMovieHash2.cs | 37 - .../MethodResponses/MethodResponseCheckSubHash.cs | 38 - .../MethodResponseDetectLanguage.cs | 37 - .../MethodResponses/MethodResponseError.cs | 36 - .../MethodResponseGetAvailableTranslations.cs | 37 - .../MethodResponses/MethodResponseGetComments.cs | 39 - .../MethodResponseGetSubLanguages.cs | 39 - .../MethodResponseGetTranslation.cs | 36 - .../MethodResponses/MethodResponseInsertMovie.cs | 36 - .../MethodResponseInsertMovieHash.cs | 38 - .../MethodResponses/MethodResponseLogIn.cs | 39 - .../MethodResponses/MethodResponseMovieDetails.cs | 73 - .../MethodResponses/MethodResponseMovieSearch.cs | 43 - .../MethodResponses/MethodResponseNoOperation.cs | 52 - .../MethodResponseReportWrongImdbMovie.cs | 33 - .../MethodResponseReportWrongMovieHash.cs | 33 - .../MethodResponses/MethodResponseSearchToMail.cs | 32 - .../MethodResponses/MethodResponseServerInfo.cs | 131 - .../MethodResponseSubtitleDownload.cs | 44 - .../MethodResponseSubtitleSearch.cs | 46 - .../MethodResponses/MethodResponseSubtitlesVote.cs | 43 - .../MethodResponseTryUploadSubtitles.cs | 40 - .../MethodResponseUploadSubtitles.cs | 38 - OpenSubtitlesHandler/Methods Implemeted.txt | 39 - OpenSubtitlesHandler/MovieHasher.cs | 48 - OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs | 42 - .../Movies/CheckMovieHash2Result.cs | 37 - .../Movies/CheckMovieHashResult.cs | 41 - .../Movies/InsertMovieHashParameters.cs | 38 - OpenSubtitlesHandler/Movies/MovieSearchResult.cs | 40 - .../Movies/SearchToMailMovieParameter.cs | 30 - OpenSubtitlesHandler/OpenSubtitles.cs | 2744 -------------------- OpenSubtitlesHandler/OpenSubtitlesHandler.csproj | 13 - .../OtherTypes/GetAvailableTranslationsResult.cs | 39 - .../OtherTypes/GetCommentsResult.cs | 36 - OpenSubtitlesHandler/Properties/AssemblyInfo.cs | 24 - OpenSubtitlesHandler/Readme.txt | 20 - .../SubtitleTypes/CheckSubHashResult.cs | 30 - .../SubtitleTypes/SubtitleDownloadResult.cs | 43 - .../SubtitleTypes/SubtitleLanguage.cs | 39 - .../SubtitleTypes/SubtitleSearchParameters.cs | 82 - .../SubtitleTypes/SubtitleSearchResult.cs | 136 - .../SubtitleTypes/TryUploadSubtitlesParameters.cs | 47 - .../SubtitleTypes/UploadSubtitleInfoParameter.cs | 46 - .../SubtitleTypes/UploadSubtitleParameters.cs | 52 - OpenSubtitlesHandler/Utilities.cs | 174 -- OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt | 225 -- .../XML-RPC/Enums/XmlRpcValueType.cs | 25 - .../XML-RPC/Types/XmlRpcMethodCall.cs | 63 - .../XML-RPC/Values/IXmlRpcValue.cs | 36 - .../XML-RPC/Values/XmlRpcStructMember.cs | 43 - .../XML-RPC/Values/XmlRpcValueArray.cs | 121 - .../XML-RPC/Values/XmlRpcValueBasic.cs | 99 - .../XML-RPC/Values/XmlRpcValueStruct.cs | 43 - OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs | 350 --- 68 files changed, 6642 deletions(-) delete mode 100644 MediaBrowser.MediaEncoding/Subtitles/ConfigurationExtension.cs delete mode 100644 MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs delete mode 100644 OpenSubtitlesHandler/Console/OSHConsole.cs delete mode 100644 OpenSubtitlesHandler/Interfaces/IMethodResponse.cs delete mode 100644 OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs delete mode 100644 OpenSubtitlesHandler/Languages/DetectLanguageResult.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs delete mode 100644 OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs delete mode 100644 OpenSubtitlesHandler/Methods Implemeted.txt delete mode 100644 OpenSubtitlesHandler/MovieHasher.cs delete mode 100644 OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs delete mode 100644 OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs delete mode 100644 OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs delete mode 100644 OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs delete mode 100644 OpenSubtitlesHandler/Movies/MovieSearchResult.cs delete mode 100644 OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs delete mode 100644 OpenSubtitlesHandler/OpenSubtitles.cs delete mode 100644 OpenSubtitlesHandler/OpenSubtitlesHandler.csproj delete mode 100644 OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs delete mode 100644 OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs delete mode 100644 OpenSubtitlesHandler/Properties/AssemblyInfo.cs delete mode 100644 OpenSubtitlesHandler/Readme.txt delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs delete mode 100644 OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs delete mode 100644 OpenSubtitlesHandler/Utilities.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt delete mode 100644 OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs delete mode 100644 OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 39e9ed375..0b0dab213 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -13,7 +13,6 @@ - diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 68b8bd4fa..e4757543e 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -14,7 +14,6 @@ - diff --git a/MediaBrowser.MediaEncoding/Subtitles/ConfigurationExtension.cs b/MediaBrowser.MediaEncoding/Subtitles/ConfigurationExtension.cs deleted file mode 100644 index 92544f4f6..000000000 --- a/MediaBrowser.MediaEncoding/Subtitles/ConfigurationExtension.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Providers; - -namespace MediaBrowser.MediaEncoding.Subtitles -{ - public static class ConfigurationExtension - { - public static SubtitleOptions GetSubtitleConfiguration(this IConfigurationManager manager) - { - return manager.GetConfiguration("subtitles"); - } - } - - public class SubtitleConfigurationFactory : IConfigurationFactory - { - public IEnumerable GetConfigurations() - { - return new List - { - new ConfigurationStore - { - Key = "subtitles", - ConfigurationType = typeof (SubtitleOptions) - } - }; - } - } -} diff --git a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs deleted file mode 100644 index a7e3f6197..000000000 --- a/MediaBrowser.MediaEncoding/Subtitles/OpenSubtitleDownloader.cs +++ /dev/null @@ -1,347 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Security; -using MediaBrowser.Controller.Subtitles; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; -using Microsoft.Extensions.Logging; -using OpenSubtitlesHandler; - -namespace MediaBrowser.MediaEncoding.Subtitles -{ - public class OpenSubtitleDownloader : ISubtitleProvider, IDisposable - { - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - private readonly IServerConfigurationManager _config; - - private readonly IJsonSerializer _json; - private readonly IFileSystem _fileSystem; - - public OpenSubtitleDownloader(ILoggerFactory loggerFactory, IHttpClient httpClient, IServerConfigurationManager config, IJsonSerializer json, IFileSystem fileSystem) - { - _logger = loggerFactory.CreateLogger(GetType().Name); - _httpClient = httpClient; - _config = config; - _json = json; - _fileSystem = fileSystem; - - _config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating; - - Utilities.HttpClient = httpClient; - OpenSubtitles.SetUserAgent("jellyfin"); - } - - private const string PasswordHashPrefix = "h:"; - void _config_NamedConfigurationUpdating(object sender, ConfigurationUpdateEventArgs e) - { - if (!string.Equals(e.Key, "subtitles", StringComparison.OrdinalIgnoreCase)) - { - return; - } - - var options = (SubtitleOptions)e.NewConfiguration; - - if (options != null && - !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) && - !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) - { - options.OpenSubtitlesPasswordHash = EncodePassword(options.OpenSubtitlesPasswordHash); - } - } - - private static string EncodePassword(string password) - { - var bytes = Encoding.UTF8.GetBytes(password); - return PasswordHashPrefix + Convert.ToBase64String(bytes); - } - - private static string DecodePassword(string password) - { - if (password == null || - !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase)) - { - return string.Empty; - } - - var bytes = Convert.FromBase64String(password.Substring(2)); - return Encoding.UTF8.GetString(bytes, 0, bytes.Length); - } - - public string Name => "Open Subtitles"; - - private SubtitleOptions GetOptions() - { - return _config.GetSubtitleConfiguration(); - } - - public IEnumerable SupportedMediaTypes - { - get - { - var options = GetOptions(); - - if (string.IsNullOrWhiteSpace(options.OpenSubtitlesUsername) || - string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash)) - { - return new VideoContentType[] { }; - } - - return new[] { VideoContentType.Episode, VideoContentType.Movie }; - } - } - - public Task GetSubtitles(string id, CancellationToken cancellationToken) - { - return GetSubtitlesInternal(id, GetOptions(), cancellationToken); - } - - private DateTime _lastRateLimitException; - private async Task GetSubtitlesInternal(string id, - SubtitleOptions options, - CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException(nameof(id)); - } - - var idParts = id.Split(new[] { '-' }, 3); - - var format = idParts[0]; - var language = idParts[1]; - var ossId = idParts[2]; - - var downloadsList = new[] { int.Parse(ossId, _usCulture) }; - - await Login(cancellationToken).ConfigureAwait(false); - - if ((DateTime.UtcNow - _lastRateLimitException).TotalHours < 1) - { - throw new RateLimitExceededException("OpenSubtitles rate limit reached"); - } - - var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false); - - if ((resultDownLoad.Status ?? string.Empty).IndexOf("407", StringComparison.OrdinalIgnoreCase) != -1) - { - _lastRateLimitException = DateTime.UtcNow; - throw new RateLimitExceededException("OpenSubtitles rate limit reached"); - } - - if (!(resultDownLoad is MethodResponseSubtitleDownload)) - { - throw new Exception("Invalid response type"); - } - - var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results; - - _lastRateLimitException = DateTime.MinValue; - - if (results.Count == 0) - { - var msg = string.Format("Subtitle with Id {0} was not found. Name: {1}. Status: {2}. Message: {3}", - ossId, - resultDownLoad.Name ?? string.Empty, - resultDownLoad.Status ?? string.Empty, - resultDownLoad.Message ?? string.Empty); - - throw new ResourceNotFoundException(msg); - } - - var data = Convert.FromBase64String(results.First().Data); - - return new SubtitleResponse - { - Format = format, - Language = language, - - Stream = new MemoryStream(Utilities.Decompress(new MemoryStream(data))) - }; - } - - private DateTime _lastLogin; - private async Task Login(CancellationToken cancellationToken) - { - if ((DateTime.UtcNow - _lastLogin).TotalSeconds < 60) - { - return; - } - - var options = GetOptions(); - - var user = options.OpenSubtitlesUsername ?? string.Empty; - var password = DecodePassword(options.OpenSubtitlesPasswordHash); - - var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false); - - if (!(loginResponse is MethodResponseLogIn)) - { - throw new Exception("Authentication to OpenSubtitles failed."); - } - - _lastLogin = DateTime.UtcNow; - } - - public async Task> GetSupportedLanguages(CancellationToken cancellationToken) - { - await Login(cancellationToken).ConfigureAwait(false); - - var result = OpenSubtitles.GetSubLanguages("en"); - if (!(result is MethodResponseGetSubLanguages)) - { - _logger.LogError("Invalid response type"); - return new List(); - } - - var results = ((MethodResponseGetSubLanguages)result).Languages; - - return results.Select(i => new NameIdPair - { - Name = i.LanguageName, - Id = i.SubLanguageID - }); - } - - private string NormalizeLanguage(string language) - { - // Problem with Greek subtitle download #1349 - if (string.Equals(language, "gre", StringComparison.OrdinalIgnoreCase)) - { - - return "ell"; - } - - return language; - } - - public async Task> Search(SubtitleSearchRequest request, CancellationToken cancellationToken) - { - var imdbIdText = request.GetProviderId(MetadataProviders.Imdb); - long imdbId = 0; - - switch (request.ContentType) - { - case VideoContentType.Episode: - if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName)) - { - _logger.LogDebug("Episode information missing"); - return new List(); - } - break; - case VideoContentType.Movie: - if (string.IsNullOrEmpty(request.Name)) - { - _logger.LogDebug("Movie name missing"); - return new List(); - } - if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, _usCulture, out imdbId)) - { - _logger.LogDebug("Imdb id missing"); - return new List(); - } - break; - } - - if (string.IsNullOrEmpty(request.MediaPath)) - { - _logger.LogDebug("Path Missing"); - return new List(); - } - - await Login(cancellationToken).ConfigureAwait(false); - - var subLanguageId = NormalizeLanguage(request.Language); - string hash; - - using (var fileStream = File.OpenRead(request.MediaPath)) - { - hash = Utilities.ComputeHash(fileStream); - } - var fileInfo = _fileSystem.GetFileInfo(request.MediaPath); - var movieByteSize = fileInfo.Length; - var searchImdbId = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : ""; - var subtitleSearchParameters = request.ContentType == VideoContentType.Episode - ? new List { - new SubtitleSearchParameters(subLanguageId, - query: request.SeriesName, - season: request.ParentIndexNumber.Value.ToString(_usCulture), - episode: request.IndexNumber.Value.ToString(_usCulture)) - } - : new List { - new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId), - new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId) - }; - var parms = new List { - new SubtitleSearchParameters( subLanguageId, - movieHash: hash, - movieByteSize: movieByteSize, - imdbid: searchImdbId ), - }; - parms.AddRange(subtitleSearchParameters); - var result = await OpenSubtitles.SearchSubtitlesAsync(parms.ToArray(), cancellationToken).ConfigureAwait(false); - if (!(result is MethodResponseSubtitleSearch)) - { - _logger.LogError("Invalid response type"); - return new List(); - } - - Predicate mediaFilter = - x => - request.ContentType == VideoContentType.Episode - ? !string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) && - int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber && - int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber - : !string.IsNullOrEmpty(x.IDMovieImdb) && long.Parse(x.IDMovieImdb, _usCulture) == imdbId; - - var results = ((MethodResponseSubtitleSearch)result).Results; - - // Avoid implicitly captured closure - var hasCopy = hash; - - return results.Where(x => x.SubBad == "0" && mediaFilter(x) && (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase))) - .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1)) - .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize)) - .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture)) - .ThenByDescending(x => double.Parse(x.SubRating, _usCulture)) - .Select(i => new RemoteSubtitleInfo - { - Author = i.UserNickName, - Comment = i.SubAuthorComment, - CommunityRating = float.Parse(i.SubRating, _usCulture), - DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture), - Format = i.SubFormat, - ProviderName = Name, - ThreeLetterISOLanguageName = i.SubLanguageID, - - Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile, - - Name = i.SubFileName, - DateCreated = DateTime.Parse(i.SubAddDate, _usCulture), - IsHashMatch = i.MovieHash == hasCopy - - }).Where(i => !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase)); - } - - public void Dispose() - { - _config.NamedConfigurationUpdating -= _config_NamedConfigurationUpdating; - } - } -} diff --git a/MediaBrowser.sln b/MediaBrowser.sln index a3c0569ba..3ed86d65c 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.WebDashboard", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}" diff --git a/OpenSubtitlesHandler/Console/OSHConsole.cs b/OpenSubtitlesHandler/Console/OSHConsole.cs deleted file mode 100644 index 396b28cbc..000000000 --- a/OpenSubtitlesHandler/Console/OSHConsole.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System; - -namespace OpenSubtitlesHandler.Console -{ - public class OSHConsole - { - /// - /// Write line to the console and raise the "LineWritten" event - /// - /// - /// The debug line - /// The status - public static void WriteLine(string text, DebugCode code = DebugCode.None) - { - if (LineWritten != null) - LineWritten(null, new DebugEventArgs(text, code)); - } - /// - /// Update the last written line - /// - /// The debug line - /// The status - public static void UpdateLine(string text, DebugCode code = DebugCode.None) - { - if (UpdateLastLine != null) - UpdateLastLine(null, new DebugEventArgs(text, code)); - } - - public static event EventHandler LineWritten; - public static event EventHandler UpdateLastLine; - } - public enum DebugCode - { - None, - Good, - Warning, - Error - } - /// - /// Console Debug Args - /// - public class DebugEventArgs : EventArgs - { - public DebugCode Code { get; private set; } - public string Text { get; private set; } - - /// - /// Console Debug Args - /// - /// The debug line - /// The status - public DebugEventArgs(string text, DebugCode code) - { - this.Text = text; - this.Code = code; - } - } - public struct DebugLine - { - public DebugLine(string debugLine, DebugCode status) - { - this.debugLine = debugLine; - this.status = status; - } - string debugLine; - DebugCode status; - - public string Text - { get { return debugLine; } set { debugLine = value; } } - public DebugCode Code - { get { return status; } set { status = value; } } - } -} diff --git a/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs b/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs deleted file mode 100644 index 3450beff5..000000000 --- a/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; - -namespace OpenSubtitlesHandler -{ - /// - /// When you call a method to communicate with OpenSubtitles server, that method should return this response with the reuired information. - /// - public abstract class IMethodResponse - { - public IMethodResponse() { LoadAttributes(); } - public IMethodResponse(string name, string message) - { - this.name = name; - this.message = message; - } - protected string name; - protected string message; - protected double seconds; - protected string status; - - protected void LoadAttributes() - { - //foreach (Attribute attr in Attribute.GetCustomAttributes(this.GetType())) - //{ - // if (attr.GetType() == typeof(MethodResponseDescription)) - // { - // this.name = ((MethodResponseDescription)attr).Name; - // this.message = ((MethodResponseDescription)attr).Message; - // break; - // } - //} - } - - [Description("The name of this response"), Category("MethodResponse")] - public virtual string Name { get { return name; } set { name = value; } } - [Description("The message about this response"), Category("MethodResponse")] - public virtual string Message { get { return message; } set { message = value; } } - [Description("Time taken to execute this command on server"), Category("MethodResponse")] - public double Seconds { get { return seconds; } set { seconds = value; } } - [Description("The status"), Category("MethodResponse")] - public string Status { get { return status; } set { status = value; } } - } - - public class DescriptionAttribute : Attribute - { - public DescriptionAttribute(string text) { } - } - - public class CategoryAttribute : Attribute - { - public CategoryAttribute(string text) { } - } -} diff --git a/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs b/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs deleted file mode 100644 index a7e49032d..000000000 --- a/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; - -namespace OpenSubtitlesHandler -{ - /// - /// Attributes to describe a method response object. - /// - public class MethodResponseDescription : Attribute - { - public MethodResponseDescription(string name, string message) - { - this.name = name; - this.message = message; - } - - private string name; - private string message; - - public string Name { get { return name; } set { name = value; } } - public string Message { get { return message; } set { message = value; } } - } -} diff --git a/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs b/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs deleted file mode 100644 index 3e72dc65c..000000000 --- a/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - public struct DetectLanguageResult - { - private string inputSample; - private string languageID; - - public string LanguageID - { get { return languageID; } set { languageID = value; } } - public string InputSample - { get { return inputSample; } set { inputSample = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs deleted file mode 100644 index 03d0337d4..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("AddComment method response", - "AddComment method response hold all expected values from server.")] - public class MethodResponseAddComment : IMethodResponse - { - public MethodResponseAddComment() - : base() - { } - public MethodResponseAddComment(string name, string message) - : base(name, message) - { } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs deleted file mode 100644 index b996043c2..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("AddRequest method response", - "AddRequest method response hold all expected values from server.")] - public class MethodResponseAddRequest : IMethodResponse - { - public MethodResponseAddRequest() - : base() - { } - public MethodResponseAddRequest(string name, string message) - : base(name, message) - { } - private string _request_url; - - public string request_url { get { return _request_url; } set { _request_url = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs deleted file mode 100644 index 6ee14f1f8..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("AutoUpdate method response", - "AutoUpdate method response hold all expected values from server.")] - public class MethodResponseAutoUpdate : IMethodResponse - { - public MethodResponseAutoUpdate() - : base() - { } - public MethodResponseAutoUpdate(string name, string message) - : base(name, message) - { } - - private string _version; - private string _url_windows; - private string _comments; - private string _url_linux; - /// - /// Latest application version - /// - [Description("Latest application version"), Category("AutoUpdate")] - public string version { get { return _version; } set { _version = value; } } - /// - /// Download URL for Windows version - /// - [Description("Download URL for Windows version"), Category("AutoUpdate")] - public string url_windows { get { return _url_windows; } set { _url_windows = value; } } - /// - /// Application changelog and other comments - /// - [Description("Application changelog and other comments"), Category("AutoUpdate")] - public string comments { get { return _comments; } set { _comments = value; } } - /// - /// Download URL for Linux version - /// - [Description("Download URL for Linux version"), Category("AutoUpdate")] - public string url_linux { get { return _url_linux; } set { _url_linux = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs deleted file mode 100644 index 4bb326244..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("CheckMovieHash method response", - "CheckMovieHash method response hold all expected values from server.")] - public class MethodResponseCheckMovieHash : IMethodResponse - { - public MethodResponseCheckMovieHash() - : base() - { } - public MethodResponseCheckMovieHash(string name, string message) - : base(name, message) - { } - private List results = new List(); - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs deleted file mode 100644 index 72b4c3b15..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("CheckMovieHash2 method response", - "CheckMovieHash2 method response hold all expected values from server.")] - public class MethodResponseCheckMovieHash2 : IMethodResponse - { - public MethodResponseCheckMovieHash2() - : base() - { } - public MethodResponseCheckMovieHash2(string name, string message) - : base(name, message) - { } - private List results = new List(); - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs deleted file mode 100644 index 04e287ea7..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("CheckSubHash method response", - "CheckSubHash method response hold all expected values from server.")] - public class MethodResponseCheckSubHash : IMethodResponse - { - public MethodResponseCheckSubHash() - : base() - { } - public MethodResponseCheckSubHash(string name, string message) - : base(name, message) - { } - private List results = new List(); - - public List Results { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs deleted file mode 100644 index 6bf21d50e..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("DetectLanguage method response", - "DetectLanguage method response hold all expected values from server.")] - public class MethodResponseDetectLanguage : IMethodResponse - { - public MethodResponseDetectLanguage() - : base() - { } - public MethodResponseDetectLanguage(string name, string message) - : base(name, message) - { } - private List results = new List(); - - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs deleted file mode 100644 index 7ed807067..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - /// - /// Response that can be used for general error like internet connection fail. - /// - [MethodResponseDescription("Error method response", - "Error method response that describes error that occured")] - public class MethodResponseError : IMethodResponse - { - public MethodResponseError() - : base() - { } - public MethodResponseError(string name, string message) - : base(name, message) - { } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs deleted file mode 100644 index 91803f4b3..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("GetAvailableTranslations method response", - "GetAvailableTranslations method response hold all expected values from server.")] - public class MethodResponseGetAvailableTranslations : IMethodResponse - { - public MethodResponseGetAvailableTranslations() - : base() - { } - public MethodResponseGetAvailableTranslations(string name, string message) - : base(name, message) - { } - private List results = new List(); - public List Results { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs deleted file mode 100644 index 421e1783b..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("GetComments method response", - "GetComments method response hold all expected values from server.")] - public class MethodResponseGetComments : IMethodResponse - { - public MethodResponseGetComments() - : base() - { } - public MethodResponseGetComments(string name, string message) - : base(name, message) - { } - private List results = new List(); - - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs deleted file mode 100644 index 905b87c91..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("GetSubLanguages method response", - "GetSubLanguages method response hold all expected values from server.")] - public class MethodResponseGetSubLanguages : IMethodResponse - { - public MethodResponseGetSubLanguages() - : base() - { } - public MethodResponseGetSubLanguages(string name, string message) - : base(name, message) - { } - private List languages = new List(); - - public List Languages - { get { return languages; } set { languages = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs deleted file mode 100644 index f008f7711..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("GetTranslation method response", - "GetTranslation method response hold all expected values from server.")] - public class MethodResponseGetTranslation : IMethodResponse - { - public MethodResponseGetTranslation() - : base() - { } - public MethodResponseGetTranslation(string name, string message) - : base(name, message) - { } - private string data; - - public string ContentData { get { return data; } set { data = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs deleted file mode 100644 index 1148b5f47..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("InsertMovie method response", - "InsertMovie method response hold all expected values from server.")] - public class MethodResponseInsertMovie : IMethodResponse - { - public MethodResponseInsertMovie() - : base() - { } - public MethodResponseInsertMovie(string name, string message) - : base(name, message) - { } - private string _ID; - public string ID - { get { return _ID; } set { _ID = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs deleted file mode 100644 index 74f52837c..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("InsertMovieHash method response", - "InsertMovieHash method response hold all expected values from server.")] - public class MethodResponseInsertMovieHash : IMethodResponse - { - public MethodResponseInsertMovieHash() - : base() - { } - public MethodResponseInsertMovieHash(string name, string message) - : base(name, message) - { } - private List _accepted_moviehashes = new List(); - private List _new_imdbs = new List(); - - public List accepted_moviehashes { get { return _accepted_moviehashes; } set { _accepted_moviehashes = value; } } - public List new_imdbs { get { return _new_imdbs; } set { _new_imdbs = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs deleted file mode 100644 index 44d294382..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - /// - /// Response can be used for log in/out operation. - /// - [MethodResponseDescription("LogIn method response", - "LogIn method response hold all expected values from server.")] - public class MethodResponseLogIn : IMethodResponse - { - public MethodResponseLogIn() - : base() - { } - public MethodResponseLogIn(string name, string message) - : base(name, message) - { } - private string token; - - public string Token { get { return token; } set { token = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs deleted file mode 100644 index 6126c0053..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("MovieDetails method response", - "MovieDetails method response hold all expected values from server.")] - public class MethodResponseMovieDetails : IMethodResponse - { - public MethodResponseMovieDetails() - : base() - { } - public MethodResponseMovieDetails(string name, string message) - : base(name, message) - { } - // Details - private string id; - private string title; - private string year; - private string coverLink; - - private string duration; - private string tagline; - private string plot; - private string goofs; - private string trivia; - private List cast = new List(); - private List directors = new List(); - private List writers = new List(); - private List awards = new List(); - private List genres = new List(); - private List country = new List(); - private List language = new List(); - private List certification = new List(); - - // Details - public string ID { get { return id; } set { id = value; } } - public string Title { get { return title; } set { title = value; } } - public string Year { get { return year; } set { year = value; } } - public string CoverLink { get { return coverLink; } set { coverLink = value; } } - public string Duration { get { return duration; } set { duration = value; } } - public string Tagline { get { return tagline; } set { tagline = value; } } - public string Plot { get { return plot; } set { plot = value; } } - public string Goofs { get { return goofs; } set { goofs = value; } } - public string Trivia { get { return trivia; } set { trivia = value; } } - public List Cast { get { return cast; } set { cast = value; } } - public List Directors { get { return directors; } set { directors = value; } } - public List Writers { get { return writers; } set { writers = value; } } - public List Genres { get { return genres; } set { genres = value; } } - public List Awards { get { return awards; } set { awards = value; } } - public List Country { get { return country; } set { country = value; } } - public List Language { get { return language; } set { language = value; } } - public List Certification { get { return certification; } set { certification = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs deleted file mode 100644 index 93cd70346..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("MovieSearch method response", - "MovieSearch method response hold all expected values from server.")] - public class MethodResponseMovieSearch : IMethodResponse - { - public MethodResponseMovieSearch() - : base() - { - results = new List(); - } - public MethodResponseMovieSearch(string name, string message) - : base(name, message) - { - results = new List(); - } - private List results; - - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs deleted file mode 100644 index 02a9993cb..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("NoOperation method response", - "NoOperation method response hold all expected values from server.")] - public class MethodResponseNoOperation : IMethodResponse - { - public MethodResponseNoOperation() - : base() { } - public MethodResponseNoOperation(string name, string message) - : base(name, message) - { } - - private string _global_wrh_download_limit; - private string _client_ip; - private string _limit_check_by; - private string _client_24h_download_count; - private string _client_downlaod_quota; - private string _client_24h_download_limit; - - public string global_wrh_download_limit - { get { return _global_wrh_download_limit; } set { _global_wrh_download_limit = value; } } - public string client_ip - { get { return _client_ip; } set { _client_ip = value; } } - public string limit_check_by - { get { return _limit_check_by; } set { _limit_check_by = value; } } - public string client_24h_download_count - { get { return _client_24h_download_count; } set { _client_24h_download_count = value; } } - public string client_downlaod_quota - { get { return _client_downlaod_quota; } set { _client_downlaod_quota = value; } } - public string client_24h_download_limit - { get { return _client_24h_download_limit; } set { _client_24h_download_limit = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs deleted file mode 100644 index 391fec58a..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("ReportWrongImdbMovie method response", - "ReportWrongImdbMovie method response hold all expected values from server.")] - public class MethodResponseReportWrongImdbMovie : IMethodResponse - { - public MethodResponseReportWrongImdbMovie() - : base() - { } - public MethodResponseReportWrongImdbMovie(string name, string message) - : base(name, message) - { } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs deleted file mode 100644 index 5696e7084..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("ReportWrongMovieHash method response", - "ReportWrongMovieHash method response hold all expected values from server.")] - public class MethodResponseReportWrongMovieHash : IMethodResponse - { - public MethodResponseReportWrongMovieHash() - : base() - { } - public MethodResponseReportWrongMovieHash(string name, string message) - : base(name, message) - { } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs deleted file mode 100644 index ea248bc22..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("SearchToMail method response", - "SearchToMail method response hold all expected values from server.")] - public class MethodResponseSearchToMail : IMethodResponse - { - public MethodResponseSearchToMail() - : base() - { } - public MethodResponseSearchToMail(string name, string message) - : base(name, message) - { } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs deleted file mode 100644 index 973550e9f..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("ServerInfo method response", - "ServerInfo method response hold all expected values from server.")] - public class MethodResponseServerInfo : IMethodResponse - { - public MethodResponseServerInfo() - : base() - { } - public MethodResponseServerInfo(string name, string message) - : base(name, message) - { } - private string _xmlrpc_version; - private string _xmlrpc_url; - private string _application; - private string _contact; - private string _website_url; - private int _users_online_total; - private int _users_online_program; - private int _users_loggedin; - private string _users_max_alltime; - private string _users_registered; - private string _subs_downloads; - private string _subs_subtitle_files; - private string _movies_total; - private string _movies_aka; - private string _total_subtitles_languages; - private List _last_update_strings = new List(); - - /// - /// Version of server's XML-RPC API implementation - /// - [Description("Version of server's XML-RPC API implementation"), Category("OS")] - public string xmlrpc_version { get { return _xmlrpc_version; } set { _xmlrpc_version = value; } } - /// - /// XML-RPC interface URL - /// - [Description("XML-RPC interface URL"), Category("OS")] - public string xmlrpc_url { get { return _xmlrpc_url; } set { _xmlrpc_url = value; } } - /// - /// Server's application name and version - /// - [Description("Server's application name and version"), Category("OS")] - public string application { get { return _application; } set { _application = value; } } - /// - /// Contact e-mail address for server related quuestions and problems - /// - [Description("Contact e-mail address for server related quuestions and problems"), Category("OS")] - public string contact { get { return _contact; } set { _contact = value; } } - /// - /// Main server URL - /// - [Description("Main server URL"), Category("OS")] - public string website_url { get { return _website_url; } set { _website_url = value; } } - /// - /// Number of users currently online - /// - [Description("Number of users currently online"), Category("OS")] - public int users_online_total { get { return _users_online_total; } set { _users_online_total = value; } } - /// - /// Number of users currently online using a client application (XML-RPC API) - /// - [Description("Number of users currently online using a client application (XML-RPC API)"), Category("OS")] - public int users_online_program { get { return _users_online_program; } set { _users_online_program = value; } } - /// - /// Number of currently logged-in users - /// - [Description("Number of currently logged-in users"), Category("OS")] - public int users_loggedin { get { return _users_loggedin; } set { _users_loggedin = value; } } - /// - /// Maximum number of users throughout the history - /// - [Description("Maximum number of users throughout the history"), Category("OS")] - public string users_max_alltime { get { return _users_max_alltime; } set { _users_max_alltime = value; } } - /// - /// Number of registered users - /// - [Description("Number of registered users"), Category("OS")] - public string users_registered { get { return _users_registered; } set { _users_registered = value; } } - /// - /// Total number of subtitle downloads - /// - [Description("Total number of subtitle downloads"), Category("OS")] - public string subs_downloads { get { return _subs_downloads; } set { _subs_downloads = value; } } - /// - /// Total number of subtitle files stored on the server - /// - [Description("Total number of subtitle files stored on the server"), Category("OS")] - public string subs_subtitle_files { get { return _subs_subtitle_files; } set { _subs_subtitle_files = value; } } - /// - /// Total number of movies in the database - /// - [Description("Total number of movies in the database"), Category("OS")] - public string movies_total { get { return _movies_total; } set { _movies_total = value; } } - /// - /// Total number of movie A.K.A. titles in the database - /// - [Description("Total number of movie A.K.A. titles in the database"), Category("OS")] - public string movies_aka { get { return _movies_aka; } set { _movies_aka = value; } } - /// - /// Total number of subtitle languages supported - /// - [Description("Total number of subtitle languages supported"), Category("OS")] - public string total_subtitles_languages { get { return _total_subtitles_languages; } set { _total_subtitles_languages = value; } } - /// - /// Structure containing information about last updates of translations. - /// - [Description("Structure containing information about last updates of translations"), Category("OS")] - public List last_update_strings { get { return _last_update_strings; } set { _last_update_strings = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs deleted file mode 100644 index 6a5d57d19..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; -namespace OpenSubtitlesHandler -{ - /// - /// The response that should be used by subtitle download methods. - /// - [MethodResponseDescription("SubtitleDownload method response", - "SubtitleDownload method response hold all expected values from server.")] - public class MethodResponseSubtitleDownload : IMethodResponse - { - public MethodResponseSubtitleDownload() - : base() - { - results = new List(); - } - public MethodResponseSubtitleDownload(string name, string message) - : base(name, message) - { - results = new List(); - } - private List results; - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs deleted file mode 100644 index 0dce20349..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - /// - /// Response to SearchSubtitle successed call. - /// - [MethodResponseDescription("SubtitleSearch method response", - "SubtitleSearch method response hold all expected values from server.")] - public class MethodResponseSubtitleSearch : IMethodResponse - { - public MethodResponseSubtitleSearch() - : base() - { - results = new List(); - } - public MethodResponseSubtitleSearch(string name, string message) - : base(name, message) - { - results = new List(); - } - - private List results; - public List Results - { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs deleted file mode 100644 index f02f822f0..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("SubtitlesVote method response", - "SubtitlesVote method response hold all expected values from server.")] - public class MethodResponseSubtitlesVote : IMethodResponse - { - public MethodResponseSubtitlesVote() - : base() - { } - public MethodResponseSubtitlesVote(string name, string message) - : base(name, message) - { } - private string _SubRating; - private string _SubSumVotes; - private string _IDSubtitle; - - public string SubRating - { get { return _SubRating; } set { _SubRating = value; } } - public string SubSumVotes - { get { return _SubSumVotes; } set { _SubSumVotes = value; } } - public string IDSubtitle - { get { return _IDSubtitle; } set { _IDSubtitle = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs deleted file mode 100644 index cb3866a62..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("TryUploadSubtitles method response", - "TryUploadSubtitles method response hold all expected values from server.")] - public class MethodResponseTryUploadSubtitles : IMethodResponse - { - public MethodResponseTryUploadSubtitles() - : base() - { } - public MethodResponseTryUploadSubtitles(string name, string message) - : base(name, message) - { } - private int alreadyindb; - private List results = new List(); - - public int AlreadyInDB { get { return alreadyindb; } set { alreadyindb = value; } } - public List Results { get { return results; } set { results = value; } } - } -} diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs deleted file mode 100644 index bda950bef..000000000 --- a/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - [MethodResponseDescription("UploadSubtitles method response", - "UploadSubtitles method response hold all expected values from server.")] - public class MethodResponseUploadSubtitles : IMethodResponse - { - public MethodResponseUploadSubtitles() - : base() - { } - public MethodResponseUploadSubtitles(string name, string message) - : base(name, message) - { } - private string _data; - private bool _subtitles; - - public string Data { get { return _data; } set { _data = value; } } - public bool SubTitles { get { return _subtitles; } set { _subtitles = value; } } - } -} diff --git a/OpenSubtitlesHandler/Methods Implemeted.txt b/OpenSubtitlesHandler/Methods Implemeted.txt deleted file mode 100644 index e3493d9a2..000000000 --- a/OpenSubtitlesHandler/Methods Implemeted.txt +++ /dev/null @@ -1,39 +0,0 @@ -List of available OpenSubtitles.org server XML-RPC methods. -========================================================== -Legends: -* OK: this method is fully implemented, tested and works fine. -* TODO: this method is in the plan to be added. -* NOT TESTED: this method added and expected to work fine but never tested. -* NOT WORK (x): this method added but not work. x= Description of the error. - --------------------------------------------- -Method name | Status --------------------------|------------------ -LogIn | OK -LogOut | OK -NoOperation | OK -SearchSubtitles | OK -DownloadSubtitles | OK -SearchToMail | OK -TryUploadSubtitles | OK -UploadSubtitles | OK -SearchMoviesOnIMDB | OK -GetIMDBMovieDetails | OK -InsertMovie | OK -InsertMovieHash | OK -ServerInfo | OK -ReportWrongMovieHash | OK -ReportWrongImdbMovie | OK -SubtitlesVote | OK -AddComment | OK -AddRequest | OK -GetComments | OK -GetSubLanguages | OK -DetectLanguage | OK -GetAvailableTranslations | OK -GetTranslation | NOT WORK (Returns status of error 410 'Other or unknown error') -AutoUpdate | NOT WORK (Returns status: 'parse error. not well formed') -CheckMovieHash | OK -CheckMovieHash2 | OK -CheckSubHash | OK --------------------------------------------- diff --git a/OpenSubtitlesHandler/MovieHasher.cs b/OpenSubtitlesHandler/MovieHasher.cs deleted file mode 100644 index 25d91c1ac..000000000 --- a/OpenSubtitlesHandler/MovieHasher.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.IO; -using System.Text; - -namespace OpenSubtitlesHandler -{ - public class MovieHasher - { - public static byte[] ComputeMovieHash(Stream input) - { - using (input) - { - long lhash, streamsize; - streamsize = input.Length; - lhash = streamsize; - - long i = 0; - byte[] buffer = new byte[sizeof(long)]; - while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0)) - { - i++; - lhash += BitConverter.ToInt64(buffer, 0); - } - - input.Position = Math.Max(0, streamsize - 65536); - i = 0; - while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0)) - { - i++; - lhash += BitConverter.ToInt64(buffer, 0); - } - byte[] result = BitConverter.GetBytes(lhash); - Array.Reverse(result); - return result; - } - } - - public static string ToHexadecimal(byte[] bytes) - { - var hexBuilder = new StringBuilder(); - for (int i = 0; i < bytes.Length; i++) - { - hexBuilder.Append(bytes[i].ToString("x2")); - } - return hexBuilder.ToString(); - } - } -} diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs b/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs deleted file mode 100644 index 953590137..000000000 --- a/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct CheckMovieHash2Data - { - private string _MovieHash; - private string _MovieImdbID; - private string _MovieName; - private string _MovieYear; - private string _MovieKind; - private string _SeriesSeason; - private string _SeriesEpisode; - private string _SeenCount; - - public string MovieHash { get { return _MovieHash; } set { _MovieHash = value; } } - public string MovieImdbID { get { return _MovieImdbID; } set { _MovieImdbID = value; } } - public string MovieName { get { return _MovieName; } set { _MovieName = value; } } - public string MovieYear { get { return _MovieYear; } set { _MovieYear = value; } } - public string MovieKind { get { return _MovieKind; } set { _MovieKind = value; } } - public string SeriesSeason { get { return _SeriesSeason; } set { _SeriesSeason = value; } } - public string SeriesEpisode { get { return _SeriesEpisode; } set { _SeriesEpisode = value; } } - public string SeenCount { get { return _SeenCount; } set { _SeenCount = value; } } - } -} diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs b/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs deleted file mode 100644 index 96652fae7..000000000 --- a/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - public class CheckMovieHash2Result - { - private string name; - private List data = new List(); - - public string Name { get { return name; } set { name = value; } } - public List Items { get { return data; } set { data = value; } } - - public override string ToString() - { - return name; - } - } -} diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs b/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs deleted file mode 100644 index 0d6c79f80..000000000 --- a/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct CheckMovieHashResult - { - private string name; - private string _MovieHash; - private string _MovieImdbID; - private string _MovieName; - private string _MovieYear; - - public string MovieHash { get { return _MovieHash; } set { _MovieHash = value; } } - public string MovieImdbID { get { return _MovieImdbID; } set { _MovieImdbID = value; } } - public string MovieName { get { return _MovieName; } set { _MovieName = value; } } - public string MovieYear { get { return _MovieYear; } set { _MovieYear = value; } } - public string Name { get { return name; } set { name = value; } } - - public override string ToString() - { - return name; - } - } -} diff --git a/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs b/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs deleted file mode 100644 index d0de7f8c6..000000000 --- a/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public class InsertMovieHashParameters - { - private string _moviehash = ""; - private string _moviebytesize = ""; - private string _imdbid = ""; - private string _movietimems = ""; - private string _moviefps = ""; - private string _moviefilename = ""; - - public string moviehash { get { return _moviehash; } set { _moviehash = value; } } - public string moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } } - public string imdbid { get { return _imdbid; } set { _imdbid = value; } } - public string movietimems { get { return _movietimems; } set { _movietimems = value; } } - public string moviefps { get { return _moviefps; } set { _moviefps = value; } } - public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } } - } -} diff --git a/OpenSubtitlesHandler/Movies/MovieSearchResult.cs b/OpenSubtitlesHandler/Movies/MovieSearchResult.cs deleted file mode 100644 index d77116583..000000000 --- a/OpenSubtitlesHandler/Movies/MovieSearchResult.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct MovieSearchResult - { - private string id; - private string title; - - public string ID - { get { return id; } set { id = value; } } - public string Title - { get { return title; } set { title = value; } } - /// - /// Title - /// - /// - public override string ToString() - { - return title; - } - } -} diff --git a/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs b/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs deleted file mode 100644 index a0ecc87f8..000000000 --- a/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct SearchToMailMovieParameter - { - private string _moviehash; - private double _moviesize; - - public string moviehash { get { return _moviehash; } set { _moviehash = value; } } - public double moviesize { get { return _moviesize; } set { _moviesize = value; } } - } -} diff --git a/OpenSubtitlesHandler/OpenSubtitles.cs b/OpenSubtitlesHandler/OpenSubtitles.cs deleted file mode 100644 index 76f70dc07..000000000 --- a/OpenSubtitlesHandler/OpenSubtitles.cs +++ /dev/null @@ -1,2744 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using OpenSubtitlesHandler.Console; -using XmlRpcHandler; - -namespace OpenSubtitlesHandler -{ - /// - /// The core of the OpenSubtitles Handler library. All members are static. - /// - public sealed class OpenSubtitles - { - private static string XML_PRC_USERAGENT = ""; - // This is session id after log in, important value and MUST be set by LogIn before any other call. - private static string TOKEN = ""; - - /// - /// Set the useragent value. This must be called before doing anything else. - /// - /// The useragent value - public static void SetUserAgent(string agent) - { - XML_PRC_USERAGENT = agent; - } - - /*Session handling*/ - /// - /// Send a LogIn request, this must be called before anything else in this class. - /// - /// The user name of OpenSubtitles - /// The password - /// The language, usally en - /// Status of the login operation - public static IMethodResponse LogIn(string userName, string password, string language) - { - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(userName)); - parms.Add(new XmlRpcValueBasic(password)); - parms.Add(new XmlRpcValueBasic(language)); - parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT)); - var call = new XmlRpcMethodCall("LogIn", parms); - OSHConsole.WriteLine("Sending LogIn request to the server ...", DebugCode.Good); - - //File.WriteAllText(".\\request.txt", Encoding.UTF8.GetString(XmlRpcGenerator.Generate(call))); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. We expect Struct here. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - var re = new MethodResponseLogIn("Success", "Log in successful."); - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "token": re.Token = TOKEN = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": re.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "status": re.Status = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - return re; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "Log in failed !"); - } - - public static async Task LogInAsync(string userName, string password, string language, CancellationToken cancellationToken) - { - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(userName)); - parms.Add(new XmlRpcValueBasic(password)); - parms.Add(new XmlRpcValueBasic(language)); - parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT)); - var call = new XmlRpcMethodCall("LogIn", parms); - OSHConsole.WriteLine("Sending LogIn request to the server ...", DebugCode.Good); - - //File.WriteAllText(".\\request.txt", Encoding.UTF8.GetString(XmlRpcGenerator.Generate(call))); - // Send the request to the server - var stream = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken) - .ConfigureAwait(false); - - string response = Utilities.GetStreamString(stream); - - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. We expect Struct here. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - var re = new MethodResponseLogIn("Success", "Log in successful."); - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "token": - re.Token = TOKEN = MEMBER.Data.Data.ToString(); - OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "seconds": - re.Seconds = double.Parse(MEMBER.Data.Data.ToString(), CultureInfo.InvariantCulture); - OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "status": - re.Status = MEMBER.Data.Data.ToString(); - OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - } - } - return re; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "Log in failed !"); - } - - /// - /// Log out from the server. Call this to terminate the session. - /// - /// - public static IMethodResponse LogOut() - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var call = new XmlRpcMethodCall("LogOut", parms); - - OSHConsole.WriteLine("Sending LogOut request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. We expect Struct here. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var strct = (XmlRpcValueStruct)calls[0].Parameters[0]; - OSHConsole.WriteLine("STATUS=" + ((XmlRpcValueBasic)strct.Members[0].Data).Data.ToString()); - OSHConsole.WriteLine("SECONDS=" + ((XmlRpcValueBasic)strct.Members[1].Data).Data.ToString()); - var re = new MethodResponseLogIn("Success", "Log out successful."); - re.Status = ((XmlRpcValueBasic)strct.Members[0].Data).Data.ToString(); - re.Seconds = (double)((XmlRpcValueBasic)strct.Members[1].Data).Data; - return re; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "Log out failed !"); - } - /// - /// keep-alive user's session, verify token/session validity - /// - /// Status of the call operation - public static IMethodResponse NoOperation() - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT, XmlRpcBasicValueType.String)); - var call = new XmlRpcMethodCall("NoOperation", parms); - - OSHConsole.WriteLine("Sending NoOperation request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. We expect Struct here. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var R = new MethodResponseNoOperation(); - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data); break; - case "download_limits": - var dlStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dlmember in dlStruct.Members) - { - OSHConsole.WriteLine(" >" + dlmember.Name + "= " + dlmember.Data.Data.ToString()); - switch (dlmember.Name) - { - case "global_wrh_download_limit": R.global_wrh_download_limit = dlmember.Data.Data.ToString(); break; - case "client_ip": R.client_ip = dlmember.Data.Data.ToString(); break; - case "limit_check_by": R.limit_check_by = dlmember.Data.Data.ToString(); break; - case "client_24h_download_count": R.client_24h_download_count = dlmember.Data.Data.ToString(); break; - case "client_downlaod_quota": R.client_downlaod_quota = dlmember.Data.Data.ToString(); break; - case "client_24h_download_limit": R.client_24h_download_limit = dlmember.Data.Data.ToString(); break; - } - } - break; - } - } - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "NoOperation call failed !"); - } - /*Search and download*/ - /// - /// Search for subtitle files matching your videos using either video file hashes or IMDb IDs. - /// - /// List of search subtitle parameters which each one represents 'struct parameter' as descriped at http://trac.opensubtitles.org/projects/opensubtitles/wiki/XmlRpcSearchSubtitles - /// Status of the call operation. If the call success the response will be 'MethodResponseSubtitleSearch' - public static IMethodResponse SearchSubtitles(SubtitleSearchParameters[] parameters) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - if (parameters == null) - { - OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle search parameter passed"); - } - if (parameters.Length == 0) - { - OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle search parameter passed"); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add subtitle search parameters. Each one will be like 'array' of structs. - var array = new XmlRpcValueArray(); - foreach (SubtitleSearchParameters param in parameters) - { - var strct = new XmlRpcValueStruct(new List()); - // sublanguageid member - var member = new XmlRpcStructMember("sublanguageid", - new XmlRpcValueBasic(param.SubLangaugeID, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - // moviehash member - if (param.MovieHash.Length > 0 && param.MovieByteSize > 0) - { - member = new XmlRpcStructMember("moviehash", - new XmlRpcValueBasic(param.MovieHash, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - // moviehash member - member = new XmlRpcStructMember("moviebytesize", - new XmlRpcValueBasic(param.MovieByteSize, XmlRpcBasicValueType.Int)); - strct.Members.Add(member); - } - if (param.Query.Length > 0) - { - member = new XmlRpcStructMember("query", - new XmlRpcValueBasic(param.Query, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - - if (param.Episode.Length > 0 && param.Season.Length > 0) - { - member = new XmlRpcStructMember("season", - new XmlRpcValueBasic(param.Season, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - member = new XmlRpcStructMember("episode", - new XmlRpcValueBasic(param.Episode, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - - // imdbid member - if (param.IMDbID.Length > 0) - { - member = new XmlRpcStructMember("imdbid", - new XmlRpcValueBasic(param.IMDbID, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - // Add the struct to the array - array.Values.Add(strct); - } - // Add the array to the parameters - parms.Add(array); - // Call ! - var call = new XmlRpcMethodCall("SearchSubtitles", parms); - OSHConsole.WriteLine("Sending SearchSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - // We expect Struct of 3 members: - //* the first is status - //* the second is [array of structs, each one includes subtitle file]. - //* the third is [double basic value] represent seconds token by server. - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSubtitleSearch(); - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Search results: "); - - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new SubtitleSearchResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break; - case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break; - case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break; - case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break; - case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break; - case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break; - case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break; - case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break; - case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break; - case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break; - case "MovieName": result.MovieName = submember.Data.Data.ToString(); break; - case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break; - case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break; - case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break; - case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break; - case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break; - case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break; - case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break; - case "SubBad": result.SubBad = submember.Data.Data.ToString(); break; - case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break; - case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break; - case "SeriesEpisode": result.SeriesEpisode = submember.Data.Data.ToString(); break; - case "SeriesSeason": result.SeriesSeason = submember.Data.Data.ToString(); break; - case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break; - case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break; - case "SubHash": result.SubHash = submember.Data.Data.ToString(); break; - case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break; - case "SubRating": result.SubRating = submember.Data.Data.ToString(); break; - case "SubSize": result.SubSize = submember.Data.Data.ToString(); break; - case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break; - case "UserID": result.UserID = submember.Data.Data.ToString(); break; - case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break; - case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine(">" + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "Search Subtitles call failed !"); - } - - public static async Task SearchSubtitlesAsync(SubtitleSearchParameters[] parameters, CancellationToken cancellationToken) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - if (parameters == null) - { - OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle search parameter passed"); - } - if (parameters.Length == 0) - { - OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle search parameter passed"); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add subtitle search parameters. Each one will be like 'array' of structs. - var array = new XmlRpcValueArray(); - foreach (SubtitleSearchParameters param in parameters) - { - var strct = new XmlRpcValueStruct(new List()); - // sublanguageid member - var member = new XmlRpcStructMember("sublanguageid", - new XmlRpcValueBasic(param.SubLangaugeID, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - // moviehash member - if (param.MovieHash.Length > 0 && param.MovieByteSize > 0) - { - member = new XmlRpcStructMember("moviehash", - new XmlRpcValueBasic(param.MovieHash, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - // moviehash member - member = new XmlRpcStructMember("moviebytesize", - new XmlRpcValueBasic(param.MovieByteSize, XmlRpcBasicValueType.Int)); - strct.Members.Add(member); - } - if (param.Query.Length > 0) - { - member = new XmlRpcStructMember("query", - new XmlRpcValueBasic(param.Query, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - - if (param.Episode.Length > 0 && param.Season.Length > 0) - { - member = new XmlRpcStructMember("season", - new XmlRpcValueBasic(param.Season, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - member = new XmlRpcStructMember("episode", - new XmlRpcValueBasic(param.Episode, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - - // imdbid member - if (param.IMDbID.Length > 0) - { - member = new XmlRpcStructMember("imdbid", - new XmlRpcValueBasic(param.IMDbID, XmlRpcBasicValueType.String)); - strct.Members.Add(member); - } - // Add the struct to the array - array.Values.Add(strct); - } - // Add the array to the parameters - parms.Add(array); - // Call ! - var call = new XmlRpcMethodCall("SearchSubtitles", parms); - OSHConsole.WriteLine("Sending SearchSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false)); - - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - // We expect Struct of 3 members: - //* the first is status - //* the second is [array of structs, each one includes subtitle file]. - //* the third is [double basic value] represent seconds token by server. - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSubtitleSearch(); - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Search results: "); - - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new SubtitleSearchResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break; - case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break; - case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break; - case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break; - case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break; - case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break; - case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break; - case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break; - case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break; - case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break; - case "MovieName": result.MovieName = submember.Data.Data.ToString(); break; - case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break; - case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break; - case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break; - case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break; - case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break; - case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break; - case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break; - case "SubBad": result.SubBad = submember.Data.Data.ToString(); break; - case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break; - case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break; - case "SeriesEpisode": result.SeriesEpisode = submember.Data.Data.ToString(); break; - case "SeriesSeason": result.SeriesSeason = submember.Data.Data.ToString(); break; - case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break; - case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break; - case "SubHash": result.SubHash = submember.Data.Data.ToString(); break; - case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break; - case "SubRating": result.SubRating = submember.Data.Data.ToString(); break; - case "SubSize": result.SubSize = submember.Data.Data.ToString(); break; - case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break; - case "UserID": result.UserID = submember.Data.Data.ToString(); break; - case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break; - case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine(">" + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "Search Subtitles call failed !"); - } - - /// - /// Download subtitle file(s) - /// - /// The subtitle IDS (an array of IDSubtitleFile value that given by server as SearchSubtiles results) - /// Status of the call operation. If the call success the response will be 'MethodResponseSubtitleDownload' which will hold downloaded subtitles - public static IMethodResponse DownloadSubtitles(int[] subIDS) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - if (subIDS == null) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - if (subIDS.Length == 0) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add subtitle search parameters. Each one will be like 'array' of structs. - var array = new XmlRpcValueArray(); - foreach (int id in subIDS) - { - array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int)); - } - // Add the array to the parameters - parms.Add(array); - // Call ! - var call = new XmlRpcMethodCall("DownloadSubtitles", parms); - OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - // We expect Struct of 3 members: - //* the first is status - //* the second is [array of structs, each one includes subtitle file]. - //* the third is [double basic value] represent seconds token by server. - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSubtitleDownload(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Download results:"); - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new SubtitleDownloadResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break; - case "data": result.Data = (string)submember.Data.Data; break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "DownloadSubtitles call failed !"); - } - - public static async Task DownloadSubtitlesAsync(int[] subIDS, CancellationToken cancellationToken) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - if (subIDS == null) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - if (subIDS.Length == 0) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add subtitle search parameters. Each one will be like 'array' of structs. - var array = new XmlRpcValueArray(); - foreach (int id in subIDS) - { - array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int)); - } - // Add the array to the parameters - parms.Add(array); - // Call ! - var call = new XmlRpcMethodCall("DownloadSubtitles", parms); - OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - - var httpResponse = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false); - - string response = Utilities.GetStreamString(httpResponse); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - // We expect Struct of 3 members: - //* the first is status - //* the second is [array of structs, each one includes subtitle file]. - //* the third is [double basic value] represent seconds token by server. - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSubtitleDownload(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Download results:"); - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new SubtitleDownloadResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break; - case "data": result.Data = (string)submember.Data.Data; break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "DownloadSubtitles call failed !"); - } - - /// - /// Returns comments for subtitles - /// - /// The subtitle IDS (an array of IDSubtitleFile value that given by server as SearchSubtiles results) - /// Status of the call operation. If the call success the response will be 'MethodResponseGetComments' - public static IMethodResponse GetComments(int[] subIDS) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - if (subIDS == null) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - if (subIDS.Length == 0) - { - OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error); - return new MethodResponseError("Fail", "No subtitle id passed"); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN)); - // Add subtitle search parameters. Each one will be like 'array' of structs. - var array = new XmlRpcValueArray(subIDS); - // Add the array to the parameters - parms.Add(array); - // Call ! - var call = new XmlRpcMethodCall("GetComments", parms); - OSHConsole.WriteLine("Sending GetComments request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseGetComments(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Comments results:"); - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue commentStruct in rarray.Values) - { - if (commentStruct == null) continue; - if (!(commentStruct is XmlRpcValueStruct)) continue; - - var result = new GetCommentsResult(); - foreach (XmlRpcStructMember commentmember in ((XmlRpcValueStruct)commentStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (commentmember.Name) - { - case "IDSubtitle": result.IDSubtitle = (string)commentmember.Data.Data; break; - case "UserID": result.UserID = (string)commentmember.Data.Data; break; - case "UserNickName": result.UserNickName = (string)commentmember.Data.Data; break; - case "Comment": result.Comment = (string)commentmember.Data.Data; break; - case "Created": result.Created = (string)commentmember.Data.Data; break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine("> IDSubtitle= " + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "GetComments call failed !"); - } - - /// - /// Schedule a periodical search for subtitles matching given video files, send results to user's e-mail address. - /// - /// The language 3 lenght ids array - /// The movies parameters - /// Status of the call operation. If the call success the response will be 'MethodResponseSearchToMail' - public static IMethodResponse SearchToMail(string[] languageIDS, SearchToMailMovieParameter[] movies) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Array of sub langs - var a = new XmlRpcValueArray(languageIDS); - parms.Add(a); - // Array of video parameters - a = new XmlRpcValueArray(); - foreach (SearchToMailMovieParameter p in movies) - { - var str = new XmlRpcValueStruct(new List()); - str.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(p.moviehash))); - str.Members.Add(new XmlRpcStructMember("moviesize", new XmlRpcValueBasic(p.moviesize))); - a.Values.Add(str); - } - parms.Add(a); - var call = new XmlRpcMethodCall("SearchToMail", parms); - - OSHConsole.WriteLine("Sending SearchToMail request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSearchToMail(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "SearchToMail call failed !"); - } - /*Movies*/ - /// - /// Search for a movie (using movie title) - /// - /// Movie title user is searching for, this is cleaned-up a bit (remove dvdrip, etc.) before searching - /// Status of the call operation. If the call success the response will be 'MethodResponseSubtitleSearch' - public static IMethodResponse SearchMoviesOnIMDB(string query) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add query param - parms.Add(new XmlRpcValueBasic(query, XmlRpcBasicValueType.String)); - // Call ! - var call = new XmlRpcMethodCall("SearchMoviesOnIMDB", parms); - OSHConsole.WriteLine("Sending SearchMoviesOnIMDB request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseMovieSearch(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Search results:"); - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new MovieSearchResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "id": result.ID = (string)submember.Data.Data; break; - case "title": result.Title = (string)submember.Data.Data; break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine(">" + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "SearchMoviesOnIMDB call failed !"); - } - /// - /// Get movie details for given IMDb ID - /// - /// http://www.imdb.com/ - /// Status of the call operation. If the call success the response will be 'MethodResponseMovieDetails' - public static IMethodResponse GetIMDBMovieDetails(string imdbid) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN)); - // Add query param - parms.Add(new XmlRpcValueBasic(imdbid)); - // Call ! - var call = new XmlRpcMethodCall("GetIMDBMovieDetails", parms); - OSHConsole.WriteLine("Sending GetIMDBMovieDetails request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseMovieDetails(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "data") - { - // We expect struct with details... - if (MEMBER.Data is XmlRpcValueStruct) - { - OSHConsole.WriteLine("Details result:"); - var detailsStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dmem in detailsStruct.Members) - { - switch (dmem.Name) - { - case "id": R.ID = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "title": R.Title = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "year": R.Year = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "cover": R.CoverLink = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "duration": R.Duration = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "tagline": R.Tagline = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "plot": R.Plot = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "goofs": R.Goofs = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "trivia": R.Trivia = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break; - case "cast": - // this is another struct with cast members... - OSHConsole.WriteLine(">" + dmem.Name + "= "); - var castStruct = (XmlRpcValueStruct)dmem.Data; - foreach (XmlRpcStructMember castMemeber in castStruct.Members) - { - R.Cast.Add(castMemeber.Data.Data.ToString()); - OSHConsole.WriteLine(" >" + castMemeber.Data.Data.ToString()); - } - break; - case "directors": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is another struct with directors members... - var directorsStruct = (XmlRpcValueStruct)dmem.Data; - foreach (XmlRpcStructMember directorsMember in directorsStruct.Members) - { - R.Directors.Add(directorsMember.Data.Data.ToString()); - OSHConsole.WriteLine(" >" + directorsMember.Data.Data.ToString()); - } - break; - case "writers": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is another struct with writers members... - var writersStruct = (XmlRpcValueStruct)dmem.Data; - foreach (XmlRpcStructMember writersMember in writersStruct.Members) - { - R.Writers.Add(writersMember.Data.Data.ToString()); - OSHConsole.WriteLine("+->" + writersMember.Data.Data.ToString()); - } - break; - case "awards": - // this is an array of genres... - var awardsArray = (XmlRpcValueArray)dmem.Data; - foreach (XmlRpcValueBasic award in awardsArray.Values) - { - R.Awards.Add(award.Data.ToString()); - OSHConsole.WriteLine(" >" + award.Data.ToString()); - } - break; - case "genres": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is an array of genres... - var genresArray = (XmlRpcValueArray)dmem.Data; - foreach (XmlRpcValueBasic genre in genresArray.Values) - { - R.Genres.Add(genre.Data.ToString()); - OSHConsole.WriteLine(" >" + genre.Data.ToString()); - } - break; - case "country": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is an array of country... - var countryArray = (XmlRpcValueArray)dmem.Data; - foreach (XmlRpcValueBasic country in countryArray.Values) - { - R.Country.Add(country.Data.ToString()); - OSHConsole.WriteLine(" >" + country.Data.ToString()); - } - break; - case "language": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is an array of language... - var languageArray = (XmlRpcValueArray)dmem.Data; - foreach (XmlRpcValueBasic language in languageArray.Values) - { - R.Language.Add(language.Data.ToString()); - OSHConsole.WriteLine(" >" + language.Data.ToString()); - } - break; - case "certification": - OSHConsole.WriteLine(">" + dmem.Name + "= "); - // this is an array of certification... - var certificationArray = (XmlRpcValueArray)dmem.Data; - foreach (XmlRpcValueBasic certification in certificationArray.Values) - { - R.Certification.Add(certification.Data.ToString()); - OSHConsole.WriteLine(" >" + certification.Data.ToString()); - } - break; - } - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "GetIMDBMovieDetails call failed !"); - } - /// - /// Allows registered users to insert new movies (not stored in IMDb) to the database. - /// - /// Movie title - /// Release year - /// Status of the call operation. If the call success the response will be 'MethodResponseInsertMovie' - public static IMethodResponse InsertMovie(string movieName, string movieyear) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - // Add token param - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // Add movieinfo struct - var movieinfo = new XmlRpcValueStruct(new List()); - movieinfo.Members.Add(new XmlRpcStructMember("moviename", new XmlRpcValueBasic(movieName))); - movieinfo.Members.Add(new XmlRpcStructMember("movieyear", new XmlRpcValueBasic(movieyear))); - parms.Add(movieinfo); - // Call ! - var call = new XmlRpcMethodCall("InsertMovie", parms); - OSHConsole.WriteLine("Sending InsertMovie request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseInsertMovie(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - if (MEMBER.Name == "status") - { - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("Status= " + R.Status); - } - else if (MEMBER.Name == "seconds") - { - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine("Seconds= " + R.Seconds); - } - else if (MEMBER.Name == "id") - { - R.ID = (string)MEMBER.Data.Data; - OSHConsole.WriteLine("ID= " + R.Seconds); - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "InsertMovie call failed !"); - } - /// - /// Inserts or updates data to tables, which are used for CheckMovieHash() and !CheckMovieHash2(). - /// - /// The parameters - /// Status of the call operation. If the call success the response will be 'MethodResponseInsertMovieHash' - public static IMethodResponse InsertMovieHash(InsertMovieHashParameters[] parameters) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - foreach (InsertMovieHashParameters p in parameters) - { - var pstruct = new XmlRpcValueStruct(new List()); - pstruct.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(p.moviehash))); - pstruct.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(p.moviebytesize))); - pstruct.Members.Add(new XmlRpcStructMember("imdbid", new XmlRpcValueBasic(p.imdbid))); - pstruct.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(p.movietimems))); - pstruct.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(p.moviefps))); - pstruct.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(p.moviefilename))); - parms.Add(pstruct); - } - var call = new XmlRpcMethodCall("InsertMovieHash", parms); - - OSHConsole.WriteLine("Sending InsertMovieHash request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseInsertMovieHash(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "seconds": - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - switch (dataMember.Name) - { - case "accepted_moviehashes": - var mh = (XmlRpcValueArray)dataMember.Data; - foreach (IXmlRpcValue val in mh.Values) - { - if (val is XmlRpcValueBasic) - { - R.accepted_moviehashes.Add(val.Data.ToString()); - } - } - break; - case "new_imdbs": - var mi = (XmlRpcValueArray)dataMember.Data; - foreach (IXmlRpcValue val in mi.Values) - { - if (val is XmlRpcValueBasic) - { - R.new_imdbs.Add(val.Data.ToString()); - } - } - break; - } - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "InsertMovieHash call failed !"); - } - /*Reporting and rating*/ - /// - /// Get basic server information and statistics - /// - /// Status of the call operation. If the call success the response will be 'MethodResponseServerInfo' - public static IMethodResponse ServerInfo() - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT, XmlRpcBasicValueType.String)); - var call = new XmlRpcMethodCall("ServerInfo", parms); - - OSHConsole.WriteLine("Sending ServerInfo request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseServerInfo(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "seconds": - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "xmlrpc_version": - R.xmlrpc_version = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "xmlrpc_url": - R.xmlrpc_url = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "application": - R.application = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "contact": - R.contact = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "website_url": - R.website_url = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "users_online_total": - R.users_online_total = (int)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "users_online_program": - R.users_online_program = (int)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "users_loggedin": - R.users_loggedin = (int)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "users_max_alltime": - R.users_max_alltime = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "users_registered": - R.users_registered = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "subs_downloads": - R.subs_downloads = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "subs_subtitle_files": - R.subs_subtitle_files = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "movies_total": - R.movies_total = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "movies_aka": - R.movies_aka = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "total_subtitles_languages": - R.total_subtitles_languages = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "last_update_strings": - //R.total_subtitles_languages = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + ":"); - var luStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember luMemeber in luStruct.Members) - { - R.last_update_strings.Add(luMemeber.Name + " [" + luMemeber.Data.Data.ToString() + "]"); - OSHConsole.WriteLine(" >" + luMemeber.Name + "= " + luMemeber.Data.Data.ToString()); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "ServerInfo call failed !"); - } - /// - /// Report wrong subtitle file <--> video file combination - /// - /// Identifier of the subtitle file <--> video file combination - /// Status of the call operation. If the call success the response will be 'MethodResponseReportWrongMovieHash' - public static IMethodResponse ReportWrongMovieHash(string IDSubMovieFile) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - parms.Add(new XmlRpcValueBasic(IDSubMovieFile, XmlRpcBasicValueType.String)); - var call = new XmlRpcMethodCall("ReportWrongMovieHash", parms); - - OSHConsole.WriteLine("Sending ReportWrongMovieHash request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseReportWrongMovieHash(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": - R.Status = (string)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - case "seconds": - R.Seconds = (double)MEMBER.Data.Data; - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "ReportWrongMovieHash call failed !"); - } - /// - /// This method is needed to report bad movie hash for imdbid. This method should be used for correcting wrong entries, - /// when using CheckMovieHash2. Pass moviehash and moviebytesize for file, and imdbid as new, corrected one IMDBID - /// (id number without trailing zeroes). After some reports, moviehash will be linked to new imdbid. - /// - /// The movie hash - /// The movie size in bytes - /// The movie imbid - /// Status of the call operation. If the call success the response will be 'MethodResponseReportWrongImdbMovie' - public static IMethodResponse ReportWrongImdbMovie(string moviehash, string moviebytesize, string imdbid) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var s = new XmlRpcValueStruct(new List()); - s.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(moviehash))); - s.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(moviebytesize))); - s.Members.Add(new XmlRpcStructMember("imdbid", new XmlRpcValueBasic(imdbid))); - parms.Add(s); - var call = new XmlRpcMethodCall("ReportWrongImdbMovie", parms); - - OSHConsole.WriteLine("Sending ReportWrongImdbMovie request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseAddComment(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "ReportWrongImdbMovie call failed !"); - } - /// - /// Rate subtitles - /// - /// Id of subtitle (NOT subtitle file) user wants to rate - /// Subtitle rating, must be in interval 1 (worst) to 10 (best). - /// Status of the call operation. If the call success the response will be 'MethodResponseSubtitlesVote' - public static IMethodResponse SubtitlesVote(int idsubtitle, int score) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var s = new XmlRpcValueStruct(new List()); - s.Members.Add(new XmlRpcStructMember("idsubtitle", new XmlRpcValueBasic(idsubtitle))); - s.Members.Add(new XmlRpcStructMember("score", new XmlRpcValueBasic(score))); - parms.Add(s); - var call = new XmlRpcMethodCall("SubtitlesVote", parms); - - OSHConsole.WriteLine("Sending SubtitlesVote request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseSubtitlesVote(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dataMemeber in dataStruct.Members) - { - OSHConsole.WriteLine(" >" + dataMemeber.Name + "= " + dataMemeber.Data.Data.ToString()); - switch (dataMemeber.Name) - { - case "SubRating": R.SubRating = dataMemeber.Data.Data.ToString(); break; - case "SubSumVotes": R.SubSumVotes = dataMemeber.Data.Data.ToString(); break; - case "IDSubtitle": R.IDSubtitle = dataMemeber.Data.Data.ToString(); break; - } - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "SubtitlesVote call failed !"); - } - /// - /// Add comment to a subtitle - /// - /// Subtitle identifier (BEWARE! this is not the ID of subtitle file but of the whole subtitle (a subtitle can contain multiple subtitle files)) - /// User's comment - /// Optional parameter. If set to 1, subtitles are marked as bad. - /// Status of the call operation. If the call success the response will be 'MethodResponseAddComment' - public static IMethodResponse AddComment(int idsubtitle, string comment, int badsubtitle) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var s = new XmlRpcValueStruct(new List()); - s.Members.Add(new XmlRpcStructMember("idsubtitle", new XmlRpcValueBasic(idsubtitle))); - s.Members.Add(new XmlRpcStructMember("comment", new XmlRpcValueBasic(comment))); - s.Members.Add(new XmlRpcStructMember("badsubtitle", new XmlRpcValueBasic(badsubtitle))); - parms.Add(s); - var call = new XmlRpcMethodCall("AddComment", parms); - - OSHConsole.WriteLine("Sending AddComment request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseAddComment(); - - // To make sure response is not currepted by server, do it in loop - foreach (var MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "AddComment call failed !"); - } - /// - /// Add new request for subtitles, user must be logged in - /// - /// The subtitle language id 3 length - /// http://www.imdb.com/ - /// The comment - /// Status of the call operation. If the call success the response will be 'MethodResponseAddRequest' - public static IMethodResponse AddRequest(string sublanguageid, string idmovieimdb, string comment) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var s = new XmlRpcValueStruct(new List()); - s.Members.Add(new XmlRpcStructMember("sublanguageid", new XmlRpcValueBasic(sublanguageid))); - s.Members.Add(new XmlRpcStructMember("idmovieimdb", new XmlRpcValueBasic(idmovieimdb))); - s.Members.Add(new XmlRpcStructMember("comment", new XmlRpcValueBasic(comment))); - parms.Add(s); - var call = new XmlRpcMethodCall("AddRequest", parms); - - OSHConsole.WriteLine("Sending AddRequest request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseAddRequest(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dataMemeber in dataStruct.Members) - { - switch (dataMemeber.Name) - { - case "request_url": R.request_url = dataMemeber.Data.Data.ToString(); OSHConsole.WriteLine(">" + dataMemeber.Name + "= " + dataMemeber.Data.Data.ToString()); break; - } - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "AddRequest call failed !"); - } - /*User interface*/ - /// - /// Get list of supported subtitle languages - /// - /// ISO639-1 2-letter language code of user's interface language. - /// Status of the call operation. If the call success the response will be 'MethodResponseGetSubLanguages' - public static IMethodResponse GetSubLanguages(string language) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueBasic(language)); - var call = new XmlRpcMethodCall("GetSubLanguages", parms); - - OSHConsole.WriteLine("Sending GetSubLanguages request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseGetSubLanguages(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data":// array of structs - var array = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue value in array.Values) - { - if (value is XmlRpcValueStruct) - { - var valueStruct = (XmlRpcValueStruct)value; - var lang = new SubtitleLanguage(); - OSHConsole.WriteLine(">SubLanguage:"); - foreach (XmlRpcStructMember langMemeber in valueStruct.Members) - { - OSHConsole.WriteLine(" >" + langMemeber.Name + "= " + langMemeber.Data.Data.ToString()); - switch (langMemeber.Name) - { - case "SubLanguageID": lang.SubLanguageID = langMemeber.Data.Data.ToString(); break; - case "LanguageName": lang.LanguageName = langMemeber.Data.Data.ToString(); break; - case "ISO639": lang.ISO639 = langMemeber.Data.Data.ToString(); break; - } - } - R.Languages.Add(lang); - } - else - { - OSHConsole.WriteLine(">" + MEMBER.Name + "= " + - MEMBER.Data.Data.ToString() + " [Struct expected !]", DebugCode.Warning); - } - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "GetSubLanguages call failed !"); - } - /// - /// Detect language for given strings - /// - /// Array of strings you want language detected for - /// The encoding that will be used to get buffer of given strings. (this is not OS official parameter) - /// Status of the call operation. If the call success the response will be 'MethodResponseDetectLanguage' - public static IMethodResponse DetectLanguage(string[] texts, Encoding encodingUsed) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - // We need to gzip texts then code them with base 24 - var decodedTexts = new List(); - foreach (string text in texts) - { - // compress - Stream str = new MemoryStream(); - byte[] stringData = encodingUsed.GetBytes(text); - str.Write(stringData, 0, stringData.Length); - str.Position = 0; - byte[] data = Utilities.Compress(str); - //base 64 - decodedTexts.Add(Convert.ToBase64String(data)); - } - parms.Add(new XmlRpcValueArray(decodedTexts.ToArray())); - var call = new XmlRpcMethodCall("DetectLanguage", parms); - - OSHConsole.WriteLine("Sending DetectLanguage request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseDetectLanguage(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - if (MEMBER.Data is XmlRpcValueStruct) - { - OSHConsole.WriteLine(">Languages:"); - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - var lang = new DetectLanguageResult(); - lang.InputSample = dataMember.Name; - lang.LanguageID = dataMember.Data.Data.ToString(); - R.Results.Add(lang); - OSHConsole.WriteLine(" >" + dataMember.Name + " (" + dataMember.Data.Data.ToString() + ")"); - } - } - else - { - OSHConsole.WriteLine(">Languages ?? Struct expected but server return another type!!", DebugCode.Warning); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "DetectLanguage call failed !"); - } - /// - /// Get available translations for given program - /// - /// Name of the program/client application you want translations for. Currently supported values: subdownloader, oscar - /// Status of the call operation. If the call success the response will be 'MethodResponseGetAvailableTranslations' - public static IMethodResponse GetAvailableTranslations(string program) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueBasic(program)); - var call = new XmlRpcMethodCall("GetAvailableTranslations", parms); - - OSHConsole.WriteLine("Sending GetAvailableTranslations request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseGetAvailableTranslations(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - OSHConsole.WriteLine(">data:"); - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - if (dataMember.Data is XmlRpcValueStruct) - { - var resStruct = (XmlRpcValueStruct)dataMember.Data; - var res = new GetAvailableTranslationsResult(); - res.LanguageID = dataMember.Name; - OSHConsole.WriteLine(" >LanguageID: " + dataMember.Name); - foreach (XmlRpcStructMember resMember in resStruct.Members) - { - switch (resMember.Name) - { - case "LastCreated": res.LastCreated = resMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + resMember.Name + "= " + resMember.Data.Data.ToString()); break; - case "StringsNo": res.StringsNo = resMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + resMember.Name + "= " + resMember.Data.Data.ToString()); break; - } - R.Results.Add(res); - } - } - else - { - OSHConsole.WriteLine(" >Struct expected !!", DebugCode.Warning); - } - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "GetAvailableTranslations call failed !"); - } - /// - /// Get a translation for given program and language - /// - /// language ​ISO639-1 2-letter code - /// available formats: [gnugettext compatible: mo, po] and [additional: txt, xml] - /// Name of the program/client application you want translations for. (currently supported values: subdownloader, oscar) - /// Status of the call operation. If the call success the response will be 'MethodResponseGetTranslation' - public static IMethodResponse GetTranslation(string iso639, string format, string program) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueBasic(iso639)); - parms.Add(new XmlRpcValueBasic(format)); - parms.Add(new XmlRpcValueBasic(program)); - var call = new XmlRpcMethodCall("GetTranslation", parms); - - OSHConsole.WriteLine("Sending GetTranslation request to the server ...", DebugCode.Good); - // Send the request to the server - //File.WriteAllText(".\\REQUEST_GetTranslation.xml", Encoding.ASCII.GetString(XmlRpcGenerator.Generate(call))); - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseGetTranslation(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": R.ContentData = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "GetTranslation call failed !"); - } - /// - /// Check for the latest version of given application - /// - /// name of the program/client application you want to check. (Currently supported values: subdownloader, oscar) - /// Status of the call operation. If the call success the response will be 'MethodResponseAutoUpdate' - public static IMethodResponse AutoUpdate(string program) - { - /*if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - }*/ - // Method call .. - var parms = new List(); - // parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueBasic(program)); - // parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT)); - - var call = new XmlRpcMethodCall("AutoUpdate", parms); - OSHConsole.WriteLine("Sending AutoUpdate request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseAutoUpdate(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "version": R.version = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "url_windows": R.url_windows = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "url_linux": R.url_linux = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "comments": R.comments = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "AutoUpdate call failed !"); - } - /*Checking*/ - /// - /// Check if video file hashes are already stored in the database - /// - /// Array of video file hashes - /// Status of the call operation. If the call success the response will be 'MethodResponseCheckMovieHash' - public static IMethodResponse CheckMovieHash(string[] hashes) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueArray(hashes)); - var call = new XmlRpcMethodCall("CheckMovieHash", parms); - - OSHConsole.WriteLine("Sending CheckMovieHash request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseCheckMovieHash(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - OSHConsole.WriteLine(">Data:"); - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - var res = new CheckMovieHashResult(); - res.Name = dataMember.Name; - OSHConsole.WriteLine(" >" + res.Name + ":"); - var movieStruct = (XmlRpcValueStruct)dataMember.Data; - foreach (XmlRpcStructMember movieMember in movieStruct.Members) - { - switch (movieMember.Name) - { - case "MovieHash": res.MovieHash = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieImdbID": res.MovieImdbID = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieName": res.MovieName = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieYear": res.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - } - } - R.Results.Add(res); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "CheckMovieHash call failed !"); - } - /// - /// Check if video file hashes are already stored in the database. This method returns matching !MovieImdbID, MovieName, MovieYear, SeriesSeason, SeriesEpisode, - /// MovieKind if available for each $moviehash, always sorted by SeenCount DESC. - /// - /// Array of video file hashes - /// Status of the call operation. If the call success the response will be 'MethodResponseCheckMovieHash2' - public static IMethodResponse CheckMovieHash2(string[] hashes) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueArray(hashes)); - var call = new XmlRpcMethodCall("CheckMovieHash2", parms); - - OSHConsole.WriteLine("Sending CheckMovieHash2 request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseCheckMovieHash2(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - OSHConsole.WriteLine(">Data:"); - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - var res = new CheckMovieHash2Result(); - res.Name = dataMember.Name; - OSHConsole.WriteLine(" >" + res.Name + ":"); - - var dataArray = (XmlRpcValueArray)dataMember.Data; - foreach (XmlRpcValueStruct movieStruct in dataArray.Values) - { - var d = new CheckMovieHash2Data(); - foreach (XmlRpcStructMember movieMember in movieStruct.Members) - { - switch (movieMember.Name) - { - case "MovieHash": d.MovieHash = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieImdbID": d.MovieImdbID = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieName": d.MovieName = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieYear": d.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "MovieKind": d.MovieKind = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "SeriesSeason": d.SeriesSeason = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "SeriesEpisode": d.SeriesEpisode = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - case "SeenCount": d.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break; - } - } - res.Items.Add(d); - } - R.Results.Add(res); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "CheckMovieHash2 call failed !"); - } - /// - /// Check if given subtitle files are already stored in the database - /// - /// Array of subtitle file hashes (MD5 hashes of subtitle file contents) - /// Status of the call operation. If the call success the response will be 'MethodResponseCheckSubHash' - public static IMethodResponse CheckSubHash(string[] hashes) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - parms.Add(new XmlRpcValueArray(hashes)); - var call = new XmlRpcMethodCall("CheckSubHash", parms); - - OSHConsole.WriteLine("Sending CheckSubHash request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseCheckSubHash(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - OSHConsole.WriteLine(">Data:"); - var dataStruct = (XmlRpcValueStruct)MEMBER.Data; - foreach (XmlRpcStructMember dataMember in dataStruct.Members) - { - OSHConsole.WriteLine(" >" + dataMember.Name + "= " + dataMember.Data.Data.ToString()); - var r = new CheckSubHashResult(); - r.Hash = dataMember.Name; - r.SubID = dataMember.Data.Data.ToString(); - R.Results.Add(r); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "CheckSubHash call failed !"); - } - /*Upload*/ - /// - /// Try to upload subtitles, perform pre-upload checking (i.e. check if subtitles already exist on server) - /// - /// The subtitle parameters collection to try to upload - /// Status of the call operation. If the call success the response will be 'MethodResponseTryUploadSubtitles' - public static IMethodResponse TryUploadSubtitles(TryUploadSubtitlesParameters[] subs) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String)); - var s = new XmlRpcValueStruct(new List()); - int i = 1; - foreach (var cd in subs) - { - var member = new XmlRpcStructMember("cd" + i, null); - var memberStruct = new XmlRpcValueStruct(new List()); - memberStruct.Members.Add(new XmlRpcStructMember("subhash", new XmlRpcValueBasic(cd.subhash))); - memberStruct.Members.Add(new XmlRpcStructMember("subfilename", new XmlRpcValueBasic(cd.subfilename))); - memberStruct.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(cd.moviehash))); - memberStruct.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(cd.moviebytesize))); - memberStruct.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(cd.moviefps))); - memberStruct.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(cd.movietimems))); - memberStruct.Members.Add(new XmlRpcStructMember("movieframes", new XmlRpcValueBasic(cd.movieframes))); - memberStruct.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(cd.moviefilename))); - member.Data = memberStruct; - s.Members.Add(member); - i++; - } - parms.Add(s); - var call = new XmlRpcMethodCall("TryUploadSubtitles", parms); - - OSHConsole.WriteLine("Sending TryUploadSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseTryUploadSubtitles(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "alreadyindb": R.AlreadyInDB = (int)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": - if (MEMBER.Data is XmlRpcValueArray) - { - OSHConsole.WriteLine("Results: "); - - var rarray = (XmlRpcValueArray)MEMBER.Data; - foreach (IXmlRpcValue subStruct in rarray.Values) - { - if (subStruct == null) continue; - if (!(subStruct is XmlRpcValueStruct)) continue; - - var result = new SubtitleSearchResult(); - foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members) - { - // To avoid errors of arranged info or missing ones, let's do it with switch.. - switch (submember.Name) - { - case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break; - case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break; - case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break; - case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break; - case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break; - case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break; - case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break; - case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break; - case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break; - case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break; - case "MovieName": result.MovieName = submember.Data.Data.ToString(); break; - case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break; - case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break; - case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break; - case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break; - case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break; - case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break; - case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break; - case "SubBad": result.SubBad = submember.Data.Data.ToString(); break; - case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break; - case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break; - case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break; - case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break; - case "SubHash": result.SubHash = submember.Data.Data.ToString(); break; - case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break; - case "SubRating": result.SubRating = submember.Data.Data.ToString(); break; - case "SubSize": result.SubSize = submember.Data.Data.ToString(); break; - case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break; - case "UserID": result.UserID = submember.Data.Data.ToString(); break; - case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break; - case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break; - } - } - R.Results.Add(result); - OSHConsole.WriteLine(">" + result.ToString()); - } - } - else// Unknown data ? - { - OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning); - } - break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "TryUploadSubtitles call failed !"); - } - /// - /// Upload given subtitles to OSDb server - /// - /// The pamaters of upload method - /// Status of the call operation. If the call success the response will be 'MethodResponseUploadSubtitles' - public static IMethodResponse UploadSubtitles(UploadSubtitleInfoParameters info) - { - if (TOKEN == "") - { - OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error); - return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first."); - } - // Method call .. - var parms = new List(); - parms.Add(new XmlRpcValueBasic(TOKEN)); - // Main struct - var s = new XmlRpcValueStruct(new List()); - - // Base info member as struct - var member = new XmlRpcStructMember("baseinfo", null); - var memberStruct = new XmlRpcValueStruct(new List()); - memberStruct.Members.Add(new XmlRpcStructMember("idmovieimdb", new XmlRpcValueBasic(info.idmovieimdb))); - memberStruct.Members.Add(new XmlRpcStructMember("sublanguageid", new XmlRpcValueBasic(info.sublanguageid))); - memberStruct.Members.Add(new XmlRpcStructMember("moviereleasename", new XmlRpcValueBasic(info.moviereleasename))); - memberStruct.Members.Add(new XmlRpcStructMember("movieaka", new XmlRpcValueBasic(info.movieaka))); - memberStruct.Members.Add(new XmlRpcStructMember("subauthorcomment", new XmlRpcValueBasic(info.subauthorcomment))); - // memberStruct.Members.Add(new XmlRpcStructMember("hearingimpaired", new XmlRpcValueBasic(info.hearingimpaired))); - // memberStruct.Members.Add(new XmlRpcStructMember("highdefinition", new XmlRpcValueBasic(info.highdefinition))); - // memberStruct.Members.Add(new XmlRpcStructMember("automatictranslation", new XmlRpcValueBasic(info.automatictranslation))); - member.Data = memberStruct; - s.Members.Add(member); - - // CDS members - int i = 1; - foreach (UploadSubtitleParameters cd in info.CDS) - { - var member2 = new XmlRpcStructMember("cd" + i, null); - var memberStruct2 = new XmlRpcValueStruct(new List()); - memberStruct2.Members.Add(new XmlRpcStructMember("subhash", new XmlRpcValueBasic(cd.subhash))); - memberStruct2.Members.Add(new XmlRpcStructMember("subfilename", new XmlRpcValueBasic(cd.subfilename))); - memberStruct2.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(cd.moviehash))); - memberStruct2.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(cd.moviebytesize))); - memberStruct2.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(cd.moviefps))); - memberStruct2.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(cd.movietimems))); - memberStruct2.Members.Add(new XmlRpcStructMember("movieframes", new XmlRpcValueBasic(cd.movieframes))); - memberStruct2.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(cd.moviefilename))); - memberStruct2.Members.Add(new XmlRpcStructMember("subcontent", new XmlRpcValueBasic(cd.subcontent))); - member2.Data = memberStruct2; - s.Members.Add(member2); - i++; - } - - // add main struct to parameters - parms.Add(s); - // add user agent - //parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT)); - var call = new XmlRpcMethodCall("UploadSubtitles", parms); - OSHConsole.WriteLine("Sending UploadSubtitles request to the server ...", DebugCode.Good); - // Send the request to the server - string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT)); - if (!response.Contains("ERROR:")) - { - // No error occur, get and decode the response. - XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response); - if (calls.Length > 0) - { - if (calls[0].Parameters.Count > 0) - { - var mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0]; - // Create the response, we'll need it later - var R = new MethodResponseUploadSubtitles(); - - // To make sure response is not currepted by server, do it in loop - foreach (XmlRpcStructMember MEMBER in mainStruct.Members) - { - switch (MEMBER.Name) - { - case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "data": R.Data = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - case "subtitles": R.SubTitles = (bool)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break; - } - } - // Return the response to user !! - return R; - } - } - } - else - { - OSHConsole.WriteLine(response, DebugCode.Error); - return new MethodResponseError("Fail", response); - } - return new MethodResponseError("Fail", "UploadSubtitles call failed !"); - } - } -} diff --git a/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj b/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj deleted file mode 100644 index eabd3e070..000000000 --- a/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - netstandard2.0 - false - - - diff --git a/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs b/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs deleted file mode 100644 index 39d048545..000000000 --- a/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - public struct GetAvailableTranslationsResult - { - private string _language; - private string _LastCreated; - private string _StringsNo; - - public string LanguageID { get { return _language; } set { _language = value; } } - public string LastCreated { get { return _LastCreated; } set { _LastCreated = value; } } - public string StringsNo { get { return _StringsNo; } set { _StringsNo = value; } } - /// - /// LanguageID (LastCreated) - /// - /// - public override string ToString() - { - return _language + " (" + _LastCreated + ")"; - } - } -} diff --git a/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs b/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs deleted file mode 100644 index 8f4aa9db4..000000000 --- a/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct GetCommentsResult - { - private string _IDSubtitle; - private string _UserID; - private string _UserNickName; - private string _Comment; - private string _Created; - - public string IDSubtitle { get { return _IDSubtitle; } set { _IDSubtitle = value; } } - public string UserID { get { return _UserID; } set { _UserID = value; } } - public string UserNickName { get { return _UserNickName; } set { _UserNickName = value; } } - public string Comment { get { return _Comment; } set { _Comment = value; } } - public string Created { get { return _Created; } set { _Created = value; } } - } -} diff --git a/OpenSubtitlesHandler/Properties/AssemblyInfo.cs b/OpenSubtitlesHandler/Properties/AssemblyInfo.cs deleted file mode 100644 index b5ae23021..000000000 --- a/OpenSubtitlesHandler/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("OpenSubtitlesHandler")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] -[assembly: AssemblyCopyright("Copyright © 2013 Ala Ibrahim Hadid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("1.0.3.0")] -[assembly: AssemblyFileVersion("2019.1.20.3")] diff --git a/OpenSubtitlesHandler/Readme.txt b/OpenSubtitlesHandler/Readme.txt deleted file mode 100644 index d5814aec1..000000000 --- a/OpenSubtitlesHandler/Readme.txt +++ /dev/null @@ -1,20 +0,0 @@ -OpenSubtitlesHandler -==================== -This project is for OpenSubtitles.org integration‏. The point is to allow user to access OpenSubtitles.org database directly -within ASM without the need to open internet browser. -The plan: Implement the "OSDb protocol" http://trac.opensubtitles.org/projects/opensubtitles/wiki/OSDb - -Copyright: -========= -This library ann all its content are written by Ala Ibrahim Hadid. -Copyright © Ala Ibrahim Hadid 2013 -mailto:ahdsoftwares@hotmail.com - -Resources: -========== -* GetHash.dll: this dll is used to compute hash for movie. - For more information please visit http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes#C2 - -XML_RPC: -======== -This class is created to generate XML-RPC requests as XML String. All you need is to call XML_RPC.Generate() method. diff --git a/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs b/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs deleted file mode 100644 index a2fbe8773..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct CheckSubHashResult - { - private string _hash; - private string _id; - - public string Hash { get { return _hash; } set { _hash = value; } } - public string SubID { get { return _id; } set { _id = value; } } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs deleted file mode 100644 index e4194994c..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct SubtitleDownloadResult - { - private string idsubtitlefile; - private string data; - - public string IdSubtitleFile - { get { return idsubtitlefile; } set { idsubtitlefile = value; } } - /// - /// Get or set the data of subtitle file. To decode, decode the string to base64 and then decompress with GZIP. - /// - public string Data - { get { return data; } set { data = value; } } - /// - /// IdSubtitleFile - /// - /// - public override string ToString() - { - return idsubtitlefile.ToString(); - } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs deleted file mode 100644 index b2dc15413..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace OpenSubtitlesHandler -{ - public struct SubtitleLanguage - { - private string _SubLanguageID; - private string _LanguageName; - private string _ISO639; - - public string SubLanguageID { get { return _SubLanguageID; } set { _SubLanguageID = value; } } - public string LanguageName { get { return _LanguageName; } set { _LanguageName = value; } } - public string ISO639 { get { return _ISO639; } set { _ISO639 = value; } } - /// - /// LanguageName [SubLanguageID] - /// - /// LanguageName [SubLanguageID] - public override string ToString() - { - return _LanguageName + " [" + _SubLanguageID + "]"; - } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs deleted file mode 100644 index 5c8f8c01a..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - /// - /// Paramaters for subtitle search call - /// - public struct SubtitleSearchParameters - { - public SubtitleSearchParameters(string subLanguageId, string query = "", string season = "", string episode = "", string movieHash = "", long movieByteSize = 0, string imdbid = "") - { - this.subLanguageId = subLanguageId; - this.movieHash = movieHash; - this.movieByteSize = movieByteSize; - this.imdbid = imdbid; - this._episode = episode; - this._season = season; - this._query = query; - } - - private string subLanguageId; - private string movieHash; - private long movieByteSize; - private string imdbid; - private string _query; - private string _episode; - - public string Episode - { - get { return _episode; } - set { _episode = value; } - } - - public string Season - { - get { return _season; } - set { _season = value; } - } - - private string _season; - - public string Query - { - get { return _query; } - set { _query = value; } - } - - /// - /// List of language ISO639-3 language codes to search for, divided by ',' (e.g. 'cze,eng,slo') - /// - public string SubLangaugeID { get { return subLanguageId; } set { subLanguageId = value; } } - /// - /// Video file hash as calculated by one of the implementation functions as seen on http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes - /// - public string MovieHash { get { return movieHash; } set { movieHash = value; } } - /// - /// Size of video file in bytes - /// - public long MovieByteSize { get { return movieByteSize; } set { movieByteSize = value; } } - /// - /// ​IMDb ID of movie this video is part of, belongs to. - /// - public string IMDbID { get { return imdbid; } set { imdbid = value; } } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs deleted file mode 100644 index a4a8dd3e6..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - /// - /// The subtitle search result that comes with server response on SearchSubtitles successed call - /// - public struct SubtitleSearchResult - { - private string _IDSubMovieFile; - private string _MovieHash; - private string _MovieByteSize; - private string _MovieTimeMS; - private string _IDSubtitleFile; - private string _SubFileName; - private string _SubActualCD; - private string _SubSize; - private string _SubHash; - private string _IDSubtitle; - private string _UserID; - private string _SubLanguageID; - private string _SubFormat; - private string _SeriesSeason; - private string _SeriesEpisode; - private string _SubSumCD; - private string _SubAuthorComment; - private string _SubAddDate; - private string _SubBad; - private string _SubRating; - private string _SubDownloadsCnt; - private string _MovieReleaseName; - private string _IDMovie; - private string _IDMovieImdb; - private string _MovieName; - private string _MovieNameEng; - private string _MovieYear; - private string _MovieImdbRating; - private string _UserNickName; - private string _ISO639; - private string _LanguageName; - private string _SubDownloadLink; - private string _ZipDownloadLink; - - public string IDSubMovieFile - { get { return _IDSubMovieFile; } set { _IDSubMovieFile = value; } } - public string MovieHash - { get { return _MovieHash; } set { _MovieHash = value; } } - public string MovieByteSize - { get { return _MovieByteSize; } set { _MovieByteSize = value; } } - public string MovieTimeMS - { get { return _MovieTimeMS; } set { _MovieTimeMS = value; } } - public string IDSubtitleFile - { get { return _IDSubtitleFile; } set { _IDSubtitleFile = value; } } - public string SubFileName - { get { return _SubFileName; } set { _SubFileName = value; } } - public string SubActualCD - { get { return _SubActualCD; } set { _SubActualCD = value; } } - public string SubSize - { get { return _SubSize; } set { _SubSize = value; } } - public string SubHash - { get { return _SubHash; } set { _SubHash = value; } } - public string IDSubtitle - { get { return _IDSubtitle; } set { _IDSubtitle = value; } } - public string UserID - { get { return _UserID; } set { _UserID = value; } } - public string SubLanguageID - { get { return _SubLanguageID; } set { _SubLanguageID = value; } } - public string SubFormat - { get { return _SubFormat; } set { _SubFormat = value; } } - public string SubSumCD - { get { return _SubSumCD; } set { _SubSumCD = value; } } - public string SubAuthorComment - { get { return _SubAuthorComment; } set { _SubAuthorComment = value; } } - public string SubAddDate - { get { return _SubAddDate; } set { _SubAddDate = value; } } - public string SubBad - { get { return _SubBad; } set { _SubBad = value; } } - public string SubRating - { get { return _SubRating; } set { _SubRating = value; } } - public string SubDownloadsCnt - { get { return _SubDownloadsCnt; } set { _SubDownloadsCnt = value; } } - public string MovieReleaseName - { get { return _MovieReleaseName; } set { _MovieReleaseName = value; } } - public string IDMovie - { get { return _IDMovie; } set { _IDMovie = value; } } - public string IDMovieImdb - { get { return _IDMovieImdb; } set { _IDMovieImdb = value; } } - public string MovieName - { get { return _MovieName; } set { _MovieName = value; } } - public string MovieNameEng - { get { return _MovieNameEng; } set { _MovieNameEng = value; } } - public string MovieYear - { get { return _MovieYear; } set { _MovieYear = value; } } - public string MovieImdbRating - { get { return _MovieImdbRating; } set { _MovieImdbRating = value; } } - public string UserNickName - { get { return _UserNickName; } set { _UserNickName = value; } } - public string ISO639 - { get { return _ISO639; } set { _ISO639 = value; } } - public string LanguageName - { get { return _LanguageName; } set { _LanguageName = value; } } - public string SubDownloadLink - { get { return _SubDownloadLink; } set { _SubDownloadLink = value; } } - public string ZipDownloadLink - { get { return _ZipDownloadLink; } set { _ZipDownloadLink = value; } } - public string SeriesSeason - { get { return _SeriesSeason; } set { _SeriesSeason = value; } } - public string SeriesEpisode - { get { return _SeriesEpisode; } set { _SeriesEpisode = value; } } - /// - /// SubFileName + " (" + SubFormat + ")" - /// - /// - public override string ToString() - { - return _SubFileName + " (" + _SubFormat + ")"; - } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs deleted file mode 100644 index 11f3a706c..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public class TryUploadSubtitlesParameters - { - private string _subhash = ""; - private string _subfilename = ""; - private string _moviehash = ""; - private string _moviebytesize = ""; - private int _movietimems = 0; - private int _movieframes = 0; - private double _moviefps = 0; - private string _moviefilename = ""; - - public string subhash { get { return _subhash; } set { _subhash = value; } } - public string subfilename { get { return _subfilename; } set { _subfilename = value; } } - public string moviehash { get { return _moviehash; } set { _moviehash = value; } } - public string moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } } - public int movietimems { get { return _movietimems; } set { _movietimems = value; } } - public int movieframes { get { return _movieframes; } set { _movieframes = value; } } - public double moviefps { get { return _moviefps; } set { _moviefps = value; } } - public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } } - - public override string ToString() - { - return _subfilename + " (" + _subhash + ")"; - } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs deleted file mode 100644 index 133cc1d23..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace OpenSubtitlesHandler -{ - public class UploadSubtitleInfoParameters - { - private string _idmovieimdb; - private string _moviereleasename; - private string _movieaka; - private string _sublanguageid; - private string _subauthorcomment; - private bool _hearingimpaired; - private bool _highdefinition; - private bool _automatictranslation; - private List cds; - - public string idmovieimdb { get { return _idmovieimdb; } set { _idmovieimdb = value; } } - public string moviereleasename { get { return _moviereleasename; } set { _moviereleasename = value; } } - public string movieaka { get { return _movieaka; } set { _movieaka = value; } } - public string sublanguageid { get { return _sublanguageid; } set { _sublanguageid = value; } } - public string subauthorcomment { get { return _subauthorcomment; } set { _subauthorcomment = value; } } - public bool hearingimpaired { get { return _hearingimpaired; } set { _hearingimpaired = value; } } - public bool highdefinition { get { return _highdefinition; } set { _highdefinition = value; } } - public bool automatictranslation { get { return _automatictranslation; } set { _automatictranslation = value; } } - public List CDS { get { return cds; } set { cds = value; } } - } -} diff --git a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs deleted file mode 100644 index 9910dadc5..000000000 --- a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace OpenSubtitlesHandler -{ - public struct UploadSubtitleParameters - { - private string _subhash; - private string _subfilename; - private string _moviehash; - private double _moviebytesize; - private int _movietimems; - private int _movieframes; - private double _moviefps; - private string _moviefilename; - private string _subcontent; - - public string subhash { get { return _subhash; } set { _subhash = value; } } - public string subfilename { get { return _subfilename; } set { _subfilename = value; } } - public string moviehash { get { return _moviehash; } set { _moviehash = value; } } - public double moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } } - public int movietimems { get { return _movietimems; } set { _movietimems = value; } } - public int movieframes { get { return _movieframes; } set { _movieframes = value; } } - public double moviefps { get { return _moviefps; } set { _moviefps = value; } } - public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } } - /// - /// Sub content. Note: this value must be the subtitle file gziped and then base64 decoded. - /// - public string subcontent { get { return _subcontent; } set { _subcontent = value; } } - - public override string ToString() - { - return _subfilename + " (" + _subhash + ")"; - } - } -} diff --git a/OpenSubtitlesHandler/Utilities.cs b/OpenSubtitlesHandler/Utilities.cs deleted file mode 100644 index 429e28a8f..000000000 --- a/OpenSubtitlesHandler/Utilities.cs +++ /dev/null @@ -1,174 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Cryptography; - -namespace OpenSubtitlesHandler -{ - /// - /// Include helper methods. All member are statics. - /// - public sealed class Utilities - { - public static ICryptoProvider CryptographyProvider { get; set; } - public static IHttpClient HttpClient { get; set; } - private static string XML_RPC_SERVER = "https://api.opensubtitles.org/xml-rpc"; - //private static string XML_RPC_SERVER = "https://92.240.234.122/xml-rpc"; - private static string HostHeader = "api.opensubtitles.org:443"; - - /// - /// Compute movie hash - /// - /// The hash as Hexadecimal string - public static string ComputeHash(Stream stream) - { - byte[] hash = MovieHasher.ComputeMovieHash(stream); - return MovieHasher.ToHexadecimal(hash); - } - /// - /// Decompress data using GZip - /// - /// The stream that hold the data - /// Bytes array of decompressed data - public static byte[] Decompress(Stream dataToDecompress) - { - using (var target = new MemoryStream()) - { - using (var decompressionStream = new System.IO.Compression.GZipStream(dataToDecompress, System.IO.Compression.CompressionMode.Decompress)) - { - decompressionStream.CopyTo(target); - } - return target.ToArray(); - } - } - - /// - /// Compress data using GZip (the retunred buffer will be WITHOUT HEADER) - /// - /// The stream that hold the data - /// Bytes array of compressed data WITHOUT HEADER bytes - public static byte[] Compress(Stream dataToCompress) - { - /*using (var compressed = new MemoryStream()) - { - using (var compressor = new System.IO.Compression.GZipStream(compressed, - System.IO.Compression.CompressionMode.Compress)) - { - dataToCompress.CopyTo(compressor); - } - // Get the compressed bytes only after closing the GZipStream - return compressed.ToArray(); - }*/ - //using (var compressedOutput = new MemoryStream()) - //{ - // using (var compressedStream = new ZlibStream(compressedOutput, - // Ionic.Zlib.CompressionMode.Compress, - // CompressionLevel.Default, false)) - // { - // var buffer = new byte[4096]; - // int byteCount; - // do - // { - // byteCount = dataToCompress.Read(buffer, 0, buffer.Length); - - // if (byteCount > 0) - // { - // compressedStream.Write(buffer, 0, byteCount); - // } - // } while (byteCount > 0); - // } - // return compressedOutput.ToArray(); - //} - - throw new NotImplementedException(); - } - - /// - /// Handle server response stream and decode it as given encoding string. - /// - /// The string of the stream after decode using given encoding - public static string GetStreamString(Stream responseStream) - { - using (responseStream) - { - // Handle response, should be XML text. - var data = new List(); - while (true) - { - int r = responseStream.ReadByte(); - if (r < 0) - break; - data.Add((byte)r); - } - var bytes = data.ToArray(); - return Encoding.ASCII.GetString(bytes, 0, bytes.Length); - } - } - - public static byte[] GetASCIIBytes(string text) - { - return Encoding.ASCII.GetBytes(text); - } - - /// - /// Send a request to the server - /// - /// The request buffer to send as bytes array. - /// The user agent value. - /// Response of the server or stream of error message as string started with 'ERROR:' keyword. - public static Stream SendRequest(byte[] request, string userAgent) - { - return SendRequestAsync(request, userAgent, CancellationToken.None).Result; - } - - public static async Task SendRequestAsync(byte[] request, string userAgent, CancellationToken cancellationToken) - { - var options = new HttpRequestOptions - { - RequestContentBytes = request, - RequestContentType = "text/xml", - UserAgent = userAgent, - Host = HostHeader, - Url = XML_RPC_SERVER, - - // Response parsing will fail with this enabled - EnableHttpCompression = false, - - CancellationToken = cancellationToken, - BufferContent = false - }; - - if (string.IsNullOrEmpty(options.UserAgent)) - { - options.UserAgent = "xmlrpc-epi-php/0.2 (PHP)"; - } - - var result = await HttpClient.Post(options).ConfigureAwait(false); - - return result.Content; - } - - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt b/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt deleted file mode 100644 index a4de38cde..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt +++ /dev/null @@ -1,225 +0,0 @@ -XML-RPC Specification - -Tue, Jun 15, 1999; by Dave Winer. - -Updated 6/30/03 DW - -Updated 10/16/99 DW - -Updated 1/21/99 DW - -This specification documents the XML-RPC protocol implemented in UserLand Frontier 5.1. - -For a non-technical explanation, see XML-RPC for Newbies. - -This page provides all the information that an implementor needs. - -Overview - -XML-RPC is a Remote Procedure Calling protocol that works over the Internet. - -An XML-RPC message is an HTTP-POST request. The body of the request is in XML. A procedure executes on the server and the value it returns is also formatted in XML. - -Procedure parameters can be scalars, numbers, strings, dates, etc.; and can also be complex record and list structures. - -Request example - -Here's an example of an XML-RPC request: - -POST /RPC2 HTTP/1.0 -User-Agent: Frontier/5.1.2 (WinNT) -Host: betty.userland.com -Content-Type: text/xml -Content-length: 181 - - - - examples.getStateName - - - - 41 - - - - - -Header requirements - -The format of the URI in the first line of the header is not specified. For example, it could be empty, a single slash, if the server is only handling XML-RPC calls. However, if the server is handling a mix of incoming HTTP requests, we allow the URI to help route the request to the code that handles XML-RPC requests. (In the example, the URI is /RPC2, telling the server to route the request to the "RPC2" responder.) - -A User-Agent and Host must be specified. - -The Content-Type is text/xml. - -The Content-Length must be specified and must be correct. - -Payload format - -The payload is in XML, a single structure. - -The must contain a sub-item, a string, containing the name of the method to be called. The string may only contain identifier characters, upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon and slash. It's entirely up to the server to decide how to interpret the characters in a methodName. - -For example, the methodName could be the name of a file containing a script that executes on an incoming request. It could be the name of a cell in a database table. Or it could be a path to a file contained within a hierarchy of folders and files. - -If the procedure call has parameters, the must contain a sub-item. The sub-item can contain any number of s, each of which has a . - -Scalar s - -s can be scalars, type is indicated by nesting the value inside one of the tags listed in this table: - -Tag Type Example - or four-byte signed integer -12 - 0 (false) or 1 (true) 1 - string hello world - double-precision signed floating point number -12.214 - date/time 19980717T14:08:55 - base64-encoded binary eW91IGNhbid0IHJlYWQgdGhpcyE= - -If no type is indicated, the type is string. - -s - -A value can also be of type . - -A contains s and each contains a and a . - -Here's an example of a two-element : - - - - lowerBound - 18 - - - upperBound - 139 - - - -s can be recursive, any may contain a or any other type, including an , described below. - -s - -A value can also be of type . - -An contains a single element, which can contain any number of s. - -Here's an example of a four-element array: - - - - 12 - Egypt - 0 - -31 - - - - elements do not have names. - -You can mix types as the example above illustrates. - -s can be recursive, any value may contain an or any other type, including a , described above. - -Response example - -Here's an example of a response to an XML-RPC request: - -HTTP/1.1 200 OK -Connection: close -Content-Length: 158 -Content-Type: text/xml -Date: Fri, 17 Jul 1998 19:55:08 GMT -Server: UserLand Frontier/5.1.2-WinNT - - South Dakota - -Response format - -Unless there's a lower-level error, always return 200 OK. - -The Content-Type is text/xml. Content-Length must be present and correct. - -The body of the response is a single XML structure, a , which can contain a single which contains a single which contains a single . - -The could also contain a which contains a which is a containing two elements, one named , an and one named , a . - -A can not contain both a and a . - -Fault example - -HTTP/1.1 200 OK -Connection: close -Content-Length: 426 -Content-Type: text/xml -Date: Fri, 17 Jul 1998 19:55:02 GMT -Server: UserLand Frontier/5.1.2-WinNT - - faultCode 4 faultString Too many parameters. - -Strategies/Goals - -Firewalls. The goal of this protocol is to lay a compatible foundation across different environments, no new power is provided beyond the capabilities of the CGI interface. Firewall software can watch for POSTs whose Content-Type is text/xml. - -Discoverability. We wanted a clean, extensible format that's very simple. It should be possible for an HTML coder to be able to look at a file containing an XML-RPC procedure call, understand what it's doing, and be able to modify it and have it work on the first or second try. - -Easy to implement. We also wanted it to be an easy to implement protocol that could quickly be adapted to run in other environments or on other operating systems. - -Updated 1/21/99 DW - -The following questions came up on the UserLand discussion group as XML-RPC was being implemented in Python. - - The Response Format section says "The body of the response is a single XML structure, a , which can contain a single ..." This is confusing. Can we leave out the ? - - No you cannot leave it out if the procedure executed successfully. There are only two options, either a response contains a structure or it contains a structure. That's why we used the word "can" in that sentence. - - Is "boolean" a distinct data type, or can boolean values be interchanged with integers (e.g. zero=false, non-zero=true)? - - Yes, boolean is a distinct data type. Some languages/environments allow for an easy coercion from zero to false and one to true, but if you mean true, send a boolean type with the value true, so your intent can't possibly be misunderstood. - - What is the legal syntax (and range) for integers? How to deal with leading zeros? Is a leading plus sign allowed? How to deal with whitespace? - - An integer is a 32-bit signed number. You can include a plus or minus at the beginning of a string of numeric characters. Leading zeros are collapsed. Whitespace is not permitted. Just numeric characters preceeded by a plus or minus. - - What is the legal syntax (and range) for floating point values (doubles)? How is the exponent represented? How to deal with whitespace? Can infinity and "not a number" be represented? - - There is no representation for infinity or negative infinity or "not a number". At this time, only decimal point notation is allowed, a plus or a minus, followed by any number of numeric characters, followed by a period and any number of numeric characters. Whitespace is not allowed. The range of allowable values is implementation-dependent, is not specified. - - What characters are allowed in strings? Non-printable characters? Null characters? Can a "string" be used to hold an arbitrary chunk of binary data? - - Any characters are allowed in a string except < and &, which are encoded as < and &. A string can be used to encode binary data. - - Does the "struct" element keep the order of keys. Or in other words, is the struct "foo=1, bar=2" equivalent to "bar=2, foo=1" or not? - - The struct element does not preserve the order of the keys. The two structs are equivalent. - - Can the struct contain other members than and ? Is there a global list of faultCodes? (so they can be mapped to distinct exceptions for languages like Python and Java)? - - A struct may not contain members other than those specified. This is true for all other structures. We believe the specification is flexible enough so that all reasonable data-transfer needs can be accomodated within the specified structures. If you believe strongly that this is not true, please post a message on the discussion group. - - There is no global list of fault codes. It is up to the server implementer, or higher-level standards to specify fault codes. - - What timezone should be assumed for the dateTime.iso8601 type? UTC? localtime? - - Don't assume a timezone. It should be specified by the server in its documentation what assumptions it makes about timezones. - -Additions - - type. 1/21/99 DW. - -Updated 6/30/03 DW - -Removed "ASCII" from definition of string. - -Changed copyright dates, below, to 1999-2003 from 1998-99. - -Copyright and disclaimer - -© Copyright 1998-2003 UserLand Software. All Rights Reserved. - -This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and these paragraphs are included on all such copies and derivative works. - -This document may not be modified in any way, such as by removing the copyright notice or references to UserLand or other organizations. Further, while these copyright restrictions apply to the written XML-RPC specification, no claim of ownership is made by UserLand to the protocol it describes. Any party may, for commercial or non-commercial purposes, implement this protocol without royalty or license fee to UserLand. The limited permissions granted herein are perpetual and will not be revoked by UserLand or its successors or assigns. - -This document and the information contained herein is provided on an "AS IS" basis and USERLAND DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. diff --git a/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs b/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs deleted file mode 100644 index 51e0ee98f..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs +++ /dev/null @@ -1,25 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -namespace XmlRpcHandler -{ - public enum XmlRpcBasicValueType - { - String, Int, Boolean, Double, dateTime_iso8601, base64 - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs b/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs deleted file mode 100644 index 7cc1a164f..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace XmlRpcHandler -{ - /// - /// A method call - /// - public struct XmlRpcMethodCall - { - /// - /// A method call - /// - /// The name of this method - public XmlRpcMethodCall(string name) - { - this.name = name; - this.parameters = new List(); - } - /// - /// A method call - /// - /// The name of this method - /// A list of parameters - public XmlRpcMethodCall(string name, List parameters) - { - this.name = name; - this.parameters = parameters; - } - - private string name; - private List parameters; - - /// - /// Get or set the name of this method - /// - public string Name - { get { return name; } set { name = value; } } - /// - /// Get or set the parameters to be sent - /// - public List Parameters - { get { return parameters; } set { parameters = value; } } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs b/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs deleted file mode 100644 index c918790cb..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace XmlRpcHandler -{ - public abstract class IXmlRpcValue - { - public IXmlRpcValue() - { } - public IXmlRpcValue(object data) - { - this.data = data; - } - private object data; - /// - /// Get or set the data of this value - /// - public virtual object Data { get { return data; } set { data = value; } } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs deleted file mode 100644 index 2aad7ebff..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -namespace XmlRpcHandler -{ - public class XmlRpcStructMember - { - public XmlRpcStructMember(string name, IXmlRpcValue data) - { - this.name = name; - this.data = data; - } - private string name; - private IXmlRpcValue data; - - /// - /// Get or set the name of this member - /// - public string Name - { get { return name; } set { name = value; } } - /// - /// Get or set the data of this member - /// - public IXmlRpcValue Data - { get { return data; } set { data = value; } } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs deleted file mode 100644 index d10a80175..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; -using System.Collections.Generic; - -namespace XmlRpcHandler -{ - public class XmlRpcValueArray : IXmlRpcValue - { - public XmlRpcValueArray() : - base() - { - values = new List(); - } - public XmlRpcValueArray(object data) : - base(data) - { - values = new List(); - } - public XmlRpcValueArray(string[] texts) : - base() - { - values = new List(); - foreach (string val in texts) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(int[] ints) : - base() - { - values = new List(); - foreach (int val in ints) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(double[] doubles) : - base() - { - values = new List(); - foreach (double val in doubles) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(bool[] bools) : - base() - { - values = new List(); - foreach (bool val in bools) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(long[] base24s) : - base() - { - values = new List(); - foreach (long val in base24s) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(DateTime[] dates) : - base() - { - values = new List(); - foreach (var val in dates) - { - values.Add(new XmlRpcValueBasic(val)); - } - } - public XmlRpcValueArray(XmlRpcValueBasic[] basicValues) : - base() - { - values = new List(); - foreach (var val in basicValues) - { - values.Add(val); - } - } - public XmlRpcValueArray(XmlRpcValueStruct[] structs) : - base() - { - values = new List(); - foreach (var val in structs) - { - values.Add(val); - } - } - public XmlRpcValueArray(XmlRpcValueArray[] arrays) : - base() - { - values = new List(); - foreach (var val in arrays) - { - values.Add(val); - } - } - private List values; - - public List Values { get { return values; } set { values = value; } } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs deleted file mode 100644 index f2811b988..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; - -namespace XmlRpcHandler -{ - public class XmlRpcValueBasic : IXmlRpcValue - { - public XmlRpcValueBasic() - : base() - { } - public XmlRpcValueBasic(string data) - : base(data) - { this.type = XmlRpcBasicValueType.String; } - public XmlRpcValueBasic(int data) - : base(data) - { this.type = XmlRpcBasicValueType.Int; } - public XmlRpcValueBasic(double data) - : base(data) - { this.type = XmlRpcBasicValueType.Double; } - public XmlRpcValueBasic(DateTime data) - : base(data) - { this.type = XmlRpcBasicValueType.dateTime_iso8601; } - public XmlRpcValueBasic(bool data) - : base(data) - { this.type = XmlRpcBasicValueType.Boolean; } - public XmlRpcValueBasic(long data) - : base(data) - { this.type = XmlRpcBasicValueType.base64; } - public XmlRpcValueBasic(object data, XmlRpcBasicValueType type) - : base(data) - { this.type = type; } - - private XmlRpcBasicValueType type = XmlRpcBasicValueType.String; - /// - /// Get or set the type of this basic value - /// - public XmlRpcBasicValueType ValueType { get { return type; } set { type = value; } } - /*Oprators. help a lot.*/ - public static implicit operator string(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return f.Data.ToString(); - else - throw new Exception("Unable to convert, this value is not string type."); - } - public static implicit operator int(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return (int)f.Data; - else - throw new Exception("Unable to convert, this value is not int type."); - } - public static implicit operator double(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return (double)f.Data; - else - throw new Exception("Unable to convert, this value is not double type."); - } - public static implicit operator bool(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return (bool)f.Data; - else - throw new Exception("Unable to convert, this value is not bool type."); - } - public static implicit operator long(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return (long)f.Data; - else - throw new Exception("Unable to convert, this value is not long type."); - } - public static implicit operator DateTime(XmlRpcValueBasic f) - { - if (f.type == XmlRpcBasicValueType.String) - return (DateTime)f.Data; - else - throw new Exception("Unable to convert, this value is not DateTime type."); - } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs deleted file mode 100644 index 4863e38e8..000000000 --- a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -using System.Collections.Generic; - -namespace XmlRpcHandler -{ - /// - /// Represents XML-RPC struct - /// - public class XmlRpcValueStruct : IXmlRpcValue - { - /// - /// Represents XML-RPC struct - /// - /// - public XmlRpcValueStruct(List members) - { this.members = members; } - - private List members; - /// - /// Get or set the members collection - /// - public List Members - { get { return members; } set { members = value; } } - } -} diff --git a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs deleted file mode 100644 index a79a278fa..000000000 --- a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs +++ /dev/null @@ -1,350 +0,0 @@ -/* This file is part of OpenSubtitles Handler - A library that handle OpenSubtitles.org XML-RPC methods. - - Copyright © Ala Ibrahim Hadid 2013 - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using System.Xml; -using OpenSubtitlesHandler; - -namespace XmlRpcHandler -{ - /// - /// A class for making XML-RPC requests. The requests then can be sent directly as http request. - /// - public class XmlRpcGenerator - { - /// - /// Generate XML-RPC request using method call. - /// - /// The method call - /// The request in xml. - public static byte[] Generate(XmlRpcMethodCall method) - { return Generate(new XmlRpcMethodCall[] { method }); } - /// - /// Generate XML-RPC request using method calls array. - /// - /// The method calls array - /// The request in utf8 xml string as buffer - public static byte[] Generate(XmlRpcMethodCall[] methods) - { - if (methods == null) - throw new Exception("No method to write !"); - if (methods.Length == 0) - throw new Exception("No method to write !"); - // Create xml - var sett = new XmlWriterSettings(); - sett.Indent = true; - - sett.Encoding = Encoding.UTF8; - - using (var ms = new MemoryStream()) - { - using (var XMLwrt = XmlWriter.Create(ms, sett)) - { - // Let's write the methods - foreach (XmlRpcMethodCall method in methods) - { - XMLwrt.WriteStartElement("methodCall");//methodCall - XMLwrt.WriteStartElement("methodName");//methodName - XMLwrt.WriteString(method.Name); - XMLwrt.WriteEndElement();//methodName - XMLwrt.WriteStartElement("params");//params - // Write values - foreach (IXmlRpcValue p in method.Parameters) - { - XMLwrt.WriteStartElement("param");//param - if (p is XmlRpcValueBasic) - { - WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p); - } - else if (p is XmlRpcValueStruct) - { - WriteStructValue(XMLwrt, (XmlRpcValueStruct)p); - } - else if (p is XmlRpcValueArray) - { - WriteArrayValue(XMLwrt, (XmlRpcValueArray)p); - } - XMLwrt.WriteEndElement();//param - } - - XMLwrt.WriteEndElement();//params - XMLwrt.WriteEndElement();//methodCall - } - XMLwrt.Flush(); - return ms.ToArray(); - } - } - } - /// - /// Decode response then return the values - /// - /// The response xml string as provided by server as methodResponse - /// - public static XmlRpcMethodCall[] DecodeMethodResponse(string xmlResponse) - { - var methods = new List(); - var sett = new XmlReaderSettings(); - sett.DtdProcessing = DtdProcessing.Ignore; - sett.IgnoreWhitespace = true; - MemoryStream str; - if (xmlResponse.Contains(@"encoding=""utf-8""")) - { - str = new MemoryStream(Encoding.UTF8.GetBytes(xmlResponse)); - } - else - { - str = new MemoryStream(Utilities.GetASCIIBytes(xmlResponse)); - } - using (str) - { - using (var XMLread = XmlReader.Create(str, sett)) - { - var call = new XmlRpcMethodCall("methodResponse"); - // Read parameters - while (XMLread.Read()) - { - if (XMLread.Name == "param" && XMLread.IsStartElement()) - { - IXmlRpcValue val = ReadValue(XMLread); - if (val != null) - call.Parameters.Add(val); - } - } - methods.Add(call); - return methods.ToArray(); - } - } - } - - private static void WriteBasicValue(XmlWriter XMLwrt, XmlRpcValueBasic val) - { - XMLwrt.WriteStartElement("value");//value - switch (val.ValueType) - { - case XmlRpcBasicValueType.String: - XMLwrt.WriteStartElement("string"); - if (val.Data != null) - XMLwrt.WriteString(val.Data.ToString()); - XMLwrt.WriteEndElement(); - break; - case XmlRpcBasicValueType.Int: - XMLwrt.WriteStartElement("int"); - if (val.Data != null) - XMLwrt.WriteString(val.Data.ToString()); - XMLwrt.WriteEndElement(); - break; - case XmlRpcBasicValueType.Boolean: - XMLwrt.WriteStartElement("boolean"); - if (val.Data != null) - XMLwrt.WriteString(((bool)val.Data) ? "1" : "0"); - XMLwrt.WriteEndElement(); - break; - case XmlRpcBasicValueType.Double: - XMLwrt.WriteStartElement("double"); - if (val.Data != null) - XMLwrt.WriteString(val.Data.ToString()); - XMLwrt.WriteEndElement(); - break; - case XmlRpcBasicValueType.dateTime_iso8601: - XMLwrt.WriteStartElement("dateTime.iso8601"); - // Get date time format - if (val.Data != null) - { - var time = (DateTime)val.Data; - string dt = time.Year + time.Month.ToString("D2") + time.Day.ToString("D2") + - "T" + time.Hour.ToString("D2") + ":" + time.Minute.ToString("D2") + ":" + - time.Second.ToString("D2"); - XMLwrt.WriteString(dt); - } - XMLwrt.WriteEndElement(); - break; - case XmlRpcBasicValueType.base64: - XMLwrt.WriteStartElement("base64"); - if (val.Data != null) - XMLwrt.WriteString(Convert.ToBase64String(BitConverter.GetBytes((long)val.Data))); - XMLwrt.WriteEndElement(); - break; - } - XMLwrt.WriteEndElement();//value - } - private static void WriteStructValue(XmlWriter XMLwrt, XmlRpcValueStruct val) - { - XMLwrt.WriteStartElement("value");//value - XMLwrt.WriteStartElement("struct");//struct - foreach (XmlRpcStructMember member in val.Members) - { - XMLwrt.WriteStartElement("member");//member - - XMLwrt.WriteStartElement("name");//name - XMLwrt.WriteString(member.Name); - XMLwrt.WriteEndElement();//name - - if (member.Data is XmlRpcValueBasic) - { - WriteBasicValue(XMLwrt, (XmlRpcValueBasic)member.Data); - } - else if (member.Data is XmlRpcValueStruct) - { - WriteStructValue(XMLwrt, (XmlRpcValueStruct)member.Data); - } - else if (member.Data is XmlRpcValueArray) - { - WriteArrayValue(XMLwrt, (XmlRpcValueArray)member.Data); - } - - XMLwrt.WriteEndElement();//member - } - XMLwrt.WriteEndElement();//struct - XMLwrt.WriteEndElement();//value - } - private static void WriteArrayValue(XmlWriter XMLwrt, XmlRpcValueArray val) - { - XMLwrt.WriteStartElement("value");//value - XMLwrt.WriteStartElement("array");//array - XMLwrt.WriteStartElement("data");//data - foreach (IXmlRpcValue o in val.Values) - { - if (o is XmlRpcValueBasic) - { - WriteBasicValue(XMLwrt, (XmlRpcValueBasic)o); - } - else if (o is XmlRpcValueStruct) - { - WriteStructValue(XMLwrt, (XmlRpcValueStruct)o); - } - else if (o is XmlRpcValueArray) - { - WriteArrayValue(XMLwrt, (XmlRpcValueArray)o); - } - } - XMLwrt.WriteEndElement();//data - XMLwrt.WriteEndElement();//array - XMLwrt.WriteEndElement();//value - } - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - private static string ReadString(XmlReader reader) - { - if (reader.NodeType == XmlNodeType.Element) - { - return reader.ReadElementContentAsString(); - } - return reader.ReadContentAsString(); - } - - private static IXmlRpcValue ReadValue(XmlReader xmlReader, bool skipRead = false) - { - while (skipRead || xmlReader.Read()) - { - if (xmlReader.Name == "value" && xmlReader.IsStartElement()) - { - xmlReader.Read(); - if (xmlReader.Name == "string" && xmlReader.IsStartElement()) - { - return new XmlRpcValueBasic(ReadString(xmlReader), XmlRpcBasicValueType.String); - } - else if (xmlReader.Name == "int" && xmlReader.IsStartElement()) - { - return new XmlRpcValueBasic(int.Parse(ReadString(xmlReader), UsCulture), XmlRpcBasicValueType.Int); - } - else if (xmlReader.Name == "boolean" && xmlReader.IsStartElement()) - { - return new XmlRpcValueBasic(ReadString(xmlReader) == "1", XmlRpcBasicValueType.Boolean); - } - else if (xmlReader.Name == "double" && xmlReader.IsStartElement()) - { - return new XmlRpcValueBasic(double.Parse(ReadString(xmlReader), UsCulture), XmlRpcBasicValueType.Double); - } - else if (xmlReader.Name == "dateTime.iso8601" && xmlReader.IsStartElement()) - { - string date = ReadString(xmlReader); - int year = int.Parse(date.Substring(0, 4), UsCulture); - int month = int.Parse(date.Substring(4, 2), UsCulture); - int day = int.Parse(date.Substring(6, 2), UsCulture); - int hour = int.Parse(date.Substring(9, 2), UsCulture); - int minute = int.Parse(date.Substring(12, 2), UsCulture);//19980717T14:08:55 - int sec = int.Parse(date.Substring(15, 2), UsCulture); - var time = new DateTime(year, month, day, hour, minute, sec); - return new XmlRpcValueBasic(time, XmlRpcBasicValueType.dateTime_iso8601); - } - else if (xmlReader.Name == "base64" && xmlReader.IsStartElement()) - { - return new XmlRpcValueBasic(BitConverter.ToInt64(Convert.FromBase64String(ReadString(xmlReader)), 0) - , XmlRpcBasicValueType.Double); - } - else if (xmlReader.Name == "struct" && xmlReader.IsStartElement()) - { - var strct = new XmlRpcValueStruct(new List()); - // Read members... - while (xmlReader.Read()) - { - if (xmlReader.Name == "member" && xmlReader.IsStartElement()) - { - var member = new XmlRpcStructMember("", null); - xmlReader.Read();// read name - member.Name = ReadString(xmlReader); - - IXmlRpcValue val = ReadValue(xmlReader, true); - if (val != null) - { - member.Data = val; - strct.Members.Add(member); - } - } - else if (xmlReader.Name == "struct" && !xmlReader.IsStartElement()) - { - return strct; - } - } - return strct; - } - else if (xmlReader.Name == "array" && xmlReader.IsStartElement()) - { - var array = new XmlRpcValueArray(); - // Read members... - while (xmlReader.Read()) - { - if (xmlReader.Name == "array" && !xmlReader.IsStartElement()) - { - return array; - } - else - { - IXmlRpcValue val = ReadValue(xmlReader); - if (val != null) - array.Values.Add(val); - } - } - return array; - } - } - else break; - - if (skipRead) - { - return null; - } - } - return null; - } - } -} -- cgit v1.2.3 From b864e9da2a512250eff48baae28251db5a508f8f Mon Sep 17 00:00:00 2001 From: PloughPuff Date: Tue, 12 Mar 2019 22:09:18 +0000 Subject: Finalise removal of --ffprobe switch Removed --ffprobe from src files and server/docker scripts. --- Dockerfile | 3 +-- Dockerfile.arm | 3 +-- Dockerfile.arm64 | 3 +-- Emby.Server.Implementations/ApplicationHost.cs | 1 - Emby.Server.Implementations/IStartupOptions.cs | 5 ----- Jellyfin.Server/StartupOptions.cs | 3 --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 9 --------- deployment/debian-package-x64/pkg-src/conf/jellyfin | 3 +-- deployment/debian-package-x64/pkg-src/jellyfin.service | 2 +- deployment/fedora-package-x64/pkg-src/jellyfin.env | 1 - deployment/fedora-package-x64/pkg-src/jellyfin.service | 2 +- 11 files changed, 6 insertions(+), 29 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Dockerfile b/Dockerfile index 91a4f5a2d..72c0cdbf3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,5 +31,4 @@ VOLUME /cache /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll \ --datadir /config \ --cachedir /cache \ - --ffmpeg /usr/local/bin/ffmpeg \ - --ffprobe /usr/local/bin/ffprobe + --ffmpeg /usr/local/bin/ffmpeg diff --git a/Dockerfile.arm b/Dockerfile.arm index 42f0354a3..238e90ccd 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -39,5 +39,4 @@ VOLUME /cache /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll \ --datadir /config \ --cachedir /cache \ - --ffmpeg /usr/bin/ffmpeg \ - --ffprobe /usr/bin/ffprobe + --ffmpeg /usr/bin/ffmpeg diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index d3103d389..2927d4e65 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -40,5 +40,4 @@ VOLUME /cache /config /media ENTRYPOINT dotnet /jellyfin/jellyfin.dll \ --datadir /config \ --cachedir /cache \ - --ffmpeg /usr/bin/ffmpeg \ - --ffprobe /usr/bin/ffprobe + --ffmpeg /usr/bin/ffmpeg diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 98f6ab6bc..1810064e6 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -837,7 +837,6 @@ namespace Emby.Server.Implementations LoggerFactory, JsonSerializer, StartupOptions.FFmpegPath, - StartupOptions.FFprobePath, ServerConfigurationManager, FileSystemManager, () => SubtitleEncoder, diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index 24aaa76c0..6e915de3d 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -7,11 +7,6 @@ namespace Emby.Server.Implementations ///
string FFmpegPath { get; } - /// - /// --ffprobe - /// - string FFprobePath { get; } - /// /// --service /// diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 345a8a731..8296d414e 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -26,9 +26,6 @@ namespace Jellyfin.Server [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")] public string FFmpegPath { get; set; } - [Option("ffprobe", Required = false, HelpText = "(deprecated) Option has no effect and shall be removed in next release.")] - public string FFprobePath { get; set; } - [Option("service", Required = false, HelpText = "Run as headless service.")] public bool IsService { get; set; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 94beda3db..f454c2723 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -51,7 +51,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IProcessFactory _processFactory; private readonly int DefaultImageExtractionTimeoutMs; private readonly string StartupOptionFFmpegPath; - private readonly string StartupOptionFFprobePath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); private readonly List _runningProcesses = new List(); @@ -60,7 +59,6 @@ namespace MediaBrowser.MediaEncoding.Encoder ILoggerFactory loggerFactory, IJsonSerializer jsonSerializer, string startupOptionsFFmpegPath, - string startupOptionsFFprobePath, IServerConfigurationManager configurationManager, IFileSystem fileSystem, Func subtitleEncoder, @@ -71,7 +69,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger = loggerFactory.CreateLogger(nameof(MediaEncoder)); _jsonSerializer = jsonSerializer; StartupOptionFFmpegPath = startupOptionsFFmpegPath; - StartupOptionFFprobePath = startupOptionsFFprobePath; ConfigurationManager = configurationManager; FileSystem = fileSystem; SubtitleEncoder = subtitleEncoder; @@ -86,12 +83,6 @@ namespace MediaBrowser.MediaEncoding.Encoder ///
public void SetFFmpegPath() { - // ToDo - Finalise removal of the --ffprobe switch - if (!string.IsNullOrEmpty(StartupOptionFFprobePath)) - { - _logger.LogWarning("--ffprobe switch is deprecated and shall be removed in the next release"); - } - // 1) Custom path stored in config/encoding xml file under tag takes precedence if (!ValidatePath(ConfigurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) { diff --git a/deployment/debian-package-x64/pkg-src/conf/jellyfin b/deployment/debian-package-x64/pkg-src/conf/jellyfin index 7db482d42..bc00c37e2 100644 --- a/deployment/debian-package-x64/pkg-src/conf/jellyfin +++ b/deployment/debian-package-x64/pkg-src/conf/jellyfin @@ -23,7 +23,6 @@ JELLYFIN_RESTART_OPT="--restartpath=/usr/lib/jellyfin/restart.sh" # ffmpeg binary paths, overriding the system values JELLYFIN_FFMPEG_OPT="--ffmpeg=/usr/share/jellyfin-ffmpeg/ffmpeg" -JELLYFIN_FFPROBE_OPT="--ffprobe=/usr/share/jellyfin-ffmpeg/ffprobe" # [OPTIONAL] run Jellyfin as a headless service #JELLYFIN_SERVICE_OPT="--service" @@ -38,4 +37,4 @@ JELLYFIN_FFPROBE_OPT="--ffprobe=/usr/share/jellyfin-ffmpeg/ffprobe" # Application username JELLYFIN_USER="jellyfin" # Full application command -JELLYFIN_ARGS="$JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_FFPROBE_OPT $JELLYFIN_SERVICE_OPT $JELLFIN_NOWEBAPP_OPT" +JELLYFIN_ARGS="$JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_SERVICE_OPT $JELLFIN_NOWEBAPP_OPT" diff --git a/deployment/debian-package-x64/pkg-src/jellyfin.service b/deployment/debian-package-x64/pkg-src/jellyfin.service index b4da3a945..1305e238b 100644 --- a/deployment/debian-package-x64/pkg-src/jellyfin.service +++ b/deployment/debian-package-x64/pkg-src/jellyfin.service @@ -6,7 +6,7 @@ After = network.target Type = simple EnvironmentFile = /etc/default/jellyfin User = jellyfin -ExecStart = /usr/bin/jellyfin ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_FFPROBE_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} +ExecStart = /usr/bin/jellyfin ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} Restart = on-failure TimeoutSec = 15 diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.env b/deployment/fedora-package-x64/pkg-src/jellyfin.env index 143a317c4..de48f13af 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.env +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.env @@ -25,7 +25,6 @@ JELLYFIN_RESTART_OPT="--restartpath=/usr/libexec/jellyfin/restart.sh" # [OPTIONAL] ffmpeg binary paths, overriding the UI-configured values #JELLYFIN_FFMPEG_OPT="--ffmpeg=/usr/bin/ffmpeg" -#JELLYFIN_FFPROBE_OPT="--ffprobe=/usr/bin/ffprobe" # [OPTIONAL] run Jellyfin as a headless service #JELLYFIN_SERVICE_OPT="--service" diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.service b/deployment/fedora-package-x64/pkg-src/jellyfin.service index 1f83d3d38..f3dc594b1 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.service +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.service @@ -5,7 +5,7 @@ Description=Jellyfin is a free software media system that puts you in control of [Service] EnvironmentFile=/etc/sysconfig/jellyfin WorkingDirectory=/var/lib/jellyfin -ExecStart=/usr/bin/jellyfin ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_FFPROBE_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} +ExecStart=/usr/bin/jellyfin ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} TimeoutSec=15 Restart=on-failure User=jellyfin -- cgit v1.2.3 From ee7bf86e0f76cdd655f9f9766a4b99f5210ce985 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 14 Mar 2019 22:05:33 +0100 Subject: Adjusted the Product Name so the User Agent is correct/better. --- BDInfo/Properties/AssemblyInfo.cs | 2 +- DvdLib/Properties/AssemblyInfo.cs | 2 +- Emby.Dlna/Properties/AssemblyInfo.cs | 2 +- Emby.Drawing/Properties/AssemblyInfo.cs | 2 +- Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs | 2 +- Emby.Naming/Properties/AssemblyInfo.cs | 2 +- Emby.Notifications/Properties/AssemblyInfo.cs | 2 +- Emby.Photos/Properties/AssemblyInfo.cs | 2 +- Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs | 2 +- Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs | 2 +- Jellyfin.Server/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Api/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Common/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Controller/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Model/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Providers/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Tests/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs | 2 +- Mono.Nat/Properties/AssemblyInfo.cs | 2 +- RSSDP/Properties/AssemblyInfo.cs | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/BDInfo/Properties/AssemblyInfo.cs b/BDInfo/Properties/AssemblyInfo.cs index 788cf7366..482cd376a 100644 --- a/BDInfo/Properties/AssemblyInfo.cs +++ b/BDInfo/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/DvdLib/Properties/AssemblyInfo.cs b/DvdLib/Properties/AssemblyInfo.cs index 5fc055d1f..09d1a3801 100644 --- a/DvdLib/Properties/AssemblyInfo.cs +++ b/DvdLib/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.Dlna/Properties/AssemblyInfo.cs b/Emby.Dlna/Properties/AssemblyInfo.cs index 9d3a22c97..0e3b03a32 100644 --- a/Emby.Dlna/Properties/AssemblyInfo.cs +++ b/Emby.Dlna/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Resources; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.Drawing/Properties/AssemblyInfo.cs b/Emby.Drawing/Properties/AssemblyInfo.cs index 8dfefe0af..442983960 100644 --- a/Emby.Drawing/Properties/AssemblyInfo.cs +++ b/Emby.Drawing/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs b/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs index d60eccc2e..702aed3b5 100644 --- a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs +++ b/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.Naming/Properties/AssemblyInfo.cs b/Emby.Naming/Properties/AssemblyInfo.cs index 15311570b..9295a1ec7 100644 --- a/Emby.Naming/Properties/AssemblyInfo.cs +++ b/Emby.Naming/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.Notifications/Properties/AssemblyInfo.cs b/Emby.Notifications/Properties/AssemblyInfo.cs index fd7037551..53b80e3dc 100644 --- a/Emby.Notifications/Properties/AssemblyInfo.cs +++ b/Emby.Notifications/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.Photos/Properties/AssemblyInfo.cs b/Emby.Photos/Properties/AssemblyInfo.cs index 262125d38..c3ebc4e08 100644 --- a/Emby.Photos/Properties/AssemblyInfo.cs +++ b/Emby.Photos/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs b/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs index ff2efb078..69a532c35 100644 --- a/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs +++ b/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs index ea1c457f6..9fdb9529f 100644 --- a/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs +++ b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Jellyfin.Server/Properties/AssemblyInfo.cs b/Jellyfin.Server/Properties/AssemblyInfo.cs index 2959cdf1f..1add32c8c 100644 --- a/Jellyfin.Server/Properties/AssemblyInfo.cs +++ b/Jellyfin.Server/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Api/Properties/AssemblyInfo.cs b/MediaBrowser.Api/Properties/AssemblyInfo.cs index f86723031..fb7d43f45 100644 --- a/MediaBrowser.Api/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Api/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Common/Properties/AssemblyInfo.cs b/MediaBrowser.Common/Properties/AssemblyInfo.cs index 1a8fdb618..d428cea2f 100644 --- a/MediaBrowser.Common/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Common/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Controller/Properties/AssemblyInfo.cs b/MediaBrowser.Controller/Properties/AssemblyInfo.cs index 007a1d739..0841e84f2 100644 --- a/MediaBrowser.Controller/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Controller/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs index 3eac83708..4d09084d2 100644 --- a/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs +++ b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs index 6ecdf89bc..8851ec527 100644 --- a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs +++ b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Model/Properties/AssemblyInfo.cs b/MediaBrowser.Model/Properties/AssemblyInfo.cs index e78719e35..f11829481 100644 --- a/MediaBrowser.Model/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Model/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Providers/Properties/AssemblyInfo.cs b/MediaBrowser.Providers/Properties/AssemblyInfo.cs index d2b13fc89..eb2599e35 100644 --- a/MediaBrowser.Providers/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Providers/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.Tests/Properties/AssemblyInfo.cs b/MediaBrowser.Tests/Properties/AssemblyInfo.cs index 9bc2a19f2..1bd3ef5d6 100644 --- a/MediaBrowser.Tests/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Tests/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin System")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs b/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs index 416ce4826..346853f58 100644 --- a/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs +++ b/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs index 11e513f1b..343befb7e 100644 --- a/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs +++ b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Mono.Nat/Properties/AssemblyInfo.cs b/Mono.Nat/Properties/AssemblyInfo.cs index ea1c9dee6..c24a4fc6c 100644 --- a/Mono.Nat/Properties/AssemblyInfo.cs +++ b/Mono.Nat/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2006 Alan McGovern. Copyright © 2007 Ben Motmans. Code releases unde the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/RSSDP/Properties/AssemblyInfo.cs b/RSSDP/Properties/AssemblyInfo.cs index d2bb7c6f3..690ddb807 100644 --- a/RSSDP/Properties/AssemblyInfo.cs +++ b/RSSDP/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")] +[assembly: AssemblyProduct("Jellyfin Server")] [assembly: AssemblyCopyright("Copyright © 2015 Troy Willmot. Code released under the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -- cgit v1.2.3 From 21cc38fcf426f5ecaedbe8a94007a89663de749c Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 14 Mar 2019 22:17:56 +0100 Subject: Adjusted AssemblyCopyright attribute values. --- BDInfo/Properties/AssemblyInfo.cs | 2 +- DvdLib/Properties/AssemblyInfo.cs | 2 +- Emby.Dlna/Properties/AssemblyInfo.cs | 2 +- Emby.Drawing/Properties/AssemblyInfo.cs | 2 +- Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs | 2 +- Emby.Naming/Properties/AssemblyInfo.cs | 2 +- Emby.Notifications/Properties/AssemblyInfo.cs | 2 +- Emby.Photos/Properties/AssemblyInfo.cs | 2 +- Emby.Server.Implementations/Properties/AssemblyInfo.cs | 2 +- Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs | 2 +- Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs | 2 +- Jellyfin.Server/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Api/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Common/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Controller/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Model/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.Providers/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs | 2 +- MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs | 2 +- Mono.Nat/Properties/AssemblyInfo.cs | 2 +- RSSDP/Properties/AssemblyInfo.cs | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/BDInfo/Properties/AssemblyInfo.cs b/BDInfo/Properties/AssemblyInfo.cs index 482cd376a..f65c7036a 100644 --- a/BDInfo/Properties/AssemblyInfo.cs +++ b/BDInfo/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/DvdLib/Properties/AssemblyInfo.cs b/DvdLib/Properties/AssemblyInfo.cs index 09d1a3801..6acd571d6 100644 --- a/DvdLib/Properties/AssemblyInfo.cs +++ b/DvdLib/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Dlna/Properties/AssemblyInfo.cs b/Emby.Dlna/Properties/AssemblyInfo.cs index 0e3b03a32..a2c1e0db8 100644 --- a/Emby.Dlna/Properties/AssemblyInfo.cs +++ b/Emby.Dlna/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Resources; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Drawing/Properties/AssemblyInfo.cs b/Emby.Drawing/Properties/AssemblyInfo.cs index 442983960..281008e37 100644 --- a/Emby.Drawing/Properties/AssemblyInfo.cs +++ b/Emby.Drawing/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs b/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs index 702aed3b5..5956fc3b3 100644 --- a/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs +++ b/Emby.IsoMounting/IsoMounter/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Naming/Properties/AssemblyInfo.cs b/Emby.Naming/Properties/AssemblyInfo.cs index 9295a1ec7..f26e0ba79 100644 --- a/Emby.Naming/Properties/AssemblyInfo.cs +++ b/Emby.Naming/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Notifications/Properties/AssemblyInfo.cs b/Emby.Notifications/Properties/AssemblyInfo.cs index 53b80e3dc..5c82c90c4 100644 --- a/Emby.Notifications/Properties/AssemblyInfo.cs +++ b/Emby.Notifications/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Photos/Properties/AssemblyInfo.cs b/Emby.Photos/Properties/AssemblyInfo.cs index c3ebc4e08..a3bb4362a 100644 --- a/Emby.Photos/Properties/AssemblyInfo.cs +++ b/Emby.Photos/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.Server.Implementations/Properties/AssemblyInfo.cs b/Emby.Server.Implementations/Properties/AssemblyInfo.cs index 79ba9374c..a1933f66e 100644 --- a/Emby.Server.Implementations/Properties/AssemblyInfo.cs +++ b/Emby.Server.Implementations/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs b/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs index 69a532c35..7beec09cb 100644 --- a/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs +++ b/Emby.XmlTv/Emby.XmlTv/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs index 9fdb9529f..e7db09449 100644 --- a/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs +++ b/Jellyfin.Drawing.Skia/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Jellyfin.Server/Properties/AssemblyInfo.cs b/Jellyfin.Server/Properties/AssemblyInfo.cs index 1add32c8c..5de1e653d 100644 --- a/Jellyfin.Server/Properties/AssemblyInfo.cs +++ b/Jellyfin.Server/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.Api/Properties/AssemblyInfo.cs b/MediaBrowser.Api/Properties/AssemblyInfo.cs index fb7d43f45..35bcbea5c 100644 --- a/MediaBrowser.Api/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Api/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.Common/Properties/AssemblyInfo.cs b/MediaBrowser.Common/Properties/AssemblyInfo.cs index d428cea2f..538e89fd1 100644 --- a/MediaBrowser.Common/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Common/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.Controller/Properties/AssemblyInfo.cs b/MediaBrowser.Controller/Properties/AssemblyInfo.cs index 0841e84f2..60e792309 100644 --- a/MediaBrowser.Controller/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Controller/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs index 4d09084d2..580cef9da 100644 --- a/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs +++ b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs index 8851ec527..a9491374b 100644 --- a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs +++ b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.Model/Properties/AssemblyInfo.cs b/MediaBrowser.Model/Properties/AssemblyInfo.cs index f11829481..f99e9ece9 100644 --- a/MediaBrowser.Model/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Model/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.Providers/Properties/AssemblyInfo.cs b/MediaBrowser.Providers/Properties/AssemblyInfo.cs index eb2599e35..f1c46899c 100644 --- a/MediaBrowser.Providers/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Providers/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs b/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs index 346853f58..584d49021 100644 --- a/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs +++ b/MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs index 343befb7e..b3e2f2717 100644 --- a/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs +++ b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/Mono.Nat/Properties/AssemblyInfo.cs b/Mono.Nat/Properties/AssemblyInfo.cs index c24a4fc6c..dc47f2ffe 100644 --- a/Mono.Nat/Properties/AssemblyInfo.cs +++ b/Mono.Nat/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2006 Alan McGovern. Copyright © 2007 Ben Motmans. Code releases unde the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2006 Alan McGovern. Copyright © 2007 Ben Motmans. Code releases under the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] diff --git a/RSSDP/Properties/AssemblyInfo.cs b/RSSDP/Properties/AssemblyInfo.cs index 690ddb807..55f7b6a83 100644 --- a/RSSDP/Properties/AssemblyInfo.cs +++ b/RSSDP/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jellyfin Project")] [assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2015 Troy Willmot. Code released under the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")] +[assembly: AssemblyCopyright("Copyright © 2015 Troy Willmot. Code released under the MIT license. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] -- cgit v1.2.3 From 427688a0a08e04e87774d01e7bfec22eecc71e7d Mon Sep 17 00:00:00 2001 From: redSpoutnik <15638041+redSpoutnik@users.noreply.github.com> Date: Thu, 14 Mar 2019 22:31:51 +0100 Subject: Change subtitles DisplayTitle behavior --- Emby.Server.Implementations/ApplicationHost.cs | 5 +++-- .../Data/SqliteItemRepository.cs | 13 ++++++++++- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 8 +++++-- .../Probing/ProbeResultNormalizer.cs | 8 ++++++- MediaBrowser.Model/Entities/MediaStream.cs | 26 +++++++++++++++++----- 5 files changed, 49 insertions(+), 11 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index b3bb4f740..f185d37ad 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -703,7 +703,7 @@ namespace Emby.Server.Implementations var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LoggerFactory, JsonSerializer, ApplicationPaths, FileSystemManager); serviceCollection.AddSingleton(displayPreferencesRepo); - ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo); + ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo, LocalizationManager); serviceCollection.AddSingleton(ItemRepository); AuthenticationRepository = GetAuthenticationRepository(); @@ -979,7 +979,8 @@ namespace Emby.Server.Implementations HttpClient, ZipClient, ProcessFactory, - 5000); + 5000, + LocalizationManager); MediaEncoder = mediaEncoder; serviceCollection.AddSingleton(MediaEncoder); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 06f6563a3..1aeb3b9c5 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -22,6 +22,7 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Reflection; @@ -56,6 +57,8 @@ namespace Emby.Server.Implementations.Data private readonly IServerConfigurationManager _config; private IServerApplicationHost _appHost; + private readonly ILocalizationManager _localization; + public IImageProcessor ImageProcessor { get; set; } /// @@ -66,7 +69,8 @@ namespace Emby.Server.Implementations.Data IServerApplicationHost appHost, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, - IAssemblyInfo assemblyInfo) + IAssemblyInfo assemblyInfo, + ILocalizationManager localization) : base(loggerFactory.CreateLogger(nameof(SqliteItemRepository))) { if (config == null) @@ -83,6 +87,7 @@ namespace Emby.Server.Implementations.Data _config = config; _jsonSerializer = jsonSerializer; _typeMapper = new TypeMapper(assemblyInfo); + _localization = localization; DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } @@ -6189,6 +6194,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type item.ColorTransfer = reader[34].ToString(); } + if (item.Type == MediaStreamType.Subtitle){ + item.localizedUndefined = _localization.GetLocalizedString("Undefined"); + item.localizedDefault = _localization.GetLocalizedString("Default"); + item.localizedForced = _localization.GetLocalizedString("Forced"); + } + return item; } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7f29c06b4..d7449d57d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -19,6 +19,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; @@ -69,6 +70,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string _originalFFMpegPath; private readonly string _originalFFProbePath; private readonly int DefaultImageExtractionTimeoutMs; + private readonly ILocalizationManager _localization; public MediaEncoder( ILoggerFactory loggerFactory, @@ -88,7 +90,8 @@ namespace MediaBrowser.MediaEncoding.Encoder IHttpClient httpClient, IZipClient zipClient, IProcessFactory processFactory, - int defaultImageExtractionTimeoutMs) + int defaultImageExtractionTimeoutMs, + ILocalizationManager localization) { _logger = loggerFactory.CreateLogger(nameof(MediaEncoder)); _jsonSerializer = jsonSerializer; @@ -110,6 +113,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _originalFFProbePath = ffProbePath; _originalFFMpegPath = ffMpegPath; _hasExternalEncoder = hasExternalEncoder; + _localization = localization; } public string EncoderLocationType @@ -537,7 +541,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + return new ProbeResultNormalizer(_logger, FileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); } catch { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 5099ccb2a..3e6e5864c 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; @@ -20,11 +21,13 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; private readonly IFileSystem _fileSystem; + private readonly ILocalizationManager _localization; - public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem) + public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, ILocalizationManager localization) { _logger = logger; _fileSystem = fileSystem; + _localization = localization; } public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) @@ -599,6 +602,9 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.Type = MediaStreamType.Subtitle; stream.Codec = NormalizeSubtitleCodec(stream.Codec); + stream.localizedUndefined = _localization.GetLocalizedString("Undefined"); + stream.localizedDefault = _localization.GetLocalizedString("Default"); + stream.localizedForced = _localization.GetLocalizedString("Forced"); } else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index fc346df37..8dcf679a3 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Text; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.MediaInfo; @@ -65,6 +67,10 @@ namespace MediaBrowser.Model.Entities } } + public string localizedUndefined { get; set; } + public string localizedDefault { get; set; } + public string localizedForced { get; set; } + public string DisplayTitle { get @@ -141,22 +147,30 @@ namespace MediaBrowser.Model.Entities } else { - attributes.Add("Und"); + attributes.Add(string.IsNullOrEmpty(localizedUndefined) ? "Und" : localizedUndefined); } if (IsDefault) { - attributes.Add("Default"); + attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault); } if (IsForced) { - attributes.Add("Forced"); + attributes.Add(string.IsNullOrEmpty(localizedForced) ? "Forced" : localizedForced); } - string name = string.Join(" ", attributes.ToArray()); + if (!string.IsNullOrEmpty(Title)) + { + return attributes.AsEnumerable() + // keep Tags that are not already in Title + .Where(tag => Title.IndexOf(tag, StringComparison.OrdinalIgnoreCase) == -1) + // attributes concatenation, starting with Title + .Aggregate(new StringBuilder(Title), (builder, attr) => builder.Append(" - ").Append(attr)) + .ToString(); + } - return name; + return string.Join(" - ", attributes.ToArray()); } if (Type == MediaStreamType.Video) @@ -220,6 +234,7 @@ namespace MediaBrowser.Model.Entities return null; } + /* private string AddLanguageIfNeeded(string title) { if (!string.IsNullOrEmpty(Language) && @@ -241,6 +256,7 @@ namespace MediaBrowser.Model.Entities return false; } + */ public string NalLengthSize { get; set; } -- cgit v1.2.3 From a7e31ef31f0202cefe1fd97a648260c3f4791446 Mon Sep 17 00:00:00 2001 From: Phallacy Date: Thu, 4 Apr 2019 23:04:54 -0700 Subject: applied changes to just also search jellyfin base dir --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4867c0f85..b626600fa 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -230,6 +230,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// private string ExistsOnSystemPath(string filename) { + string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, filename); + if (!string.IsNullOrEmpty(inJellyfinPath)) + { + return inJellyfinPath; + } var values = Environment.GetEnvironmentVariable("PATH"); foreach (var path in values.Split(Path.PathSeparator)) -- cgit v1.2.3 From 91cd7d2f6b3e9ce1212d9c29519aa2b23731b8e9 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 30 Apr 2019 23:35:39 +0200 Subject: Limit amount of ffmpeg processes extracting images at once --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 37 +++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index b626600fa..a8874b6d0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly int DefaultImageExtractionTimeoutMs; private readonly string StartupOptionFFmpegPath; - private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); private readonly List _runningProcesses = new List(); private readonly ILocalizationManager _localization; @@ -582,19 +582,27 @@ namespace MediaBrowser.MediaEncoding.Encoder { bool ranToCompletion; - StartProcess(processWrapper); - - var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs; - if (timeoutMs <= 0) + await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + try { - timeoutMs = DefaultImageExtractionTimeoutMs; - } + StartProcess(processWrapper); + + var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs; + if (timeoutMs <= 0) + { + timeoutMs = DefaultImageExtractionTimeoutMs; + } - ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false); + ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false); - if (!ranToCompletion) + if (!ranToCompletion) + { + StopProcess(processWrapper, 1000); + } + } + finally { - StopProcess(processWrapper, 1000); + _thumbnailResourcePool.Release(); } var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; @@ -625,7 +633,8 @@ namespace MediaBrowser.MediaEncoding.Encoder return time.ToString(@"hh\:mm\:ss\.fff", UsCulture); } - public async Task ExtractVideoImagesOnInterval(string[] inputFiles, + public async Task ExtractVideoImagesOnInterval( + string[] inputFiles, string container, MediaStream videoStream, MediaProtocol protocol, @@ -636,8 +645,6 @@ namespace MediaBrowser.MediaEncoding.Encoder int? maxWidth, CancellationToken cancellationToken) { - var resourcePool = _thumbnailResourcePool; - var inputArgument = GetInputArgument(inputFiles, protocol); var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture); @@ -701,7 +708,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments); - await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); bool ranToCompletion = false; @@ -742,7 +749,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } finally { - resourcePool.Release(); + _thumbnailResourcePool.Release(); } var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; -- cgit v1.2.3 From 5d85076ad5152b60ca2101177330b24944a65411 Mon Sep 17 00:00:00 2001 From: JMCC Date: Sat, 11 May 2019 17:17:32 +0200 Subject: Enable Exynos V4L2-m2m HW encoder --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 3eed891cb..b00350875 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -207,6 +207,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc_omx", "h264_vaapi", "hevc_vaapi", + "h264_v4l2m2m", "ac3" }; -- cgit v1.2.3 From 5c1fbfca03a88eebb7ae4703c97d1d7896c93585 Mon Sep 17 00:00:00 2001 From: Tristan McCann Date: Tue, 11 Jun 2019 21:34:23 -0400 Subject: Stop path substitution in SubtitleEncoder This fixes jellyfin/jellyfin#1446. I am not an expert in this section of code, but I cannot think of a need to do path substitution during subtitle encoding. --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d978359c7..8677b363f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -126,8 +126,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(mediaSourceId)); } - // TODO network path substition useful ? - var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, true, cancellationToken).ConfigureAwait(false); + var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); var mediaSource = mediaSources .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); -- cgit v1.2.3 From 555459525515edf9f506465cefce0c6a6aca326d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 14 Jun 2019 18:49:57 +0200 Subject: Update deps --- Emby.Naming/Emby.Naming.csproj | 2 +- .../Emby.Server.Implementations.csproj | 7 +++---- Jellyfin.Server/Jellyfin.Server.csproj | 14 +++++++------- .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 +- jellyfin.ruleset | 4 ++++ 6 files changed, 17 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 6e05eb795..9e2a4950f 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -23,7 +23,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index d4e17c42a..49015a07e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -31,10 +31,9 @@ - - + + - @@ -52,7 +51,7 @@ - + diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 81f145abf..641b3f182 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -26,7 +26,7 @@ - + @@ -36,17 +36,17 @@ - - + + - - + + - - + + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index e4757543e..c0f92ac4a 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,7 +18,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index cfbb85ea6..5941ed436 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -14,7 +14,7 @@ - + diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 0a60c8c7a..1249a60c0 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -25,10 +25,14 @@ + + + + -- cgit v1.2.3 From 59518ec87e828aff21e5f0f67e82f00fc8fa13ba Mon Sep 17 00:00:00 2001 From: Khinenw Date: Sun, 14 Jul 2019 23:05:45 +0900 Subject: Fixed SMI to SRT UTF-16 Encoding bug --- CONTRIBUTORS.md | 1 + MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9168dccc8..c96228f31 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -27,6 +27,7 @@ - [pjeanjean](https://github.com/pjeanjean) - [DrPandemic](https://github.com/drpandemic) - [joern-h](https://github.com/joern-h) + - [Khinenw](https://github.com/HelloWorld017) # Emby Contributors diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 8677b363f..9ddfb9b01 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -425,7 +425,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrEmpty(encodingParam)) + // 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 ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) && (encodingParam == "UTF-16BE" || encodingParam == "UTF-16LE")) + { + encodingParam = ""; + } + else if (!string.IsNullOrEmpty(encodingParam)) { encodingParam = " -sub_charenc " + encodingParam; } -- cgit v1.2.3 From 003238ef5e5151c43738fedcc90f83fd5064580a Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Aug 2019 15:11:53 +0200 Subject: Update deps + document startup project * Fixed the release build * Documented all public/internal members of Jellyfin.Server * Enable TreatWarningsAsErrors for debug builds for Jellyfin.Server This will ensure that any new public/internal members of Jellyfin.Server are documented --- Emby.Naming/Emby.Naming.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 10 +++----- Jellyfin.Server/CoreAppHost.cs | 17 ++++++++++++++ Jellyfin.Server/Jellyfin.Server.csproj | 10 ++++---- Jellyfin.Server/Program.cs | 27 +++++++++++++++++----- Jellyfin.Server/StartupOptions.cs | 26 +++++++++++++++++++++ .../MediaBrowser.MediaEncoding.csproj | 2 +- 8 files changed, 74 insertions(+), 22 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 9e2a4950f..0b1ce2fce 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -23,7 +23,7 @@ - + diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index c9830abc5..8a79bf7e1 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -10,7 +10,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 73a64b0cd..c78d96d4a 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,7 +32,7 @@ - + @@ -48,17 +48,13 @@ - + latest - - true - - - + diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b9b0cc382..8b4b61e29 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -9,8 +9,21 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Server { + /// + /// Implementation of the abstract class. + /// public class CoreAppHost : ApplicationHost { + /// + /// Initializes a new instance of the class. + /// + /// The to be used by the . + /// The to be used by the . + /// The to be used by the . + /// The to be used by the . + /// The to be used by the . + /// The to be used by the . + /// The to be used by the . public CoreAppHost( ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, @@ -30,15 +43,19 @@ namespace Jellyfin.Server { } + /// public override bool CanSelfRestart => StartupOptions.RestartPath != null; + /// protected override void RestartInternal() => Program.Restart(); + /// protected override IEnumerable GetAssembliesWithPartsInternal() { yield return typeof(CoreAppHost).Assembly; } + /// protected override void ShutdownInternal() => Program.Shutdown(); } } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 641b3f182..e87283477 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -9,10 +9,8 @@ - + latest - - SA1600;SA1601;SA1629;CS1591 true @@ -26,7 +24,7 @@ - + @@ -36,7 +34,7 @@ - + @@ -45,7 +43,7 @@ - + diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 952990493..82b903198 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -28,6 +28,9 @@ using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Jellyfin.Server { + /// + /// Class containing the entry point of the application. + /// public static class Program { private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource(); @@ -35,6 +38,11 @@ namespace Jellyfin.Server private static ILogger _logger; private static bool _restartOnShutdown; + /// + /// The entry point of the application. + /// + /// The command line arguments passed. + /// . public static Task Main(string[] args) { // For backwards compatibility. @@ -53,7 +61,10 @@ namespace Jellyfin.Server .MapResult(StartApp, _ => Task.CompletedTask); } - public static void Shutdown() + /// + /// Shuts down the application. + /// + internal static void Shutdown() { if (!_tokenSource.IsCancellationRequested) { @@ -61,7 +72,10 @@ namespace Jellyfin.Server } } - public static void Restart() + /// + /// Restarts the application. + /// + internal static void Restart() { _restartOnShutdown = true; @@ -171,11 +185,12 @@ namespace Jellyfin.Server /// /// Create the data, config and log paths from the variety of inputs(command line args, /// environment variables) or decide on what default to use. For Windows it's %AppPath% - /// for everything else the XDG approach is followed: - /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + /// for everything else the + /// XDG approach + /// is followed. /// - /// StartupOptions - /// ServerApplicationPaths + /// The for this instance. + /// . private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options) { // dataDir diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 8296d414e..bb0adaf63 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -8,36 +8,62 @@ namespace Jellyfin.Server /// public class StartupOptions : IStartupOptions { + /// + /// Gets or sets the path to the data directory. + /// + /// The path to the data directory. [Option('d', "datadir", Required = false, HelpText = "Path to use for the data folder (database files, etc.).")] public string DataDir { get; set; } + /// + /// Gets or sets the path to the web directory. + /// + /// The path to the web directory. [Option('w', "webdir", Required = false, HelpText = "Path to the Jellyfin web UI resources.")] public string WebDir { get; set; } + /// + /// Gets or sets the path to the cache directory. + /// + /// The path to the cache directory. [Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")] public string CacheDir { get; set; } + /// + /// Gets or sets the path to the config directory. + /// + /// The path to the config directory. [Option('c', "configdir", Required = false, HelpText = "Path to use for configuration data (user settings and pictures).")] public string ConfigDir { get; set; } + /// + /// Gets or sets the path to the log directory. + /// + /// The path to the log directory. [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")] public string LogDir { get; set; } + /// [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")] public string FFmpegPath { get; set; } + /// [Option("service", Required = false, HelpText = "Run as headless service.")] public bool IsService { get; set; } + /// [Option("noautorunwebapp", Required = false, HelpText = "Run headless if startup wizard is complete.")] public bool NoAutoRunWebApp { get; set; } + /// [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")] public string PackageName { get; set; } + /// [Option("restartpath", Required = false, HelpText = "Path to restart script.")] public string RestartPath { get; set; } + /// [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")] public string RestartArgs { get; set; } } diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index c0f92ac4a..681a2e372 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,7 +18,7 @@ - + -- cgit v1.2.3 From 838e5d05d51c4c171c07d512f741304a6dc58f24 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 11 Aug 2019 16:52:37 +0200 Subject: Document all public/internal members of Emby.Drawing Forces all new public/internal members to be documented. Enables TreatWarningsAsErrors for Emby.Drawing --- BDInfo/BDInfo.csproj | 1 + DvdLib/DvdLib.csproj | 1 + Emby.Dlna/Emby.Dlna.csproj | 1 + Emby.Drawing/Emby.Drawing.csproj | 2 + Emby.Drawing/ImageProcessor.cs | 159 ++++++++------------- Emby.Drawing/NullImageEncoder.cs | 34 +++-- Emby.IsoMounting/IsoMounter/IsoMounter.csproj | 1 + Emby.Notifications/Emby.Notifications.csproj | 1 + Emby.Photos/Emby.Photos.csproj | 1 + Emby.Server.Implementations/ApplicationHost.cs | 21 +-- Emby.Server.Implementations/Dto/DtoService.cs | 2 +- Emby.XmlTv/Emby.XmlTv/Emby.XmlTv.csproj | 1 + Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 1 + MediaBrowser.Api/Images/ImageService.cs | 8 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 + MediaBrowser.Common/IApplicationHost.cs | 8 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 1 + MediaBrowser.Controller/Drawing/IImageEncoder.cs | 21 +-- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 30 ++-- .../Drawing/ImageProcessingOptions.cs | 5 +- .../MediaBrowser.Controller.csproj | 1 + .../MediaBrowser.LocalMetadata.csproj | 1 + .../MediaBrowser.MediaEncoding.csproj | 1 + MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + .../MediaBrowser.Providers.csproj | 1 + .../MediaBrowser.WebDashboard.csproj | 1 + .../MediaBrowser.XbmcMetadata.csproj | 1 + 27 files changed, 141 insertions(+), 166 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/BDInfo/BDInfo.csproj b/BDInfo/BDInfo.csproj index b2c752d0c..9dbaa9e2f 100644 --- a/BDInfo/BDInfo.csproj +++ b/BDInfo/BDInfo.csproj @@ -11,6 +11,7 @@ netstandard2.0 false + true diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index b2c752d0c..9dbaa9e2f 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -11,6 +11,7 @@ netstandard2.0 false + true diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 4c07087c5..34b49120b 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -14,6 +14,7 @@ netstandard2.0 false + true diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 9f97baf77..716de059d 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -3,6 +3,8 @@ netstandard2.0 false + true + true diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index a7d95eb20..ce8089e59 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -22,42 +22,47 @@ using Microsoft.Extensions.Logging; namespace Emby.Drawing { /// - /// Class ImageProcessor + /// Class ImageProcessor. /// public class ImageProcessor : IImageProcessor, IDisposable { - /// - /// The us culture - /// - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); + // Increment this when there's a change requiring caches to be invalidated + private const string Version = "3"; - /// - /// Gets the list of currently registered image processors - /// Image processors are specialized metadata providers that run after the normal ones - /// - /// The image enhancers. - public IImageEnhancer[] ImageEnhancers { get; private set; } + private static readonly HashSet _transparentImageTypes + = new HashSet(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" }; /// /// The _logger /// private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; private IImageEncoder _imageEncoder; private readonly Func _libraryManager; private readonly Func _mediaEncoder; + private readonly Dictionary _locks = new Dictionary(); + private bool _disposed = false; + + /// + /// + /// + /// + /// + /// + /// + /// + /// public ImageProcessor( - ILoggerFactory loggerFactory, + ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IImageEncoder imageEncoder, Func libraryManager, Func mediaEncoder) { - _logger = loggerFactory.CreateLogger(nameof(ImageProcessor)); + _logger = logger; _fileSystem = fileSystem; _imageEncoder = imageEncoder; _libraryManager = libraryManager; @@ -69,20 +74,11 @@ namespace Emby.Drawing ImageHelper.ImageProcessor = this; } - public IImageEncoder ImageEncoder - { - get => _imageEncoder; - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images"); - _imageEncoder = value; - } - } + private string EnhancedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "enhanced-images"); + /// public IReadOnlyCollection SupportedInputFormats => new HashSet(StringComparer.OrdinalIgnoreCase) { @@ -115,18 +111,20 @@ namespace Emby.Drawing "wbmp" }; + /// + public IReadOnlyCollection ImageEnhancers { get; set; } + /// public bool SupportsImageCollageCreation => _imageEncoder.SupportsImageCollageCreation; - private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images"); - - private string EnhancedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "enhanced-images"); - - public void AddParts(IEnumerable enhancers) + /// + public IImageEncoder ImageEncoder { - ImageEnhancers = enhancers.ToArray(); + get => _imageEncoder; + set => _imageEncoder = value ?? throw new ArgumentNullException(nameof(value)); } + /// public async Task ProcessImage(ImageProcessingOptions options, Stream toStream) { var file = await ProcessImage(options).ConfigureAwait(false); @@ -137,15 +135,15 @@ namespace Emby.Drawing } } + /// public IReadOnlyCollection GetSupportedImageOutputFormats() => _imageEncoder.SupportedOutputFormats; - private static readonly HashSet TransparentImageTypes - = new HashSet(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" }; - + /// public bool SupportsTransparency(string path) - => TransparentImageTypes.Contains(Path.GetExtension(path)); + => _transparentImageTypes.Contains(Path.GetExtension(path)); + /// public async Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options) { if (options == null) @@ -187,9 +185,9 @@ namespace Emby.Drawing } dateModified = supportedImageInfo.dateModified; - bool requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath)); + bool requiresTransparency = _transparentImageTypes.Contains(Path.GetExtension(originalImagePath)); - if (options.Enhancers.Length > 0) + if (options.Enhancers.Count > 0) { if (item == null) { @@ -279,7 +277,7 @@ namespace Emby.Drawing } } - private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency) + private ImageFormat GetOutputFormat(IReadOnlyCollection clientSupportedFormats, bool requiresTransparency) { var serverFormats = GetSupportedImageOutputFormats(); @@ -320,11 +318,6 @@ namespace Emby.Drawing } } - /// - /// Increment this when there's a change requiring caches to be invalidated - /// - private const string Version = "3"; - /// /// Gets the cache file path based on a set of parameters /// @@ -372,9 +365,11 @@ namespace Emby.Drawing return GetCachePath(ResizedImageCachePath, filename, "." + format.ToString().ToLowerInvariant()); } + /// public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info) => GetImageDimensions(item, info, true); + /// public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem) { int width = info.Width; @@ -400,26 +395,19 @@ namespace Emby.Drawing return size; } - /// - /// Gets the size of the image. - /// + /// public ImageDimensions GetImageDimensions(string path) => _imageEncoder.GetImageSize(path); - /// - /// Gets the image cache tag. - /// - /// The item. - /// The image. - /// Guid. - /// item + /// public string GetImageCacheTag(BaseItem item, ItemImageInfo image) { - var supportedEnhancers = GetSupportedEnhancers(item, image.Type); + var supportedEnhancers = GetSupportedEnhancers(item, image.Type).ToArray(); return GetImageCacheTag(item, image, supportedEnhancers); } + /// public string GetImageCacheTag(BaseItem item, ChapterInfo chapter) { try @@ -437,22 +425,15 @@ namespace Emby.Drawing } } - /// - /// Gets the image cache tag. - /// - /// The item. - /// The image. - /// The image enhancers. - /// Guid. - /// item - public string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers) + /// + public string GetImageCacheTag(BaseItem item, ItemImageInfo image, IReadOnlyCollection imageEnhancers) { string originalImagePath = image.Path; DateTime dateModified = image.DateModified; ImageType imageType = image.Type; // Optimization - if (imageEnhancers.Length == 0) + if (imageEnhancers.Count == 0) { return (originalImagePath + dateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture); } @@ -480,7 +461,7 @@ namespace Emby.Drawing { try { - string filename = (originalImagePath + dateModified.Ticks.ToString(UsCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture); + string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture); string cacheExtension = _mediaEncoder().SupportsEncoder("libwebp") ? ".webp" : ".png"; var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension); @@ -507,16 +488,10 @@ namespace Emby.Drawing return (originalImagePath, dateModified); } - /// - /// Gets the enhanced image. - /// - /// The item. - /// Type of the image. - /// Index of the image. - /// Task{System.String}. + /// public async Task GetEnhancedImage(BaseItem item, ImageType imageType, int imageIndex) { - var enhancers = GetSupportedEnhancers(item, imageType); + var enhancers = GetSupportedEnhancers(item, imageType).ToArray(); ItemImageInfo imageInfo = item.GetImageInfo(imageType, imageIndex); @@ -532,7 +507,7 @@ namespace Emby.Drawing bool inputImageSupportsTransparency, BaseItem item, int imageIndex, - IImageEnhancer[] enhancers, + IReadOnlyCollection enhancers, CancellationToken cancellationToken) { var originalImagePath = image.Path; @@ -573,6 +548,7 @@ namespace Emby.Drawing /// Index of the image. /// The supported enhancers. /// The cache unique identifier. + /// The cancellation token. /// Task<System.String>. /// /// originalImagePath @@ -584,9 +560,9 @@ namespace Emby.Drawing BaseItem item, ImageType imageType, int imageIndex, - IImageEnhancer[] supportedEnhancers, + IReadOnlyCollection supportedEnhancers, string cacheGuid, - CancellationToken cancellationToken) + CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(originalImagePath)) { @@ -680,6 +656,7 @@ namespace Emby.Drawing { throw new ArgumentNullException(nameof(path)); } + if (string.IsNullOrEmpty(uniqueName)) { throw new ArgumentNullException(nameof(uniqueName)); @@ -722,6 +699,7 @@ namespace Emby.Drawing return Path.Combine(path, prefix, filename); } + /// public void CreateImageCollage(ImageCollageOptions options) { _logger.LogInformation("Creating image collage and saving to {Path}", options.OutputPath); @@ -731,38 +709,25 @@ namespace Emby.Drawing _logger.LogInformation("Completed creation of image collage and saved to {Path}", options.OutputPath); } - public IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType) + /// + public IEnumerable GetSupportedEnhancers(BaseItem item, ImageType imageType) { - List list = null; - foreach (var i in ImageEnhancers) { - try - { - if (i.Supports(item, imageType)) - { - if (list == null) - { - list = new List(); - } - list.Add(i); - } - } - catch (Exception ex) + if (i.Supports(item, imageType)) { - _logger.LogError(ex, "Error in image enhancer: {0}", i.GetType().Name); + yield return i; } } - - return list == null ? Array.Empty() : list.ToArray(); } - private Dictionary _locks = new Dictionary(); + private class LockInfo { public SemaphoreSlim Lock = new SemaphoreSlim(1, 1); public int Count = 1; } + private LockInfo GetLock(string key) { lock (_locks) @@ -795,7 +760,7 @@ namespace Emby.Drawing } } - private bool _disposed; + /// public void Dispose() { _disposed = true; diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index fc4a5af9f..5af7f1622 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -5,36 +5,40 @@ using MediaBrowser.Model.Drawing; namespace Emby.Drawing { + /// + /// A fallback implementation of . + /// public class NullImageEncoder : IImageEncoder { + /// public IReadOnlyCollection SupportedInputFormats => new HashSet(StringComparer.OrdinalIgnoreCase) { "png", "jpeg", "jpg" }; + /// public IReadOnlyCollection SupportedOutputFormats => new HashSet() { ImageFormat.Jpg, ImageFormat.Png }; - public void CropWhiteSpace(string inputPath, string outputPath) - { - throw new NotImplementedException(); - } - - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) - { - throw new NotImplementedException(); - } - - public void CreateImageCollage(ImageCollageOptions options) - { - throw new NotImplementedException(); - } - + /// public string Name => "Null Image Encoder"; + /// public bool SupportsImageCollageCreation => false; + /// public bool SupportsImageEncoding => false; + /// public ImageDimensions GetImageSize(string path) + => throw new NotImplementedException(); + + /// + public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + { + throw new NotImplementedException(); + } + + /// + public void CreateImageCollage(ImageCollageOptions options) { throw new NotImplementedException(); } diff --git a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj b/Emby.IsoMounting/IsoMounter/IsoMounter.csproj index dafa51cd5..0778b987b 100644 --- a/Emby.IsoMounting/IsoMounter/IsoMounter.csproj +++ b/Emby.IsoMounting/IsoMounter/IsoMounter.csproj @@ -12,6 +12,7 @@ netstandard2.0 false + true diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 5c68e48c8..cbd3bde4f 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -3,6 +3,7 @@ netstandard2.0 false + true diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index c9830abc5..39b97a3bf 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -16,6 +16,7 @@ netstandard2.0 false + true diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 09847b2f8..b620f6be2 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -510,13 +510,8 @@ namespace Emby.Server.Implementations return AllConcreteTypes.Where(i => currentType.IsAssignableFrom(i)); } - /// - /// Gets the exports. - /// - /// The type - /// if set to true [manage lifetime]. - /// IEnumerable{``0}. - public IEnumerable GetExports(bool manageLifetime = true) + /// + public IReadOnlyCollection GetExports(bool manageLifetime = true) { var parts = GetExportTypes() .Select(CreateInstanceSafe) @@ -538,6 +533,7 @@ namespace Emby.Server.Implementations /// /// Runs the startup tasks. /// + /// . public async Task RunStartupTasksAsync() { Logger.LogInformation("Running startup tasks"); @@ -550,7 +546,7 @@ namespace Emby.Server.Implementations Logger.LogInformation("ServerId: {0}", SystemId); - var entryPoints = GetExports().ToList(); + var entryPoints = GetExports(); var stopWatch = new Stopwatch(); stopWatch.Start(); @@ -801,7 +797,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(HttpServer); - ImageProcessor = GetImageProcessor(); + ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); serviceCollection.AddSingleton(ImageProcessor); TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager); @@ -953,11 +949,6 @@ namespace Emby.Server.Implementations } } - private IImageProcessor GetImageProcessor() - { - return new ImageProcessor(LoggerFactory, ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder); - } - /// /// Gets the user repository. /// @@ -1087,7 +1078,7 @@ namespace Emby.Server.Implementations GetExports(), GetExports()); - ImageProcessor.AddParts(GetExports()); + ImageProcessor.ImageEnhancers = GetExports(); LiveTvManager.AddParts(GetExports(), GetExports(), GetExports()); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 6e7aa1313..1a7f10634 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1364,7 +1364,7 @@ namespace Emby.Server.Implementations.Dto return null; } - var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary); + var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToArray(); ImageDimensions size; diff --git a/Emby.XmlTv/Emby.XmlTv/Emby.XmlTv.csproj b/Emby.XmlTv/Emby.XmlTv/Emby.XmlTv.csproj index 0225be2c2..04f558173 100644 --- a/Emby.XmlTv/Emby.XmlTv/Emby.XmlTv.csproj +++ b/Emby.XmlTv/Emby.XmlTv/Emby.XmlTv.csproj @@ -3,6 +3,7 @@ netstandard2.0 false + true diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index f023bc55d..396bdd4b7 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -3,6 +3,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 23c7339d2..6d3037b24 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -550,14 +550,14 @@ namespace MediaBrowser.Api.Images } IImageEnhancer[] supportedImageEnhancers; - if (_imageProcessor.ImageEnhancers.Length > 0) + if (_imageProcessor.ImageEnhancers.Count > 0) { if (item == null) { item = _libraryManager.GetItemById(itemId); } - supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.GetSupportedEnhancers(item, request.Type) : Array.Empty(); + supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.GetSupportedEnhancers(item, request.Type).ToArray() : Array.Empty(); } else { @@ -606,8 +606,8 @@ namespace MediaBrowser.Api.Images ImageRequest request, ItemImageInfo image, bool cropwhitespace, - ImageFormat[] supportedFormats, - IImageEnhancer[] enhancers, + IReadOnlyCollection supportedFormats, + IReadOnlyCollection enhancers, TimeSpan? cacheDuration, IDictionary headers, bool isHeadRequest) diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index ba29c656b..f653270a6 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -12,6 +12,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index cb7343440..2248e9c85 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -75,10 +75,10 @@ namespace MediaBrowser.Common /// /// Gets the exports. /// - /// - /// if set to true [manage liftime]. - /// IEnumerable{``0}. - IEnumerable GetExports(bool manageLifetime = true); + /// The type. + /// If set to true [manage lifetime]. + /// . + IReadOnlyCollection GetExports(bool manageLifetime = true); /// /// Resolves this instance. diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 05b48a2a1..1b753aa29 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -23,6 +23,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index 4eaecd0a0..a0f9ae46e 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -17,16 +17,6 @@ namespace MediaBrowser.Controller.Drawing /// The supported output formats. IReadOnlyCollection SupportedOutputFormats { get; } - /// - /// Encodes the image. - /// - string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat); - - /// - /// Creates the image collage. - /// - /// The options. - void CreateImageCollage(ImageCollageOptions options); /// /// Gets the name. /// @@ -46,5 +36,16 @@ namespace MediaBrowser.Controller.Drawing bool SupportsImageEncoding { get; } ImageDimensions GetImageSize(string path); + + /// + /// Encodes the image. + /// + string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat); + + /// + /// Creates the image collage. + /// + /// The options. + void CreateImageCollage(ImageCollageOptions options); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index a11e2186f..a58a11bd1 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -24,7 +24,15 @@ namespace MediaBrowser.Controller.Drawing /// Gets the image enhancers. /// /// The image enhancers. - IImageEnhancer[] ImageEnhancers { get; } + IReadOnlyCollection ImageEnhancers { get; set; } + + /// + /// Gets a value indicating whether [supports image collage creation]. + /// + /// true if [supports image collage creation]; otherwise, false. + bool SupportsImageCollageCreation { get; } + + IImageEncoder ImageEncoder { get; set; } /// /// Gets the dimensions of the image. @@ -50,19 +58,13 @@ namespace MediaBrowser.Controller.Drawing /// ImageDimensions ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem); - /// - /// Adds the parts. - /// - /// The enhancers. - void AddParts(IEnumerable enhancers); - /// /// Gets the supported enhancers. /// /// The item. /// Type of the image. /// IEnumerable{IImageEnhancer}. - IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType); + IEnumerable GetSupportedEnhancers(BaseItem item, ImageType imageType); /// /// Gets the image cache tag. @@ -80,7 +82,7 @@ namespace MediaBrowser.Controller.Drawing /// The image. /// The image enhancers. /// Guid. - string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers); + string GetImageCacheTag(BaseItem item, ItemImageInfo image, IReadOnlyCollection imageEnhancers); /// /// Processes the image. @@ -109,7 +111,7 @@ namespace MediaBrowser.Controller.Drawing /// /// Gets the supported image output formats. /// - /// IReadOnlyCollection{ImageOutput}. + /// . IReadOnlyCollection GetSupportedImageOutputFormats(); /// @@ -118,14 +120,6 @@ namespace MediaBrowser.Controller.Drawing /// The options. void CreateImageCollage(ImageCollageOptions options); - /// - /// Gets a value indicating whether [supports image collage creation]. - /// - /// true if [supports image collage creation]; otherwise, false. - bool SupportsImageCollageCreation { get; } - - IImageEncoder ImageEncoder { get; set; } - bool SupportsTransparency(string path); } } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index db432f500..29addf6e6 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Controller.Entities; @@ -33,9 +34,9 @@ namespace MediaBrowser.Controller.Drawing public int Quality { get; set; } - public IImageEnhancer[] Enhancers { get; set; } + public IReadOnlyCollection Enhancers { get; set; } - public ImageFormat[] SupportedOutputFormats { get; set; } + public IReadOnlyCollection SupportedOutputFormats { get; set; } public bool AddPlayedIndicator { get; set; } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 01893f1b5..c6bca2518 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -19,6 +19,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 867b82ede..a8f8da9b8 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -12,6 +12,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index c0f92ac4a..05af9fd03 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -3,6 +3,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 3de2cca2d..e9f43ea56 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -10,6 +10,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 5941ed436..ab4759c61 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -21,6 +21,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index c099e77d6..883986894 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -18,6 +18,7 @@ netstandard2.0 false + true diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index ba29c656b..f653270a6 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -12,6 +12,7 @@ netstandard2.0 false + true -- cgit v1.2.3 From 1616f24cee15095b22092c63b5627662bf47befc Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 1 Sep 2019 18:39:23 +0200 Subject: Fix more warnings --- Emby.Photos/PhotoProvider.cs | 4 +- .../MediaEncoder/EncodingManager.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 775 ++++++++++++--------- .../MediaEncoding/MediaEncoderHelpers.cs | 17 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../MediaInfo/VideoImageProvider.cs | 2 +- MediaBrowser.XbmcMetadata/EntryPoint.cs | 16 +- MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs | 39 +- MediaBrowser.sln | 8 +- 9 files changed, 492 insertions(+), 373 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 99a635e60..1591609ab 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -170,8 +170,8 @@ namespace Emby.Photos } } - const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport; - return Task.FromResult(result); + const ItemUpdateType Result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport; + return Task.FromResult(Result); } } } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 52d07d784..840aca7a6 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.MediaEncoder var protocol = MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, Array.Empty()); + var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, null, Array.Empty()); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5665e72cf..963091673 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text; using System.Threading; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; @@ -22,8 +23,17 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; - // private readonly IApplicationPaths _appPaths; - // private readonly IAssemblyInfo _assemblyInfo; + + private static readonly string[] _videoProfiles = new[] + { + "ConstrainedBaseline", + "Baseline", + "Extended", + "Main", + "High", + "ProgressiveHigh", + "ConstrainedHigh" + }; public EncodingHelper(IMediaEncoder mediaEncoder, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder) { @@ -33,14 +43,10 @@ namespace MediaBrowser.Controller.MediaEncoding } public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) - { - return GetH264OrH265Encoder("libx264", "h264", state, encodingOptions); - } + => GetH264OrH265Encoder("libx264", "h264", state, encodingOptions); public string GetH265Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) - { - return GetH264OrH265Encoder("libx265", "hevc", state, encodingOptions); - } + => GetH264OrH265Encoder("libx265", "hevc", state, encodingOptions); private string GetH264OrH265Encoder(string defaultEncoder, string hwEncoder, EncodingJobInfo state, EncodingOptions encodingOptions) { @@ -64,19 +70,17 @@ namespace MediaBrowser.Controller.MediaEncoding }; if (!string.IsNullOrEmpty(hwType) - && encodingOptions.EnableHardwareEncoding && codecMap.ContainsKey(hwType)) + && encodingOptions.EnableHardwareEncoding + && codecMap.ContainsKey(hwType) + && CheckVaapi(state, hwType, encodingOptions)) { - if (CheckVaapi(state, hwType, encodingOptions)) - { - var preferredEncoder = codecMap[hwType]; + var preferredEncoder = codecMap[hwType]; - if (_mediaEncoder.SupportsEncoder(preferredEncoder)) - { - return preferredEncoder; - } + if (_mediaEncoder.SupportsEncoder(preferredEncoder)) + { + return preferredEncoder; } } - } // Avoid performing a second attempt when the first one @@ -106,15 +110,13 @@ namespace MediaBrowser.Controller.MediaEncoding { var videoStream = state.VideoStream; - if (videoStream != null) + // vaapi will throw an error with this input + // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99. + if (string.Equals(videoStream?.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase)) { - // vaapi will throw an error with this input - // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99. - if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase)) - { - return false; - } + return false; } + return true; } @@ -127,23 +129,27 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(codec)) { - if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || - string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) { return GetH265Encoder(state, encodingOptions); } + if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) { return GetH264Encoder(state, encodingOptions); } + if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) { return "libvpx"; } + if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) { return "wmv2"; } + if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) { return "libtheora"; @@ -162,9 +168,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// System.String. public string GetUserAgentParam(EncodingJobInfo state) { - string useragent = null; - - state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent); + state.RemoteHttpHeaders.TryGetValue("User-Agent", out string useragent); if (!string.IsNullOrEmpty(useragent)) { @@ -193,50 +197,62 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(container, "wmv", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "mts", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "vob", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "mpg", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "mpeg", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "rec", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "dvr-ms", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "ogm", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "divx", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "tp", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "rmvb", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(container, "rtp", StringComparison.OrdinalIgnoreCase)) { return null; @@ -264,10 +280,12 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(codec, "aac_latm", StringComparison.OrdinalIgnoreCase)) { return null; } + if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) { return null; @@ -292,30 +310,37 @@ namespace MediaBrowser.Controller.MediaEncoding { return "mp3"; } + if (string.Equals(ext, ".aac", StringComparison.OrdinalIgnoreCase)) { return "aac"; } + if (string.Equals(ext, ".wma", StringComparison.OrdinalIgnoreCase)) { return "wma"; } + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } + if (string.Equals(ext, ".oga", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } + if (string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } + if (string.Equals(ext, ".webma", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; @@ -337,14 +362,17 @@ namespace MediaBrowser.Controller.MediaEncoding { return "wmv"; } + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vpx"; } + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "theora"; } + if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase)) { return "h264"; @@ -355,19 +383,9 @@ namespace MediaBrowser.Controller.MediaEncoding public int GetVideoProfileScore(string profile) { - var list = new[] - { - "ConstrainedBaseline", - "Baseline", - "Extended", - "Main", - "High", - "ProgressiveHigh", - "ConstrainedHigh" - }; - // strip spaces because they may be stripped out on the query string - return Array.FindIndex(list, t => string.Equals(t, profile.Replace(" ", ""), StringComparison.OrdinalIgnoreCase)); + profile = profile.Replace(" ", ""); + return Array.FindIndex(_videoProfiles, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); } public string GetInputPathArgument(EncodingJobInfo state) @@ -375,14 +393,19 @@ namespace MediaBrowser.Controller.MediaEncoding var protocol = state.InputProtocol; var mediaPath = state.MediaPath ?? string.Empty; - var inputPath = new[] { mediaPath }; - - if (state.IsInputVideo) + string[] inputPath; + if (state.IsInputVideo + && !(state.VideoType == VideoType.Iso && state.IsoMount == null)) { - if (!(state.VideoType == VideoType.Iso && state.IsoMount == null)) - { - inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); - } + inputPath = MediaEncoderHelpers.GetInputArgument( + _fileSystem, + mediaPath, + state.IsoMount, + state.PlayableStreamFileNames); + } + else + { + inputPath = new[] { mediaPath }; } return _mediaEncoder.GetInputArgument(inputPath, protocol); @@ -401,18 +424,22 @@ namespace MediaBrowser.Controller.MediaEncoding { return "aac -strict experimental"; } + if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) { return "libmp3lame"; } + if (string.Equals(codec, "vorbis", StringComparison.OrdinalIgnoreCase)) { return "libvorbis"; } + if (string.Equals(codec, "wma", StringComparison.OrdinalIgnoreCase)) { return "wmav2"; } + if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) { return "libopus"; @@ -426,54 +453,59 @@ namespace MediaBrowser.Controller.MediaEncoding /// public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions) { - var request = state.BaseRequest; - - var arg = string.Format("-i {0}", GetInputPathArgument(state)); + var arg = new StringBuilder(); - if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + if (state.IsVideoRequest + && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) { - if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; + var hwOutputFormat = "vaapi"; + + if (hasGraphicalSubs) { - if (state.VideoStream != null && state.VideoStream.Width.HasValue) - { - // This is hacky but not sure how to get the exact subtitle resolution - int height = Convert.ToInt32((double)state.VideoStream.Width.Value / 16.0 * 9.0); + hwOutputFormat = "yuv420p"; + } - arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), height.ToString(CultureInfo.InvariantCulture)); - } + arg.Append("-hwaccel vaapi -hwaccel_output_format ") + .Append(hwOutputFormat) + .Append(" -vaapi_device ") + .Append(encodingOptions.VaapiDevice) + .Append(' '); + } - var subtitlePath = state.SubtitleStream.Path; + arg.Append("-i ") + .Append(GetInputPathArgument(state)); - if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase)) - { - var idxFile = Path.ChangeExtension(subtitlePath, ".idx"); - if (File.Exists(idxFile)) - { - subtitlePath = idxFile; - } - } + if (state.SubtitleStream != null + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode + && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) + { + if (state.VideoStream != null && state.VideoStream.Width.HasValue) + { + // This is hacky but not sure how to get the exact subtitle resolution + int height = Convert.ToInt32(state.VideoStream.Width.Value / 16.0 * 9.0); - arg += " -i \"" + subtitlePath + "\""; + arg.Append(" -canvas_size ") + .Append(state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture)) + .Append(':') + .Append(height.ToString(CultureInfo.InvariantCulture)); } - } - if (state.IsVideoRequest) - { - if (string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) - { - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; - var hwOutputFormat = "vaapi"; + var subtitlePath = state.SubtitleStream.Path; - if (hasGraphicalSubs) + if (string.Equals(Path.GetExtension(subtitlePath), ".sub", StringComparison.OrdinalIgnoreCase)) + { + var idxFile = Path.ChangeExtension(subtitlePath, ".idx"); + if (File.Exists(idxFile)) { - hwOutputFormat = "yuv420p"; + subtitlePath = idxFile; } - - arg = "-hwaccel vaapi -hwaccel_output_format " + hwOutputFormat + " -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; } + + arg.Append(" -i \"").Append(subtitlePath).Append('\"'); } - return arg.Trim(); + return arg.ToString(); } /// @@ -485,16 +517,16 @@ namespace MediaBrowser.Controller.MediaEncoding { var codec = stream.Codec ?? string.Empty; - return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 || - codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1; + return codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 + || codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1; } public bool IsH265(MediaStream stream) { var codec = stream.Codec ?? string.Empty; - return codec.IndexOf("265", StringComparison.OrdinalIgnoreCase) != -1 || - codec.IndexOf("hevc", StringComparison.OrdinalIgnoreCase) != -1; + return codec.IndexOf("265", StringComparison.OrdinalIgnoreCase) != -1 + || codec.IndexOf("hevc", StringComparison.OrdinalIgnoreCase) != -1; } public string GetBitStreamArgs(MediaStream stream) @@ -523,27 +555,38 @@ namespace MediaBrowser.Controller.MediaEncoding { // With vpx when crf is used, b:v becomes a max rate // https://trac.ffmpeg.org/wiki/vpxEncodingGuide. - return string.Format(" -maxrate:v {0} -bufsize:v {1} -b:v {0}", bitrate.Value.ToString(_usCulture), (bitrate.Value * 2).ToString(_usCulture)); + return string.Format( + CultureInfo.InvariantCulture, + " -maxrate:v {0} -bufsize:v {1} -b:v {0}", + bitrate.Value, + bitrate.Value * 2); } if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { - return string.Format(" -b:v {0}", bitrate.Value.ToString(_usCulture)); + return string.Format( + CultureInfo.InvariantCulture, + " -b:v {0}", + bitrate.Value); } if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) { // h264 - return string.Format(" -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(_usCulture), - (bitrate.Value * 2).ToString(_usCulture)); + return string.Format( + CultureInfo.InvariantCulture, + " -maxrate {0} -bufsize {1}", + bitrate.Value, + bitrate.Value * 2); } // h264 - return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(_usCulture), - (bitrate.Value * 2).ToString(_usCulture)); + return string.Format( + CultureInfo.InvariantCulture, + " -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value, + bitrate.Value * 2); } return string.Empty; @@ -576,7 +619,7 @@ namespace MediaBrowser.Controller.MediaEncoding // hls always copies timestamps var setPtsParam = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive ? string.Empty - : string.Format(",setpts=PTS -{0}/TB", seconds.ToString(_usCulture)); + : string.Format(CultureInfo.InvariantCulture, ",setpts=PTS -{0}/TB", seconds); // TODO // var fallbackFontPath = Path.Combine(_appPaths.ProgramDataPath, "fonts", "DroidSansFallback.ttf"); @@ -684,6 +727,7 @@ namespace MediaBrowser.Controller.MediaEncoding { encodeCrf = encodingOptions.H265Crf; } + if (encodeCrf >= 0 && encodeCrf <= 51) { param += " -crf " + encodeCrf.ToString(CultureInfo.InvariantCulture); @@ -695,12 +739,11 @@ namespace MediaBrowser.Controller.MediaEncoding { defaultCrf = "28"; } + param += " -crf " + defaultCrf; } } - - // h264 (h264_qsv) - else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) // h264 (h264_qsv) { string[] valid_h264_qsv = { "veryslow", "slower", "slow", "medium", "fast", "faster", "veryfast" }; @@ -716,10 +759,8 @@ namespace MediaBrowser.Controller.MediaEncoding param += " -look_ahead 0"; } - - // h264 (h264_nvenc) - else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc) + || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) { switch (encodingOptions.EncoderPreset) { @@ -750,9 +791,7 @@ namespace MediaBrowser.Controller.MediaEncoding break; } } - - // webm - else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // webm { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -778,18 +817,14 @@ namespace MediaBrowser.Controller.MediaEncoding qmin, qmax); } - else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; } - - // asf/wmv - else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) // asf/wmv { param += "-qmin 2"; } - else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd 2"; @@ -805,21 +840,21 @@ namespace MediaBrowser.Controller.MediaEncoding var targetVideoCodec = state.ActualOutputVideoCodec; - var request = state.BaseRequest; var profile = state.GetRequestedProfiles(targetVideoCodec).FirstOrDefault(); // vaapi does not support Baseline profile, force Constrained Baseline in this case, // which is compatible (and ugly) - if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && - profile != null && profile.ToLowerInvariant().Contains("baseline")) + if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + && profile != null + && profile.IndexOf("baseline", StringComparison.OrdinalIgnoreCase) != -1) { - profile = "constrained_baseline"; + profile = "constrained_baseline"; } if (!string.IsNullOrEmpty(profile)) { - if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) + && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + profile; @@ -834,9 +869,9 @@ namespace MediaBrowser.Controller.MediaEncoding // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 - if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { switch (level) { @@ -872,11 +907,11 @@ namespace MediaBrowser.Controller.MediaEncoding break; } } - // nvenc doesn't decode with param -level set ?! - else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) { - // todo param += ""; + // nvenc doesn't decode with param -level set ?! + // TODO: } else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { @@ -894,10 +929,10 @@ namespace MediaBrowser.Controller.MediaEncoding // todo } - if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) + && !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) + && !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -919,12 +954,10 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } - if (videoStream.IsInterlaced) + if (videoStream.IsInterlaced + && state.DeInterlace(videoStream.Codec, false)) { - if (state.DeInterlace(videoStream.Codec, false)) - { - return false; - } + return false; } if (videoStream.IsAnamorphic ?? false) @@ -936,24 +969,23 @@ namespace MediaBrowser.Controller.MediaEncoding } // Can't stream copy if we're burning in subtitles - if (request.SubtitleStreamIndex.HasValue) + if (request.SubtitleStreamIndex.HasValue + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { - if (state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) - { - return false; - } + return false; } - if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase) + && videoStream.IsAVC.HasValue + && !videoStream.IsAVC.Value + && request.RequireAvc) { - if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value && request.RequireAvc) - { - return false; - } + return false; } // Source and target codecs must match - if (string.IsNullOrEmpty(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(videoStream.Codec) + || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase)) { return false; } @@ -983,21 +1015,17 @@ namespace MediaBrowser.Controller.MediaEncoding } // Video width must fall within requested value - if (request.MaxWidth.HasValue) + if (request.MaxWidth.HasValue + && (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value)) { - if (!videoStream.Width.HasValue || videoStream.Width.Value > request.MaxWidth.Value) - { - return false; - } + return false; } // Video height must fall within requested value - if (request.MaxHeight.HasValue) + if (request.MaxHeight.HasValue + && (!videoStream.Height.HasValue || videoStream.Height.Value > request.MaxHeight.Value)) { - if (!videoStream.Height.HasValue || videoStream.Height.Value > request.MaxHeight.Value) - { - return false; - } + return false; } // Video framerate must fall within requested value @@ -1013,12 +1041,10 @@ namespace MediaBrowser.Controller.MediaEncoding } // Video bitrate must fall within requested value - if (request.VideoBitRate.HasValue) + if (request.VideoBitRate.HasValue + && (!videoStream.BitRate.HasValue || videoStream.BitRate.Value > request.VideoBitRate.Value)) { - if (!videoStream.BitRate.HasValue || videoStream.BitRate.Value > request.VideoBitRate.Value) - { - return false; - } + return false; } var maxBitDepth = state.GetRequestedVideoBitDepth(videoStream.Codec); @@ -1031,35 +1057,31 @@ namespace MediaBrowser.Controller.MediaEncoding } var maxRefFrames = state.GetRequestedMaxRefFrames(videoStream.Codec); - if (maxRefFrames.HasValue) + if (maxRefFrames.HasValue + && videoStream.RefFrames.HasValue && videoStream.RefFrames.Value > maxRefFrames.Value) { - if (videoStream.RefFrames.HasValue && videoStream.RefFrames.Value > maxRefFrames.Value) - { - return false; - } + return false; } // If a specific level was requested, the source must match or be less than var level = state.GetRequestedLevel(videoStream.Codec); - if (!string.IsNullOrEmpty(level)) + if (!string.IsNullOrEmpty(level) + && double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel)) { - if (double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel)) + if (!videoStream.Level.HasValue) { - if (!videoStream.Level.HasValue) - { - //return false; - } + //return false; + } - if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel) - { - return false; - } + if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel) + { + return false; } } - if (string.Equals(state.InputContainer, "avi", StringComparison.OrdinalIgnoreCase) && - string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) && - !(videoStream.IsAVC ?? false)) + if (string.Equals(state.InputContainer, "avi", StringComparison.OrdinalIgnoreCase) + && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) + && !(videoStream.IsAVC ?? false)) { // see Coach S01E01 - Kelly and the Professor(0).avi return false; @@ -1068,7 +1090,7 @@ namespace MediaBrowser.Controller.MediaEncoding return request.EnableAutoStreamCopy; } - public bool CanStreamCopyAudio(EncodingJobInfo state, MediaStream audioStream, string[] supportedAudioCodecs) + public bool CanStreamCopyAudio(EncodingJobInfo state, MediaStream audioStream, IEnumerable supportedAudioCodecs) { var request = state.BaseRequest; @@ -1078,16 +1100,16 @@ namespace MediaBrowser.Controller.MediaEncoding } var maxBitDepth = state.GetRequestedAudioBitDepth(audioStream.Codec); - if (maxBitDepth.HasValue) + if (maxBitDepth.HasValue + && audioStream.BitDepth.HasValue + && audioStream.BitDepth.Value > maxBitDepth.Value) { - if (audioStream.BitDepth.HasValue && audioStream.BitDepth.Value > maxBitDepth.Value) - { - return false; - } + return false; } // Source and target codecs must match - if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(audioStream.Codec) + || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase)) { return false; } @@ -1100,6 +1122,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return false; } + if (audioStream.Channels.Value > channels.Value) { return false; @@ -1113,6 +1136,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return false; } + if (audioStream.SampleRate.Value > request.AudioSampleRate.Value) { return false; @@ -1126,6 +1150,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return false; } + if (audioStream.BitRate.Value > request.AudioBitRate.Value) { return false; @@ -1141,17 +1166,17 @@ namespace MediaBrowser.Controller.MediaEncoding if (videoStream != null) { - var isUpscaling = request.Height.HasValue && videoStream.Height.HasValue && - request.Height.Value > videoStream.Height.Value && request.Width.HasValue && videoStream.Width.HasValue && - request.Width.Value > videoStream.Width.Value; + var isUpscaling = request.Height.HasValue + && videoStream.Height.HasValue + && request.Height.Value > videoStream.Height.Value + && request.Width.HasValue + && videoStream.Width.HasValue + && request.Width.Value > videoStream.Width.Value; // Don't allow bitrate increases unless upscaling - if (!isUpscaling) + if (!isUpscaling && bitrate.HasValue && videoStream.BitRate.HasValue) { - if (bitrate.HasValue && videoStream.BitRate.HasValue) - { - bitrate = GetMinBitrate(videoStream.BitRate.Value, bitrate.Value); - } + bitrate = GetMinBitrate(videoStream.BitRate.Value, bitrate.Value); } } @@ -1179,7 +1204,7 @@ namespace MediaBrowser.Controller.MediaEncoding } else if (sourceBitrate <= 3000000) { - sourceBitrate = Convert.ToInt32(sourceBitrate * 2); + sourceBitrate *= 2; } var bitrate = Math.Min(sourceBitrate, requestedBitrate); @@ -1189,12 +1214,13 @@ namespace MediaBrowser.Controller.MediaEncoding private static double GetVideoBitrateScaleFactor(string codec) { - if (StringHelper.EqualsIgnoreCase(codec, "h265") || - StringHelper.EqualsIgnoreCase(codec, "hevc") || - StringHelper.EqualsIgnoreCase(codec, "vp9")) + if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) { return .5; } + return 1; } @@ -1221,9 +1247,7 @@ namespace MediaBrowser.Controller.MediaEncoding scaleFactor = Math.Max(scaleFactor, 2); } - var newBitrate = scaleFactor * bitrate; - - return Convert.ToInt32(newBitrate); + return Convert.ToInt32(scaleFactor * bitrate); } public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream) @@ -1235,7 +1259,6 @@ namespace MediaBrowser.Controller.MediaEncoding // Don't encode any higher than this return Math.Min(384000, request.AudioBitRate.Value); - //return Math.Min(currentBitrate, request.AudioBitRate.Value); } return null; @@ -1248,12 +1271,14 @@ namespace MediaBrowser.Controller.MediaEncoding var filters = new List(); // Boost volume to 200% when downsampling from 6ch to 2ch - if (channels.HasValue && channels.Value <= 2) + if (channels.HasValue + && channels.Value <= 2 + && state.AudioStream != null + && state.AudioStream.Channels.HasValue + && state.AudioStream.Channels.Value > 5 + && !encodingOptions.DownMixAudioBoost.Equals(1)) { - if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5 && !encodingOptions.DownMixAudioBoost.Equals(1)) - { - filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture)); - } + filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture)); } var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive; @@ -1261,12 +1286,16 @@ namespace MediaBrowser.Controller.MediaEncoding { var seconds = TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds; - filters.Add(string.Format("asetpts=PTS-{0}/TB", Math.Round(seconds).ToString(_usCulture))); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "asetpts=PTS-{0}/TB", + Math.Round(seconds))); } if (filters.Count > 0) { - return "-af \"" + string.Join(",", filters.ToArray()) + "\""; + return "-af \"" + string.Join(",", filters) + "\""; } return string.Empty; @@ -1283,18 +1312,17 @@ namespace MediaBrowser.Controller.MediaEncoding { var request = state.BaseRequest; - var inputChannels = audioStream == null - ? null - : audioStream.Channels; + var inputChannels = audioStream?.Channels; if (inputChannels <= 0) { inputChannels = null; } - int? transcoderChannelLimit = null; var codec = outputAudioCodec ?? string.Empty; + + int? transcoderChannelLimit; if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1) { // wmav2 currently only supports two channel output @@ -1343,6 +1371,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return val2; } + if (!val2.HasValue) { return val1; @@ -1416,7 +1445,10 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream != null) { - args += string.Format("-map 0:{0}", state.VideoStream.Index); + args += string.Format( + CultureInfo.InvariantCulture, + "-map 0:{0}", + state.VideoStream.Index); } else { @@ -1426,7 +1458,10 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream != null) { - args += string.Format(" -map 0:{0}", state.AudioStream.Index); + args += string.Format( + CultureInfo.InvariantCulture, + " -map 0:{0}", + state.AudioStream.Index); } else @@ -1441,7 +1476,10 @@ namespace MediaBrowser.Controller.MediaEncoding } else if (subtitleMethod == SubtitleDeliveryMethod.Embed) { - args += string.Format(" -map 0:{0}", state.SubtitleStream.Index); + args += string.Format( + CultureInfo.InvariantCulture, + " -map 0:{0}", + state.SubtitleStream.Index); } else if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) { @@ -1493,7 +1531,10 @@ namespace MediaBrowser.Controller.MediaEncoding var request = state.BaseRequest; // Add resolution params, if specified - if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue) + if (request.Width.HasValue + || request.Height.HasValue + || request.MaxHeight.HasValue + || request.MaxWidth.HasValue) { outputSizeParam = GetOutputSizeParam(state, options, outputVideoCodec).TrimEnd('"'); @@ -1515,12 +1556,15 @@ namespace MediaBrowser.Controller.MediaEncoding } } - if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0) + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + && outputSizeParam.Length == 0) { outputSizeParam = ",format=nv12|vaapi,hwupload"; // Add parameters to use VAAPI with burn-in subttiles (GH issue #642) - if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { + if (state.SubtitleStream != null + && state.SubtitleStream.IsTextSubtitleStream + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { outputSizeParam += ",hwmap=mode=read+write+direct"; } } @@ -1529,7 +1573,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue) { - videoSizeParam = string.Format("scale={0}:{1}", state.VideoStream.Width.Value.ToString(_usCulture), state.VideoStream.Height.Value.ToString(_usCulture)); + videoSizeParam = string.Format( + CultureInfo.InvariantCulture, + "scale={0}:{1}", + state.VideoStream.Width.Value, + state.VideoStream.Height.Value); videoSizeParam += ":force_original_aspect_ratio=decrease"; } @@ -1542,15 +1590,18 @@ namespace MediaBrowser.Controller.MediaEncoding ? 0 : state.SubtitleStream.Index; - return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"", - mapPrefix.ToString(_usCulture), - subtitleStreamIndex.ToString(_usCulture), - state.VideoStream.Index.ToString(_usCulture), + return string.Format( + CultureInfo.InvariantCulture, + " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"", + mapPrefix, + subtitleStreamIndex, + state.VideoStream.Index, outputSizeParam, videoSizeParam); } - private ValueTuple GetFixedOutputSize(int? videoWidth, + private (int? width, int? height) GetFixedOutputSize( + int? videoWidth, int? videoHeight, int? requestedWidth, int? requestedHeight, @@ -1559,11 +1610,11 @@ namespace MediaBrowser.Controller.MediaEncoding { if (!videoWidth.HasValue && !requestedWidth.HasValue) { - return new ValueTuple(null, null); + return (null, null); } if (!videoHeight.HasValue && !requestedHeight.HasValue) { - return new ValueTuple(null, null); + return (null, null); } decimal inputWidth = Convert.ToDecimal(videoWidth ?? requestedWidth); @@ -1583,7 +1634,7 @@ namespace MediaBrowser.Controller.MediaEncoding outputWidth = 2 * Math.Truncate(outputWidth / 2); outputHeight = 2 * Math.Truncate(outputHeight / 2); - return new ValueTuple(Convert.ToInt32(outputWidth), Convert.ToInt32(outputHeight)); + return (Convert.ToInt32(outputWidth), Convert.ToInt32(outputHeight)); } public List GetScalingFilters(int? videoWidth, @@ -1597,9 +1648,17 @@ namespace MediaBrowser.Controller.MediaEncoding int? requestedMaxHeight) { var filters = new List(); - var fixedOutputSize = GetFixedOutputSize(videoWidth, videoHeight, requestedWidth, requestedHeight, requestedMaxWidth, requestedMaxHeight); - - if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue) + var (width, height) = GetFixedOutputSize( + videoWidth, + videoHeight, + requestedWidth, + requestedHeight, + requestedMaxWidth, + requestedMaxHeight); + + if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + && width.HasValue + && height.HasValue) { // Work around vaapi's reduced scaling features var scaler = "scale_vaapi"; @@ -1607,15 +1666,26 @@ namespace MediaBrowser.Controller.MediaEncoding // Given the input dimensions (inputWidth, inputHeight), determine the output dimensions // (outputWidth, outputHeight). The user may request precise output dimensions or maximum // output dimensions. Output dimensions are guaranteed to be even. - var outputWidth = fixedOutputSize.Item1.Value; - var outputHeight = fixedOutputSize.Item2.Value; + var outputWidth = width.Value; + var outputHeight = height.Value; - if (!videoWidth.HasValue || outputWidth != videoWidth.Value || !videoHeight.HasValue || outputHeight != videoHeight.Value) + if (!videoWidth.HasValue + || outputWidth != videoWidth.Value + || !videoHeight.HasValue + || outputHeight != videoHeight.Value) { - filters.Add(string.Format("{0}=w={1}:h={2}", scaler, outputWidth.ToString(_usCulture), outputHeight.ToString(_usCulture))); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "{0}=w={1}:h={2}", + scaler, + outputWidth, + outputHeight)); } } - else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue) + else if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 + && width.HasValue + && height.HasValue) { // Nothing to do, it's handled as an input resize filter } @@ -1631,7 +1701,12 @@ namespace MediaBrowser.Controller.MediaEncoding var widthParam = requestedWidth.Value.ToString(_usCulture); var heightParam = requestedHeight.Value.ToString(_usCulture); - filters.Add(string.Format("scale=trunc({0}/64)*64:trunc({1}/2)*2", widthParam, heightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc({0}/64)*64:trunc({1}/2)*2", + widthParam, + heightParam)); } else { @@ -1647,11 +1722,21 @@ namespace MediaBrowser.Controller.MediaEncoding if (isExynosV4L2) { - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/64)*64:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/64)*64:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", + maxWidthParam, + maxHeightParam)); } else { - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", + maxWidthParam, + maxHeightParam)); } } @@ -1667,7 +1752,11 @@ namespace MediaBrowser.Controller.MediaEncoding { var widthParam = requestedWidth.Value.ToString(_usCulture); - filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale={0}:trunc(ow/a/2)*2", + widthParam)); } } @@ -1678,11 +1767,19 @@ namespace MediaBrowser.Controller.MediaEncoding if (isExynosV4L2) { - filters.Add(string.Format("scale=trunc(oh*a/64)*64:{0}", heightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/64)*64:{0}", + heightParam)); } else { - filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/2)*2:{0}", + heightParam)); } } @@ -1693,11 +1790,19 @@ namespace MediaBrowser.Controller.MediaEncoding if (isExynosV4L2) { - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/64)*64:trunc(ow/dar/2)*2", maxWidthParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*dar)\\,{0})/64)*64:trunc(ow/dar/2)*2", + maxWidthParam)); } else { - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", + maxWidthParam)); } } @@ -1708,11 +1813,19 @@ namespace MediaBrowser.Controller.MediaEncoding if (isExynosV4L2) { - filters.Add(string.Format("scale=trunc(oh*a/64)*64:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/64)*64:min(max(iw/dar\\,ih)\\,{0})", + maxHeightParam)); } else { - filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam)); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", + maxHeightParam)); } } } @@ -1722,8 +1835,8 @@ namespace MediaBrowser.Controller.MediaEncoding private string GetFixedSizeScalingFilter(Video3DFormat? threedFormat, int requestedWidth, int requestedHeight) { - var widthParam = requestedWidth.ToString(_usCulture); - var heightParam = requestedHeight.ToString(_usCulture); + var widthParam = requestedWidth.ToString(CultureInfo.InvariantCulture); + var heightParam = requestedHeight.ToString(CultureInfo.InvariantCulture); string filter = null; @@ -1765,13 +1878,14 @@ namespace MediaBrowser.Controller.MediaEncoding } } - return string.Format(filter, widthParam, heightParam); + return string.Format(CultureInfo.InvariantCulture, filter, widthParam, heightParam); } /// /// If we're going to put a fixed size on the command line, this will calculate it /// - public string GetOutputSizeParam(EncodingJobInfo state, + public string GetOutputSizeParam( + EncodingJobInfo state, EncodingOptions options, string outputVideoCodec, bool allowTimeStampCopy = true) @@ -1790,8 +1904,9 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwdownload"); // If transcoding from 10 bit, transform colour spaces too - if ( !string.IsNullOrEmpty(videoStream.PixelFormat) && videoStream.PixelFormat.IndexOf( "p10", StringComparison.OrdinalIgnoreCase ) != -1 - && string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase ) ) + if (!string.IsNullOrEmpty(videoStream.PixelFormat) + && videoStream.PixelFormat.IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1 + && string.Equals(outputVideoCodec,"libx264", StringComparison.OrdinalIgnoreCase)) { filters.Add("format=p010le"); filters.Add("format=nv12"); @@ -1800,7 +1915,6 @@ namespace MediaBrowser.Controller.MediaEncoding { filters.Add("format=nv12"); } - } if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) @@ -1809,15 +1923,16 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload"); } - if (state.DeInterlace("h264", true) && string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (state.DeInterlace("h264", true) + && string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { - filters.Add(string.Format("deinterlace_vaapi")); + filters.Add(string.Format(CultureInfo.InvariantCulture, "deinterlace_vaapi")); } - if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true)) && - !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if ((state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true)) + && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { - var inputFramerate = videoStream == null ? null : videoStream.RealFrameRate; + var inputFramerate = videoStream?.RealFrameRate; // If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase) && (inputFramerate ?? 60) <= 30) @@ -1830,11 +1945,11 @@ namespace MediaBrowser.Controller.MediaEncoding } } - var inputWidth = videoStream == null ? null : videoStream.Width; - var inputHeight = videoStream == null ? null : videoStream.Height; + var inputWidth = videoStream?.Width; + var inputHeight = videoStream?.Height; var threeDFormat = state.MediaSource.Video3DFormat; - var videoDecoder = this.GetHardwareAcceleratedVideoDecoder(state, options); + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options); filters.AddRange(GetScalingFilters(inputWidth, inputHeight, threeDFormat, videoDecoder, outputVideoCodec, request.Width, request.Height, request.MaxWidth, request.MaxHeight)); @@ -1852,6 +1967,7 @@ namespace MediaBrowser.Controller.MediaEncoding { filters.Add("hwmap"); } + if (allowTimeStampCopy) { output += " -copyts"; @@ -1860,7 +1976,10 @@ namespace MediaBrowser.Controller.MediaEncoding if (filters.Count > 0) { - output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); + output += string.Format( + CultureInfo.InvariantCulture, + " -vf \"{0}\"", + string.Join(",", filters)); } return output; @@ -1908,7 +2027,8 @@ namespace MediaBrowser.Controller.MediaEncoding } } - if (state.AudioStream != null && CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs)) + if (state.AudioStream != null + && CanStreamCopyAudio(state, state.AudioStream, state.SupportedAudioCodecs)) { state.OutputAudioCodec = "copy"; } @@ -1925,14 +2045,10 @@ namespace MediaBrowser.Controller.MediaEncoding } public static string GetProbeSizeArgument(int numInputFiles) - { - return numInputFiles > 1 ? "-probesize 1G" : ""; - } + => numInputFiles > 1 ? "-probesize 1G" : ""; public static string GetAnalyzeDurationArgument(int numInputFiles) - { - return numInputFiles > 1 ? "-analyzeduration 200M" : ""; - } + => numInputFiles > 1 ? "-analyzeduration 200M" : ""; public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions) { @@ -2000,18 +2116,22 @@ namespace MediaBrowser.Controller.MediaEncoding { flags.Add("+igndts"); } + if (state.IgnoreInputIndex) { flags.Add("+ignidx"); } + if (state.GenPtsInput || string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { flags.Add("+genpts"); } + if (state.DiscardCorruptFramesInput) { flags.Add("+discardcorrupt"); } + if (state.EnableFastSeekInput) { flags.Add("+fastseek"); @@ -2019,24 +2139,33 @@ namespace MediaBrowser.Controller.MediaEncoding if (flags.Count > 0) { - inputModifier += " -fflags " + string.Join("", flags.ToArray()); + inputModifier += " -fflags " + string.Join(string.Empty, flags); } - var videoDecoder = this.GetHardwareAcceleratedVideoDecoder(state, encodingOptions); + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); if (!string.IsNullOrEmpty(videoDecoder)) { inputModifier += " " + videoDecoder; - var videoStream = state.VideoStream; - var inputWidth = videoStream == null ? null : videoStream.Width; - var inputHeight = videoStream == null ? null : videoStream.Height; - var request = state.BaseRequest; + if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1) + { + var videoStream = state.VideoStream; + var inputWidth = videoStream?.Width; + var inputHeight = videoStream?.Height; + var request = state.BaseRequest; - var fixedOutputSize = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); + var (width, height) = GetFixedOutputSize(inputWidth, inputHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); - if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 && fixedOutputSize.Item1.HasValue && fixedOutputSize.Item2.HasValue) - { - inputModifier += string.Format(" -resize {0}x{1}", fixedOutputSize.Item1.Value.ToString(_usCulture), fixedOutputSize.Item2.Value.ToString(_usCulture)); + if ((videoDecoder ?? string.Empty).IndexOf("_cuvid", StringComparison.OrdinalIgnoreCase) != -1 + && width.HasValue + && height.HasValue) + { + inputModifier += string.Format( + CultureInfo.InvariantCulture, + " -resize {0}x{1}", + width.Value, + height.Value); + } } } @@ -2045,9 +2174,9 @@ namespace MediaBrowser.Controller.MediaEncoding var outputVideoCodec = GetVideoEncoder(state, encodingOptions); // Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking - if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) && - state.TranscodingType != TranscodingJobType.Progressive && - state.EnableBreakOnNonKeyFrames(outputVideoCodec)) + if (!string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) + && state.TranscodingType != TranscodingJobType.Progressive + && state.EnableBreakOnNonKeyFrames(outputVideoCodec)) { inputModifier += " -noaccurate_seek"; } @@ -2071,14 +2200,16 @@ namespace MediaBrowser.Controller.MediaEncoding } - public void AttachMediaSourceInfo(EncodingJobInfo state, - MediaSourceInfo mediaSource, - string requestedUrl) + public void AttachMediaSourceInfo( + EncodingJobInfo state, + MediaSourceInfo mediaSource, + string requestedUrl) { if (state == null) { throw new ArgumentNullException(nameof(state)); } + if (mediaSource == null) { throw new ArgumentNullException(nameof(mediaSource)); @@ -2136,15 +2267,16 @@ namespace MediaBrowser.Controller.MediaEncoding state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; - if (state.ReadInputAtNativeFramerate || - mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase)) + if (state.ReadInputAtNativeFramerate + || mediaSource.Protocol == MediaProtocol.File + && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase)) { state.InputVideoSync = "-1"; state.InputAudioSync = "1"; } - if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase) || - string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase) + || string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase)) { // Seeing some stuttering when transcoding wma to audio-only HLS state.InputAudioSync = "1"; @@ -2256,7 +2388,7 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - return this.GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions); + return GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions); } public string GetHardwareAcceleratedVideoDecoder(VideoType videoType, MediaStream videoStream, EncodingOptions encodingOptions) @@ -2269,9 +2401,9 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - if (videoStream != null && - !string.IsNullOrEmpty(videoStream.Codec) && - !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType)) + if (videoStream != null + && !string.IsNullOrEmpty(videoStream.Codec) + && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType)) { if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { @@ -2469,11 +2601,7 @@ namespace MediaBrowser.Controller.MediaEncoding codec = format; } - var args = " -codec:s:0 " + codec; - - args += " -disposition:s:0 default"; - - return args; + return " -codec:s:0 " + codec + " -disposition:s:0 default"; } public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath, string defaultPreset) @@ -2484,8 +2612,8 @@ namespace MediaBrowser.Controller.MediaEncoding var format = string.Empty; var keyFrame = string.Empty; - if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) && - state.BaseRequest.Context == EncodingContext.Streaming) + if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) + && state.BaseRequest.Context == EncodingContext.Streaming) { // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js format = " -f mp4 -movflags frag_keyframe+empty_moov"; @@ -2495,7 +2623,9 @@ namespace MediaBrowser.Controller.MediaEncoding var inputModifier = GetInputModifier(state, encodingOptions); - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", inputModifier, GetInputArgument(state, encodingOptions), keyFrame, @@ -2505,8 +2635,7 @@ namespace MediaBrowser.Controller.MediaEncoding GetProgressiveVideoAudioArguments(state, encodingOptions), GetSubtitleEmbedArguments(state), format, - outputPath - ).Trim(); + outputPath).Trim(); } public string GetOutputFFlags(EncodingJobInfo state) @@ -2519,7 +2648,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (flags.Count > 0) { - return " -fflags " + string.Join("", flags.ToArray()); + return " -fflags " + string.Join("", flags); } return string.Empty; @@ -2536,9 +2665,9 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && - string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && - !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) + if (state.VideoStream != null + && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) + && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { string bitStreamArgs = GetBitStreamArgs(state.VideoStream); if (!string.IsNullOrEmpty(bitStreamArgs)) @@ -2559,8 +2688,10 @@ namespace MediaBrowser.Controller.MediaEncoding } else { - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - 5.ToString(_usCulture)); + var keyFrameArg = string.Format( + CultureInfo.InvariantCulture, + " -force_key_frames \"expr:gte(t,n_forced*{0})\"", + 5); args += keyFrameArg; @@ -2581,6 +2712,7 @@ namespace MediaBrowser.Controller.MediaEncoding { args += " -copyts"; } + args += " -avoid_negative_ts disabled -start_at_zero"; } @@ -2681,39 +2813,22 @@ namespace MediaBrowser.Controller.MediaEncoding } } - var albumCoverInput = string.Empty; - var mapArgs = string.Empty; - var metadata = string.Empty; - var vn = string.Empty; - - var hasArt = !string.IsNullOrEmpty(state.AlbumCoverPath); - hasArt = false; - - if (hasArt) - { - albumCoverInput = " -i \"" + state.AlbumCoverPath + "\""; - mapArgs = " -map 0:a -map 1:v -c:1:v copy"; - metadata = " -metadata:s:v title=\"Album cover\" -metadata:s:v comment=\"Cover(Front)\""; - } - else - { - vn = " -vn"; - } - var threads = GetNumberOfThreads(state, encodingOptions, null); var inputModifier = GetInputModifier(state, encodingOptions); - return string.Format("{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"", + return string.Format( + CultureInfo.InvariantCulture, + "{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"", inputModifier, GetInputArgument(state, encodingOptions), threads, - vn, - string.Join(" ", audioTranscodeParams.ToArray()), + " -vn", + string.Join(" ", audioTranscodeParams), outputPath, - metadata, - albumCoverInput, - mapArgs).Trim(); + string.Empty, + string.Empty, + string.Empty).Trim(); } } diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 7f842c1d0..5cedc3d57 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -1,8 +1,8 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Model.IO; -using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Controller.MediaEncoding { @@ -16,31 +16,26 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// The file system. /// The video path. - /// The protocol. /// The iso mount. /// The playable stream file names. - /// System.String[][]. - public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, MediaProtocol protocol, IIsoMount isoMount, string[] playableStreamFileNames) + /// string[]. + public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IIsoMount isoMount, IReadOnlyCollection playableStreamFileNames) { - if (playableStreamFileNames.Length > 0) + if (playableStreamFileNames.Count > 0) { if (isoMount == null) { return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames); } + return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames); } return new[] { videoPath }; } - private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, string[] filenames) + private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable filenames) { - if (filenames.Length == 0) - { - return new string[] { }; - } - var allFiles = fileSystem .GetFilePaths(rootPath, true) .ToArray(); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a8874b6d0..75bb960c3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters; - var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MediaSource.Protocol, request.MountedIso, request.PlayableStreamFileNames); + var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length); string analyzeDuration; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index d80084acf..e0b23108f 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.MediaInfo { var protocol = item.PathProtocol ?? MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, null, item.GetPlayableStreamFileNames(_mediaEncoder)); + var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, null, item.GetPlayableStreamFileNames(_mediaEncoder)); var mediaStreams = item.GetMediaStreams(); diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index 992991a7e..fe4d50efa 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -16,27 +16,30 @@ namespace MediaBrowser.XbmcMetadata { private readonly IUserDataManager _userDataManager; private readonly ILogger _logger; - private readonly ILibraryManager _libraryManager; private readonly IProviderManager _providerManager; private readonly IConfigurationManager _config; - public EntryPoint(IUserDataManager userDataManager, ILibraryManager libraryManager, ILogger logger, IProviderManager providerManager, IConfigurationManager config) + public EntryPoint( + IUserDataManager userDataManager, + ILogger logger, + IProviderManager providerManager, + IConfigurationManager config) { _userDataManager = userDataManager; - _libraryManager = libraryManager; _logger = logger; _providerManager = providerManager; _config = config; } + /// public Task RunAsync() { - _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; + _userDataManager.UserDataSaved += OnUserDataSaved; return Task.CompletedTask; } - void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) + private void OnUserDataSaved(object sender, UserDataSaveEventArgs e) { if (e.SaveReason == UserDataSaveReason.PlaybackFinished || e.SaveReason == UserDataSaveReason.TogglePlayed || e.SaveReason == UserDataSaveReason.UpdateUserRating) { @@ -47,9 +50,10 @@ namespace MediaBrowser.XbmcMetadata } } + /// public void Dispose() { - _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved; + _userDataManager.UserDataSaved -= OnUserDataSaved; } private void SaveMetadataForItem(BaseItem item, ItemUpdateType updateReason) diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs index 430b93199..a1905bf26 100644 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs @@ -15,16 +15,30 @@ namespace MediaBrowser.XbmcMetadata.Savers { public class AlbumNfoSaver : BaseNfoSaver { + public AlbumNfoSaver( + IFileSystem fileSystem, + IServerConfigurationManager configurationManager, + ILibraryManager libraryManager, + IUserManager userManager, + IUserDataManager userDataManager, + ILogger logger) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger) + { + } + + /// protected override string GetLocalSavePath(BaseItem item) { return Path.Combine(item.Path, "album.nfo"); } + /// protected override string GetRootElementName(BaseItem item) { return "album"; } + /// public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) { if (!item.SupportsLocalMetadata) @@ -35,6 +49,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return item is MusicAlbum && updateType >= MinimumUpdateType; } + /// protected override void WriteCustomElements(BaseItem item, XmlWriter writer) { var album = (MusicAlbum)item; @@ -52,8 +67,6 @@ namespace MediaBrowser.XbmcMetadata.Savers AddTracks(album.Tracks, writer); } - private readonly CultureInfo UsCulture = new CultureInfo("en-US"); - private void AddTracks(IEnumerable tracks, XmlWriter writer) { foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0)) @@ -62,7 +75,7 @@ namespace MediaBrowser.XbmcMetadata.Savers if (track.IndexNumber.HasValue) { - writer.WriteElementString("position", track.IndexNumber.Value.ToString(UsCulture)); + writer.WriteElementString("position", track.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (!string.IsNullOrEmpty(track.Name)) @@ -81,21 +94,19 @@ namespace MediaBrowser.XbmcMetadata.Savers } } + /// protected override List GetTagsUsed(BaseItem item) { var list = base.GetTagsUsed(item); - list.AddRange(new string[] - { - "track", - "artist", - "albumartist" - }); - return list; - } + list.AddRange( + new string[] + { + "track", + "artist", + "albumartist" + }); - public AlbumNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) - : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger) - { + return list; } } } diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 3ed86d65c..39839e273 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26730.3 @@ -41,8 +41,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}" @@ -141,10 +139,6 @@ Global {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.Build.0 = Debug|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.ActiveCfg = Release|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.Build.0 = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.Build.0 = Release|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.Build.0 = Debug|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.ActiveCfg = Release|Any CPU -- cgit v1.2.3 From 2919cf28ead3fc7b80dec789477eef4d2688616b Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 11 Sep 2019 19:31:35 +0200 Subject: Update deps (#1735) --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 4 ++-- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++-- Jellyfin.Server/Program.cs | 2 +- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index b48193c58..2c71f0457 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -21,7 +21,7 @@ - + @@ -33,7 +33,7 @@ - + diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 8c57ee453..35f0c84cb 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -37,13 +37,13 @@ - + - + diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 594441af0..716dd0fcd 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -22,7 +22,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; -using Serilog.AspNetCore; +using Serilog.Extensions.Logging; using SQLitePCL; using ILogger = Microsoft.Extensions.Logging.ILogger; diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index fdb20477f..264f31f3c 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -19,7 +19,7 @@ - + -- cgit v1.2.3 From c9820d30edf1cb8fa99a52ec72b6571d6d4506f7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 20 Sep 2019 12:42:08 +0200 Subject: Fix multiple mistakes and warnings --- BDInfo/BDROM.cs | 9 +---- Emby.Server.Implementations/Dto/DtoService.cs | 10 ++--- .../HttpServer/Security/AuthService.cs | 2 +- .../Library/CoreResolutionIgnoreRule.cs | 1 - Emby.Server.Implementations/Library/UserManager.cs | 4 +- .../Library/UserViewManager.cs | 4 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 3 -- .../LiveTv/Listings/SchedulesDirect.cs | 37 ++++++++---------- .../LiveTv/LiveTvManager.cs | 45 ++++++++++------------ .../TunerHosts/HdHomerun/HdHomerunManager.cs | 4 +- .../Services/StringMapTypeDeserializer.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- MediaBrowser.Api/UserLibrary/ItemsService.cs | 4 +- MediaBrowser.Common/Extensions/BaseExtensions.cs | 12 +++--- .../Extensions/CollectionExtensions.cs | 19 ++++++++- MediaBrowser.Controller/Entities/BaseItem.cs | 21 ++++++---- .../MediaEncoding/EncodingHelper.cs | 3 -- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 - .../Subtitles/SubtitleEncoder.cs | 8 ++-- .../Savers/EpisodeNfoSaver.cs | 2 +- RSSDP/SsdpDevicePublisher.cs | 4 -- 21 files changed, 94 insertions(+), 104 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs index 6759ed55a..3a0c14ffd 100644 --- a/BDInfo/BDROM.cs +++ b/BDInfo/BDROM.cs @@ -212,7 +212,6 @@ namespace BDInfo public void Scan() { - var errorStreamClipFiles = new List(); foreach (var streamClipFile in StreamClipFiles.Values) { try @@ -221,7 +220,6 @@ namespace BDInfo } catch (Exception ex) { - errorStreamClipFiles.Add(streamClipFile); if (StreamClipFileScanError != null) { if (StreamClipFileScanError(streamClipFile, ex)) @@ -250,7 +248,6 @@ namespace BDInfo StreamFiles.Values.CopyTo(streamFiles, 0); Array.Sort(streamFiles, CompareStreamFiles); - var errorPlaylistFiles = new List(); foreach (var playlistFile in PlaylistFiles.Values) { try @@ -259,7 +256,6 @@ namespace BDInfo } catch (Exception ex) { - errorPlaylistFiles.Add(playlistFile); if (PlaylistFileScanError != null) { if (PlaylistFileScanError(playlistFile, ex)) @@ -275,7 +271,6 @@ namespace BDInfo } } - var errorStreamFiles = new List(); foreach (var streamFile in streamFiles) { try @@ -296,7 +291,6 @@ namespace BDInfo } catch (Exception ex) { - errorStreamFiles.Add(streamFile); if (StreamFileScanError != null) { if (StreamFileScanError(streamFile, ex)) @@ -431,7 +425,7 @@ namespace BDInfo { return 1; } - else if ((x != null || x.FileInfo != null) && (y == null || y.FileInfo == null)) + else if ((x != null && x.FileInfo != null) && (y == null || y.FileInfo == null)) { return -1; } @@ -451,6 +445,5 @@ namespace BDInfo } } } - } } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 75192a8f1..a3201f0bc 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -218,14 +218,12 @@ namespace Emby.Server.Implementations.Dto AttachUserSpecificInfo(dto, item, user, options); } - if (item is IHasMediaSources hasMediaSources) + if (item is IHasMediaSources + && options.ContainsField(ItemFields.MediaSources)) { - if (options.ContainsField(ItemFields.MediaSources)) - { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(item, true, user).ToArray(); + dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(item, true, user).ToArray(); - NormalizeMediaSourceContainers(dto); - } + NormalizeMediaSourceContainers(dto); } if (options.ContainsField(ItemFields.Studios)) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 3d3f67ca2..93a61fe67 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.HttpServer.Security var user = auth.User; - if (user == null & !auth.UserId.Equals(Guid.Empty)) + if (user == null && auth.UserId != Guid.Empty) { throw new SecurityException("User with Id " + auth.UserId + " not found"); } diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index f1ae2fc9c..8bdb38784 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library } var filename = fileInfo.Name; - var path = fileInfo.FullName; // Ignore hidden files on UNIX if (Environment.OSVersion.Platform != PlatformID.Win32NT diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index ac6b4a209..52b2f56ff 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -273,14 +273,12 @@ namespace Emby.Server.Implementations.Library var user = Users.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase)); var success = false; - string updatedUsername = null; IAuthenticationProvider authenticationProvider = null; if (user != null) { var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false); authenticationProvider = authResult.authenticationProvider; - updatedUsername = authResult.username; success = authResult.success; } else @@ -288,7 +286,7 @@ namespace Emby.Server.Implementations.Library // user is null var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false); authenticationProvider = authResult.authenticationProvider; - updatedUsername = authResult.username; + string updatedUsername = authResult.username; success = authResult.success; if (success diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 4d79cae13..88e2a8fa6 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -236,7 +236,7 @@ namespace Emby.Server.Implementations.Library if (!parentId.Equals(Guid.Empty)) { var parentItem = _libraryManager.GetItemById(parentId); - if (parentItem is Channel parentItemChannel) + if (parentItem is Channel) { return _channelManager.GetLatestChannelItemsInternal( new InternalItemsQuery(user) @@ -248,7 +248,7 @@ namespace Emby.Server.Implementations.Library IncludeItemTypes = request.IncludeItemTypes, EnableTotalRecordCount = false }, - CancellationToken.None).Result.Items; + CancellationToken.None).GetAwaiter().GetResult().Items; } if (parentItem is Folder parent) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3cc0541e7..cc9c8e5d2 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -208,9 +208,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private static string GetAudioArgs(MediaSourceInfo mediaSource) { - var mediaStreams = mediaSource.MediaStreams ?? new List(); - var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty; - return "-codec:a:0 copy"; //var audioChannels = 2; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index f5dffc22a..9a4c91d0b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -17,7 +17,6 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; namespace Emby.Server.Implementations.LiveTv.Listings { @@ -41,6 +40,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings private string UserAgent => _appHost.ApplicationUserAgent; + /// + public string Name => "Schedules Direct"; + + /// + public string Type => nameof(SchedulesDirect); + private static List GetScheduleRequestDates(DateTime startDateUtc, DateTime endDateUtc) { var dates = new List(); @@ -103,7 +108,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings httpOptions.RequestHeaders["token"] = token; using (var response = await Post(httpOptions, true, info).ConfigureAwait(false)) - using (var reader = new StreamReader(response.Content)) { var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync>(response.Content).ConfigureAwait(false); _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); @@ -122,7 +126,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings httpOptions.RequestContent = "[\"" + string.Join("\", \"", programsID) + "\"]"; using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false)) - using (var innerReader = new StreamReader(innerResponse.Content)) { var programDetails = await _jsonSerializer.DeserializeFromStreamAsync>(innerResponse.Content).ConfigureAwait(false); var programDict = programDetails.ToDictionary(p => p.programID, y => y); @@ -152,14 +155,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)); var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)); - const double desiredAspect = 0.666666667; + const double DesiredAspect = 2.0 / 3; - programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, desiredAspect) ?? - GetProgramImage(ApiUrl, allImages, true, desiredAspect); + programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ?? + GetProgramImage(ApiUrl, allImages, true, DesiredAspect); - const double wideAspect = 1.77777778; + const double WideAspect = 16.0 / 9; - programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, wideAspect); + programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect); // Don't supply the same image twice if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal)) @@ -167,7 +170,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programEntry.thumbImage = null; } - programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, wideAspect); + programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); //programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? @@ -178,6 +181,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID])); } + return programsInfo; } } @@ -185,12 +189,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings private static int GetSizeOrder(ScheduleDirect.ImageData image) { - if (!string.IsNullOrWhiteSpace(image.height)) + if (!string.IsNullOrWhiteSpace(image.height) + && int.TryParse(image.height, out int value)) { - if (int.TryParse(image.height, out int value)) - { - return value; - } + return value; } return 0; @@ -736,16 +738,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings httpOptions.RequestHeaders["token"] = token; - using (var response = await _httpClient.SendAsync(httpOptions, "PUT")) + using (await _httpClient.SendAsync(httpOptions, "PUT")) { } } - public string Name => "Schedules Direct"; - - public static string TypeName = "SchedulesDirect"; - public string Type => TypeName; - private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(info.ListingsId)) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ee975e19a..89b92c999 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -60,16 +60,6 @@ namespace Emby.Server.Implementations.LiveTv private IListingsProvider[] _listingProviders = Array.Empty(); private readonly IFileSystem _fileSystem; - public event EventHandler> SeriesTimerCancelled; - public event EventHandler> TimerCancelled; - public event EventHandler> TimerCreated; - public event EventHandler> SeriesTimerCreated; - - public string GetEmbyTvActiveRecordingPath(string id) - { - return EmbyTV.EmbyTV.Current.GetActiveRecordingPath(id); - } - public LiveTvManager( IServerApplicationHost appHost, IServerConfigurationManager config, @@ -102,17 +92,34 @@ namespace Emby.Server.Implementations.LiveTv _tvDtoService = new LiveTvDtoService(dtoService, imageProcessor, loggerFactory, appHost, _libraryManager); } + public event EventHandler> SeriesTimerCancelled; + + public event EventHandler> TimerCancelled; + + public event EventHandler> TimerCreated; + + public event EventHandler> SeriesTimerCreated; + /// /// Gets the services. /// /// The services. public IReadOnlyList Services => _services; + public ITunerHost[] TunerHosts => _tunerHosts; + + public IListingsProvider[] ListingProviders => _listingProviders; + private LiveTvOptions GetConfiguration() { return _config.GetConfiguration("livetv"); } + public string GetEmbyTvActiveRecordingPath(string id) + { + return EmbyTV.EmbyTV.Current.GetActiveRecordingPath(id); + } + /// /// Adds the parts. /// @@ -130,13 +137,13 @@ namespace Emby.Server.Implementations.LiveTv { if (service is EmbyTV.EmbyTV embyTv) { - embyTv.TimerCreated += EmbyTv_TimerCreated; - embyTv.TimerCancelled += EmbyTv_TimerCancelled; + embyTv.TimerCreated += OnEmbyTvTimerCreated; + embyTv.TimerCancelled += OnEmbyTvTimerCancelled; } } } - private void EmbyTv_TimerCancelled(object sender, GenericEventArgs e) + private void OnEmbyTvTimerCancelled(object sender, GenericEventArgs e) { var timerId = e.Argument; @@ -149,10 +156,9 @@ namespace Emby.Server.Implementations.LiveTv }); } - private void EmbyTv_TimerCreated(object sender, GenericEventArgs e) + private void OnEmbyTvTimerCreated(object sender, GenericEventArgs e) { var timer = e.Argument; - var service = sender as ILiveTvService; TimerCreated?.Invoke(this, new GenericEventArgs { @@ -164,10 +170,6 @@ namespace Emby.Server.Implementations.LiveTv }); } - public ITunerHost[] TunerHosts => _tunerHosts; - - public IListingsProvider[] ListingProviders => _listingProviders; - public List GetTunerHostTypes() { return _tunerHosts.OrderBy(i => i.Name).Select(i => new NameIdPair @@ -966,9 +968,6 @@ namespace Emby.Server.Implementations.LiveTv private async Task AddRecordingInfo(IEnumerable> programs, CancellationToken cancellationToken) { - var timers = new Dictionary>(); - var seriesTimers = new Dictionary>(); - IReadOnlyList timerList = null; IReadOnlyList seriesTimerList = null; @@ -1601,8 +1600,6 @@ namespace Emby.Server.Implementations.LiveTv if (!string.IsNullOrEmpty(query.Id)) { - var guid = new Guid(query.Id); - timers = timers .Where(i => string.Equals(_tvDtoService.GetInternalTimerId(i.Item1.Id), query.Id, StringComparison.OrdinalIgnoreCase)); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 3699b988c..9702392b2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -424,14 +424,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return false; } - var nameTag = buf[offset++]; + offset++; // Name Tag var nameLength = buf[offset++]; // skip the name field to get to value for return offset += nameLength; - var valueTag = buf[offset++]; + offset++; // Value Tag var valueLength = buf[offset++]; diff --git a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs index c27eb7686..23e22afd5 100644 --- a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs +++ b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Services { PropertySetFn = propertySetFn; PropertyParseStringFn = propertyParseStringFn; - PropertyType = PropertyType; + PropertyType = propertyType; } public Action PropertySetFn { get; private set; } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 35f0c84cb..fa3e9cb35 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -22,7 +22,7 @@ - + diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index ada540ba6..b4a302648 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -455,9 +455,7 @@ namespace MediaBrowser.Api.UserLibrary IncludeItemTypes = new[] { typeof(MusicAlbum).Name }, Name = i, Limit = 1 - - }).Select(albumId => albumId); - + }); }).ToArray(); } diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index 40c16b957..33473c2be 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -14,20 +14,20 @@ namespace MediaBrowser.Common.Extensions /// Strips the HTML. /// /// The HTML string. - /// System.String. + /// . public static string StripHtml(this string htmlString) { // http://stackoverflow.com/questions/1349023/how-can-i-strip-html-from-text-in-net - const string pattern = @"<(.|\n)*?>"; + const string Pattern = @"<(.|\n)*?>"; - return Regex.Replace(htmlString, pattern, string.Empty).Trim(); + return Regex.Replace(htmlString, Pattern, string.Empty).Trim(); } /// - /// Gets the M d5. + /// Gets the Md5. /// - /// The STR. - /// Guid. + /// The string. + /// . public static Guid GetMD5(this string str) { using (var provider = MD5.Create()) diff --git a/MediaBrowser.Common/Extensions/CollectionExtensions.cs b/MediaBrowser.Common/Extensions/CollectionExtensions.cs index 3bc0295a0..75b9f59f8 100644 --- a/MediaBrowser.Common/Extensions/CollectionExtensions.cs +++ b/MediaBrowser.Common/Extensions/CollectionExtensions.cs @@ -5,13 +5,28 @@ namespace MediaBrowser.Common.Extensions // The MS CollectionExtensions are only available in netcoreapp public static class CollectionExtensions { - public static TValue GetValueOrDefault (this IReadOnlyDictionary dictionary, TKey key) + public static TValue GetValueOrDefault(this IReadOnlyDictionary dictionary, TKey key) { dictionary.TryGetValue(key, out var ret); return ret; } - // REVIEW: Inline? + /// + /// Copies all the elements of the current collection to the specified list + /// starting at the specified destination array index. The index is specified as a 32-bit integer. + /// + /// The current collection that is the source of the elements. + /// The list that is the destination of the elements copied from the current collection. + /// A 32-bit integer that represents the index in destination at which copying begins. + /// + public static void CopyTo(this IReadOnlyList source, IList destination, int index = 0) + { + for (int i = 0; i < source.Count; i++) + { + destination[index + i] = source[i]; + } + } + /// /// Copies all the elements of the current collection to the specified list /// starting at the specified destination array index. The index is specified as a 32-bit integer. diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 0e9f7ee44..369f63b13 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2045,7 +2045,7 @@ namespace MediaBrowser.Controller.Entities if (itemByPath == null) { - //Logger.LogWarning("Unable to find linked item at path {0}", info.Path); + Logger.LogWarning("Unable to find linked item at path {0}", info.Path); } return itemByPath; @@ -2057,7 +2057,7 @@ namespace MediaBrowser.Controller.Entities if (item == null) { - //Logger.LogWarning("Unable to find linked item at path {0}", info.Path); + Logger.LogWarning("Unable to find linked item at path {0}", info.Path); } return item; @@ -2085,14 +2085,17 @@ namespace MediaBrowser.Controller.Entities if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) { - if (current.Length == 0) + int curLen = current.Length; + if (curLen == 0) { Studios = new[] { name }; } else { - var list = - Studios = current.Concat(new[] { name }).ToArray(); + var newArr = new string[curLen + 1]; + current.CopyTo(newArr, 0); + newArr[curLen] = name; + Studios = newArr; } } } @@ -2231,8 +2234,12 @@ namespace MediaBrowser.Controller.Entities else { - var currentCount = ImageInfos.Length; - ImageInfos = ImageInfos.Concat(new[] { image }).ToArray(); + var current = ImageInfos; + var currentCount = current.Length; + var newArr = new ItemImageInfo[currentCount + 1]; + current.CopyTo(newArr, 0); + current[currentCount] = image; + ImageInfos = current; } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 841205d0c..eb3d2ab81 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1252,9 +1252,6 @@ namespace MediaBrowser.Controller.MediaEncoding { if (request.AudioBitRate.HasValue) { - // Make sure we don't request a bitrate higher than the source - var currentBitrate = audioStream == null ? request.AudioBitRate.Value : audioStream.BitRate ?? request.AudioBitRate.Value; - // Don't encode any higher than this return Math.Min(384000, request.AudioBitRate.Value); } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 19009e577..bd727bcdf 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -158,8 +158,6 @@ namespace MediaBrowser.LocalMetadata.Savers /// Task. public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) { - var writtenProviderIds = new HashSet(StringComparer.OrdinalIgnoreCase); - if (!string.IsNullOrEmpty(item.OfficialRating)) { writer.WriteElementString("ContentRating", item.OfficialRating); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 9ddfb9b01..d5fa76c3a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -506,12 +506,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (failed) { - var msg = string.Format("ffmpeg subtitle conversion failed for {Path}", inputPath); + _logger.LogError("ffmpeg subtitle conversion failed for {Path}", inputPath); - _logger.LogError(msg); - - throw new Exception(msg); + throw new Exception( + string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath)); } + await SetAssFont(outputPath).ConfigureAwait(false); _logger.LogInformation("ffmpeg subtitle conversion succeeded for {Path}", inputPath); diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs index aa28fded1..091c1957e 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.XbmcMetadata.Savers /// public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) - => !item.SupportsLocalMetadata && item is Episode && updateType >= MinimumUpdateType; + => item.SupportsLocalMetadata && item is Episode && updateType >= MinimumUpdateType; /// protected override void WriteCustomElements(BaseItem item, XmlWriter writer) diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 7f3e56394..53b740052 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -86,7 +86,6 @@ namespace Rssdp.Infrastructure ThrowIfDisposed(); - var minCacheTime = TimeSpan.Zero; bool wasAdded = false; lock (_Devices) { @@ -94,7 +93,6 @@ namespace Rssdp.Infrastructure { _Devices.Add(device); wasAdded = true; - minCacheTime = GetMinimumNonZeroCacheLifetime(); } } @@ -120,14 +118,12 @@ namespace Rssdp.Infrastructure if (device == null) throw new ArgumentNullException(nameof(device)); bool wasRemoved = false; - var minCacheTime = TimeSpan.Zero; lock (_Devices) { if (_Devices.Contains(device)) { _Devices.Remove(device); wasRemoved = true; - minCacheTime = GetMinimumNonZeroCacheLifetime(); } } -- cgit v1.2.3 From 1b01a6ece1c60ed5b767f825265de17f78a2770a Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 28 Sep 2019 01:29:54 +0200 Subject: Add tests for EncoderValidator * Add support for ffmpeg 4.2 * Parse the complete ffmpeg version instead of only the first 2 digits * Make max and min version optional * Remove max limitation (for now) * Style improvements --- .../Encoder/EncoderValidator.cs | 299 ++++++++++----------- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 21 +- .../Properties/AssemblyInfo.cs | 2 + MediaBrowser.sln | 7 + .../Jellyfin.Common.Tests.csproj | 4 +- .../EncoderValidatorTests.cs | 39 +++ .../EncoderValidatorTestsData.cs | 31 +++ .../Jellyfin.MediaEncoding.Tests.csproj | 19 ++ 8 files changed, 246 insertions(+), 176 deletions(-) create mode 100644 tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs create mode 100644 tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index b00350875..da0b7693e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,111 +1,154 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; +using System.Diagnostics; using System.Linq; +using System.Text; using System.Text.RegularExpressions; -using MediaBrowser.Model.Diagnostics; using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { public class EncoderValidator { - private readonly ILogger _logger; - private readonly IProcessFactory _processFactory; + private const string DefaultEncoderPath = "ffmpeg"; - public EncoderValidator(ILogger logger, IProcessFactory processFactory) + private static readonly string[] requiredDecoders = new[] { - _logger = logger; - _processFactory = processFactory; - } + "mpeg2video", + "h264_qsv", + "hevc_qsv", + "mpeg2_qsv", + "vc1_qsv", + "h264_cuvid", + "hevc_cuvid", + "dts", + "ac3", + "aac", + "mp3", + "h264", + "hevc" + }; - public (IEnumerable decoders, IEnumerable encoders) GetAvailableCoders(string encoderPath) + private static readonly string[] requiredEncoders = new[] + { + "libx264", + "libx265", + "mpeg4", + "msmpeg4", + "libvpx", + "libvpx-vp9", + "aac", + "libmp3lame", + "libopus", + "libvorbis", + "srt", + "h264_nvenc", + "hevc_nvenc", + "h264_qsv", + "hevc_qsv", + "h264_omx", + "hevc_omx", + "h264_vaapi", + "hevc_vaapi", + "h264_v4l2m2m", + "ac3" + }; + + // Try and use the individual library versions to determine a FFmpeg version + // This lookup table is to be maintained with the following command line: + // $ ffmpeg -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' + private static readonly IReadOnlyDictionary _ffmpegVersionMap = new Dictionary { - _logger.LogInformation("Validating media encoder at {EncoderPath}", encoderPath); + { "libavutil=56.31,libavcodec=58.54,libavformat=58.29,libavdevice=58.8,libavfilter=7.57,libswscale=5.5,libswresample=3.5,libpostproc=55.5,", new Version(4, 2) }, + { "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3,", new Version(4, 1) }, + { "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1,", new Version(4, 0) }, + { "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7,", new Version(3, 4) }, + { "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5,", new Version(3, 3) }, + { "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1,", new Version(3, 2) }, + { "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3,", new Version(2, 8) } + }; - var decoders = GetCodecs(encoderPath, Codec.Decoder); - var encoders = GetCodecs(encoderPath, Codec.Encoder); + private readonly ILogger _logger; - _logger.LogInformation("Encoder validation complete"); + private readonly string _encoderPath; - return (decoders, encoders); + public EncoderValidator(ILogger logger, string encoderPath = DefaultEncoderPath) + { + _logger = logger; + _encoderPath = encoderPath; } - public bool ValidateVersion(string encoderAppPath, bool logOutput) + public static Version MinVersion { get; } = new Version(4, 0); + + public static Version MaxVersion { get; } = null; + + public bool ValidateVersion() { string output = null; try { - output = GetProcessOutput(encoderAppPath, "-version"); + output = GetProcessOutput(_encoderPath, "-version"); } catch (Exception ex) { - if (logOutput) - { - _logger.LogError(ex, "Error validating encoder"); - } + _logger.LogError(ex, "Error validating encoder"); } if (string.IsNullOrWhiteSpace(output)) { - if (logOutput) - { - _logger.LogError("FFmpeg validation: The process returned no result"); - } + _logger.LogError("FFmpeg validation: The process returned no result"); return false; } _logger.LogDebug("ffmpeg output: {Output}", output); - if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1) + return ValidateVersionInternal(output); + } + + internal bool ValidateVersionInternal(string versionOutput) + { + if (versionOutput.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1) { - if (logOutput) - { - _logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported"); - } + _logger.LogError("FFmpeg validation: avconv instead of ffmpeg is not supported"); return false; } - // The min and max FFmpeg versions required to run jellyfin successfully - var minRequired = new Version(4, 0); - var maxRequired = new Version(4, 0); - // Work out what the version under test is - var underTest = GetFFmpegVersion(output); + var version = GetFFmpegVersion(versionOutput); - if (logOutput) - { - _logger.LogInformation("FFmpeg validation: Found ffmpeg version {0}", underTest != null ? underTest.ToString() : "unknown"); + _logger.LogInformation("Found ffmpeg version {0}", version != null ? version.ToString() : "unknown"); - if (underTest == null) // Version is unknown - { - if (minRequired.Equals(maxRequired)) - { - _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", minRequired.ToString()); - } - else - { - _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", minRequired.ToString(), maxRequired.ToString()); - } - } - else if (underTest.CompareTo(minRequired) < 0) // Version is below what we recommend - { - _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", minRequired.ToString()); - } - else if (underTest.CompareTo(maxRequired) > 0) // Version is above what we recommend + if (version == null && MinVersion != null && MaxVersion != null) // Version is unknown + { + if (MinVersion == MaxVersion) { - _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", maxRequired.ToString()); + _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", MinVersion); } - else // Version is ok + else { - _logger.LogInformation("FFmpeg validation: Found suitable ffmpeg version"); + _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", MinVersion, MaxVersion); } + + return false; + } + else if (MinVersion != null && version < MinVersion) // Version is below what we recommend + { + _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", MinVersion); + return false; + } + else if (MaxVersion != null && version > MaxVersion) // Version is above what we recommend + { + _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", MaxVersion); + return false; } - // underTest shall be null if versions is unknown - return (underTest == null) ? false : (underTest.CompareTo(minRequired) >= 0 && underTest.CompareTo(maxRequired) <= 0); + return true; } + public IEnumerable GetDecoders() => GetCodecs(Codec.Decoder); + + public IEnumerable GetEncoders() => GetCodecs(Codec.Encoder); + /// /// Using the output from "ffmpeg -version" work out the FFmpeg version. /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy @@ -115,10 +158,10 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - static private Version GetFFmpegVersion(string output) + internal static Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output - var match = Regex.Match(output, @"ffmpeg version (\d+\.\d+)"); + var match = Regex.Match(output, @"ffmpeg version ((?:\d+\.?)+)"); if (match.Success) { @@ -126,25 +169,11 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - // Try and use the individual library versions to determine a FFmpeg version - // This lookup table is to be maintained with the following command line: - // $ ./ffmpeg.exe -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' - var lut = new ReadOnlyDictionary - (new Dictionary - { - { new Version("4.1"), "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3," }, - { new Version("4.0"), "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1," }, - { new Version("3.4"), "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7," }, - { new Version("3.3"), "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5," }, - { new Version("3.2"), "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1," }, - { new Version("2.8"), "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3," } - }); - // Create a reduced version string and lookup key from dictionary - var reducedVersion = GetVersionString(output); + var reducedVersion = GetLibrariesVersionString(output); // Try to lookup the string and return Key, otherwise if not found returns null - return lut.FirstOrDefault(x => x.Value == reducedVersion).Key; + return _ffmpegVersionMap.TryGetValue(reducedVersion, out Version version) ? version : null; } } @@ -154,76 +183,38 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - static private string GetVersionString(string output) + private static string GetLibrariesVersionString(string output) { - string pattern = @"((?lib\w+)\s+(?\d+)\.\s*(?\d+))"; - RegexOptions options = RegexOptions.Multiline; - - string rc = null; - - foreach (Match m in Regex.Matches(output, pattern, options)) + var rc = new StringBuilder(144); + foreach (Match m in Regex.Matches( + output, + @"((?lib\w+)\s+(?\d+)\.\s*(?\d+))", + RegexOptions.Multiline)) { - rc += string.Concat(m.Groups["name"], '=', m.Groups["major"], '.', m.Groups["minor"], ','); + rc.Append(m.Groups["name"]) + .Append('=') + .Append(m.Groups["major"]) + .Append('.') + .Append(m.Groups["minor"]) + .Append(','); } - return rc; + return rc.Length == 0 ? null : rc.ToString(); } - private static readonly string[] requiredDecoders = new[] - { - "mpeg2video", - "h264_qsv", - "hevc_qsv", - "mpeg2_qsv", - "vc1_qsv", - "h264_cuvid", - "hevc_cuvid", - "dts", - "ac3", - "aac", - "mp3", - "h264", - "hevc" - }; - - private static readonly string[] requiredEncoders = new[] - { - "libx264", - "libx265", - "mpeg4", - "msmpeg4", - "libvpx", - "libvpx-vp9", - "aac", - "libmp3lame", - "libopus", - "libvorbis", - "srt", - "h264_nvenc", - "hevc_nvenc", - "h264_qsv", - "hevc_qsv", - "h264_omx", - "hevc_omx", - "h264_vaapi", - "hevc_vaapi", - "h264_v4l2m2m", - "ac3" - }; - private enum Codec { Encoder, Decoder } - private IEnumerable GetCodecs(string encoderAppPath, Codec codec) + private IEnumerable GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; string output = null; try { - output = GetProcessOutput(encoderAppPath, "-" + codecstr); + output = GetProcessOutput(_encoderPath, "-" + codecstr); } catch (Exception ex) { @@ -250,45 +241,25 @@ namespace MediaBrowser.MediaEncoding.Encoder private string GetProcessOutput(string path, string arguments) { - IProcess process = _processFactory.Create(new ProcessOptions + using (var process = new Process() { - CreateNoWindow = true, - UseShellExecute = false, - FileName = path, - Arguments = arguments, - IsHidden = true, - ErrorDialog = false, - RedirectStandardOutput = true, - // ffmpeg uses stderr to log info, don't show this - RedirectStandardError = true - }); - - _logger.LogDebug("Running {Path} {Arguments}", path, arguments); - - using (process) + StartInfo = new ProcessStartInfo(path, arguments) + { + CreateNoWindow = true, + UseShellExecute = false, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + RedirectStandardOutput = true, + // ffmpeg uses stderr to log info, don't show this + RedirectStandardError = true + } + }) { + _logger.LogDebug("Running {Path} {Arguments}", path, arguments); + process.Start(); - try - { - return process.StandardOutput.ReadToEnd(); - } - catch - { - _logger.LogWarning("Killing process {Path} {Arguments}", path, arguments); - - // Hate having to do this - try - { - process.Kill(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error killing process"); - } - - throw; - } + return process.StandardOutput.ReadToEnd(); } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 75bb960c3..04ff66991 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -114,13 +114,13 @@ namespace MediaBrowser.MediaEncoding.Encoder FFprobePath = Regex.Replace(FFmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); // Interrogate to understand what coders are supported - var result = new EncoderValidator(_logger, _processFactory).GetAvailableCoders(FFmpegPath); + var validator = new EncoderValidator(_logger, FFmpegPath); - SetAvailableDecoders(result.decoders); - SetAvailableEncoders(result.encoders); + SetAvailableDecoders(validator.GetDecoders()); + SetAvailableEncoders(validator.GetEncoders()); } - _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation.ToString(), FFmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, FFmpegPath ?? string.Empty); } /// @@ -183,11 +183,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (File.Exists(path)) { - rc = new EncoderValidator(_logger, _processFactory).ValidateVersion(path, true); + rc = new EncoderValidator(_logger, path).ValidateVersion(); if (!rc) { - _logger.LogWarning("FFmpeg: {0}: Failed version check: {1}", location.ToString(), path); + _logger.LogWarning("FFmpeg: {0}: Failed version check: {1}", location, path); } // ToDo - Enable the ffmpeg validator. At the moment any version can be used. @@ -198,7 +198,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - _logger.LogWarning("FFmpeg: {0}: File not found: {1}", location.ToString(), path); + _logger.LogWarning("FFmpeg: {0}: File not found: {1}", location, path); } } @@ -228,9 +228,9 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - private string ExistsOnSystemPath(string filename) + private string ExistsOnSystemPath(string fileName) { - string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, filename); + string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, fileName); if (!string.IsNullOrEmpty(inJellyfinPath)) { return inJellyfinPath; @@ -239,13 +239,14 @@ namespace MediaBrowser.MediaEncoding.Encoder foreach (var path in values.Split(Path.PathSeparator)) { - var candidatePath = GetEncoderPathFromDirectory(path, filename); + var candidatePath = GetEncoderPathFromDirectory(path, fileName); if (!string.IsNullOrEmpty(candidatePath)) { return candidatePath; } } + return null; } diff --git a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs index a9491374b..7b74cfc89 100644 --- a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs +++ b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -14,6 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] +[assembly: InternalsVisibleTo("Jellyfin.MediaEncoding.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/MediaBrowser.sln b/MediaBrowser.sln index d23ca1cdb..dd4e9f8a6 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -57,6 +57,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FBBB5129 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Common.Tests", "tests\Jellyfin.Common.Tests\Jellyfin.Common.Tests.csproj", "{DF194677-DFD3-42AF-9F75-D44D5A416478}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MediaEncoding.Tests", "tests\Jellyfin.MediaEncoding.Tests\Jellyfin.MediaEncoding.Tests.csproj", "{28464062-0939-4AA7-9F7B-24DDDA61A7C0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -159,6 +161,10 @@ Global {DF194677-DFD3-42AF-9F75-D44D5A416478}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF194677-DFD3-42AF-9F75-D44D5A416478}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF194677-DFD3-42AF-9F75-D44D5A416478}.Release|Any CPU.Build.0 = Release|Any CPU + {28464062-0939-4AA7-9F7B-24DDDA61A7C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28464062-0939-4AA7-9F7B-24DDDA61A7C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28464062-0939-4AA7-9F7B-24DDDA61A7C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28464062-0939-4AA7-9F7B-24DDDA61A7C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -186,5 +192,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {DF194677-DFD3-42AF-9F75-D44D5A416478} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {28464062-0939-4AA7-9F7B-24DDDA61A7C0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection EndGlobal diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 449aaa1a5..242d99381 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -2,14 +2,14 @@ netcoreapp2.2 - false - + + diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs new file mode 100644 index 000000000..9fa1e4f7e --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using MediaBrowser.MediaEncoding.Encoder; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Jellyfin.MediaEncoding.Tests +{ + public class EncoderValidatorTests + { + private class GetFFmpegVersionTestData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; + yield return new object[] { EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4) }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + [Theory] + [ClassData(typeof(GetFFmpegVersionTestData))] + public void GetFFmpegVersionTest(string versionOutput, Version version) + { + Assert.Equal(version, EncoderValidator.GetFFmpegVersion(versionOutput)); + } + + [Theory] + [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] + [InlineData(EncoderValidatorTestsData.FFmpegV404Output, true)] + public void ValidateVersionInternalTest(string versionOutput, bool valid) + { + var val = new EncoderValidator(new NullLogger()); + Assert.Equal(valid, val.ValidateVersionInternal(versionOutput)); + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs new file mode 100644 index 000000000..d2a2e4358 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs @@ -0,0 +1,31 @@ +namespace Jellyfin.MediaEncoding.Tests +{ + internal static class EncoderValidatorTestsData + { + public const string FFmpegV42Output = @"ffmpeg version n4.2 Copyright (c) 2000-2019 the FFmpeg developers +built with gcc 9.1.0 (GCC) +configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-omx --enable-shared --enable-version3 +libavutil 56. 31.100 / 56. 31.100 +libavcodec 58. 54.100 / 58. 54.100 +libavformat 58. 29.100 / 58. 29.100 +libavdevice 58. 8.100 / 58. 8.100 +libavfilter 7. 57.100 / 7. 57.100 +libswscale 5. 5.100 / 5. 5.100 +libswresample 3. 5.100 / 3. 5.100 +libpostproc 55. 5.100 / 55. 5.100 +"; + + public const string FFmpegV404Output = @"ffmpeg version 4.0.4 Copyright (c) 2000-2019 the FFmpeg developers +built with gcc 8 (Debian 8.3.0-6) +configuration: --toolchain=hardened --prefix=/usr --target-os=linux --enable-cross-compile --extra-cflags=--static --enable-gpl --enable-static --disable-doc --disable-ffplay --disable-shared --disable-libxcb --disable-sdl2 --disable-xlib --enable-libfontconfig --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libwebp --enable-libx264 --enable-libx265 --enable-libzvbi --enable-omx --enable-omx-rpi --enable-version3 --enable-vaapi --enable-vdpau --arch=amd64 --enable-nvenc --enable-nvdec +libavutil 56. 14.100 / 56. 14.100 +libavcodec 58. 18.100 / 58. 18.100 +libavformat 58. 12.100 / 58. 12.100 +libavdevice 58. 3.100 / 58. 3.100 +libavfilter 7. 16.100 / 7. 16.100 +libswscale 5. 1.100 / 5. 1.100 +libswresample 3. 1.100 / 3. 1.100 +libpostproc 55. 1.100 / 55. 1.100 +"; + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj new file mode 100644 index 000000000..beb03d563 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.2 + false + + + + + + + + + + + + + + -- cgit v1.2.3 From 3e1aab6b29621db741ecfb469189322c907b673f Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 29 Sep 2019 13:41:24 +0200 Subject: Fix ffmpeg version check for unknown versions --- .../Encoder/EncoderValidator.cs | 19 +++++++------ .../EncoderValidatorTests.cs | 4 +++ .../EncoderValidatorTestsData.cs | 32 ++++++++++++++++++---- 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index da0b7693e..3620abfee 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -118,15 +118,18 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogInformation("Found ffmpeg version {0}", version != null ? version.ToString() : "unknown"); - if (version == null && MinVersion != null && MaxVersion != null) // Version is unknown + if (version == null) { - if (MinVersion == MaxVersion) + if (MinVersion != null && MaxVersion != null) // Version is unknown { - _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", MinVersion); - } - else - { - _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", MinVersion, MaxVersion); + if (MinVersion == MaxVersion) + { + _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", MinVersion); + } + else + { + _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", MinVersion, MaxVersion); + } } return false; @@ -161,7 +164,7 @@ namespace MediaBrowser.MediaEncoding.Encoder internal static Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output - var match = Regex.Match(output, @"ffmpeg version ((?:\d+\.?)+)"); + var match = Regex.Match(output, @"^ffmpeg version n?((?:\d+\.?)+)"); if (match.Success) { diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index 5a759bcb2..a7848316e 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -13,9 +13,11 @@ namespace Jellyfin.MediaEncoding.Tests { public IEnumerator GetEnumerator() { + yield return new object[] { EncoderValidatorTestsData.FFmpegV421Output, new Version(4, 2, 1) }; yield return new object[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; yield return new object[] { EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4) }; yield return new object[] { EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4) }; + yield return new object[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, null }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); @@ -29,9 +31,11 @@ namespace Jellyfin.MediaEncoding.Tests } [Theory] + [InlineData(EncoderValidatorTestsData.FFmpegV421Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV414Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV404Output, true)] + [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)] public void ValidateVersionInternalTest(string versionOutput, bool valid) { var val = new EncoderValidator(new NullLogger()); diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs index 1d444e2b3..12fde0770 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs @@ -2,6 +2,18 @@ namespace Jellyfin.MediaEncoding.Tests { internal static class EncoderValidatorTestsData { + public const string FFmpegV421Output = @"ffmpeg version 4.2.1 Copyright (c) 2000-2019 the FFmpeg developers +built with gcc 9.1.1 (GCC) 20190807 +configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt +libavutil 56. 31.100 / 56. 31.100 +libavcodec 58. 54.100 / 58. 54.100 +libavformat 58. 29.100 / 58. 29.100 +libavdevice 58. 8.100 / 58. 8.100 +libavfilter 7. 57.100 / 7. 57.100 +libswscale 5. 5.100 / 5. 5.100 +libswresample 3. 5.100 / 3. 5.100 +libpostproc 55. 5.100 / 55. 5.100"; + public const string FFmpegV42Output = @"ffmpeg version n4.2 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.1.0 (GCC) configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-omx --enable-shared --enable-version3 @@ -12,8 +24,7 @@ libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 -libpostproc 55. 5.100 / 55. 5.100 -"; +libpostproc 55. 5.100 / 55. 5.100"; public const string FFmpegV414Output = @"ffmpeg version 4.1.4-1~deb10u1 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 8 (Raspbian 8.3.0-6+rpi1) @@ -26,8 +37,7 @@ libavfilter 7. 40.101 / 7. 40.101 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 3.100 / 5. 3.100 libswresample 3. 3.100 / 3. 3.100 -libpostproc 55. 3.100 / 55. 3.100 -"; +libpostproc 55. 3.100 / 55. 3.100"; public const string FFmpegV404Output = @"ffmpeg version 4.0.4 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 8 (Debian 8.3.0-6) @@ -39,8 +49,18 @@ libavdevice 58. 3.100 / 58. 3.100 libavfilter 7. 16.100 / 7. 16.100 libswscale 5. 1.100 / 5. 1.100 libswresample 3. 1.100 / 3. 1.100 -libpostproc 55. 1.100 / 55. 1.100 -"; +libpostproc 55. 1.100 / 55. 1.100"; + public const string FFmpegGitUnknownOutput = @"ffmpeg version N-94303-g7cb4f8c962 Copyright (c) 2000-2019 the FFmpeg developers +built with gcc 9.1.1 (GCC) 20190716 +configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt +libavutil 56. 30.100 / 56. 30.100 +libavcodec 58. 53.101 / 58. 53.101 +libavformat 58. 28.102 / 58. 28.102 +libavdevice 58. 7.100 / 58. 7.100 +libavfilter 7. 56.101 / 7. 56.101 +libswscale 5. 4.101 / 5. 4.101 +libswresample 3. 4.100 / 3. 4.100 +libpostproc 55. 4.100 / 55. 4.100"; } } -- cgit v1.2.3 From 321e5cba60825d5791730da75cd12905e97b527e Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 3 Oct 2019 11:51:28 -0400 Subject: Add new MediaAttachment to store attachments found during media probing. --- .../Probing/ProbeResultNormalizer.cs | 38 +++++++++++++++++++ MediaBrowser.Model/Dto/MediaSourceInfo.cs | 2 + MediaBrowser.Model/Entities/MediaAttachment.cs | 44 ++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 MediaBrowser.Model/Entities/MediaAttachment.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 54d02fc9f..2c001d775 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -49,6 +49,10 @@ namespace MediaBrowser.MediaEncoding.Probing .Where(i => i.Type != MediaStreamType.Subtitle || !string.IsNullOrWhiteSpace(i.Codec)) .ToList(); + info.MediaAttachments = internalStreams.Select(s => GetMediaAttachment(s)) + .Where(i => i != null) + .ToList(); + if (data.format != null) { info.Container = NormalizeFormat(data.format.format_name); @@ -513,6 +517,40 @@ namespace MediaBrowser.MediaEncoding.Probing return codec; } + /// + /// Converts ffprobe stream info to our MediaAttachment class + /// + /// The stream info. + /// MediaAttachments. + private MediaAttachment GetMediaAttachment(MediaStreamInfo streamInfo) + { + if (!string.Equals(streamInfo.codec_type, "attachment", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + var attachment = new MediaAttachment + { + Codec = streamInfo.codec_name, + Index = streamInfo.index + }; + + // Filter out junk + if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + { + attachment.CodecTag = streamInfo.codec_tag_string; + } + + if (streamInfo.tags != null) + { + attachment.Filename = GetDictionaryValue(streamInfo.tags, "filename"); + attachment.MIMEType = GetDictionaryValue(streamInfo.tags, "mimetype"); + attachment.Comment = GetDictionaryValue(streamInfo.tags, "comment"); + } + + return attachment; + } + /// /// Converts ffprobe stream info to our MediaStream class /// diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 5bdc4809a..8a1aa55b6 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -57,6 +57,8 @@ namespace MediaBrowser.Model.Dto public List MediaStreams { get; set; } + public List MediaAttachments { get; set; } + public string[] Formats { get; set; } public int? Bitrate { get; set; } diff --git a/MediaBrowser.Model/Entities/MediaAttachment.cs b/MediaBrowser.Model/Entities/MediaAttachment.cs new file mode 100644 index 000000000..daabbe91d --- /dev/null +++ b/MediaBrowser.Model/Entities/MediaAttachment.cs @@ -0,0 +1,44 @@ +namespace MediaBrowser.Model.Entities +{ + /// + /// Class MediaAttachment + /// + public class MediaAttachment + { + /// + /// Gets or sets the codec. + /// + /// The codec. + public string Codec { get; set; } + + /// + /// Gets or sets the codec tag. + /// + /// The codec tag. + public string CodecTag { get; set; } + + /// + /// Gets or sets the comment. + /// + /// The comment. + public string Comment { get; set; } + + /// + /// Gets or sets the index. + /// + /// The index. + public int Index { get; set; } + + /// + /// Gets or sets the filename. + /// + /// The filename. + public string Filename { get; set; } + + /// + /// Gets or sets the MIME type. + /// + /// The MIME type. + public string MIMEType { get; set; } + } +} -- cgit v1.2.3 From 12f752d8b1bbc9d6d480bfc34283dd15a08d1f8a Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Fri, 18 Oct 2019 07:52:32 -0400 Subject: FFMPEG extractor for attachments. --- .../MediaEncoding/IAttachmentExtractor.cs | 17 ++ .../Attachments/AttachmentExtractor.cs | 277 +++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs create mode 100644 MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs new file mode 100644 index 000000000..59c0a3f21 --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs @@ -0,0 +1,17 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.MediaEncoding +{ + public interface IAttachmentExtractor + { + Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, + string mediaSourceId, + int attachmentStreamIndex, + CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs new file mode 100644 index 000000000..d6106df29 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Concurrent; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Diagnostics; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Serialization; +using Microsoft.Extensions.Logging; +using UtfUnknown; + +namespace MediaBrowser.MediaEncoding.Attachments +{ + public class AttachmentExtractor : IAttachmentExtractor + { + private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; + private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly IMediaEncoder _mediaEncoder; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly IProcessFactory _processFactory; + + public AttachmentExtractor( + ILibraryManager libraryManager, + ILoggerFactory loggerFactory, + IApplicationPaths appPaths, + IFileSystem fileSystem, + IMediaEncoder mediaEncoder, + IMediaSourceManager mediaSourceManager, + IProcessFactory processFactory) + { + _libraryManager = libraryManager; + _logger = loggerFactory.CreateLogger(nameof(AttachmentExtractor)); + _appPaths = appPaths; + _fileSystem = fileSystem; + _mediaEncoder = mediaEncoder; + _mediaSourceManager = mediaSourceManager; + _processFactory = processFactory; + } + + private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments"); + + public async Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) + { + if (item == null) + { + throw new ArgumentNullException(nameof(item)); + } + if (string.IsNullOrWhiteSpace(mediaSourceId)) + { + throw new ArgumentNullException(nameof(mediaSourceId)); + } + + var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); + var mediaSource = mediaSources + .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); + var mediaAttachment = mediaSource.MediaAttachments + .First(i => i.Index == attachmentStreamIndex); + var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken) + .ConfigureAwait(false); + + return (mediaAttachment, attachmentStream); + } + + private async Task GetAttachmentStream( + MediaSourceInfo mediaSource, + MediaAttachment mediaAttachment, + CancellationToken cancellationToken) + { + var inputFiles = new[] {mediaSource.Path}; + var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); + var stream = await GetAttachmentStream(fileInfo.Path, fileInfo.Protocol, cancellationToken).ConfigureAwait(false); + return stream; + } + + private async Task GetAttachmentStream( + string path, + MediaProtocol protocol, + CancellationToken cancellationToken) + { + return File.OpenRead(path); + } + + private async Task GetReadableFile( + string mediaPath, + string[] inputFiles, + MediaProtocol protocol, + MediaAttachment mediaAttachment, + CancellationToken cancellationToken) + { + var outputPath = GetAttachmentCachePath(mediaPath, protocol, mediaAttachment.Index); + await ExtractAttachment(inputFiles, protocol, mediaAttachment.Index, outputPath, cancellationToken) + .ConfigureAwait(false); + + return new AttachmentInfo(outputPath, MediaProtocol.File); + } + + private struct AttachmentInfo + { + public AttachmentInfo(string path, MediaProtocol protocol) + { + Path = path; + Protocol = protocol; + } + public string Path { get; set; } + public MediaProtocol Protocol { get; set; } + } + + private readonly ConcurrentDictionary _semaphoreLocks = + new ConcurrentDictionary(); + + private SemaphoreSlim GetLock(string filename) + { + return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1)); + } + + private async Task ExtractAttachment( + string[] inputFiles, + MediaProtocol protocol, + int attachmentStreamIndex, + string outputPath, + CancellationToken cancellationToken) + { + var semaphore = GetLock(outputPath); + + await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + if (!File.Exists(outputPath)) + { + await ExtractAttachmentInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), attachmentStreamIndex, outputPath, cancellationToken).ConfigureAwait(false); + } + } + finally + { + semaphore.Release(); + } + } + + private async Task ExtractAttachmentInternal( + string inputPath, + int attachmentStreamIndex, + string outputPath, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(inputPath)) + { + throw new ArgumentNullException(nameof(inputPath)); + } + + if (string.IsNullOrEmpty(outputPath)) + { + throw new ArgumentNullException(nameof(outputPath)); + } + + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + + var processArgs = string.Format("-dump_attachment:{1} {2} -i {0} -t 0 -f null null", inputPath, attachmentStreamIndex, outputPath); + var process = _processFactory.Create(new ProcessOptions + { + CreateNoWindow = true, + UseShellExecute = false, + EnableRaisingEvents = true, + FileName = _mediaEncoder.EncoderPath, + Arguments = processArgs, + IsHidden = true, + ErrorDialog = false + }); + + _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); + + try + { + process.Start(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error starting ffmpeg"); + + throw; + } + + var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); + + if (!ranToCompletion) + { + try + { + _logger.LogWarning("Killing ffmpeg attachment extraction process"); + process.Kill(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error killing attachment extraction process"); + } + + } + + var exitCode = ranToCompletion ? process.ExitCode : -1; + + process.Dispose(); + + var failed = false; + + if (exitCode == -1) + { + failed = true; + + try + { + _logger.LogWarning("Deleting extracted attachment due to failure: {Path}", outputPath); + _fileSystem.DeleteFile(outputPath); + } + catch (FileNotFoundException) + { + + } + catch (IOException ex) + { + _logger.LogError(ex, "Error deleting extracted attachment {Path}", outputPath); + } + + } + else if (!File.Exists(outputPath)) + { + failed = true; + } + + if (failed) + { + var msg = $"ffmpeg attachment extraction failed for {inputPath} to {outputPath}"; + + _logger.LogError(msg); + + throw new Exception(msg); + } + else + { + var msg = $"ffmpeg attachment extraction completed for {inputPath} to {outputPath}"; + + _logger.LogInformation(msg); + } + } + + private string GetAttachmentCachePath(string mediaPath, MediaProtocol protocol, int attachmentStreamIndex) + { + if (protocol == MediaProtocol.File) + { + var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); + var filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); + var prefix = filename.Substring(0, 1); + return Path.Combine(AttachmentCachePath, prefix, filename); + } + else + { + var filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); + var prefix = filename.Substring(0, 1); + return Path.Combine(AttachmentCachePath, prefix, filename); + } + } + + } +} -- cgit v1.2.3 From a245f5a0d463e132bcbb3c5871465bdb8bbec0b7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 19 Oct 2019 00:22:08 +0200 Subject: Rewrite hex encoder/decoder --- .gitignore | 3 ++ Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Drawing/Emby.Drawing.csproj | 7 +-- Emby.Notifications/Emby.Notifications.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Library/DefaultAuthenticationProvider.cs | 4 +- Emby.Server.Implementations/Library/UserManager.cs | 4 +- .../LiveTv/LiveTvManager.cs | 6 ++- .../Updates/InstallationManager.cs | 4 +- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 2 +- MediaBrowser.Api/LiveTv/LiveTvService.cs | 7 +-- MediaBrowser.Api/MediaBrowser.Api.csproj | 2 +- MediaBrowser.Common/Cryptography/PasswordHash.cs | 11 ++--- .../Extensions/CollectionExtensions.cs | 48 ------------------ MediaBrowser.Common/Extensions/CopyToExtensions.cs | 26 ++++++++++ MediaBrowser.Common/Hex.cs | 57 ++++++++++++++++++++++ MediaBrowser.Common/HexHelper.cs | 24 --------- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- .../MediaBrowser.Controller.csproj | 2 +- .../MediaBrowser.LocalMetadata.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- .../MediaBrowser.Providers.csproj | 4 +- .../MediaBrowser.WebDashboard.csproj | 2 +- .../MediaBrowser.XbmcMetadata.csproj | 2 +- Mono.Nat/Mono.Nat.csproj | 2 +- RSSDP/RSSDP.csproj | 2 +- .../Jellyfin.Common.Benches/HexDecodeBenches.cs | 42 ++++++++++++++++ .../Jellyfin.Common.Benches/HexEncodeBenches.cs | 29 +++++++++++ .../Jellyfin.Common.Benches.csproj | 16 ++++++ benches/Jellyfin.Common.Benches/Program.cs | 14 ++++++ tests/Jellyfin.Common.Tests/HexTests.cs | 19 ++++++++ tests/Jellyfin.Common.Tests/PasswordHashTests.cs | 6 +-- 32 files changed, 243 insertions(+), 114 deletions(-) delete mode 100644 MediaBrowser.Common/Extensions/CollectionExtensions.cs create mode 100644 MediaBrowser.Common/Extensions/CopyToExtensions.cs create mode 100644 MediaBrowser.Common/Hex.cs delete mode 100644 MediaBrowser.Common/HexHelper.cs create mode 100644 benches/Jellyfin.Common.Benches/HexDecodeBenches.cs create mode 100644 benches/Jellyfin.Common.Benches/HexEncodeBenches.cs create mode 100644 benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj create mode 100644 benches/Jellyfin.Common.Benches/Program.cs create mode 100644 tests/Jellyfin.Common.Tests/HexTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/.gitignore b/.gitignore index 34cf1a84c..42243f01a 100644 --- a/.gitignore +++ b/.gitignore @@ -268,3 +268,6 @@ doc/ # Deployment artifacts dist *.exe + +# BenchmarkDotNet artifacts +BenchmarkDotNet.Artifacts diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 34b49120b..8d6fabdb4 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -12,7 +12,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 2e539f2c7..85cecdc44 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 false true true @@ -17,9 +17,4 @@ - - - latest - - diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index cbd3bde4f..004ded77b 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index b57b93a8c..a71c75127 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -14,7 +14,7 @@ - netstandard2.0 + netstandard2.1 false true true diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs index c95b00ede..85110c21c 100644 --- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs +++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs @@ -2,11 +2,11 @@ using System; using System.Linq; using System.Text; using System.Threading.Tasks; +using MediaBrowser.Common; using MediaBrowser.Common.Cryptography; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Cryptography; -using static MediaBrowser.Common.HexHelper; namespace Emby.Server.Implementations.Library { @@ -122,7 +122,7 @@ namespace Emby.Server.Implementations.Library { return string.IsNullOrEmpty(user.EasyPassword) ? null - : ToHexString(PasswordHash.Parse(user.EasyPassword).Hash); + : Hex.Encode(PasswordHash.Parse(user.EasyPassword).Hash); } /// diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 2b6ae1297..60d16c8a0 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common; using MediaBrowser.Common.Cryptography; using MediaBrowser.Common.Events; using MediaBrowser.Common.Net; @@ -31,7 +32,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Users; using Microsoft.Extensions.Logging; -using static MediaBrowser.Common.HexHelper; namespace Emby.Server.Implementations.Library { @@ -490,7 +490,7 @@ namespace Emby.Server.Implementations.Library { return string.IsNullOrEmpty(user.EasyPassword) ? null - : ToHexString(PasswordHash.Parse(user.EasyPassword).Hash); + : Hex.Encode(PasswordHash.Parse(user.EasyPassword).Hash); } private void ResetInvalidLoginAttemptCount(User user) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 49308b2b1..d4bd598e3 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2304,8 +2304,10 @@ namespace Emby.Server.Implementations.LiveTv if (provider == null) { throw new ResourceNotFoundException( - string.Format("Couldn't find provider of type: '{0}'", info.Type) - ); + string.Format( + CultureInfo.InvariantCulture, + "Couldn't find provider of type: '{0}'", + info.Type)); } await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 0c0c77cda..024bc9a47 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -19,7 +18,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Updates; using Microsoft.Extensions.Logging; -using static MediaBrowser.Common.HexHelper; namespace Emby.Server.Implementations.Updates { @@ -455,7 +453,7 @@ namespace Emby.Server.Implementations.Updates { cancellationToken.ThrowIfCancellationRequested(); - var hash = ToHexString(md5.ComputeHash(stream)); + var hash = Hex.Encode(md5.ComputeHash(stream)); if (!string.Equals(package.checksum, hash, StringComparison.OrdinalIgnoreCase)) { _logger.LogError( diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 396bdd4b7..988ac364a 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index b05e8c949..2b9a64e97 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Api.UserLibrary; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -25,7 +26,6 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Services; using Microsoft.Net.Http.Headers; -using static MediaBrowser.Common.HexHelper; namespace MediaBrowser.Api.LiveTv { @@ -887,8 +887,9 @@ namespace MediaBrowser.Api.LiveTv { // SchedulesDirect requires a SHA1 hash of the user's password // https://github.com/SchedulesDirect/JSON-Service/wiki/API-20141201#obtain-a-token - using (SHA1 sha = SHA1.Create()) { - return ToHexString( + using (SHA1 sha = SHA1.Create()) + { + return Hex.Encode( sha.ComputeHash(Encoding.UTF8.GetBytes(str))); } } diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index f653270a6..0d62cf8c5 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -10,7 +10,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.Common/Cryptography/PasswordHash.cs b/MediaBrowser.Common/Cryptography/PasswordHash.cs index dca31cd92..4c6804097 100644 --- a/MediaBrowser.Common/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Common/Cryptography/PasswordHash.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; -using static MediaBrowser.Common.HexHelper; namespace MediaBrowser.Common.Cryptography { @@ -102,13 +101,13 @@ namespace MediaBrowser.Common.Cryptography // Check if the string also contains a salt if (splitted.Length - index == 2) { - salt = FromHexString(splitted[index++]); - hash = FromHexString(splitted[index++]); + salt = Hex.Decode(splitted[index++]); + hash = Hex.Decode(splitted[index++]); } else { salt = Array.Empty(); - hash = FromHexString(splitted[index++]); + hash = Hex.Decode(splitted[index++]); } return new PasswordHash(id, hash, salt, parameters); @@ -145,11 +144,11 @@ namespace MediaBrowser.Common.Cryptography if (Salt.Length != 0) { str.Append('$') - .Append(ToHexString(Salt)); + .Append(Hex.Encode(Salt, false)); } return str.Append('$') - .Append(ToHexString(Hash)).ToString(); + .Append(Hex.Encode(Hash, false)).ToString(); } } } diff --git a/MediaBrowser.Common/Extensions/CollectionExtensions.cs b/MediaBrowser.Common/Extensions/CollectionExtensions.cs deleted file mode 100644 index 215224398..000000000 --- a/MediaBrowser.Common/Extensions/CollectionExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -#pragma warning disable CS1591 - -using System.Collections.Generic; - -namespace MediaBrowser.Common.Extensions -{ - // The MS CollectionExtensions are only available in netcoreapp - public static class CollectionExtensions - { - public static TValue GetValueOrDefault(this IReadOnlyDictionary dictionary, TKey key) - { - dictionary.TryGetValue(key, out var ret); - return ret; - } - - /// - /// Copies all the elements of the current collection to the specified list - /// starting at the specified destination array index. The index is specified as a 32-bit integer. - /// - /// The current collection that is the source of the elements. - /// The list that is the destination of the elements copied from the current collection. - /// A 32-bit integer that represents the index in destination at which copying begins. - /// - public static void CopyTo(this IReadOnlyList source, IList destination, int index = 0) - { - for (int i = 0; i < source.Count; i++) - { - destination[index + i] = source[i]; - } - } - - /// - /// Copies all the elements of the current collection to the specified list - /// starting at the specified destination array index. The index is specified as a 32-bit integer. - /// - /// The current collection that is the source of the elements. - /// The list that is the destination of the elements copied from the current collection. - /// A 32-bit integer that represents the index in destination at which copying begins. - /// - public static void CopyTo(this IReadOnlyCollection source, IList destination, int index = 0) - { - foreach (T item in source) - { - destination[index++] = item; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/CopyToExtensions.cs b/MediaBrowser.Common/Extensions/CopyToExtensions.cs new file mode 100644 index 000000000..78a73f07e --- /dev/null +++ b/MediaBrowser.Common/Extensions/CopyToExtensions.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Common.Extensions +{ + /// + /// Provides CopyTo extensions methods for . + /// + public static class CollectionExtensions + { + /// + /// Copies all the elements of the current collection to the specified list + /// starting at the specified destination array index. The index is specified as a 32-bit integer. + /// + /// The current collection that is the source of the elements. + /// The list that is the destination of the elements copied from the current collection. + /// A 32-bit integer that represents the index in destination at which copying begins. + /// + public static void CopyTo(this IReadOnlyList source, IList destination, int index = 0) + { + for (int i = 0; i < source.Count; i++) + { + destination[index + i] = source[i]; + } + } + } +} diff --git a/MediaBrowser.Common/Hex.cs b/MediaBrowser.Common/Hex.cs new file mode 100644 index 000000000..e19a9a1f4 --- /dev/null +++ b/MediaBrowser.Common/Hex.cs @@ -0,0 +1,57 @@ +using System; +using System.Globalization; + +namespace MediaBrowser.Common +{ + /// + /// Encoding and decoding hex strings. + /// + public static class Hex + { + internal const string HexCharsLower = "0123456789abcdef"; + internal const string HexCharsUpper = "0123456789ABCDEF"; + + /// + /// Encodes bytes as a hex string. + /// + /// + /// + /// bytes as a hex string. + public static string Encode(ReadOnlySpan bytes, bool lowercase = true) + { + var hexChars = lowercase ? HexCharsLower : HexCharsUpper; + + // TODO: use string.Create when it's supports spans + // Ref: https://github.com/dotnet/corefx/issues/29120 + char[] s = new char[bytes.Length * 2]; + int j = 0; + for (int i = 0; i < bytes.Length; i++) + { + s[j++] = hexChars[bytes[i] >> 4]; + s[j++] = hexChars[bytes[i] & 0x0f]; + } + + return new string(s); + } + + /// + /// Decodes a hex string into bytes. + /// + /// The . + /// The decoded bytes. + public static byte[] Decode(ReadOnlySpan str) + { + byte[] bytes = new byte[str.Length / 2]; + int j = 0; + for (int i = 0; i < str.Length; i += 2) + { + bytes[j++] = byte.Parse( + str.Slice(i, 2), + NumberStyles.HexNumber, + CultureInfo.InvariantCulture); + } + + return bytes; + } + } +} diff --git a/MediaBrowser.Common/HexHelper.cs b/MediaBrowser.Common/HexHelper.cs deleted file mode 100644 index 61007b5b2..000000000 --- a/MediaBrowser.Common/HexHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Globalization; - -namespace MediaBrowser.Common -{ - public static class HexHelper - { - public static byte[] FromHexString(string str) - { - byte[] bytes = new byte[str.Length / 2]; - for (int i = 0; i < str.Length; i += 2) - { - bytes[i / 2] = byte.Parse(str.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); - } - - return bytes; - } - - public static string ToHexString(byte[] bytes) - => BitConverter.ToString(bytes).Replace("-", ""); - } -} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index cf3f6c2a4..922a62a5f 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -21,7 +21,7 @@ - netstandard2.0 + netstandard2.1 false true true diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index c6bca2518..276eb71bc 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -17,7 +17,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index a8f8da9b8..71eb62693 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -10,7 +10,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 264f31f3c..083c361d0 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index c7ecc59c9..9e108a18b 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -19,7 +19,7 @@ - netstandard2.0 + netstandard2.1 false true @@ -28,5 +28,5 @@ latest - + diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index a43949367..1d256d689 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -16,7 +16,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 1ca9e43bb..ecc61a8d8 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -10,7 +10,7 @@ - netstandard2.0 + netstandard2.1 false true diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj index edfd5c9bb..c143000b3 100644 --- a/Mono.Nat/Mono.Nat.csproj +++ b/Mono.Nat/Mono.Nat.csproj @@ -10,7 +10,7 @@ - netstandard2.0 + netstandard2.1 false diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 456a93aa8..9753ae9b1 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -7,7 +7,7 @@ - netstandard2.0 + netstandard2.1 false diff --git a/benches/Jellyfin.Common.Benches/HexDecodeBenches.cs b/benches/Jellyfin.Common.Benches/HexDecodeBenches.cs new file mode 100644 index 000000000..281275597 --- /dev/null +++ b/benches/Jellyfin.Common.Benches/HexDecodeBenches.cs @@ -0,0 +1,42 @@ +using System; +using System.Globalization; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; +using MediaBrowser.Common; + +namespace Jellyfin.Common.Benches +{ + [MemoryDiagnoser] + public class HexDecodeBenches + { + private const int N = 1000000; + private readonly string data; + + public HexDecodeBenches() + { + var tmp = new byte[N]; + new Random(42).NextBytes(tmp); + data = Hex.Encode(tmp); + } + + public static byte[] DecodeSubString(string str) + { + byte[] bytes = new byte[str.Length / 2]; + for (int i = 0; i < str.Length; i += 2) + { + bytes[i / 2] = byte.Parse( + str.Substring(i, 2), + NumberStyles.HexNumber, + CultureInfo.InvariantCulture); + } + + return bytes; + } + + [Benchmark] + public byte[] Decode() => Hex.Decode(data); + + [Benchmark] + public byte[] DecodeSubString() => DecodeSubString(data); + } +} diff --git a/benches/Jellyfin.Common.Benches/HexEncodeBenches.cs b/benches/Jellyfin.Common.Benches/HexEncodeBenches.cs new file mode 100644 index 000000000..e7b446cc2 --- /dev/null +++ b/benches/Jellyfin.Common.Benches/HexEncodeBenches.cs @@ -0,0 +1,29 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; +using MediaBrowser.Common; + +namespace Jellyfin.Common.Benches +{ + [MemoryDiagnoser] + public class HexEncodeBenches + { + private const int N = 1000; + private readonly byte[] data; + + public HexEncodeBenches() + { + data = new byte[N]; + new Random(42).NextBytes(data); + } + + [Benchmark] + public string HexEncode() => Hex.Encode(data); + + [Benchmark] + public string BitConverterToString() => BitConverter.ToString(data); + + [Benchmark] + public string BitConverterToStringWithReplace() => BitConverter.ToString(data).Replace("-", ""); + } +} diff --git a/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj b/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj new file mode 100644 index 000000000..4d5046bf9 --- /dev/null +++ b/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + diff --git a/benches/Jellyfin.Common.Benches/Program.cs b/benches/Jellyfin.Common.Benches/Program.cs new file mode 100644 index 000000000..b218b0dc1 --- /dev/null +++ b/benches/Jellyfin.Common.Benches/Program.cs @@ -0,0 +1,14 @@ +using System; +using BenchmarkDotNet.Running; + +namespace Jellyfin.Common.Benches +{ + public static class Program + { + public static void Main(string[] args) + { + _ = BenchmarkRunner.Run(); + _ = BenchmarkRunner.Run(); + } + } +} diff --git a/tests/Jellyfin.Common.Tests/HexTests.cs b/tests/Jellyfin.Common.Tests/HexTests.cs new file mode 100644 index 000000000..5b578d38c --- /dev/null +++ b/tests/Jellyfin.Common.Tests/HexTests.cs @@ -0,0 +1,19 @@ +using MediaBrowser.Common; +using Xunit; + +namespace Jellyfin.Common.Tests +{ + public class HexTests + { + [Theory] + [InlineData("")] + [InlineData("00")] + [InlineData("01")] + [InlineData("000102030405060708090a0b0c0d0e0f")] + [InlineData("0123456789abcdef")] + public void RoundTripTest(string data) + { + Assert.Equal(data, Hex.Encode(Hex.Decode(data))); + } + } +} diff --git a/tests/Jellyfin.Common.Tests/PasswordHashTests.cs b/tests/Jellyfin.Common.Tests/PasswordHashTests.cs index 5fa86f3bd..03523dbc4 100644 --- a/tests/Jellyfin.Common.Tests/PasswordHashTests.cs +++ b/tests/Jellyfin.Common.Tests/PasswordHashTests.cs @@ -1,6 +1,6 @@ +using MediaBrowser.Common; using MediaBrowser.Common.Cryptography; using Xunit; -using static MediaBrowser.Common.HexHelper; namespace Jellyfin.Common.Tests { @@ -15,8 +15,8 @@ namespace Jellyfin.Common.Tests { var pass = PasswordHash.Parse(passwordHash); Assert.Equal(id, pass.Id); - Assert.Equal(salt, ToHexString(pass.Salt)); - Assert.Equal(hash, ToHexString(pass.Hash)); + Assert.Equal(salt, Hex.Encode(pass.Salt, false)); + Assert.Equal(hash, Hex.Encode(pass.Hash, false)); } [Theory] -- cgit v1.2.3 From 3f7836d9eb16d90b890dc925d8f7a3e8f2cb6b71 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 23 Sep 2019 23:10:51 +0200 Subject: Update deps and add MultiThreading analyzer --- Emby.Naming/Emby.Naming.csproj | 3 +- .../AppBase/BaseConfigurationManager.cs | 25 +++++-- .../Emby.Server.Implementations.csproj | 16 ++--- .../EntryPoints/ExternalPortForwarding.cs | 17 +++-- .../Networking/NetworkManager.cs | 16 +++-- .../Updates/InstallationManager.cs | 84 +++++++++++----------- Jellyfin.Server/Jellyfin.Server.csproj | 9 ++- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- .../MediaBrowser.Providers.csproj | 6 +- jellyfin.ruleset | 2 + 12 files changed, 106 insertions(+), 78 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index fca0aa1b3..a23fa3df7 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -24,8 +24,9 @@ - + + diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 4832c19c4..7ec5252d0 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.AppBase /// /// The _configuration sync lock. /// - private object _configurationSyncLock = new object(); + private readonly object _configurationSyncLock = new object(); /// /// The _configuration. @@ -98,16 +98,31 @@ namespace Emby.Server.Implementations.AppBase public IApplicationPaths CommonApplicationPaths { get; private set; } /// - /// Gets the system configuration + /// Gets the system configuration. /// /// The configuration. public BaseApplicationConfiguration CommonConfiguration { get { - // Lazy load - LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer)); - return _configuration; + if (_configurationLoaded) + { + return _configuration; + } + + lock (_configurationSyncLock) + { + if (_configurationLoaded) + { + return _configuration; + } + + _configuration = (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer); + + _configurationLoaded = true; + + return _configuration; + } } protected set { diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ea4444268..d6ca19e3f 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -1,4 +1,4 @@ - + @@ -29,9 +29,9 @@ - - - + + + @@ -47,16 +47,12 @@ true - - - latest - - - + + diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index f26a70586..d55dc2f18 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -27,6 +27,11 @@ namespace Emby.Server.Implementations.EntryPoints private NatManager _natManager; + private readonly object _createdRulesLock = new object(); + private List _createdRules = new List(); + private readonly object _usnsHandledLock = new object(); + private List _usnsHandled = new List(); + public ExternalPortForwarding(ILoggerFactory loggerFactory, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient) { _logger = loggerFactory.CreateLogger("PortMapper"); @@ -127,12 +132,13 @@ namespace Emby.Server.Implementations.EntryPoints return; } - lock (_usnsHandled) + lock (_usnsHandledLock) { if (_usnsHandled.Contains(identifier)) { return; } + _usnsHandled.Add(identifier); } @@ -186,11 +192,12 @@ namespace Emby.Server.Implementations.EntryPoints private void ClearCreatedRules(object state) { - lock (_createdRules) + lock (_createdRulesLock) { _createdRules.Clear(); } - lock (_usnsHandled) + + lock (_usnsHandledLock) { _usnsHandled.Clear(); } @@ -216,8 +223,6 @@ namespace Emby.Server.Implementations.EntryPoints } } - private List _createdRules = new List(); - private List _usnsHandled = new List(); private async void CreateRules(INatDevice device) { if (_disposed) @@ -231,7 +236,7 @@ namespace Emby.Server.Implementations.EntryPoints var addressString = address.ToString(); - lock (_createdRules) + lock (_createdRulesLock) { if (!_createdRules.Contains(addressString)) { diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 7d85a0666..d948dad68 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -20,6 +20,9 @@ namespace Emby.Server.Implementations.Networking private IPAddress[] _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); + private readonly object _subnetLookupLock = new object(); + private Dictionary> _subnetLookup = new Dictionary>(StringComparer.Ordinal); + public NetworkManager(ILogger logger) { _logger = logger; @@ -28,10 +31,10 @@ namespace Emby.Server.Implementations.Networking NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged; } - public Func LocalSubnetsFn { get; set; } - public event EventHandler NetworkChanged; + public Func LocalSubnetsFn { get; set; } + private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) { _logger.LogDebug("NetworkAvailabilityChanged"); @@ -179,10 +182,9 @@ namespace Emby.Server.Implementations.Networking return false; } - private Dictionary> _subnetLookup = new Dictionary>(StringComparer.Ordinal); private List GetSubnets(string endpointFirstPart) { - lock (_subnetLookup) + lock (_subnetLookupLock) { if (_subnetLookup.TryGetValue(endpointFirstPart, out var subnets)) { @@ -200,7 +202,11 @@ namespace Emby.Server.Implementations.Networking int subnet_Test = 0; foreach (string part in unicastIPAddressInformation.IPv4Mask.ToString().Split('.')) { - if (part.Equals("0")) break; + if (part.Equals("0", StringComparison.Ordinal)) + { + break; + } + subnet_Test++; } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 0c0c77cda..1c36ba359 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -28,43 +28,10 @@ namespace Emby.Server.Implementations.Updates /// public class InstallationManager : IInstallationManager { - public event EventHandler PackageInstalling; - public event EventHandler PackageInstallationCompleted; - public event EventHandler PackageInstallationFailed; - public event EventHandler PackageInstallationCancelled; - - /// - /// The current installations - /// - private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations { get; set; } - - /// - /// The completed installations - /// - private ConcurrentBag _completedInstallationsInternal; - - public IEnumerable CompletedInstallations => _completedInstallationsInternal; - - /// - /// Occurs when [plugin uninstalled]. - /// - public event EventHandler> PluginUninstalled; - - /// - /// Occurs when [plugin updated]. - /// - public event EventHandler> PluginUpdated; - /// - /// Occurs when [plugin updated]. - /// - public event EventHandler> PluginInstalled; - - /// - /// The _logger + /// The _logger. /// private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; @@ -79,6 +46,18 @@ namespace Emby.Server.Implementations.Updates private readonly IZipClient _zipClient; + private readonly object _currentInstallationsLock = new object(); + + /// + /// The current installations. + /// + private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations; + + /// + /// The completed installations. + /// + private ConcurrentBag _completedInstallationsInternal; + public InstallationManager( ILogger logger, IApplicationHost appHost, @@ -107,6 +86,31 @@ namespace Emby.Server.Implementations.Updates _zipClient = zipClient; } + public event EventHandler PackageInstalling; + + public event EventHandler PackageInstallationCompleted; + + public event EventHandler PackageInstallationFailed; + + public event EventHandler PackageInstallationCancelled; + + /// + /// Occurs when [plugin uninstalled]. + /// + public event EventHandler> PluginUninstalled; + + /// + /// Occurs when [plugin updated]. + /// + public event EventHandler> PluginUpdated; + + /// + /// Occurs when [plugin updated]. + /// + public event EventHandler> PluginInstalled; + + public IEnumerable CompletedInstallations => _completedInstallationsInternal; + /// /// Gets all available packages. /// @@ -330,7 +334,7 @@ namespace Emby.Server.Implementations.Updates var tuple = (installationInfo, innerCancellationTokenSource); // Add it to the in-progress list - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Add(tuple); } @@ -349,7 +353,7 @@ namespace Emby.Server.Implementations.Updates { await InstallPackageInternal(package, linkedToken).ConfigureAwait(false); - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -360,7 +364,7 @@ namespace Emby.Server.Implementations.Updates } catch (OperationCanceledException) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -375,7 +379,7 @@ namespace Emby.Server.Implementations.Updates { _logger.LogError(ex, "Package installation failed"); - lock (_currentInstallations) + lock (_currentInstallationsLock) { _currentInstallations.Remove(tuple); } @@ -535,7 +539,7 @@ namespace Emby.Server.Implementations.Updates /// public bool CancelInstallation(Guid id) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { var install = _currentInstallations.Find(x => x.Item1.Id == id); if (install == default((InstallationInfo, CancellationTokenSource))) @@ -563,7 +567,7 @@ namespace Emby.Server.Implementations.Updates { if (dispose) { - lock (_currentInstallations) + lock (_currentInstallationsLock) { foreach (var tuple in _currentInstallations) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index efdb75f98..4238d7fe3 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -9,8 +9,6 @@ - - latest true @@ -25,8 +23,9 @@ - + + @@ -35,8 +34,8 @@ - - + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index cf3f6c2a4..ec98400c8 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -12,7 +12,7 @@ - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 264f31f3c..ad07fdd8e 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,7 +18,7 @@ - + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 3ed319a0d..bd4eeea18 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -15,7 +15,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index c7ecc59c9..ec160a848 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -11,8 +11,8 @@ - - + + @@ -28,5 +28,5 @@ latest - + diff --git a/jellyfin.ruleset b/jellyfin.ruleset index e259131b0..16d68567c 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -10,6 +10,8 @@ + + -- cgit v1.2.3 From e9c893f07eeb0ddb59f136cedfdf7e5a3f06d36d Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 10:58:56 -0500 Subject: Fail attachment extraction on non-zero exit code. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index d6106df29..246023582 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -216,7 +216,7 @@ namespace MediaBrowser.MediaEncoding.Attachments var failed = false; - if (exitCode == -1) + if (exitCode != 0) { failed = true; -- cgit v1.2.3 From 9eef5f860d29eaa32d6b06f76d74f6c9bbe1e3cd Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 11:16:57 -0500 Subject: AttachmentExtractor logging cleanup. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 246023582..57b80d060 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -220,9 +220,9 @@ namespace MediaBrowser.MediaEncoding.Attachments { failed = true; + _logger.LogWarning("Deleting extracted attachment {Path} due to failure: {ExitCode}", outputPath, exitCode); try { - _logger.LogWarning("Deleting extracted attachment due to failure: {Path}", outputPath); _fileSystem.DeleteFile(outputPath); } catch (FileNotFoundException) -- cgit v1.2.3 From c7d303a6ae9e0d5489273fa5a15262987c735bd0 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 11:39:40 -0500 Subject: MediaExtractor logging cleanup. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 57b80d060..b369e4515 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -250,9 +250,7 @@ namespace MediaBrowser.MediaEncoding.Attachments } else { - var msg = $"ffmpeg attachment extraction completed for {inputPath} to {outputPath}"; - - _logger.LogInformation(msg); + _logger.LogInformation("ffmpeg attachment extraction completed for {Path} to {Path}", inputPath, outputPath); } } -- cgit v1.2.3 From 154fb1fe9b45892807a9bea9abb282380bfd9383 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 11:45:31 -0500 Subject: AttachmentExtractor code cleanup. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index b369e4515..1c214d5d3 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -256,19 +256,18 @@ namespace MediaBrowser.MediaEncoding.Attachments private string GetAttachmentCachePath(string mediaPath, MediaProtocol protocol, int attachmentStreamIndex) { + String filename; if (protocol == MediaProtocol.File) { var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); - var filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); - var prefix = filename.Substring(0, 1); - return Path.Combine(AttachmentCachePath, prefix, filename); + filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); } else { - var filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); - var prefix = filename.Substring(0, 1); - return Path.Combine(AttachmentCachePath, prefix, filename); + filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); } + var prefix = filename.Substring(0, 1); + return Path.Combine(AttachmentCachePath, prefix, filename); } } -- cgit v1.2.3 From 04a96788f9f3ea20b05d3c57d16d222ba7a53101 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 14:34:21 -0500 Subject: Convert exceptions for missing MediaSource or MediaAttachment to ResourceNotFoundException with appropriate message. --- .../Attachments/AttachmentExtractor.cs | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 1c214d5d3..be5908cce 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -65,10 +65,26 @@ namespace MediaBrowser.MediaEncoding.Attachments } var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); - var mediaSource = mediaSources - .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); - var mediaAttachment = mediaSource.MediaAttachments - .First(i => i.Index == attachmentStreamIndex); + MediaSourceInfo mediaSource; + MediaAttachment mediaAttachment; + try + { + mediaSource = mediaSources + .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); + } + catch (Exception ex) when (ex is ArgumentNullException || ex is InvalidOperationException) + { + throw new ResourceNotFoundException($"MediaSource {mediaSourceId} not found"); + } + try + { + mediaAttachment = mediaSource.MediaAttachments + .First(i => i.Index == attachmentStreamIndex); + } + catch (Exception ex) when (ex is ArgumentNullException || ex is InvalidOperationException) + { + throw new ResourceNotFoundException($"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}"); + } var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken) .ConfigureAwait(false); -- cgit v1.2.3 From 28a6718d8e77527c3949118676dc6e165e3608f5 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Mon, 4 Nov 2019 14:48:28 -0500 Subject: Return path of extracted attachment, which is always a file, instead of AttachmentInfo with path and protocol. --- .../Attachments/AttachmentExtractor.cs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index be5908cce..6bef1cd5a 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -97,20 +97,19 @@ namespace MediaBrowser.MediaEncoding.Attachments CancellationToken cancellationToken) { var inputFiles = new[] {mediaSource.Path}; - var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); - var stream = await GetAttachmentStream(fileInfo.Path, fileInfo.Protocol, cancellationToken).ConfigureAwait(false); + var attachmentPath = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); + var stream = await GetAttachmentStream(attachmentPath, cancellationToken).ConfigureAwait(false); return stream; } private async Task GetAttachmentStream( string path, - MediaProtocol protocol, CancellationToken cancellationToken) { return File.OpenRead(path); } - private async Task GetReadableFile( + private async Task GetReadableFile( string mediaPath, string[] inputFiles, MediaProtocol protocol, @@ -121,18 +120,7 @@ namespace MediaBrowser.MediaEncoding.Attachments await ExtractAttachment(inputFiles, protocol, mediaAttachment.Index, outputPath, cancellationToken) .ConfigureAwait(false); - return new AttachmentInfo(outputPath, MediaProtocol.File); - } - - private struct AttachmentInfo - { - public AttachmentInfo(string path, MediaProtocol protocol) - { - Path = path; - Protocol = protocol; - } - public string Path { get; set; } - public MediaProtocol Protocol { get; set; } + return outputPath; } private readonly ConcurrentDictionary _semaphoreLocks = -- cgit v1.2.3 From 6ca252ba5c651e41ad8a18c5555f5b60d81f0952 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Tue, 5 Nov 2019 07:09:55 -0500 Subject: Remove check for "[0]" in codec_tag. --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 2c001d775..f2056c566 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -535,8 +535,7 @@ namespace MediaBrowser.MediaEncoding.Probing Index = streamInfo.index }; - // Filter out junk - if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string)) { attachment.CodecTag = streamInfo.codec_tag_string; } -- cgit v1.2.3 From 349310787cbf49964a0e9bd1548adb5a3a3a3c1c Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Tue, 5 Nov 2019 08:16:46 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs formatting Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 6bef1cd5a..0c8d9ae9c 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -59,6 +59,7 @@ namespace MediaBrowser.MediaEncoding.Attachments { throw new ArgumentNullException(nameof(item)); } + if (string.IsNullOrWhiteSpace(mediaSourceId)) { throw new ArgumentNullException(nameof(mediaSourceId)); -- cgit v1.2.3 From 4f3b8831552db1d376198384cfe42894883286dd Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Wed, 6 Nov 2019 09:46:31 -0500 Subject: Clean up handling of missing source/attachment in AttachmentExtractor. --- .../Attachments/AttachmentExtractor.cs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 0c8d9ae9c..bda5c2f37 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -66,23 +66,15 @@ namespace MediaBrowser.MediaEncoding.Attachments } var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); - MediaSourceInfo mediaSource; - MediaAttachment mediaAttachment; - try - { - mediaSource = mediaSources - .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); - } - catch (Exception ex) when (ex is ArgumentNullException || ex is InvalidOperationException) + var mediaSource = mediaSources + .FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); + if (mediaSource == null) { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} not found"); } - try - { - mediaAttachment = mediaSource.MediaAttachments - .First(i => i.Index == attachmentStreamIndex); - } - catch (Exception ex) when (ex is ArgumentNullException || ex is InvalidOperationException) + var mediaAttachment = mediaSource.MediaAttachments + .FirstOrDefault(i => i.Index == attachmentStreamIndex); + if (mediaAttachment == null) { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}"); } -- cgit v1.2.3 From c09eb3470815c8f868fd6eda6b542169d29f2098 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 08:56:12 -0500 Subject: Check for attachment file before trying to remove it during cleanup. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index bda5c2f37..501dd3fed 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -220,11 +220,10 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogWarning("Deleting extracted attachment {Path} due to failure: {ExitCode}", outputPath, exitCode); try { - _fileSystem.DeleteFile(outputPath); - } - catch (FileNotFoundException) - { - + if (File.Exists(outputPath)) + { + _fileSystem.DeleteFile(outputPath); + } } catch (IOException ex) { -- cgit v1.2.3 From 92aae268a352c20964ca10348078fdaf4fbf8263 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:24:53 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs formatting Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 501dd3fed..4218b180d 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -204,7 +204,6 @@ namespace MediaBrowser.MediaEncoding.Attachments { _logger.LogError(ex, "Error killing attachment extraction process"); } - } var exitCode = ranToCompletion ? process.ExitCode : -1; -- cgit v1.2.3 From 492bbc9e13f177eea62b0b22a921106def90309c Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:25:44 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs String -> string Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 4218b180d..7c3a0fbd3 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -251,7 +251,7 @@ namespace MediaBrowser.MediaEncoding.Attachments private string GetAttachmentCachePath(string mediaPath, MediaProtocol protocol, int attachmentStreamIndex) { - String filename; + string filename; if (protocol == MediaProtocol.File) { var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); -- cgit v1.2.3 From 2338a53229431070b1c128436e990a486011205b Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:55:39 -0500 Subject: Don't user ILoggerFactory. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 7c3a0fbd3..d18463cb5 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.MediaEncoding.Attachments public AttachmentExtractor( ILibraryManager libraryManager, - ILoggerFactory loggerFactory, + ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, @@ -43,7 +43,7 @@ namespace MediaBrowser.MediaEncoding.Attachments IProcessFactory processFactory) { _libraryManager = libraryManager; - _logger = loggerFactory.CreateLogger(nameof(AttachmentExtractor)); + _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; -- cgit v1.2.3 From 2f728fd2a1be2e0abde3b8d7f8269b849e1555c6 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:58:26 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs formatting Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 7c3a0fbd3..2cecdf1cd 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -89,7 +89,7 @@ namespace MediaBrowser.MediaEncoding.Attachments MediaAttachment mediaAttachment, CancellationToken cancellationToken) { - var inputFiles = new[] {mediaSource.Path}; + var inputFiles = new[] { mediaSource.Path }; var attachmentPath = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); var stream = await GetAttachmentStream(attachmentPath, cancellationToken).ConfigureAwait(false); return stream; -- cgit v1.2.3 From 1eb3df1d6ce21641612ce2f7ce9f25cd757a0e0d Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:59:54 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs formatting / style Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index f5f5d213f..e5b82d075 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -166,7 +166,12 @@ namespace MediaBrowser.MediaEncoding.Attachments Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var processArgs = string.Format("-dump_attachment:{1} {2} -i {0} -t 0 -f null null", inputPath, attachmentStreamIndex, outputPath); + var processArgs = string.Format( + CultureInfo.InvariantCulture, + "-dump_attachment:{1} {2} -i {0} -t 0 -f null null", + inputPath, + attachmentStreamIndex, + outputPath); var process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, -- cgit v1.2.3 From 3a9bf84e3b1b4d6c3cd1eaf979a418087ce41e0d Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 12:00:47 -0500 Subject: Update MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs formatting Co-Authored-By: Bond-009 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index e5b82d075..0780df773 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -233,7 +233,6 @@ namespace MediaBrowser.MediaEncoding.Attachments { _logger.LogError(ex, "Error deleting extracted attachment {Path}", outputPath); } - } else if (!File.Exists(outputPath)) { -- cgit v1.2.3 From 79858eb26c60aa7ad8b6e63ee90fbd2e0727d594 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 14:24:49 -0500 Subject: Remove use of ProcessFactory, as well as arbitrary timeout in AttachmentExtractor. --- .../Attachments/AttachmentExtractor.cs | 31 +++++++++++++--------- MediaBrowser.MediaEncoding/packages.config | 3 --- 2 files changed, 18 insertions(+), 16 deletions(-) delete mode 100644 MediaBrowser.MediaEncoding/packages.config (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index f5f5d213f..369e597ea 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Collections.Concurrent; using System.Globalization; using System.IO; @@ -31,7 +32,6 @@ namespace MediaBrowser.MediaEncoding.Attachments private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IProcessFactory _processFactory; public AttachmentExtractor( ILibraryManager libraryManager, @@ -39,8 +39,7 @@ namespace MediaBrowser.MediaEncoding.Attachments IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, - IMediaSourceManager mediaSourceManager, - IProcessFactory processFactory) + IMediaSourceManager mediaSourceManager) { _libraryManager = libraryManager; _logger = logger; @@ -48,7 +47,6 @@ namespace MediaBrowser.MediaEncoding.Attachments _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; _mediaSourceManager = mediaSourceManager; - _processFactory = processFactory; } private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments"); @@ -167,16 +165,19 @@ namespace MediaBrowser.MediaEncoding.Attachments Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); var processArgs = string.Format("-dump_attachment:{1} {2} -i {0} -t 0 -f null null", inputPath, attachmentStreamIndex, outputPath); - var process = _processFactory.Create(new ProcessOptions + var startInfo = new ProcessStartInfo { - CreateNoWindow = true, - UseShellExecute = false, - EnableRaisingEvents = true, - FileName = _mediaEncoder.EncoderPath, Arguments = processArgs, - IsHidden = true, + FileName = _mediaEncoder.EncoderPath, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false - }); + }; + var process = new Process + { + StartInfo = startInfo + }; _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -191,7 +192,12 @@ namespace MediaBrowser.MediaEncoding.Attachments throw; } - var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); + var processTcs = new TaskCompletionSource(); + process.EnableRaisingEvents = true; + process.Exited += (sender, args) => processTcs.TrySetResult(true); + var unregister = cancellationToken.Register(() => processTcs.TrySetResult(process.HasExited)); + var ranToCompletion = await processTcs.Task.ConfigureAwait(false); + unregister.Dispose(); if (!ranToCompletion) { @@ -205,7 +211,6 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogError(ex, "Error killing attachment extraction process"); } } - var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); diff --git a/MediaBrowser.MediaEncoding/packages.config b/MediaBrowser.MediaEncoding/packages.config deleted file mode 100644 index bbeaf5f00..000000000 --- a/MediaBrowser.MediaEncoding/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file -- cgit v1.2.3 From dee247453e7b5cab1badb6a844af690cdf80aacd Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Wed, 13 Nov 2019 08:52:37 -0500 Subject: Throw InvalidOperationException when attachment extraction exits abnormally or doesn't produce output. --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 4e277826a..cb22343c4 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -250,7 +250,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogError(msg); - throw new Exception(msg); + throw new InvalidOperationException(msg); } else { -- cgit v1.2.3 From 9989b7b68fb6d87d3a2bf7f271e8fe0c8c3e41ab Mon Sep 17 00:00:00 2001 From: Stanislav Ionascu Date: Sun, 13 Oct 2019 11:21:20 +0200 Subject: Replace BDInfo plugin with nupkg and UHD/Atmos/DTS:X support --- BDInfo/BDInfo.csproj | 17 - BDInfo/BDInfoSettings.cs | 33 - BDInfo/BDROM.cs | 449 ------ BDInfo/LanguageCodes.cs | 493 ------- BDInfo/Properties/AssemblyInfo.cs | 21 - BDInfo/ReadMe.txt | 5 - BDInfo/TSCodecAC3.cs | 309 ---- BDInfo/TSCodecAVC.cs | 148 -- BDInfo/TSCodecDTS.cs | 159 -- BDInfo/TSCodecDTSHD.cs | 246 ---- BDInfo/TSCodecLPCM.cs | 123 -- BDInfo/TSCodecMPEG2.cs | 208 --- BDInfo/TSCodecMVC.cs | 36 - BDInfo/TSCodecTrueHD.cs | 186 --- BDInfo/TSCodecVC1.cs | 131 -- BDInfo/TSInterleavedFile.cs | 37 - BDInfo/TSPlaylistFile.cs | 1282 ---------------- BDInfo/TSStream.cs | 780 ---------- BDInfo/TSStreamBuffer.cs | 130 -- BDInfo/TSStreamClip.cs | 107 -- BDInfo/TSStreamClipFile.cs | 244 --- BDInfo/TSStreamFile.cs | 1555 -------------------- .../BdInfo/BdInfoDirectoryInfo.cs | 74 + .../BdInfo/BdInfoExaminer.cs | 4 +- .../BdInfo/BdInfoFileInfo.cs | 40 + .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.sln | 2 - 27 files changed, 117 insertions(+), 6704 deletions(-) delete mode 100644 BDInfo/BDInfo.csproj delete mode 100644 BDInfo/BDInfoSettings.cs delete mode 100644 BDInfo/BDROM.cs delete mode 100644 BDInfo/LanguageCodes.cs delete mode 100644 BDInfo/Properties/AssemblyInfo.cs delete mode 100644 BDInfo/ReadMe.txt delete mode 100644 BDInfo/TSCodecAC3.cs delete mode 100644 BDInfo/TSCodecAVC.cs delete mode 100644 BDInfo/TSCodecDTS.cs delete mode 100644 BDInfo/TSCodecDTSHD.cs delete mode 100644 BDInfo/TSCodecLPCM.cs delete mode 100644 BDInfo/TSCodecMPEG2.cs delete mode 100644 BDInfo/TSCodecMVC.cs delete mode 100644 BDInfo/TSCodecTrueHD.cs delete mode 100644 BDInfo/TSCodecVC1.cs delete mode 100644 BDInfo/TSInterleavedFile.cs delete mode 100644 BDInfo/TSPlaylistFile.cs delete mode 100644 BDInfo/TSStream.cs delete mode 100644 BDInfo/TSStreamBuffer.cs delete mode 100644 BDInfo/TSStreamClip.cs delete mode 100644 BDInfo/TSStreamClipFile.cs delete mode 100644 BDInfo/TSStreamFile.cs create mode 100644 MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs create mode 100644 MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/BDInfo/BDInfo.csproj b/BDInfo/BDInfo.csproj deleted file mode 100644 index 9dbaa9e2f..000000000 --- a/BDInfo/BDInfo.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - netstandard2.0 - false - true - - - diff --git a/BDInfo/BDInfoSettings.cs b/BDInfo/BDInfoSettings.cs deleted file mode 100644 index f4cb30016..000000000 --- a/BDInfo/BDInfoSettings.cs +++ /dev/null @@ -1,33 +0,0 @@ - -namespace BDInfo -{ - class BDInfoSettings - { - public static bool GenerateStreamDiagnostics => true; - - public static bool EnableSSIF => true; - - public static bool AutosaveReport => false; - - public static bool GenerateFrameDataFile => false; - - public static bool FilterLoopingPlaylists => true; - - public static bool FilterShortPlaylists => false; - - public static int FilterShortPlaylistsValue => 0; - - public static bool UseImagePrefix => false; - - public static string UseImagePrefixValue => null; - - /// - /// Setting this to false throws an IComparer error on some discs. - /// - public static bool KeepStreamOrder => true; - - public static bool GenerateTextSummary => false; - - public static string LastPath => string.Empty; - } -} diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs deleted file mode 100644 index 3a0c14ffd..000000000 --- a/BDInfo/BDROM.cs +++ /dev/null @@ -1,449 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using MediaBrowser.Model.IO; - -namespace BDInfo -{ - public class BDROM - { - public FileSystemMetadata DirectoryRoot = null; - public FileSystemMetadata DirectoryBDMV = null; - public FileSystemMetadata DirectoryBDJO = null; - public FileSystemMetadata DirectoryCLIPINF = null; - public FileSystemMetadata DirectoryPLAYLIST = null; - public FileSystemMetadata DirectorySNP = null; - public FileSystemMetadata DirectorySSIF = null; - public FileSystemMetadata DirectorySTREAM = null; - - public string VolumeLabel = null; - public ulong Size = 0; - public bool IsBDPlus = false; - public bool IsBDJava = false; - public bool IsDBOX = false; - public bool IsPSP = false; - public bool Is3D = false; - public bool Is50Hz = false; - - private readonly IFileSystem _fileSystem; - - public Dictionary PlaylistFiles = - new Dictionary(); - public Dictionary StreamClipFiles = - new Dictionary(); - public Dictionary StreamFiles = - new Dictionary(); - public Dictionary InterleavedFiles = - new Dictionary(); - - public delegate bool OnStreamClipFileScanError( - TSStreamClipFile streamClipFile, Exception ex); - - public event OnStreamClipFileScanError StreamClipFileScanError; - - public delegate bool OnStreamFileScanError( - TSStreamFile streamClipFile, Exception ex); - - public event OnStreamFileScanError StreamFileScanError; - - public delegate bool OnPlaylistFileScanError( - TSPlaylistFile playlistFile, Exception ex); - - public event OnPlaylistFileScanError PlaylistFileScanError; - - public BDROM(string path, IFileSystem fileSystem) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - _fileSystem = fileSystem; - // - // Locate BDMV directories. - // - - DirectoryBDMV = - GetDirectoryBDMV(path); - - if (DirectoryBDMV == null) - { - throw new Exception("Unable to locate BD structure."); - } - - DirectoryRoot = - _fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName)); - DirectoryBDJO = - GetDirectory("BDJO", DirectoryBDMV, 0); - DirectoryCLIPINF = - GetDirectory("CLIPINF", DirectoryBDMV, 0); - DirectoryPLAYLIST = - GetDirectory("PLAYLIST", DirectoryBDMV, 0); - DirectorySNP = - GetDirectory("SNP", DirectoryRoot, 0); - DirectorySTREAM = - GetDirectory("STREAM", DirectoryBDMV, 0); - DirectorySSIF = - GetDirectory("SSIF", DirectorySTREAM, 0); - - if (DirectoryCLIPINF == null - || DirectoryPLAYLIST == null) - { - throw new Exception("Unable to locate BD structure."); - } - - // - // Initialize basic disc properties. - // - - VolumeLabel = GetVolumeLabel(DirectoryRoot); - Size = (ulong)GetDirectorySize(DirectoryRoot); - - if (null != GetDirectory("BDSVM", DirectoryRoot, 0)) - { - IsBDPlus = true; - } - if (null != GetDirectory("SLYVM", DirectoryRoot, 0)) - { - IsBDPlus = true; - } - if (null != GetDirectory("ANYVM", DirectoryRoot, 0)) - { - IsBDPlus = true; - } - - if (DirectoryBDJO != null && - _fileSystem.GetFilePaths(DirectoryBDJO.FullName).Any()) - { - IsBDJava = true; - } - - if (DirectorySNP != null && - GetFilePaths(DirectorySNP.FullName, ".mnv").Any()) - { - IsPSP = true; - } - - if (DirectorySSIF != null && - _fileSystem.GetFilePaths(DirectorySSIF.FullName).Any()) - { - Is3D = true; - } - - if (File.Exists(Path.Combine(DirectoryRoot.FullName, "FilmIndex.xml"))) - { - IsDBOX = true; - } - - // - // Initialize file lists. - // - - if (DirectoryPLAYLIST != null) - { - FileSystemMetadata[] files = GetFiles(DirectoryPLAYLIST.FullName, ".mpls").ToArray(); - foreach (var file in files) - { - PlaylistFiles.Add( - file.Name.ToUpper(), new TSPlaylistFile(this, file)); - } - } - - if (DirectorySTREAM != null) - { - FileSystemMetadata[] files = GetFiles(DirectorySTREAM.FullName, ".m2ts").ToArray(); - foreach (var file in files) - { - StreamFiles.Add( - file.Name.ToUpper(), new TSStreamFile(file, _fileSystem)); - } - } - - if (DirectoryCLIPINF != null) - { - FileSystemMetadata[] files = GetFiles(DirectoryCLIPINF.FullName, ".clpi").ToArray(); - foreach (var file in files) - { - StreamClipFiles.Add( - file.Name.ToUpper(), new TSStreamClipFile(file)); - } - } - - if (DirectorySSIF != null) - { - FileSystemMetadata[] files = GetFiles(DirectorySSIF.FullName, ".ssif").ToArray(); - foreach (var file in files) - { - InterleavedFiles.Add( - file.Name.ToUpper(), new TSInterleavedFile(file)); - } - } - } - - private IEnumerable GetFiles(string path, string extension) - { - return _fileSystem.GetFiles(path, new[] { extension }, false, false); - } - - private IEnumerable GetFilePaths(string path, string extension) - { - return _fileSystem.GetFilePaths(path, new[] { extension }, false, false); - } - - public void Scan() - { - foreach (var streamClipFile in StreamClipFiles.Values) - { - try - { - streamClipFile.Scan(); - } - catch (Exception ex) - { - if (StreamClipFileScanError != null) - { - if (StreamClipFileScanError(streamClipFile, ex)) - { - continue; - } - else - { - break; - } - } - else throw; - } - } - - foreach (var streamFile in StreamFiles.Values) - { - string ssifName = Path.GetFileNameWithoutExtension(streamFile.Name) + ".SSIF"; - if (InterleavedFiles.ContainsKey(ssifName)) - { - streamFile.InterleavedFile = InterleavedFiles[ssifName]; - } - } - - TSStreamFile[] streamFiles = new TSStreamFile[StreamFiles.Count]; - StreamFiles.Values.CopyTo(streamFiles, 0); - Array.Sort(streamFiles, CompareStreamFiles); - - foreach (var playlistFile in PlaylistFiles.Values) - { - try - { - playlistFile.Scan(StreamFiles, StreamClipFiles); - } - catch (Exception ex) - { - if (PlaylistFileScanError != null) - { - if (PlaylistFileScanError(playlistFile, ex)) - { - continue; - } - else - { - break; - } - } - else throw; - } - } - - foreach (var streamFile in streamFiles) - { - try - { - var playlists = new List(); - foreach (var playlist in PlaylistFiles.Values) - { - foreach (var streamClip in playlist.StreamClips) - { - if (streamClip.Name == streamFile.Name) - { - playlists.Add(playlist); - break; - } - } - } - streamFile.Scan(playlists, false); - } - catch (Exception ex) - { - if (StreamFileScanError != null) - { - if (StreamFileScanError(streamFile, ex)) - { - continue; - } - else - { - break; - } - } - else throw; - } - } - - foreach (var playlistFile in PlaylistFiles.Values) - { - playlistFile.Initialize(); - if (!Is50Hz) - { - foreach (var videoStream in playlistFile.VideoStreams) - { - if (videoStream.FrameRate == TSFrameRate.FRAMERATE_25 || - videoStream.FrameRate == TSFrameRate.FRAMERATE_50) - { - Is50Hz = true; - } - } - } - } - } - - private FileSystemMetadata GetDirectoryBDMV( - string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - FileSystemMetadata dir = _fileSystem.GetDirectoryInfo(path); - - while (dir != null) - { - if (string.Equals(dir.Name, "BDMV", StringComparison.OrdinalIgnoreCase)) - { - return dir; - } - var parentFolder = Path.GetDirectoryName(dir.FullName); - if (string.IsNullOrEmpty(parentFolder)) - { - dir = null; - } - else - { - dir = _fileSystem.GetDirectoryInfo(parentFolder); - } - } - - return GetDirectory("BDMV", _fileSystem.GetDirectoryInfo(path), 0); - } - - private FileSystemMetadata GetDirectory( - string name, - FileSystemMetadata dir, - int searchDepth) - { - if (dir != null) - { - FileSystemMetadata[] children = _fileSystem.GetDirectories(dir.FullName).ToArray(); - foreach (var child in children) - { - if (string.Equals(child.Name, name, StringComparison.OrdinalIgnoreCase)) - { - return child; - } - } - if (searchDepth > 0) - { - foreach (var child in children) - { - GetDirectory( - name, child, searchDepth - 1); - } - } - } - return null; - } - - private long GetDirectorySize(FileSystemMetadata directoryInfo) - { - long size = 0; - - //if (!ExcludeDirs.Contains(directoryInfo.Name.ToUpper())) // TODO: Keep? - { - FileSystemMetadata[] pathFiles = _fileSystem.GetFiles(directoryInfo.FullName).ToArray(); - foreach (var pathFile in pathFiles) - { - if (pathFile.Extension.ToUpper() == ".SSIF") - { - continue; - } - size += pathFile.Length; - } - - FileSystemMetadata[] pathChildren = _fileSystem.GetDirectories(directoryInfo.FullName).ToArray(); - foreach (var pathChild in pathChildren) - { - size += GetDirectorySize(pathChild); - } - } - - return size; - } - - private string GetVolumeLabel(FileSystemMetadata dir) - { - return dir.Name; - } - - public int CompareStreamFiles( - TSStreamFile x, - TSStreamFile y) - { - // TODO: Use interleaved file sizes - - if ((x == null || x.FileInfo == null) && (y == null || y.FileInfo == null)) - { - return 0; - } - else if ((x == null || x.FileInfo == null) && (y != null && y.FileInfo != null)) - { - return 1; - } - else if ((x != null && x.FileInfo != null) && (y == null || y.FileInfo == null)) - { - return -1; - } - else - { - if (x.FileInfo.Length > y.FileInfo.Length) - { - return 1; - } - else if (y.FileInfo.Length > x.FileInfo.Length) - { - return -1; - } - else - { - return 0; - } - } - } - } -} diff --git a/BDInfo/LanguageCodes.cs b/BDInfo/LanguageCodes.cs deleted file mode 100644 index ab2693ffb..000000000 --- a/BDInfo/LanguageCodes.cs +++ /dev/null @@ -1,493 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class LanguageCodes - { - public static string GetName(string code) - { - switch (code) - { - case "abk": return "Abkhazian"; - case "ace": return "Achinese"; - case "ach": return "Acoli"; - case "ada": return "Adangme"; - case "aar": return "Afar"; - case "afh": return "Afrihili"; - case "afr": return "Afrikaans"; - case "afa": return "Afro-Asiatic (Other)"; - case "aka": return "Akan"; - case "akk": return "Akkadian"; - case "alb": return "Albanian"; - case "sqi": return "Albanian"; - case "ale": return "Aleut"; - case "alg": return "Algonquian languages"; - case "tut": return "Altaic (Other)"; - case "amh": return "Amharic"; - case "apa": return "Apache languages"; - case "ara": return "Arabic"; - case "arc": return "Aramaic"; - case "arp": return "Arapaho"; - case "arn": return "Araucanian"; - case "arw": return "Arawak"; - case "arm": return "Armenian"; - case "hye": return "Armenian"; - case "art": return "Artificial (Other)"; - case "asm": return "Assamese"; - case "ath": return "Athapascan languages"; - case "aus": return "Australian languages"; - case "map": return "Austronesian (Other)"; - case "ava": return "Avaric"; - case "ave": return "Avestan"; - case "awa": return "Awadhi"; - case "aym": return "Aymara"; - case "aze": return "Azerbaijani"; - case "ban": return "Balinese"; - case "bat": return "Baltic (Other)"; - case "bal": return "Baluchi"; - case "bam": return "Bambara"; - case "bai": return "Bamileke languages"; - case "bad": return "Banda"; - case "bnt": return "Bantu (Other)"; - case "bas": return "Basa"; - case "bak": return "Bashkir"; - case "baq": return "Basque"; - case "eus": return "Basque"; - case "btk": return "Batak (Indonesia)"; - case "bej": return "Beja"; - case "bel": return "Belarusian"; - case "bem": return "Bemba"; - case "ben": return "Bengali"; - case "ber": return "Berber (Other)"; - case "bho": return "Bhojpuri"; - case "bih": return "Bihari"; - case "bik": return "Bikol"; - case "bin": return "Bini"; - case "bis": return "Bislama"; - case "bos": return "Bosnian"; - case "bra": return "Braj"; - case "bre": return "Breton"; - case "bug": return "Buginese"; - case "bul": return "Bulgarian"; - case "bua": return "Buriat"; - case "bur": return "Burmese"; - case "mya": return "Burmese"; - case "cad": return "Caddo"; - case "car": return "Carib"; - case "cat": return "Catalan"; - case "cau": return "Caucasian (Other)"; - case "ceb": return "Cebuano"; - case "cel": return "Celtic (Other)"; - case "cai": return "Central American Indian (Other)"; - case "chg": return "Chagatai"; - case "cmc": return "Chamic languages"; - case "cha": return "Chamorro"; - case "che": return "Chechen"; - case "chr": return "Cherokee"; - case "chy": return "Cheyenne"; - case "chb": return "Chibcha"; - case "chi": return "Chinese"; - case "zho": return "Chinese"; - case "chn": return "Chinook jargon"; - case "chp": return "Chipewyan"; - case "cho": return "Choctaw"; - case "chu": return "Church Slavic"; - case "chk": return "Chuukese"; - case "chv": return "Chuvash"; - case "cop": return "Coptic"; - case "cor": return "Cornish"; - case "cos": return "Corsican"; - case "cre": return "Cree"; - case "mus": return "Creek"; - case "crp": return "Creoles and pidgins (Other)"; - case "cpe": return "Creoles and pidgins,"; - case "cpf": return "Creoles and pidgins,"; - case "cpp": return "Creoles and pidgins,"; - case "scr": return "Croatian"; - case "hrv": return "Croatian"; - case "cus": return "Cushitic (Other)"; - case "cze": return "Czech"; - case "ces": return "Czech"; - case "dak": return "Dakota"; - case "dan": return "Danish"; - case "day": return "Dayak"; - case "del": return "Delaware"; - case "din": return "Dinka"; - case "div": return "Divehi"; - case "doi": return "Dogri"; - case "dgr": return "Dogrib"; - case "dra": return "Dravidian (Other)"; - case "dua": return "Duala"; - case "dut": return "Dutch"; - case "nld": return "Dutch"; - case "dum": return "Dutch, Middle (ca. 1050-1350)"; - case "dyu": return "Dyula"; - case "dzo": return "Dzongkha"; - case "efi": return "Efik"; - case "egy": return "Egyptian (Ancient)"; - case "eka": return "Ekajuk"; - case "elx": return "Elamite"; - case "eng": return "English"; - case "enm": return "English, Middle (1100-1500)"; - case "ang": return "English, Old (ca.450-1100)"; - case "epo": return "Esperanto"; - case "est": return "Estonian"; - case "ewe": return "Ewe"; - case "ewo": return "Ewondo"; - case "fan": return "Fang"; - case "fat": return "Fanti"; - case "fao": return "Faroese"; - case "fij": return "Fijian"; - case "fin": return "Finnish"; - case "fiu": return "Finno-Ugrian (Other)"; - case "fon": return "Fon"; - case "fre": return "French"; - case "fra": return "French"; - case "frm": return "French, Middle (ca.1400-1600)"; - case "fro": return "French, Old (842-ca.1400)"; - case "fry": return "Frisian"; - case "fur": return "Friulian"; - case "ful": return "Fulah"; - case "gaa": return "Ga"; - case "glg": return "Gallegan"; - case "lug": return "Ganda"; - case "gay": return "Gayo"; - case "gba": return "Gbaya"; - case "gez": return "Geez"; - case "geo": return "Georgian"; - case "kat": return "Georgian"; - case "ger": return "German"; - case "deu": return "German"; - case "nds": return "Saxon"; - case "gmh": return "German, Middle High (ca.1050-1500)"; - case "goh": return "German, Old High (ca.750-1050)"; - case "gem": return "Germanic (Other)"; - case "gil": return "Gilbertese"; - case "gon": return "Gondi"; - case "gor": return "Gorontalo"; - case "got": return "Gothic"; - case "grb": return "Grebo"; - case "grc": return "Greek, Ancient (to 1453)"; - case "gre": return "Greek"; - case "ell": return "Greek"; - case "grn": return "Guarani"; - case "guj": return "Gujarati"; - case "gwi": return "Gwich´in"; - case "hai": return "Haida"; - case "hau": return "Hausa"; - case "haw": return "Hawaiian"; - case "heb": return "Hebrew"; - case "her": return "Herero"; - case "hil": return "Hiligaynon"; - case "him": return "Himachali"; - case "hin": return "Hindi"; - case "hmo": return "Hiri Motu"; - case "hit": return "Hittite"; - case "hmn": return "Hmong"; - case "hun": return "Hungarian"; - case "hup": return "Hupa"; - case "iba": return "Iban"; - case "ice": return "Icelandic"; - case "isl": return "Icelandic"; - case "ibo": return "Igbo"; - case "ijo": return "Ijo"; - case "ilo": return "Iloko"; - case "inc": return "Indic (Other)"; - case "ine": return "Indo-European (Other)"; - case "ind": return "Indonesian"; - case "ina": return "Interlingua (International"; - case "ile": return "Interlingue"; - case "iku": return "Inuktitut"; - case "ipk": return "Inupiaq"; - case "ira": return "Iranian (Other)"; - case "gle": return "Irish"; - case "mga": return "Irish, Middle (900-1200)"; - case "sga": return "Irish, Old (to 900)"; - case "iro": return "Iroquoian languages"; - case "ita": return "Italian"; - case "jpn": return "Japanese"; - case "jav": return "Javanese"; - case "jrb": return "Judeo-Arabic"; - case "jpr": return "Judeo-Persian"; - case "kab": return "Kabyle"; - case "kac": return "Kachin"; - case "kal": return "Kalaallisut"; - case "kam": return "Kamba"; - case "kan": return "Kannada"; - case "kau": return "Kanuri"; - case "kaa": return "Kara-Kalpak"; - case "kar": return "Karen"; - case "kas": return "Kashmiri"; - case "kaw": return "Kawi"; - case "kaz": return "Kazakh"; - case "kha": return "Khasi"; - case "khm": return "Khmer"; - case "khi": return "Khoisan (Other)"; - case "kho": return "Khotanese"; - case "kik": return "Kikuyu"; - case "kmb": return "Kimbundu"; - case "kin": return "Kinyarwanda"; - case "kir": return "Kirghiz"; - case "kom": return "Komi"; - case "kon": return "Kongo"; - case "kok": return "Konkani"; - case "kor": return "Korean"; - case "kos": return "Kosraean"; - case "kpe": return "Kpelle"; - case "kro": return "Kru"; - case "kua": return "Kuanyama"; - case "kum": return "Kumyk"; - case "kur": return "Kurdish"; - case "kru": return "Kurukh"; - case "kut": return "Kutenai"; - case "lad": return "Ladino"; - case "lah": return "Lahnda"; - case "lam": return "Lamba"; - case "lao": return "Lao"; - case "lat": return "Latin"; - case "lav": return "Latvian"; - case "ltz": return "Letzeburgesch"; - case "lez": return "Lezghian"; - case "lin": return "Lingala"; - case "lit": return "Lithuanian"; - case "loz": return "Lozi"; - case "lub": return "Luba-Katanga"; - case "lua": return "Luba-Lulua"; - case "lui": return "Luiseno"; - case "lun": return "Lunda"; - case "luo": return "Luo (Kenya and Tanzania)"; - case "lus": return "Lushai"; - case "mac": return "Macedonian"; - case "mkd": return "Macedonian"; - case "mad": return "Madurese"; - case "mag": return "Magahi"; - case "mai": return "Maithili"; - case "mak": return "Makasar"; - case "mlg": return "Malagasy"; - case "may": return "Malay"; - case "msa": return "Malay"; - case "mal": return "Malayalam"; - case "mlt": return "Maltese"; - case "mnc": return "Manchu"; - case "mdr": return "Mandar"; - case "man": return "Mandingo"; - case "mni": return "Manipuri"; - case "mno": return "Manobo languages"; - case "glv": return "Manx"; - case "mao": return "Maori"; - case "mri": return "Maori"; - case "mar": return "Marathi"; - case "chm": return "Mari"; - case "mah": return "Marshall"; - case "mwr": return "Marwari"; - case "mas": return "Masai"; - case "myn": return "Mayan languages"; - case "men": return "Mende"; - case "mic": return "Micmac"; - case "min": return "Minangkabau"; - case "mis": return "Miscellaneous languages"; - case "moh": return "Mohawk"; - case "mol": return "Moldavian"; - case "mkh": return "Mon-Khmer (Other)"; - case "lol": return "Mongo"; - case "mon": return "Mongolian"; - case "mos": return "Mossi"; - case "mul": return "Multiple languages"; - case "mun": return "Munda languages"; - case "nah": return "Nahuatl"; - case "nau": return "Nauru"; - case "nav": return "Navajo"; - case "nde": return "Ndebele, North"; - case "nbl": return "Ndebele, South"; - case "ndo": return "Ndonga"; - case "nep": return "Nepali"; - case "new": return "Newari"; - case "nia": return "Nias"; - case "nic": return "Niger-Kordofanian (Other)"; - case "ssa": return "Nilo-Saharan (Other)"; - case "niu": return "Niuean"; - case "non": return "Norse, Old"; - case "nai": return "North American Indian (Other)"; - case "sme": return "Northern Sami"; - case "nor": return "Norwegian"; - case "nob": return "Norwegian Bokmål"; - case "nno": return "Norwegian Nynorsk"; - case "nub": return "Nubian languages"; - case "nym": return "Nyamwezi"; - case "nya": return "Nyanja"; - case "nyn": return "Nyankole"; - case "nyo": return "Nyoro"; - case "nzi": return "Nzima"; - case "oci": return "Occitan"; - case "oji": return "Ojibwa"; - case "ori": return "Oriya"; - case "orm": return "Oromo"; - case "osa": return "Osage"; - case "oss": return "Ossetian"; - case "oto": return "Otomian languages"; - case "pal": return "Pahlavi"; - case "pau": return "Palauan"; - case "pli": return "Pali"; - case "pam": return "Pampanga"; - case "pag": return "Pangasinan"; - case "pan": return "Panjabi"; - case "pap": return "Papiamento"; - case "paa": return "Papuan (Other)"; - case "per": return "Persian"; - case "fas": return "Persian"; - case "peo": return "Persian, Old (ca.600-400 B.C.)"; - case "phi": return "Philippine (Other)"; - case "phn": return "Phoenician"; - case "pon": return "Pohnpeian"; - case "pol": return "Polish"; - case "por": return "Portuguese"; - case "pra": return "Prakrit languages"; - case "pro": return "Provençal"; - case "pus": return "Pushto"; - case "que": return "Quechua"; - case "roh": return "Raeto-Romance"; - case "raj": return "Rajasthani"; - case "rap": return "Rapanui"; - case "rar": return "Rarotongan"; - case "roa": return "Romance (Other)"; - case "rum": return "Romanian"; - case "ron": return "Romanian"; - case "rom": return "Romany"; - case "run": return "Rundi"; - case "rus": return "Russian"; - case "sal": return "Salishan languages"; - case "sam": return "Samaritan Aramaic"; - case "smi": return "Sami languages (Other)"; - case "smo": return "Samoan"; - case "sad": return "Sandawe"; - case "sag": return "Sango"; - case "san": return "Sanskrit"; - case "sat": return "Santali"; - case "srd": return "Sardinian"; - case "sas": return "Sasak"; - case "sco": return "Scots"; - case "gla": return "Gaelic"; - case "sel": return "Selkup"; - case "sem": return "Semitic (Other)"; - case "scc": return "Serbian"; - case "srp": return "Serbian"; - case "srr": return "Serer"; - case "shn": return "Shan"; - case "sna": return "Shona"; - case "sid": return "Sidamo"; - case "sgn": return "Sign languages"; - case "bla": return "Siksika"; - case "snd": return "Sindhi"; - case "sin": return "Sinhalese"; - case "sit": return "Sino-Tibetan (Other)"; - case "sio": return "Siouan languages"; - case "den": return "Slave (Athapascan)"; - case "sla": return "Slavic (Other)"; - case "slo": return "Slovak"; - case "slk": return "Slovak"; - case "slv": return "Slovenian"; - case "sog": return "Sogdian"; - case "som": return "Somali"; - case "son": return "Songhai"; - case "snk": return "Soninke"; - case "wen": return "Sorbian languages"; - case "nso": return "Sotho, Northern"; - case "sot": return "Sotho, Southern"; - case "sai": return "South American Indian (Other)"; - case "spa": return "Spanish"; - case "suk": return "Sukuma"; - case "sux": return "Sumerian"; - case "sun": return "Sundanese"; - case "sus": return "Susu"; - case "swa": return "Swahili"; - case "ssw": return "Swati"; - case "swe": return "Swedish"; - case "syr": return "Syriac"; - case "tgl": return "Tagalog"; - case "tah": return "Tahitian"; - case "tai": return "Tai (Other)"; - case "tgk": return "Tajik"; - case "tmh": return "Tamashek"; - case "tam": return "Tamil"; - case "tat": return "Tatar"; - case "tel": return "Telugu"; - case "ter": return "Tereno"; - case "tet": return "Tetum"; - case "tha": return "Thai"; - case "tib": return "Tibetan"; - case "bod": return "Tibetan"; - case "tig": return "Tigre"; - case "tir": return "Tigrinya"; - case "tem": return "Timne"; - case "tiv": return "Tiv"; - case "tli": return "Tlingit"; - case "tpi": return "Tok Pisin"; - case "tkl": return "Tokelau"; - case "tog": return "Tonga (Nyasa)"; - case "ton": return "Tonga (Tonga Islands)"; - case "tsi": return "Tsimshian"; - case "tso": return "Tsonga"; - case "tsn": return "Tswana"; - case "tum": return "Tumbuka"; - case "tur": return "Turkish"; - case "ota": return "Turkish, Ottoman (1500-1928)"; - case "tuk": return "Turkmen"; - case "tvl": return "Tuvalu"; - case "tyv": return "Tuvinian"; - case "twi": return "Twi"; - case "uga": return "Ugaritic"; - case "uig": return "Uighur"; - case "ukr": return "Ukrainian"; - case "umb": return "Umbundu"; - case "und": return "Undetermined"; - case "urd": return "Urdu"; - case "uzb": return "Uzbek"; - case "vai": return "Vai"; - case "ven": return "Venda"; - case "vie": return "Vietnamese"; - case "vol": return "Volapük"; - case "vot": return "Votic"; - case "wak": return "Wakashan languages"; - case "wal": return "Walamo"; - case "war": return "Waray"; - case "was": return "Washo"; - case "wel": return "Welsh"; - case "cym": return "Welsh"; - case "wol": return "Wolof"; - case "xho": return "Xhosa"; - case "sah": return "Yakut"; - case "yao": return "Yao"; - case "yap": return "Yapese"; - case "yid": return "Yiddish"; - case "yor": return "Yoruba"; - case "ypk": return "Yupik languages"; - case "znd": return "Zande"; - case "zap": return "Zapotec"; - case "zen": return "Zenaga"; - case "zha": return "Zhuang"; - case "zul": return "Zulu"; - case "zun": return "Zuni"; - - default: return code; - } - } - } -} diff --git a/BDInfo/Properties/AssemblyInfo.cs b/BDInfo/Properties/AssemblyInfo.cs deleted file mode 100644 index f65c7036a..000000000 --- a/BDInfo/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("BDInfo")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2016 CinemaSquid. Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] diff --git a/BDInfo/ReadMe.txt b/BDInfo/ReadMe.txt deleted file mode 100644 index e70b0b66c..000000000 --- a/BDInfo/ReadMe.txt +++ /dev/null @@ -1,5 +0,0 @@ -The source is taken from the BDRom folder of this project: - -http://www.cinemasquid.com/blu-ray/tools/bdinfo - -BDInfoSettings was taken from the FormSettings class, and changed so that the settings all return defaults. diff --git a/BDInfo/TSCodecAC3.cs b/BDInfo/TSCodecAC3.cs deleted file mode 100644 index 35d306a19..000000000 --- a/BDInfo/TSCodecAC3.cs +++ /dev/null @@ -1,309 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -#undef DEBUG -using System.IO; - -namespace BDInfo -{ - public abstract class TSCodecAC3 - { - private static byte[] eac3_blocks = new byte[] { 1, 2, 3, 6 }; - - public static void Scan( - TSAudioStream stream, - TSStreamBuffer buffer, - ref string tag) - { - if (stream.IsInitialized) return; - - byte[] sync = buffer.ReadBytes(2); - if (sync == null || - sync[0] != 0x0B || - sync[1] != 0x77) - { - return; - } - - int sr_code = 0; - int frame_size = 0; - int frame_size_code = 0; - int channel_mode = 0; - int lfe_on = 0; - int dial_norm = 0; - int num_blocks = 0; - - byte[] hdr = buffer.ReadBytes(4); - int bsid = (hdr[3] & 0xF8) >> 3; - buffer.Seek(-4, SeekOrigin.Current); - if (bsid <= 10) - { - byte[] crc = buffer.ReadBytes(2); - sr_code = buffer.ReadBits(2); - frame_size_code = buffer.ReadBits(6); - bsid = buffer.ReadBits(5); - int bsmod = buffer.ReadBits(3); - - channel_mode = buffer.ReadBits(3); - int cmixlev = 0; - if (((channel_mode & 0x1) > 0) && (channel_mode != 0x1)) - { - cmixlev = buffer.ReadBits(2); - } - int surmixlev = 0; - if ((channel_mode & 0x4) > 0) - { - surmixlev = buffer.ReadBits(2); - } - int dsurmod = 0; - if (channel_mode == 0x2) - { - dsurmod = buffer.ReadBits(2); - if (dsurmod == 0x2) - { - stream.AudioMode = TSAudioMode.Surround; - } - } - lfe_on = buffer.ReadBits(1); - dial_norm = buffer.ReadBits(5); - int compr = 0; - if (1 == buffer.ReadBits(1)) - { - compr = buffer.ReadBits(8); - } - int langcod = 0; - if (1 == buffer.ReadBits(1)) - { - langcod = buffer.ReadBits(8); - } - int mixlevel = 0; - int roomtyp = 0; - if (1 == buffer.ReadBits(1)) - { - mixlevel = buffer.ReadBits(5); - roomtyp = buffer.ReadBits(2); - } - if (channel_mode == 0) - { - int dialnorm2 = buffer.ReadBits(5); - int compr2 = 0; - if (1 == buffer.ReadBits(1)) - { - compr2 = buffer.ReadBits(8); - } - int langcod2 = 0; - if (1 == buffer.ReadBits(1)) - { - langcod2 = buffer.ReadBits(8); - } - int mixlevel2 = 0; - int roomtyp2 = 0; - if (1 == buffer.ReadBits(1)) - { - mixlevel2 = buffer.ReadBits(5); - roomtyp2 = buffer.ReadBits(2); - } - } - int copyrightb = buffer.ReadBits(1); - int origbs = buffer.ReadBits(1); - if (bsid == 6) - { - if (1 == buffer.ReadBits(1)) - { - int dmixmod = buffer.ReadBits(2); - int ltrtcmixlev = buffer.ReadBits(3); - int ltrtsurmixlev = buffer.ReadBits(3); - int lorocmixlev = buffer.ReadBits(3); - int lorosurmixlev = buffer.ReadBits(3); - } - if (1 == buffer.ReadBits(1)) - { - int dsurexmod = buffer.ReadBits(2); - int dheadphonmod = buffer.ReadBits(2); - if (dheadphonmod == 0x2) - { - // TODO - } - int adconvtyp = buffer.ReadBits(1); - int xbsi2 = buffer.ReadBits(8); - int encinfo = buffer.ReadBits(1); - if (dsurexmod == 2) - { - stream.AudioMode = TSAudioMode.Extended; - } - } - } - } - else - { - int frame_type = buffer.ReadBits(2); - int substreamid = buffer.ReadBits(3); - frame_size = (buffer.ReadBits(11) + 1) << 1; - - sr_code = buffer.ReadBits(2); - if (sr_code == 3) - { - sr_code = buffer.ReadBits(2); - } - else - { - num_blocks = buffer.ReadBits(2); - } - channel_mode = buffer.ReadBits(3); - lfe_on = buffer.ReadBits(1); - } - - switch (channel_mode) - { - case 0: // 1+1 - stream.ChannelCount = 2; - if (stream.AudioMode == TSAudioMode.Unknown) - { - stream.AudioMode = TSAudioMode.DualMono; - } - break; - case 1: // 1/0 - stream.ChannelCount = 1; - break; - case 2: // 2/0 - stream.ChannelCount = 2; - if (stream.AudioMode == TSAudioMode.Unknown) - { - stream.AudioMode = TSAudioMode.Stereo; - } - break; - case 3: // 3/0 - stream.ChannelCount = 3; - break; - case 4: // 2/1 - stream.ChannelCount = 3; - break; - case 5: // 3/1 - stream.ChannelCount = 4; - break; - case 6: // 2/2 - stream.ChannelCount = 4; - break; - case 7: // 3/2 - stream.ChannelCount = 5; - break; - default: - stream.ChannelCount = 0; - break; - } - - switch (sr_code) - { - case 0: - stream.SampleRate = 48000; - break; - case 1: - stream.SampleRate = 44100; - break; - case 2: - stream.SampleRate = 32000; - break; - default: - stream.SampleRate = 0; - break; - } - - if (bsid <= 10) - { - switch (frame_size_code >> 1) - { - case 18: - stream.BitRate = 640000; - break; - case 17: - stream.BitRate = 576000; - break; - case 16: - stream.BitRate = 512000; - break; - case 15: - stream.BitRate = 448000; - break; - case 14: - stream.BitRate = 384000; - break; - case 13: - stream.BitRate = 320000; - break; - case 12: - stream.BitRate = 256000; - break; - case 11: - stream.BitRate = 224000; - break; - case 10: - stream.BitRate = 192000; - break; - case 9: - stream.BitRate = 160000; - break; - case 8: - stream.BitRate = 128000; - break; - case 7: - stream.BitRate = 112000; - break; - case 6: - stream.BitRate = 96000; - break; - case 5: - stream.BitRate = 80000; - break; - case 4: - stream.BitRate = 64000; - break; - case 3: - stream.BitRate = 56000; - break; - case 2: - stream.BitRate = 48000; - break; - case 1: - stream.BitRate = 40000; - break; - case 0: - stream.BitRate = 32000; - break; - default: - stream.BitRate = 0; - break; - } - } - else - { - stream.BitRate = (long) - (4.0 * frame_size * stream.SampleRate / (num_blocks * 256)); - } - - stream.LFE = lfe_on; - if (stream.StreamType != TSStreamType.AC3_PLUS_AUDIO && - stream.StreamType != TSStreamType.AC3_PLUS_SECONDARY_AUDIO) - { - stream.DialNorm = dial_norm - 31; - } - stream.IsVBR = false; - stream.IsInitialized = true; - } - } -} diff --git a/BDInfo/TSCodecAVC.cs b/BDInfo/TSCodecAVC.cs deleted file mode 100644 index 5833d169f..000000000 --- a/BDInfo/TSCodecAVC.cs +++ /dev/null @@ -1,148 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecAVC - { - public static void Scan( - TSVideoStream stream, - TSStreamBuffer buffer, - ref string tag) - { - uint parse = 0; - byte accessUnitDelimiterParse = 0; - byte sequenceParameterSetParse = 0; - string profile = null; - string level = null; - byte constraintSet0Flag = 0; - byte constraintSet1Flag = 0; - byte constraintSet2Flag = 0; - byte constraintSet3Flag = 0; - - for (int i = 0; i < buffer.Length; i++) - { - parse = (parse << 8) + buffer.ReadByte(); - - if (parse == 0x00000109) - { - accessUnitDelimiterParse = 1; - } - else if (accessUnitDelimiterParse > 0) - { - --accessUnitDelimiterParse; - if (accessUnitDelimiterParse == 0) - { - switch ((parse & 0xFF) >> 5) - { - case 0: // I - case 3: // SI - case 5: // I, SI - tag = "I"; - break; - - case 1: // I, P - case 4: // SI, SP - case 6: // I, SI, P, SP - tag = "P"; - break; - - case 2: // I, P, B - case 7: // I, SI, P, SP, B - tag = "B"; - break; - } - if (stream.IsInitialized) return; - } - } - else if (parse == 0x00000127 || parse == 0x00000167) - { - sequenceParameterSetParse = 3; - } - else if (sequenceParameterSetParse > 0) - { - --sequenceParameterSetParse; - switch (sequenceParameterSetParse) - { - case 2: - switch (parse & 0xFF) - { - case 66: - profile = "Baseline Profile"; - break; - case 77: - profile = "Main Profile"; - break; - case 88: - profile = "Extended Profile"; - break; - case 100: - profile = "High Profile"; - break; - case 110: - profile = "High 10 Profile"; - break; - case 122: - profile = "High 4:2:2 Profile"; - break; - case 144: - profile = "High 4:4:4 Profile"; - break; - default: - profile = "Unknown Profile"; - break; - } - break; - - case 1: - constraintSet0Flag = (byte) - ((parse & 0x80) >> 7); - constraintSet1Flag = (byte) - ((parse & 0x40) >> 6); - constraintSet2Flag = (byte) - ((parse & 0x20) >> 5); - constraintSet3Flag = (byte) - ((parse & 0x10) >> 4); - break; - - case 0: - byte b = (byte)(parse & 0xFF); - if (b == 11 && constraintSet3Flag == 1) - { - level = "1b"; - } - else - { - level = string.Format( - "{0:D}.{1:D}", - b / 10, (b - ((b / 10) * 10))); - } - stream.EncodingProfile = string.Format( - "{0} {1}", profile, level); - stream.IsVBR = true; - stream.IsInitialized = true; - break; - } - } - } - return; - } - } -} diff --git a/BDInfo/TSCodecDTS.cs b/BDInfo/TSCodecDTS.cs deleted file mode 100644 index ff94cb702..000000000 --- a/BDInfo/TSCodecDTS.cs +++ /dev/null @@ -1,159 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecDTS - { - private static int[] dca_sample_rates = - { - 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, - 12000, 24000, 48000, 96000, 192000 - }; - - private static int[] dca_bit_rates = - { - 32000, 56000, 64000, 96000, 112000, 128000, - 192000, 224000, 256000, 320000, 384000, - 448000, 512000, 576000, 640000, 768000, - 896000, 1024000, 1152000, 1280000, 1344000, - 1408000, 1411200, 1472000, 1509000, 1920000, - 2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/ - }; - - private static int[] dca_channels = - { - 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8 - }; - - private static int[] dca_bits_per_sample = - { - 16, 16, 20, 20, 0, 24, 24 - }; - - public static void Scan( - TSAudioStream stream, - TSStreamBuffer buffer, - long bitrate, - ref string tag) - { - if (stream.IsInitialized) return; - - bool syncFound = false; - uint sync = 0; - for (int i = 0; i < buffer.Length; i++) - { - sync = (sync << 8) + buffer.ReadByte(); - if (sync == 0x7FFE8001) - { - syncFound = true; - break; - } - } - if (!syncFound) return; - - int frame_type = buffer.ReadBits(1); - int samples_deficit = buffer.ReadBits(5); - int crc_present = buffer.ReadBits(1); - int sample_blocks = buffer.ReadBits(7); - int frame_size = buffer.ReadBits(14); - if (frame_size < 95) - { - return; - } - int amode = buffer.ReadBits(6); - int sample_rate = buffer.ReadBits(4); - if (sample_rate < 0 || sample_rate >= dca_sample_rates.Length) - { - return; - } - int bit_rate = buffer.ReadBits(5); - if (bit_rate < 0 || bit_rate >= dca_bit_rates.Length) - { - return; - } - int downmix = buffer.ReadBits(1); - int dynrange = buffer.ReadBits(1); - int timestamp = buffer.ReadBits(1); - int aux_data = buffer.ReadBits(1); - int hdcd = buffer.ReadBits(1); - int ext_descr = buffer.ReadBits(3); - int ext_coding = buffer.ReadBits(1); - int aspf = buffer.ReadBits(1); - int lfe = buffer.ReadBits(2); - int predictor_history = buffer.ReadBits(1); - if (crc_present == 1) - { - int crc = buffer.ReadBits(16); - } - int multirate_inter = buffer.ReadBits(1); - int version = buffer.ReadBits(4); - int copy_history = buffer.ReadBits(2); - int source_pcm_res = buffer.ReadBits(3); - int front_sum = buffer.ReadBits(1); - int surround_sum = buffer.ReadBits(1); - int dialog_norm = buffer.ReadBits(4); - if (source_pcm_res < 0 || source_pcm_res >= dca_bits_per_sample.Length) - { - return; - } - int subframes = buffer.ReadBits(4); - int total_channels = buffer.ReadBits(3) + 1 + ext_coding; - - stream.SampleRate = dca_sample_rates[sample_rate]; - stream.ChannelCount = total_channels; - stream.LFE = (lfe > 0 ? 1 : 0); - stream.BitDepth = dca_bits_per_sample[source_pcm_res]; - stream.DialNorm = -dialog_norm; - if ((source_pcm_res & 0x1) == 0x1) - { - stream.AudioMode = TSAudioMode.Extended; - } - - stream.BitRate = (uint)dca_bit_rates[bit_rate]; - switch (stream.BitRate) - { - case 1: - if (bitrate > 0) - { - stream.BitRate = bitrate; - stream.IsVBR = false; - stream.IsInitialized = true; - } - else - { - stream.BitRate = 0; - } - break; - - case 2: - case 3: - stream.IsVBR = true; - stream.IsInitialized = true; - break; - - default: - stream.IsVBR = false; - stream.IsInitialized = true; - break; - } - } - } -} diff --git a/BDInfo/TSCodecDTSHD.cs b/BDInfo/TSCodecDTSHD.cs deleted file mode 100644 index 57a136d2d..000000000 --- a/BDInfo/TSCodecDTSHD.cs +++ /dev/null @@ -1,246 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecDTSHD - { - private static int[] SampleRates = new int[] - { 0x1F40, 0x3E80, 0x7D00, 0x0FA00, 0x1F400, 0x5622, 0x0AC44, 0x15888, 0x2B110, 0x56220, 0x2EE0, 0x5DC0, 0x0BB80, 0x17700, 0x2EE00, 0x5DC00 }; - - public static void Scan( - TSAudioStream stream, - TSStreamBuffer buffer, - long bitrate, - ref string tag) - { - if (stream.IsInitialized && - (stream.StreamType == TSStreamType.DTS_HD_SECONDARY_AUDIO || - (stream.CoreStream != null && - stream.CoreStream.IsInitialized))) return; - - bool syncFound = false; - uint sync = 0; - for (int i = 0; i < buffer.Length; i++) - { - sync = (sync << 8) + buffer.ReadByte(); - if (sync == 0x64582025) - { - syncFound = true; - break; - } - } - - if (!syncFound) - { - tag = "CORE"; - if (stream.CoreStream == null) - { - stream.CoreStream = new TSAudioStream(); - stream.CoreStream.StreamType = TSStreamType.DTS_AUDIO; - } - if (!stream.CoreStream.IsInitialized) - { - buffer.BeginRead(); - TSCodecDTS.Scan(stream.CoreStream, buffer, bitrate, ref tag); - } - return; - } - - tag = "HD"; - int temp1 = buffer.ReadBits(8); - int nuSubStreamIndex = buffer.ReadBits(2); - int nuExtSSHeaderSize = 0; - int nuExtSSFSize = 0; - int bBlownUpHeader = buffer.ReadBits(1); - if (1 == bBlownUpHeader) - { - nuExtSSHeaderSize = buffer.ReadBits(12) + 1; - nuExtSSFSize = buffer.ReadBits(20) + 1; - } - else - { - nuExtSSHeaderSize = buffer.ReadBits(8) + 1; - nuExtSSFSize = buffer.ReadBits(16) + 1; - } - int nuNumAudioPresent = 1; - int nuNumAssets = 1; - int bStaticFieldsPresent = buffer.ReadBits(1); - if (1 == bStaticFieldsPresent) - { - int nuRefClockCode = buffer.ReadBits(2); - int nuExSSFrameDurationCode = buffer.ReadBits(3) + 1; - long nuTimeStamp = 0; - if (1 == buffer.ReadBits(1)) - { - nuTimeStamp = (buffer.ReadBits(18) << 18) + buffer.ReadBits(18); - } - nuNumAudioPresent = buffer.ReadBits(3) + 1; - nuNumAssets = buffer.ReadBits(3) + 1; - int[] nuActiveExSSMask = new int[nuNumAudioPresent]; - for (int i = 0; i < nuNumAudioPresent; i++) - { - nuActiveExSSMask[i] = buffer.ReadBits(nuSubStreamIndex + 1); //? - } - for (int i = 0; i < nuNumAudioPresent; i++) - { - for (int j = 0; j < nuSubStreamIndex + 1; j++) - { - if (((j + 1) % 2) == 1) - { - int mask = buffer.ReadBits(8); - } - } - } - if (1 == buffer.ReadBits(1)) - { - int nuMixMetadataAdjLevel = buffer.ReadBits(2); - int nuBits4MixOutMask = buffer.ReadBits(2) * 4 + 4; - int nuNumMixOutConfigs = buffer.ReadBits(2) + 1; - int[] nuMixOutChMask = new int[nuNumMixOutConfigs]; - for (int i = 0; i < nuNumMixOutConfigs; i++) - { - nuMixOutChMask[i] = buffer.ReadBits(nuBits4MixOutMask); - } - } - } - int[] AssetSizes = new int[nuNumAssets]; - for (int i = 0; i < nuNumAssets; i++) - { - if (1 == bBlownUpHeader) - { - AssetSizes[i] = buffer.ReadBits(20) + 1; - } - else - { - AssetSizes[i] = buffer.ReadBits(16) + 1; - } - } - for (int i = 0; i < nuNumAssets; i++) - { - long bufferPosition = buffer.Position; - int nuAssetDescriptorFSIZE = buffer.ReadBits(9) + 1; - int DescriptorDataForAssetIndex = buffer.ReadBits(3); - if (1 == bStaticFieldsPresent) - { - int AssetTypeDescrPresent = buffer.ReadBits(1); - if (1 == AssetTypeDescrPresent) - { - int AssetTypeDescriptor = buffer.ReadBits(4); - } - int LanguageDescrPresent = buffer.ReadBits(1); - if (1 == LanguageDescrPresent) - { - int LanguageDescriptor = buffer.ReadBits(24); - } - int bInfoTextPresent = buffer.ReadBits(1); - if (1 == bInfoTextPresent) - { - int nuInfoTextByteSize = buffer.ReadBits(10) + 1; - int[] InfoText = new int[nuInfoTextByteSize]; - for (int j = 0; j < nuInfoTextByteSize; j++) - { - InfoText[j] = buffer.ReadBits(8); - } - } - int nuBitResolution = buffer.ReadBits(5) + 1; - int nuMaxSampleRate = buffer.ReadBits(4); - int nuTotalNumChs = buffer.ReadBits(8) + 1; - int bOne2OneMapChannels2Speakers = buffer.ReadBits(1); - int nuSpkrActivityMask = 0; - if (1 == bOne2OneMapChannels2Speakers) - { - int bEmbeddedStereoFlag = 0; - if (nuTotalNumChs > 2) - { - bEmbeddedStereoFlag = buffer.ReadBits(1); - } - int bEmbeddedSixChFlag = 0; - if (nuTotalNumChs > 6) - { - bEmbeddedSixChFlag = buffer.ReadBits(1); - } - int bSpkrMaskEnabled = buffer.ReadBits(1); - int nuNumBits4SAMask = 0; - if (1 == bSpkrMaskEnabled) - { - nuNumBits4SAMask = buffer.ReadBits(2); - nuNumBits4SAMask = nuNumBits4SAMask * 4 + 4; - nuSpkrActivityMask = buffer.ReadBits(nuNumBits4SAMask); - } - // TODO... - } - stream.SampleRate = SampleRates[nuMaxSampleRate]; - stream.BitDepth = nuBitResolution; - - stream.LFE = 0; - if ((nuSpkrActivityMask & 0x8) == 0x8) - { - ++stream.LFE; - } - if ((nuSpkrActivityMask & 0x1000) == 0x1000) - { - ++stream.LFE; - } - stream.ChannelCount = nuTotalNumChs - stream.LFE; - } - if (nuNumAssets > 1) - { - // TODO... - break; - } - } - - // TODO - if (stream.CoreStream != null) - { - var coreStream = (TSAudioStream)stream.CoreStream; - if (coreStream.AudioMode == TSAudioMode.Extended && - stream.ChannelCount == 5) - { - stream.AudioMode = TSAudioMode.Extended; - } - /* - if (coreStream.DialNorm != 0) - { - stream.DialNorm = coreStream.DialNorm; - } - */ - } - - if (stream.StreamType == TSStreamType.DTS_HD_MASTER_AUDIO) - { - stream.IsVBR = true; - stream.IsInitialized = true; - } - else if (bitrate > 0) - { - stream.IsVBR = false; - stream.BitRate = bitrate; - if (stream.CoreStream != null) - { - stream.BitRate += stream.CoreStream.BitRate; - stream.IsInitialized = true; - } - stream.IsInitialized = (stream.BitRate > 0 ? true : false); - } - } - } -} diff --git a/BDInfo/TSCodecLPCM.cs b/BDInfo/TSCodecLPCM.cs deleted file mode 100644 index 5709d8689..000000000 --- a/BDInfo/TSCodecLPCM.cs +++ /dev/null @@ -1,123 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecLPCM - { - public static void Scan( - TSAudioStream stream, - TSStreamBuffer buffer, - ref string tag) - { - if (stream.IsInitialized) return; - - byte[] header = buffer.ReadBytes(4); - int flags = (header[2] << 8) + header[3]; - - switch ((flags & 0xF000) >> 12) - { - case 1: // 1/0/0 - stream.ChannelCount = 1; - stream.LFE = 0; - break; - case 3: // 2/0/0 - stream.ChannelCount = 2; - stream.LFE = 0; - break; - case 4: // 3/0/0 - stream.ChannelCount = 3; - stream.LFE = 0; - break; - case 5: // 2/1/0 - stream.ChannelCount = 3; - stream.LFE = 0; - break; - case 6: // 3/1/0 - stream.ChannelCount = 4; - stream.LFE = 0; - break; - case 7: // 2/2/0 - stream.ChannelCount = 4; - stream.LFE = 0; - break; - case 8: // 3/2/0 - stream.ChannelCount = 5; - stream.LFE = 0; - break; - case 9: // 3/2/1 - stream.ChannelCount = 5; - stream.LFE = 1; - break; - case 10: // 3/4/0 - stream.ChannelCount = 7; - stream.LFE = 0; - break; - case 11: // 3/4/1 - stream.ChannelCount = 7; - stream.LFE = 1; - break; - default: - stream.ChannelCount = 0; - stream.LFE = 0; - break; - } - - switch ((flags & 0xC0) >> 6) - { - case 1: - stream.BitDepth = 16; - break; - case 2: - stream.BitDepth = 20; - break; - case 3: - stream.BitDepth = 24; - break; - default: - stream.BitDepth = 0; - break; - } - - switch ((flags & 0xF00) >> 8) - { - case 1: - stream.SampleRate = 48000; - break; - case 4: - stream.SampleRate = 96000; - break; - case 5: - stream.SampleRate = 192000; - break; - default: - stream.SampleRate = 0; - break; - } - - stream.BitRate = (uint) - (stream.SampleRate * stream.BitDepth * - (stream.ChannelCount + stream.LFE)); - - stream.IsVBR = false; - stream.IsInitialized = true; - } - } -} diff --git a/BDInfo/TSCodecMPEG2.cs b/BDInfo/TSCodecMPEG2.cs deleted file mode 100644 index 8bcd07d02..000000000 --- a/BDInfo/TSCodecMPEG2.cs +++ /dev/null @@ -1,208 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -#undef DEBUG - - -namespace BDInfo -{ - public abstract class TSCodecMPEG2 - { - public static void Scan( - TSVideoStream stream, - TSStreamBuffer buffer, - ref string tag) - { - int parse = 0; - int pictureParse = 0; - int sequenceHeaderParse = 0; - int extensionParse = 0; - int sequenceExtensionParse = 0; - - for (int i = 0; i < buffer.Length; i++) - { - parse = (parse << 8) + buffer.ReadByte(); - - if (parse == 0x00000100) - { - pictureParse = 2; - } - else if (parse == 0x000001B3) - { - sequenceHeaderParse = 7; - } - else if (sequenceHeaderParse > 0) - { - --sequenceHeaderParse; - switch (sequenceHeaderParse) - { -#if DEBUG - case 6: - break; - - case 5: - break; - - case 4: - stream.Width = - (int)((parse & 0xFFF000) >> 12); - stream.Height = - (int)(parse & 0xFFF); - break; - - case 3: - stream.AspectRatio = - (TSAspectRatio)((parse & 0xF0) >> 4); - - switch ((parse & 0xF0) >> 4) - { - case 0: // Forbidden - break; - case 1: // Square - break; - case 2: // 4:3 - break; - case 3: // 16:9 - break; - case 4: // 2.21:1 - break; - default: // Reserved - break; - } - - switch (parse & 0xF) - { - case 0: // Forbidden - break; - case 1: // 23.976 - stream.FrameRateEnumerator = 24000; - stream.FrameRateDenominator = 1001; - break; - case 2: // 24 - stream.FrameRateEnumerator = 24000; - stream.FrameRateDenominator = 1000; - break; - case 3: // 25 - stream.FrameRateEnumerator = 25000; - stream.FrameRateDenominator = 1000; - break; - case 4: // 29.97 - stream.FrameRateEnumerator = 30000; - stream.FrameRateDenominator = 1001; - break; - case 5: // 30 - stream.FrameRateEnumerator = 30000; - stream.FrameRateDenominator = 1000; - break; - case 6: // 50 - stream.FrameRateEnumerator = 50000; - stream.FrameRateDenominator = 1000; - break; - case 7: // 59.94 - stream.FrameRateEnumerator = 60000; - stream.FrameRateDenominator = 1001; - break; - case 8: // 60 - stream.FrameRateEnumerator = 60000; - stream.FrameRateDenominator = 1000; - break; - default: // Reserved - stream.FrameRateEnumerator = 0; - stream.FrameRateDenominator = 0; - break; - } - break; - - case 2: - break; - - case 1: - break; -#endif - - case 0: -#if DEBUG - stream.BitRate = - (((parse & 0xFFFFC0) >> 6) * 200); -#endif - stream.IsVBR = true; - stream.IsInitialized = true; - break; - } - } - else if (pictureParse > 0) - { - --pictureParse; - if (pictureParse == 0) - { - switch ((parse & 0x38) >> 3) - { - case 1: - tag = "I"; - break; - case 2: - tag = "P"; - break; - case 3: - tag = "B"; - break; - default: - break; - } - if (stream.IsInitialized) return; - } - } - else if (parse == 0x000001B5) - { - extensionParse = 1; - } - else if (extensionParse > 0) - { - --extensionParse; - if (extensionParse == 0) - { - if ((parse & 0xF0) == 0x10) - { - sequenceExtensionParse = 1; - } - } - } - else if (sequenceExtensionParse > 0) - { - --sequenceExtensionParse; -#if DEBUG - if (sequenceExtensionParse == 0) - { - uint sequenceExtension = - ((parse & 0x8) >> 3); - if (sequenceExtension == 0) - { - stream.IsInterlaced = true; - } - else - { - stream.IsInterlaced = false; - } - } -#endif - } - } - } - } -} diff --git a/BDInfo/TSCodecMVC.cs b/BDInfo/TSCodecMVC.cs deleted file mode 100644 index abff0c1b0..000000000 --- a/BDInfo/TSCodecMVC.cs +++ /dev/null @@ -1,36 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - // TODO: Do something more interesting here... - - public abstract class TSCodecMVC - { - public static void Scan( - TSVideoStream stream, - TSStreamBuffer buffer, - ref string tag) - { - stream.IsVBR = true; - stream.IsInitialized = true; - } - } -} diff --git a/BDInfo/TSCodecTrueHD.cs b/BDInfo/TSCodecTrueHD.cs deleted file mode 100644 index 5e81e162c..000000000 --- a/BDInfo/TSCodecTrueHD.cs +++ /dev/null @@ -1,186 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecTrueHD - { - public static void Scan( - TSAudioStream stream, - TSStreamBuffer buffer, - ref string tag) - { - if (stream.IsInitialized && - stream.CoreStream != null && - stream.CoreStream.IsInitialized) return; - - bool syncFound = false; - uint sync = 0; - for (int i = 0; i < buffer.Length; i++) - { - sync = (sync << 8) + buffer.ReadByte(); - if (sync == 0xF8726FBA) - { - syncFound = true; - break; - } - } - - if (!syncFound) - { - tag = "CORE"; - if (stream.CoreStream == null) - { - stream.CoreStream = new TSAudioStream(); - stream.CoreStream.StreamType = TSStreamType.AC3_AUDIO; - } - if (!stream.CoreStream.IsInitialized) - { - buffer.BeginRead(); - TSCodecAC3.Scan(stream.CoreStream, buffer, ref tag); - } - return; - } - - tag = "HD"; - int ratebits = buffer.ReadBits(4); - if (ratebits != 0xF) - { - stream.SampleRate = - (((ratebits & 8) > 0 ? 44100 : 48000) << (ratebits & 7)); - } - int temp1 = buffer.ReadBits(8); - int channels_thd_stream1 = buffer.ReadBits(5); - int temp2 = buffer.ReadBits(2); - - stream.ChannelCount = 0; - stream.LFE = 0; - int c_LFE2 = buffer.ReadBits(1); - if (c_LFE2 == 1) - { - stream.LFE += 1; - } - int c_Cvh = buffer.ReadBits(1); - if (c_Cvh == 1) - { - stream.ChannelCount += 1; - } - int c_LRw = buffer.ReadBits(1); - if (c_LRw == 1) - { - stream.ChannelCount += 2; - } - int c_LRsd = buffer.ReadBits(1); - if (c_LRsd == 1) - { - stream.ChannelCount += 2; - } - int c_Ts = buffer.ReadBits(1); - if (c_Ts == 1) - { - stream.ChannelCount += 1; - } - int c_Cs = buffer.ReadBits(1); - if (c_Cs == 1) - { - stream.ChannelCount += 1; - } - int c_LRrs = buffer.ReadBits(1); - if (c_LRrs == 1) - { - stream.ChannelCount += 2; - } - int c_LRc = buffer.ReadBits(1); - if (c_LRc == 1) - { - stream.ChannelCount += 2; - } - int c_LRvh = buffer.ReadBits(1); - if (c_LRvh == 1) - { - stream.ChannelCount += 2; - } - int c_LRs = buffer.ReadBits(1); - if (c_LRs == 1) - { - stream.ChannelCount += 2; - } - int c_LFE = buffer.ReadBits(1); - if (c_LFE == 1) - { - stream.LFE += 1; - } - int c_C = buffer.ReadBits(1); - if (c_C == 1) - { - stream.ChannelCount += 1; - } - int c_LR = buffer.ReadBits(1); - if (c_LR == 1) - { - stream.ChannelCount += 2; - } - - int access_unit_size = 40 << (ratebits & 7); - int access_unit_size_pow2 = 64 << (ratebits & 7); - - int a1 = buffer.ReadBits(16); - int a2 = buffer.ReadBits(16); - int a3 = buffer.ReadBits(16); - - int is_vbr = buffer.ReadBits(1); - int peak_bitrate = buffer.ReadBits(15); - peak_bitrate = (peak_bitrate * stream.SampleRate) >> 4; - - double peak_bitdepth = - (double)peak_bitrate / - (stream.ChannelCount + stream.LFE) / - stream.SampleRate; - if (peak_bitdepth > 14) - { - stream.BitDepth = 24; - } - else - { - stream.BitDepth = 16; - } - -#if DEBUG - System.Diagnostics.Debug.WriteLine(string.Format( - "{0}\t{1}\t{2:F2}", - stream.PID, peak_bitrate, peak_bitdepth)); -#endif - /* - // TODO: Get THD dialnorm from metadata - if (stream.CoreStream != null) - { - TSAudioStream coreStream = (TSAudioStream)stream.CoreStream; - if (coreStream.DialNorm != 0) - { - stream.DialNorm = coreStream.DialNorm; - } - } - */ - - stream.IsVBR = true; - stream.IsInitialized = true; - } - } -} diff --git a/BDInfo/TSCodecVC1.cs b/BDInfo/TSCodecVC1.cs deleted file mode 100644 index e2fbbf692..000000000 --- a/BDInfo/TSCodecVC1.cs +++ /dev/null @@ -1,131 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - - -namespace BDInfo -{ - public abstract class TSCodecVC1 - { - public static void Scan( - TSVideoStream stream, - TSStreamBuffer buffer, - ref string tag) - { - int parse = 0; - byte frameHeaderParse = 0; - byte sequenceHeaderParse = 0; - bool isInterlaced = false; - - for (int i = 0; i < buffer.Length; i++) - { - parse = (parse << 8) + buffer.ReadByte(); - - if (parse == 0x0000010D) - { - frameHeaderParse = 4; - } - else if (frameHeaderParse > 0) - { - --frameHeaderParse; - if (frameHeaderParse == 0) - { - uint pictureType = 0; - if (isInterlaced) - { - if ((parse & 0x80000000) == 0) - { - pictureType = - (uint)((parse & 0x78000000) >> 13); - } - else - { - pictureType = - (uint)((parse & 0x3c000000) >> 12); - } - } - else - { - pictureType = - (uint)((parse & 0xf0000000) >> 14); - } - - if ((pictureType & 0x20000) == 0) - { - tag = "P"; - } - else if ((pictureType & 0x10000) == 0) - { - tag = "B"; - } - else if ((pictureType & 0x8000) == 0) - { - tag = "I"; - } - else if ((pictureType & 0x4000) == 0) - { - tag = "BI"; - } - else - { - tag = null; - } - if (stream.IsInitialized) return; - } - } - else if (parse == 0x0000010F) - { - sequenceHeaderParse = 6; - } - else if (sequenceHeaderParse > 0) - { - --sequenceHeaderParse; - switch (sequenceHeaderParse) - { - case 5: - int profileLevel = ((parse & 0x38) >> 3); - if (((parse & 0xC0) >> 6) == 3) - { - stream.EncodingProfile = string.Format( - "Advanced Profile {0}", profileLevel); - } - else - { - stream.EncodingProfile = string.Format( - "Main Profile {0}", profileLevel); - } - break; - - case 0: - if (((parse & 0x40) >> 6) > 0) - { - isInterlaced = true; - } - else - { - isInterlaced = false; - } - break; - } - stream.IsVBR = true; - stream.IsInitialized = true; - } - } - } - } -} diff --git a/BDInfo/TSInterleavedFile.cs b/BDInfo/TSInterleavedFile.cs deleted file mode 100644 index 0f35cfb2a..000000000 --- a/BDInfo/TSInterleavedFile.cs +++ /dev/null @@ -1,37 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -using MediaBrowser.Model.IO; - -// TODO: Do more interesting things here... - -namespace BDInfo -{ - public class TSInterleavedFile - { - public FileSystemMetadata FileInfo = null; - public string Name = null; - - public TSInterleavedFile(FileSystemMetadata fileInfo) - { - FileInfo = fileInfo; - Name = fileInfo.Name.ToUpper(); - } - } -} diff --git a/BDInfo/TSPlaylistFile.cs b/BDInfo/TSPlaylistFile.cs deleted file mode 100644 index 1cc629b1d..000000000 --- a/BDInfo/TSPlaylistFile.cs +++ /dev/null @@ -1,1282 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -#undef DEBUG -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using MediaBrowser.Model.IO; - -namespace BDInfo -{ - public class TSPlaylistFile - { - private FileSystemMetadata FileInfo = null; - public string FileType = null; - public bool IsInitialized = false; - public string Name = null; - public BDROM BDROM = null; - public bool HasHiddenTracks = false; - public bool HasLoops = false; - public bool IsCustom = false; - - public List Chapters = new List(); - - public Dictionary Streams = - new Dictionary(); - public Dictionary PlaylistStreams = - new Dictionary(); - public List StreamClips = - new List(); - public List> AngleStreams = - new List>(); - public List> AngleClips = - new List>(); - public int AngleCount = 0; - - public List SortedStreams = - new List(); - public List VideoStreams = - new List(); - public List AudioStreams = - new List(); - public List TextStreams = - new List(); - public List GraphicsStreams = - new List(); - - public TSPlaylistFile(BDROM bdrom, - FileSystemMetadata fileInfo) - { - BDROM = bdrom; - FileInfo = fileInfo; - Name = fileInfo.Name.ToUpper(); - } - - public TSPlaylistFile(BDROM bdrom, - string name, - List clips) - { - BDROM = bdrom; - Name = name; - IsCustom = true; - foreach (var clip in clips) - { - var newClip = new TSStreamClip( - clip.StreamFile, clip.StreamClipFile); - - newClip.Name = clip.Name; - newClip.TimeIn = clip.TimeIn; - newClip.TimeOut = clip.TimeOut; - newClip.Length = newClip.TimeOut - newClip.TimeIn; - newClip.RelativeTimeIn = TotalLength; - newClip.RelativeTimeOut = newClip.RelativeTimeIn + newClip.Length; - newClip.AngleIndex = clip.AngleIndex; - newClip.Chapters.Add(clip.TimeIn); - StreamClips.Add(newClip); - - if (newClip.AngleIndex > AngleCount) - { - AngleCount = newClip.AngleIndex; - } - if (newClip.AngleIndex == 0) - { - Chapters.Add(newClip.RelativeTimeIn); - } - } - LoadStreamClips(); - IsInitialized = true; - } - - public override string ToString() - { - return Name; - } - - public ulong InterleavedFileSize - { - get - { - ulong size = 0; - foreach (var clip in StreamClips) - { - size += clip.InterleavedFileSize; - } - return size; - } - } - public ulong FileSize - { - get - { - ulong size = 0; - foreach (var clip in StreamClips) - { - size += clip.FileSize; - } - return size; - } - } - public double TotalLength - { - get - { - double length = 0; - foreach (var clip in StreamClips) - { - if (clip.AngleIndex == 0) - { - length += clip.Length; - } - } - return length; - } - } - - public double TotalAngleLength - { - get - { - double length = 0; - foreach (var clip in StreamClips) - { - length += clip.Length; - } - return length; - } - } - - public ulong TotalSize - { - get - { - ulong size = 0; - foreach (var clip in StreamClips) - { - if (clip.AngleIndex == 0) - { - size += clip.PacketSize; - } - } - return size; - } - } - - public ulong TotalAngleSize - { - get - { - ulong size = 0; - foreach (var clip in StreamClips) - { - size += clip.PacketSize; - } - return size; - } - } - - public ulong TotalBitRate - { - get - { - if (TotalLength > 0) - { - return (ulong)Math.Round(((TotalSize * 8.0) / TotalLength)); - } - return 0; - } - } - - public ulong TotalAngleBitRate - { - get - { - if (TotalAngleLength > 0) - { - return (ulong)Math.Round(((TotalAngleSize * 8.0) / TotalAngleLength)); - } - return 0; - } - } - - public void Scan( - Dictionary streamFiles, - Dictionary streamClipFiles) - { - Stream fileStream = null; - BinaryReader fileReader = null; - - try - { - Streams.Clear(); - StreamClips.Clear(); - - fileStream = File.OpenRead(FileInfo.FullName); - fileReader = new BinaryReader(fileStream); - - byte[] data = new byte[fileStream.Length]; - int dataLength = fileReader.Read(data, 0, data.Length); - - int pos = 0; - - FileType = ReadString(data, 8, ref pos); - if (FileType != "MPLS0100" && FileType != "MPLS0200") - { - throw new Exception(string.Format( - "Playlist {0} has an unknown file type {1}.", - FileInfo.Name, FileType)); - } - - int playlistOffset = ReadInt32(data, ref pos); - int chaptersOffset = ReadInt32(data, ref pos); - int extensionsOffset = ReadInt32(data, ref pos); - - pos = playlistOffset; - - int playlistLength = ReadInt32(data, ref pos); - int playlistReserved = ReadInt16(data, ref pos); - int itemCount = ReadInt16(data, ref pos); - int subitemCount = ReadInt16(data, ref pos); - - var chapterClips = new List(); - for (int itemIndex = 0; itemIndex < itemCount; itemIndex++) - { - int itemStart = pos; - int itemLength = ReadInt16(data, ref pos); - string itemName = ReadString(data, 5, ref pos); - string itemType = ReadString(data, 4, ref pos); - - TSStreamFile streamFile = null; - string streamFileName = string.Format( - "{0}.M2TS", itemName); - if (streamFiles.ContainsKey(streamFileName)) - { - streamFile = streamFiles[streamFileName]; - } - if (streamFile == null) - { - // Error condition - } - - TSStreamClipFile streamClipFile = null; - string streamClipFileName = string.Format( - "{0}.CLPI", itemName); - if (streamClipFiles.ContainsKey(streamClipFileName)) - { - streamClipFile = streamClipFiles[streamClipFileName]; - } - if (streamClipFile == null) - { - throw new Exception(string.Format( - "Playlist {0} referenced missing file {1}.", - FileInfo.Name, streamFileName)); - } - - pos += 1; - int multiangle = (data[pos] >> 4) & 0x01; - int condition = data[pos] & 0x0F; - pos += 2; - - int inTime = ReadInt32(data, ref pos); - if (inTime < 0) inTime &= 0x7FFFFFFF; - double timeIn = (double)inTime / 45000; - - int outTime = ReadInt32(data, ref pos); - if (outTime < 0) outTime &= 0x7FFFFFFF; - double timeOut = (double)outTime / 45000; - - var streamClip = new TSStreamClip( - streamFile, streamClipFile); - - streamClip.Name = streamFileName; //TODO - streamClip.TimeIn = timeIn; - streamClip.TimeOut = timeOut; - streamClip.Length = streamClip.TimeOut - streamClip.TimeIn; - streamClip.RelativeTimeIn = TotalLength; - streamClip.RelativeTimeOut = streamClip.RelativeTimeIn + streamClip.Length; - StreamClips.Add(streamClip); - chapterClips.Add(streamClip); - - pos += 12; - if (multiangle > 0) - { - int angles = data[pos]; - pos += 2; - for (int angle = 0; angle < angles - 1; angle++) - { - string angleName = ReadString(data, 5, ref pos); - string angleType = ReadString(data, 4, ref pos); - pos += 1; - - TSStreamFile angleFile = null; - string angleFileName = string.Format( - "{0}.M2TS", angleName); - if (streamFiles.ContainsKey(angleFileName)) - { - angleFile = streamFiles[angleFileName]; - } - if (angleFile == null) - { - throw new Exception(string.Format( - "Playlist {0} referenced missing angle file {1}.", - FileInfo.Name, angleFileName)); - } - - TSStreamClipFile angleClipFile = null; - string angleClipFileName = string.Format( - "{0}.CLPI", angleName); - if (streamClipFiles.ContainsKey(angleClipFileName)) - { - angleClipFile = streamClipFiles[angleClipFileName]; - } - if (angleClipFile == null) - { - throw new Exception(string.Format( - "Playlist {0} referenced missing angle file {1}.", - FileInfo.Name, angleClipFileName)); - } - - var angleClip = - new TSStreamClip(angleFile, angleClipFile); - angleClip.AngleIndex = angle + 1; - angleClip.TimeIn = streamClip.TimeIn; - angleClip.TimeOut = streamClip.TimeOut; - angleClip.RelativeTimeIn = streamClip.RelativeTimeIn; - angleClip.RelativeTimeOut = streamClip.RelativeTimeOut; - angleClip.Length = streamClip.Length; - StreamClips.Add(angleClip); - } - if (angles - 1 > AngleCount) AngleCount = angles - 1; - } - - int streamInfoLength = ReadInt16(data, ref pos); - pos += 2; - int streamCountVideo = data[pos++]; - int streamCountAudio = data[pos++]; - int streamCountPG = data[pos++]; - int streamCountIG = data[pos++]; - int streamCountSecondaryAudio = data[pos++]; - int streamCountSecondaryVideo = data[pos++]; - int streamCountPIP = data[pos++]; - pos += 5; - -#if DEBUG - Debug.WriteLine(string.Format( - "{0} : {1} -> V:{2} A:{3} PG:{4} IG:{5} 2A:{6} 2V:{7} PIP:{8}", - Name, streamFileName, streamCountVideo, streamCountAudio, streamCountPG, streamCountIG, - streamCountSecondaryAudio, streamCountSecondaryVideo, streamCountPIP)); -#endif - - for (int i = 0; i < streamCountVideo; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - } - for (int i = 0; i < streamCountAudio; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - } - for (int i = 0; i < streamCountPG; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - } - for (int i = 0; i < streamCountIG; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - } - for (int i = 0; i < streamCountSecondaryAudio; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - pos += 2; - } - for (int i = 0; i < streamCountSecondaryVideo; i++) - { - var stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - pos += 6; - } - /* - * TODO - * - for (int i = 0; i < streamCountPIP; i++) - { - TSStream stream = CreatePlaylistStream(data, ref pos); - if (stream != null) PlaylistStreams[stream.PID] = stream; - } - */ - - pos += itemLength - (pos - itemStart) + 2; - } - - pos = chaptersOffset + 4; - - int chapterCount = ReadInt16(data, ref pos); - - for (int chapterIndex = 0; - chapterIndex < chapterCount; - chapterIndex++) - { - int chapterType = data[pos + 1]; - - if (chapterType == 1) - { - int streamFileIndex = - ((int)data[pos + 2] << 8) + data[pos + 3]; - - long chapterTime = - ((long)data[pos + 4] << 24) + - ((long)data[pos + 5] << 16) + - ((long)data[pos + 6] << 8) + - ((long)data[pos + 7]); - - var streamClip = chapterClips[streamFileIndex]; - - double chapterSeconds = (double)chapterTime / 45000; - - double relativeSeconds = - chapterSeconds - - streamClip.TimeIn + - streamClip.RelativeTimeIn; - - // TODO: Ignore short last chapter? - if (TotalLength - relativeSeconds > 1.0) - { - streamClip.Chapters.Add(chapterSeconds); - this.Chapters.Add(relativeSeconds); - } - } - else - { - // TODO: Handle other chapter types? - } - pos += 14; - } - } - finally - { - if (fileReader != null) - { - fileReader.Dispose(); - } - if (fileStream != null) - { - fileStream.Dispose(); - } - } - } - - public void Initialize() - { - LoadStreamClips(); - - var clipTimes = new Dictionary>(); - foreach (var clip in StreamClips) - { - if (clip.AngleIndex == 0) - { - if (clipTimes.ContainsKey(clip.Name)) - { - if (clipTimes[clip.Name].Contains(clip.TimeIn)) - { - HasLoops = true; - break; - } - else - { - clipTimes[clip.Name].Add(clip.TimeIn); - } - } - else - { - clipTimes[clip.Name] = new List { clip.TimeIn }; - } - } - } - ClearBitrates(); - IsInitialized = true; - } - - protected TSStream CreatePlaylistStream(byte[] data, ref int pos) - { - TSStream stream = null; - - int start = pos; - - int headerLength = data[pos++]; - int headerPos = pos; - int headerType = data[pos++]; - - int pid = 0; - int subpathid = 0; - int subclipid = 0; - - switch (headerType) - { - case 1: - pid = ReadInt16(data, ref pos); - break; - case 2: - subpathid = data[pos++]; - subclipid = data[pos++]; - pid = ReadInt16(data, ref pos); - break; - case 3: - subpathid = data[pos++]; - pid = ReadInt16(data, ref pos); - break; - case 4: - subpathid = data[pos++]; - subclipid = data[pos++]; - pid = ReadInt16(data, ref pos); - break; - default: - break; - } - - pos = headerPos + headerLength; - - int streamLength = data[pos++]; - int streamPos = pos; - - var streamType = (TSStreamType)data[pos++]; - switch (streamType) - { - case TSStreamType.MVC_VIDEO: - // TODO - break; - - case TSStreamType.AVC_VIDEO: - case TSStreamType.MPEG1_VIDEO: - case TSStreamType.MPEG2_VIDEO: - case TSStreamType.VC1_VIDEO: - - var videoFormat = (TSVideoFormat) - (data[pos] >> 4); - var frameRate = (TSFrameRate) - (data[pos] & 0xF); - var aspectRatio = (TSAspectRatio) - (data[pos + 1] >> 4); - - stream = new TSVideoStream(); - ((TSVideoStream)stream).VideoFormat = videoFormat; - ((TSVideoStream)stream).AspectRatio = aspectRatio; - ((TSVideoStream)stream).FrameRate = frameRate; - -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2} {3} {4}", - pid, - streamType, - videoFormat, - frameRate, - aspectRatio)); -#endif - - break; - - case TSStreamType.AC3_AUDIO: - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - case TSStreamType.AC3_TRUE_HD_AUDIO: - case TSStreamType.DTS_AUDIO: - case TSStreamType.DTS_HD_AUDIO: - case TSStreamType.DTS_HD_MASTER_AUDIO: - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - case TSStreamType.LPCM_AUDIO: - case TSStreamType.MPEG1_AUDIO: - case TSStreamType.MPEG2_AUDIO: - - int audioFormat = ReadByte(data, ref pos); - - var channelLayout = (TSChannelLayout) - (audioFormat >> 4); - var sampleRate = (TSSampleRate) - (audioFormat & 0xF); - - string audioLanguage = ReadString(data, 3, ref pos); - - stream = new TSAudioStream(); - ((TSAudioStream)stream).ChannelLayout = channelLayout; - ((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate); - ((TSAudioStream)stream).LanguageCode = audioLanguage; - -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2} {3} {4}", - pid, - streamType, - audioLanguage, - channelLayout, - sampleRate)); -#endif - - break; - - case TSStreamType.INTERACTIVE_GRAPHICS: - case TSStreamType.PRESENTATION_GRAPHICS: - - string graphicsLanguage = ReadString(data, 3, ref pos); - - stream = new TSGraphicsStream(); - ((TSGraphicsStream)stream).LanguageCode = graphicsLanguage; - - if (data[pos] != 0) - { - } - -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2}", - pid, - streamType, - graphicsLanguage)); -#endif - - break; - - case TSStreamType.SUBTITLE: - - int code = ReadByte(data, ref pos); // TODO - string textLanguage = ReadString(data, 3, ref pos); - - stream = new TSTextStream(); - ((TSTextStream)stream).LanguageCode = textLanguage; - -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2}", - pid, - streamType, - textLanguage)); -#endif - - break; - - default: - break; - } - - pos = streamPos + streamLength; - - if (stream != null) - { - stream.PID = (ushort)pid; - stream.StreamType = streamType; - } - - return stream; - } - - private void LoadStreamClips() - { - AngleClips.Clear(); - if (AngleCount > 0) - { - for (int angleIndex = 0; angleIndex < AngleCount; angleIndex++) - { - AngleClips.Add(new Dictionary()); - } - } - - TSStreamClip referenceClip = null; - if (StreamClips.Count > 0) - { - referenceClip = StreamClips[0]; - } - foreach (var clip in StreamClips) - { - if (clip.StreamClipFile.Streams.Count > referenceClip.StreamClipFile.Streams.Count) - { - referenceClip = clip; - } - else if (clip.Length > referenceClip.Length) - { - referenceClip = clip; - } - if (AngleCount > 0) - { - if (clip.AngleIndex == 0) - { - for (int angleIndex = 0; angleIndex < AngleCount; angleIndex++) - { - AngleClips[angleIndex][clip.RelativeTimeIn] = clip; - } - } - else - { - AngleClips[clip.AngleIndex - 1][clip.RelativeTimeIn] = clip; - } - } - } - - foreach (var clipStream - in referenceClip.StreamClipFile.Streams.Values) - { - if (!Streams.ContainsKey(clipStream.PID)) - { - var stream = clipStream.Clone(); - Streams[clipStream.PID] = stream; - - if (!IsCustom && !PlaylistStreams.ContainsKey(stream.PID)) - { - stream.IsHidden = true; - HasHiddenTracks = true; - } - - if (stream.IsVideoStream) - { - VideoStreams.Add((TSVideoStream)stream); - } - else if (stream.IsAudioStream) - { - AudioStreams.Add((TSAudioStream)stream); - } - else if (stream.IsGraphicsStream) - { - GraphicsStreams.Add((TSGraphicsStream)stream); - } - else if (stream.IsTextStream) - { - TextStreams.Add((TSTextStream)stream); - } - } - } - - if (referenceClip.StreamFile != null) - { - // TODO: Better way to add this in? - if (BDInfoSettings.EnableSSIF && - referenceClip.StreamFile.InterleavedFile != null && - referenceClip.StreamFile.Streams.ContainsKey(4114) && - !Streams.ContainsKey(4114)) - { - var stream = referenceClip.StreamFile.Streams[4114].Clone(); - Streams[4114] = stream; - if (stream.IsVideoStream) - { - VideoStreams.Add((TSVideoStream)stream); - } - } - - foreach (var clipStream - in referenceClip.StreamFile.Streams.Values) - { - if (Streams.ContainsKey(clipStream.PID)) - { - var stream = Streams[clipStream.PID]; - - if (stream.StreamType != clipStream.StreamType) continue; - - if (clipStream.BitRate > stream.BitRate) - { - stream.BitRate = clipStream.BitRate; - } - stream.IsVBR = clipStream.IsVBR; - - if (stream.IsVideoStream && - clipStream.IsVideoStream) - { - ((TSVideoStream)stream).EncodingProfile = - ((TSVideoStream)clipStream).EncodingProfile; - } - else if (stream.IsAudioStream && - clipStream.IsAudioStream) - { - var audioStream = (TSAudioStream)stream; - var clipAudioStream = (TSAudioStream)clipStream; - - if (clipAudioStream.ChannelCount > audioStream.ChannelCount) - { - audioStream.ChannelCount = clipAudioStream.ChannelCount; - } - if (clipAudioStream.LFE > audioStream.LFE) - { - audioStream.LFE = clipAudioStream.LFE; - } - if (clipAudioStream.SampleRate > audioStream.SampleRate) - { - audioStream.SampleRate = clipAudioStream.SampleRate; - } - if (clipAudioStream.BitDepth > audioStream.BitDepth) - { - audioStream.BitDepth = clipAudioStream.BitDepth; - } - if (clipAudioStream.DialNorm < audioStream.DialNorm) - { - audioStream.DialNorm = clipAudioStream.DialNorm; - } - if (clipAudioStream.AudioMode != TSAudioMode.Unknown) - { - audioStream.AudioMode = clipAudioStream.AudioMode; - } - if (clipAudioStream.CoreStream != null && - audioStream.CoreStream == null) - { - audioStream.CoreStream = (TSAudioStream) - clipAudioStream.CoreStream.Clone(); - } - } - } - } - } - - for (int i = 0; i < AngleCount; i++) - { - AngleStreams.Add(new Dictionary()); - } - - if (!BDInfoSettings.KeepStreamOrder) - { - VideoStreams.Sort(CompareVideoStreams); - } - foreach (TSStream stream in VideoStreams) - { - SortedStreams.Add(stream); - for (int i = 0; i < AngleCount; i++) - { - var angleStream = stream.Clone(); - angleStream.AngleIndex = i + 1; - AngleStreams[i][angleStream.PID] = angleStream; - SortedStreams.Add(angleStream); - } - } - - if (!BDInfoSettings.KeepStreamOrder) - { - AudioStreams.Sort(CompareAudioStreams); - } - foreach (TSStream stream in AudioStreams) - { - SortedStreams.Add(stream); - } - - if (!BDInfoSettings.KeepStreamOrder) - { - GraphicsStreams.Sort(CompareGraphicsStreams); - } - foreach (TSStream stream in GraphicsStreams) - { - SortedStreams.Add(stream); - } - - if (!BDInfoSettings.KeepStreamOrder) - { - TextStreams.Sort(CompareTextStreams); - } - foreach (TSStream stream in TextStreams) - { - SortedStreams.Add(stream); - } - } - - public void ClearBitrates() - { - foreach (var clip in StreamClips) - { - clip.PayloadBytes = 0; - clip.PacketCount = 0; - clip.PacketSeconds = 0; - - if (clip.StreamFile != null) - { - foreach (var stream in clip.StreamFile.Streams.Values) - { - stream.PayloadBytes = 0; - stream.PacketCount = 0; - stream.PacketSeconds = 0; - } - - if (clip.StreamFile != null && - clip.StreamFile.StreamDiagnostics != null) - { - clip.StreamFile.StreamDiagnostics.Clear(); - } - } - } - - foreach (var stream in SortedStreams) - { - stream.PayloadBytes = 0; - stream.PacketCount = 0; - stream.PacketSeconds = 0; - } - } - - public bool IsValid - { - get - { - if (!IsInitialized) return false; - - if (BDInfoSettings.FilterShortPlaylists && - TotalLength < BDInfoSettings.FilterShortPlaylistsValue) - { - return false; - } - - if (HasLoops && - BDInfoSettings.FilterLoopingPlaylists) - { - return false; - } - - return true; - } - } - - public int CompareVideoStreams( - TSVideoStream x, - TSVideoStream y) - { - if (x == null && y == null) - { - return 0; - } - else if (x == null && y != null) - { - return 1; - } - else if (x != null && y == null) - { - return -1; - } - else - { - if (x.Height > y.Height) - { - return -1; - } - else if (y.Height > x.Height) - { - return 1; - } - else if (x.PID > y.PID) - { - return 1; - } - else if (y.PID > x.PID) - { - return -1; - } - else - { - return 0; - } - } - } - - public int CompareAudioStreams( - TSAudioStream x, - TSAudioStream y) - { - if (x == y) - { - return 0; - } - else if (x == null && y == null) - { - return 0; - } - else if (x == null && y != null) - { - return -1; - } - else if (x != null && y == null) - { - return 1; - } - else - { - if (x.ChannelCount > y.ChannelCount) - { - return -1; - } - else if (y.ChannelCount > x.ChannelCount) - { - return 1; - } - else - { - int sortX = GetStreamTypeSortIndex(x.StreamType); - int sortY = GetStreamTypeSortIndex(y.StreamType); - - if (sortX > sortY) - { - return -1; - } - else if (sortY > sortX) - { - return 1; - } - else - { - if (x.LanguageCode == "eng") - { - return -1; - } - else if (y.LanguageCode == "eng") - { - return 1; - } - else if (x.LanguageCode != y.LanguageCode) - { - return string.Compare( - x.LanguageName, y.LanguageName); - } - else if (x.PID < y.PID) - { - return -1; - } - else if (y.PID < x.PID) - { - return 1; - } - return 0; - } - } - } - } - - public int CompareTextStreams( - TSTextStream x, - TSTextStream y) - { - if (x == y) - { - return 0; - } - else if (x == null && y == null) - { - return 0; - } - else if (x == null && y != null) - { - return -1; - } - else if (x != null && y == null) - { - return 1; - } - else - { - if (x.LanguageCode == "eng") - { - return -1; - } - else if (y.LanguageCode == "eng") - { - return 1; - } - else - { - if (x.LanguageCode == y.LanguageCode) - { - if (x.PID > y.PID) - { - return 1; - } - else if (y.PID > x.PID) - { - return -1; - } - else - { - return 0; - } - } - else - { - return string.Compare( - x.LanguageName, y.LanguageName); - } - } - } - } - - private int CompareGraphicsStreams( - TSGraphicsStream x, - TSGraphicsStream y) - { - if (x == y) - { - return 0; - } - else if (x == null && y == null) - { - return 0; - } - else if (x == null && y != null) - { - return -1; - } - else if (x != null && y == null) - { - return 1; - } - else - { - int sortX = GetStreamTypeSortIndex(x.StreamType); - int sortY = GetStreamTypeSortIndex(y.StreamType); - - if (sortX > sortY) - { - return -1; - } - else if (sortY > sortX) - { - return 1; - } - else if (x.LanguageCode == "eng") - { - return -1; - } - else if (y.LanguageCode == "eng") - { - return 1; - } - else - { - if (x.LanguageCode == y.LanguageCode) - { - if (x.PID > y.PID) - { - return 1; - } - else if (y.PID > x.PID) - { - return -1; - } - else - { - return 0; - } - } - else - { - return string.Compare(x.LanguageName, y.LanguageName); - } - } - } - } - - private int GetStreamTypeSortIndex(TSStreamType streamType) - { - switch (streamType) - { - case TSStreamType.Unknown: - return 0; - case TSStreamType.MPEG1_VIDEO: - return 1; - case TSStreamType.MPEG2_VIDEO: - return 2; - case TSStreamType.AVC_VIDEO: - return 3; - case TSStreamType.VC1_VIDEO: - return 4; - case TSStreamType.MVC_VIDEO: - return 5; - - case TSStreamType.MPEG1_AUDIO: - return 1; - case TSStreamType.MPEG2_AUDIO: - return 2; - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - return 3; - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - return 4; - case TSStreamType.AC3_AUDIO: - return 5; - case TSStreamType.DTS_AUDIO: - return 6; - case TSStreamType.AC3_PLUS_AUDIO: - return 7; - case TSStreamType.DTS_HD_AUDIO: - return 8; - case TSStreamType.AC3_TRUE_HD_AUDIO: - return 9; - case TSStreamType.DTS_HD_MASTER_AUDIO: - return 10; - case TSStreamType.LPCM_AUDIO: - return 11; - - case TSStreamType.SUBTITLE: - return 1; - case TSStreamType.INTERACTIVE_GRAPHICS: - return 2; - case TSStreamType.PRESENTATION_GRAPHICS: - return 3; - - default: - return 0; - } - } - - protected string ReadString( - byte[] data, - int count, - ref int pos) - { - string val = Encoding.ASCII.GetString(data, pos, count); - - pos += count; - - return val; - } - - protected int ReadInt32( - byte[] data, - ref int pos) - { - int val = - ((int)data[pos] << 24) + - ((int)data[pos + 1] << 16) + - ((int)data[pos + 2] << 8) + - ((int)data[pos + 3]); - - pos += 4; - - return val; - } - - protected int ReadInt16( - byte[] data, - ref int pos) - { - int val = - ((int)data[pos] << 8) + - ((int)data[pos + 1]); - - pos += 2; - - return val; - } - - protected byte ReadByte( - byte[] data, - ref int pos) - { - return data[pos++]; - } - } -} diff --git a/BDInfo/TSStream.cs b/BDInfo/TSStream.cs deleted file mode 100644 index 3c30a8597..000000000 --- a/BDInfo/TSStream.cs +++ /dev/null @@ -1,780 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -using System; -using System.Collections.Generic; - -namespace BDInfo -{ - public enum TSStreamType : byte - { - Unknown = 0, - MPEG1_VIDEO = 0x01, - MPEG2_VIDEO = 0x02, - AVC_VIDEO = 0x1b, - MVC_VIDEO = 0x20, - VC1_VIDEO = 0xea, - MPEG1_AUDIO = 0x03, - MPEG2_AUDIO = 0x04, - LPCM_AUDIO = 0x80, - AC3_AUDIO = 0x81, - AC3_PLUS_AUDIO = 0x84, - AC3_PLUS_SECONDARY_AUDIO = 0xA1, - AC3_TRUE_HD_AUDIO = 0x83, - DTS_AUDIO = 0x82, - DTS_HD_AUDIO = 0x85, - DTS_HD_SECONDARY_AUDIO = 0xA2, - DTS_HD_MASTER_AUDIO = 0x86, - PRESENTATION_GRAPHICS = 0x90, - INTERACTIVE_GRAPHICS = 0x91, - SUBTITLE = 0x92 - } - - public enum TSVideoFormat : byte - { - Unknown = 0, - VIDEOFORMAT_480i = 1, - VIDEOFORMAT_576i = 2, - VIDEOFORMAT_480p = 3, - VIDEOFORMAT_1080i = 4, - VIDEOFORMAT_720p = 5, - VIDEOFORMAT_1080p = 6, - VIDEOFORMAT_576p = 7, - } - - public enum TSFrameRate : byte - { - Unknown = 0, - FRAMERATE_23_976 = 1, - FRAMERATE_24 = 2, - FRAMERATE_25 = 3, - FRAMERATE_29_97 = 4, - FRAMERATE_50 = 6, - FRAMERATE_59_94 = 7 - } - - public enum TSChannelLayout : byte - { - Unknown = 0, - CHANNELLAYOUT_MONO = 1, - CHANNELLAYOUT_STEREO = 3, - CHANNELLAYOUT_MULTI = 6, - CHANNELLAYOUT_COMBO = 12 - } - - public enum TSSampleRate : byte - { - Unknown = 0, - SAMPLERATE_48 = 1, - SAMPLERATE_96 = 4, - SAMPLERATE_192 = 5, - SAMPLERATE_48_192 = 12, - SAMPLERATE_48_96 = 14 - } - - public enum TSAspectRatio - { - Unknown = 0, - ASPECT_4_3 = 2, - ASPECT_16_9 = 3, - ASPECT_2_21 = 4 - } - - public class TSDescriptor - { - public byte Name; - public byte[] Value; - - public TSDescriptor(byte name, byte length) - { - Name = name; - Value = new byte[length]; - } - - public TSDescriptor Clone() - { - var descriptor = - new TSDescriptor(Name, (byte)Value.Length); - Value.CopyTo(descriptor.Value, 0); - return descriptor; - } - } - - public abstract class TSStream - { - public TSStream() - { - } - - public override string ToString() - { - return string.Format("{0} ({1})", CodecShortName, PID); - } - - public ushort PID; - public TSStreamType StreamType; - public List Descriptors = null; - public long BitRate = 0; - public long ActiveBitRate = 0; - public bool IsVBR = false; - public bool IsInitialized = false; - public string LanguageName; - public bool IsHidden = false; - - public ulong PayloadBytes = 0; - public ulong PacketCount = 0; - public double PacketSeconds = 0; - public int AngleIndex = 0; - - public ulong PacketSize => PacketCount * 192; - - private string _LanguageCode; - public string LanguageCode - { - get => _LanguageCode; - set - { - _LanguageCode = value; - LanguageName = LanguageCodes.GetName(value); - } - } - - public bool IsVideoStream - { - get - { - switch (StreamType) - { - case TSStreamType.MPEG1_VIDEO: - case TSStreamType.MPEG2_VIDEO: - case TSStreamType.AVC_VIDEO: - case TSStreamType.MVC_VIDEO: - case TSStreamType.VC1_VIDEO: - return true; - - default: - return false; - } - } - } - - public bool IsAudioStream - { - get - { - switch (StreamType) - { - case TSStreamType.MPEG1_AUDIO: - case TSStreamType.MPEG2_AUDIO: - case TSStreamType.LPCM_AUDIO: - case TSStreamType.AC3_AUDIO: - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - case TSStreamType.AC3_TRUE_HD_AUDIO: - case TSStreamType.DTS_AUDIO: - case TSStreamType.DTS_HD_AUDIO: - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - case TSStreamType.DTS_HD_MASTER_AUDIO: - return true; - - default: - return false; - } - } - } - - public bool IsGraphicsStream - { - get - { - switch (StreamType) - { - case TSStreamType.PRESENTATION_GRAPHICS: - case TSStreamType.INTERACTIVE_GRAPHICS: - return true; - - default: - return false; - } - } - } - - public bool IsTextStream - { - get - { - switch (StreamType) - { - case TSStreamType.SUBTITLE: - return true; - - default: - return false; - } - } - } - - public string CodecName - { - get - { - switch (StreamType) - { - case TSStreamType.MPEG1_VIDEO: - return "MPEG-1 Video"; - case TSStreamType.MPEG2_VIDEO: - return "MPEG-2 Video"; - case TSStreamType.AVC_VIDEO: - return "MPEG-4 AVC Video"; - case TSStreamType.MVC_VIDEO: - return "MPEG-4 MVC Video"; - case TSStreamType.VC1_VIDEO: - return "VC-1 Video"; - case TSStreamType.MPEG1_AUDIO: - return "MP1 Audio"; - case TSStreamType.MPEG2_AUDIO: - return "MP2 Audio"; - case TSStreamType.LPCM_AUDIO: - return "LPCM Audio"; - case TSStreamType.AC3_AUDIO: - if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended) - return "Dolby Digital EX Audio"; - else - return "Dolby Digital Audio"; - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - return "Dolby Digital Plus Audio"; - case TSStreamType.AC3_TRUE_HD_AUDIO: - return "Dolby TrueHD Audio"; - case TSStreamType.DTS_AUDIO: - if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended) - return "DTS-ES Audio"; - else - return "DTS Audio"; - case TSStreamType.DTS_HD_AUDIO: - return "DTS-HD High-Res Audio"; - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - return "DTS Express"; - case TSStreamType.DTS_HD_MASTER_AUDIO: - return "DTS-HD Master Audio"; - case TSStreamType.PRESENTATION_GRAPHICS: - return "Presentation Graphics"; - case TSStreamType.INTERACTIVE_GRAPHICS: - return "Interactive Graphics"; - case TSStreamType.SUBTITLE: - return "Subtitle"; - default: - return "UNKNOWN"; - } - } - } - - public string CodecAltName - { - get - { - switch (StreamType) - { - case TSStreamType.MPEG1_VIDEO: - return "MPEG-1"; - case TSStreamType.MPEG2_VIDEO: - return "MPEG-2"; - case TSStreamType.AVC_VIDEO: - return "AVC"; - case TSStreamType.MVC_VIDEO: - return "MVC"; - case TSStreamType.VC1_VIDEO: - return "VC-1"; - case TSStreamType.MPEG1_AUDIO: - return "MP1"; - case TSStreamType.MPEG2_AUDIO: - return "MP2"; - case TSStreamType.LPCM_AUDIO: - return "LPCM"; - case TSStreamType.AC3_AUDIO: - return "DD AC3"; - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - return "DD AC3+"; - case TSStreamType.AC3_TRUE_HD_AUDIO: - return "Dolby TrueHD"; - case TSStreamType.DTS_AUDIO: - return "DTS"; - case TSStreamType.DTS_HD_AUDIO: - return "DTS-HD Hi-Res"; - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - return "DTS Express"; - case TSStreamType.DTS_HD_MASTER_AUDIO: - return "DTS-HD Master"; - case TSStreamType.PRESENTATION_GRAPHICS: - return "PGS"; - case TSStreamType.INTERACTIVE_GRAPHICS: - return "IGS"; - case TSStreamType.SUBTITLE: - return "SUB"; - default: - return "UNKNOWN"; - } - } - } - - public string CodecShortName - { - get - { - switch (StreamType) - { - case TSStreamType.MPEG1_VIDEO: - return "MPEG-1"; - case TSStreamType.MPEG2_VIDEO: - return "MPEG-2"; - case TSStreamType.AVC_VIDEO: - return "AVC"; - case TSStreamType.MVC_VIDEO: - return "MVC"; - case TSStreamType.VC1_VIDEO: - return "VC-1"; - case TSStreamType.MPEG1_AUDIO: - return "MP1"; - case TSStreamType.MPEG2_AUDIO: - return "MP2"; - case TSStreamType.LPCM_AUDIO: - return "LPCM"; - case TSStreamType.AC3_AUDIO: - if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended) - return "AC3-EX"; - else - return "AC3"; - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - return "AC3+"; - case TSStreamType.AC3_TRUE_HD_AUDIO: - return "TrueHD"; - case TSStreamType.DTS_AUDIO: - if (((TSAudioStream)this).AudioMode == TSAudioMode.Extended) - return "DTS-ES"; - else - return "DTS"; - case TSStreamType.DTS_HD_AUDIO: - return "DTS-HD HR"; - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - return "DTS Express"; - case TSStreamType.DTS_HD_MASTER_AUDIO: - return "DTS-HD MA"; - case TSStreamType.PRESENTATION_GRAPHICS: - return "PGS"; - case TSStreamType.INTERACTIVE_GRAPHICS: - return "IGS"; - case TSStreamType.SUBTITLE: - return "SUB"; - default: - return "UNKNOWN"; - } - } - } - - public virtual string Description => ""; - - public abstract TSStream Clone(); - - protected void CopyTo(TSStream stream) - { - stream.PID = PID; - stream.StreamType = StreamType; - stream.IsVBR = IsVBR; - stream.BitRate = BitRate; - stream.IsInitialized = IsInitialized; - stream.LanguageCode = _LanguageCode; - if (Descriptors != null) - { - stream.Descriptors = new List(); - foreach (var descriptor in Descriptors) - { - stream.Descriptors.Add(descriptor.Clone()); - } - } - } - } - - public class TSVideoStream : TSStream - { - public TSVideoStream() - { - } - - public int Width; - public int Height; - public bool IsInterlaced; - public int FrameRateEnumerator; - public int FrameRateDenominator; - public TSAspectRatio AspectRatio; - public string EncodingProfile; - - private TSVideoFormat _VideoFormat; - public TSVideoFormat VideoFormat - { - get => _VideoFormat; - set - { - _VideoFormat = value; - switch (value) - { - case TSVideoFormat.VIDEOFORMAT_480i: - Height = 480; - IsInterlaced = true; - break; - case TSVideoFormat.VIDEOFORMAT_480p: - Height = 480; - IsInterlaced = false; - break; - case TSVideoFormat.VIDEOFORMAT_576i: - Height = 576; - IsInterlaced = true; - break; - case TSVideoFormat.VIDEOFORMAT_576p: - Height = 576; - IsInterlaced = false; - break; - case TSVideoFormat.VIDEOFORMAT_720p: - Height = 720; - IsInterlaced = false; - break; - case TSVideoFormat.VIDEOFORMAT_1080i: - Height = 1080; - IsInterlaced = true; - break; - case TSVideoFormat.VIDEOFORMAT_1080p: - Height = 1080; - IsInterlaced = false; - break; - } - } - } - - private TSFrameRate _FrameRate; - public TSFrameRate FrameRate - { - get => _FrameRate; - set - { - _FrameRate = value; - switch (value) - { - case TSFrameRate.FRAMERATE_23_976: - FrameRateEnumerator = 24000; - FrameRateDenominator = 1001; - break; - case TSFrameRate.FRAMERATE_24: - FrameRateEnumerator = 24000; - FrameRateDenominator = 1000; - break; - case TSFrameRate.FRAMERATE_25: - FrameRateEnumerator = 25000; - FrameRateDenominator = 1000; - break; - case TSFrameRate.FRAMERATE_29_97: - FrameRateEnumerator = 30000; - FrameRateDenominator = 1001; - break; - case TSFrameRate.FRAMERATE_50: - FrameRateEnumerator = 50000; - FrameRateDenominator = 1000; - break; - case TSFrameRate.FRAMERATE_59_94: - FrameRateEnumerator = 60000; - FrameRateDenominator = 1001; - break; - } - } - } - - public override string Description - { - get - { - string description = ""; - - if (Height > 0) - { - description += string.Format("{0:D}{1} / ", - Height, - IsInterlaced ? "i" : "p"); - } - if (FrameRateEnumerator > 0 && - FrameRateDenominator > 0) - { - if (FrameRateEnumerator % FrameRateDenominator == 0) - { - description += string.Format("{0:D} fps / ", - FrameRateEnumerator / FrameRateDenominator); - } - else - { - description += string.Format("{0:F3} fps / ", - (double)FrameRateEnumerator / FrameRateDenominator); - } - - } - if (AspectRatio == TSAspectRatio.ASPECT_4_3) - { - description += "4:3 / "; - } - else if (AspectRatio == TSAspectRatio.ASPECT_16_9) - { - description += "16:9 / "; - } - if (EncodingProfile != null) - { - description += EncodingProfile + " / "; - } - if (description.EndsWith(" / ")) - { - description = description.Substring(0, description.Length - 3); - } - return description; - } - } - - public override TSStream Clone() - { - var stream = new TSVideoStream(); - CopyTo(stream); - - stream.VideoFormat = _VideoFormat; - stream.FrameRate = _FrameRate; - stream.Width = Width; - stream.Height = Height; - stream.IsInterlaced = IsInterlaced; - stream.FrameRateEnumerator = FrameRateEnumerator; - stream.FrameRateDenominator = FrameRateDenominator; - stream.AspectRatio = AspectRatio; - stream.EncodingProfile = EncodingProfile; - - return stream; - } - } - - public enum TSAudioMode - { - Unknown, - DualMono, - Stereo, - Surround, - Extended - } - - public class TSAudioStream : TSStream - { - public TSAudioStream() - { - } - - public int SampleRate; - public int ChannelCount; - public int BitDepth; - public int LFE; - public int DialNorm; - public TSAudioMode AudioMode; - public TSAudioStream CoreStream; - public TSChannelLayout ChannelLayout; - - public static int ConvertSampleRate( - TSSampleRate sampleRate) - { - switch (sampleRate) - { - case TSSampleRate.SAMPLERATE_48: - return 48000; - - case TSSampleRate.SAMPLERATE_96: - case TSSampleRate.SAMPLERATE_48_96: - return 96000; - - case TSSampleRate.SAMPLERATE_192: - case TSSampleRate.SAMPLERATE_48_192: - return 192000; - } - return 0; - } - - public string ChannelDescription - { - get - { - if (ChannelLayout == TSChannelLayout.CHANNELLAYOUT_MONO && - ChannelCount == 2) - { - } - - string description = ""; - if (ChannelCount > 0) - { - description += string.Format( - "{0:D}.{1:D}", - ChannelCount, LFE); - } - else - { - switch (ChannelLayout) - { - case TSChannelLayout.CHANNELLAYOUT_MONO: - description += "1.0"; - break; - case TSChannelLayout.CHANNELLAYOUT_STEREO: - description += "2.0"; - break; - case TSChannelLayout.CHANNELLAYOUT_MULTI: - description += "5.1"; - break; - } - } - if (AudioMode == TSAudioMode.Extended) - { - if (StreamType == TSStreamType.AC3_AUDIO) - { - description += "-EX"; - } - if (StreamType == TSStreamType.DTS_AUDIO || - StreamType == TSStreamType.DTS_HD_AUDIO || - StreamType == TSStreamType.DTS_HD_MASTER_AUDIO) - { - description += "-ES"; - } - } - return description; - } - } - - public override string Description - { - get - { - string description = ChannelDescription; - - if (SampleRate > 0) - { - description += string.Format( - " / {0:D} kHz", SampleRate / 1000); - } - if (BitRate > 0) - { - description += string.Format( - " / {0:D} kbps", (uint)Math.Round((double)BitRate / 1000)); - } - if (BitDepth > 0) - { - description += string.Format( - " / {0:D}-bit", BitDepth); - } - if (DialNorm != 0) - { - description += string.Format( - " / DN {0}dB", DialNorm); - } - if (ChannelCount == 2) - { - switch (AudioMode) - { - case TSAudioMode.DualMono: - description += " / Dual Mono"; - break; - - case TSAudioMode.Surround: - description += " / Dolby Surround"; - break; - } - } - if (description.EndsWith(" / ")) - { - description = description.Substring(0, description.Length - 3); - } - if (CoreStream != null) - { - string codec = ""; - switch (CoreStream.StreamType) - { - case TSStreamType.AC3_AUDIO: - codec = "AC3 Embedded"; - break; - case TSStreamType.DTS_AUDIO: - codec = "DTS Core"; - break; - } - description += string.Format( - " ({0}: {1})", - codec, - CoreStream.Description); - } - return description; - } - } - - public override TSStream Clone() - { - var stream = new TSAudioStream(); - CopyTo(stream); - - stream.SampleRate = SampleRate; - stream.ChannelLayout = ChannelLayout; - stream.ChannelCount = ChannelCount; - stream.BitDepth = BitDepth; - stream.LFE = LFE; - stream.DialNorm = DialNorm; - stream.AudioMode = AudioMode; - if (CoreStream != null) - { - stream.CoreStream = (TSAudioStream)CoreStream.Clone(); - } - - return stream; - } - } - - public class TSGraphicsStream : TSStream - { - public TSGraphicsStream() - { - IsVBR = true; - IsInitialized = true; - } - - public override TSStream Clone() - { - var stream = new TSGraphicsStream(); - CopyTo(stream); - return stream; - } - } - - public class TSTextStream : TSStream - { - public TSTextStream() - { - IsVBR = true; - IsInitialized = true; - } - - public override TSStream Clone() - { - var stream = new TSTextStream(); - CopyTo(stream); - return stream; - } - } -} diff --git a/BDInfo/TSStreamBuffer.cs b/BDInfo/TSStreamBuffer.cs deleted file mode 100644 index 30bd1a3f4..000000000 --- a/BDInfo/TSStreamBuffer.cs +++ /dev/null @@ -1,130 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -using System; -using System.Collections.Specialized; -using System.IO; - -namespace BDInfo -{ - public class TSStreamBuffer - { - private MemoryStream Stream = new MemoryStream(); - private int SkipBits = 0; - private byte[] Buffer; - private int BufferLength = 0; - public int TransferLength = 0; - - public TSStreamBuffer() - { - Buffer = new byte[4096]; - Stream = new MemoryStream(Buffer); - } - - public long Length => (long)BufferLength; - - public long Position => Stream.Position; - - public void Add( - byte[] buffer, - int offset, - int length) - { - TransferLength += length; - - if (BufferLength + length >= Buffer.Length) - { - length = Buffer.Length - BufferLength; - } - if (length > 0) - { - Array.Copy(buffer, offset, Buffer, BufferLength, length); - BufferLength += length; - } - } - - public void Seek( - long offset, - SeekOrigin loc) - { - Stream.Seek(offset, loc); - } - - public void Reset() - { - BufferLength = 0; - TransferLength = 0; - } - - public void BeginRead() - { - SkipBits = 0; - Stream.Seek(0, SeekOrigin.Begin); - } - - public void EndRead() - { - } - - public byte[] ReadBytes(int bytes) - { - if (Stream.Position + bytes >= BufferLength) - { - return null; - } - - byte[] value = new byte[bytes]; - Stream.Read(value, 0, bytes); - return value; - } - - public byte ReadByte() - { - return (byte)Stream.ReadByte(); - } - - public int ReadBits(int bits) - { - long pos = Stream.Position; - - int shift = 24; - int data = 0; - for (int i = 0; i < 4; i++) - { - if (pos + i >= BufferLength) break; - data += (Stream.ReadByte() << shift); - shift -= 8; - } - var vector = new BitVector32(data); - - int value = 0; - for (int i = SkipBits; i < SkipBits + bits; i++) - { - value <<= 1; - value += (vector[1 << (32 - i - 1)] ? 1 : 0); - } - - SkipBits += bits; - Stream.Seek(pos + (SkipBits >> 3), SeekOrigin.Begin); - SkipBits = SkipBits % 8; - - return value; - } - } -} diff --git a/BDInfo/TSStreamClip.cs b/BDInfo/TSStreamClip.cs deleted file mode 100644 index 295eeb6b1..000000000 --- a/BDInfo/TSStreamClip.cs +++ /dev/null @@ -1,107 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -using System; -using System.Collections.Generic; - -namespace BDInfo -{ - public class TSStreamClip - { - public int AngleIndex = 0; - public string Name; - public double TimeIn; - public double TimeOut; - public double RelativeTimeIn; - public double RelativeTimeOut; - public double Length; - - public ulong FileSize = 0; - public ulong InterleavedFileSize = 0; - public ulong PayloadBytes = 0; - public ulong PacketCount = 0; - public double PacketSeconds = 0; - - public List Chapters = new List(); - - public TSStreamFile StreamFile = null; - public TSStreamClipFile StreamClipFile = null; - - public TSStreamClip( - TSStreamFile streamFile, - TSStreamClipFile streamClipFile) - { - if (streamFile != null) - { - Name = streamFile.Name; - StreamFile = streamFile; - FileSize = (ulong)StreamFile.FileInfo.Length; - if (StreamFile.InterleavedFile != null) - { - InterleavedFileSize = (ulong)StreamFile.InterleavedFile.FileInfo.Length; - } - } - StreamClipFile = streamClipFile; - } - - public string DisplayName - { - get - { - if (StreamFile != null && - StreamFile.InterleavedFile != null && - BDInfoSettings.EnableSSIF) - { - return StreamFile.InterleavedFile.Name; - } - return Name; - } - } - - public ulong PacketSize => PacketCount * 192; - - public ulong PacketBitRate - { - get - { - if (PacketSeconds > 0) - { - return (ulong)Math.Round(((PacketSize * 8.0) / PacketSeconds)); - } - return 0; - } - } - - public bool IsCompatible(TSStreamClip clip) - { - foreach (var stream1 in StreamFile.Streams.Values) - { - if (clip.StreamFile.Streams.ContainsKey(stream1.PID)) - { - var stream2 = clip.StreamFile.Streams[stream1.PID]; - if (stream1.StreamType != stream2.StreamType) - { - return false; - } - } - } - return true; - } - } -} diff --git a/BDInfo/TSStreamClipFile.cs b/BDInfo/TSStreamClipFile.cs deleted file mode 100644 index e1097b23d..000000000 --- a/BDInfo/TSStreamClipFile.cs +++ /dev/null @@ -1,244 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -#undef DEBUG -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using MediaBrowser.Model.IO; - -namespace BDInfo -{ - public class TSStreamClipFile - { - public FileSystemMetadata FileInfo = null; - public string FileType = null; - public bool IsValid = false; - public string Name = null; - - public Dictionary Streams = - new Dictionary(); - - public TSStreamClipFile(FileSystemMetadata fileInfo) - { - FileInfo = fileInfo; - Name = fileInfo.Name.ToUpper(); - } - - public void Scan() - { - Stream fileStream = null; - BinaryReader fileReader = null; - - try - { -#if DEBUG - Debug.WriteLine(string.Format( - "Scanning {0}...", Name)); -#endif - Streams.Clear(); - - fileStream = File.OpenRead(FileInfo.FullName); - fileReader = new BinaryReader(fileStream); - - byte[] data = new byte[fileStream.Length]; - fileReader.Read(data, 0, data.Length); - - byte[] fileType = new byte[8]; - Array.Copy(data, 0, fileType, 0, fileType.Length); - - FileType = Encoding.ASCII.GetString(fileType, 0, fileType.Length); - if (FileType != "HDMV0100" && - FileType != "HDMV0200") - { - throw new Exception(string.Format( - "Clip info file {0} has an unknown file type {1}.", - FileInfo.Name, FileType)); - } -#if DEBUG - Debug.WriteLine(string.Format( - "\tFileType: {0}", FileType)); -#endif - int clipIndex = - ((int)data[12] << 24) + - ((int)data[13] << 16) + - ((int)data[14] << 8) + - ((int)data[15]); - - int clipLength = - ((int)data[clipIndex] << 24) + - ((int)data[clipIndex + 1] << 16) + - ((int)data[clipIndex + 2] << 8) + - ((int)data[clipIndex + 3]); - - byte[] clipData = new byte[clipLength]; - Array.Copy(data, clipIndex + 4, clipData, 0, clipData.Length); - - int streamCount = clipData[8]; -#if DEBUG - Debug.WriteLine(string.Format( - "\tStreamCount: {0}", streamCount)); -#endif - int streamOffset = 10; - for (int streamIndex = 0; - streamIndex < streamCount; - streamIndex++) - { - TSStream stream = null; - - ushort PID = (ushort) - ((clipData[streamOffset] << 8) + - clipData[streamOffset + 1]); - - streamOffset += 2; - - var streamType = (TSStreamType) - clipData[streamOffset + 1]; - switch (streamType) - { - case TSStreamType.MVC_VIDEO: - // TODO - break; - - case TSStreamType.AVC_VIDEO: - case TSStreamType.MPEG1_VIDEO: - case TSStreamType.MPEG2_VIDEO: - case TSStreamType.VC1_VIDEO: - { - var videoFormat = (TSVideoFormat) - (clipData[streamOffset + 2] >> 4); - var frameRate = (TSFrameRate) - (clipData[streamOffset + 2] & 0xF); - var aspectRatio = (TSAspectRatio) - (clipData[streamOffset + 3] >> 4); - - stream = new TSVideoStream(); - ((TSVideoStream)stream).VideoFormat = videoFormat; - ((TSVideoStream)stream).AspectRatio = aspectRatio; - ((TSVideoStream)stream).FrameRate = frameRate; -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2} {3} {4}", - PID, - streamType, - videoFormat, - frameRate, - aspectRatio)); -#endif - } - break; - - case TSStreamType.AC3_AUDIO: - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - case TSStreamType.AC3_TRUE_HD_AUDIO: - case TSStreamType.DTS_AUDIO: - case TSStreamType.DTS_HD_AUDIO: - case TSStreamType.DTS_HD_MASTER_AUDIO: - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - case TSStreamType.LPCM_AUDIO: - case TSStreamType.MPEG1_AUDIO: - case TSStreamType.MPEG2_AUDIO: - { - byte[] languageBytes = new byte[3]; - Array.Copy(clipData, streamOffset + 3, - languageBytes, 0, languageBytes.Length); - string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length); - - var channelLayout = (TSChannelLayout) - (clipData[streamOffset + 2] >> 4); - var sampleRate = (TSSampleRate) - (clipData[streamOffset + 2] & 0xF); - - stream = new TSAudioStream(); - ((TSAudioStream)stream).LanguageCode = languageCode; - ((TSAudioStream)stream).ChannelLayout = channelLayout; - ((TSAudioStream)stream).SampleRate = TSAudioStream.ConvertSampleRate(sampleRate); - ((TSAudioStream)stream).LanguageCode = languageCode; -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2} {3} {4}", - PID, - streamType, - languageCode, - channelLayout, - sampleRate)); -#endif - } - break; - - case TSStreamType.INTERACTIVE_GRAPHICS: - case TSStreamType.PRESENTATION_GRAPHICS: - { - byte[] languageBytes = new byte[3]; - Array.Copy(clipData, streamOffset + 2, - languageBytes, 0, languageBytes.Length); - string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length); - - stream = new TSGraphicsStream(); - stream.LanguageCode = languageCode; -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2}", - PID, - streamType, - languageCode)); -#endif - } - break; - - case TSStreamType.SUBTITLE: - { - byte[] languageBytes = new byte[3]; - Array.Copy(clipData, streamOffset + 3, - languageBytes, 0, languageBytes.Length); - string languageCode = Encoding.ASCII.GetString(languageBytes, 0, languageBytes.Length); -#if DEBUG - Debug.WriteLine(string.Format( - "\t{0} {1} {2}", - PID, - streamType, - languageCode)); -#endif - stream = new TSTextStream(); - stream.LanguageCode = languageCode; - } - break; - } - - if (stream != null) - { - stream.PID = PID; - stream.StreamType = streamType; - Streams.Add(PID, stream); - } - - streamOffset += clipData[streamOffset] + 1; - } - IsValid = true; - } - finally - { - if (fileReader != null) fileReader.Dispose(); - if (fileStream != null) fileStream.Dispose(); - } - } - } -} diff --git a/BDInfo/TSStreamFile.cs b/BDInfo/TSStreamFile.cs deleted file mode 100644 index ecf6609e2..000000000 --- a/BDInfo/TSStreamFile.cs +++ /dev/null @@ -1,1555 +0,0 @@ -//============================================================================ -// BDInfo - Blu-ray Video and Audio Analysis Tool -// Copyright © 2010 Cinema Squid -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -//============================================================================= - -#undef DEBUG -using System; -using System.Collections.Generic; -using System.IO; -using MediaBrowser.Model.IO; - -namespace BDInfo -{ - public class TSStreamState - { - public ulong TransferCount = 0; - - public string StreamTag = null; - - public ulong TotalPackets = 0; - public ulong WindowPackets = 0; - - public ulong TotalBytes = 0; - public ulong WindowBytes = 0; - - public long PeakTransferLength = 0; - public long PeakTransferRate = 0; - - public double TransferMarker = 0; - public double TransferInterval = 0; - - public TSStreamBuffer StreamBuffer = new TSStreamBuffer(); - - public uint Parse = 0; - public bool TransferState = false; - public int TransferLength = 0; - public int PacketLength = 0; - public byte PacketLengthParse = 0; - public byte PacketParse = 0; - - public byte PTSParse = 0; - public ulong PTS = 0; - public ulong PTSTemp = 0; - public ulong PTSLast = 0; - public ulong PTSPrev = 0; - public ulong PTSDiff = 0; - public ulong PTSCount = 0; - public ulong PTSTransfer = 0; - - public byte DTSParse = 0; - public ulong DTSTemp = 0; - public ulong DTSPrev = 0; - - public byte PESHeaderLength = 0; - public byte PESHeaderFlags = 0; -#if DEBUG - public byte PESHeaderIndex = 0; - public byte[] PESHeader = new byte[256 + 9]; -#endif - } - - public class TSPacketParser - { - public bool SyncState = false; - public byte TimeCodeParse = 4; - public byte PacketLength = 0; - public byte HeaderParse = 0; - - public uint TimeCode; - public byte TransportErrorIndicator; - public byte PayloadUnitStartIndicator; - public byte TransportPriority; - public ushort PID; - public byte TransportScramblingControl; - public byte AdaptionFieldControl; - - public bool AdaptionFieldState = false; - public byte AdaptionFieldParse = 0; - public byte AdaptionFieldLength = 0; - - public ushort PCRPID = 0xFFFF; - public byte PCRParse = 0; - public ulong PreviousPCR = 0; - public ulong PCR = 0; - public ulong PCRCount = 0; - public ulong PTSFirst = ulong.MaxValue; - public ulong PTSLast = ulong.MinValue; - public ulong PTSDiff = 0; - - public byte[] PAT = new byte[1024]; - public bool PATSectionStart = false; - public byte PATPointerField = 0; - public uint PATOffset = 0; - public byte PATSectionLengthParse = 0; - public ushort PATSectionLength = 0; - public uint PATSectionParse = 0; - public bool PATTransferState = false; - public byte PATSectionNumber = 0; - public byte PATLastSectionNumber = 0; - - public ushort TransportStreamId = 0xFFFF; - - public List PMTProgramDescriptors = new List(); - public ushort PMTPID = 0xFFFF; - public Dictionary PMT = new Dictionary(); - public bool PMTSectionStart = false; - public ushort PMTProgramInfoLength = 0; - public byte PMTProgramDescriptor = 0; - public byte PMTProgramDescriptorLengthParse = 0; - public byte PMTProgramDescriptorLength = 0; - public ushort PMTStreamInfoLength = 0; - public uint PMTStreamDescriptorLengthParse = 0; - public uint PMTStreamDescriptorLength = 0; - public byte PMTPointerField = 0; - public uint PMTOffset = 0; - public uint PMTSectionLengthParse = 0; - public ushort PMTSectionLength = 0; - public uint PMTSectionParse = 0; - public bool PMTTransferState = false; - public byte PMTSectionNumber = 0; - public byte PMTLastSectionNumber = 0; - - public byte PMTTemp = 0; - - public TSStream Stream = null; - public TSStreamState StreamState = null; - - public ulong TotalPackets = 0; - } - - public class TSStreamDiagnostics - { - public ulong Bytes = 0; - public ulong Packets = 0; - public double Marker = 0; - public double Interval = 0; - public string Tag = null; - } - - public class TSStreamFile - { - public FileSystemMetadata FileInfo = null; - public string Name = null; - public long Size = 0; - public double Length = 0; - - public TSInterleavedFile InterleavedFile = null; - - private Dictionary StreamStates = - new Dictionary(); - - public Dictionary Streams = - new Dictionary(); - - public Dictionary> StreamDiagnostics = - new Dictionary>(); - - private List Playlists = null; - - private readonly IFileSystem _fileSystem; - - public TSStreamFile(FileSystemMetadata fileInfo, IFileSystem fileSystem) - { - FileInfo = fileInfo; - _fileSystem = fileSystem; - Name = fileInfo.Name.ToUpper(); - } - - public string DisplayName - { - get - { - if (BDInfoSettings.EnableSSIF && - InterleavedFile != null) - { - return InterleavedFile.Name; - } - return Name; - } - } - - private bool ScanStream( - TSStream stream, - TSStreamState streamState, - TSStreamBuffer buffer) - { - streamState.StreamTag = null; - - long bitrate = 0; - if (stream.IsAudioStream && - streamState.PTSTransfer > 0) - { - bitrate = (long)Math.Round( - (buffer.TransferLength * 8.0) / - ((double)streamState.PTSTransfer / 90000)); - - if (bitrate > streamState.PeakTransferRate) - { - streamState.PeakTransferRate = bitrate; - } - } - if (buffer.TransferLength > streamState.PeakTransferLength) - { - streamState.PeakTransferLength = buffer.TransferLength; - } - - buffer.BeginRead(); - switch (stream.StreamType) - { - case TSStreamType.MPEG2_VIDEO: - TSCodecMPEG2.Scan( - (TSVideoStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.AVC_VIDEO: - TSCodecAVC.Scan( - (TSVideoStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.MVC_VIDEO: - TSCodecMVC.Scan( - (TSVideoStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.VC1_VIDEO: - TSCodecVC1.Scan( - (TSVideoStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.AC3_AUDIO: - TSCodecAC3.Scan( - (TSAudioStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - TSCodecAC3.Scan( - (TSAudioStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.AC3_TRUE_HD_AUDIO: - TSCodecTrueHD.Scan( - (TSAudioStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.LPCM_AUDIO: - TSCodecLPCM.Scan( - (TSAudioStream)stream, buffer, ref streamState.StreamTag); - break; - - case TSStreamType.DTS_AUDIO: - TSCodecDTS.Scan( - (TSAudioStream)stream, buffer, bitrate, ref streamState.StreamTag); - break; - - case TSStreamType.DTS_HD_AUDIO: - case TSStreamType.DTS_HD_MASTER_AUDIO: - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - TSCodecDTSHD.Scan( - (TSAudioStream)stream, buffer, bitrate, ref streamState.StreamTag); - break; - - default: - stream.IsInitialized = true; - break; - } - buffer.EndRead(); - streamState.StreamBuffer.Reset(); - - bool isAVC = false; - bool isMVC = false; - foreach (var finishedStream in Streams.Values) - { - if (!finishedStream.IsInitialized) - { - return false; - } - if (finishedStream.StreamType == TSStreamType.AVC_VIDEO) - { - isAVC = true; - } - if (finishedStream.StreamType == TSStreamType.MVC_VIDEO) - { - isMVC = true; - } - } - if (isMVC && !isAVC) - { - return false; - } - return true; - } - - private void UpdateStreamBitrates( - ushort PTSPID, - ulong PTS, - ulong PTSDiff) - { - if (Playlists == null) return; - - foreach (ushort PID in StreamStates.Keys) - { - if (Streams.ContainsKey(PID) && - Streams[PID].IsVideoStream && - PID != PTSPID) - { - continue; - } - if (StreamStates[PID].WindowPackets == 0) - { - continue; - } - UpdateStreamBitrate(PID, PTSPID, PTS, PTSDiff); - } - - foreach (var playlist in Playlists) - { - double packetSeconds = 0; - foreach (var clip in playlist.StreamClips) - { - if (clip.AngleIndex == 0) - { - packetSeconds += clip.PacketSeconds; - } - } - if (packetSeconds > 0) - { - foreach (var playlistStream in playlist.SortedStreams) - { - if (playlistStream.IsVBR) - { - playlistStream.BitRate = (long)Math.Round( - ((playlistStream.PayloadBytes * 8.0) / packetSeconds)); - - if (playlistStream.StreamType == TSStreamType.AC3_TRUE_HD_AUDIO && - ((TSAudioStream)playlistStream).CoreStream != null) - { - playlistStream.BitRate -= - ((TSAudioStream)playlistStream).CoreStream.BitRate; - } - } - } - } - } - } - - private void UpdateStreamBitrate( - ushort PID, - ushort PTSPID, - ulong PTS, - ulong PTSDiff) - { - if (Playlists == null) return; - - var streamState = StreamStates[PID]; - double streamTime = (double)PTS / 90000; - double streamInterval = (double)PTSDiff / 90000; - double streamOffset = streamTime + streamInterval; - - foreach (var playlist in Playlists) - { - foreach (var clip in playlist.StreamClips) - { - if (clip.Name != this.Name) continue; - - if (streamTime == 0 || - (streamTime >= clip.TimeIn && - streamTime <= clip.TimeOut)) - { - clip.PayloadBytes += streamState.WindowBytes; - clip.PacketCount += streamState.WindowPackets; - - if (streamOffset > clip.TimeIn && - streamOffset - clip.TimeIn > clip.PacketSeconds) - { - clip.PacketSeconds = streamOffset - clip.TimeIn; - } - - var playlistStreams = playlist.Streams; - if (clip.AngleIndex > 0 && - clip.AngleIndex < playlist.AngleStreams.Count + 1) - { - playlistStreams = playlist.AngleStreams[clip.AngleIndex - 1]; - } - if (playlistStreams.ContainsKey(PID)) - { - var stream = playlistStreams[PID]; - - stream.PayloadBytes += streamState.WindowBytes; - stream.PacketCount += streamState.WindowPackets; - - if (stream.IsVideoStream) - { - stream.PacketSeconds += streamInterval; - - stream.ActiveBitRate = (long)Math.Round( - ((stream.PayloadBytes * 8.0) / - stream.PacketSeconds)); - } - - if (stream.StreamType == TSStreamType.AC3_TRUE_HD_AUDIO && - ((TSAudioStream)stream).CoreStream != null) - { - stream.ActiveBitRate -= - ((TSAudioStream)stream).CoreStream.BitRate; - } - } - } - } - } - - if (Streams.ContainsKey(PID)) - { - var stream = Streams[PID]; - stream.PayloadBytes += streamState.WindowBytes; - stream.PacketCount += streamState.WindowPackets; - - if (stream.IsVideoStream) - { - var diag = new TSStreamDiagnostics(); - diag.Marker = (double)PTS / 90000; - diag.Interval = (double)PTSDiff / 90000; - diag.Bytes = streamState.WindowBytes; - diag.Packets = streamState.WindowPackets; - diag.Tag = streamState.StreamTag; - StreamDiagnostics[PID].Add(diag); - - stream.PacketSeconds += streamInterval; - } - } - streamState.WindowPackets = 0; - streamState.WindowBytes = 0; - } - - public void Scan(List playlists, bool isFullScan) - { - if (playlists == null || playlists.Count == 0) - { - return; - } - - Playlists = playlists; - int dataSize = 16384; - Stream fileStream = null; - try - { - string fileName; - if (BDInfoSettings.EnableSSIF && - InterleavedFile != null) - { - fileName = InterleavedFile.FileInfo.FullName; - } - else - { - fileName = FileInfo.FullName; - } - fileStream = _fileSystem.GetFileStream( - fileName, - FileOpenMode.Open, - FileAccessMode.Read, - FileShareMode.Read, - false); - - Size = 0; - Length = 0; - - Streams.Clear(); - StreamStates.Clear(); - StreamDiagnostics.Clear(); - - var parser = - new TSPacketParser(); - - long fileLength = (uint)fileStream.Length; - byte[] buffer = new byte[dataSize]; - int bufferLength = 0; - while ((bufferLength = - fileStream.Read(buffer, 0, buffer.Length)) > 0) - { - int offset = 0; - for (int i = 0; i < bufferLength; i++) - { - if (parser.SyncState == false) - { - if (parser.TimeCodeParse > 0) - { - parser.TimeCodeParse--; - switch (parser.TimeCodeParse) - { - case 3: - parser.TimeCode = 0; - parser.TimeCode |= - ((uint)buffer[i] & 0x3F) << 24; - break; - case 2: - parser.TimeCode |= - ((uint)buffer[i] & 0xFF) << 16; - break; - case 1: - parser.TimeCode |= - ((uint)buffer[i] & 0xFF) << 8; - break; - case 0: - parser.TimeCode |= - ((uint)buffer[i] & 0xFF); - break; - } - } - else if (buffer[i] == 0x47) - { - parser.SyncState = true; - parser.PacketLength = 187; - parser.TimeCodeParse = 4; - parser.HeaderParse = 3; - } - } - else if (parser.HeaderParse > 0) - { - parser.PacketLength--; - parser.HeaderParse--; - - switch (parser.HeaderParse) - { - case 2: - { - parser.TransportErrorIndicator = - (byte)((buffer[i] >> 7) & 0x1); - parser.PayloadUnitStartIndicator = - (byte)((buffer[i] >> 6) & 0x1); - parser.TransportPriority = - (byte)((buffer[i] >> 5) & 0x1); - parser.PID = - (ushort)((buffer[i] & 0x1f) << 8); - } - break; - - case 1: - { - parser.PID |= (ushort)buffer[i]; - if (Streams.ContainsKey(parser.PID)) - { - parser.Stream = Streams[parser.PID]; - } - else - { - parser.Stream = null; - } - if (!StreamStates.ContainsKey(parser.PID)) - { - StreamStates[parser.PID] = new TSStreamState(); - } - parser.StreamState = StreamStates[parser.PID]; - parser.StreamState.TotalPackets++; - parser.StreamState.WindowPackets++; - parser.TotalPackets++; - } - break; - - case 0: - { - parser.TransportScramblingControl = - (byte)((buffer[i] >> 6) & 0x3); - parser.AdaptionFieldControl = - (byte)((buffer[i] >> 4) & 0x3); - - if ((parser.AdaptionFieldControl & 0x2) == 0x2) - { - parser.AdaptionFieldState = true; - } - if (parser.PayloadUnitStartIndicator == 1) - { - if (parser.PID == 0) - { - parser.PATSectionStart = true; - } - else if (parser.PID == parser.PMTPID) - { - parser.PMTSectionStart = true; - } - else if (parser.StreamState != null && - parser.StreamState.TransferState) - { - parser.StreamState.TransferState = false; - parser.StreamState.TransferCount++; - - bool isFinished = ScanStream( - parser.Stream, - parser.StreamState, - parser.StreamState.StreamBuffer); - - if (!isFullScan && isFinished) - { - return; - } - } - } - } - break; - } - } - else if (parser.AdaptionFieldState) - { - parser.PacketLength--; - parser.AdaptionFieldParse = buffer[i]; - parser.AdaptionFieldLength = buffer[i]; - parser.AdaptionFieldState = false; - } - else if (parser.AdaptionFieldParse > 0) - { - parser.PacketLength--; - parser.AdaptionFieldParse--; - if ((parser.AdaptionFieldLength - parser.AdaptionFieldParse) == 1) - { - if ((buffer[i] & 0x10) == 0x10) - { - parser.PCRParse = 6; - parser.PCR = 0; - } - } - else if (parser.PCRParse > 0) - { - parser.PCRParse--; - parser.PCR = (parser.PCR << 8) + (ulong)buffer[i]; - if (parser.PCRParse == 0) - { - parser.PreviousPCR = parser.PCR; - parser.PCR = (parser.PCR & 0x1FF) + - ((parser.PCR >> 15) * 300); - } - parser.PCRCount++; - } - if (parser.PacketLength == 0) - { - parser.SyncState = false; - } - } - else if (parser.PID == 0) - { - if (parser.PATTransferState) - { - if ((bufferLength - i) > parser.PATSectionLength) - { - offset = parser.PATSectionLength; - } - else - { - offset = (bufferLength - i); - } - if (parser.PacketLength <= offset) - { - offset = parser.PacketLength; - } - - for (int k = 0; k < offset; k++) - { - parser.PAT[parser.PATOffset++] = buffer[i++]; - parser.PATSectionLength--; - parser.PacketLength--; - } - --i; - - if (parser.PATSectionLength == 0) - { - parser.PATTransferState = false; - if (parser.PATSectionNumber == parser.PATLastSectionNumber) - { - for (int k = 0; k < (parser.PATOffset - 4); k += 4) - { - uint programNumber = (uint) - ((parser.PAT[k] << 8) + - parser.PAT[k + 1]); - - ushort programPID = (ushort) - (((parser.PAT[k + 2] & 0x1F) << 8) + - parser.PAT[k + 3]); - - if (programNumber == 1) - { - parser.PMTPID = programPID; - } - } - } - } - } - else - { - --parser.PacketLength; - if (parser.PATSectionStart) - { - parser.PATPointerField = buffer[i]; - if (parser.PATPointerField == 0) - { - parser.PATSectionLengthParse = 3; - } - parser.PATSectionStart = false; - } - else if (parser.PATPointerField > 0) - { - --parser.PATPointerField; - if (parser.PATPointerField == 0) - { - parser.PATSectionLengthParse = 3; - } - } - else if (parser.PATSectionLengthParse > 0) - { - --parser.PATSectionLengthParse; - switch (parser.PATSectionLengthParse) - { - case 2: - break; - case 1: - parser.PATSectionLength = (ushort) - ((buffer[i] & 0xF) << 8); - break; - case 0: - parser.PATSectionLength |= buffer[i]; - if (parser.PATSectionLength > 1021) - { - parser.PATSectionLength = 0; - } - else - { - parser.PATSectionParse = 5; - } - break; - } - } - else if (parser.PATSectionParse > 0) - { - --parser.PATSectionLength; - --parser.PATSectionParse; - - switch (parser.PATSectionParse) - { - case 4: - parser.TransportStreamId = (ushort) - (buffer[i] << 8); - break; - case 3: - parser.TransportStreamId |= buffer[i]; - break; - case 2: - break; - case 1: - parser.PATSectionNumber = buffer[i]; - if (parser.PATSectionNumber == 0) - { - parser.PATOffset = 0; - } - break; - case 0: - parser.PATLastSectionNumber = buffer[i]; - parser.PATTransferState = true; - break; - } - } - } - if (parser.PacketLength == 0) - { - parser.SyncState = false; - } - } - else if (parser.PID == parser.PMTPID) - { - if (parser.PMTTransferState) - { - if ((bufferLength - i) >= parser.PMTSectionLength) - { - offset = parser.PMTSectionLength; - } - else - { - offset = (bufferLength - i); - } - if (parser.PacketLength <= offset) - { - offset = parser.PacketLength; - } - if (!parser.PMT.ContainsKey(parser.PID)) - { - parser.PMT[parser.PID] = new byte[1024]; - } - - byte[] PMT = parser.PMT[parser.PID]; - for (int k = 0; k < offset; k++) - { - PMT[parser.PMTOffset++] = buffer[i++]; - --parser.PMTSectionLength; - --parser.PacketLength; - } - --i; - - if (parser.PMTSectionLength == 0) - { - parser.PMTTransferState = false; - if (parser.PMTSectionNumber == parser.PMTLastSectionNumber) - { - //Console.WriteLine("PMT Start: " + parser.PMTTemp); - try - { - for (int k = 0; k < (parser.PMTOffset - 4); k += 5) - { - byte streamType = PMT[k]; - - ushort streamPID = (ushort) - (((PMT[k + 1] & 0x1F) << 8) + - PMT[k + 2]); - - ushort streamInfoLength = (ushort) - (((PMT[k + 3] & 0xF) << 8) + - PMT[k + 4]); - - /* - if (streamInfoLength == 2) - { - // TODO: Cleanup - //streamInfoLength = 0; - } - - Console.WriteLine(string.Format( - "Type: {0} PID: {1} Length: {2}", - streamType, streamPID, streamInfoLength)); - */ - - if (!Streams.ContainsKey(streamPID)) - { - var streamDescriptors = - new List(); - - /* - * TODO: Getting bad streamInfoLength - if (streamInfoLength > 0) - { - for (int d = 0; d < streamInfoLength; d++) - { - byte name = PMT[k + d + 5]; - byte length = PMT[k + d + 6]; - TSDescriptor descriptor = - new TSDescriptor(name, length); - for (int v = 0; v < length; v++) - { - descriptor.Value[v] = - PMT[k + d + v + 7]; - } - streamDescriptors.Add(descriptor); - d += (length + 1); - } - } - */ - CreateStream(streamPID, streamType, streamDescriptors); - } - k += streamInfoLength; - } - } - catch - { - // TODO - //Console.WriteLine(ex.Message); - } - } - } - } - else - { - --parser.PacketLength; - if (parser.PMTSectionStart) - { - parser.PMTPointerField = buffer[i]; - if (parser.PMTPointerField == 0) - { - parser.PMTSectionLengthParse = 3; - } - parser.PMTSectionStart = false; - } - else if (parser.PMTPointerField > 0) - { - --parser.PMTPointerField; - if (parser.PMTPointerField == 0) - { - parser.PMTSectionLengthParse = 3; - } - } - else if (parser.PMTSectionLengthParse > 0) - { - --parser.PMTSectionLengthParse; - switch (parser.PMTSectionLengthParse) - { - case 2: - if (buffer[i] != 0x2) - { - parser.PMTSectionLengthParse = 0; - } - break; - case 1: - parser.PMTSectionLength = (ushort) - ((buffer[i] & 0xF) << 8); - break; - case 0: - parser.PMTSectionLength |= buffer[i]; - if (parser.PMTSectionLength > 1021) - { - parser.PMTSectionLength = 0; - } - else - { - parser.PMTSectionParse = 9; - } - break; - } - } - else if (parser.PMTSectionParse > 0) - { - --parser.PMTSectionLength; - --parser.PMTSectionParse; - - switch (parser.PMTSectionParse) - { - case 8: - case 7: - break; - case 6: - parser.PMTTemp = buffer[i]; - break; - case 5: - parser.PMTSectionNumber = buffer[i]; - if (parser.PMTSectionNumber == 0) - { - parser.PMTOffset = 0; - } - break; - case 4: - parser.PMTLastSectionNumber = buffer[i]; - break; - case 3: - parser.PCRPID = (ushort) - ((buffer[i] & 0x1F) << 8); - break; - case 2: - parser.PCRPID |= buffer[i]; - break; - case 1: - parser.PMTProgramInfoLength = (ushort) - ((buffer[i] & 0xF) << 8); - break; - case 0: - parser.PMTProgramInfoLength |= buffer[i]; - if (parser.PMTProgramInfoLength == 0) - { - parser.PMTTransferState = true; - } - else - { - parser.PMTProgramDescriptorLengthParse = 2; - } - break; - } - } - else if (parser.PMTProgramInfoLength > 0) - { - --parser.PMTSectionLength; - --parser.PMTProgramInfoLength; - - if (parser.PMTProgramDescriptorLengthParse > 0) - { - --parser.PMTProgramDescriptorLengthParse; - switch (parser.PMTProgramDescriptorLengthParse) - { - case 1: - parser.PMTProgramDescriptor = buffer[i]; - break; - case 0: - parser.PMTProgramDescriptorLength = buffer[i]; - parser.PMTProgramDescriptors.Add( - new TSDescriptor( - parser.PMTProgramDescriptor, - parser.PMTProgramDescriptorLength)); - break; - } - } - else if (parser.PMTProgramDescriptorLength > 0) - { - --parser.PMTProgramDescriptorLength; - - var descriptor = parser.PMTProgramDescriptors[ - parser.PMTProgramDescriptors.Count - 1]; - - int valueIndex = - descriptor.Value.Length - - parser.PMTProgramDescriptorLength - 1; - - descriptor.Value[valueIndex] = buffer[i]; - - if (parser.PMTProgramDescriptorLength == 0 && - parser.PMTProgramInfoLength > 0) - { - parser.PMTProgramDescriptorLengthParse = 2; - } - } - if (parser.PMTProgramInfoLength == 0) - { - parser.PMTTransferState = true; - } - } - } - if (parser.PacketLength == 0) - { - parser.SyncState = false; - } - } - else if (parser.Stream != null && - parser.StreamState != null && - parser.TransportScramblingControl == 0) - { - var stream = parser.Stream; - var streamState = parser.StreamState; - - streamState.Parse = - (streamState.Parse << 8) + buffer[i]; - - if (streamState.TransferState) - { - if ((bufferLength - i) >= streamState.PacketLength && - streamState.PacketLength > 0) - { - offset = streamState.PacketLength; - } - else - { - offset = (bufferLength - i); - } - if (parser.PacketLength <= offset) - { - offset = parser.PacketLength; - } - streamState.TransferLength = offset; - - if (!stream.IsInitialized || - stream.IsVideoStream) - { - streamState.StreamBuffer.Add( - buffer, i, offset); - } - else - { - streamState.StreamBuffer.TransferLength += offset; - } - - i += (int)(streamState.TransferLength - 1); - streamState.PacketLength -= streamState.TransferLength; - parser.PacketLength -= (byte)streamState.TransferLength; - - streamState.TotalBytes += (ulong)streamState.TransferLength; - streamState.WindowBytes += (ulong)streamState.TransferLength; - - if (streamState.PacketLength == 0) - { - streamState.TransferState = false; - streamState.TransferCount++; - bool isFinished = ScanStream( - stream, - streamState, - streamState.StreamBuffer); - - if (!isFullScan && isFinished) - { - return; - } - } - } - else - { - --parser.PacketLength; - - bool headerFound = false; - if (stream.IsVideoStream && - streamState.Parse == 0x000001FD) - { - headerFound = true; - } - if (stream.IsVideoStream && - streamState.Parse >= 0x000001E0 && - streamState.Parse <= 0x000001EF) - { - headerFound = true; - } - if (stream.IsAudioStream && - streamState.Parse == 0x000001BD) - { - headerFound = true; - } - if (stream.IsAudioStream && - (streamState.Parse == 0x000001FA || - streamState.Parse == 0x000001FD)) - { - headerFound = true; - } - - if (!stream.IsVideoStream && - !stream.IsAudioStream && - (streamState.Parse == 0x000001FA || - streamState.Parse == 0x000001FD || - streamState.Parse == 0x000001BD || - (streamState.Parse >= 0x000001E0 && - streamState.Parse <= 0x000001EF))) - { - headerFound = true; - } - - if (headerFound) - { - streamState.PacketLengthParse = 2; -#if DEBUG - streamState.PESHeaderIndex = 0; - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)((streamState.Parse >> 24) & 0xFF); - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)((streamState.Parse >> 16) & 0xFF); - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)((streamState.Parse >> 8) & 0xFF); - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - } - else if (streamState.PacketLengthParse > 0) - { - --streamState.PacketLengthParse; - switch (streamState.PacketLengthParse) - { - case 1: -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 0: - streamState.PacketLength = - (int)(streamState.Parse & 0xFFFF); - streamState.PacketParse = 3; -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - } - } - else if (streamState.PacketParse > 0) - { - --streamState.PacketLength; - --streamState.PacketParse; - - switch (streamState.PacketParse) - { - case 2: -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 1: - streamState.PESHeaderFlags = - (byte)(streamState.Parse & 0xFF); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 0: - streamState.PESHeaderLength = - (byte)(streamState.Parse & 0xFF); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - if ((streamState.PESHeaderFlags & 0xC0) == 0x80) - { - streamState.PTSParse = 5; - } - else if ((streamState.PESHeaderFlags & 0xC0) == 0xC0) - { - streamState.DTSParse = 10; - } - if (streamState.PESHeaderLength == 0) - { - streamState.TransferState = true; - } - break; - } - } - else if (streamState.PTSParse > 0) - { - --streamState.PacketLength; - --streamState.PESHeaderLength; - --streamState.PTSParse; - - switch (streamState.PTSParse) - { - case 4: - streamState.PTSTemp = - ((streamState.Parse & 0xE) << 29); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - break; - - case 3: - streamState.PTSTemp |= - ((streamState.Parse & 0xFF) << 22); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 2: - streamState.PTSTemp |= - ((streamState.Parse & 0xFE) << 14); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 1: - streamState.PTSTemp |= - ((streamState.Parse & 0xFF) << 7); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 0: - streamState.PTSTemp |= - ((streamState.Parse & 0xFE) >> 1); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - streamState.PTS = streamState.PTSTemp; - - if (streamState.PTS > streamState.PTSLast) - { - if (streamState.PTSLast > 0) - { - streamState.PTSTransfer = (streamState.PTS - streamState.PTSLast); - } - streamState.PTSLast = streamState.PTS; - } - - streamState.PTSDiff = streamState.PTS - streamState.DTSPrev; - - if (streamState.PTSCount > 0 && - stream.IsVideoStream) - { - UpdateStreamBitrates(stream.PID, streamState.PTS, streamState.PTSDiff); - if (streamState.DTSTemp < parser.PTSFirst) - { - parser.PTSFirst = streamState.DTSTemp; - } - if (streamState.DTSTemp > parser.PTSLast) - { - parser.PTSLast = streamState.DTSTemp; - } - Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000; - } - - streamState.DTSPrev = streamState.PTS; - streamState.PTSCount++; - if (streamState.PESHeaderLength == 0) - { - streamState.TransferState = true; - } - break; - } - } - else if (streamState.DTSParse > 0) - { - --streamState.PacketLength; - --streamState.PESHeaderLength; - --streamState.DTSParse; - - switch (streamState.DTSParse) - { - case 9: - streamState.PTSTemp = - ((streamState.Parse & 0xE) << 29); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 8: - streamState.PTSTemp |= - ((streamState.Parse & 0xFF) << 22); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 7: - streamState.PTSTemp |= - ((streamState.Parse & 0xFE) << 14); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - break; - - case 6: - streamState.PTSTemp |= - ((streamState.Parse & 0xFF) << 7); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 5: - streamState.PTSTemp |= - ((streamState.Parse & 0xFE) >> 1); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - streamState.PTS = streamState.PTSTemp; - if (streamState.PTS > streamState.PTSLast) - { - streamState.PTSLast = streamState.PTS; - } - break; - - case 4: - streamState.DTSTemp = - ((streamState.Parse & 0xE) << 29); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - break; - - case 3: - streamState.DTSTemp |= - ((streamState.Parse & 0xFF) << 22); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - break; - - case 2: - streamState.DTSTemp |= - ((streamState.Parse & 0xFE) << 14); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - break; - - case 1: - streamState.DTSTemp |= - ((streamState.Parse & 0xFF) << 7); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - break; - - case 0: - streamState.DTSTemp |= - ((streamState.Parse & 0xFE) >> 1); -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xff); -#endif - streamState.PTSDiff = streamState.DTSTemp - streamState.DTSPrev; - - if (streamState.PTSCount > 0 && - stream.IsVideoStream) - { - UpdateStreamBitrates(stream.PID, streamState.DTSTemp, streamState.PTSDiff); - if (streamState.DTSTemp < parser.PTSFirst) - { - parser.PTSFirst = streamState.DTSTemp; - } - if (streamState.DTSTemp > parser.PTSLast) - { - parser.PTSLast = streamState.DTSTemp; - } - Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000; - } - streamState.DTSPrev = streamState.DTSTemp; - streamState.PTSCount++; - if (streamState.PESHeaderLength == 0) - { - streamState.TransferState = true; - } - break; - } - } - else if (streamState.PESHeaderLength > 0) - { - --streamState.PacketLength; - --streamState.PESHeaderLength; -#if DEBUG - streamState.PESHeader[streamState.PESHeaderIndex++] = - (byte)(streamState.Parse & 0xFF); -#endif - if (streamState.PESHeaderLength == 0) - { - streamState.TransferState = true; - } - } - } - if (parser.PacketLength == 0) - { - parser.SyncState = false; - } - } - else - { - parser.PacketLength--; - if ((bufferLength - i) >= parser.PacketLength) - { - i = i + parser.PacketLength; - parser.PacketLength = 0; - } - else - { - parser.PacketLength -= (byte)((bufferLength - i) + 1); - i = bufferLength; - } - if (parser.PacketLength == 0) - { - parser.SyncState = false; - } - } - } - Size += bufferLength; - } - - ulong PTSLast = 0; - ulong PTSDiff = 0; - foreach (var stream in Streams.Values) - { - if (!stream.IsVideoStream) continue; - - if (StreamStates.ContainsKey(stream.PID) && - StreamStates[stream.PID].PTSLast > PTSLast) - { - PTSLast = StreamStates[stream.PID].PTSLast; - PTSDiff = PTSLast - StreamStates[stream.PID].DTSPrev; - } - UpdateStreamBitrates(stream.PID, PTSLast, PTSDiff); - } - } - finally - { - if (fileStream != null) - { - fileStream.Dispose(); - } - } - } - - private TSStream CreateStream( - ushort streamPID, - byte streamType, - List streamDescriptors) - { - TSStream stream = null; - - switch ((TSStreamType)streamType) - { - case TSStreamType.MVC_VIDEO: - case TSStreamType.AVC_VIDEO: - case TSStreamType.MPEG1_VIDEO: - case TSStreamType.MPEG2_VIDEO: - case TSStreamType.VC1_VIDEO: - { - stream = new TSVideoStream(); - } - break; - - case TSStreamType.AC3_AUDIO: - case TSStreamType.AC3_PLUS_AUDIO: - case TSStreamType.AC3_PLUS_SECONDARY_AUDIO: - case TSStreamType.AC3_TRUE_HD_AUDIO: - case TSStreamType.DTS_AUDIO: - case TSStreamType.DTS_HD_AUDIO: - case TSStreamType.DTS_HD_MASTER_AUDIO: - case TSStreamType.DTS_HD_SECONDARY_AUDIO: - case TSStreamType.LPCM_AUDIO: - case TSStreamType.MPEG1_AUDIO: - case TSStreamType.MPEG2_AUDIO: - { - stream = new TSAudioStream(); - } - break; - - case TSStreamType.INTERACTIVE_GRAPHICS: - case TSStreamType.PRESENTATION_GRAPHICS: - { - stream = new TSGraphicsStream(); - } - break; - - case TSStreamType.SUBTITLE: - { - stream = new TSTextStream(); - } - break; - - default: - break; - } - - if (stream != null && - !Streams.ContainsKey(streamPID)) - { - stream.PID = streamPID; - stream.StreamType = (TSStreamType)streamType; - stream.Descriptors = streamDescriptors; - Streams[stream.PID] = stream; - } - if (!StreamDiagnostics.ContainsKey(streamPID)) - { - StreamDiagnostics[streamPID] = - new List(); - } - - return stream; - } - } -} diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs new file mode 100644 index 000000000..91c8b2792 --- /dev/null +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BDInfo.IO; +using MediaBrowser.Model.IO; + +namespace MediaBrowser.MediaEncoding.BdInfo +{ + class BdInfoDirectoryInfo : BDInfo.IO.IDirectoryInfo + { + IFileSystem _fileSystem = null; + + FileSystemMetadata _impl = null; + + public string Name => _impl.Name; + + public string FullName => _impl.FullName; + + public IDirectoryInfo Parent + { + get + { + var parentFolder = System.IO.Path.GetDirectoryName(_impl.FullName); + if (parentFolder != null) + { + return new BdInfoDirectoryInfo(_fileSystem, parentFolder); + } + return null; + } + } + + public BdInfoDirectoryInfo(IFileSystem fileSystem, string path) + { + _fileSystem = fileSystem; + _impl = _fileSystem.GetDirectoryInfo(path); + } + + private BdInfoDirectoryInfo(IFileSystem fileSystem, FileSystemMetadata impl) + { + _fileSystem = fileSystem; + _impl = impl; + } + + public IDirectoryInfo[] GetDirectories() + { + return Array.ConvertAll(_fileSystem.GetDirectories(_impl.FullName).ToArray(), + x => new BdInfoDirectoryInfo(_fileSystem, x)); + } + + public IFileInfo[] GetFiles() + { + return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName).ToArray(), + x => new BdInfoFileInfo(_fileSystem, x)); + } + + public IFileInfo[] GetFiles(string searchPattern) + { + return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), + x => new BdInfoFileInfo(_fileSystem, x)); + } + + public IFileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption) + { + return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, + searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), + x => new BdInfoFileInfo(_fileSystem, x)); + } + + public static IDirectoryInfo FromFileSystemPath(Model.IO.IFileSystem fs, string path) + { + return new BdInfoDirectoryInfo(fs, path); + } + } +} diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index 3b6b91684..3260f3051 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using BDInfo; @@ -32,7 +32,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo throw new ArgumentNullException(nameof(path)); } - var bdrom = new BDROM(path, _fileSystem); + var bdrom = new BDROM(BdInfoDirectoryInfo.FromFileSystemPath(_fileSystem, path)); bdrom.Scan(); diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs new file mode 100644 index 000000000..de9d7cb78 --- /dev/null +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -0,0 +1,40 @@ +using MediaBrowser.Model.IO; + +namespace MediaBrowser.MediaEncoding.BdInfo +{ + class BdInfoFileInfo : BDInfo.IO.IFileInfo + { + IFileSystem _fileSystem = null; + + FileSystemMetadata _impl = null; + + public string Name => _impl.Name; + + public string FullName => _impl.FullName; + + public string Extension => _impl.Extension; + + public long Length => _impl.Length; + + public bool IsDir => _impl.IsDirectory; + + public BdInfoFileInfo(IFileSystem fileSystem, FileSystemMetadata impl) + { + _fileSystem = fileSystem; + _impl = impl; + } + + public System.IO.Stream OpenRead() + { + return _fileSystem.GetFileStream(FullName, + FileOpenMode.Open, + FileAccessMode.Read, + FileShareMode.Read); + } + + public System.IO.StreamReader OpenText() + { + return new System.IO.StreamReader(OpenRead()); + } + } +} diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 558ea7d67..74a5e53b2 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -11,13 +11,13 @@ - + diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 27c8c1668..0d2a3b885 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -25,8 +25,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Photos", "Emby.Photos\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BDInfo", "BDInfo\BDInfo.csproj", "{88AE38DF-19D7-406F-A6A9-09527719A21E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}" -- cgit v1.2.3 From d4b438791f49dc74fe05ad20575d5f0c111ee234 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Fri, 8 Nov 2019 12:49:00 +0100 Subject: Don't append transcodes to transcoding temp path --- .../AppBase/BaseConfigurationManager.cs | 6 ++-- Emby.Server.Implementations/ApplicationHost.cs | 5 ++-- .../Configuration/ServerConfigurationManager.cs | 33 +-------------------- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 7 ++--- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 5 ++-- .../LiveTv/TunerHosts/LiveStream.cs | 12 ++++---- .../LiveTv/TunerHosts/M3UTunerHost.cs | 4 +-- .../LiveTv/TunerHosts/SharedHttpStream.cs | 5 ++-- .../Tasks/DeleteTranscodeFileTask.cs | 22 ++++---------- .../ServerApplicationPaths.cs | 34 ---------------------- MediaBrowser.Api/ApiEntryPoint.cs | 8 +---- MediaBrowser.Api/Playback/BaseStreamingService.cs | 7 +++-- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 13 ++++----- .../EncodingConfigurationExtensions.cs | 28 ++++++++++++++++++ MediaBrowser.Controller/IServerApplicationPaths.cs | 8 ----- .../MediaEncoding/EncodingHelper.cs | 1 - .../Configuration/EncodingConfigurationFactory.cs | 30 +++++++------------ 17 files changed, 77 insertions(+), 151 deletions(-) create mode 100644 MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 7ec5252d0..14ad1235f 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; @@ -16,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.AppBase { /// - /// Class BaseConfigurationManager + /// Class BaseConfigurationManager. /// public abstract class BaseConfigurationManager : IConfigurationManager { @@ -314,8 +313,7 @@ namespace Emby.Server.Implementations.AppBase throw new ArgumentException("Expected configuration type is " + configurationType.Name); } - var validatingStore = configurationStore as IValidatingConfiguration; - if (validatingStore != null) + if (configurationStore is IValidatingConfiguration validatingStore) { var currentConfiguration = GetConfiguration(key); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3a607aa54..65f9f491b 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -88,7 +88,6 @@ using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -110,7 +109,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using ServiceStack; using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; @@ -1424,6 +1422,7 @@ namespace Emby.Server.Implementations public async Task GetSystemInfo(CancellationToken cancellationToken) { var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false); + var transcodingTempPath = ConfigurationManager.GetTranscodePath(); return new SystemInfo { @@ -1447,7 +1446,7 @@ namespace Emby.Server.Implementations CanSelfRestart = CanSelfRestart, CanLaunchWebBrowser = CanLaunchWebBrowser, HasUpdateAvailable = HasUpdateAvailable, - TranscodingTempPath = ApplicationPaths.TranscodePath, + TranscodingTempPath = transcodingTempPath, ServerName = FriendlyName, LocalAddress = localAddress, SupportsLibraryMonitor = true, diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index fe705cbe2..2291345be 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using Emby.Server.Implementations.AppBase; using MediaBrowser.Common.Configuration; @@ -14,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Configuration { /// - /// Class ServerConfigurationManager + /// Class ServerConfigurationManager. /// public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager { @@ -62,13 +61,6 @@ namespace Emby.Server.Implementations.Configuration base.OnConfigurationUpdated(); } - public override void AddParts(IEnumerable factories) - { - base.AddParts(factories); - - UpdateTranscodePath(); - } - /// /// Updates the metadata path. /// @@ -84,28 +76,6 @@ namespace Emby.Server.Implementations.Configuration } } - /// - /// Updates the transcoding temporary path. - /// - private void UpdateTranscodePath() - { - var encodingConfig = this.GetConfiguration("encoding"); - - ((ServerApplicationPaths)ApplicationPaths).TranscodePath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ? - null : - Path.Combine(encodingConfig.TranscodingTempPath, "transcodes"); - } - - protected override void OnNamedConfigurationUpdated(string key, object configuration) - { - base.OnNamedConfigurationUpdated(key, configuration); - - if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase)) - { - UpdateTranscodePath(); - } - } - /// /// Replaces the configuration. /// @@ -123,7 +93,6 @@ namespace Emby.Server.Implementations.Configuration base.ReplaceConfiguration(newConfiguration); } - /// /// Validates the SSL certificate. /// diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index da98f3e58..440e8f4f0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -582,11 +582,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun modelInfo.TunerCount, FileSystem, Logger, - Config.ApplicationPaths, + Config, _appHost, _networkManager, _streamHelper); - } var enableHttpStream = true; @@ -611,7 +610,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun FileSystem, _httpClient, Logger, - Config.ApplicationPaths, + Config, _appHost, _streamHelper); } @@ -624,7 +623,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun modelInfo.TunerCount, FileSystem, Logger, - Config.ApplicationPaths, + Config, _appHost, _networkManager, _streamHelper); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index eafa86d54..649becbd3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -6,6 +6,7 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; @@ -33,11 +34,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun int numTuners, IFileSystem fileSystem, ILogger logger, - IServerApplicationPaths appPaths, + IConfigurationManager configurationManager, IServerApplicationHost appHost, INetworkManager networkManager, IStreamHelper streamHelper) - : base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths, streamHelper) + : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper) { _appHost = appHost; _networkManager = networkManager; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 2ea171031..1d55e7992 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -5,8 +5,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller; using MediaBrowser.Controller.Library; +using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; @@ -16,8 +16,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class LiveStream : ILiveStream { + private readonly IConfigurationManager _configurationManager; + protected readonly IFileSystem FileSystem; - protected readonly IServerApplicationPaths AppPaths; + protected readonly IStreamHelper StreamHelper; protected string TempFilePath; @@ -29,7 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts TunerHostInfo tuner, IFileSystem fileSystem, ILogger logger, - IServerApplicationPaths appPaths, + IConfigurationManager configurationManager, IStreamHelper streamHelper) { OriginalMediaSource = mediaSource; @@ -44,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts TunerHostId = tuner.Id; } - AppPaths = appPaths; + _configurationManager = configurationManager; StreamHelper = streamHelper; ConsumerCount = 1; @@ -68,7 +70,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts protected void SetTempFilePath(string extension) { - TempFilePath = Path.Combine(AppPaths.GetTranscodePath(), UniqueId + "." + extension); + TempFilePath = Path.Combine(_configurationManager.GetTranscodePath(), UniqueId + "." + extension); } public virtual Task Open(CancellationToken openCancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index a02a9ade4..df054f1eb 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -114,11 +114,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { - return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _streamHelper); + return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config, _appHost, _streamHelper); } } - return new LiveStream(mediaSource, info, FileSystem, Logger, Config.ApplicationPaths, _streamHelper); + return new LiveStream(mediaSource, info, FileSystem, Logger, Config, _streamHelper); } public async Task Validate(TunerHostInfo info) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index c6e894560..758495362 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; @@ -26,10 +27,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, - IServerApplicationPaths appPaths, + IConfigurationManager configurationManager, IServerApplicationHost appHost, IStreamHelper streamHelper) - : base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths, streamHelper) + : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper) { _httpClient = httpClient; _appHost = appHost; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index 200649ba9..91d990137 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -15,24 +16,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask { - /// - /// Gets or sets the application paths. - /// - /// The application paths. - private ServerApplicationPaths ApplicationPaths { get; set; } - private readonly ILogger _logger; - + private readonly IConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; /// /// Initializes a new instance of the class. /// - public DeleteTranscodeFileTask(ServerApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem) + public DeleteTranscodeFileTask(ILogger logger, IFileSystem fileSystem, IConfigurationManager configurationManager) { - ApplicationPaths = appPaths; _logger = logger; _fileSystem = fileSystem; + _configurationManager = configurationManager; } /// @@ -52,14 +47,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks var minDateModified = DateTime.UtcNow.AddDays(-1); progress.Report(50); - try - { - DeleteTempFilesFromDirectory(cancellationToken, ApplicationPaths.TranscodePath, minDateModified, progress); - } - catch (DirectoryNotFoundException) - { - // No biggie here. Nothing to delete - } + DeleteTempFilesFromDirectory(cancellationToken, _configurationManager.GetTranscodingTempPath(), minDateModified, progress); return Task.CompletedTask; } diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index 87de9804a..4b8298abb 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -107,40 +107,6 @@ namespace Emby.Server.Implementations /// The user configuration directory path. public string UserConfigurationDirectoryPath => Path.Combine(ConfigurationDirectoryPath, "users"); - public string DefaultTranscodePath => _defaultTranscodePath ?? (_defaultTranscodePath = Path.Combine(ProgramDataPath, "transcodes")); - - public string TranscodePath - { - get => _transcodePath ?? (_transcodePath = DefaultTranscodePath); - set => _transcodePath = value; - } - - public string GetTranscodePath() - { - var path = TranscodePath; - - if (!string.Equals(path, DefaultTranscodePath, StringComparison.OrdinalIgnoreCase)) - { - try - { - Directory.CreateDirectory(path); - - var testPath = Path.Combine(path, Guid.NewGuid().ToString()); - Directory.CreateDirectory(testPath); - Directory.Delete(testPath); - - return path; - } - catch - { - } - } - - path = DefaultTranscodePath; - Directory.CreateDirectory(path); - return path; - } - public string InternalMetadataPath { get => _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata")); diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index a962b0240..0542807af 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -13,7 +13,6 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; @@ -157,17 +156,12 @@ namespace MediaBrowser.Api return Task.CompletedTask; } - public EncodingOptions GetEncodingOptions() - { - return ConfigurationManagerExtensions.GetConfiguration(ConfigurationManager, "encoding"); - } - /// /// Deletes the encoded media cache. /// private void DeleteEncodedMediaCache() { - var path = ConfigurationManager.ApplicationPaths.GetTranscodePath(); + var path = ConfigurationManager.GetTranscodePath(); if (!Directory.Exists(path)) { diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index c7104c950..537980e02 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; @@ -141,7 +142,7 @@ namespace MediaBrowser.Api.Playback var filename = data.GetMD5().ToString("N", CultureInfo.InvariantCulture); var ext = outputFileExtension.ToLowerInvariant(); - var folder = ServerConfigurationManager.ApplicationPaths.TranscodePath; + var folder = ServerConfigurationManager.GetTranscodePath(); if (EnableOutputInSubFolder) { @@ -215,7 +216,7 @@ namespace MediaBrowser.Api.Playback } } - var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); + var encodingOptions = ServerConfigurationManager.GetEncodingOptions(); var process = new Process() { @@ -845,7 +846,7 @@ namespace MediaBrowser.Api.Playback ? GetOutputFileExtension(state) : ('.' + state.OutputContainer); - var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); + var encodingOptions = ServerConfigurationManager.GetEncodingOptions(); state.OutputFilePath = GetOutputFilePath(state, encodingOptions, ext); diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 7487f2b64..ca5a73ff1 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; -using MediaBrowser.Controller; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; @@ -83,13 +83,11 @@ namespace MediaBrowser.Api.Playback.Hls public class HlsSegmentService : BaseApiService { - private readonly IServerApplicationPaths _appPaths; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config, IFileSystem fileSystem) + public HlsSegmentService(IServerConfigurationManager config, IFileSystem fileSystem) { - _appPaths = appPaths; _config = config; _fileSystem = fileSystem; } @@ -97,7 +95,7 @@ namespace MediaBrowser.Api.Playback.Hls public Task Get(GetHlsPlaylistLegacy request) { var file = request.PlaylistId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodePath, file); + file = Path.Combine(_config.GetTranscodePath(), file); return GetFileResult(file, file); } @@ -115,8 +113,7 @@ namespace MediaBrowser.Api.Playback.Hls public Task Get(GetHlsVideoSegmentLegacy request) { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - - var transcodeFolderPath = _config.ApplicationPaths.TranscodePath; + var transcodeFolderPath = _config.GetTranscodePath(); file = Path.Combine(transcodeFolderPath, file); var normalizedPlaylistId = request.PlaylistId; @@ -136,7 +133,7 @@ namespace MediaBrowser.Api.Playback.Hls { // TODO: Deprecate with new iOS app var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_appPaths.TranscodePath, file); + file = Path.Combine(_config.GetTranscodePath(), file); return ResultFactory.GetStaticFileResult(Request, file, FileShareMode.ReadWrite); } diff --git a/MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs b/MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs new file mode 100644 index 000000000..6a3e94645 --- /dev/null +++ b/MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs @@ -0,0 +1,28 @@ +using System.IO; +using MediaBrowser.Model.Configuration; + +namespace MediaBrowser.Common.Configuration +{ + /// + /// Class containing extension methods for working with the encoding configuration. + /// + public static class EncodingConfigurationExtensions + { + /// + /// Gets the encoding options. + /// + /// The configuration manager. + /// The encoding options. + public static EncodingOptions GetEncodingOptions(this IConfigurationManager configurationManager) + => configurationManager.GetConfiguration("encoding"); + + /// + /// Retrieves the transcoding temp path from the encoding configuration. + /// + /// The Configuration manager. + /// The transcoding temp path. + public static string GetTranscodePath(this IConfigurationManager configurationManager) + => configurationManager.GetEncodingOptions().TranscodingTempPath + ?? Path.Combine(configurationManager.CommonApplicationPaths.ProgramDataPath, "transcoding-temp"); + } +} diff --git a/MediaBrowser.Controller/IServerApplicationPaths.cs b/MediaBrowser.Controller/IServerApplicationPaths.cs index 127a31329..56e7e4e47 100644 --- a/MediaBrowser.Controller/IServerApplicationPaths.cs +++ b/MediaBrowser.Controller/IServerApplicationPaths.cs @@ -82,12 +82,6 @@ namespace MediaBrowser.Controller /// The user configuration directory path. string UserConfigurationDirectoryPath { get; } - /// - /// Gets the transcoding temporary path. - /// - /// The transcoding temporary path. - string TranscodePath { get; } - /// /// Gets the internal metadata path. /// @@ -96,7 +90,5 @@ namespace MediaBrowser.Controller string VirtualInternalMetadataPath { get; } string ArtistsPath { get; } - - string GetTranscodePath(); } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 4dfb27130..349e371a7 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -10,7 +10,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index bb806ee55..75534b5bd 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -1,54 +1,46 @@ +using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.Configuration { public class EncodingConfigurationFactory : IConfigurationFactory { - private readonly IFileSystem _fileSystem; - - public EncodingConfigurationFactory(IFileSystem fileSystem) - { - _fileSystem = fileSystem; - } - public IEnumerable GetConfigurations() { return new[] { - new EncodingConfigurationStore(_fileSystem) + new EncodingConfigurationStore() }; } } public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration { - private readonly IFileSystem _fileSystem; - - public EncodingConfigurationStore(IFileSystem fileSystem) + public EncodingConfigurationStore() { ConfigurationType = typeof(EncodingOptions); Key = "encoding"; - _fileSystem = fileSystem; } public void Validate(object oldConfig, object newConfig) { - var oldEncodingConfig = (EncodingOptions)oldConfig; - var newEncodingConfig = (EncodingOptions)newConfig; - - var newPath = newEncodingConfig.TranscodingTempPath; + var newPath = ((EncodingOptions)newConfig).TranscodingTempPath; if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath)) + && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal)) { // Validate if (!Directory.Exists(newPath)) { - throw new FileNotFoundException(string.Format("{0} does not exist.", newPath)); + throw new DirectoryNotFoundException( + string.Format( + CultureInfo.InvariantCulture, + "{0} does not exist.", + newPath)); } } } -- cgit v1.2.3 From 3cf9313c86baaa8b7520b65d4eaa527b90964e50 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 4 Nov 2019 21:57:57 +0100 Subject: Update deps --- Emby.Naming/Emby.Naming.csproj | 4 ++-- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 11 ++++++----- Jellyfin.Server/Jellyfin.Server.csproj | 13 ++++++------- .../MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 9 ++------- MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 4 ---- .../Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj | 2 +- 8 files changed, 19 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index fd0773df5..7258beaf4 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -3,6 +3,7 @@ netstandard2.1 false + true @@ -18,12 +19,11 @@ Jellyfin.Naming https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt https://github.com/jellyfin/jellyfin - true - + diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index a71c75127..64692c370 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -22,7 +22,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 45607dc09..214ea5aff 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -28,11 +28,12 @@ - - - + + + + - + @@ -49,7 +50,7 @@ - + diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 4238d7fe3..8afeb8750 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -22,7 +22,7 @@ - + @@ -34,15 +34,14 @@ - - - + + + - - - + + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 558ea7d67..e977bd8fe 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -19,7 +19,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index ae2102806..8d373be28 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -11,8 +11,8 @@ - - + + @@ -24,9 +24,4 @@ true - - - latest - - diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index ecc61a8d8..0d62cf8c5 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,8 +15,4 @@ true - - latest - - diff --git a/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj b/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj index 4d5046bf9..bea2e6f0f 100644 --- a/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj +++ b/benches/Jellyfin.Common.Benches/Jellyfin.Common.Benches.csproj @@ -6,7 +6,7 @@ - + -- cgit v1.2.3 From cc5acf37f75d2c652d9cd855ebc34a1e7d414a9f Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 26 Oct 2019 22:53:53 +0200 Subject: Make probesize and analyzeduration configurable and simplify circular dependencies Makes the probesize and analyzeduration configurable with env args. (`JELLYFIN_FFmpeg_probesize` and `FFmpeg_analyzeduration`) --- Emby.Server.Implementations/ApplicationHost.cs | 23 ++- .../ConfigurationOptions.cs | 9 +- .../Emby.Server.Implementations.csproj | 1 - .../HttpServer/HttpListenerHost.cs | 2 +- Jellyfin.Server/Program.cs | 7 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 11 +- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 56 +++--- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 9 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 56 +++--- .../Playback/Progressive/AudioService.cs | 8 +- .../Progressive/BaseProgressiveStreamingService.cs | 11 +- .../Playback/Progressive/VideoService.cs | 8 +- MediaBrowser.Api/Playback/UniversalAudioService.cs | 63 +++---- MediaBrowser.Controller/Entities/Video.cs | 5 +- .../Extensions/ConfigurationExtensions.cs | 36 ++++ .../MediaBrowser.Controller.csproj | 4 + .../MediaEncoding/EncodingHelper.cs | 31 +++- .../MediaEncoding/IMediaEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 191 ++++++++++----------- .../Subtitles/ISubtitleWriter.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs | 36 ++-- MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs | 17 +- .../Subtitles/SubtitleEncoder.cs | 103 ++++++----- MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs | 7 - .../Configuration/ServerConfiguration.cs | 1 - MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs | 7 +- .../MediaInfo/VideoImageProvider.cs | 6 +- .../Music/MusicBrainzAlbumProvider.cs | 2 +- 28 files changed, 396 insertions(+), 320 deletions(-) create mode 100644 MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bd5e973c0..1c034ca79 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -886,16 +886,14 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(ChapterManager); MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - LoggerFactory, - JsonSerializer, - StartupOptions.FFmpegPath, + LoggerFactory.CreateLogger(), ServerConfigurationManager, FileSystemManager, - () => SubtitleEncoder, - () => MediaSourceManager, ProcessFactory, - 5000, - LocalizationManager); + LocalizationManager, + () => SubtitleEncoder, + _configuration, + StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); @@ -912,10 +910,19 @@ namespace Emby.Server.Implementations AuthService = new AuthService(authContext, ServerConfigurationManager, SessionManager, NetworkManager); serviceCollection.AddSingleton(AuthService); - SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory); + SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder( + LibraryManager, + LoggerFactory.CreateLogger(), + ApplicationPaths, + FileSystemManager, + MediaEncoder, + HttpClient, + MediaSourceManager, + ProcessFactory); serviceCollection.AddSingleton(SubtitleEncoder); serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); + serviceCollection.AddSingleton(); _displayPreferencesRepository.Initialize(); diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index 62408ee70..445a554b2 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -1,13 +1,16 @@ using System.Collections.Generic; +using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Emby.Server.Implementations { public static class ConfigurationOptions { - public static readonly Dictionary Configuration = new Dictionary + public static Dictionary Configuration => new Dictionary { - { "HttpListenerHost:DefaultRedirectPath", "web/index.html" }, - { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" } + { "HttpListenerHost_DefaultRedirectPath", "web/index.html" }, + { "MusicBrainz_BaseUrl", "https://www.musicbrainz.org" }, + { FfmpegProbeSizeKey, "1G" }, + { FfmpegAnalyzeDuration, "200M" } }; } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 214ea5aff..618f54ce7 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -28,7 +28,6 @@ - diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index dc1a56e27..2736339b1 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.HttpServer _appHost = applicationHost; _logger = logger; _config = config; - _defaultRedirectPath = configuration["HttpListenerHost:DefaultRedirectPath"]; + _defaultRedirectPath = configuration["HttpListenerHost_DefaultRedirectPath"]; _baseUrlPrefix = _config.Configuration.BaseUrl; _networkManager = networkManager; _jsonSerializer = jsonSerializer; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index bdf3689f1..c9ca79a2b 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.Security; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -133,6 +134,10 @@ namespace Jellyfin.Server ApplicationHost.LogEnvironmentInfo(_logger, appPaths); + // Make sure we have all the code pages we can get + // Ref: https://docs.microsoft.com/en-us/dotnet/api/system.text.codepagesencodingprovider.instance?view=netcore-3.0#remarks + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + // Increase the max http request limit // The default connection limit is 10 for ASP.NET hosted applications and 2 for all others. ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit); @@ -369,9 +374,9 @@ namespace Jellyfin.Server return new ConfigurationBuilder() .SetBasePath(appPaths.ConfigurationDirectoryPath) + .AddInMemoryCollection(ConfigurationOptions.Configuration) .AddJsonFile("logging.json", false, true) .AddEnvironmentVariables("JELLYFIN_") - .AddInMemoryCollection(ConfigurationOptions.Configuration) .Build(); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4bd729aac..d554930ac 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -69,8 +69,6 @@ namespace MediaBrowser.Api.Playback protected IDeviceManager DeviceManager { get; private set; } - protected ISubtitleEncoder SubtitleEncoder { get; private set; } - protected IMediaSourceManager MediaSourceManager { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } @@ -96,11 +94,11 @@ namespace MediaBrowser.Api.Playback IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) { ServerConfigurationManager = serverConfig; UserManager = userManager; @@ -109,13 +107,12 @@ namespace MediaBrowser.Api.Playback MediaEncoder = mediaEncoder; FileSystem = fileSystem; DlnaManager = dlnaManager; - SubtitleEncoder = subtitleEncoder; DeviceManager = deviceManager; MediaSourceManager = mediaSourceManager; JsonSerializer = jsonSerializer; AuthorizationContext = authorizationContext; - EncodingHelper = new EncodingHelper(MediaEncoder, FileSystem, SubtitleEncoder); + EncodingHelper = encodingHelper; } /// @@ -152,8 +149,6 @@ namespace MediaBrowser.Api.Playback return Path.Combine(folder, filename + ext); } - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - protected virtual string GetDefaultEncoderPreset() { return "superfast"; diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 27eb67ee6..390e85d08 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -25,6 +25,34 @@ namespace MediaBrowser.Api.Playback.Hls /// public abstract class BaseHlsService : BaseStreamingService { + public BaseHlsService( + IServerConfigurationManager serverConfig, + IUserManager userManager, + ILibraryManager libraryManager, + IIsoManager isoManager, + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + IDlnaManager dlnaManager, + IDeviceManager deviceManager, + IMediaSourceManager mediaSourceManager, + IJsonSerializer jsonSerializer, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base(serverConfig, + userManager, + libraryManager, + isoManager, + mediaEncoder, + fileSystem, + dlnaManager, + deviceManager, + mediaSourceManager, + jsonSerializer, + authorizationContext, + encodingHelper) + { + } + /// /// Gets the audio arguments. /// @@ -313,33 +341,5 @@ namespace MediaBrowser.Api.Playback.Hls { return 0; } - - public BaseHlsService( - IServerConfigurationManager serverConfig, - IUserManager userManager, - ILibraryManager libraryManager, - IIsoManager isoManager, - IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, - IDeviceManager deviceManager, - IMediaSourceManager mediaSourceManager, - IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, - userManager, - libraryManager, - isoManager, - mediaEncoder, - fileSystem, - dlnaManager, - subtitleEncoder, - deviceManager, - mediaSourceManager, - jsonSerializer, - authorizationContext) - { - } } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 9ecb5fe8c..60a1f6899 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -94,7 +94,6 @@ namespace MediaBrowser.Api.Playback.Hls [Authenticated] public class DynamicHlsService : BaseHlsService { - public DynamicHlsService( IServerConfigurationManager serverConfig, IUserManager userManager, @@ -103,12 +102,12 @@ namespace MediaBrowser.Api.Playback.Hls IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, - INetworkManager networkManager) + INetworkManager networkManager, + EncodingHelper encodingHelper) : base(serverConfig, userManager, libraryManager, @@ -116,11 +115,11 @@ namespace MediaBrowser.Api.Playback.Hls mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { NetworkManager = networkManager; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 4a5f4025b..cada7138c 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -26,6 +26,34 @@ namespace MediaBrowser.Api.Playback.Hls [Authenticated] public class VideoHlsService : BaseHlsService { + public VideoHlsService( + IServerConfigurationManager serverConfig, + IUserManager userManager, + ILibraryManager libraryManager, + IIsoManager isoManager, + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + IDlnaManager dlnaManager, + IDeviceManager deviceManager, + IMediaSourceManager mediaSourceManager, + IJsonSerializer jsonSerializer, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base(serverConfig, + userManager, + libraryManager, + isoManager, + mediaEncoder, + fileSystem, + dlnaManager, + deviceManager, + mediaSourceManager, + jsonSerializer, + authorizationContext, + encodingHelper) + { + } + public Task Get(GetLiveHlsStream request) { return ProcessRequestAsync(request, true); @@ -135,33 +163,5 @@ namespace MediaBrowser.Api.Playback.Hls return args; } - - public VideoHlsService( - IServerConfigurationManager serverConfig, - IUserManager userManager, - ILibraryManager libraryManager, - IIsoManager isoManager, - IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, - IDeviceManager deviceManager, - IMediaSourceManager mediaSourceManager, - IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, - userManager, - libraryManager, - isoManager, - mediaEncoder, - fileSystem, - dlnaManager, - subtitleEncoder, - deviceManager, - mediaSourceManager, - jsonSerializer, - authorizationContext) - { - } } } diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index dfe4b2b8e..5679a4e17 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -40,11 +40,11 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) : base(httpClient, serverConfig, userManager, @@ -53,11 +53,11 @@ namespace MediaBrowser.Api.Playback.Progressive mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 97c1a7a49..ee7b99c2a 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -35,23 +35,24 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base( + serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { HttpClient = httpClient; } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index cfc8a283d..976e11b47 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -77,11 +77,11 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) : base(httpClient, serverConfig, userManager, @@ -90,11 +90,11 @@ namespace MediaBrowser.Api.Playback.Progressive mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { } diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index b3d8bfe59..70c0f4b01 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -9,7 +9,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; @@ -75,6 +74,9 @@ namespace MediaBrowser.Api.Playback [Authenticated] public class UniversalAudioService : BaseApiService { + private readonly ILoggerFactory _loggerFactory; + private readonly EncodingHelper _encodingHelper; + public UniversalAudioService( IHttpClient httpClient, IServerConfigurationManager serverConfigurationManager, @@ -85,14 +87,12 @@ namespace MediaBrowser.Api.Playback IFileSystem fileSystem, IDlnaManager dlnaManager, IDeviceManager deviceManager, - ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, - IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, - IImageProcessor imageProcessor, INetworkManager networkManager, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + EncodingHelper encodingHelper) { HttpClient = httpClient; ServerConfigurationManager = serverConfigurationManager; @@ -103,15 +103,12 @@ namespace MediaBrowser.Api.Playback FileSystem = fileSystem; DlnaManager = dlnaManager; DeviceManager = deviceManager; - SubtitleEncoder = subtitleEncoder; MediaSourceManager = mediaSourceManager; - ZipClient = zipClient; JsonSerializer = jsonSerializer; AuthorizationContext = authorizationContext; - ImageProcessor = imageProcessor; NetworkManager = networkManager; _loggerFactory = loggerFactory; - _logger = loggerFactory.CreateLogger(nameof(UniversalAudioService)); + _encodingHelper = encodingHelper; } protected IHttpClient HttpClient { get; private set; } @@ -123,15 +120,10 @@ namespace MediaBrowser.Api.Playback protected IFileSystem FileSystem { get; private set; } protected IDlnaManager DlnaManager { get; private set; } protected IDeviceManager DeviceManager { get; private set; } - protected ISubtitleEncoder SubtitleEncoder { get; private set; } protected IMediaSourceManager MediaSourceManager { get; private set; } - protected IZipClient ZipClient { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } protected IAuthorizationContext AuthorizationContext { get; private set; } - protected IImageProcessor ImageProcessor { get; private set; } protected INetworkManager NetworkManager { get; private set; } - private ILoggerFactory _loggerFactory; - private ILogger _logger; public Task Get(GetUniversalAudioStream request) { @@ -242,7 +234,17 @@ namespace MediaBrowser.Api.Playback AuthorizationContext.GetAuthorizationInfo(Request).DeviceId = request.DeviceId; - var mediaInfoService = new MediaInfoService(MediaSourceManager, DeviceManager, LibraryManager, ServerConfigurationManager, NetworkManager, MediaEncoder, UserManager, JsonSerializer, AuthorizationContext, _loggerFactory) + var mediaInfoService = new MediaInfoService( + MediaSourceManager, + DeviceManager, + LibraryManager, + ServerConfigurationManager, + NetworkManager, + MediaEncoder, + UserManager, + JsonSerializer, + AuthorizationContext, + _loggerFactory) { Request = Request }; @@ -276,19 +278,20 @@ namespace MediaBrowser.Api.Playback if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - var service = new DynamicHlsService(ServerConfigurationManager, - UserManager, - LibraryManager, - IsoManager, - MediaEncoder, - FileSystem, - DlnaManager, - SubtitleEncoder, - DeviceManager, - MediaSourceManager, - JsonSerializer, - AuthorizationContext, - NetworkManager) + var service = new DynamicHlsService( + ServerConfigurationManager, + UserManager, + LibraryManager, + IsoManager, + MediaEncoder, + FileSystem, + DlnaManager, + DeviceManager, + MediaSourceManager, + JsonSerializer, + AuthorizationContext, + NetworkManager, + _encodingHelper) { Request = Request }; @@ -330,11 +333,11 @@ namespace MediaBrowser.Api.Playback MediaEncoder, FileSystem, DlnaManager, - SubtitleEncoder, DeviceManager, MediaSourceManager, JsonSerializer, - AuthorizationContext) + AuthorizationContext, + _encodingHelper) { Request = Request }; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 60906bdb0..af4d227bc 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -137,7 +137,7 @@ namespace MediaBrowser.Controller.Entities /// The video3 D format. public Video3DFormat? Video3DFormat { get; set; } - public string[] GetPlayableStreamFileNames(IMediaEncoder mediaEncoder) + public string[] GetPlayableStreamFileNames() { var videoType = VideoType; @@ -153,7 +153,8 @@ namespace MediaBrowser.Controller.Entities { return Array.Empty(); } - return mediaEncoder.GetPlayableStreamFileNames(Path, videoType); + + throw new NotImplementedException(); } /// diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs new file mode 100644 index 000000000..80a98ad5f --- /dev/null +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Configuration; + +namespace MediaBrowser.Controller.Extensions +{ + /// + /// Configuration extensions for MediaBrowser.Controller. + /// + public static class ConfigurationExtensions + { + /// + /// The key for the FFmpeg probe size option. + /// + public const string FfmpegProbeSizeKey = "FFmpeg_probesize"; + + /// + /// The key for the FFmpeg analyse duration option. + /// + public const string FfmpegAnalyzeDuration = "FFmpeg_analyzeduration"; + + /// + /// Retrieves the FFmpeg probe size from the . + /// + /// This configuration. + /// The FFmpeg probe size option. + public static string GetProbeSize(this IConfiguration configuration) + => configuration[FfmpegProbeSizeKey]; + + /// + /// Retrieves the FFmpeg analyse duration from the . + /// + /// This configuration. + /// The FFmpeg analyse duration option. + public static string GetAnalyzeDuration(this IConfiguration configuration) + => configuration[FfmpegAnalyzeDuration]; + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 276eb71bc..60c76ef7d 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -7,6 +7,10 @@ https://github.com/jellyfin/jellyfin + + + + diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 349e371a7..d829db44b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using Microsoft.Extensions.Configuration; namespace MediaBrowser.Controller.MediaEncoding { @@ -22,6 +23,7 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfiguration _configuration; private static readonly string[] _videoProfiles = new[] { @@ -34,11 +36,16 @@ namespace MediaBrowser.Controller.MediaEncoding "ConstrainedHigh" }; - public EncodingHelper(IMediaEncoder mediaEncoder, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder) + public EncodingHelper( + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + ISubtitleEncoder subtitleEncoder, + IConfiguration configuration) { _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; + _configuration = configuration; } public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) @@ -172,7 +179,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Empty; } - public string GetInputFormat(string container) + public static string GetInputFormat(string container) { if (string.IsNullOrEmpty(container)) { @@ -641,7 +648,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language, state.MediaSource.Protocol, CancellationToken.None).Result; + var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet( + subtitlePath, + state.SubtitleStream.Language, + state.MediaSource.Protocol, + CancellationToken.None).GetAwaiter().GetResult(); if (!string.IsNullOrEmpty(charenc)) { @@ -1897,7 +1908,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If transcoding from 10 bit, transform colour spaces too if (!string.IsNullOrEmpty(videoStream.PixelFormat) && videoStream.PixelFormat.IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1 - && string.Equals(outputVideoCodec,"libx264", StringComparison.OrdinalIgnoreCase)) + && string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) { filters.Add("format=p010le"); filters.Add("format=nv12"); @@ -1946,7 +1957,9 @@ namespace MediaBrowser.Controller.MediaEncoding var output = string.Empty; - if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + if (state.SubtitleStream != null + && state.SubtitleStream.IsTextSubtitleStream + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { var subParam = GetTextSubtitleParam(state); @@ -2035,11 +2048,11 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public static string GetProbeSizeArgument(int numInputFiles) - => numInputFiles > 1 ? "-probesize 1G" : ""; + public string GetProbeSizeArgument(int numInputFiles) + => numInputFiles > 1 ? "-probesize " + _configuration["FFmpeg:probesize"] : string.Empty; - public static string GetAnalyzeDurationArgument(int numInputFiles) - => numInputFiles > 1 ? "-analyzeduration 200M" : ""; + public string GetAnalyzeDurationArgument(int numInputFiles) + => numInputFiles > 1 ? "-analyzeduration " + _configuration["FFmpeg:analyzeduration"] : string.Empty; public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions) { diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d032a849e..37f0b11a7 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -15,6 +15,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// public interface IMediaEncoder : ITranscoderSupport { + /// + /// The location of the discovered FFmpeg tool. + /// FFmpegLocation EncoderLocation { get; } /// @@ -97,7 +100,6 @@ namespace MediaBrowser.Controller.MediaEncoding void UpdateEncoderPath(string path, string pathType); bool SupportsEncoder(string encoder); - string[] GetPlayableStreamFileNames(string path, VideoType videoType); IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 04ff66991..6bcd6cd46 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Configuration; @@ -19,9 +19,9 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; namespace MediaBrowser.MediaEncoding.Encoder { @@ -31,55 +31,60 @@ namespace MediaBrowser.MediaEncoding.Encoder public class MediaEncoder : IMediaEncoder, IDisposable { /// - /// Gets the encoder path. + /// The default image extraction timeout in milliseconds. /// - /// The encoder path. - public string EncoderPath => FFmpegPath; - - /// - /// The location of the discovered FFmpeg tool. - /// - public FFmpegLocation EncoderLocation { get; private set; } + internal const int DefaultImageExtractionTimeout = 5000; private readonly ILogger _logger; - private readonly IJsonSerializer _jsonSerializer; - private string FFmpegPath; - private string FFprobePath; - protected readonly IServerConfigurationManager ConfigurationManager; - protected readonly IFileSystem FileSystem; - protected readonly Func SubtitleEncoder; - protected readonly Func MediaSourceManager; + private readonly IServerConfigurationManager _configurationManager; + private readonly IFileSystem _fileSystem; private readonly IProcessFactory _processFactory; - private readonly int DefaultImageExtractionTimeoutMs; - private readonly string StartupOptionFFmpegPath; + private readonly ILocalizationManager _localization; + private readonly Func _subtitleEncoder; + private readonly IConfiguration _configuration; + private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); + + private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); - private readonly ILocalizationManager _localization; + + private EncodingHelper _encodingHelper; + + private string _ffmpegPath; + private string _ffprobePath; public MediaEncoder( - ILoggerFactory loggerFactory, - IJsonSerializer jsonSerializer, - string startupOptionsFFmpegPath, + ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, - Func subtitleEncoder, - Func mediaSourceManager, IProcessFactory processFactory, - int defaultImageExtractionTimeoutMs, - ILocalizationManager localization) - { - _logger = loggerFactory.CreateLogger(nameof(MediaEncoder)); - _jsonSerializer = jsonSerializer; - StartupOptionFFmpegPath = startupOptionsFFmpegPath; - ConfigurationManager = configurationManager; - FileSystem = fileSystem; - SubtitleEncoder = subtitleEncoder; + ILocalizationManager localization, + Func subtitleEncoder, + IConfiguration configuration, + string startupOptionsFFmpegPath) + { + _logger = logger; + _configurationManager = configurationManager; + _fileSystem = fileSystem; _processFactory = processFactory; - DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs; _localization = localization; + _startupOptionFFmpegPath = startupOptionsFFmpegPath; + _subtitleEncoder = subtitleEncoder; + _configuration = configuration; } + private EncodingHelper EncodingHelper + => LazyInitializer.EnsureInitialized( + ref _encodingHelper, + () => new EncodingHelper(this, _fileSystem, _subtitleEncoder(), _configuration)); + + /// + public string EncoderPath => _ffmpegPath; + + /// + public FFmpegLocation EncoderLocation { get; private set; } + /// /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. @@ -88,39 +93,39 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetFFmpegPath() { // 1) Custom path stored in config/encoding xml file under tag takes precedence - if (!ValidatePath(ConfigurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) + if (!ValidatePath(_configurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) { // 2) Check if the --ffmpeg CLI switch has been given - if (!ValidatePath(StartupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument)) { // 3) Search system $PATH environment variable for valid FFmpeg if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) { EncoderLocation = FFmpegLocation.NotFound; - FFmpegPath = null; + _ffmpegPath = null; } } } // Write the FFmpeg path to the config/encoding.xml file as so it appears in UI - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathDisplay = FFmpegPath ?? string.Empty; - ConfigurationManager.SaveConfiguration("encoding", config); + var config = _configurationManager.GetConfiguration("encoding"); + config.EncoderAppPathDisplay = _ffmpegPath ?? string.Empty; + _configurationManager.SaveConfiguration("encoding", config); // Only if mpeg path is set, try and set path to probe - if (FFmpegPath != null) + if (_ffmpegPath != null) { // Determine a probe path from the mpeg path - FFprobePath = Regex.Replace(FFmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); + _ffprobePath = Regex.Replace(_ffmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); // Interrogate to understand what coders are supported - var validator = new EncoderValidator(_logger, FFmpegPath); + var validator = new EncoderValidator(_logger, _ffmpegPath); SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); } - _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, FFmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, _ffmpegPath ?? string.Empty); } /// @@ -160,9 +165,9 @@ namespace MediaBrowser.MediaEncoding.Encoder // Write the new ffmpeg path to the xml as // This ensures its not lost on next startup - var config = ConfigurationManager.GetConfiguration("encoding"); + var config = _configurationManager.GetConfiguration("encoding"); config.EncoderAppPath = newPath; - ConfigurationManager.SaveConfiguration("encoding", config); + _configurationManager.SaveConfiguration("encoding", config); // Trigger SetFFmpegPath so we validate the new path and setup probe path SetFFmpegPath(); @@ -193,7 +198,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // ToDo - Enable the ffmpeg validator. At the moment any version can be used. rc = true; - FFmpegPath = path; + _ffmpegPath = path; EncoderLocation = location; } else @@ -209,7 +214,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { try { - var files = FileSystem.GetFilePaths(path); + var files = _fileSystem.GetFilePaths(path); var excludeExtensions = new[] { ".c" }; @@ -304,7 +309,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters; - var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); + var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length); string analyzeDuration; @@ -365,7 +370,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Must consume both or ffmpeg may hang due to deadlocks. See comments below. RedirectStandardOutput = true, - FileName = FFprobePath, + FileName = _ffprobePath, Arguments = args, @@ -383,7 +388,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); } - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { _logger.LogDebug("Starting ffprobe with args {Args}", args); StartProcess(processWrapper); @@ -391,7 +396,7 @@ namespace MediaBrowser.MediaEncoding.Encoder InternalMediaInfoResult result; try { - result = await _jsonSerializer.DeserializeFromStreamAsync( + result = await JsonSerializer.DeserializeAsync( process.StandardOutput.BaseStream).ConfigureAwait(false); } catch @@ -423,7 +428,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return new ProbeResultNormalizer(_logger, FileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + return new ProbeResultNormalizer(_logger, _fileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); } } @@ -486,7 +491,7 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ArgumentNullException(nameof(inputPath)); } - var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); + var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. @@ -545,7 +550,6 @@ namespace MediaBrowser.MediaEncoding.Encoder args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args; } - var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder()); if (videoStream != null) { /* fix @@ -559,7 +563,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrWhiteSpace(container)) { - var inputFormat = encodinghelper.GetInputFormat(container); + var inputFormat = EncodingHelper.GetInputFormat(container); if (!string.IsNullOrWhiteSpace(inputFormat)) { args = "-f " + inputFormat + " " + args; @@ -570,7 +574,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFmpegPath, + FileName = _ffmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, @@ -579,7 +583,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { bool ranToCompletion; @@ -588,10 +592,10 @@ namespace MediaBrowser.MediaEncoding.Encoder { StartProcess(processWrapper); - var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs; + var timeoutMs = _configurationManager.Configuration.ImageExtractionTimeoutMs; if (timeoutMs <= 0) { - timeoutMs = DefaultImageExtractionTimeoutMs; + timeoutMs = DefaultImageExtractionTimeout; } ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false); @@ -607,7 +611,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; - var file = FileSystem.GetFileInfo(tempExtractPath); + var file = _fileSystem.GetFileInfo(tempExtractPath); if (exitCode == -1 || !file.Exists || file.Length == 0) { @@ -675,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Encoder args = analyzeDurationArgument + " " + args; } - var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder()); if (videoStream != null) { /* fix @@ -689,7 +692,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrWhiteSpace(container)) { - var inputFormat = encodinghelper.GetInputFormat(container); + var inputFormat = EncodingHelper.GetInputFormat(container); if (!string.IsNullOrWhiteSpace(inputFormat)) { args = "-f " + inputFormat + " " + args; @@ -700,7 +703,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFmpegPath, + FileName = _ffmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, @@ -713,7 +716,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion = false; - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { try { @@ -736,10 +739,10 @@ namespace MediaBrowser.MediaEncoding.Encoder cancellationToken.ThrowIfCancellationRequested(); - var jpegCount = FileSystem.GetFilePaths(targetDirectory) + var jpegCount = _fileSystem.GetFilePaths(targetDirectory) .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); - isResponsive = (jpegCount > lastCount); + isResponsive = jpegCount > lastCount; lastCount = jpegCount; } @@ -770,7 +773,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { process.Process.Start(); - lock (_runningProcesses) + lock (_runningProcessesLock) { _runningProcesses.Add(process); } @@ -804,7 +807,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void StopProcesses() { List proceses; - lock (_runningProcesses) + lock (_runningProcessesLock) { proceses = _runningProcesses.ToList(); _runningProcesses.Clear(); @@ -827,12 +830,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''"); } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// + /// public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// @@ -852,11 +854,6 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new NotImplementedException(); } - public string[] GetPlayableStreamFileNames(string path, VideoType videoType) - { - throw new NotImplementedException(); - } - public IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber) { throw new NotImplementedException(); @@ -870,21 +867,24 @@ namespace MediaBrowser.MediaEncoding.Encoder private class ProcessWrapper : IDisposable { - public readonly IProcess Process; - public bool HasExited; - public int? ExitCode; private readonly MediaEncoder _mediaEncoder; - private readonly ILogger _logger; - public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder, ILogger logger) + private bool _disposed = false; + + public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder) { Process = process; _mediaEncoder = mediaEncoder; - _logger = logger; - Process.Exited += Process_Exited; + Process.Exited += OnProcessExited; } - void Process_Exited(object sender, EventArgs e) + public IProcess Process { get; } + + public bool HasExited { get; private set; } + + public int? ExitCode { get; private set; } + + void OnProcessExited(object sender, EventArgs e) { var process = (IProcess)sender; @@ -903,7 +903,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void DisposeProcess(IProcess process) { - lock (_mediaEncoder._runningProcesses) + lock (_mediaEncoder._runningProcessesLock) { _mediaEncoder._runningProcesses.Remove(this); } @@ -917,23 +917,18 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - private bool _disposed; - private readonly object _syncLock = new object(); public void Dispose() { - lock (_syncLock) + if (!_disposed) { - if (!_disposed) + if (Process != null) { - if (Process != null) - { - Process.Exited -= Process_Exited; - DisposeProcess(Process); - } + Process.Exited -= OnProcessExited; + DisposeProcess(Process); } - - _disposed = true; } + + _disposed = true; } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs index 3401c2d67..dec714121 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { /// - /// Interface ISubtitleWriter + /// Interface ISubtitleWriter. /// public interface ISubtitleWriter { diff --git a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs index 8995fcfe1..241ebc6df 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs @@ -1,27 +1,39 @@ using System.IO; -using System.Text; +using System.Text.Json; using System.Threading; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.MediaEncoding.Subtitles { + /// + /// JSON subtitle writer. + /// public class JsonWriter : ISubtitleWriter { - private readonly IJsonSerializer _json; - - public JsonWriter(IJsonSerializer json) - { - _json = json; - } - + /// public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken) { - using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + using (var writer = new Utf8JsonWriter(stream)) { - var json = _json.SerializeToString(info); + var trackevents = info.TrackEvents; + writer.WriteStartArray("TrackEvents"); + + for (int i = 0; i < trackevents.Count; i++) + { + cancellationToken.ThrowIfCancellationRequested(); + + var current = trackevents[i]; + writer.WriteStartObject(); + + writer.WriteString("Id", current.Id); + writer.WriteString("Text", current.Text); + writer.WriteNumber("StartPositionTicks", current.StartPositionTicks); + writer.WriteNumber("EndPositionTicks", current.EndPositionTicks); + + writer.WriteEndObject(); + } - writer.Write(json); + writer.WriteEndObject(); } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs index 6f96a641e..45b317b2e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs @@ -14,14 +14,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles { using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { - var index = 1; + var trackEvents = info.TrackEvents; - foreach (var trackEvent in info.TrackEvents) + for (int i = 0; i < trackEvents.Count; i++) { cancellationToken.ThrowIfCancellationRequested(); - writer.WriteLine(index.ToString(CultureInfo.InvariantCulture)); - writer.WriteLine(@"{0:hh\:mm\:ss\,fff} --> {1:hh\:mm\:ss\,fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks)); + var trackEvent = trackEvents[i]; + + writer.WriteLine((i + 1).ToString(CultureInfo.InvariantCulture)); + writer.WriteLine( + @"{0:hh\:mm\:ss\,fff} --> {1:hh\:mm\:ss\,fff}", + TimeSpan.FromTicks(trackEvent.StartPositionTicks), + TimeSpan.FromTicks(trackEvent.EndPositionTicks)); var text = trackEvent.Text; @@ -29,9 +34,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = Regex.Replace(text, @"\\n", " ", RegexOptions.IgnoreCase); writer.WriteLine(text); - writer.WriteLine(string.Empty); - - index++; + writer.WriteLine(); } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d5fa76c3a..183d7566d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -17,7 +17,6 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; using UtfUnknown; @@ -30,28 +29,25 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; - private readonly IJsonSerializer _json; private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; private readonly IProcessFactory _processFactory; public SubtitleEncoder( ILibraryManager libraryManager, - ILoggerFactory loggerFactory, + ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, - IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IProcessFactory processFactory) { _libraryManager = libraryManager; - _logger = loggerFactory.CreateLogger(nameof(SubtitleEncoder)); + _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; - _json = json; _httpClient = httpClient; _mediaSourceManager = mediaSourceManager; _processFactory = processFactory; @@ -59,7 +55,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); - private Stream ConvertSubtitles(Stream stream, + private Stream ConvertSubtitles( + Stream stream, string inputFormat, string outputFormat, long startTimeTicks, @@ -170,7 +167,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles && (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd)) { var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSource.Id)); - inputFiles = mediaSourceItem.GetPlayableStreamFileNames(_mediaEncoder); + inputFiles = mediaSourceItem.GetPlayableStreamFileNames(); } else { @@ -179,32 +176,27 @@ namespace MediaBrowser.MediaEncoding.Subtitles var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); - var stream = await GetSubtitleStream(fileInfo.Path, subtitleStream.Language, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); return (stream, fileInfo.Format); } - private async Task GetSubtitleStream(string path, string language, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) + private async Task GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) { if (requiresCharset) { - var bytes = await GetBytes(path, protocol, cancellationToken).ConfigureAwait(false); - - var charset = CharsetDetector.DetectFromBytes(bytes).Detected?.EncodingName; - _logger.LogDebug("charset {CharSet} detected for {Path}", charset ?? "null", path); - - if (!string.IsNullOrEmpty(charset)) + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) { - // Make sure we have all the code pages we can get - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - using (var inputStream = new MemoryStream(bytes)) - using (var reader = new StreamReader(inputStream, Encoding.GetEncoding(charset))) + var result = CharsetDetector.DetectFromStream(stream).Detected; + + if (result != null) { - var text = await reader.ReadToEndAsync().ConfigureAwait(false); + _logger.LogDebug("charset {CharSet} detected for {Path}", result.EncodingName, path); - bytes = Encoding.UTF8.GetBytes(text); + using var reader = new StreamReader(stream, result.Encoding); + var text = await reader.ReadToEndAsync().ConfigureAwait(false); - return new MemoryStream(bytes); + return new MemoryStream(Encoding.UTF8.GetBytes(text)); } } } @@ -323,7 +315,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase)) { - return new JsonWriter(_json); + return new JsonWriter(); } if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { @@ -544,7 +536,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, outputCodec, outputPath, cancellationToken).ConfigureAwait(false); + await ExtractTextSubtitleInternal( + _mediaEncoder.GetInputArgument(inputFiles, protocol), + subtitleStreamIndex, + outputCodec, + outputPath, + cancellationToken).ConfigureAwait(false); } } finally @@ -572,8 +569,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, - subtitleStreamIndex, outputCodec, outputPath); + var processArgs = string.Format( + CultureInfo.InvariantCulture, + "-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", + inputPath, + subtitleStreamIndex, + outputCodec, + outputPath); var process = _processFactory.Create(new ProcessOptions { @@ -721,41 +723,38 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } + /// public async Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken) { - var bytes = await GetBytes(path, protocol, cancellationToken).ConfigureAwait(false); - - var charset = CharsetDetector.DetectFromBytes(bytes).Detected?.EncodingName; + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) + { + var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName; - _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); + _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); - return charset; + return charset; + } } - private async Task GetBytes(string path, MediaProtocol protocol, CancellationToken cancellationToken) + private Task GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) { - if (protocol == MediaProtocol.Http) + switch (protocol) { - var opts = new HttpRequestOptions() - { - Url = path, - CancellationToken = cancellationToken - }; - using (var file = await _httpClient.Get(opts).ConfigureAwait(false)) - using (var memoryStream = new MemoryStream()) - { - await file.CopyToAsync(memoryStream).ConfigureAwait(false); - memoryStream.Position = 0; + case MediaProtocol.Http: + var opts = new HttpRequestOptions() + { + Url = path, + CancellationToken = cancellationToken, + BufferContent = true + }; - return memoryStream.ToArray(); - } - } - if (protocol == MediaProtocol.File) - { - return File.ReadAllBytes(path); - } + return _httpClient.Get(opts); - throw new ArgumentOutOfRangeException(nameof(protocol)); + case MediaProtocol.File: + return Task.FromResult(File.OpenRead(path)); + default: + throw new ArgumentOutOfRangeException(nameof(protocol)); + } } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs index cdaf94964..4f15bac49 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs @@ -49,12 +49,5 @@ namespace MediaBrowser.MediaEncoding.Subtitles writer.WriteLine(""); } } - - private string FormatTime(long ticks) - { - var time = TimeSpan.FromTicks(ticks); - - return string.Format(@"{0:hh\:mm\:ss\,fff}", time); - } } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index b8abe49e3..ede2d71ad 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -231,7 +231,6 @@ namespace MediaBrowser.Model.Configuration LocalNetworkSubnets = Array.Empty(); LocalNetworkAddresses = Array.Empty(); CodecsUsed = Array.Empty(); - ImageExtractionTimeoutMs = 0; PathSubstitutions = Array.Empty(); IgnoreVirtualInterfaces = false; EnableSimpleArtistDetection = true; diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs index 962f4d2fe..c382b20c9 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs @@ -1,12 +1,15 @@ +using System; +using System.Collections.Generic; + namespace MediaBrowser.Model.MediaInfo { public class SubtitleTrackInfo { - public SubtitleTrackEvent[] TrackEvents { get; set; } + public IReadOnlyList TrackEvents { get; set; } public SubtitleTrackInfo() { - TrackEvents = new SubtitleTrackEvent[] { }; + TrackEvents = Array.Empty(); } } } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index e0b23108f..95b915b3d 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -62,7 +62,11 @@ namespace MediaBrowser.Providers.MediaInfo { var protocol = item.PathProtocol ?? MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, null, item.GetPlayableStreamFileNames(_mediaEncoder)); + var inputPath = MediaEncoderHelpers.GetInputArgument( + _fileSystem, + item.Path, + null, + item.GetPlayableStreamFileNames()); var mediaStreams = item.GetMediaStreams(); diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 8e71b625e..e9ca7938e 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Providers.Music _appHost = appHost; _logger = logger; - _musicBrainzBaseUrl = configuration["MusicBrainz:BaseUrl"]; + _musicBrainzBaseUrl = configuration["MusicBrainz_BaseUrl"]; // Use a stopwatch to ensure we don't exceed the MusicBrainz rate limit _stopWatchMusicBrainz.Start(); -- cgit v1.2.3 From 94ef239de0087ed4df490673b5b395d8b0111e8f Mon Sep 17 00:00:00 2001 From: ferferga Date: Mon, 25 Nov 2019 23:09:23 +0100 Subject: Add full Raspberry Pi hardware decoding support --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 16 ++++++++++++++-- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 349e371a7..0664bdd98 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2529,13 +2529,25 @@ namespace MediaBrowser.Controller.MediaEncoding case "h264": if (_mediaEncoder.SupportsDecoder("h264_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase)) { - return "-c:v h264_mmal"; + return "-c:v h264_mmal "; } break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { - return "-c:v mpeg2_mmal"; + return "-c:v mpeg2_mmal "; + } + break; + case "mpeg4": + if (_mediaEncoder.SupportsDecoder("mpeg4_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v mpeg4_mmal "; + } + break; + case "vc1": + if (_mediaEncoder.SupportsDecoder("vc1_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v vc1_mmal "; } break; } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 3620abfee..1feca0ec9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -18,7 +18,10 @@ namespace MediaBrowser.MediaEncoding.Encoder "h264_qsv", "hevc_qsv", "mpeg2_qsv", + "mpeg2_mmal", + "mpeg4_mmal", "vc1_qsv", + "vc1_mmal", "h264_cuvid", "hevc_cuvid", "dts", @@ -26,6 +29,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "aac", "mp3", "h264", + "h264_mmal", "hevc" }; -- cgit v1.2.3 From 5cab79c839d2212ae638db403ec4d7ba0699f9a1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 4 Dec 2019 21:39:27 +0100 Subject: Clean up Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs --- .../Library/MediaSourceManager.cs | 4 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 3 +- .../LiveTv/EmbyTV/EmbyTV.cs | 504 +++++++++------------ .../LiveTv/EmbyTV/EpgChannelData.cs | 68 +++ .../LiveTv/EmbyTV/NfoConfigurationExtensions.cs | 19 + .../LiveTv/LiveTvManager.cs | 5 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/Playback/MediaInfoService.cs | 2 +- .../Library/IMediaSourceManager.cs | 4 +- .../Subtitles/SubtitleEncoder.cs | 2 +- jellyfin.ruleset | 4 +- 11 files changed, 319 insertions(+), 298 deletions(-) create mode 100644 Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs create mode 100644 Emby.Server.Implementations/LiveTv/EmbyTV/NfoConfigurationExtensions.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 7a26e0c37..059b27e87 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.Library return streams; } - public async Task> GetPlayackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken) + public async Task> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken) { var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user); @@ -290,7 +290,7 @@ namespace Emby.Server.Implementations.Library return await GetLiveStream(liveStreamId, cancellationToken).ConfigureAwait(false); } - var sources = await GetPlayackMediaSources(item, null, false, enablePathSubstitution, cancellationToken).ConfigureAwait(false); + var sources = await GetPlaybackMediaSources(item, null, false, enablePathSubstitution, cancellationToken).ConfigureAwait(false); return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 8dee7046e..84e8c31f9 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; @@ -74,7 +75,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV DecompressionMethod = CompressionMethod.None }; - using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false)) + using (var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false)) { _logger.LogInformation("Opened recording stream from tuner provider"); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ef5928e48..420209eda 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1,3 +1,6 @@ +#pragma warning disable SA1600 +#pragma warning disable CS1591 + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -40,6 +43,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable { + public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; + + private const int TunerDiscoveryDurationMs = 3000; + private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; private readonly IHttpClient _httpClient; @@ -57,19 +64,21 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IProviderManager _providerManager; private readonly IMediaEncoder _mediaEncoder; private readonly IProcessFactory _processFactory; - private IMediaSourceManager _mediaSourceManager; - - public static EmbyTV Current; - - public event EventHandler> TimerCreated; - public event EventHandler> TimerCancelled; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly IStreamHelper _streamHelper; private readonly ConcurrentDictionary _activeRecordings = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - private readonly IStreamHelper _streamHelper; + private readonly ConcurrentDictionary _epgChannels = + new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + + private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1); - public EmbyTV(IServerApplicationHost appHost, + private bool _disposed = false; + + public EmbyTV( + IServerApplicationHost appHost, IStreamHelper streamHelper, IMediaSourceManager mediaSourceManager, ILogger logger, @@ -103,12 +112,40 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers.json")); _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers.json")); - _timerProvider.TimerFired += _timerProvider_TimerFired; + _timerProvider.TimerFired += OnTimerProviderTimerFired; - _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; + _config.NamedConfigurationUpdated += OnNamedConfigurationUpdated; } - private void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + public event EventHandler> TimerCreated; + + public event EventHandler> TimerCancelled; + + public static EmbyTV Current { get; private set; } + + /// + public string Name => "Emby"; + + public string DataPath => Path.Combine(_config.CommonApplicationPaths.DataPath, "livetv"); + + /// + public string HomePageUrl => "https://github.com/jellyfin/jellyfin"; + + private string DefaultRecordingPath => Path.Combine(DataPath, "recordings"); + + private string RecordingPath + { + get + { + var path = GetConfiguration().RecordingPath; + + return string.IsNullOrWhiteSpace(path) + ? DefaultRecordingPath + : path; + } + } + + private void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { if (string.Equals(e.Key, "livetv", StringComparison.OrdinalIgnoreCase)) { @@ -116,11 +153,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - public async Task Start() + public Task Start() { _timerProvider.RestartTimers(); - await CreateRecordingFolders().ConfigureAwait(false); + return CreateRecordingFolders(); } private async void OnRecordingFoldersChanged() @@ -132,8 +169,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { try { - var recordingFolders = GetRecordingFolders(); - + var recordingFolders = GetRecordingFolders().ToArray(); var virtualFolders = _libraryManager.GetVirtualFolders() .ToList(); @@ -241,26 +277,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - public string Name => "Emby"; - - public string DataPath => Path.Combine(_config.CommonApplicationPaths.DataPath, "livetv"); - - private string DefaultRecordingPath => Path.Combine(DataPath, "recordings"); - - private string RecordingPath - { - get - { - var path = GetConfiguration().RecordingPath; - - return string.IsNullOrWhiteSpace(path) - ? DefaultRecordingPath - : path; - } - } - - public string HomePageUrl => "https://github.com/jellyfin/jellyfin"; - public async Task RefreshSeriesTimers(CancellationToken cancellationToken) { var seriesTimers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); @@ -339,7 +355,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (NotSupportedException) { - } catch (Exception ex) { @@ -351,7 +366,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return list; } - private async Task AddMetadata(IListingsProvider provider, ListingsProviderInfo info, List tunerChannels, bool enableCache, CancellationToken cancellationToken) + private async Task AddMetadata( + IListingsProvider provider, + ListingsProviderInfo info, + IEnumerable tunerChannels, + bool enableCache, + CancellationToken cancellationToken) { var epgChannels = await GetEpgChannels(provider, info, enableCache, cancellationToken).ConfigureAwait(false); @@ -363,8 +383,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (!string.IsNullOrWhiteSpace(epgChannel.Name)) { - //tunerChannel.Name = epgChannel.Name; + // tunerChannel.Name = epgChannel.Name; } + if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl)) { tunerChannel.ImageUrl = epgChannel.ImageUrl; @@ -373,10 +394,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private readonly ConcurrentDictionary _epgChannels = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - - private async Task GetEpgChannels(IListingsProvider provider, ListingsProviderInfo info, bool enableCache, CancellationToken cancellationToken) + private async Task GetEpgChannels( + IListingsProvider provider, + ListingsProviderInfo info, + bool enableCache, + CancellationToken cancellationToken) { if (!enableCache || !_epgChannels.TryGetValue(info.Id, out var result)) { @@ -394,59 +416,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return result; } - private class EpgChannelData - { - public EpgChannelData(List channels) - { - ChannelsById = new Dictionary(StringComparer.OrdinalIgnoreCase); - ChannelsByNumber = new Dictionary(StringComparer.OrdinalIgnoreCase); - ChannelsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var channel in channels) - { - ChannelsById[channel.Id] = channel; - - if (!string.IsNullOrEmpty(channel.Number)) - { - ChannelsByNumber[channel.Number] = channel; - } - - var normalizedName = NormalizeName(channel.Name ?? string.Empty); - if (!string.IsNullOrWhiteSpace(normalizedName)) - { - ChannelsByName[normalizedName] = channel; - } - } - } - - private Dictionary ChannelsById { get; set; } - private Dictionary ChannelsByNumber { get; set; } - private Dictionary ChannelsByName { get; set; } - - public ChannelInfo GetChannelById(string id) - { - ChannelInfo result = null; - - ChannelsById.TryGetValue(id, out result); - - return result; - } - - public ChannelInfo GetChannelByNumber(string number) - { - ChannelsByNumber.TryGetValue(number, out var result); - - return result; - } - - public ChannelInfo GetChannelByName(string name) - { - ChannelsByName.TryGetValue(name, out var result); - - return result; - } - } - private async Task GetEpgChannelFromTunerChannel(IListingsProvider provider, ListingsProviderInfo info, ChannelInfo tunerChannel, CancellationToken cancellationToken) { var epgChannels = await GetEpgChannels(provider, info, true, cancellationToken).ConfigureAwait(false); @@ -463,6 +432,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return mapping.Value; } } + return channelId; } @@ -476,7 +446,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return GetEpgChannelFromTunerChannel(info.ChannelMappings, tunerChannel, epgChannels); } - private ChannelInfo GetEpgChannelFromTunerChannel(NameValuePair[] mappings, ChannelInfo tunerChannel, EpgChannelData epgChannelData) + private ChannelInfo GetEpgChannelFromTunerChannel( + NameValuePair[] mappings, + ChannelInfo tunerChannel, + EpgChannelData epgChannelData) { if (!string.IsNullOrWhiteSpace(tunerChannel.Id)) { @@ -537,7 +510,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (!string.IsNullOrWhiteSpace(tunerChannel.Name)) { - var normalizedName = NormalizeName(tunerChannel.Name); + var normalizedName = EpgChannelData.NormalizeName(tunerChannel.Name); var channel = epgChannelData.GetChannelByName(normalizedName); @@ -550,11 +523,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return null; } - private static string NormalizeName(string value) - { - return value.Replace(" ", string.Empty).Replace("-", string.Empty); - } - public async Task> GetChannelsForListingsProvider(ListingsProviderInfo listingsProvider, CancellationToken cancellationToken) { var list = new List(); @@ -600,6 +568,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _seriesTimerProvider.Delete(remove); } + return Task.CompletedTask; } @@ -689,6 +658,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { programInfo = GetProgramInfoFromCache(timer); } + if (programInfo == null) { _logger.LogInformation("Unable to find program with Id {0}. Will search using start date", timer.ProgramId); @@ -703,10 +673,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV timer.IsManual = true; _timerProvider.Add(timer); - if (TimerCreated != null) - { - TimerCreated(this, new GenericEventArgs(timer)); - } + TimerCreated?.Invoke(this, new GenericEventArgs(timer)); return Task.FromResult(timer.Id); } @@ -800,7 +767,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } // Only update if not currently active - if (!_activeRecordings.TryGetValue(updatedTimer.Id, out var activeRecordingInfo)) + if (!_activeRecordings.TryGetValue(updatedTimer.Id, out _)) { existingTimer.PrePaddingSeconds = updatedTimer.PrePaddingSeconds; existingTimer.PostPaddingSeconds = updatedTimer.PostPaddingSeconds; @@ -846,6 +813,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { return info.Path; } + return null; } @@ -870,9 +838,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { return null; } + return recording; } } + return null; } @@ -1061,13 +1031,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV mediaSource.Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture) + "_" + mediaSource.Id; - //if (mediaSource.DateLiveStreamOpened.HasValue && enableStreamSharing) - //{ - // var ticks = (DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value).Ticks - TimeSpan.FromSeconds(10).Ticks; - // ticks = Math.Max(0, ticks); - // mediaSource.Path += "?t=" + ticks.ToString(CultureInfo.InvariantCulture) + "&s=" + mediaSource.DateLiveStreamOpened.Value.Ticks.ToString(CultureInfo.InvariantCulture); - //} - return mediaSource; } @@ -1091,7 +1054,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (NotImplementedException) { - } } @@ -1142,7 +1104,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return Task.CompletedTask; } - async void _timerProvider_TimerFired(object sender, GenericEventArgs e) + private async void OnTimerProviderTimerFired(object sender, GenericEventArgs e) { var timer = e.Argument; @@ -1177,7 +1139,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (OperationCanceledException) { - } catch (Exception ex) { @@ -1221,7 +1182,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (timer.SeasonNumber.HasValue) { - folderName = string.Format("Season {0}", timer.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); + folderName = string.Format( + CultureInfo.InvariantCulture, + "Season {0}", + timer.SeasonNumber.Value); recordPath = Path.Combine(recordPath, folderName); } } @@ -1275,6 +1239,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { recordPath = Path.Combine(recordPath, "Sports"); } + recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(timer.Name).Trim()); } else @@ -1283,6 +1248,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { recordPath = Path.Combine(recordPath, "Other"); } + recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(timer.Name).Trim()); } @@ -1304,6 +1270,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { programInfo = GetProgramInfoFromCache(timer); } + if (programInfo == null) { _logger.LogInformation("Unable to find program with Id {0}. Will search using start date", timer.ProgramId); @@ -1315,9 +1282,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV CopyProgramInfoToTimerInfo(programInfo, timer); } - string seriesPath = null; var remoteMetadata = await FetchInternetMetadata(timer, CancellationToken.None).ConfigureAwait(false); - var recordPath = GetRecordingPath(timer, remoteMetadata, out seriesPath); + var recordPath = GetRecordingPath(timer, remoteMetadata, out string seriesPath); var recordingStatus = RecordingStatus.New; string liveStreamId = null; @@ -1326,19 +1292,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - var allMediaSources = await _mediaSourceManager.GetPlayackMediaSources(channelItem, null, true, false, CancellationToken.None).ConfigureAwait(false); + var allMediaSources = await _mediaSourceManager.GetPlaybackMediaSources(channelItem, null, true, false, CancellationToken.None).ConfigureAwait(false); var mediaStreamInfo = allMediaSources[0]; IDirectStreamProvider directStreamProvider = null; if (mediaStreamInfo.RequiresOpening) { - var liveStreamResponse = await _mediaSourceManager.OpenLiveStreamInternal(new LiveStreamRequest - { - ItemId = channelItem.Id, - OpenToken = mediaStreamInfo.OpenToken - - }, CancellationToken.None).ConfigureAwait(false); + var liveStreamResponse = await _mediaSourceManager.OpenLiveStreamInternal( + new LiveStreamRequest + { + ItemId = channelItem.Id, + OpenToken = mediaStreamInfo.OpenToken + }, + CancellationToken.None).ConfigureAwait(false); mediaStreamInfo = liveStreamResponse.Item1.MediaSource; liveStreamId = mediaStreamInfo.LiveStreamId; @@ -1412,12 +1379,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate && timer.RetryCount < 10) { - const int retryIntervalSeconds = 60; - _logger.LogInformation("Retrying recording in {0} seconds.", retryIntervalSeconds); + const int RetryIntervalSeconds = 60; + _logger.LogInformation("Retrying recording in {0} seconds.", RetryIntervalSeconds); timer.Status = RecordingStatus.New; timer.PrePaddingSeconds = 0; - timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds); + timer.StartDate = DateTime.UtcNow.AddSeconds(RetryIntervalSeconds); timer.RetryCount++; _timerProvider.AddOrUpdate(timer); } @@ -1538,6 +1505,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { return; } + if (string.IsNullOrWhiteSpace(seriesPath)) { return; @@ -1576,34 +1544,34 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV DeleteLibraryItemsForTimers(timersToDelete); var librarySeries = _libraryManager.FindByPath(seriesPath, true) as Folder; - if (librarySeries == null) { return; } - var episodesToDelete = (librarySeries.GetItemList(new InternalItemsQuery - { - OrderBy = new[] { new ValueTuple(ItemSortBy.DateCreated, SortOrder.Descending) }, - IsVirtualItem = false, - IsFolder = false, - Recursive = true, - DtoOptions = new DtoOptions(true) - - })) - .Where(i => i.IsFileProtocol && File.Exists(i.Path)) - .Skip(seriesTimer.KeepUpTo - 1) - .ToList(); + var episodesToDelete = librarySeries.GetItemList( + new InternalItemsQuery + { + OrderBy = new[] { new ValueTuple(ItemSortBy.DateCreated, SortOrder.Descending) }, + IsVirtualItem = false, + IsFolder = false, + Recursive = true, + DtoOptions = new DtoOptions(true) + }).Where(i => i.IsFileProtocol && File.Exists(i.Path)) + .Skip(seriesTimer.KeepUpTo - 1) + .ToList(); foreach (var item in episodesToDelete) { try { - _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = true - - }, true); + _libraryManager.DeleteItem( + item, + new DeleteOptions + { + DeleteFileLocation = true + }, + true); } catch (Exception ex) { @@ -1617,7 +1585,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1); private void DeleteLibraryItemsForTimers(List timers) { foreach (var timer in timers) @@ -1644,22 +1611,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (libraryItem != null) { - _libraryManager.DeleteItem(libraryItem, new DeleteOptions - { - DeleteFileLocation = true - - }, true); + _libraryManager.DeleteItem( + libraryItem, + new DeleteOptions + { + DeleteFileLocation = true + }, + true); } else { - try + if (File.Exists(timer.RecordingPath)) { _fileSystem.DeleteFile(timer.RecordingPath); } - catch (IOException) - { - - } } _timerProvider.Delete(timer); @@ -1690,16 +1655,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return true; } - var hasRecordingAtPath = _activeRecordings + return _activeRecordings .Values .ToList() .Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase)); - - if (hasRecordingAtPath) - { - return true; - } - return false; } private IRecorder GetRecorder(MediaSourceInfo mediaSource) @@ -1756,17 +1715,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void Process_Exited(object sender, EventArgs e) { - var process = (IProcess)sender; - try + using (var process = (IProcess)sender) { _logger.LogInformation("Recording post-processing script completed with exit code {ExitCode}", process.ExitCode); - } - catch - { + process.Dispose(); } - - process.Dispose(); } private async Task SaveRecordingImage(string recordingPath, LiveTvProgram program, ItemImageInfo image) @@ -1776,44 +1730,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV image = await _libraryManager.ConvertImageToLocal(program, image, 0).ConfigureAwait(false); } - string imageSaveFilenameWithoutExtension = null; - - switch (image.Type) + string imageSaveFilenameWithoutExtension = image.Type switch { - case ImageType.Primary: - - if (program.IsSeries) - { - imageSaveFilenameWithoutExtension = Path.GetFileNameWithoutExtension(recordingPath) + "-thumb"; - } - else - { - imageSaveFilenameWithoutExtension = "poster"; - } - - break; - case ImageType.Logo: - imageSaveFilenameWithoutExtension = "logo"; - break; - case ImageType.Thumb: - if (program.IsSeries) - { - imageSaveFilenameWithoutExtension = Path.GetFileNameWithoutExtension(recordingPath) + "-thumb"; - } - else - { - imageSaveFilenameWithoutExtension = "landscape"; - } - - break; - case ImageType.Backdrop: - imageSaveFilenameWithoutExtension = "fanart"; - break; - default: - break; - } + ImageType.Primary => program.IsSeries ? Path.GetFileNameWithoutExtension(recordingPath) + "-thumb" : "poster", + ImageType.Logo => "logo", + ImageType.Thumb => program.IsSeries ? Path.GetFileNameWithoutExtension(recordingPath) + "-thumb" : "landscape", + ImageType.Backdrop => "fanart", + _ => null + }; - if (string.IsNullOrWhiteSpace(imageSaveFilenameWithoutExtension)) + if (imageSaveFilenameWithoutExtension == null) { return; } @@ -1897,7 +1823,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Limit = 1, ExternalId = timer.ProgramId, DtoOptions = new DtoOptions(true) - }).FirstOrDefault() as LiveTvProgram; // dummy this up @@ -1921,11 +1846,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { program.AddGenre("Sports"); } + if (timer.IsKids) { program.AddGenre("Kids"); program.AddGenre("Children"); } + if (timer.IsNews) { program.AddGenre("News"); @@ -1980,14 +1907,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { writer.WriteElementString("id", id); } + if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id)) { writer.WriteElementString("imdb_id", id); } + if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out id)) { writer.WriteElementString("tmdbid", id); } + if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out id)) { writer.WriteElementString("zap2itid", id); @@ -2014,7 +1944,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; private void SaveVideoNfo(TimerInfo timer, string recordingPath, BaseItem item, bool lockData) { var nfoPath = Path.ChangeExtension(recordingPath, ".nfo"); @@ -2056,7 +1985,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var formatString = options.ReleaseDateFormat; - writer.WriteElementString("aired", premiereDate.Value.ToLocalTime().ToString(formatString)); + writer.WriteElementString( + "aired", + premiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)); } if (item.IndexNumber.HasValue) @@ -2087,12 +2018,18 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var formatString = options.ReleaseDateFormat; - writer.WriteElementString("premiered", item.PremiereDate.Value.ToLocalTime().ToString(formatString)); - writer.WriteElementString("releasedate", item.PremiereDate.Value.ToLocalTime().ToString(formatString)); + writer.WriteElementString( + "premiered", + item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)); + writer.WriteElementString( + "releasedate", + item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)); } } - writer.WriteElementString("dateadded", DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat)); + writer.WriteElementString( + "dateadded", + DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat, CultureInfo.InvariantCulture)); if (item.ProductionYear.HasValue) { @@ -2106,7 +2043,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var overview = (item.Overview ?? string.Empty) .StripHtml() - .Replace(""", "'"); + .Replace(""", "'", StringComparison.Ordinal); writer.WriteElementString("plot", overview); @@ -2214,17 +2151,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } private static bool IsPersonType(PersonInfo person, string type) - { - return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - } - - private void AddGenre(List genres, string genre) - { - if (!genres.Contains(genre, StringComparer.OrdinalIgnoreCase)) - { - genres.Add(genre); - } - } + => string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) + || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); private LiveTvProgram GetProgramInfoFromCache(string programId) { @@ -2283,25 +2211,19 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return false; } - if (!seriesTimer.RecordAnyTime) + if (!seriesTimer.RecordAnyTime + && Math.Abs(seriesTimer.StartDate.TimeOfDay.Ticks - timer.StartDate.TimeOfDay.Ticks) >= TimeSpan.FromMinutes(10).Ticks) { - if (Math.Abs(seriesTimer.StartDate.TimeOfDay.Ticks - timer.StartDate.TimeOfDay.Ticks) >= TimeSpan.FromMinutes(10).Ticks) - { - return true; - } + return true; } - //if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek)) - //{ - // return true; - //} - if (seriesTimer.RecordNewOnly && timer.IsRepeat) { return true; } - if (!seriesTimer.RecordAnyChannel && !string.Equals(timer.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)) + if (!seriesTimer.RecordAnyChannel + && !string.Equals(timer.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)) { return true; } @@ -2346,7 +2268,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var allTimers = GetTimersForSeries(seriesTimer).ToList(); - var enabledTimersForSeries = new List(); foreach (var timer in allTimers) { @@ -2369,10 +2290,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { enabledTimersForSeries.Add(timer); } + _timerProvider.Add(timer); TimerCreated?.Invoke(this, new GenericEventArgs(timer)); } + // Only update if not currently active - test both new timer and existing in case Id's are different // Id's could be different if the timer was created manually prior to series timer creation else if (!_activeRecordings.TryGetValue(timer.Id, out _) && !_activeRecordings.TryGetValue(existingTimer.Id, out _)) @@ -2508,13 +2431,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (!tempChannelCache.TryGetValue(parent.ChannelId, out LiveTvChannel channel)) { - channel = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, - ItemIds = new[] { parent.ChannelId }, - DtoOptions = new DtoOptions() - - }).Cast().FirstOrDefault(); + channel = _libraryManager.GetItemList( + new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, + ItemIds = new[] { parent.ChannelId }, + DtoOptions = new DtoOptions() + }).FirstOrDefault() as LiveTvChannel; if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId)) { @@ -2567,13 +2490,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (!tempChannelCache.TryGetValue(programInfo.ChannelId, out LiveTvChannel channel)) { - channel = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, - ItemIds = new[] { programInfo.ChannelId }, - DtoOptions = new DtoOptions() - - }).Cast().FirstOrDefault(); + channel = _libraryManager.GetItemList( + new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name }, + ItemIds = new[] { programInfo.ChannelId }, + DtoOptions = new DtoOptions() + }).FirstOrDefault() as LiveTvChannel; if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId)) { @@ -2618,10 +2541,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV foreach (var providerId in timerInfo.ProviderIds) { - var srch = "Series"; - if (providerId.Key.StartsWith(srch, StringComparison.OrdinalIgnoreCase)) + const string Search = "Series"; + if (providerId.Key.StartsWith(Search, StringComparison.OrdinalIgnoreCase)) { - seriesProviderIds[providerId.Key.Substring(srch.Length)] = providerId.Value; + seriesProviderIds[providerId.Key.Substring(Search.Length)] = providerId.Value; } } @@ -2632,12 +2555,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if ((program.EpisodeNumber.HasValue && program.SeasonNumber.HasValue) || !string.IsNullOrWhiteSpace(program.EpisodeTitle)) { - var seriesIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Name = program.Name - - }).ToArray(); + var seriesIds = _libraryManager.GetItemIds( + new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Name = program.Name + }).ToArray(); if (seriesIds.Length == 0) { @@ -2666,59 +2589,70 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return false; } - private bool _disposed; + /// public void Dispose() { - _disposed = true; + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _recordingDeleteSemaphore.Dispose(); + } + foreach (var pair in _activeRecordings.ToList()) { pair.Value.CancellationTokenSource.Cancel(); } + + _disposed = true; } - public List GetRecordingFolders() + public IEnumerable GetRecordingFolders() { - var list = new List(); - var defaultFolder = RecordingPath; var defaultName = "Recordings"; if (Directory.Exists(defaultFolder)) { - list.Add(new VirtualFolderInfo + yield return new VirtualFolderInfo { Locations = new string[] { defaultFolder }, Name = defaultName - }); + }; } var customPath = GetConfiguration().MovieRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) + if (!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase) && Directory.Exists(customPath)) { - list.Add(new VirtualFolderInfo + yield return new VirtualFolderInfo { Locations = new string[] { customPath }, Name = "Recorded Movies", CollectionType = CollectionType.Movies - }); + }; } customPath = GetConfiguration().SeriesRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) + if (!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase) && Directory.Exists(customPath)) { - list.Add(new VirtualFolderInfo + yield return new VirtualFolderInfo { Locations = new string[] { customPath }, Name = "Recorded Shows", CollectionType = CollectionType.TvShows - }); + }; } - - return list; } - private const int TunerDiscoveryDurationMs = 3000; - public async Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) { var list = new List(); @@ -2737,6 +2671,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparer.OrdinalIgnoreCase)) .ToList(); } + list.AddRange(discoveredDevices); } @@ -2773,11 +2708,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private async Task> DiscoverDevices(ITunerHost host, int discoveryDuationMs, CancellationToken cancellationToken) + private async Task> DiscoverDevices(ITunerHost host, int discoveryDurationMs, CancellationToken cancellationToken) { try { - var discoveredDevices = await host.DiscoverDevices(discoveryDuationMs, cancellationToken).ConfigureAwait(false); + var discoveredDevices = await host.DiscoverDevices(discoveryDurationMs, cancellationToken).ConfigureAwait(false); foreach (var device in discoveredDevices) { @@ -2794,11 +2729,4 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } } - public static class ConfigurationExtension - { - public static XbmcMetadataOptions GetNfoConfiguration(this IConfigurationManager manager) - { - return manager.GetConfiguration("xbmcmetadata"); - } - } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs new file mode 100644 index 000000000..498aa3c26 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EpgChannelData.cs @@ -0,0 +1,68 @@ +#pragma warning disable SA1600 +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using MediaBrowser.Controller.LiveTv; + +namespace Emby.Server.Implementations.LiveTv.EmbyTV +{ + + internal class EpgChannelData + { + public EpgChannelData(IEnumerable channels) + { + ChannelsById = new Dictionary(StringComparer.OrdinalIgnoreCase); + ChannelsByNumber = new Dictionary(StringComparer.OrdinalIgnoreCase); + ChannelsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var channel in channels) + { + ChannelsById[channel.Id] = channel; + + if (!string.IsNullOrEmpty(channel.Number)) + { + ChannelsByNumber[channel.Number] = channel; + } + + var normalizedName = NormalizeName(channel.Name ?? string.Empty); + if (!string.IsNullOrWhiteSpace(normalizedName)) + { + ChannelsByName[normalizedName] = channel; + } + } + } + + private Dictionary ChannelsById { get; set; } + + private Dictionary ChannelsByNumber { get; set; } + + private Dictionary ChannelsByName { get; set; } + + public ChannelInfo GetChannelById(string id) + { + ChannelsById.TryGetValue(id, out var result); + + return result; + } + + public ChannelInfo GetChannelByNumber(string number) + { + ChannelsByNumber.TryGetValue(number, out var result); + + return result; + } + + public ChannelInfo GetChannelByName(string name) + { + ChannelsByName.TryGetValue(name, out var result); + + return result; + } + + public static string NormalizeName(string value) + { + return value.Replace(" ", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal); + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/NfoConfigurationExtensions.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/NfoConfigurationExtensions.cs new file mode 100644 index 000000000..83f5e8413 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/NfoConfigurationExtensions.cs @@ -0,0 +1,19 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; + +namespace Emby.Server.Implementations.LiveTv.EmbyTV +{ + /// + /// Class containing extension methods for working with the nfo configuration. + /// + public static class NfoConfigurationExtensions + { + /// + /// Gets the nfo configuration. + /// + /// The configuration manager. + /// The nfo configuration. + public static XbmcMetadataOptions GetNfoConfiguration(this IConfigurationManager configurationManager) + => configurationManager.GetConfiguration("xbmcmetadata"); + } +} diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index d4bd598e3..d1f405679 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,3 +1,6 @@ +#pragma warning disable SA1600 +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; @@ -35,7 +38,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv { /// - /// Class LiveTvManager + /// Class LiveTvManager. /// public class LiveTvManager : ILiveTvManager, IDisposable { diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4bd729aac..d6f5bb0c0 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -768,7 +768,7 @@ namespace MediaBrowser.Api.Playback if (mediaSource == null) { - var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false)).ToList(); + var mediaSources = (await MediaSourceManager.GetPlaybackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false)).ToList(); mediaSource = string.IsNullOrEmpty(request.MediaSourceId) ? mediaSources[0] diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index da8f99a3d..ee440f5db 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -270,7 +270,7 @@ namespace MediaBrowser.Api.Playback try { // TODO handle supportedLiveMediaTypes ? - mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, user, true, false, CancellationToken.None).ConfigureAwait(false); + mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, user, true, false, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index fbae4edb0..1bf981d79 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -39,9 +39,9 @@ namespace MediaBrowser.Controller.Library List GetMediaStreams(MediaStreamQuery query); /// - /// Gets the playack media sources. + /// Gets the playback media sources. /// - Task> GetPlayackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken); + Task> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken); /// /// Gets the static media sources. diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d5fa76c3a..67c7fa343 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -126,7 +126,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(mediaSourceId)); } - var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); + var mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); var mediaSource = mediaSources .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 75b5573b6..d3d3001ed 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -31,7 +31,9 @@ - + + + -- cgit v1.2.3 From cf2e2a3f309d59c3c31696fc7f3ef2b6668c89dd Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 22 Dec 2019 21:39:26 +0100 Subject: Fix exceptions while scanning Fixes these exceptions: ``` [2019-12-22 20:48:14.779 +01:00] [ERR] Error in WaitForExit System.InvalidOperationException: No process is associated with this object. at System.Diagnostics.Process.EnsureState(State state) at System.Diagnostics.Process.EnsureState(State state) at System.Diagnostics.Process.GetWaitState() at System.Diagnostics.Process.WaitForExitCore(Int32 milliseconds) at System.Diagnostics.Process.WaitForExit(Int32 milliseconds) at Emby.Server.Implementations.Diagnostics.CommonProcess.WaitForExit(Int32 timeMs) in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 100 at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 785 [2019-12-22 20:48:14.790 +01:00] [INF] Killing ffmpeg process [2019-12-22 20:48:14.795 +01:00] [ERR] Error killing process System.InvalidOperationException: No process is associated with this object. at System.Diagnostics.Process.EnsureState(State state) at System.Diagnostics.Process.EnsureState(State state) at System.Diagnostics.Process.Kill() at Emby.Server.Implementations.Diagnostics.CommonProcess.Kill() in /home/pi/dev/jellyfin/Emby.Server.Implementations/Diagnostics/CommonProcess.cs:line 95 at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.StopProcess(ProcessWrapper process, Int32 waitTimeMs) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 799 [2019-12-22 20:48:14.808 +01:00] [ERR] Error in "ffprobe" System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.streams[0].start_pts | LineNumber: 32 | BytePositionInLine: 26. ---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string. at System.Text.Json.Utf8JsonReader.GetString() at System.Text.Json.Serialization.Converters.JsonConverterString.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) at System.Text.Json.JsonPropertyInfoNotNullable`4.OnRead(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.JsonPropertyInfo.Read(JsonTokenType tokenType, ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.JsonSerializer.HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& state) at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack) --- End of inner exception stack trace --- at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, Utf8JsonReader& reader, Exception ex) at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack) at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack) at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken) at MediaBrowser.MediaEncoding.Encoder.MediaEncoder.GetMediaInfoInternal(String inputPath, String primaryPath, MediaProtocol protocol, Boolean extractChapters, String probeSizeArgument, Boolean isAudio, Nullable`1 videoType, Boolean forceEnableLogging, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs:line 399 at MediaBrowser.Providers.MediaInfo.FFProbeVideoInfo.ProbeVideo[T](T item, MetadataRefreshOptions options, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs:line 122 at MediaBrowser.Providers.Manager.MetadataService`2.RunCustomProvider(ICustomMetadataProvider`1 provider, TItemType item, String logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken) in /home/pi/dev/jellyfin/MediaBrowser.Providers/Manager/MetadataService.cs:line 815 ``` --- .../Json/Converters/GuidConverter.cs | 20 -- .../Json/Converters/JsonGuidConverter.cs | 20 ++ .../Json/Converters/JsonInt32Converter.cs | 40 +++ MediaBrowser.Common/Json/JsonDefaults.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 30 +- .../Probing/FFProbeHelpers.cs | 21 +- .../Probing/InternalMediaInfoResult.cs | 325 +-------------------- MediaBrowser.MediaEncoding/Probing/MediaChapter.cs | 32 ++ .../Probing/MediaFormatInfo.cs | 81 +++++ .../Probing/MediaStreamInfo.cs | 282 ++++++++++++++++++ .../Probing/ProbeResultNormalizer.cs | 181 ++++++------ 11 files changed, 579 insertions(+), 455 deletions(-) delete mode 100644 MediaBrowser.Common/Json/Converters/GuidConverter.cs create mode 100644 MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs create mode 100644 MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs create mode 100644 MediaBrowser.MediaEncoding/Probing/MediaChapter.cs create mode 100644 MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs create mode 100644 MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Common/Json/Converters/GuidConverter.cs b/MediaBrowser.Common/Json/Converters/GuidConverter.cs deleted file mode 100644 index 3081e12ee..000000000 --- a/MediaBrowser.Common/Json/Converters/GuidConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Converts a GUID object or value to/from JSON. - /// - public class GuidConverter : JsonConverter - { - /// - public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => new Guid(reader.GetString()); - - /// - public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) - => writer.WriteStringValue(value); - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs b/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs new file mode 100644 index 000000000..d35a761f3 --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs @@ -0,0 +1,20 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Converts a GUID object or value to/from JSON. + /// + public class JsonGuidConverter : JsonConverter + { + /// + public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => new Guid(reader.GetString()); + + /// + public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) + => writer.WriteStringValue(value); + } +} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs new file mode 100644 index 000000000..0fd68babe --- /dev/null +++ b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs @@ -0,0 +1,40 @@ +using System; +using System.Buffers; +using System.Buffers.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Common.Json.Converters +{ + /// + /// Converts a GUID object or value to/from JSON. + /// + public class JsonInt32Converter : JsonConverter + { + /// + public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + static void ThrowFormatException() => throw new FormatException("Invalid format for an integer."); + ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; + if (!Utf8Parser.TryParse(span, out int number, out _)) + { + ThrowFormatException(); + } + + return number; + } + + /// + public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) + { + static void ThrowInvalidOperationException() => throw new InvalidOperationException(); + Span span = new byte[16]; + if (Utf8Formatter.TryFormat(value, span, out int bytesWritten)) + { + writer.WriteStringValue(span.Slice(0, bytesWritten)); + } + + ThrowInvalidOperationException(); + } + } +} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 4ba0d5a1a..4a6ee0a79 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Common.Json WriteIndented = false }; - options.Converters.Add(new GuidConverter()); + options.Converters.Add(new JsonGuidConverter()); options.Converters.Add(new JsonStringEnumConverter()); return options; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 6bcd6cd46..e0f7b992c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -397,7 +397,8 @@ namespace MediaBrowser.MediaEncoding.Encoder try { result = await JsonSerializer.DeserializeAsync( - process.StandardOutput.BaseStream).ConfigureAwait(false); + process.StandardOutput.BaseStream, + cancellationToken: cancellationToken).ConfigureAwait(false); } catch { @@ -406,24 +407,24 @@ namespace MediaBrowser.MediaEncoding.Encoder throw; } - if (result == null || (result.streams == null && result.format == null)) + if (result == null || (result.Streams == null && result.Format == null)) { throw new Exception("ffprobe failed - streams and format are both null."); } - if (result.streams != null) + if (result.Streams != null) { // Normalize aspect ratio if invalid - foreach (var stream in result.streams) + foreach (var stream in result.Streams) { - if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(stream.DisplayAspectRatio, "0:1", StringComparison.OrdinalIgnoreCase)) { - stream.display_aspect_ratio = string.Empty; + stream.DisplayAspectRatio = string.Empty; } - if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(stream.SampleAspectRatio, "0:1", StringComparison.OrdinalIgnoreCase)) { - stream.sample_aspect_ratio = string.Empty; + stream.SampleAspectRatio = string.Empty; } } } @@ -778,6 +779,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _runningProcesses.Add(process); } } + private void StopProcess(ProcessWrapper process, int waitTimeMs) { try @@ -786,18 +788,16 @@ namespace MediaBrowser.MediaEncoding.Encoder { return; } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error in WaitForExit"); - } - try - { _logger.LogInformation("Killing ffmpeg process"); process.Process.Kill(); } + catch (InvalidOperationException) + { + // The process has already exited or + // there is no process associated with this Process object. + } catch (Exception ex) { _logger.LogError(ex, "Error killing process"); diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index e4eabaf38..cd3d82e86 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -16,24 +16,19 @@ namespace MediaBrowser.MediaEncoding.Probing throw new ArgumentNullException(nameof(result)); } - if (result.format != null && result.format.tags != null) + if (result.Format != null && result.Format.Tags != null) { - result.format.tags = ConvertDictionaryToCaseInSensitive(result.format.tags); + result.Format.Tags = ConvertDictionaryToCaseInSensitive(result.Format.Tags); } - if (result.streams != null) + if (result.Streams != null) { // Convert all dictionaries to case insensitive - foreach (var stream in result.streams) + foreach (var stream in result.Streams) { - if (stream.tags != null) + if (stream.Tags != null) { - stream.tags = ConvertDictionaryToCaseInSensitive(stream.tags); - } - - if (stream.disposition != null) - { - stream.disposition = ConvertDictionaryToCaseInSensitive(stream.disposition); + stream.Tags = ConvertDictionaryToCaseInSensitive(stream.Tags); } } } @@ -45,7 +40,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// The tags. /// The key. /// System.String. - public static string GetDictionaryValue(Dictionary tags, string key) + public static string GetDictionaryValue(IReadOnlyDictionary tags, string key) { if (tags == null) { @@ -103,7 +98,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The dict. /// Dictionary{System.StringSystem.String}. - private static Dictionary ConvertDictionaryToCaseInSensitive(Dictionary dict) + private static Dictionary ConvertDictionaryToCaseInSensitive(IReadOnlyDictionary dict) { return new Dictionary(dict, StringComparer.OrdinalIgnoreCase); } diff --git a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs index cc9d27608..0e319c1a8 100644 --- a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs +++ b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; +using System.Text.Json.Serialization; namespace MediaBrowser.MediaEncoding.Probing { /// - /// Class MediaInfoResult + /// Class MediaInfoResult. /// public class InternalMediaInfoResult { @@ -11,331 +12,21 @@ namespace MediaBrowser.MediaEncoding.Probing /// Gets or sets the streams. /// /// The streams. - public MediaStreamInfo[] streams { get; set; } + [JsonPropertyName("streams")] + public IReadOnlyList Streams { get; set; } /// /// Gets or sets the format. /// /// The format. - public MediaFormatInfo format { get; set; } + [JsonPropertyName("format")] + public MediaFormatInfo Format { get; set; } /// /// Gets or sets the chapters. /// /// The chapters. - public MediaChapter[] Chapters { get; set; } - } - - public class MediaChapter - { - public int id { get; set; } - public string time_base { get; set; } - public long start { get; set; } - public string start_time { get; set; } - public long end { get; set; } - public string end_time { get; set; } - public Dictionary tags { get; set; } - } - - /// - /// Represents a stream within the output - /// - public class MediaStreamInfo - { - /// - /// Gets or sets the index. - /// - /// The index. - public int index { get; set; } - - /// - /// Gets or sets the profile. - /// - /// The profile. - public string profile { get; set; } - - /// - /// Gets or sets the codec_name. - /// - /// The codec_name. - public string codec_name { get; set; } - - /// - /// Gets or sets the codec_long_name. - /// - /// The codec_long_name. - public string codec_long_name { get; set; } - - /// - /// Gets or sets the codec_type. - /// - /// The codec_type. - public string codec_type { get; set; } - - /// - /// Gets or sets the sample_rate. - /// - /// The sample_rate. - public string sample_rate { get; set; } - - /// - /// Gets or sets the channels. - /// - /// The channels. - public int channels { get; set; } - - /// - /// Gets or sets the channel_layout. - /// - /// The channel_layout. - public string channel_layout { get; set; } - - /// - /// Gets or sets the avg_frame_rate. - /// - /// The avg_frame_rate. - public string avg_frame_rate { get; set; } - - /// - /// Gets or sets the duration. - /// - /// The duration. - public string duration { get; set; } - - /// - /// Gets or sets the bit_rate. - /// - /// The bit_rate. - public string bit_rate { get; set; } - - /// - /// Gets or sets the width. - /// - /// The width. - public int width { get; set; } - - /// - /// Gets or sets the refs. - /// - /// The refs. - public int refs { get; set; } - - /// - /// Gets or sets the height. - /// - /// The height. - public int height { get; set; } - - /// - /// Gets or sets the display_aspect_ratio. - /// - /// The display_aspect_ratio. - public string display_aspect_ratio { get; set; } - - /// - /// Gets or sets the tags. - /// - /// The tags. - public Dictionary tags { get; set; } - - /// - /// Gets or sets the bits_per_sample. - /// - /// The bits_per_sample. - public int bits_per_sample { get; set; } - - /// - /// Gets or sets the bits_per_raw_sample. - /// - /// The bits_per_raw_sample. - public int bits_per_raw_sample { get; set; } - - /// - /// Gets or sets the r_frame_rate. - /// - /// The r_frame_rate. - public string r_frame_rate { get; set; } - - /// - /// Gets or sets the has_b_frames. - /// - /// The has_b_frames. - public int has_b_frames { get; set; } - - /// - /// Gets or sets the sample_aspect_ratio. - /// - /// The sample_aspect_ratio. - public string sample_aspect_ratio { get; set; } - - /// - /// Gets or sets the pix_fmt. - /// - /// The pix_fmt. - public string pix_fmt { get; set; } - - /// - /// Gets or sets the level. - /// - /// The level. - public int level { get; set; } - - /// - /// Gets or sets the time_base. - /// - /// The time_base. - public string time_base { get; set; } - - /// - /// Gets or sets the start_time. - /// - /// The start_time. - public string start_time { get; set; } - - /// - /// Gets or sets the codec_time_base. - /// - /// The codec_time_base. - public string codec_time_base { get; set; } - - /// - /// Gets or sets the codec_tag. - /// - /// The codec_tag. - public string codec_tag { get; set; } - - /// - /// Gets or sets the codec_tag_string. - /// - /// The codec_tag_string. - public string codec_tag_string { get; set; } - - /// - /// Gets or sets the sample_fmt. - /// - /// The sample_fmt. - public string sample_fmt { get; set; } - - /// - /// Gets or sets the dmix_mode. - /// - /// The dmix_mode. - public string dmix_mode { get; set; } - - /// - /// Gets or sets the start_pts. - /// - /// The start_pts. - public string start_pts { get; set; } - - /// - /// Gets or sets the is_avc. - /// - /// The is_avc. - public string is_avc { get; set; } - - /// - /// Gets or sets the nal_length_size. - /// - /// The nal_length_size. - public string nal_length_size { get; set; } - - /// - /// Gets or sets the ltrt_cmixlev. - /// - /// The ltrt_cmixlev. - public string ltrt_cmixlev { get; set; } - - /// - /// Gets or sets the ltrt_surmixlev. - /// - /// The ltrt_surmixlev. - public string ltrt_surmixlev { get; set; } - - /// - /// Gets or sets the loro_cmixlev. - /// - /// The loro_cmixlev. - public string loro_cmixlev { get; set; } - - /// - /// Gets or sets the loro_surmixlev. - /// - /// The loro_surmixlev. - public string loro_surmixlev { get; set; } - - public string field_order { get; set; } - - /// - /// Gets or sets the disposition. - /// - /// The disposition. - public Dictionary disposition { get; set; } - } - - /// - /// Class MediaFormat - /// - public class MediaFormatInfo - { - /// - /// Gets or sets the filename. - /// - /// The filename. - public string filename { get; set; } - - /// - /// Gets or sets the nb_streams. - /// - /// The nb_streams. - public int nb_streams { get; set; } - - /// - /// Gets or sets the format_name. - /// - /// The format_name. - public string format_name { get; set; } - - /// - /// Gets or sets the format_long_name. - /// - /// The format_long_name. - public string format_long_name { get; set; } - - /// - /// Gets or sets the start_time. - /// - /// The start_time. - public string start_time { get; set; } - - /// - /// Gets or sets the duration. - /// - /// The duration. - public string duration { get; set; } - - /// - /// Gets or sets the size. - /// - /// The size. - public string size { get; set; } - - /// - /// Gets or sets the bit_rate. - /// - /// The bit_rate. - public string bit_rate { get; set; } - - /// - /// Gets or sets the probe_score. - /// - /// The probe_score. - public int probe_score { get; set; } - - /// - /// Gets or sets the tags. - /// - /// The tags. - public Dictionary tags { get; set; } + [JsonPropertyName("chapters")] + public IReadOnlyList Chapters { get; set; } } } diff --git a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs new file mode 100644 index 000000000..a3607a760 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace MediaBrowser.MediaEncoding.Probing +{ + /// + /// Class MediaChapter. + /// + public class MediaChapter + { + [JsonPropertyName("id")] + public int id { get; set; } + + [JsonPropertyName("time_base")] + public string TimeBase { get; set; } + + [JsonPropertyName("start")] + public long Start { get; set; } + + [JsonPropertyName("start_time")] + public string StartTime { get; set; } + + [JsonPropertyName("end")] + public long End { get; set; } + + [JsonPropertyName("end_time")] + public string EndTime { get; set; } + + [JsonPropertyName("tags")] + public IReadOnlyDictionary Tags { get; set; } + } +} diff --git a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs new file mode 100644 index 000000000..d5529e56c --- /dev/null +++ b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace MediaBrowser.MediaEncoding.Probing +{ + /// + /// Class MediaFormat. + /// + public class MediaFormatInfo + { + /// + /// Gets or sets the filename. + /// + /// The filename. + [JsonPropertyName("filename")] + public string Fileame { get; set; } + + /// + /// Gets or sets the nb_streams. + /// + /// The nb_streams. + [JsonPropertyName("nb_streams")] + public int NbStreams { get; set; } + + /// + /// Gets or sets the format_name. + /// + /// The format_name. + [JsonPropertyName("format_name")] + public string FormatName { get; set; } + + /// + /// Gets or sets the format_long_name. + /// + /// The format_long_name. + [JsonPropertyName("format_long_name")] + public string FormatLongName { get; set; } + + /// + /// Gets or sets the start_time. + /// + /// The start_time. + [JsonPropertyName("start_time")] + public string StartTime { get; set; } + + /// + /// Gets or sets the duration. + /// + /// The duration. + [JsonPropertyName("duration")] + public string Duration { get; set; } + + /// + /// Gets or sets the size. + /// + /// The size. + [JsonPropertyName("size")] + public string Size { get; set; } + + /// + /// Gets or sets the bit_rate. + /// + /// The bit_rate. + [JsonPropertyName("bit_rate")] + public string BitRate { get; set; } + + /// + /// Gets or sets the probe_score. + /// + /// The probe_score. + [JsonPropertyName("probe_score")] + public int ProbeScore { get; set; } + + /// + /// Gets or sets the tags. + /// + /// The tags. + [JsonPropertyName("tags")] + public IReadOnlyDictionary Tags { get; set; } + } +} diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs new file mode 100644 index 000000000..7fa7afa5b --- /dev/null +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -0,0 +1,282 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +using MediaBrowser.Common.Json.Converters; + +namespace MediaBrowser.MediaEncoding.Probing +{ + /// + /// Represents a stream within the output. + /// + public class MediaStreamInfo + { + /// + /// Gets or sets the index. + /// + /// The index. + [JsonPropertyName("index")] + public int Index { get; set; } + + /// + /// Gets or sets the profile. + /// + /// The profile. + [JsonPropertyName("profile")] + public string Profile { get; set; } + + /// + /// Gets or sets the codec_name. + /// + /// The codec_name. + [JsonPropertyName("codec_name")] + public string CodecName { get; set; } + + /// + /// Gets or sets the codec_long_name. + /// + /// The codec_long_name. + [JsonPropertyName("codec_long_name")] + public string CodecLongName { get; set; } + + /// + /// Gets or sets the codec_type. + /// + /// The codec_type. + [JsonPropertyName("codec_type")] + public string CodecType { get; set; } + + /// + /// Gets or sets the sample_rate. + /// + /// The sample_rate. + [JsonPropertyName("sample_rate")] + public string SampleRate { get; set; } + + /// + /// Gets or sets the channels. + /// + /// The channels. + [JsonPropertyName("channels")] + public int Channels { get; set; } + + /// + /// Gets or sets the channel_layout. + /// + /// The channel_layout. + [JsonPropertyName("channel_layout")] + public string ChannelLayout { get; set; } + + /// + /// Gets or sets the avg_frame_rate. + /// + /// The avg_frame_rate. + [JsonPropertyName("avg_frame_rate")] + public string AverageFrameRate { get; set; } + + /// + /// Gets or sets the duration. + /// + /// The duration. + [JsonPropertyName("duration")] + public string Duration { get; set; } + + /// + /// Gets or sets the bit_rate. + /// + /// The bit_rate. + [JsonPropertyName("bit_rate")] + public string BitRate { get; set; } + + /// + /// Gets or sets the width. + /// + /// The width. + [JsonPropertyName("width")] + public int Width { get; set; } + + /// + /// Gets or sets the refs. + /// + /// The refs. + [JsonPropertyName("refs")] + public int Refs { get; set; } + + /// + /// Gets or sets the height. + /// + /// The height. + [JsonPropertyName("height")] + public int Height { get; set; } + + /// + /// Gets or sets the display_aspect_ratio. + /// + /// The display_aspect_ratio. + [JsonPropertyName("display_aspect_ratio")] + public string DisplayAspectRatio { get; set; } + + /// + /// Gets or sets the tags. + /// + /// The tags. + [JsonPropertyName("tags")] + public IReadOnlyDictionary Tags { get; set; } + + /// + /// Gets or sets the bits_per_sample. + /// + /// The bits_per_sample. + [JsonPropertyName("bits_per_sample")] + public int BitsPerSample { get; set; } + + /// + /// Gets or sets the bits_per_raw_sample. + /// + /// The bits_per_raw_sample. + [JsonPropertyName("bits_per_raw_sample")] + [JsonConverter(typeof(JsonInt32Converter))] + public int BitsPerRawSample { get; set; } + + /// + /// Gets or sets the r_frame_rate. + /// + /// The r_frame_rate. + [JsonPropertyName("r_frame_rate")] + public string RFrameRate { get; set; } + + /// + /// Gets or sets the has_b_frames. + /// + /// The has_b_frames. + [JsonPropertyName("has_b_frames")] + public int HasBFrames { get; set; } + + /// + /// Gets or sets the sample_aspect_ratio. + /// + /// The sample_aspect_ratio. + [JsonPropertyName("sample_aspect_ratio")] + public string SampleAspectRatio { get; set; } + + /// + /// Gets or sets the pix_fmt. + /// + /// The pix_fmt. + [JsonPropertyName("pix_fmt")] + public string PixelFormat { get; set; } + + /// + /// Gets or sets the level. + /// + /// The level. + [JsonPropertyName("level")] + public int Level { get; set; } + + /// + /// Gets or sets the time_base. + /// + /// The time_base. + [JsonPropertyName("time_base")] + public string TimeBase { get; set; } + + /// + /// Gets or sets the start_time. + /// + /// The start_time. + [JsonPropertyName("start_time")] + public string StartTime { get; set; } + + /// + /// Gets or sets the codec_time_base. + /// + /// The codec_time_base. + [JsonPropertyName("codec_time_base")] + public string CodecTimeBase { get; set; } + + /// + /// Gets or sets the codec_tag. + /// + /// The codec_tag. + [JsonPropertyName("codec_tag")] + public string CodecTag { get; set; } + + /// + /// Gets or sets the codec_tag_string. + /// + /// The codec_tag_string. + [JsonPropertyName("codec_tag_string")] + public string CodecTagString { get; set; } + + /// + /// Gets or sets the sample_fmt. + /// + /// The sample_fmt. + [JsonPropertyName("sample_fmt")] + public string SampleFmt { get; set; } + + /// + /// Gets or sets the dmix_mode. + /// + /// The dmix_mode. + [JsonPropertyName("dmix_mode")] + public string DmixMode { get; set; } + + /// + /// Gets or sets the start_pts. + /// + /// The start_pts. + [JsonPropertyName("start_pts")] + public int StartPts { get; set; } + + /// + /// Gets or sets the is_avc. + /// + /// The is_avc. + [JsonPropertyName("is_avc")] + public string IsAvc { get; set; } + + /// + /// Gets or sets the nal_length_size. + /// + /// The nal_length_size. + [JsonPropertyName("nal_length_size")] + public string NalLengthSize { get; set; } + + /// + /// Gets or sets the ltrt_cmixlev. + /// + /// The ltrt_cmixlev. + [JsonPropertyName("ltrt_cmixlev")] + public string LtrtCmixlev { get; set; } + + /// + /// Gets or sets the ltrt_surmixlev. + /// + /// The ltrt_surmixlev. + [JsonPropertyName("ltrt_surmixlev")] + public string LtrtSurmixlev { get; set; } + + /// + /// Gets or sets the loro_cmixlev. + /// + /// The loro_cmixlev. + [JsonPropertyName("loro_cmixlev")] + public string LoroCmixlev { get; set; } + + /// + /// Gets or sets the loro_surmixlev. + /// + /// The loro_surmixlev. + [JsonPropertyName("loro_surmixlev")] + public string LoroSurmixlev { get; set; } + + [JsonPropertyName("field_order")] + public string FieldOrder { get; set; } + + /// + /// Gets or sets the disposition. + /// + /// The disposition. + [JsonPropertyName("disposition")] + public IReadOnlyDictionary Disposition { get; set; } + } +} diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 54d02fc9f..99f0df60f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -8,7 +8,6 @@ using System.Xml; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -41,21 +40,21 @@ namespace MediaBrowser.MediaEncoding.Probing FFProbeHelpers.NormalizeFFProbeResult(data); SetSize(data, info); - var internalStreams = data.streams ?? new MediaStreamInfo[] { }; + var internalStreams = data.Streams ?? new MediaStreamInfo[] { }; - info.MediaStreams = internalStreams.Select(s => GetMediaStream(isAudio, s, data.format)) + info.MediaStreams = internalStreams.Select(s => GetMediaStream(isAudio, s, data.Format)) .Where(i => i != null) // Drop subtitle streams if we don't know the codec because it will just cause failures if we don't know how to handle them .Where(i => i.Type != MediaStreamType.Subtitle || !string.IsNullOrWhiteSpace(i.Codec)) .ToList(); - if (data.format != null) + if (data.Format != null) { - info.Container = NormalizeFormat(data.format.format_name); + info.Container = NormalizeFormat(data.Format.FormatName); - if (!string.IsNullOrEmpty(data.format.bit_rate)) + if (!string.IsNullOrEmpty(data.Format.BitRate)) { - if (int.TryParse(data.format.bit_rate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(data.Format.BitRate, NumberStyles.Any, _usCulture, out var value)) { info.Bitrate = value; } @@ -65,22 +64,22 @@ namespace MediaBrowser.MediaEncoding.Probing var tags = new Dictionary(StringComparer.OrdinalIgnoreCase); var tagStreamType = isAudio ? "audio" : "video"; - if (data.streams != null) + if (data.Streams != null) { - var tagStream = data.streams.FirstOrDefault(i => string.Equals(i.codec_type, tagStreamType, StringComparison.OrdinalIgnoreCase)); + var tagStream = data.Streams.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); - if (tagStream != null && tagStream.tags != null) + if (tagStream != null && tagStream.Tags != null) { - foreach (var pair in tagStream.tags) + foreach (var pair in tagStream.Tags) { tags[pair.Key] = pair.Value; } } } - if (data.format != null && data.format.tags != null) + if (data.Format != null && data.Format.Tags != null) { - foreach (var pair in data.format.tags) + foreach (var pair in data.Format.Tags) { tags[pair.Key] = pair.Value; } @@ -153,9 +152,9 @@ namespace MediaBrowser.MediaEncoding.Probing FetchFromItunesInfo(itunesXml, info); } - if (data.format != null && !string.IsNullOrEmpty(data.format.duration)) + if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) { - info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks; + info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.Format.Duration, _usCulture)).Ticks; } FetchWtvInfo(info, data); @@ -523,7 +522,7 @@ namespace MediaBrowser.MediaEncoding.Probing private MediaStream GetMediaStream(bool isAudio, MediaStreamInfo streamInfo, MediaFormatInfo formatInfo) { // These are mp4 chapters - if (string.Equals(streamInfo.codec_name, "mov_text", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(streamInfo.CodecName, "mov_text", StringComparison.OrdinalIgnoreCase)) { // Edit: but these are also sometimes subtitles? //return null; @@ -531,71 +530,71 @@ namespace MediaBrowser.MediaEncoding.Probing var stream = new MediaStream { - Codec = streamInfo.codec_name, - Profile = streamInfo.profile, - Level = streamInfo.level, - Index = streamInfo.index, - PixelFormat = streamInfo.pix_fmt, - NalLengthSize = streamInfo.nal_length_size, - TimeBase = streamInfo.time_base, - CodecTimeBase = streamInfo.codec_time_base + Codec = streamInfo.CodecName, + Profile = streamInfo.Profile, + Level = streamInfo.Level, + Index = streamInfo.Index, + PixelFormat = streamInfo.PixelFormat, + NalLengthSize = streamInfo.NalLengthSize, + TimeBase = streamInfo.TimeBase, + CodecTimeBase = streamInfo.CodecTimeBase }; - if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) || - string.Equals(streamInfo.is_avc, "1", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(streamInfo.IsAvc, "true", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.IsAvc, "1", StringComparison.OrdinalIgnoreCase)) { stream.IsAVC = true; } - else if (string.Equals(streamInfo.is_avc, "false", StringComparison.OrdinalIgnoreCase) || - string.Equals(streamInfo.is_avc, "0", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(streamInfo.IsAvc, "false", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.IsAvc, "0", StringComparison.OrdinalIgnoreCase)) { stream.IsAVC = false; } - if (!string.IsNullOrWhiteSpace(streamInfo.field_order) && !string.Equals(streamInfo.field_order, "progressive", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrWhiteSpace(streamInfo.FieldOrder) && !string.Equals(streamInfo.FieldOrder, "progressive", StringComparison.OrdinalIgnoreCase)) { stream.IsInterlaced = true; } // Filter out junk - if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString) && streamInfo.CodecTagString.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) { - stream.CodecTag = streamInfo.codec_tag_string; + stream.CodecTag = streamInfo.CodecTagString; } - if (streamInfo.tags != null) + if (streamInfo.Tags != null) { - stream.Language = GetDictionaryValue(streamInfo.tags, "language"); - stream.Comment = GetDictionaryValue(streamInfo.tags, "comment"); - stream.Title = GetDictionaryValue(streamInfo.tags, "title"); + stream.Language = GetDictionaryValue(streamInfo.Tags, "language"); + stream.Comment = GetDictionaryValue(streamInfo.Tags, "comment"); + stream.Title = GetDictionaryValue(streamInfo.Tags, "title"); } - if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(streamInfo.CodecType, "audio", StringComparison.OrdinalIgnoreCase)) { stream.Type = MediaStreamType.Audio; - stream.Channels = streamInfo.channels; + stream.Channels = streamInfo.Channels; - if (!string.IsNullOrEmpty(streamInfo.sample_rate)) + if (!string.IsNullOrEmpty(streamInfo.SampleRate)) { - if (int.TryParse(streamInfo.sample_rate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.SampleRate, NumberStyles.Any, _usCulture, out var value)) { stream.SampleRate = value; } } - stream.ChannelLayout = ParseChannelLayout(streamInfo.channel_layout); + stream.ChannelLayout = ParseChannelLayout(streamInfo.ChannelLayout); - if (streamInfo.bits_per_sample > 0) + if (streamInfo.BitsPerSample > 0) { - stream.BitDepth = streamInfo.bits_per_sample; + stream.BitDepth = streamInfo.BitsPerSample; } - else if (streamInfo.bits_per_raw_sample > 0) + else if (streamInfo.BitsPerRawSample > 0) { - stream.BitDepth = streamInfo.bits_per_raw_sample; + stream.BitDepth = streamInfo.BitsPerRawSample; } } - else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(streamInfo.CodecType, "subtitle", StringComparison.OrdinalIgnoreCase)) { stream.Type = MediaStreamType.Subtitle; stream.Codec = NormalizeSubtitleCodec(stream.Codec); @@ -603,14 +602,14 @@ namespace MediaBrowser.MediaEncoding.Probing stream.localizedDefault = _localization.GetLocalizedString("Default"); stream.localizedForced = _localization.GetLocalizedString("Forced"); } - else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase)) { stream.Type = isAudio || string.Equals(stream.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase) || string.Equals(stream.Codec, "gif", StringComparison.OrdinalIgnoreCase) || string.Equals(stream.Codec, "png", StringComparison.OrdinalIgnoreCase) ? MediaStreamType.EmbeddedImage : MediaStreamType.Video; - stream.AverageFrameRate = GetFrameRate(streamInfo.avg_frame_rate); - stream.RealFrameRate = GetFrameRate(streamInfo.r_frame_rate); + stream.AverageFrameRate = GetFrameRate(streamInfo.AverageFrameRate); + stream.RealFrameRate = GetFrameRate(streamInfo.RFrameRate); if (isAudio || string.Equals(stream.Codec, "gif", StringComparison.OrdinalIgnoreCase) || string.Equals(stream.Codec, "png", StringComparison.OrdinalIgnoreCase)) @@ -635,17 +634,17 @@ namespace MediaBrowser.MediaEncoding.Probing stream.Type = MediaStreamType.Video; } - stream.Width = streamInfo.width; - stream.Height = streamInfo.height; + stream.Width = streamInfo.Width; + stream.Height = streamInfo.Height; stream.AspectRatio = GetAspectRatio(streamInfo); - if (streamInfo.bits_per_sample > 0) + if (streamInfo.BitsPerSample > 0) { - stream.BitDepth = streamInfo.bits_per_sample; + stream.BitDepth = streamInfo.BitsPerSample; } - else if (streamInfo.bits_per_raw_sample > 0) + else if (streamInfo.BitsPerRawSample > 0) { - stream.BitDepth = streamInfo.bits_per_raw_sample; + stream.BitDepth = streamInfo.BitsPerRawSample; } //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || @@ -653,11 +652,11 @@ namespace MediaBrowser.MediaEncoding.Probing // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase); // http://stackoverflow.com/questions/17353387/how-to-detect-anamorphic-video-with-ffprobe - stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase); + stream.IsAnamorphic = string.Equals(streamInfo.SampleAspectRatio, "0:1", StringComparison.OrdinalIgnoreCase); - if (streamInfo.refs > 0) + if (streamInfo.Refs > 0) { - stream.RefFrames = streamInfo.refs; + stream.RefFrames = streamInfo.Refs; } } else @@ -668,18 +667,18 @@ namespace MediaBrowser.MediaEncoding.Probing // Get stream bitrate var bitrate = 0; - if (!string.IsNullOrEmpty(streamInfo.bit_rate)) + if (!string.IsNullOrEmpty(streamInfo.BitRate)) { - if (int.TryParse(streamInfo.bit_rate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) { bitrate = value; } } - if (bitrate == 0 && formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video) + if (bitrate == 0 && formatInfo != null && !string.IsNullOrEmpty(formatInfo.BitRate) && stream.Type == MediaStreamType.Video) { // If the stream info doesn't have a bitrate get the value from the media format info - if (int.TryParse(formatInfo.bit_rate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) { bitrate = value; } @@ -690,14 +689,18 @@ namespace MediaBrowser.MediaEncoding.Probing stream.BitRate = bitrate; } - if (streamInfo.disposition != null) + var disposition = streamInfo.Disposition; + if (disposition != null) { - var isDefault = GetDictionaryValue(streamInfo.disposition, "default"); - var isForced = GetDictionaryValue(streamInfo.disposition, "forced"); - - stream.IsDefault = string.Equals(isDefault, "1", StringComparison.OrdinalIgnoreCase); + if (disposition.GetValueOrDefault("default") == 1) + { + stream.IsDefault = true; + } - stream.IsForced = string.Equals(isForced, "1", StringComparison.OrdinalIgnoreCase); + if (disposition.GetValueOrDefault("forced") == 1) + { + stream.IsForced = true; + } } NormalizeStreamTitle(stream); @@ -724,7 +727,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// The tags. /// The key. /// System.String. - private string GetDictionaryValue(Dictionary tags, string key) + private string GetDictionaryValue(IReadOnlyDictionary tags, string key) { if (tags == null) { @@ -747,7 +750,7 @@ namespace MediaBrowser.MediaEncoding.Probing private string GetAspectRatio(MediaStreamInfo info) { - var original = info.display_aspect_ratio; + var original = info.DisplayAspectRatio; var parts = (original ?? string.Empty).Split(':'); if (!(parts.Length == 2 && @@ -756,8 +759,8 @@ namespace MediaBrowser.MediaEncoding.Probing width > 0 && height > 0)) { - width = info.width; - height = info.height; + width = info.Width; + height = info.Height; } if (width > 0 && height > 0) @@ -850,20 +853,20 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetAudioRuntimeTicks(InternalMediaInfoResult result, MediaInfo data) { - if (result.streams != null) + if (result.Streams != null) { // Get the first info stream - var stream = result.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase)); + var stream = result.Streams.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); if (stream != null) { // Get duration from stream properties - var duration = stream.duration; + var duration = stream.Duration; // If it's not there go into format properties if (string.IsNullOrEmpty(duration)) { - duration = result.format.duration; + duration = result.Format.Duration; } // If we got something, parse it @@ -877,11 +880,11 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetSize(InternalMediaInfoResult data, MediaInfo info) { - if (data.format != null) + if (data.Format != null) { - if (!string.IsNullOrEmpty(data.format.size)) + if (!string.IsNullOrEmpty(data.Format.Size)) { - info.Size = long.Parse(data.format.size, _usCulture); + info.Size = long.Parse(data.Format.Size, _usCulture); } else { @@ -1194,16 +1197,16 @@ namespace MediaBrowser.MediaEncoding.Probing { var info = new ChapterInfo(); - if (chapter.tags != null) + if (chapter.Tags != null) { - if (chapter.tags.TryGetValue("title", out string name)) + if (chapter.Tags.TryGetValue("title", out string name)) { info.Name = name; } } // Limit accuracy to milliseconds to match xml saving - var secondsString = chapter.start_time; + var secondsString = chapter.StartTime; if (double.TryParse(secondsString, NumberStyles.Any, CultureInfo.InvariantCulture, out var seconds)) { @@ -1218,12 +1221,12 @@ namespace MediaBrowser.MediaEncoding.Probing private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) { - if (data.format == null || data.format.tags == null) + if (data.Format == null || data.Format.Tags == null) { return; } - var genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/Genre"); + var genres = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/Genre"); if (!string.IsNullOrWhiteSpace(genres)) { @@ -1239,14 +1242,14 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var officialRating = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/ParentalRating"); + var officialRating = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/ParentalRating"); if (!string.IsNullOrWhiteSpace(officialRating)) { video.OfficialRating = officialRating; } - var people = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaCredits"); + var people = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaCredits"); if (!string.IsNullOrEmpty(people)) { @@ -1256,7 +1259,7 @@ namespace MediaBrowser.MediaEncoding.Probing .ToArray(); } - var year = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/OriginalReleaseTime"); + var year = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/OriginalReleaseTime"); if (!string.IsNullOrWhiteSpace(year)) { if (int.TryParse(year, NumberStyles.Integer, _usCulture, out var val)) @@ -1265,7 +1268,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaOriginalBroadcastDateTime"); + var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaOriginalBroadcastDateTime"); if (!string.IsNullOrWhiteSpace(premiereDateString)) { // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ @@ -1276,9 +1279,9 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var description = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitleDescription"); + var description = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitleDescription"); - var subTitle = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitle"); + var subTitle = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitle"); // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ -- cgit v1.2.3 From a41ec5c9d4642f28cc1a277f555fc6a4f2929b85 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 23 Dec 2019 15:29:30 +0100 Subject: Fix typo --- MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs index d5529e56c..6b60b66c0 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The filename. [JsonPropertyName("filename")] - public string Fileame { get; set; } + public string Filename { get; set; } /// /// Gets or sets the nb_streams. -- cgit v1.2.3 From 59cdfdc2d9435f06dc535837ae9d1fe63543bb08 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 2 Jan 2020 14:38:13 +0100 Subject: Fix JSON subtitle writer --- MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs index 241ebc6df..1b452b0ce 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs @@ -16,6 +16,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles using (var writer = new Utf8JsonWriter(stream)) { var trackevents = info.TrackEvents; + writer.WriteStartObject(); writer.WriteStartArray("TrackEvents"); for (int i = 0; i < trackevents.Count; i++) @@ -33,7 +34,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles writer.WriteEndObject(); } + writer.WriteEndArray(); writer.WriteEndObject(); + + writer.Flush(); } } } -- cgit v1.2.3 From 09d1f976d994f13dd6e69bae3d371262abb0d56d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 2 Jan 2020 20:19:01 +0100 Subject: Replace unicode char with its integer value --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 54d02fc9f..3067238f7 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1334,24 +1334,25 @@ namespace MediaBrowser.MediaEncoding.Probing { video.Timestamp = GetMpegTimestamp(video.Path); - _logger.LogDebug("Video has {timestamp} timestamp", video.Timestamp); + _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); } catch (Exception ex) { - _logger.LogError(ex, "Error extracting timestamp info from {path}", video.Path); + _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); video.Timestamp = null; } } } } + // REVIEW: private TransportStreamTimestamp GetMpegTimestamp(string path) { - var packetBuffer = new byte['Å']; + var packetBuffer = new byte[197]; - using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { - fs.Read(packetBuffer, 0, packetBuffer.Length); + fs.Read(packetBuffer); } if (packetBuffer[0] == 71) @@ -1359,7 +1360,7 @@ namespace MediaBrowser.MediaEncoding.Probing return TransportStreamTimestamp.None; } - if ((packetBuffer[4] == 71) && (packetBuffer['Ä'] == 71)) + if ((packetBuffer[4] == 71) && (packetBuffer[196] == 71)) { if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) { -- cgit v1.2.3 From 70210b47a4dedd3d3905fc4d234c0346f58d064f Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Mon, 6 Jan 2020 10:39:01 +0100 Subject: Update MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs Co-Authored-By: dkanada --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 3067238f7..ff3596a85 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1345,7 +1345,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - // REVIEW: + // REVIEW: find out why the byte array needs to be 197 bytes long and comment the reason private TransportStreamTimestamp GetMpegTimestamp(string path) { var packetBuffer = new byte[197]; -- cgit v1.2.3 From 49fef5f09c12ff4b40b7213a9e155802acf45fff Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 7 Jan 2020 11:13:11 +0100 Subject: Update MediaBrowser.MediaEncoding/Probing/MediaChapter.cs Co-Authored-By: Erwin de Haan --- MediaBrowser.MediaEncoding/Probing/MediaChapter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs index a3607a760..6a45ccf49 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.MediaEncoding.Probing public class MediaChapter { [JsonPropertyName("id")] - public int id { get; set; } + public int Id { get; set; } [JsonPropertyName("time_base")] public string TimeBase { get; set; } -- cgit v1.2.3 From 9dfafb9e9fcddb253b157fe03b085b7fceef4290 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 7 Jan 2020 11:13:47 +0100 Subject: Update MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs Co-Authored-By: Erwin de Haan --- MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs index 6b60b66c0..8af122ef9 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The filename. [JsonPropertyName("filename")] - public string Filename { get; set; } + public string FileName { get; set; } /// /// Gets or sets the nb_streams. -- cgit v1.2.3 From a253fa616da3fd982ca2190b69d25853893665f1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 26 Dec 2019 23:09:00 +0100 Subject: Fix build and address comments --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Data/SqliteItemRepository.cs | 34 ++++---- .../Library/MediaSourceManager.cs | 9 -- Jellyfin.Api/Controllers/StartupController.cs | 1 - MediaBrowser.Api/Attachments/AttachmentService.cs | 19 ++--- .../Library/IMediaSourceManager.cs | 11 +-- .../MediaEncoding/IAttachmentExtractor.cs | 4 +- .../Attachments/AttachmentExtractor.cs | 97 +++++++++++----------- .../Encoder/EncodingUtils.cs | 2 +- 9 files changed, 82 insertions(+), 97 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7c3f59af2..c5ac27ed4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -878,7 +878,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(MediaBrowser.Controller.MediaEncoding.IAttachmentExtractor),typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); + serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); _displayPreferencesRepository.Initialize(); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 2206816a5..91ca8477d 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -55,8 +55,8 @@ namespace Emby.Server.Implementations.Data queryPrefixText.Append("insert into mediaattachments ("); foreach (var column in _mediaAttachmentSaveColumns) { - queryPrefixText.Append(column); - queryPrefixText.Append(','); + queryPrefixText.Append(column) + .Append(','); } queryPrefixText.Length -= 1; @@ -449,6 +449,7 @@ namespace Emby.Server.Implementations.Data "Filename", "MIMEType" }; + private static readonly string _mediaAttachmentInsertPrefix; private static string GetSaveItemCommandText() @@ -6208,7 +6209,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return list; } - public void SaveMediaAttachments(Guid id, List attachments, CancellationToken cancellationToken) + public void SaveMediaAttachments( + Guid id, + List attachments, + CancellationToken cancellationToken) { CheckDisposed(); if (id == Guid.Empty) @@ -6237,24 +6241,22 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } - private void InsertMediaAttachments(byte[] idBlob, List attachments, IDatabaseConnection db, CancellationToken cancellationToken) + private void InsertMediaAttachments( + byte[] idBlob, + List attachments, + IDatabaseConnection db, + CancellationToken cancellationToken) { - var startIndex = 0; - var insertAtOnce = 10; + const int InsertAtOnce = 10; - while (startIndex < attachments.Count) + for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce) { var insertText = new StringBuilder(_mediaAttachmentInsertPrefix); - var endIndex = Math.Min(attachments.Count, startIndex + insertAtOnce); + var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce); for (var i = startIndex; i < endIndex; i++) { - if (i != startIndex) - { - insertText.Append(','); - } - var index = i.ToString(CultureInfo.InvariantCulture); insertText.Append("(@ItemId, "); @@ -6265,9 +6267,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type insertText.Length -= 1; - insertText.Append(")"); + insertText.Append("),"); } + insertText.Length--; + cancellationToken.ThrowIfCancellationRequested(); using (var statement = PrepareStatement(db, insertText.ToString())) @@ -6291,8 +6295,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.Reset(); statement.MoveNext(); } - - startIndex += insertAtOnce; } } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 4eff2807c..ba1564d1f 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -136,15 +136,6 @@ namespace Emby.Server.Implementations.Library return _itemRepo.GetMediaAttachments(query); } - /// - public List GetMediaAttachments(string mediaSourceId) - { - return GetMediaAttachments(new MediaAttachmentQuery - { - ItemId = new Guid(mediaSourceId) - }); - } - /// public List GetMediaAttachments(Guid itemId) { diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs index 1014c8c56..afc9b8f3d 100644 --- a/Jellyfin.Api/Controllers/StartupController.cs +++ b/Jellyfin.Api/Controllers/StartupController.cs @@ -96,7 +96,6 @@ namespace Jellyfin.Api.Controllers public StartupUserDto GetFirstUser() { var user = _userManager.Users.First(); - return new StartupUserDto { Name = user.Name, diff --git a/MediaBrowser.Api/Attachments/AttachmentService.cs b/MediaBrowser.Api/Attachments/AttachmentService.cs index 1ebfaa14b..ef09951b6 100644 --- a/MediaBrowser.Api/Attachments/AttachmentService.cs +++ b/MediaBrowser.Api/Attachments/AttachmentService.cs @@ -1,22 +1,14 @@ using System; -using System.Collections.Generic; -using System.Globalization; using System.IO; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; -using MimeTypes = MediaBrowser.Model.Net.MimeTypes; namespace MediaBrowser.Api.Attachments { @@ -38,7 +30,13 @@ namespace MediaBrowser.Api.Attachments private readonly ILibraryManager _libraryManager; private readonly IAttachmentExtractor _attachmentExtractor; - public AttachmentService(ILibraryManager libraryManager, IAttachmentExtractor attachmentExtractor) + public AttachmentService( + ILogger logger, + IServerConfigurationManager serverConfigurationManager, + IHttpResultFactory httpResultFactory, + ILibraryManager libraryManager, + IAttachmentExtractor attachmentExtractor) + : base(logger, serverConfigurationManager, httpResultFactory) { _libraryManager = libraryManager; _attachmentExtractor = attachmentExtractor; @@ -46,7 +44,6 @@ namespace MediaBrowser.Api.Attachments public async Task Get(GetAttachment request) { - var item = (Video)_libraryManager.GetItemById(request.Id); var (attachment, attachmentStream) = await GetAttachment(request).ConfigureAwait(false); var mime = string.IsNullOrWhiteSpace(attachment.MIMEType) ? "application/octet-stream" : attachment.MIMEType; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index dda8d397a..09e6fda88 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -41,21 +41,14 @@ namespace MediaBrowser.Controller.Library /// /// Gets the media attachments. /// - /// The item identifier. + /// The item identifier. /// IEnumerable<MediaAttachment>. List GetMediaAttachments(Guid itemId); /// /// Gets the media attachments. /// - /// The The media source identifier. - /// IEnumerable<MediaAttachment>. - - List GetMediaAttachments(string mediaSourceId); - /// - /// Gets the media attachments. - /// - /// The query. + /// The query. /// IEnumerable<MediaAttachment>. List GetMediaAttachments(MediaAttachmentQuery query); diff --git a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs index 59c0a3f21..7c7e84de6 100644 --- a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs +++ b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs @@ -2,14 +2,14 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.MediaEncoding { public interface IAttachmentExtractor { - Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, + Task<(MediaAttachment attachment, Stream stream)> GetAttachment( + BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken); diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index cb22343c4..c371e8b94 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -4,44 +4,41 @@ using System.Collections.Concurrent; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; -using UtfUnknown; namespace MediaBrowser.MediaEncoding.Attachments { - public class AttachmentExtractor : IAttachmentExtractor + public class AttachmentExtractor : IAttachmentExtractor, IDisposable { - private readonly ILibraryManager _libraryManager; private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IMediaSourceManager _mediaSourceManager; + private readonly ConcurrentDictionary _semaphoreLocks = + new ConcurrentDictionary(); + + private bool _disposed = false; + public AttachmentExtractor( - ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IMediaSourceManager mediaSourceManager) { - _libraryManager = libraryManager; _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; @@ -49,8 +46,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _mediaSourceManager = mediaSourceManager; } - private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments"); - + /// public async Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) { if (item == null) @@ -70,12 +66,14 @@ namespace MediaBrowser.MediaEncoding.Attachments { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} not found"); } + var mediaAttachment = mediaSource.MediaAttachments .FirstOrDefault(i => i.Index == attachmentStreamIndex); if (mediaAttachment == null) { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}"); } + var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken) .ConfigureAwait(false); @@ -87,49 +85,32 @@ namespace MediaBrowser.MediaEncoding.Attachments MediaAttachment mediaAttachment, CancellationToken cancellationToken) { - var inputFiles = new[] { mediaSource.Path }; - var attachmentPath = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); - var stream = await GetAttachmentStream(attachmentPath, cancellationToken).ConfigureAwait(false); - return stream; + var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); + return File.OpenRead(attachmentPath); } - private async Task GetAttachmentStream( - string path, - CancellationToken cancellationToken) - { - return File.OpenRead(path); - } - - private async Task GetReadableFile( + private async Task GetReadableFile( string mediaPath, - string[] inputFiles, + string inputFile, MediaProtocol protocol, MediaAttachment mediaAttachment, CancellationToken cancellationToken) { var outputPath = GetAttachmentCachePath(mediaPath, protocol, mediaAttachment.Index); - await ExtractAttachment(inputFiles, protocol, mediaAttachment.Index, outputPath, cancellationToken) + await ExtractAttachment(inputFile, protocol, mediaAttachment.Index, outputPath, cancellationToken) .ConfigureAwait(false); return outputPath; } - private readonly ConcurrentDictionary _semaphoreLocks = - new ConcurrentDictionary(); - - private SemaphoreSlim GetLock(string filename) - { - return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1)); - } - private async Task ExtractAttachment( - string[] inputFiles, + string inputFile, MediaProtocol protocol, int attachmentStreamIndex, string outputPath, CancellationToken cancellationToken) { - var semaphore = GetLock(outputPath); + var semaphore = _semaphoreLocks.GetOrAdd(outputPath, key => new SemaphoreSlim(1, 1)); await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -137,7 +118,11 @@ namespace MediaBrowser.MediaEncoding.Attachments { if (!File.Exists(outputPath)) { - await ExtractAttachmentInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), attachmentStreamIndex, outputPath, cancellationToken).ConfigureAwait(false); + await ExtractAttachmentInternal( + _mediaEncoder.GetInputArgument(new[] { inputFile }, protocol), + attachmentStreamIndex, + outputPath, + cancellationToken).ConfigureAwait(false); } } finally @@ -186,16 +171,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); - try - { - process.Start(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting ffmpeg"); - - throw; - } + process.Start(); var processTcs = new TaskCompletionSource(); process.EnableRaisingEvents = true; @@ -216,6 +192,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogError(ex, "Error killing attachment extraction process"); } } + var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); @@ -270,9 +247,35 @@ namespace MediaBrowser.MediaEncoding.Attachments { filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); } + var prefix = filename.Substring(0, 1); - return Path.Combine(AttachmentCachePath, prefix, filename); + return Path.Combine(_appPaths.DataPath, "attachments", prefix, filename); + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); } + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + + } + + _disposed = true; + } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index d4aede572..c5da42089 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -43,7 +43,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// The path. /// System.String. - private static string GetFileInputArgument(string path) + public static string GetFileInputArgument(string path) { if (path.IndexOf("://") != -1) { -- cgit v1.2.3 From 8a0ef4103632b2888249af2f385e1e7bfc06fbfe Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 26 Dec 2019 23:20:31 +0100 Subject: Minor improvements --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 4 ++-- MediaBrowser.Controller/Persistence/IItemRepository.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs | 2 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 2 +- MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs | 10 +++++----- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 91ca8477d..2ff19a639 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -6211,7 +6211,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public void SaveMediaAttachments( Guid id, - List attachments, + IReadOnlyList attachments, CancellationToken cancellationToken) { CheckDisposed(); @@ -6243,7 +6243,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type private void InsertMediaAttachments( byte[] idBlob, - List attachments, + IReadOnlyList attachments, IDatabaseConnection db, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 68df20c3a..5a5b7f58f 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller.Persistence /// The identifier. /// The attachments. /// The cancellation token. - void SaveMediaAttachments(Guid id, List attachments, CancellationToken cancellationToken); + void SaveMediaAttachments(Guid id, IReadOnlyList attachments, CancellationToken cancellationToken); /// /// Gets the item ids. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index c5da42089..d4aede572 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -43,7 +43,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// The path. /// System.String. - public static string GetFileInputArgument(string path) + private static string GetFileInputArgument(string path) { if (path.IndexOf("://") != -1) { diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 8a1aa55b6..5cb056566 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Model.Dto public List MediaStreams { get; set; } - public List MediaAttachments { get; set; } + public IReadOnlyList MediaAttachments { get; set; } public string[] Formats { get; set; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index ae3e584d4..2b178d4d4 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -158,7 +158,7 @@ namespace MediaBrowser.Providers.MediaInfo MetadataRefreshOptions options) { List mediaStreams; - List mediaAttachments; + IReadOnlyList mediaAttachments; List chapters; if (mediaInfo != null) @@ -200,7 +200,7 @@ namespace MediaBrowser.Providers.MediaInfo else { mediaStreams = new List(); - mediaAttachments = new List(); + mediaAttachments = Array.Empty(); chapters = new List(); } @@ -213,13 +213,13 @@ namespace MediaBrowser.Providers.MediaInfo FetchEmbeddedInfo(video, mediaInfo, options, libraryOptions); FetchPeople(video, mediaInfo, options); video.Timestamp = mediaInfo.Timestamp; - video.Video3DFormat = video.Video3DFormat ?? mediaInfo.Video3DFormat; + video.Video3DFormat ??= mediaInfo.Video3DFormat; } var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); - video.Height = videoStream == null ? 0 : videoStream.Height ?? 0; - video.Width = videoStream == null ? 0 : videoStream.Width ?? 0; + video.Height = videoStream?.Height ?? 0; + video.Width = videoStream?.Width ?? 0; video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index; -- cgit v1.2.3 From 73fac50e57982ac46aea2b487e9906826c3dc3b2 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 8 Jan 2020 10:52:48 +0900 Subject: rename two properties based on code suggestions --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 8 ++++---- MediaBrowser.Api/Attachments/AttachmentService.cs | 2 +- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 4 ++-- MediaBrowser.Model/Entities/MediaAttachment.cs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 2ff19a639..c514846e5 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -6288,8 +6288,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.TryBind("@Codec" + index, attachment.Codec); statement.TryBind("@CodecTag" + index, attachment.CodecTag); statement.TryBind("@Comment" + index, attachment.Comment); - statement.TryBind("@Filename" + index, attachment.Filename); - statement.TryBind("@MIMEType" + index, attachment.MIMEType); + statement.TryBind("@FileName" + index, attachment.FileName); + statement.TryBind("@MimeType" + index, attachment.MimeType); } statement.Reset(); @@ -6327,12 +6327,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type if (reader[6].SQLiteType != SQLiteType.Null) { - item.Filename = reader[5].ToString(); + item.FileName = reader[5].ToString(); } if (reader[6].SQLiteType != SQLiteType.Null) { - item.MIMEType = reader[6].ToString(); + item.MimeType = reader[6].ToString(); } return item; diff --git a/MediaBrowser.Api/Attachments/AttachmentService.cs b/MediaBrowser.Api/Attachments/AttachmentService.cs index ef09951b6..1632ca1b0 100644 --- a/MediaBrowser.Api/Attachments/AttachmentService.cs +++ b/MediaBrowser.Api/Attachments/AttachmentService.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Api.Attachments public async Task Get(GetAttachment request) { var (attachment, attachmentStream) = await GetAttachment(request).ConfigureAwait(false); - var mime = string.IsNullOrWhiteSpace(attachment.MIMEType) ? "application/octet-stream" : attachment.MIMEType; + var mime = string.IsNullOrWhiteSpace(attachment.MimeType) ? "application/octet-stream" : attachment.MimeType; return ResultFactory.GetResult(Request, attachmentStream, mime); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index f2056c566..6664b34a5 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -542,8 +542,8 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo.tags != null) { - attachment.Filename = GetDictionaryValue(streamInfo.tags, "filename"); - attachment.MIMEType = GetDictionaryValue(streamInfo.tags, "mimetype"); + attachment.FileName = GetDictionaryValue(streamInfo.tags, "filename"); + attachment.MimeType = GetDictionaryValue(streamInfo.tags, "mimetype"); attachment.Comment = GetDictionaryValue(streamInfo.tags, "comment"); } diff --git a/MediaBrowser.Model/Entities/MediaAttachment.cs b/MediaBrowser.Model/Entities/MediaAttachment.cs index 26279b72b..8f8c3efd2 100644 --- a/MediaBrowser.Model/Entities/MediaAttachment.cs +++ b/MediaBrowser.Model/Entities/MediaAttachment.cs @@ -33,13 +33,13 @@ namespace MediaBrowser.Model.Entities /// Gets or sets the filename. /// /// The filename. - public string Filename { get; set; } + public string FileName { get; set; } /// /// Gets or sets the MIME type. /// /// The MIME type. - public string MIMEType { get; set; } + public string MimeType { get; set; } /// /// Gets or sets the delivery URL. -- cgit v1.2.3 From 277e9d2b0b9859aa374ed4c4add10f3c46dbdfd2 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 8 Jan 2020 18:13:11 +0100 Subject: fix build --- .../Probing/ProbeResultNormalizer.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 37baef5b0..bd89c6cae 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.MediaEncoding.Probing .Where(i => i != null) .ToList(); - if (data.format != null) + if (data.Format != null) { info.Container = NormalizeFormat(data.Format.FormatName); @@ -523,27 +523,27 @@ namespace MediaBrowser.MediaEncoding.Probing /// MediaAttachments. private MediaAttachment GetMediaAttachment(MediaStreamInfo streamInfo) { - if (!string.Equals(streamInfo.codec_type, "attachment", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(streamInfo.CodecType, "attachment", StringComparison.OrdinalIgnoreCase)) { return null; } var attachment = new MediaAttachment { - Codec = streamInfo.codec_name, - Index = streamInfo.index + Codec = streamInfo.CodecName, + Index = streamInfo.Index }; - if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string)) + if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString)) { - attachment.CodecTag = streamInfo.codec_tag_string; + attachment.CodecTag = streamInfo.CodecTagString; } - if (streamInfo.tags != null) + if (streamInfo.Tags != null) { - attachment.FileName = GetDictionaryValue(streamInfo.tags, "filename"); - attachment.MimeType = GetDictionaryValue(streamInfo.tags, "mimetype"); - attachment.Comment = GetDictionaryValue(streamInfo.tags, "comment"); + attachment.FileName = GetDictionaryValue(streamInfo.Tags, "filename"); + attachment.MimeType = GetDictionaryValue(streamInfo.Tags, "mimetype"); + attachment.Comment = GetDictionaryValue(streamInfo.Tags, "comment"); } return attachment; -- cgit v1.2.3 From b1af8a4178b5d993b09e5682a0149ea37766ff91 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 8 Jan 2020 18:14:01 +0100 Subject: Rename function --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index cd3d82e86..78dc7b607 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (result.Format != null && result.Format.Tags != null) { - result.Format.Tags = ConvertDictionaryToCaseInSensitive(result.Format.Tags); + result.Format.Tags = ConvertDictionaryToCaseInsensitive(result.Format.Tags); } if (result.Streams != null) @@ -28,7 +28,7 @@ namespace MediaBrowser.MediaEncoding.Probing { if (stream.Tags != null) { - stream.Tags = ConvertDictionaryToCaseInSensitive(stream.Tags); + stream.Tags = ConvertDictionaryToCaseInsensitive(stream.Tags); } } } @@ -98,7 +98,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The dict. /// Dictionary{System.StringSystem.String}. - private static Dictionary ConvertDictionaryToCaseInSensitive(IReadOnlyDictionary dict) + private static Dictionary ConvertDictionaryToCaseInsensitive(IReadOnlyDictionary dict) { return new Dictionary(dict, StringComparer.OrdinalIgnoreCase); } -- cgit v1.2.3 From e95239e28132b4d6486ee9272d20ec5ada46b66c Mon Sep 17 00:00:00 2001 From: Nyanmisaka <799610810@qq.com> Date: Sat, 11 Jan 2020 01:36:25 +0800 Subject: add support for AMD h264_amf & hevc_amf --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 1feca0ec9..993cd3f74 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -55,7 +55,9 @@ namespace MediaBrowser.MediaEncoding.Encoder "h264_vaapi", "hevc_vaapi", "h264_v4l2m2m", - "ac3" + "ac3", + "h264_amf", + "hevc_amf" }; // Try and use the individual library versions to determine a FFmpeg version -- cgit v1.2.3 From 0d6a4c2909632229b3c6a0f1b65f03c48d0f9eb2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 11 Jan 2020 00:08:47 +0100 Subject: Fix build --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index c371e8b94..c530c9fd8 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Attachments throw new ArgumentNullException(nameof(mediaSourceId)); } - var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); + var mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false); var mediaSource = mediaSources .FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); if (mediaSource == null) @@ -196,7 +196,7 @@ namespace MediaBrowser.MediaEncoding.Attachments var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); - + var failed = false; if (exitCode != 0) -- cgit v1.2.3 From 93ab829df523c36a44ffa2f9caaf96505a2b2e5c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 12 Jan 2020 23:25:57 +0100 Subject: Attempt #3 --- MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 7fa7afa5b..0b2f1d231 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -225,7 +225,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The start_pts. [JsonPropertyName("start_pts")] - public int StartPts { get; set; } + public long StartPts { get; set; } /// /// Gets or sets the is_avc. -- cgit v1.2.3 From 2c10891b66bf5963d2bfca34b704607a3bc0de85 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <799610810@qq.com> Date: Wed, 15 Jan 2020 18:45:28 +0800 Subject: turn on indentation. --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 993cd3f74..f5decdc0d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -56,8 +56,8 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc_vaapi", "h264_v4l2m2m", "ac3", - "h264_amf", - "hevc_amf" + "h264_amf", + "hevc_amf" }; // Try and use the individual library versions to determine a FFmpeg version -- cgit v1.2.3 From e882b03e817715bd14223cb2b9495e983ff5ac2f Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 16 Jan 2020 13:30:38 +0100 Subject: Add back support for DVDs copied as folders --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 77 +++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index e0f7b992c..deab0715c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -849,14 +849,89 @@ namespace MediaBrowser.MediaEncoding.Encoder } } + /// public Task ConvertImage(string inputPath, string outputPath) { throw new NotImplementedException(); } + /// public IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber) { - throw new NotImplementedException(); + // min size 300 mb + const long MinPlayableSize = 314572800; + + var root = isoMount != null ? isoMount.MountedPath : path; + + // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size + // Once we reach a file that is at least the minimum, return all subsequent ones + var allVobs = _fileSystem.GetFiles(root, true) + .Where(file => string.Equals(file.Extension, ".vob", StringComparison.OrdinalIgnoreCase)) + .OrderBy(i => i.FullName) + .ToList(); + + // If we didn't find any satisfying the min length, just take them all + if (allVobs.Count == 0) + { + _logger.LogWarning("No vobs found in dvd structure."); + return Enumerable.Empty(); + } + + if (titleNumber.HasValue) + { + var prefix = string.Format("VTS_0{0}_", titleNumber.Value.ToString(CultureInfo.InvariantCulture)); + var vobs = allVobs.Where(i => i.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList(); + + if (vobs.Count > 0) + { + var minSizeVobs = vobs + .SkipWhile(f => f.Length < MinPlayableSize) + .ToList(); + + return minSizeVobs.Count == 0 ? vobs.Select(i => i.FullName) : minSizeVobs.Select(i => i.FullName); + } + + _logger.LogWarning("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", video.Path); + } + + var files = allVobs + .SkipWhile(f => f.Length < MinPlayableSize) + .ToList(); + + // If we didn't find any satisfying the min length, just take them all + if (files.Count == 0) + { + _logger.LogWarning("Vob size filter resulted in zero matches. Taking all vobs."); + files = allVobs; + } + + // Assuming they're named "vts_05_01", take all files whose second part matches that of the first file + if (files.Count > 0) + { + var parts = _fileSystem.GetFileNameWithoutExtension(files[0]).Split('_'); + + if (parts.Length == 3) + { + var title = parts[1]; + + files = files.TakeWhile(f => + { + var fileParts = _fileSystem.GetFileNameWithoutExtension(f).Split('_'); + + return fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase); + + }).ToList(); + + // If this resulted in not getting any vobs, just take them all + if (files.Count == 0) + { + _logger.LogWarning("Vob filename filter resulted in zero matches. Taking all vobs."); + files = allVobs; + } + } + } + + return files.Select(i => i.FullName); } public bool CanExtractSubtitles(string codec) -- cgit v1.2.3 From f3a1729964f8ff582aaa9f31eb415114340035ce Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 16 Jan 2020 15:02:50 +0100 Subject: Address comments --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index deab0715c..4123f0203 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -879,7 +879,10 @@ namespace MediaBrowser.MediaEncoding.Encoder if (titleNumber.HasValue) { - var prefix = string.Format("VTS_0{0}_", titleNumber.Value.ToString(CultureInfo.InvariantCulture)); + var prefix = string.Format( + CultureInfo.InvariantCulture, + titleNumber.Value >= 10 ? "VTS_{0}_" : "VTS_0{0}_", + titleNumber.Value); var vobs = allVobs.Where(i => i.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList(); if (vobs.Count > 0) @@ -891,7 +894,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return minSizeVobs.Count == 0 ? vobs.Select(i => i.FullName) : minSizeVobs.Select(i => i.FullName); } - _logger.LogWarning("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", video.Path); + _logger.LogWarning("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", path); } var files = allVobs -- cgit v1.2.3 From c8409d2ea1b4843bb89377b130733e61e6dc2e41 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 8 Jan 2020 17:52:50 +0100 Subject: Remove FileSystem.GetStream --- DvdLib/Ifo/Dvd.cs | 4 +- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 3 +- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Devices/DeviceManager.cs | 2 +- .../HttpClientManager/HttpClientManager.cs | 4 +- .../HttpServer/FileWriter.cs | 14 +-- .../IO/ManagedFileSystem.cs | 81 ------------ .../LiveTv/EmbyTV/DirectRecorder.cs | 8 +- .../LiveTv/EmbyTV/EmbyTV.cs | 8 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 6 +- .../LiveTv/TunerHosts/LiveStream.cs | 4 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 4 +- .../Serialization/JsonSerializer.cs | 32 ++--- MediaBrowser.Api/Images/ImageService.cs | 2 +- MediaBrowser.Api/Images/RemoteImageService.cs | 6 +- MediaBrowser.Api/ItemLookupService.cs | 2 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 8 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 8 +- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 4 +- .../Progressive/BaseProgressiveStreamingService.cs | 2 +- .../Progressive/ProgressiveStreamWriter.cs | 12 +- MediaBrowser.Api/System/SystemService.cs | 4 +- .../MediaEncoding/EncodingHelper.cs | 28 ++--- MediaBrowser.Controller/Net/IHttpResultFactory.cs | 2 +- MediaBrowser.Controller/Net/StaticResultOptions.cs | 4 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- .../BdInfo/BdInfoDirectoryInfo.cs | 38 +++--- .../BdInfo/BdInfoFileInfo.cs | 14 +-- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/IO/IFileSystem.cs | 138 --------------------- MediaBrowser.Model/IO/IODefaults.cs | 18 +++ MediaBrowser.Model/IO/StreamDefaults.cs | 18 --- MediaBrowser.Providers/Manager/ImageSaver.cs | 4 +- .../Manager/ItemImageProvider.cs | 6 +- MediaBrowser.Providers/Manager/MetadataService.cs | 2 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../Music/AudioDbAlbumProvider.cs | 6 +- .../Music/AudioDbArtistProvider.cs | 5 +- MediaBrowser.Providers/Omdb/OmdbProvider.cs | 4 +- .../Studios/StudiosImageProvider.cs | 6 +- .../Subtitles/SubtitleManager.cs | 4 +- .../Tmdb/People/TmdbPersonProvider.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 +- 45 files changed, 142 insertions(+), 389 deletions(-) create mode 100644 MediaBrowser.Model/IO/IODefaults.cs delete mode 100644 MediaBrowser.Model/IO/StreamDefaults.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index 90125fa3e..157b2e197 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -42,7 +42,7 @@ namespace DvdLib.Ifo } else { - using (var vmgFs = _fileSystem.GetFileStream(vmgPath.FullName, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var vmgFs = new FileStream(vmgPath.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var vmgRead = new BigEndianBinaryReader(vmgFs)) { @@ -95,7 +95,7 @@ namespace DvdLib.Ifo { VTSPaths[vtsNum] = vtsPath; - using (var vtsFs = _fileSystem.GetFileStream(vtsPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var vtsFs = new FileStream(vtsPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var vtsRead = new BigEndianBinaryReader(vtsFs)) { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index d5d788021..7e744e0aa 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -385,7 +385,7 @@ namespace Emby.Dlna { Directory.CreateDirectory(systemProfilesPath); - using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { await stream.CopyToAsync(fileStream); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index ce8089e59..4e0f9493a 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; @@ -129,7 +128,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = _fileSystem.GetFileStream(file.Item1, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true)) + using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0bb1d832f..226a8f302 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -599,7 +599,7 @@ namespace Emby.Server.Implementations HttpsPort = ServerConfiguration.DefaultHttpsPort; } - JsonSerializer = new JsonSerializer(FileSystemManager); + JsonSerializer = new JsonSerializer(); if (Plugins != null) { diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index ef7317050..2bd0b840a 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -243,7 +243,7 @@ namespace Emby.Server.Implementations.Devices try { - using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { await stream.CopyToAsync(fs).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 50233ea48..8a2bc83fb 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -197,7 +197,7 @@ namespace Emby.Server.Implementations.HttpClientManager if (File.Exists(responseCachePath) && _fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow) { - var stream = _fileSystem.GetFileStream(responseCachePath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true); + var stream = new FileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true); return new HttpResponseInfo { @@ -220,7 +220,7 @@ namespace Emby.Server.Implementations.HttpClientManager FileMode.Create, FileAccess.Write, FileShare.None, - StreamDefaults.DefaultFileStreamBufferSize, + IODefaults.FileStreamBufferSize, true)) { await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs index 1795651fd..d36f230d6 100644 --- a/Emby.Server.Implementations/HttpServer/FileWriter.cs +++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.HttpServer SetRangeValues(); } - FileShare = FileShareMode.Read; + FileShare = FileShare.Read; Cookies = new List(); } @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.HttpServer public List Cookies { get; private set; } - public FileShareMode FileShare { get; set; } + public FileShare FileShare { get; set; } /// /// Gets the options. @@ -222,17 +222,17 @@ namespace Emby.Server.Implementations.HttpServer } } - public async Task TransmitFile(Stream stream, string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) + public async Task TransmitFile(Stream stream, string path, long offset, long count, FileShare fileShare, CancellationToken cancellationToken) { - var fileOpenOptions = FileOpenOptions.SequentialScan; + var fileOptions = FileOptions.SequentialScan; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - fileOpenOptions |= FileOpenOptions.Asynchronous; + fileOptions |= FileOptions.Asynchronous; } - using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, fileOpenOptions)) + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, fileOptions)) { if (offset > 0) { @@ -245,7 +245,7 @@ namespace Emby.Server.Implementations.HttpServer } else { - await fs.CopyToAsync(stream, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + await fs.CopyToAsync(stream, IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false); } } } diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 68417876c..da5a4d50e 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -365,87 +365,6 @@ namespace Emby.Server.Implementations.IO return GetLastWriteTimeUtc(GetFileSystemInfo(path)); } - /// - /// Gets the file stream. - /// - /// The path. - /// The mode. - /// The access. - /// The share. - /// if set to true [is asynchronous]. - /// FileStream. - public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false) - { - if (isAsync) - { - return GetFileStream(path, mode, access, share, FileOpenOptions.Asynchronous); - } - - return GetFileStream(path, mode, access, share, FileOpenOptions.None); - } - - public virtual Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions) - => new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 4096, GetFileOptions(fileOpenOptions)); - - private static FileOptions GetFileOptions(FileOpenOptions mode) - { - var val = (int)mode; - return (FileOptions)val; - } - - private static FileMode GetFileMode(FileOpenMode mode) - { - switch (mode) - { - //case FileOpenMode.Append: - // return FileMode.Append; - case FileOpenMode.Create: - return FileMode.Create; - case FileOpenMode.CreateNew: - return FileMode.CreateNew; - case FileOpenMode.Open: - return FileMode.Open; - case FileOpenMode.OpenOrCreate: - return FileMode.OpenOrCreate; - //case FileOpenMode.Truncate: - // return FileMode.Truncate; - default: - throw new Exception("Unrecognized FileOpenMode"); - } - } - - private static FileAccess GetFileAccess(FileAccessMode mode) - { - switch (mode) - { - //case FileAccessMode.ReadWrite: - // return FileAccess.ReadWrite; - case FileAccessMode.Write: - return FileAccess.Write; - case FileAccessMode.Read: - return FileAccess.Read; - default: - throw new Exception("Unrecognized FileAccessMode"); - } - } - - private static FileShare GetFileShare(FileShareMode mode) - { - switch (mode) - { - case FileShareMode.ReadWrite: - return FileShare.ReadWrite; - case FileShareMode.Write: - return FileShare.Write; - case FileShareMode.Read: - return FileShare.Read; - case FileShareMode.None: - return FileShare.None; - default: - throw new Exception("Unrecognized FileShareMode"); - } - } - public virtual void SetHidden(string path, bool isHidden) { if (OperatingSystem.Id != OperatingSystemId.Windows) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 84e8c31f9..161cf6051 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -15,14 +15,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { private readonly ILogger _logger; private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; private readonly IStreamHelper _streamHelper; - public DirectRecorder(ILogger logger, IHttpClient httpClient, IFileSystem fileSystem, IStreamHelper streamHelper) + public DirectRecorder(ILogger logger, IHttpClient httpClient, IStreamHelper streamHelper) { _logger = logger; _httpClient = httpClient; - _fileSystem = fileSystem; _streamHelper = streamHelper; } @@ -45,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) { onStarted(); @@ -81,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) { onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index f4d6cd4d3..2fe699aab 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1664,10 +1664,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (mediaSource.RequiresLooping || !(mediaSource.Container ?? string.Empty).EndsWith("ts", StringComparison.OrdinalIgnoreCase) || (mediaSource.Protocol != MediaProtocol.File && mediaSource.Protocol != MediaProtocol.Http)) { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config); + return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config); } - return new DirectRecorder(_logger, _httpClient, _fileSystem, _streamHelper); + return new DirectRecorder(_logger, _httpClient, _streamHelper); } private void OnSuccessfulRecording(TimerInfo timer, string path) @@ -1888,7 +1888,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = _fileSystem.GetFileStream(nfoPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) { var settings = new XmlWriterSettings { @@ -1952,7 +1952,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = _fileSystem.GetFileStream(nfoPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) { var settings = new XmlWriterSettings { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index cc9c8e5d2..ee5086a65 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -24,7 +23,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public class EncodedRecorder : IRecorder { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IServerApplicationPaths _appPaths; private bool _hasExited; @@ -38,7 +36,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public EncodedRecorder( ILogger logger, - IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, @@ -46,7 +43,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IServerConfigurationManager config) { _logger = logger; - _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; @@ -107,7 +103,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 1d55e7992..862b9fdfe 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts FileMode.Open, FileAccess.Read, FileShare.ReadWrite, - StreamDefaults.DefaultFileStreamBufferSize, + IODefaults.FileStreamBufferSize, allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan); public Task DeleteTempFiles() @@ -199,7 +199,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts await StreamHelper.CopyToAsync( inputStream, stream, - StreamDefaults.DefaultCopyToBufferSize, + IODefaults.CopyToBufferSize, emptyReadLimit, cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 0d94f4b32..99244eb62 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -127,12 +127,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using (response) using (var stream = response.Content) - using (var fileStream = FileSystem.GetFileStream(TempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None)) + using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { await StreamHelper.CopyToAsync( stream, fileStream, - StreamDefaults.DefaultCopyToBufferSize, + IODefaults.CopyToBufferSize, () => Resolve(openTaskCompletionSource), cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/Serialization/JsonSerializer.cs b/Emby.Server.Implementations/Serialization/JsonSerializer.cs index 36196ee36..bcc814daf 100644 --- a/Emby.Server.Implementations/Serialization/JsonSerializer.cs +++ b/Emby.Server.Implementations/Serialization/JsonSerializer.cs @@ -2,7 +2,6 @@ using System; using System.Globalization; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.Serialization @@ -12,13 +11,15 @@ namespace Emby.Server.Implementations.Serialization /// public class JsonSerializer : IJsonSerializer { - private readonly IFileSystem _fileSystem; - - public JsonSerializer( - IFileSystem fileSystem) + public JsonSerializer() { - _fileSystem = fileSystem; - Configure(); + ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601; + ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; + ServiceStack.Text.JsConfig.IncludeNullValues = false; + ServiceStack.Text.JsConfig.AlwaysUseUtc = true; + ServiceStack.Text.JsConfig.AssumeUtc = true; + + ServiceStack.Text.JsConfig.SerializeFn = SerializeGuid; } /// @@ -81,7 +82,7 @@ namespace Emby.Server.Implementations.Serialization throw new ArgumentNullException(nameof(file)); } - using (var stream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) { SerializeToStream(obj, stream); } @@ -162,7 +163,6 @@ namespace Emby.Server.Implementations.Serialization throw new ArgumentNullException(nameof(stream)); } - return ServiceStack.Text.JsonSerializer.DeserializeFromStreamAsync(stream); } @@ -225,20 +225,6 @@ namespace Emby.Server.Implementations.Serialization } } - /// - /// Configures this instance. - /// - private void Configure() - { - ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601; - ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; - ServiceStack.Text.JsConfig.IncludeNullValues = false; - ServiceStack.Text.JsConfig.AlwaysUseUtc = true; - ServiceStack.Text.JsConfig.AssumeUtc = true; - - ServiceStack.Text.JsConfig.SerializeFn = SerializeGuid; - } - private static string SerializeGuid(Guid guid) { if (guid.Equals(Guid.Empty)) diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index e94c1321f..c55618aa1 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -656,7 +656,7 @@ namespace MediaBrowser.Api.Images IsHeadRequest = isHeadRequest, Path = imageResult.Item1, - FileShare = FileShareMode.Read + FileShare = FileShare.Read }).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 5a37d3730..f03f5efd8 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -274,11 +274,9 @@ namespace MediaBrowser.Api.Images Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) + using (var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { - using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) - { - await stream.CopyToAsync(filestream).ConfigureAwait(false); - } + await stream.CopyToAsync(filestream).ConfigureAwait(false); } Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index ea5a99892..a76369a15 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -305,7 +305,7 @@ namespace MediaBrowser.Api Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) - using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) + using (var filestream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { await stream.CopyToAsync(filestream).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 1f7dc0d71..ab74bab1c 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -261,7 +261,7 @@ namespace MediaBrowser.Api.Playback var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt"); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(Request.AbsoluteUri + Environment.NewLine + Environment.NewLine + JsonSerializer.SerializeToString(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 5d0dc98dd..0cbfe4bdf 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -168,7 +168,7 @@ namespace MediaBrowser.Api.Playback.Hls private string GetLivePlaylistText(string path, int segmentLength) { - using (var stream = FileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite)) + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var reader = new StreamReader(stream)) { @@ -211,7 +211,7 @@ namespace MediaBrowser.Api.Playback.Hls { try { - // Need to use FileShareMode.ReadWrite because we're reading the file at the same time it's being written + // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written using (var fileStream = GetPlaylistFileStream(playlist)) { using (var reader = new StreamReader(fileStream)) @@ -252,11 +252,11 @@ namespace MediaBrowser.Api.Playback.Hls try { - return FileSystem.GetFileStream(tmpPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, FileOpenOptions.SequentialScan); + return new FileStream(tmpPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.SequentialScan); } catch (IOException) { - return FileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, FileOpenOptions.SequentialScan); + return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.SequentialScan); } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 0178f53af..e85ed2050 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -537,7 +537,7 @@ namespace MediaBrowser.Api.Playback.Hls return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions { Path = segmentPath, - FileShare = FileShareMode.ReadWrite, + FileShare = FileShare.ReadWrite, OnComplete = () => { Logger.LogDebug("finished serving {0}", segmentPath); @@ -954,12 +954,12 @@ namespace MediaBrowser.Api.Playback.Hls // Unable to force key frames to h264_qsv transcode if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { - Logger.LogInformation("Bug Workaround: Disabling force_key_frames for h264_qsv"); - } + Logger.LogInformation("Bug Workaround: Disabling force_key_frames for h264_qsv"); + } else { args += " " + keyFrameArg; - } + } //args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0"; diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index bb12ab1f0..87ccde2e0 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Playback.Hls var file = request.SegmentId + Path.GetExtension(Request.PathInfo); file = Path.Combine(ServerConfigurationManager.GetTranscodePath(), file); - return ResultFactory.GetStaticFileResult(Request, file, FileShareMode.ReadWrite); + return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } private Task GetFileResult(string path, string playlistPath) @@ -150,7 +150,7 @@ namespace MediaBrowser.Api.Playback.Hls return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions { Path = path, - FileShare = FileShareMode.ReadWrite, + FileShare = FileShare.ReadWrite, OnComplete = () => { if (transcodingJob != null) diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index ed30dbba6..ed68219c9 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.Api.Playback.Progressive // ContentType = contentType, // IsHeadRequest = isHeadRequest, // Path = outputPath, - // FileShare = FileShareMode.ReadWrite, + // FileShare = FileShare.ReadWrite, // OnComplete = () => // { // if (transcodingJob != null) diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index 660912065..a53b848f9 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -21,8 +21,6 @@ namespace MediaBrowser.Api.Playback.Progressive private readonly CancellationToken _cancellationToken; private readonly Dictionary _outputHeaders; - const int StreamCopyToBufferSize = 81920; - private long _bytesWritten = 0; public long StartPosition { get; set; } public bool AllowEndOfFile = true; @@ -52,14 +50,14 @@ namespace MediaBrowser.Api.Playback.Progressive private Stream GetInputStream(bool allowAsyncFileRead) { - var fileOpenOptions = FileOpenOptions.SequentialScan; + var fileOptions = FileOptions.SequentialScan; if (allowAsyncFileRead) { - fileOpenOptions |= FileOpenOptions.Asynchronous; + fileOptions |= FileOptions.Asynchronous; } - return _fileSystem.GetFileStream(_path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, fileOpenOptions); + return new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); } public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken) @@ -127,7 +125,7 @@ namespace MediaBrowser.Api.Playback.Progressive private async Task CopyToInternalAsyncWithSyncRead(Stream source, Stream destination, CancellationToken cancellationToken) { - var array = new byte[StreamCopyToBufferSize]; + var array = new byte[IODefaults.CopyToBufferSize]; int bytesRead; int totalBytesRead = 0; @@ -154,7 +152,7 @@ namespace MediaBrowser.Api.Playback.Progressive private async Task CopyToInternalAsync(Stream source, Stream destination, CancellationToken cancellationToken) { - var array = new byte[StreamCopyToBufferSize]; + var array = new byte[IODefaults.CopyToBufferSize]; int bytesRead; int totalBytesRead = 0; diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index 3a56ba701..3a3eeb8b8 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -170,10 +170,10 @@ namespace MediaBrowser.Api.System // For older files, assume fully static if (file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1)) { - return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShareMode.Read); + return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.Read); } - return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShareMode.ReadWrite); + return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite); } /// diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index acc89e352..342c76414 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -475,7 +475,7 @@ namespace MediaBrowser.Controller.MediaEncoding .Append(' '); } - if (state.IsVideoRequest + if (state.IsVideoRequest && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); @@ -486,11 +486,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)) { arg.Append("-hwaccel qsv "); - } - else + } + else { arg.Append("-init_hw_device qsv=hw -filter_hw_device hw "); - } + } } arg.Append(videoDecoder + " "); @@ -653,7 +653,7 @@ namespace MediaBrowser.Controller.MediaEncoding // _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fallbackFontPath)); // using (var stream = _assemblyInfo.GetManifestResourceStream(GetType(), GetType().Namespace + ".DroidSansFallback.ttf")) // { - // using (var fileStream = _fileSystem.GetFileStream(fallbackFontPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + // using (var fileStream = new FileStream(fallbackFontPath, FileMode.Create, FileAccess.Write, FileShare.Read)) // { // stream.CopyTo(fileStream); // } @@ -1624,22 +1624,22 @@ namespace MediaBrowser.Controller.MediaEncoding // Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference) var retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\""; - if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { /* QSV in FFMpeg can now setup hardware overlay for transcodes. For software decoding and hardware encoding option, frames must be hwuploaded into hardware - with fixed frame size. + with fixed frame size. */ if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)) { retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\""; - } - else + } + else { retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]hwupload=extra_hw_frames=64[v];[v][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\""; } - } + } return string.Format( CultureInfo.InvariantCulture, @@ -1731,8 +1731,8 @@ namespace MediaBrowser.Controller.MediaEncoding vaapi_or_qsv, outputWidth, outputHeight)); - } - else + } + else { filters.Add(string.Format(CultureInfo.InvariantCulture, "scale_{0}=format=nv12", vaapi_or_qsv)); } @@ -1979,8 +1979,8 @@ namespace MediaBrowser.Controller.MediaEncoding var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options); - // If we are software decoding, and hardware encoding - if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) + // If we are software decoding, and hardware encoding + if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && (string.IsNullOrEmpty(videoDecoder) || !videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase))) { filters.Add("format=nv12|qsv"); diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index ff9ecf8af..fb00ee008 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Net /// The path. /// The file share. /// System.Object. - Task GetStaticFileResult(IRequest requestContext, string path, FileShareMode fileShare = FileShareMode.Read); + Task GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read); /// /// Gets the static file result. diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs index 7a179913a..726732660 100644 --- a/MediaBrowser.Controller/Net/StaticResultOptions.cs +++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs @@ -24,12 +24,12 @@ namespace MediaBrowser.Controller.Net public string Path { get; set; } public long? ContentLength { get; set; } - public FileShareMode FileShare { get; set; } + public FileShare FileShare { get; set; } public StaticResultOptions() { ResponseHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - FileShare = FileShareMode.Read; + FileShare = FileShare.Read; } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index bd727bcdf..46c531797 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.LocalMetadata.Savers // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { stream.CopyTo(filestream); } diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index 91c8b2792..e040286ab 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -1,16 +1,27 @@ using System; -using System.Collections.Generic; using System.Linq; using BDInfo.IO; using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { - class BdInfoDirectoryInfo : BDInfo.IO.IDirectoryInfo + class BdInfoDirectoryInfo : IDirectoryInfo { - IFileSystem _fileSystem = null; + private readonly IFileSystem _fileSystem = null; - FileSystemMetadata _impl = null; + private readonly FileSystemMetadata _impl = null; + + public BdInfoDirectoryInfo(IFileSystem fileSystem, string path) + { + _fileSystem = fileSystem; + _impl = _fileSystem.GetDirectoryInfo(path); + } + + private BdInfoDirectoryInfo(IFileSystem fileSystem, FileSystemMetadata impl) + { + _fileSystem = fileSystem; + _impl = impl; + } public string Name => _impl.Name; @@ -25,22 +36,11 @@ namespace MediaBrowser.MediaEncoding.BdInfo { return new BdInfoDirectoryInfo(_fileSystem, parentFolder); } + return null; } } - public BdInfoDirectoryInfo(IFileSystem fileSystem, string path) - { - _fileSystem = fileSystem; - _impl = _fileSystem.GetDirectoryInfo(path); - } - - private BdInfoDirectoryInfo(IFileSystem fileSystem, FileSystemMetadata impl) - { - _fileSystem = fileSystem; - _impl = impl; - } - public IDirectoryInfo[] GetDirectories() { return Array.ConvertAll(_fileSystem.GetDirectories(_impl.FullName).ToArray(), @@ -50,20 +50,20 @@ namespace MediaBrowser.MediaEncoding.BdInfo public IFileInfo[] GetFiles() { return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName).ToArray(), - x => new BdInfoFileInfo(_fileSystem, x)); + x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern) { return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), - x => new BdInfoFileInfo(_fileSystem, x)); + x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption) { return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), - x => new BdInfoFileInfo(_fileSystem, x)); + x => new BdInfoFileInfo(x)); } public static IDirectoryInfo FromFileSystemPath(Model.IO.IFileSystem fs, string path) diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs index de9d7cb78..a6ff4f767 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -1,11 +1,10 @@ +using System.IO; using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { class BdInfoFileInfo : BDInfo.IO.IFileInfo { - IFileSystem _fileSystem = null; - FileSystemMetadata _impl = null; public string Name => _impl.Name; @@ -18,18 +17,17 @@ namespace MediaBrowser.MediaEncoding.BdInfo public bool IsDir => _impl.IsDirectory; - public BdInfoFileInfo(IFileSystem fileSystem, FileSystemMetadata impl) + public BdInfoFileInfo(FileSystemMetadata impl) { - _fileSystem = fileSystem; _impl = impl; } public System.IO.Stream OpenRead() { - return _fileSystem.GetFileStream(FullName, - FileOpenMode.Open, - FileAccessMode.Read, - FileShareMode.Read); + return new FileStream(FullName, + FileMode.Open, + FileAccess.Read, + FileShare.Read); } public System.IO.StreamReader OpenText() diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 99bb368b2..a4a7595d2 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -691,7 +691,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText)) { - using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(fileStream, encoding)) { writer.Write(newText); diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index ca99b28ca..48e5eea6f 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -98,20 +98,6 @@ namespace MediaBrowser.Model.IO /// DateTime. DateTime GetLastWriteTimeUtc(string path); - /// - /// Gets the file stream. - /// - /// The path. - /// The mode. - /// The access. - /// The share. - /// if set to true [is asynchronous]. - /// FileStream. - Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false); - - Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, - FileOpenOptions fileOpenOptions); - /// /// Swaps the files. /// @@ -218,128 +204,4 @@ namespace MediaBrowser.Model.IO List GetDrives(); void SetExecutable(string path); } - - //TODO Investigate if can be replaced by the one from System.IO ? - public enum FileOpenMode - { - // - // Summary: - // Specifies that the operating system should create a new file. This requires System.Security.Permissions.FileIOPermissionAccess.Write - // permission. If the file already exists, an System.IO.IOException exception is - // thrown. - CreateNew = 1, - // - // Summary: - // Specifies that the operating system should create a new file. If the file already - // exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write - // permission. FileMode.Create is equivalent to requesting that if the file does - // not exist, use System.IO.FileMode.CreateNew; otherwise, use System.IO.FileMode.Truncate. - // If the file already exists but is a hidden file, an System.UnauthorizedAccessException - // exception is thrown. - Create = 2, - // - // Summary: - // Specifies that the operating system should open an existing file. The ability - // to open the file is dependent on the value specified by the System.IO.FileAccess - // enumeration. A System.IO.FileNotFoundException exception is thrown if the file - // does not exist. - Open = 3, - // - // Summary: - // Specifies that the operating system should open a file if it exists; otherwise, - // a new file should be created. If the file is opened with FileAccess.Read, System.Security.Permissions.FileIOPermissionAccess.Read - // permission is required. If the file access is FileAccess.Write, System.Security.Permissions.FileIOPermissionAccess.Write - // permission is required. If the file is opened with FileAccess.ReadWrite, both - // System.Security.Permissions.FileIOPermissionAccess.Read and System.Security.Permissions.FileIOPermissionAccess.Write - // permissions are required. - OpenOrCreate = 4 - } - - public enum FileAccessMode - { - // - // Summary: - // Read access to the file. Data can be read from the file. Combine with Write for - // read/write access. - Read = 1, - // - // Summary: - // Write access to the file. Data can be written to the file. Combine with Read - // for read/write access. - Write = 2 - } - - public enum FileShareMode - { - // - // Summary: - // Declines sharing of the current file. Any request to open the file (by this process - // or another process) will fail until the file is closed. - None = 0, - // - // Summary: - // Allows subsequent opening of the file for reading. If this flag is not specified, - // any request to open the file for reading (by this process or another process) - // will fail until the file is closed. However, even if this flag is specified, - // additional permissions might still be needed to access the file. - Read = 1, - // - // Summary: - // Allows subsequent opening of the file for writing. If this flag is not specified, - // any request to open the file for writing (by this process or another process) - // will fail until the file is closed. However, even if this flag is specified, - // additional permissions might still be needed to access the file. - Write = 2, - // - // Summary: - // Allows subsequent opening of the file for reading or writing. If this flag is - // not specified, any request to open the file for reading or writing (by this process - // or another process) will fail until the file is closed. However, even if this - // flag is specified, additional permissions might still be needed to access the - // file. - ReadWrite = 3 - } - - // - // Summary: - // Represents advanced options for creating a System.IO.FileStream object. - [Flags] - public enum FileOpenOptions - { - // - // Summary: - // Indicates that the system should write through any intermediate cache and go - // directly to disk. - WriteThrough = int.MinValue, - // - // Summary: - // Indicates that no additional options should be used when creating a System.IO.FileStream - // object. - None = 0, - // - // Summary: - // Indicates that a file is encrypted and can be decrypted only by using the same - // user account used for encryption. - Encrypted = 16384, - // - // Summary: - // Indicates that a file is automatically deleted when it is no longer in use. - DeleteOnClose = 67108864, - // - // Summary: - // Indicates that the file is to be accessed sequentially from beginning to end. - // The system can use this as a hint to optimize file caching. If an application - // moves the file pointer for random access, optimum caching may not occur; however, - // correct operation is still guaranteed. - SequentialScan = 134217728, - // - // Summary: - // Indicates that the file is accessed randomly. The system can use this as a hint - // to optimize file caching. - RandomAccess = 268435456, - // - // Summary: - // Indicates that a file can be used for asynchronous reading and writing. - Asynchronous = 1073741824 - } } diff --git a/MediaBrowser.Model/IO/IODefaults.cs b/MediaBrowser.Model/IO/IODefaults.cs new file mode 100644 index 000000000..f392dbcce --- /dev/null +++ b/MediaBrowser.Model/IO/IODefaults.cs @@ -0,0 +1,18 @@ +namespace MediaBrowser.Model.IO +{ + /// + /// Class IODefaults. + /// + public static class IODefaults + { + /// + /// The default copy to buffer size. + /// + public const int CopyToBufferSize = 81920; + + /// + /// The default file stream buffer size. + /// + public const int FileStreamBufferSize = 4096; + } +} diff --git a/MediaBrowser.Model/IO/StreamDefaults.cs b/MediaBrowser.Model/IO/StreamDefaults.cs deleted file mode 100644 index 4b55ce1f3..000000000 --- a/MediaBrowser.Model/IO/StreamDefaults.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MediaBrowser.Model.IO -{ - /// - /// Class StreamDefaults. - /// - public static class StreamDefaults - { - /// - /// The default copy to buffer size. - /// - public const int DefaultCopyToBufferSize = 81920; - - /// - /// The default file stream buffer size. - /// - public const int DefaultFileStreamBufferSize = 4096; - } -} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index ab906809f..3ab621ba4 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -244,9 +244,9 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); - using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous)) + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { - await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); + await source.CopyToAsync(fs, IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false); } if (_config.Configuration.SaveMetadataHidden) diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index e9179815e..d83c0cc86 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -25,14 +25,12 @@ namespace MediaBrowser.Providers.Manager { private readonly ILogger _logger; private readonly IProviderManager _providerManager; - private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public ItemImageProvider(ILogger logger, IProviderManager providerManager, IServerConfigurationManager config, IFileSystem fileSystem) + public ItemImageProvider(ILogger logger, IProviderManager providerManager, IFileSystem fileSystem) { _logger = logger; _providerManager = providerManager; - _config = config; _fileSystem = fileSystem; } @@ -141,7 +139,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = _fileSystem.GetFileStream(response.Path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true); + var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index c3401f12b..e6cb923e3 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Providers.Manager } } - var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); + var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, FileSystem); var localImagesFailed = false; var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item, refreshOptions).ToList(); diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 631d063a5..e7b349f67 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -182,7 +182,7 @@ namespace MediaBrowser.Providers.Manager throw new ArgumentNullException(nameof(source)); } - var fileStream = _fileSystem.GetFileStream(source, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, true); + var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, true); return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); } diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs index e61d8792c..939c74c01 100644 --- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -164,11 +165,10 @@ namespace MediaBrowser.Providers.Music { Url = url, CancellationToken = cancellationToken - }, - "GET").ConfigureAwait(false)) + HttpMethod.Get).ConfigureAwait(false)) using (var response = httpResponse.Content) - using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) + using (var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { await response.CopyToAsync(xmlFileStream).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs index 7e5893d49..e073a295b 100644 --- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; @@ -152,12 +153,12 @@ namespace MediaBrowser.Providers.Music CancellationToken = cancellationToken, BufferContent = true }, - "GET").ConfigureAwait(false)) + HttpMethod.Get).ConfigureAwait(false)) using (var response = httpResponse.Content) { Directory.CreateDirectory(Path.GetDirectoryName(path)); - using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) + using (var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { await response.CopyToAsync(xmlFileStream).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs index f8b876580..fbf6ae135 100644 --- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs @@ -209,7 +209,7 @@ namespace MediaBrowser.Providers.Omdb string resultString; - using (var stream = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new StreamReader(stream, new UTF8Encoding(false))) { @@ -228,7 +228,7 @@ namespace MediaBrowser.Providers.Omdb string resultString; - using (var stream = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new StreamReader(stream, new UTF8Encoding(false))) { diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index ef412db5a..cbef27a09 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.Studios private RemoteImageInfo GetImage(BaseItem item, string filename, ImageType type, string remoteFilename) { - var list = GetAvailableImages(filename, _fileSystem); + var list = GetAvailableImages(filename); var match = FindMatch(item, list); @@ -179,9 +179,9 @@ namespace MediaBrowser.Providers.Studios .Replace("/", string.Empty); } - public IEnumerable GetAvailableImages(string file, IFileSystem fileSystem) + public IEnumerable GetAvailableImages(string file) { - using (var fileStream = fileSystem.GetFileStream(file, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read)) + using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new StreamReader(fileStream)) { diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 37d1230e2..583c7e8ea 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -19,7 +19,7 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using Microsoft.Extensions.Logging; -using static MediaBrowser.Model.IO.StreamDefaults; +using static MediaBrowser.Model.IO.IODefaults; namespace MediaBrowser.Providers.Subtitles { @@ -210,7 +210,7 @@ namespace MediaBrowser.Providers.Subtitles { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize, true)) + using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, FileStreamBufferSize, true)) { await stream.CopyToAsync(fs).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs index 130403e4d..50af9913a 100644 --- a/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs @@ -234,7 +234,7 @@ namespace MediaBrowser.Providers.Tmdb.People { Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); - using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) + using (var fs = new FileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true)) { await json.CopyToAsync(fs).ConfigureAwait(false); } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index fadf32b28..96ebdf4a8 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -425,7 +425,7 @@ namespace MediaBrowser.WebDashboard.Api private async Task DumpFile(PackageCreator packageCreator, string resourceVirtualPath, string destinationFilePath, string mode, string appVersion) { using (var stream = await packageCreator.GetResource(resourceVirtualPath, mode, null, appVersion).ConfigureAwait(false)) - using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + using (var fs = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { await stream.CopyToAsync(fs); } -- cgit v1.2.3 From 2186df8ac445b74dce86bdf2fe7ba5500da0c492 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 28 Jan 2020 22:42:07 +0100 Subject: Update deps --- Emby.Naming/Emby.Naming.csproj | 5 +---- Emby.Notifications/CoreNotificationTypes.cs | 1 - Emby.Photos/Emby.Photos.csproj | 5 ----- .../Emby.Server.Implementations.csproj | 8 ++++---- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 6 +++--- Jellyfin.Server/Jellyfin.Server.csproj | 11 ++++------- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- .../MediaBrowser.Controller.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Common.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- .../Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 19 +++++++++---------- 17 files changed, 37 insertions(+), 50 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 900b9694c..c6b08d372 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -4,10 +4,7 @@ netstandard2.1 false true - - - - true + true diff --git a/Emby.Notifications/CoreNotificationTypes.cs b/Emby.Notifications/CoreNotificationTypes.cs index 0f9fc08d9..d11e01e33 100644 --- a/Emby.Notifications/CoreNotificationTypes.cs +++ b/Emby.Notifications/CoreNotificationTypes.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Controller; using MediaBrowser.Controller.Notifications; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 29ed3c5f7..ed6918dba 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -1,9 +1,4 @@ - - - true - - diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 77333a03d..f8560ca85 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -29,11 +29,11 @@ - - - + + + - + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 38cdb0998..4241d9b95 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index febb1adab..f9ce0bbe1 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -12,8 +12,8 @@ - - + + @@ -25,7 +25,7 @@ - + diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 62bf5b0fb..bc18f11fd 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -6,9 +6,6 @@ netcoreapp3.1 false true - - - true enable @@ -38,16 +35,16 @@ - - - + + + - + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 567fcdda1..3da864404 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -12,7 +12,7 @@ - + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 60c76ef7d..f85b0949a 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -8,7 +8,7 @@ - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 783457bda..a312dcd70 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 53cd08fbd..4029084e7 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -15,9 +15,9 @@ - + - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 8d373be28..5593c5036 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -11,11 +11,11 @@ - - + + - + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 1f83489bd..0e8ef135e 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -9,11 +9,11 @@ - + - + diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index bc0114d1e..da5e6576d 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 5d9b32086..c01edd9fe 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 79d2f2144..f246d459b 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index f62d3dcbc..c554bc937 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -1,19 +1,18 @@  - netcoreapp3.1 - false - Jellyfin.Server.Implementations.Tests + netcoreapp3.1 + false + Jellyfin.Server.Implementations.Tests - - - - - - - + + + + + + -- cgit v1.2.3 From 87d2479b784139584e386349c59f81688930571a Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 31 Jan 2020 22:23:46 +0100 Subject: Fix warnings --- Emby.Dlna/Didl/DidlBuilder.cs | 1 - Emby.Dlna/PlayTo/PlayToController.cs | 1 - Emby.Dlna/PlayTo/PlaylistItemFactory.cs | 1 - Emby.Dlna/Server/DescriptionXmlBuilder.cs | 1 - Emby.Dlna/Service/BaseControlHandler.cs | 1 - .../Activity/ActivityManager.cs | 1 - Emby.Server.Implementations/ApplicationHost.cs | 25 +---------------- .../Channels/ChannelPostScanTask.cs | 32 ++++++++++------------ .../Channels/RefreshChannelsScheduledTask.cs | 24 +++++++++++----- .../Collections/CollectionImageProvider.cs | 1 - .../Configuration/ServerConfigurationManager.cs | 1 - .../EntryPoints/LibraryChangedNotifier.cs | 1 - .../EntryPoints/UdpServerEntryPoint.cs | 1 - .../LiveTv/EmbyTV/EncodedRecorder.cs | 1 - .../LiveTv/TunerHosts/M3uParser.cs | 1 - Emby.Server.Implementations/Net/SocketFactory.cs | 1 - .../Net/WebSocketConnectEventArgs.cs | 2 -- .../Playlists/PlaylistImageProvider.cs | 1 - .../SocketSharp/HttpPostedFile.cs | 6 ---- .../SocketSharp/WebSocketSharpListener.cs | 2 -- .../WebSockets/WebSocketManager.cs | 2 -- Jellyfin.Drawing.Skia/SkiaCodecException.cs | 1 - Jellyfin.Server/Program.cs | 25 ++++++++--------- Jellyfin.Server/Startup.cs | 1 - MediaBrowser.Api/ApiEntryPoint.cs | 1 - MediaBrowser.Api/EnvironmentService.cs | 1 - MediaBrowser.Api/ItemUpdateService.cs | 1 - MediaBrowser.Api/Library/LibraryService.cs | 4 --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 1 - MediaBrowser.Api/Playback/MediaInfoService.cs | 2 -- MediaBrowser.Api/Playback/StreamRequest.cs | 1 - .../System/ActivityLogWebSocketListener.cs | 1 - MediaBrowser.Api/UserLibrary/GenresService.cs | 1 - MediaBrowser.Api/UserLibrary/PersonsService.cs | 1 - MediaBrowser.Api/UserLibrary/YearsService.cs | 1 - MediaBrowser.Controller/Entities/Video.cs | 1 - .../MediaEncoding/EncodingJobOptions.cs | 1 - MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 1 - MediaBrowser.Controller/Net/IHttpResultFactory.cs | 2 -- .../Net/IWebSocketConnection.cs | 1 - MediaBrowser.Controller/Net/StaticResultOptions.cs | 2 -- .../Persistence/MediaAttachmentQuery.cs | 1 - .../Parsers/BaseItemXmlParser.cs | 1 - MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs | 1 - MediaBrowser.Model/IO/IFileSystem.cs | 1 - MediaBrowser.Model/Net/ISocketFactory.cs | 1 - MediaBrowser.Model/Tasks/IScheduledTask.cs | 4 +-- .../Manager/ItemImageProvider.cs | 1 - .../MediaInfo/SubtitleResolver.cs | 1 - MediaBrowser.Providers/TV/DummySeasonProvider.cs | 1 - .../TV/TheTVDB/TvdbSeriesProvider.cs | 1 - .../Tmdb/BoxSets/TmdbBoxSetImageProvider.cs | 1 - .../Tmdb/Models/Search/ExternalIdLookupResult.cs | 1 - .../Tmdb/Movies/GenericTmdbMovieInfo.cs | 2 -- .../Tmdb/Movies/TmdbImageProvider.cs | 1 - .../Tmdb/Movies/TmdbMovieProvider.cs | 1 - .../Tmdb/Music/TmdbMusicVideoProvider.cs | 1 - .../Tmdb/People/TmdbPersonImageProvider.cs | 1 - .../Tmdb/TV/TmdbEpisodeImageProvider.cs | 1 - .../Tmdb/TV/TmdbEpisodeProviderBase.cs | 1 - .../Tmdb/TV/TmdbSeasonImageProvider.cs | 2 -- .../Tmdb/TV/TmdbSeasonProvider.cs | 1 - .../Tmdb/TV/TmdbSeriesImageProvider.cs | 1 - .../Tmdb/TV/TmdbSeriesProvider.cs | 1 - .../Tmdb/Trailers/TmdbTrailerProvider.cs | 1 - MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 -- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 1 - RSSDP/DeviceEventArgs.cs | 2 -- RSSDP/DeviceUnavailableEventArgs.cs | 3 -- RSSDP/DiscoveredSsdpDevice.cs | 4 --- RSSDP/DisposableManagedObjectBase.cs | 1 - RSSDP/HttpParserBase.cs | 2 -- RSSDP/HttpRequestParser.cs | 4 --- RSSDP/HttpResponseParser.cs | 3 -- RSSDP/IEnumerableExtensions.cs | 1 - RSSDP/ISsdpDevicePublisher.cs | 1 - RSSDP/SsdpConstants.cs | 5 ---- RSSDP/SsdpEmbeddedDevice.cs | 4 --- tests/Jellyfin.Naming.Tests/Video/StubTests.cs | 4 +-- .../IO/ManagedFileSystemTests.cs | 1 - 84 files changed, 46 insertions(+), 182 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 85ef9d482..a5e46df78 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -18,7 +18,6 @@ using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index c58f16438..d378c2c30 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Emby.Dlna.Didl; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; diff --git a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs index 446d8e1e6..3b1cbab62 100644 --- a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs +++ b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs @@ -1,4 +1,3 @@ -using System.Globalization; using System.IO; using System.Linq; using MediaBrowser.Controller.Entities; diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 03d8f80ab..1b53e9242 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using Emby.Dlna.Common; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Extensions; namespace Emby.Dlna.Server { diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 49129f6ff..a8da7aecd 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs index b03c4d182..6712c4782 100644 --- a/Emby.Server.Implementations/Activity/ActivityManager.cs +++ b/Emby.Server.Implementations/Activity/ActivityManager.cs @@ -2,7 +2,6 @@ #pragma warning disable SA1600 using System; -using System.Linq; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 226a8f302..e2df8877a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1007,7 +1007,7 @@ namespace Emby.Server.Implementations { string dir = Path.Combine(ApplicationPaths.PluginsPath, args.Argument.name); var types = Directory.EnumerateFiles(dir, "*.dll", SearchOption.AllDirectories) - .Select(x => Assembly.LoadFrom(x)) + .Select(Assembly.LoadFrom) .SelectMany(x => x.ExportedTypes) .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && !x.IsGenericType) .ToArray(); @@ -1707,29 +1707,6 @@ namespace Emby.Server.Implementations _plugins = list.ToArray(); } - /// - /// This returns localhost in the case of no external dns, and the hostname if the - /// dns is prefixed with a valid Uri prefix. - /// - /// The external dns prefix to get the hostname of. - /// The hostname in . - private static string GetHostnameFromExternalDns(string externalDns) - { - if (string.IsNullOrEmpty(externalDns)) - { - return "localhost"; - } - - try - { - return new Uri(externalDns).Host; - } - catch - { - return externalDns; - } - } - public virtual void LaunchUrl(string url) { if (!CanLaunchWebBrowser) diff --git a/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs index 36e0e5e26..6cbd04fea 100644 --- a/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs +++ b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs @@ -35,14 +35,6 @@ namespace Emby.Server.Implementations.Channels return Task.CompletedTask; } - public static string GetUserDistinctValue(User user) - { - var channels = user.Policy.EnabledChannels - .OrderBy(i => i); - - return string.Join("|", channels); - } - private void CleanDatabase(CancellationToken cancellationToken) { var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds(); @@ -75,19 +67,23 @@ namespace Emby.Server.Implementations.Channels { cancellationToken.ThrowIfCancellationRequested(); - _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = false - - }, false); + _libraryManager.DeleteItem( + item, + new DeleteOptions + { + DeleteFileLocation = false + }, + false); } // Finally, delete the channel itself - _libraryManager.DeleteItem(channel, new DeleteOptions - { - DeleteFileLocation = false - - }, false); + _libraryManager.DeleteItem( + channel, + new DeleteOptions + { + DeleteFileLocation = false + }, + false); } } } diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index 039e2c138..03e6abcfb 100644 --- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -28,18 +28,28 @@ namespace Emby.Server.Implementations.Channels _libraryManager = libraryManager; } + /// public string Name => "Refresh Channels"; + /// public string Description => "Refreshes internet channel information."; + /// public string Category => "Internet Channels"; + /// public bool IsHidden => ((ChannelManager)_channelManager).Channels.Length == 0; + /// public bool IsEnabled => true; + /// public bool IsLogged => true; + /// + public string Key => "RefreshInternetChannels"; + + /// public async Task Execute(CancellationToken cancellationToken, IProgress progress) { var manager = (ChannelManager)_channelManager; @@ -50,18 +60,18 @@ namespace Emby.Server.Implementations.Channels .ConfigureAwait(false); } - /// - /// Creates the triggers that define when the task will run - /// + /// public IEnumerable GetDefaultTriggers() { - return new[] { + return new[] + { // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} + new TaskTriggerInfo + { + Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks + } }; } - - public string Key => "RefreshInternetChannels"; } } diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs index 8006b8694..8b1407984 100644 --- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs @@ -1,7 +1,6 @@ #pragma warning disable CS1591 #pragma warning disable SA1600 -using System; using System.Collections.Generic; using System.Linq; using Emby.Server.Implementations.Images; diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index 3d8d15d19..30b654886 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using Emby.Server.Implementations.AppBase; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index f85d52dbc..06458baed 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -16,7 +16,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Extensions; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index a83817cb9..529f83560 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Udp; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index ee5086a65..6e4ac2fec 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 3d2267e75..51f61bac7 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -10,7 +10,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Extensions; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 4e04cde78..e42ff8496 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Net; using System.Net.Sockets; using MediaBrowser.Model.Net; diff --git a/Emby.Server.Implementations/Net/WebSocketConnectEventArgs.cs b/Emby.Server.Implementations/Net/WebSocketConnectEventArgs.cs index e3047d392..6880766f9 100644 --- a/Emby.Server.Implementations/Net/WebSocketConnectEventArgs.cs +++ b/Emby.Server.Implementations/Net/WebSocketConnectEventArgs.cs @@ -1,6 +1,4 @@ using System; -using System.Net.WebSockets; -using MediaBrowser.Model.Services; using Microsoft.AspNetCore.Http; namespace Emby.Server.Implementations.Net diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs index 2dfe59088..bb56d9771 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using Emby.Server.Implementations.Images; diff --git a/Emby.Server.Implementations/SocketSharp/HttpPostedFile.cs b/Emby.Server.Implementations/SocketSharp/HttpPostedFile.cs index 95b7912fb..7479d8104 100644 --- a/Emby.Server.Implementations/SocketSharp/HttpPostedFile.cs +++ b/Emby.Server.Implementations/SocketSharp/HttpPostedFile.cs @@ -1,11 +1,5 @@ using System; -using System.Collections.Generic; -using System.Globalization; using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Model.Services; public sealed class HttpPostedFile : IDisposable { diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs index ba5ba1904..2e12a19fd 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpListener.cs @@ -1,13 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.Net; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Services; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; diff --git a/Emby.Server.Implementations/WebSockets/WebSocketManager.cs b/Emby.Server.Implementations/WebSockets/WebSocketManager.cs index efd97e4ff..31a7468fb 100644 --- a/Emby.Server.Implementations/WebSockets/WebSocketManager.cs +++ b/Emby.Server.Implementations/WebSockets/WebSocketManager.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Drawing.Skia/SkiaCodecException.cs b/Jellyfin.Drawing.Skia/SkiaCodecException.cs index 8158b846d..1d2db5515 100644 --- a/Jellyfin.Drawing.Skia/SkiaCodecException.cs +++ b/Jellyfin.Drawing.Skia/SkiaCodecException.cs @@ -1,4 +1,3 @@ -using System.Diagnostics.CodeAnalysis; using System.Globalization; using SkiaSharp; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 2638d5bfa..1b4280d82 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; -using System.Net.Security; using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -238,7 +237,7 @@ namespace Jellyfin.Server { foreach (var address in addresses) { - _logger.LogInformation("Kestrel listening on {ipaddr}", address); + _logger.LogInformation("Kestrel listening on {IpAddress}", address); options.Listen(address, appHost.HttpPort); if (appHost.EnableHttps && appHost.Certificate != null) @@ -443,20 +442,18 @@ namespace Jellyfin.Server if (!File.Exists(configPath)) { // For some reason the csproj name is used instead of the assembly name - using (Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)) + await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath); + if (resource == null) { - if (resource == null) - { - throw new InvalidOperationException( - string.Format( - CultureInfo.InvariantCulture, - "Invalid resource path: '{0}'", - ResourcePath)); - } - - using Stream dst = File.Open(configPath, FileMode.CreateNew); - await resource.CopyToAsync(dst).ConfigureAwait(false); + throw new InvalidOperationException( + string.Format( + CultureInfo.InvariantCulture, + "Invalid resource path: '{0}'", + ResourcePath)); } + + await using Stream dst = File.Open(configPath, FileMode.CreateNew); + await resource.CopyToAsync(dst).ConfigureAwait(false); } return new ConfigurationBuilder() diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 3ee5fb8b5..4d7d56e9d 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 1a3657c92..7d3546eb7 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index c6dbfb938..322b9805b 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -6,7 +6,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 1847f7fde..c81e89ca3 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index b1ea3e262..3d1e4a363 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -16,17 +16,13 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.TV; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index e85ed2050..262f51786 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -16,7 +16,6 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 15880a9a1..0eb184d14 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -5,7 +5,6 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Globalization; using System.Text.Json; using System.Linq; @@ -23,7 +22,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 7626cc378..9ba8eda91 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -1,4 +1,3 @@ -using System; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs index a036619b8..4b6a22b7d 100644 --- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs +++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 13bb88ca8..1fa272a5f 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -5,7 +5,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 853eada25..3204e5219 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index 07b9aff1b..d023ee90a 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index af4d227bc..c3ea7f347 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index d64feb2f7..addc88174 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index 171aedb0e..11d206df7 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; -using MediaBrowser.Model.Extensions; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.MediaEncoding diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index fb00ee008..25404fa78 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; - -using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; namespace MediaBrowser.Controller.Net diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs index 566897b31..31eb7ccb7 100644 --- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs @@ -3,7 +3,6 @@ using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Net; -using MediaBrowser.Model.Services; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs index 726732660..071beaed1 100644 --- a/MediaBrowser.Controller/Net/StaticResultOptions.cs +++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using MediaBrowser.Model.IO; - namespace MediaBrowser.Controller.Net { public class StaticResultOptions diff --git a/MediaBrowser.Controller/Persistence/MediaAttachmentQuery.cs b/MediaBrowser.Controller/Persistence/MediaAttachmentQuery.cs index 91ab34aab..e3b2d4665 100644 --- a/MediaBrowser.Controller/Persistence/MediaAttachmentQuery.cs +++ b/MediaBrowser.Controller/Persistence/MediaAttachmentQuery.cs @@ -1,5 +1,4 @@ using System; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Persistence { diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 59c8f4da5..d4b98182f 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -9,7 +9,6 @@ using System.Xml; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; namespace MediaBrowser.LocalMetadata.Parsers diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 46c531797..ba1d850e3 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 605504418..293cf5ea5 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 0606dbdb2..c98dd1502 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Threading; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 0d696b906..b94d45165 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles diff --git a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs index 4f15bac49..7d3e18578 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; using System.Text.RegularExpressions; diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index 48e5eea6f..6a874d047 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; namespace MediaBrowser.Model.IO { diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index dc69b1fb2..a7965463a 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -1,4 +1,3 @@ -using System.IO; using System.Net; namespace MediaBrowser.Model.Net diff --git a/MediaBrowser.Model/Tasks/IScheduledTask.cs b/MediaBrowser.Model/Tasks/IScheduledTask.cs index a615ebb07..71f6e15f8 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTask.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTask.cs @@ -39,9 +39,9 @@ namespace MediaBrowser.Model.Tasks Task Execute(CancellationToken cancellationToken, IProgress progress); /// - /// Gets the default triggers. + /// Gets the default triggers that define when the task will run. /// - /// IEnumerable{BaseTaskTrigger}. + /// The default triggers that define when the task will run. IEnumerable GetDefaultTriggers(); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index d83c0cc86..01c950260 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index 8195591e1..7ebbb9e23 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -5,7 +5,6 @@ using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index 4a6676cb9..6a1e6df8f 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index 72ceadaf1..9e791bd9d 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; diff --git a/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs index 5db0edac2..0bdf2bce1 100644 --- a/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs @@ -10,7 +10,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.Collections; using MediaBrowser.Providers.Tmdb.Models.General; using MediaBrowser.Providers.Tmdb.Movies; diff --git a/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs b/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs index 6d9fe7081..d19f4e8cb 100644 --- a/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs +++ b/MediaBrowser.Providers/Tmdb/Models/Search/ExternalIdLookupResult.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using MediaBrowser.Providers.Movies; namespace MediaBrowser.Providers.Tmdb.Models.Search { diff --git a/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs index b7b447b68..ad42b564c 100644 --- a/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -11,10 +11,8 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.Movies; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs index cdb96e6ac..039a49728 100644 --- a/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbImageProvider.cs @@ -13,7 +13,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.General; using MediaBrowser.Providers.Tmdb.Models.Movies; diff --git a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs index a1bea5847..861847f71 100644 --- a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs @@ -19,7 +19,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.Movies; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs b/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs index f3f8a92cf..81909fa38 100644 --- a/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Music/TmdbMusicVideoProvider.cs @@ -6,7 +6,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Providers; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Movies; namespace MediaBrowser.Providers.Tmdb.Music diff --git a/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs index 44ccbf453..e205d796a 100644 --- a/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonImageProvider.cs @@ -10,7 +10,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.General; using MediaBrowser.Providers.Tmdb.Models.People; using MediaBrowser.Providers.Tmdb.Movies; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs index 51e7891a1..558c8149e 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs @@ -13,7 +13,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.General; using MediaBrowser.Providers.Tmdb.Movies; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs index 2003261c9..e87fe9332 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.TV; using MediaBrowser.Providers.Tmdb.Movies; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs index 24cc8c73b..698a43604 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonImageProvider.cs @@ -10,8 +10,6 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Tmdb.Models.General; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs index fc0cde8b3..5ad331971 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs @@ -14,7 +14,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.TV; using MediaBrowser.Providers.Tmdb.Movies; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs index 882ec7574..0460fe994 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesImageProvider.cs @@ -12,7 +12,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.General; using MediaBrowser.Providers.Tmdb.Models.TV; using MediaBrowser.Providers.Tmdb.Movies; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs index 304f34c25..7dcb272d6 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs @@ -17,7 +17,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Models.Search; using MediaBrowser.Providers.Tmdb.Models.TV; using MediaBrowser.Providers.Tmdb.Movies; diff --git a/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs b/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs index b0dec0245..b15de0125 100644 --- a/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Trailers/TmdbTrailerProvider.cs @@ -5,7 +5,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Providers; -using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.Tmdb.Movies; namespace MediaBrowser.Providers.Tmdb.Trailers diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 96ebdf4a8..a8768459a 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -9,11 +9,9 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index b8d0e6560..62d7a8cf4 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.XbmcMetadata.Configuration; using MediaBrowser.XbmcMetadata.Savers; using Microsoft.Extensions.Logging; diff --git a/RSSDP/DeviceEventArgs.cs b/RSSDP/DeviceEventArgs.cs index 3925ba248..05eb4a256 100644 --- a/RSSDP/DeviceEventArgs.cs +++ b/RSSDP/DeviceEventArgs.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Rssdp { diff --git a/RSSDP/DeviceUnavailableEventArgs.cs b/RSSDP/DeviceUnavailableEventArgs.cs index d90ddfb60..ef04904bd 100644 --- a/RSSDP/DeviceUnavailableEventArgs.cs +++ b/RSSDP/DeviceUnavailableEventArgs.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; namespace Rssdp { diff --git a/RSSDP/DiscoveredSsdpDevice.cs b/RSSDP/DiscoveredSsdpDevice.cs index f42e7c674..1244ce523 100644 --- a/RSSDP/DiscoveredSsdpDevice.cs +++ b/RSSDP/DiscoveredSsdpDevice.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; using System.Net.Http.Headers; namespace Rssdp diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 0f656fb46..bb36229c4 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using System.Threading.Tasks; namespace Rssdp.Infrastructure { diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 76d816e7b..773a06cdb 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Text; -using System.IO; namespace Rssdp.Infrastructure { diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index d4505b8ad..279ef883c 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Net; using System.Net.Http; -using System.Text; -using System.Threading.Tasks; namespace Rssdp.Infrastructure { diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index a77c898ff..b96eaf625 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; -using System.Threading.Tasks; namespace Rssdp.Infrastructure { diff --git a/RSSDP/IEnumerableExtensions.cs b/RSSDP/IEnumerableExtensions.cs index c96542dca..371454893 100644 --- a/RSSDP/IEnumerableExtensions.cs +++ b/RSSDP/IEnumerableExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace Rssdp.Infrastructure { diff --git a/RSSDP/ISsdpDevicePublisher.cs b/RSSDP/ISsdpDevicePublisher.cs index 7e914c109..96c15443d 100644 --- a/RSSDP/ISsdpDevicePublisher.cs +++ b/RSSDP/ISsdpDevicePublisher.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; namespace Rssdp.Infrastructure diff --git a/RSSDP/SsdpConstants.cs b/RSSDP/SsdpConstants.cs index 8372d1cb3..28a014fce 100644 --- a/RSSDP/SsdpConstants.cs +++ b/RSSDP/SsdpConstants.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; - namespace Rssdp.Infrastructure { /// diff --git a/RSSDP/SsdpEmbeddedDevice.cs b/RSSDP/SsdpEmbeddedDevice.cs index 6f05518a9..4810703d7 100644 --- a/RSSDP/SsdpEmbeddedDevice.cs +++ b/RSSDP/SsdpEmbeddedDevice.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace Rssdp { /// diff --git a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs index 96fa8c5a5..7b3a01bc0 100644 --- a/tests/Jellyfin.Naming.Tests/Video/StubTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/StubTests.cs @@ -1,6 +1,4 @@ -using System; -using System.Globalization; -using Emby.Naming.Common; +using Emby.Naming.Common; using Emby.Naming.Video; using Xunit; diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index e324002f0..671c59b2e 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -1,4 +1,3 @@ -using System; using AutoFixture; using AutoFixture.AutoMoq; using Emby.Server.Implementations.IO; -- cgit v1.2.3 From d7f199bb1c43b56cafe8876f620d7757da17d8cd Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Mon, 17 Feb 2020 14:56:31 +0100 Subject: #2407: Prefer MP4-Metadata for episodes --- .../Library/LibraryManager.cs | 25 ++++++++++++++++++++++ .../Probing/ProbeResultNormalizer.cs | 3 +++ MediaBrowser.Model/Configuration/LibraryOptions.cs | 1 + MediaBrowser.Model/MediaInfo/MediaInfo.cs | 1 + 4 files changed, 30 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d983c1dc6..c390d2b82 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -29,11 +29,13 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; @@ -2387,6 +2389,7 @@ namespace Emby.Server.Implementations.Library public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh) { + var libraryOptions = GetLibraryOptions(episode); var series = episode.Series; bool? isAbsoluteNaming = series == null ? false : string.Equals(series.DisplayOrder, "absolute", StringComparison.OrdinalIgnoreCase); if (!isAbsoluteNaming.Value) @@ -2408,6 +2411,28 @@ namespace Emby.Server.Implementations.Library episodeInfo = new Naming.TV.EpisodeInfo(); } + if (libraryOptions.EnableEmbeddedEpisodeInfos && episodeInfo.Container.ToLowerInvariant() == "mp4") { + // Read from metadata + IMediaEncoder mediaEncoder = _appHost.Resolve(); + var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest + { + MediaSource = episode.GetMediaSources(false).First(), + MediaType = DlnaProfileType.Video, + ExtractChapters = false + + }, CancellationToken.None); + task.Wait(); + if (task.Result.ParentIndexNumber > 0) { + episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; + } + if (task.Result.IndexNumber > 0) { + episodeInfo.EpisodeNumber = task.Result.IndexNumber; + } + if (!string.IsNullOrEmpty(task.Result.ShowName)) { + episodeInfo.SeriesName = task.Result.ShowName; + } + } + var changed = false; if (episodeInfo.IsByDate) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index bd89c6cae..f8047af42 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -112,6 +112,9 @@ namespace MediaBrowser.MediaEncoding.Probing info.Name = title; } + info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); + info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); + info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); // Several different forms of retaildate diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 3c99f9bb5..9d5d2b869 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.Model.Configuration public bool ImportMissingEpisodes { get; set; } public bool EnableAutomaticSeriesGrouping { get; set; } public bool EnableEmbeddedTitles { get; set; } + public bool EnableEmbeddedEpisodeInfos { get; set; } public int AutomaticRefreshIntervalDays { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index 6ad766d39..237a2b36c 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -36,6 +36,7 @@ namespace MediaBrowser.Model.MediaInfo /// The studios. public string[] Studios { get; set; } public string[] Genres { get; set; } + public string ShowName { get; set; } public int? IndexNumber { get; set; } public int? ParentIndexNumber { get; set; } public int? ProductionYear { get; set; } -- cgit v1.2.3 From a07ee6536567a048b85d4bdc7d17e1c46f292572 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 23 Feb 2020 10:53:51 +0100 Subject: Minor improvements --- Emby.Server.Implementations/ApplicationHost.cs | 9 +- .../Data/SqliteItemRepository.cs | 11 +- .../MediaEncoder/EncodingManager.cs | 40 +++---- .../Chapters/IChapterManager.cs | 5 +- MediaBrowser.Controller/Entities/Folder.cs | 6 +- MediaBrowser.Controller/Entities/IItemByName.cs | 2 +- .../MediaEncoding/IEncodingManager.cs | 5 +- .../Persistence/IItemRepository.cs | 2 +- .../Providers/DirectoryService.cs | 8 +- .../Providers/IDirectoryService.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 7 +- MediaBrowser.Providers/Chapters/ChapterManager.cs | 23 ++-- MediaBrowser.Providers/Manager/ProviderManager.cs | 80 ++++++------- .../MediaBrowser.Providers.csproj | 13 +++ .../MediaInfo/FFProbeProvider.cs | 14 ++- .../MediaInfo/FFProbeVideoInfo.cs | 128 ++++++++++++--------- .../Music/MusicBrainzAlbumProvider.cs | 3 +- .../Tmdb/Movies/TmdbMovieProvider.cs | 22 ++-- 19 files changed, 214 insertions(+), 170 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index fd0112266..a8f457390 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -852,10 +852,15 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(new DeviceDiscovery(ServerConfigurationManager)); - ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); + ChapterManager = new ChapterManager(ItemRepository); serviceCollection.AddSingleton(ChapterManager); - EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); + EncodingManager = new MediaEncoder.EncodingManager( + LoggerFactory.CreateLogger(), + FileSystemManager, + MediaEncoder, + ChapterManager, + LibraryManager); serviceCollection.AddSingleton(EncodingManager); var activityLogRepo = GetActivityLogRepository(); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 44f38504a..b73609acb 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2006,7 +2006,7 @@ namespace Emby.Server.Implementations.Data /// /// Saves the chapters. /// - public void SaveChapters(Guid id, List chapters) + public void SaveChapters(Guid id, IReadOnlyList chapters) { CheckDisposed(); @@ -2035,22 +2035,24 @@ namespace Emby.Server.Implementations.Data } } - private void InsertChapters(byte[] idBlob, List chapters, IDatabaseConnection db) + private void InsertChapters(byte[] idBlob, IReadOnlyList chapters, IDatabaseConnection db) { var startIndex = 0; var limit = 100; var chapterIndex = 0; + const string StartInsertText = "insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values "; + var insertText = new StringBuilder(StartInsertText, 256); + while (startIndex < chapters.Count) { - var insertText = new StringBuilder("insert into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values "); - var endIndex = Math.Min(chapters.Count, startIndex + limit); for (var i = startIndex; i < endIndex; i++) { insertText.AppendFormat("(@ItemId, @ChapterIndex{0}, @StartPositionTicks{0}, @Name{0}, @ImagePath{0}, @ImageDateModified{0}),", i.ToString(CultureInfo.InvariantCulture)); } + insertText.Length -= 1; // Remove last , using (var statement = PrepareStatement(db, insertText.ToString())) @@ -2077,6 +2079,7 @@ namespace Emby.Server.Implementations.Data } startIndex += limit; + insertText.Length = StartInsertText.Length; } } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 840aca7a6..069c02b85 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -26,14 +26,20 @@ namespace Emby.Server.Implementations.MediaEncoder private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; + /// + /// The first chapter ticks. + /// + private static readonly long _firstChapterTicks = TimeSpan.FromSeconds(15).Ticks; + public EncodingManager( + ILogger logger, IFileSystem fileSystem, - ILoggerFactory loggerFactory, IMediaEncoder encoder, - IChapterManager chapterManager, ILibraryManager libraryManager) + IChapterManager chapterManager, + ILibraryManager libraryManager) { + _logger = logger; _fileSystem = fileSystem; - _logger = loggerFactory.CreateLogger(nameof(EncodingManager)); _encoder = encoder; _chapterManager = chapterManager; _libraryManager = libraryManager; @@ -97,12 +103,7 @@ namespace Emby.Server.Implementations.MediaEncoder return video.DefaultVideoStreamIndex.HasValue; } - /// - /// The first chapter ticks - /// - private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - - public async Task RefreshChapterImages(Video video, IDirectoryService directoryService, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) + public async Task RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) { if (!IsEligibleForChapterImageExtraction(video)) { @@ -135,7 +136,7 @@ namespace Emby.Server.Implementations.MediaEncoder try { // Add some time for the first chapter to make sure we don't end up with a black image - var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); + var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); var protocol = MediaProtocol.File; @@ -152,9 +153,9 @@ namespace Emby.Server.Implementations.MediaEncoder { _fileSystem.DeleteFile(tempFile); } - catch + catch (IOException ex) { - + _logger.LogError(ex, "Error deleting {Path}", tempFile); } chapter.ImagePath = path; @@ -184,7 +185,7 @@ namespace Emby.Server.Implementations.MediaEncoder if (saveChapters && changesMade) { - _chapterManager.SaveChapters(video.Id.ToString(), chapters); + _chapterManager.SaveChapters(video.Id, chapters); } DeleteDeadImages(currentImages, chapters); @@ -199,22 +200,21 @@ namespace Emby.Server.Implementations.MediaEncoder return Path.Combine(GetChapterImagesPath(video), filename); } - private static List GetSavedChapterImages(Video video, IDirectoryService directoryService) + private static IReadOnlyList GetSavedChapterImages(Video video, IDirectoryService directoryService) { var path = GetChapterImagesPath(video); if (!Directory.Exists(path)) { - return new List(); + return Array.Empty(); } try { - return directoryService.GetFilePaths(path) - .ToList(); + return directoryService.GetFilePaths(path); } catch (IOException) { - return new List(); + return Array.Empty(); } } @@ -227,7 +227,7 @@ namespace Emby.Server.Implementations.MediaEncoder foreach (var image in deadImages) { - _logger.LogDebug("Deleting dead chapter image {path}", image); + _logger.LogDebug("Deleting dead chapter image {Path}", image); try { @@ -235,7 +235,7 @@ namespace Emby.Server.Implementations.MediaEncoder } catch (IOException ex) { - _logger.LogError(ex, "Error deleting {path}.", image); + _logger.LogError(ex, "Error deleting {Path}.", image); } } } diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index d061898a1..f82e5b41a 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -1,16 +1,17 @@ +using System; using System.Collections.Generic; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Chapters { /// - /// Interface IChapterManager + /// Interface IChapterManager. /// public interface IChapterManager { /// /// Saves the chapters. /// - void SaveChapters(string itemId, List chapters); + void SaveChapters(Guid itemId, IReadOnlyList chapters); } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 07fbe6035..9296ae4fd 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1,3 +1,6 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System; using System.Collections.Generic; using System.Globalization; @@ -28,7 +31,6 @@ namespace MediaBrowser.Controller.Entities /// public class Folder : BaseItem { - public static IUserManager UserManager { get; set; } public static IUserViewManager UserViewManager { get; set; } /// @@ -620,7 +622,6 @@ namespace MediaBrowser.Controller.Entities { EnableImages = false } - }).TotalRecordCount; } @@ -1672,7 +1673,6 @@ namespace MediaBrowser.Controller.Entities { EnableImages = false } - }); double unplayedCount = unplayedQueryResult.TotalRecordCount; diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index 89b5dfee3..8ef5c8d96 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace MediaBrowser.Controller.Entities { /// - /// Marker interface + /// Marker interface. /// public interface IItemByName { diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs index e560999e8..7063d3939 100644 --- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs +++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs @@ -1,3 +1,6 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -12,6 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Refreshes the chapter images. /// - Task RefreshChapterImages(Video video, IDirectoryService directoryService, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); + Task RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 5a5b7f58f..eb5a8ded8 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Controller.Persistence /// /// Saves the chapters. /// - void SaveChapters(Guid id, List chapters); + void SaveChapters(Guid id, IReadOnlyList chapters); /// /// Gets the media streams. diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index 303b03a21..b4dcb5441 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -69,12 +69,10 @@ namespace MediaBrowser.Controller.Providers //return _fileSystem.GetFileInfo(path); } - public List GetFilePaths(string path) - { - return GetFilePaths(path, false); - } + public IReadOnlyList GetFilePaths(string path) + => GetFilePaths(path, false); - public List GetFilePaths(string path, bool clearCache) + public IReadOnlyList GetFilePaths(string path, bool clearCache) { if (clearCache || !_filePathCache.TryGetValue(path, out List result)) { diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs index 8059d2bd1..e3815facc 100644 --- a/MediaBrowser.Controller/Providers/IDirectoryService.cs +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Providers List GetFiles(string path); FileSystemMetadata GetFile(string path); - List GetFilePaths(string path); - List GetFilePaths(string path, bool clearCache); + IReadOnlyList GetFilePaths(string path); + IReadOnlyList GetFilePaths(string path, bool clearCache); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4123f0203..c3a5e21d9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -429,7 +429,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return new ProbeResultNormalizer(_logger, _fileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + return new ProbeResultNormalizer(_logger, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index f8047af42..ac626f9f8 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -9,7 +9,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; @@ -19,13 +18,11 @@ namespace MediaBrowser.MediaEncoding.Probing { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; - public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem, ILocalizationManager localization) + public ProbeResultNormalizer(ILogger logger, ILocalizationManager localization) { _logger = logger; - _fileSystem = fileSystem; _localization = localization; } @@ -40,7 +37,7 @@ namespace MediaBrowser.MediaEncoding.Probing FFProbeHelpers.NormalizeFFProbeResult(data); SetSize(data, info); - var internalStreams = data.Streams ?? new MediaStreamInfo[] { }; + var internalStreams = data.Streams ?? Array.Empty(); info.MediaStreams = internalStreams.Select(s => GetMediaStream(isAudio, s, data.Format)) .Where(i => i != null) diff --git a/MediaBrowser.Providers/Chapters/ChapterManager.cs b/MediaBrowser.Providers/Chapters/ChapterManager.cs index 45e87f137..242fc84f6 100644 --- a/MediaBrowser.Providers/Chapters/ChapterManager.cs +++ b/MediaBrowser.Providers/Chapters/ChapterManager.cs @@ -1,36 +1,27 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System; using System.Collections.Generic; using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; -using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Chapters { public class ChapterManager : IChapterManager { - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; private readonly IItemRepository _itemRepo; - public ChapterManager( - ILibraryManager libraryManager, - ILoggerFactory loggerFactory, - IServerConfigurationManager config, - IItemRepository itemRepo) + public ChapterManager(IItemRepository itemRepo) { - _libraryManager = libraryManager; - _logger = loggerFactory.CreateLogger(nameof(ChapterManager)); - _config = config; _itemRepo = itemRepo; } - public void SaveChapters(string itemId, List chapters) + /// + public void SaveChapters(Guid itemId, IReadOnlyList chapters) { - _itemRepo.SaveChapters(new Guid(itemId), chapters); + _itemRepo.SaveChapters(itemId, chapters); } } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index e7b349f67..ae1e0492b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -1,5 +1,10 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -897,7 +902,10 @@ namespace MediaBrowser.Providers.Manager return new ExternalUrl { Name = i.Name, - Url = string.Format(i.UrlFormatString, value) + Url = string.Format( + CultureInfo.InvariantCulture, + i.UrlFormatString, + value) }; }).Where(i => i != null).Concat(item.GetRelatedUrls()); @@ -911,11 +919,10 @@ namespace MediaBrowser.Providers.Manager Name = i.Name, Key = i.Key, UrlFormatString = i.UrlFormatString - }); } - private Dictionary _activeRefreshes = new Dictionary(); + private ConcurrentDictionary _activeRefreshes = new ConcurrentDictionary(); public Dictionary GetRefreshQueue() { @@ -927,65 +934,56 @@ namespace MediaBrowser.Providers.Manager { dict[item.Item1] = item.Item1; } + return dict; } } public void OnRefreshStart(BaseItem item) { - //_logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); - var id = item.Id; - - lock (_activeRefreshes) - { - _activeRefreshes[id] = 0; - } - + _logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); + _activeRefreshes[item.Id] = 0; RefreshStarted?.Invoke(this, new GenericEventArgs(item)); } public void OnRefreshComplete(BaseItem item) { - //_logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); - lock (_activeRefreshes) - { - _activeRefreshes.Remove(item.Id); - } + _logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); + + _activeRefreshes.Remove(item.Id, out _); RefreshCompleted?.Invoke(this, new GenericEventArgs(item)); } public double? GetRefreshProgress(Guid id) { - lock (_activeRefreshes) + if (_activeRefreshes.TryGetValue(id, out double value)) { - if (_activeRefreshes.TryGetValue(id, out double value)) - { - return value; - } - - return null; + return value; } + + return null; } public void OnRefreshProgress(BaseItem item, double progress) { - //_logger.LogInformation("OnRefreshProgress {0} {1}", item.Id.ToString("N", CultureInfo.InvariantCulture), progress); var id = item.Id; + _logger.LogInformation("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress); - lock (_activeRefreshes) + if (_activeRefreshes.ContainsKey(id)) { - if (_activeRefreshes.ContainsKey(id)) - { - _activeRefreshes[id] = progress; - - RefreshProgress?.Invoke(this, new GenericEventArgs>(new Tuple(item, progress))); - } - else - { - // TODO: Need to hunt down the conditions for this happening - //throw new Exception(string.Format("Refresh for item {0} {1} is not in progress", item.GetType().Name, item.Id.ToString("N", CultureInfo.InvariantCulture))); - } + _activeRefreshes[id] = progress; + RefreshProgress?.Invoke(this, new GenericEventArgs>(new Tuple(item, progress))); + } + else + { + // TODO: Need to hunt down the conditions for this happening + throw new Exception( + string.Format( + CultureInfo.InvariantCulture, + "Refresh for item {0} {1} is not in progress", + item.GetType().Name, + item.Id.ToString("N", CultureInfo.InvariantCulture))); } } @@ -1040,10 +1038,9 @@ namespace MediaBrowser.Providers.Manager // Try to throttle this a little bit. await Task.Delay(100).ConfigureAwait(false); - var artist = item as MusicArtist; - var task = artist == null - ? RefreshItem(item, refreshItem.Item2, cancellationToken) - : RefreshArtist(artist, refreshItem.Item2, cancellationToken); + var task = item is MusicArtist artist + ? RefreshArtist(artist, refreshItem.Item2, cancellationToken) + : RefreshItem(item, refreshItem.Item2, cancellationToken); await task.ConfigureAwait(false); } @@ -1125,8 +1122,7 @@ namespace MediaBrowser.Providers.Manager } } - public Task RefreshFullItem(BaseItem item, MetadataRefreshOptions options, - CancellationToken cancellationToken) + public Task RefreshFullItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return RefreshItem(item, options, cancellationToken); } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 5593c5036..4e33d0048 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -22,6 +22,19 @@ netstandard2.1 false true + true + + + + + + + + + + + + ../jellyfin.ruleset diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 4e11fcbb2..95808eb1a 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -177,7 +177,19 @@ namespace MediaBrowser.Providers.MediaInfo FetchShortcutInfo(item); } - var prober = new FFProbeVideoInfo(_logger, _mediaSourceManager, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager, _chapterManager, _libraryManager); + var prober = new FFProbeVideoInfo( + _logger, + _mediaSourceManager, + _mediaEncoder, + _itemRepo, + _blurayExaminer, + _localization, + _encodingManager, + _fileSystem, + _config, + _subtitleManager, + _chapterManager, + _libraryManager); return prober.ProbeVideo(item, options, cancellationToken); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 2b178d4d4..ea1db88ba 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -1,3 +1,6 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1600 + using System; using System.Collections.Generic; using System.Globalization; @@ -25,7 +28,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.MediaInfo @@ -33,13 +35,10 @@ namespace MediaBrowser.Providers.MediaInfo public class FFProbeVideoInfo { private readonly ILogger _logger; - private readonly IIsoManager _isoManager; private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; private readonly IBlurayExaminer _blurayExaminer; private readonly ILocalizationManager _localization; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private readonly IEncodingManager _encodingManager; private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _config; @@ -48,16 +47,30 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; - public FFProbeVideoInfo(ILogger logger, IMediaSourceManager mediaSourceManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, ILibraryManager libraryManager) + /// + /// The dummy chapter duration. + /// + private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks; + + public FFProbeVideoInfo( + ILogger logger, + IMediaSourceManager mediaSourceManager, + IMediaEncoder mediaEncoder, + IItemRepository itemRepo, + IBlurayExaminer blurayExaminer, + ILocalizationManager localization, + IEncodingManager encodingManager, + IFileSystem fileSystem, + IServerConfigurationManager config, + ISubtitleManager subtitleManager, + IChapterManager chapterManager, + ILibraryManager libraryManager) { _logger = logger; - _isoManager = isoManager; _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; _blurayExaminer = blurayExaminer; _localization = localization; - _appPaths = appPaths; - _json = json; _encodingManager = encodingManager; _fileSystem = fileSystem; _config = config; @@ -159,7 +172,7 @@ namespace MediaBrowser.Providers.MediaInfo { List mediaStreams; IReadOnlyList mediaAttachments; - List chapters; + ChapterInfo[] chapters; if (mediaInfo != null) { @@ -191,17 +204,17 @@ namespace MediaBrowser.Providers.MediaInfo } video.Container = mediaInfo.Container; - chapters = mediaInfo.Chapters == null ? new List() : mediaInfo.Chapters.ToList(); + chapters = mediaInfo.Chapters == null ? Array.Empty() : mediaInfo.Chapters; if (blurayInfo != null) { - FetchBdInfo(video, chapters, mediaStreams, blurayInfo); + FetchBdInfo(video, ref chapters, mediaStreams, blurayInfo); } } else { mediaStreams = new List(); mediaAttachments = Array.Empty(); - chapters = new List(); + chapters = Array.Empty(); } await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); @@ -231,9 +244,9 @@ namespace MediaBrowser.Providers.MediaInfo if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || options.MetadataRefreshMode == MetadataRefreshMode.Default) { - if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) + if (chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video)) { - AddDummyChapters(video, chapters); + CreateDummyChapters(video, ref chapters); } NormalizeChapterNames(chapters); @@ -246,28 +259,29 @@ namespace MediaBrowser.Providers.MediaInfo await _encodingManager.RefreshChapterImages(video, options.DirectoryService, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false); - _chapterManager.SaveChapters(video.Id.ToString(), chapters); + _chapterManager.SaveChapters(video.Id, chapters); } } - private void NormalizeChapterNames(List chapters) + private void NormalizeChapterNames(ChapterInfo[] chapters) { - var index = 1; - - foreach (var chapter in chapters) + for (int i = 0; i < chapters.Length; i++) { + string name = chapters[i].Name; // Check if the name is empty and/or if the name is a time // Some ripping programs do that. - if (string.IsNullOrWhiteSpace(chapter.Name) || - TimeSpan.TryParse(chapter.Name, out var time)) + if (string.IsNullOrWhiteSpace(name) || + TimeSpan.TryParse(name, out _)) { - chapter.Name = string.Format(_localization.GetLocalizedString("ChapterNameValue"), index.ToString(CultureInfo.InvariantCulture)); + chapters[i].Name = string.Format( + CultureInfo.InvariantCulture, + _localization.GetLocalizedString("ChapterNameValue"), + (i + 1).ToString(CultureInfo.InvariantCulture)); } - index++; } } - private void FetchBdInfo(BaseItem item, List chapters, List mediaStreams, BlurayDiscInfo blurayInfo) + private void FetchBdInfo(BaseItem item, ref ChapterInfo[] chapters, List mediaStreams, BlurayDiscInfo blurayInfo) { var video = (Video)item; @@ -301,13 +315,15 @@ namespace MediaBrowser.Providers.MediaInfo if (blurayInfo.Chapters != null) { - chapters.Clear(); - - chapters.AddRange(blurayInfo.Chapters.Select(c => new ChapterInfo + double[] brChapter = blurayInfo.Chapters; + chapters = new ChapterInfo[brChapter.Length]; + for (int i = 0; i < brChapter.Length; i++) { - StartPositionTicks = TimeSpan.FromSeconds(c).Ticks - - })); + chapters[i] = new ChapterInfo + { + StartPositionTicks = TimeSpan.FromSeconds(brChapter[i]).Ticks + }; + } } videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); @@ -495,17 +511,17 @@ namespace MediaBrowser.Providers.MediaInfo var libraryOptions = _libraryManager.GetLibraryOptions(video); string[] subtitleDownloadLanguages; - bool SkipIfEmbeddedSubtitlesPresent; - bool SkipIfAudioTrackMatches; - bool RequirePerfectMatch; + bool skipIfEmbeddedSubtitlesPresent; + bool skipIfAudioTrackMatches; + bool requirePerfectMatch; bool enabled; if (libraryOptions.SubtitleDownloadLanguages == null) { subtitleDownloadLanguages = subtitleOptions.DownloadLanguages; - SkipIfEmbeddedSubtitlesPresent = subtitleOptions.SkipIfEmbeddedSubtitlesPresent; - SkipIfAudioTrackMatches = subtitleOptions.SkipIfAudioTrackMatches; - RequirePerfectMatch = subtitleOptions.RequirePerfectMatch; + skipIfEmbeddedSubtitlesPresent = subtitleOptions.SkipIfEmbeddedSubtitlesPresent; + skipIfAudioTrackMatches = subtitleOptions.SkipIfAudioTrackMatches; + requirePerfectMatch = subtitleOptions.RequirePerfectMatch; enabled = (subtitleOptions.DownloadEpisodeSubtitles && video is Episode) || (subtitleOptions.DownloadMovieSubtitles && @@ -514,9 +530,9 @@ namespace MediaBrowser.Providers.MediaInfo else { subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages; - SkipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent; - SkipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches; - RequirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch; + skipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent; + skipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches; + requirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch; enabled = true; } @@ -526,9 +542,9 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager) .DownloadSubtitles(video, currentStreams.Concat(externalSubtitleStreams).ToList(), - SkipIfEmbeddedSubtitlesPresent, - SkipIfAudioTrackMatches, - RequirePerfectMatch, + skipIfEmbeddedSubtitlesPresent, + skipIfAudioTrackMatches, + requirePerfectMatch, subtitleDownloadLanguages, libraryOptions.DisabledSubtitleFetchers, libraryOptions.SubtitleFetcherOrder, @@ -546,23 +562,23 @@ namespace MediaBrowser.Providers.MediaInfo currentStreams.AddRange(externalSubtitleStreams); } - /// - /// The dummy chapter duration - /// - private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks; - /// /// Adds the dummy chapters. /// /// The video. /// The chapters. - private void AddDummyChapters(Video video, List chapters) + private void CreateDummyChapters(Video video, ref ChapterInfo[] chapters) { var runtime = video.RunTimeTicks ?? 0; if (runtime < 0) { - throw new ArgumentException(string.Format("{0} has invalid runtime of {1}", video.Name, runtime)); + throw new ArgumentException( + string.Format( + CultureInfo.InvariantCulture, + "{0} has invalid runtime of {1}", + video.Name, + runtime)); } if (runtime < _dummyChapterDuration) @@ -570,18 +586,18 @@ namespace MediaBrowser.Providers.MediaInfo return; } - long currentChapterTicks = 0; - var index = 1; - // Limit to 100 chapters just in case there's some incorrect metadata here - while (currentChapterTicks < runtime && index < 100) + int chapterCount = (int)Math.Min(runtime / _dummyChapterDuration, 100); + chapters = new ChapterInfo[chapterCount]; + + long currentChapterTicks = 0; + for (int i = 0; i < chapterCount; i++) { - chapters.Add(new ChapterInfo + chapters[i] = new ChapterInfo { StartPositionTicks = currentChapterTicks - }); + }; - index++; currentChapterTicks += _dummyChapterDuration; } } diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 8e71b625e..3e276ba37 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -776,7 +777,7 @@ namespace MediaBrowser.Providers.Music _logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds); _stopWatchMusicBrainz.Restart(); - response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false); + response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false); // We retry a finite number of times, and only whilst MB is indcating 503 (throttling) } diff --git a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs index 861847f71..e2fd5b9e3 100644 --- a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -36,20 +37,25 @@ namespace MediaBrowser.Providers.Tmdb.Movies private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; private readonly ILogger _logger; - private readonly ILocalizationManager _localization; private readonly ILibraryManager _libraryManager; private readonly IApplicationHost _appHost; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public TmdbMovieProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager, IApplicationHost appHost) + public TmdbMovieProvider( + IJsonSerializer jsonSerializer, + IHttpClient httpClient, + IFileSystem fileSystem, + IServerConfigurationManager configurationManager, + ILogger logger, + ILibraryManager libraryManager, + IApplicationHost appHost) { _jsonSerializer = jsonSerializer; _httpClient = httpClient; _fileSystem = fileSystem; _configurationManager = configurationManager; _logger = logger; - _localization = localization; _libraryManager = libraryManager; _appHost = appHost; Current = this; @@ -401,15 +407,15 @@ namespace MediaBrowser.Providers.Tmdb.Movies private static long _lastRequestTicks; // The limit is 40 requests per 10 seconds - private static int requestIntervalMs = 300; + private const int RequestIntervalMs = 300; /// /// Gets the movie db response. /// internal async Task GetMovieDbResponse(HttpRequestOptions options) { - var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks); - var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs); + var delayTicks = (RequestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks); + var delayMs = Math.Min(delayTicks / 10000, RequestIntervalMs); if (delayMs > 0) { @@ -422,11 +428,13 @@ namespace MediaBrowser.Providers.Tmdb.Movies options.BufferContent = true; options.UserAgent = _appHost.ApplicationUserAgent; - return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false); + return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false); } + /// public int Order => 1; + /// public Task GetImageResponse(string url, CancellationToken cancellationToken) { return _httpClient.GetResponse(new HttpRequestOptions -- cgit v1.2.3 From 2c8592fe78270723ce9e1def145569a879943b2a Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Thu, 12 Mar 2020 17:18:49 +0100 Subject: Fix subtitles --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index a4a7595d2..72db56974 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -183,11 +183,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles private async Task GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) { - if (requiresCharset) + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) { - using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) + if (requiresCharset) { var result = CharsetDetector.DetectFromStream(stream).Detected; + stream.Position = 0; if (result != null) { @@ -199,9 +200,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new MemoryStream(Encoding.UTF8.GetBytes(text)); } } - } - return File.OpenRead(path); + return stream; + } } private async Task GetReadableFile( @@ -745,6 +746,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles { Url = path, CancellationToken = cancellationToken, + + // Needed for seeking BufferContent = true }; -- cgit v1.2.3 From 4836d1674bdc076431c0ac18171c1b97c7e254ce Mon Sep 17 00:00:00 2001 From: Ian Walton Date: Mon, 23 Mar 2020 12:39:12 -0400 Subject: Don't return closed stream for subtitles. (jellyfin/jellyfin#2650) --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 72db56974..6284e0fd9 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -183,9 +183,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles private async Task GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) { - using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) + if (requiresCharset) { - if (requiresCharset) + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) { var result = CharsetDetector.DetectFromStream(stream).Detected; stream.Position = 0; @@ -200,9 +200,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new MemoryStream(Encoding.UTF8.GetBytes(text)); } } - - return stream; } + + return File.OpenRead(path); } private async Task GetReadableFile( -- cgit v1.2.3 From e9d1eabd53105ae15bca08f5722bbaa0bfa49758 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 24 Mar 2020 16:12:06 +0100 Subject: Remove unused usings --- DvdLib/Ifo/Dvd.cs | 2 +- Emby.Dlna/Didl/DidlBuilder.cs | 32 +++++++++++----------- Emby.Dlna/Didl/Filter.cs | 1 - Emby.Dlna/Main/DlnaEntryPoint.cs | 4 +-- .../Activity/ActivityLogEntryPoint.cs | 1 - .../Configuration/ServerConfigurationManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 25 +++++++++-------- .../Data/SqliteUserRepository.cs | 2 +- .../HttpServer/FileWriter.cs | 2 +- .../IO/ManagedFileSystem.cs | 10 +++---- .../Library/Resolvers/TV/SeriesResolver.cs | 1 - Emby.Server.Implementations/Library/UserManager.cs | 18 ++++++------ .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../LiveTv/TunerHosts/LiveStream.cs | 2 +- .../Networking/NetworkManager.cs | 2 +- .../Tasks/RefreshMediaLibraryTask.cs | 3 +- .../Services/SwaggerService.cs | 4 +-- Jellyfin.Server/CoreAppHost.cs | 1 - .../Routines/DisableTranscodingThrottling.cs | 2 -- Jellyfin.Server/Program.cs | 5 +--- MediaBrowser.Api/BaseApiService.cs | 2 +- MediaBrowser.Api/ChannelService.cs | 2 +- MediaBrowser.Api/EnvironmentService.cs | 2 +- MediaBrowser.Api/Playback/MediaInfoService.cs | 18 ++++++------ MediaBrowser.Api/TvShowsService.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 1 - MediaBrowser.Controller/Entities/Person.cs | 1 - MediaBrowser.Controller/Entities/PersonInfo.cs | 1 - MediaBrowser.Controller/Library/NameExtensions.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 7 +++-- .../MediaEncoding/EncodingJobInfo.cs | 2 +- MediaBrowser.Controller/Sorting/SortExtensions.cs | 1 - .../Attachments/AttachmentExtractor.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 8 +++--- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 1 - MediaBrowser.Model/Dlna/SearchCriteria.cs | 1 - MediaBrowser.Model/Entities/DisplayPreferences.cs | 2 +- MediaBrowser.Model/Entities/MediaStream.cs | 6 ++-- MediaBrowser.Model/Entities/SeriesStatus.cs | 2 +- MediaBrowser.Model/Entities/SortOrder.cs | 2 +- .../Music/ArtistMetadataService.cs | 8 +++--- .../Plugins/MusicBrainz/AlbumProvider.cs | 3 +- .../Plugins/TheTvdb/TvdbClientManager.cs | 8 +++--- .../Plugins/TheTvdb/TvdbEpisodeProvider.cs | 2 +- .../Tmdb/Models/General/Profile.cs | 10 +++---- RSSDP/DisposableManagedObjectBase.cs | 2 +- RSSDP/SsdpCommunicationsServer.cs | 4 +-- .../FirstTimeSetupOrElevatedHandlerTests.cs | 4 +-- .../RequiresElevationHandlerTests.cs | 4 +-- 51 files changed, 112 insertions(+), 123 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index 157b2e197..c0f9cf410 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -33,7 +33,7 @@ namespace DvdLib.Ifo continue; } - var nums = ifo.Name.Split(new [] { '_' }, StringSplitOptions.RemoveEmptyEntries); + var nums = ifo.Name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); if (nums.Length >= 2 && ushort.TryParse(nums[1], out var ifoNumber)) { ReadVTS(ifoNumber, ifo.FullName); diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 45335f90d..efc86f333 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -392,24 +392,24 @@ namespace Emby.Dlna.Didl { switch (itemStubType.Value) { - case StubType.Latest: return _localization.GetLocalizedString("Latest"); - case StubType.Playlists: return _localization.GetLocalizedString("Playlists"); - case StubType.AlbumArtists: return _localization.GetLocalizedString("HeaderAlbumArtists"); - case StubType.Albums: return _localization.GetLocalizedString("Albums"); - case StubType.Artists: return _localization.GetLocalizedString("Artists"); - case StubType.Songs: return _localization.GetLocalizedString("Songs"); - case StubType.Genres: return _localization.GetLocalizedString("Genres"); - case StubType.FavoriteAlbums: return _localization.GetLocalizedString("HeaderFavoriteAlbums"); - case StubType.FavoriteArtists: return _localization.GetLocalizedString("HeaderFavoriteArtists"); - case StubType.FavoriteSongs: return _localization.GetLocalizedString("HeaderFavoriteSongs"); + case StubType.Latest: return _localization.GetLocalizedString("Latest"); + case StubType.Playlists: return _localization.GetLocalizedString("Playlists"); + case StubType.AlbumArtists: return _localization.GetLocalizedString("HeaderAlbumArtists"); + case StubType.Albums: return _localization.GetLocalizedString("Albums"); + case StubType.Artists: return _localization.GetLocalizedString("Artists"); + case StubType.Songs: return _localization.GetLocalizedString("Songs"); + case StubType.Genres: return _localization.GetLocalizedString("Genres"); + case StubType.FavoriteAlbums: return _localization.GetLocalizedString("HeaderFavoriteAlbums"); + case StubType.FavoriteArtists: return _localization.GetLocalizedString("HeaderFavoriteArtists"); + case StubType.FavoriteSongs: return _localization.GetLocalizedString("HeaderFavoriteSongs"); case StubType.ContinueWatching: return _localization.GetLocalizedString("HeaderContinueWatching"); - case StubType.Movies: return _localization.GetLocalizedString("Movies"); - case StubType.Collections: return _localization.GetLocalizedString("Collections"); - case StubType.Favorites: return _localization.GetLocalizedString("Favorites"); - case StubType.NextUp: return _localization.GetLocalizedString("HeaderNextUp"); - case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows"); + case StubType.Movies: return _localization.GetLocalizedString("Movies"); + case StubType.Collections: return _localization.GetLocalizedString("Collections"); + case StubType.Favorites: return _localization.GetLocalizedString("Favorites"); + case StubType.NextUp: return _localization.GetLocalizedString("HeaderNextUp"); + case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows"); case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes"); - case StubType.Series: return _localization.GetLocalizedString("Shows"); + case StubType.Series: return _localization.GetLocalizedString("Shows"); default: break; } } diff --git a/Emby.Dlna/Didl/Filter.cs b/Emby.Dlna/Didl/Filter.cs index f6217d91e..412259e90 100644 --- a/Emby.Dlna/Didl/Filter.cs +++ b/Emby.Dlna/Didl/Filter.cs @@ -1,7 +1,6 @@ #pragma warning disable CS1591 using System; -using MediaBrowser.Model.Extensions; namespace Emby.Dlna.Didl { diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 770d48168..ba416ce09 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -262,8 +262,8 @@ namespace Emby.Dlna.Main { if (address.AddressFamily == AddressFamily.InterNetworkV6) { - // Not support IPv6 right now - continue; + // Not support IPv6 right now + continue; } var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 332dfa95c..d900520b2 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -8,7 +8,6 @@ using System.Text; using System.Threading.Tasks; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Entities; diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index 30b654886..f407317ec 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Configuration var newPath = newConfig.MetadataPath; if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(Configuration.MetadataPath, newPath, StringComparison.Ordinal)) + && !string.Equals(Configuration.MetadataPath, newPath, StringComparison.Ordinal)) { // Validate if (!Directory.Exists(newPath)) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 0eb396af4..f77a6103b 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -454,7 +454,7 @@ namespace Emby.Server.Implementations.Data private static string GetSaveItemCommandText() { - var saveColumns = new [] + var saveColumns = new[] { "guid", "type", @@ -560,7 +560,7 @@ namespace Emby.Server.Implementations.Data throw new ArgumentNullException(nameof(item)); } - SaveItems(new [] { item }, cancellationToken); + SaveItems(new[] { item }, cancellationToken); } public void SaveImages(BaseItem item) @@ -1622,7 +1622,7 @@ namespace Emby.Server.Implementations.Data { IEnumerable GetLockedFields(string s) { - foreach (var i in s.Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (var i in s.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { if (Enum.TryParse(i, true, out MetadataFields parsedValue)) { @@ -1818,7 +1818,7 @@ namespace Emby.Server.Implementations.Data { if (!reader.IsDBNull(index)) { - item.ProductionLocations = reader.GetString(index).Split(new [] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); + item.ProductionLocations = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } index++; } @@ -2897,8 +2897,8 @@ namespace Emby.Server.Implementations.Data BindSimilarParams(query, statement); BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); } @@ -2925,7 +2925,7 @@ namespace Emby.Server.Implementations.Data prepend.Add(("SearchScore", SortOrder.Descending)); prepend.Add((ItemSortBy.SortName, SortOrder.Ascending)); } - + if (hasSimilar) { prepend.Add(("SimilarityScore", SortOrder.Descending)); @@ -3266,8 +3266,8 @@ namespace Emby.Server.Implementations.Data BindSimilarParams(query, statement); BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); foreach (var row in statement.ExecuteQuery()) { @@ -3288,8 +3288,8 @@ namespace Emby.Server.Implementations.Data BindSimilarParams(query, statement); BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); } @@ -6159,7 +6159,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type item.ColorTransfer = reader[34].ToString(); } - if (item.Type == MediaStreamType.Subtitle){ + if (item.Type == MediaStreamType.Subtitle) + { item.localizedUndefined = _localization.GetLocalizedString("Undefined"); item.localizedDefault = _localization.GetLocalizedString("Default"); item.localizedForced = _localization.GetLocalizedString("Forced"); diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs index a042320c9..fee4b7f3c 100644 --- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Data IServerApplicationPaths appPaths) : base(logger) { - _jsonOptions = JsonDefaults.GetOptions();; + _jsonOptions = JsonDefaults.GetOptions(); ; DbFilePath = Path.Combine(appPaths.DataPath, "users.db"); } diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs index 82f1e5b52..0b61e40b0 100644 --- a/Emby.Server.Implementations/HttpServer/FileWriter.cs +++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs @@ -11,8 +11,8 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; -using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Microsoft.Net.Http.Headers; namespace Emby.Server.Implementations.HttpServer diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 48599beb7..7461ec4f1 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -587,11 +587,11 @@ namespace Emby.Server.Implementations.IO // some drives on linux have no actual size or are used for other purposes return DriveInfo.GetDrives().Where(d => d.IsReady && d.TotalSize != 0 && d.DriveType != DriveType.Ram) .Select(d => new FileSystemMetadata - { - Name = d.Name, - FullName = d.RootDirectory.FullName, - IsDirectory = true - }).ToList(); + { + Name = d.Name, + FullName = d.RootDirectory.FullName, + IsDirectory = true + }).ToList(); } public virtual IEnumerable GetDirectories(string path, bool recursive = false) diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index c759e7115..dd6bd8ee8 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 25d733a65..7b17cc913 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -805,17 +805,17 @@ namespace Emby.Server.Implementations.Library // Delete user config dir lock (_configSyncLock) - lock (_policySyncLock) - { - try - { - Directory.Delete(user.ConfigurationDirectoryPath, true); - } - catch (IOException ex) + lock (_policySyncLock) { - _logger.LogError(ex, "Error deleting user config dir: {Path}", user.ConfigurationDirectoryPath); + try + { + Directory.Delete(user.ConfigurationDirectoryPath, true); + } + catch (IOException ex) + { + _logger.LogError(ex, "Error deleting user config dir: {Path}", user.ConfigurationDirectoryPath); + } } - } _users.TryRemove(user.Id, out _); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 77669da39..1bad38982 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -8,8 +8,8 @@ using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 5354489f9..9fa042090 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -8,8 +8,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Library; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 1d8d3cf39..b3e88b667 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -500,7 +500,7 @@ namespace Emby.Server.Implementations.Networking { if (ip.Address.Equals(address) && ip.IPv4Mask != null) { - return ip.IPv4Mask; + return ip.IPv4Mask; } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index 073678019..99e5ab2cf 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -38,7 +38,8 @@ namespace Emby.Server.Implementations.ScheduledTasks { yield return new TaskTriggerInfo { - Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(12).Ticks + Type = TaskTriggerInfo.TriggerInterval, + IntervalTicks = TimeSpan.FromHours(12).Ticks }; } diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs index c30f32af9..5177251c3 100644 --- a/Emby.Server.Implementations/Services/SwaggerService.cs +++ b/Emby.Server.Implementations/Services/SwaggerService.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using Emby.Server.Implementations.HttpServer; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Services; -using Emby.Server.Implementations.HttpServer; namespace Emby.Server.Implementations.Services { @@ -241,7 +241,7 @@ namespace Emby.Server.Implementations.Services responses = responses, - security = new [] { apiKeySecurity } + security = new[] { apiKeySecurity } }; } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index ed5968ad6..1d5313c13 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -4,7 +4,6 @@ using Emby.Server.Implementations; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.IO; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Server diff --git a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs index 673f0e415..6f8e4a8ff 100644 --- a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs +++ b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs @@ -1,8 +1,6 @@ using System; -using System.IO; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Configuration; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Migrations.Routines diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index e9e852349..9e8ac2e9a 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -18,7 +17,6 @@ using Emby.Server.Implementations.Networking; using Jellyfin.Drawing.Skia; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Globalization; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -26,7 +24,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Serilog; -using Serilog.Events; using Serilog.Extensions.Logging; using SQLitePCL; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -531,7 +528,7 @@ namespace Jellyfin.Server } catch (Exception ex) { - _logger.LogWarning(ex, "Skia not available. Will fallback to NullIMageEncoder."); + _logger.LogWarning(ex, "Skia not available. Will fallback to NullImageEncoder."); } return new NullImageEncoder(); diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 2b994d279..112ee8f79 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -9,8 +9,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Services; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; namespace MediaBrowser.Api diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs index 92c32f2ad..6139ba156 100644 --- a/MediaBrowser.Api/ChannelService.cs +++ b/MediaBrowser.Api/ChannelService.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Api.UserLibrary; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 322b9805b..36b03f09c 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -177,7 +177,7 @@ namespace MediaBrowser.Api } public object Get(GetDefaultDirectoryBrowser request) => - ToOptimizedResult(new DefaultDirectoryBrowserInfo {Path = null}); + ToOptimizedResult(new DefaultDirectoryBrowserInfo { Path = null }); /// /// Gets the specified request. diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2aa5e2df1..d74ec3ca6 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -5,8 +5,8 @@ using System; using System.Buffers; using System.Globalization; -using System.Text.Json; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; @@ -470,7 +470,7 @@ namespace MediaBrowser.Api.Playback else { options.MaxBitrate = GetMaxBitrate(maxBitrate, user); - + if (item is Audio) { if (!user.Policy.EnableAudioPlaybackTranscoding) @@ -486,10 +486,10 @@ namespace MediaBrowser.Api.Playback } } - // 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); + // 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) { @@ -516,7 +516,7 @@ namespace MediaBrowser.Api.Playback { if (streamInfo != null) { - streamInfo.PlaySessionId = playSessionId; + streamInfo.PlaySessionId = playSessionId; streamInfo.StartPositionTicks = startTimeTicks; mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; @@ -526,10 +526,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); - } + } } else { diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index b843f7096..334d1db51 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -12,8 +12,8 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Services; using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; namespace MediaBrowser.Api diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a9ec19e2f..7380e6da1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -15,7 +15,6 @@ using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 64e216e69..9e4f9d47e 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities diff --git a/MediaBrowser.Controller/Entities/PersonInfo.cs b/MediaBrowser.Controller/Entities/PersonInfo.cs index e90c55a8a..f3ec73b32 100644 --- a/MediaBrowser.Controller/Entities/PersonInfo.cs +++ b/MediaBrowser.Controller/Entities/PersonInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Collections.Generic; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Controller/Library/NameExtensions.cs b/MediaBrowser.Controller/Library/NameExtensions.cs index 6b0b7e53a..24d0347e9 100644 --- a/MediaBrowser.Controller/Library/NameExtensions.cs +++ b/MediaBrowser.Controller/Library/NameExtensions.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Controller.Extensions; namespace MediaBrowser.Controller.Library diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 342c76414..663ec0701 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1588,7 +1588,8 @@ namespace MediaBrowser.Controller.MediaEncoding // Add parameters to use VAAPI with burn-in subttiles (GH issue #642) if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream - && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + { outputSizeParam += ",hwmap=mode=read+write+direct"; } } @@ -1953,7 +1954,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If we're hardware VAAPI decoding and software encoding, download frames from the decoder first var hwType = options.HardwareAccelerationType ?? string.Empty; - if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding ) + if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !options.EnableHardwareEncoding) { filters.Add("hwdownload"); @@ -2637,7 +2638,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { - if(Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1)) + if (Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1)) return "-hwaccel d3d11va"; else return "-hwaccel dxva2"; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 38ef33caf..1127a08de 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -9,8 +9,8 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Session; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; namespace MediaBrowser.Controller.MediaEncoding { diff --git a/MediaBrowser.Controller/Sorting/SortExtensions.cs b/MediaBrowser.Controller/Sorting/SortExtensions.cs index f5ee574a2..2a68f4678 100644 --- a/MediaBrowser.Controller/Sorting/SortExtensions.cs +++ b/MediaBrowser.Controller/Sorting/SortExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace MediaBrowser.Controller.Sorting { diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index c530c9fd8..43d33c716 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,6 +1,6 @@ using System; -using System.Diagnostics; using System.Collections.Concurrent; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4123f0203..8c46af7db 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -20,8 +20,8 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index f8047af42..ded8dffd6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -539,7 +539,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString)) { - attachment.CodecTag = streamInfo.CodecTagString; + attachment.CodecTag = streamInfo.CodecTagString; } if (streamInfo.Tags != null) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 72db56974..4deca120d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -753,10 +753,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles return _httpClient.Get(opts); - case MediaProtocol.File: - return Task.FromResult(File.OpenRead(path)); - default: - throw new ArgumentOutOfRangeException(nameof(protocol)); + case MediaProtocol.File: + return Task.FromResult(File.OpenRead(path)); + default: + throw new ArgumentOutOfRangeException(nameof(protocol)); } } } diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index 6a58b4adc..8235b72d1 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -1,7 +1,6 @@ #pragma warning disable CS1591 using System; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/SearchCriteria.cs b/MediaBrowser.Model/Dlna/SearchCriteria.cs index dc6d201ae..394fb9af9 100644 --- a/MediaBrowser.Model/Dlna/SearchCriteria.cs +++ b/MediaBrowser.Model/Dlna/SearchCriteria.cs @@ -2,7 +2,6 @@ using System; using System.Text.RegularExpressions; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Entities/DisplayPreferences.cs b/MediaBrowser.Model/Entities/DisplayPreferences.cs index 499baa058..2cd8bd306 100644 --- a/MediaBrowser.Model/Entities/DisplayPreferences.cs +++ b/MediaBrowser.Model/Entities/DisplayPreferences.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Model.Entities /// /// true if [show sidebar]; otherwise, false. public bool ShowSidebar { get; set; } - + /// /// Gets or sets the client /// diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 37f9d7c1a..e7e8d7cec 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -69,9 +69,9 @@ namespace MediaBrowser.Model.Entities } } - public string localizedUndefined { get; set; } - public string localizedDefault { get; set; } - public string localizedForced { get; set; } + public string localizedUndefined { get; set; } + public string localizedDefault { get; set; } + public string localizedForced { get; set; } public string DisplayTitle { diff --git a/MediaBrowser.Model/Entities/SeriesStatus.cs b/MediaBrowser.Model/Entities/SeriesStatus.cs index 51351c135..c77c4a8ad 100644 --- a/MediaBrowser.Model/Entities/SeriesStatus.cs +++ b/MediaBrowser.Model/Entities/SeriesStatus.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Entities /// The continuing. /// Continuing, - + /// /// The ended. /// diff --git a/MediaBrowser.Model/Entities/SortOrder.cs b/MediaBrowser.Model/Entities/SortOrder.cs index e6cb6fd09..f3abc06f3 100644 --- a/MediaBrowser.Model/Entities/SortOrder.cs +++ b/MediaBrowser.Model/Entities/SortOrder.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Entities /// The ascending. /// Ascending, - + /// /// The descending. /// diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index f90a631c6..5a30260a5 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -31,10 +31,10 @@ namespace MediaBrowser.Providers.Music { return item.IsAccessedByName ? item.GetTaggedItems(new InternalItemsQuery - { - Recursive = true, - IsFolder = false - }) + { + Recursive = true, + IsFolder = false + }) : item.GetRecursiveChildren(i => i is IHasArtist && !i.IsFolder); } diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index bc973dee5..31cdaf616 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -775,7 +776,7 @@ namespace MediaBrowser.Providers.Music _logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds); _stopWatchMusicBrainz.Restart(); - response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false); + response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false); // We retry a finite number of times, and only whilst MB is indicating 503 (throttling) } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs index a12b4d3ad..b73834155 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs @@ -60,21 +60,21 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb CancellationToken cancellationToken) { var cacheKey = GenerateKey("series", name, language); - return TryGetValue(cacheKey, language,() => TvDbClient.Search.SearchSeriesByNameAsync(name, cancellationToken)); + return TryGetValue(cacheKey, language, () => TvDbClient.Search.SearchSeriesByNameAsync(name, cancellationToken)); } public Task> GetSeriesByIdAsync(int tvdbId, string language, CancellationToken cancellationToken) { var cacheKey = GenerateKey("series", tvdbId, language); - return TryGetValue(cacheKey, language,() => TvDbClient.Series.GetAsync(tvdbId, cancellationToken)); + return TryGetValue(cacheKey, language, () => TvDbClient.Series.GetAsync(tvdbId, cancellationToken)); } public Task> GetEpisodesAsync(int episodeTvdbId, string language, CancellationToken cancellationToken) { var cacheKey = GenerateKey("episode", episodeTvdbId, language); - return TryGetValue(cacheKey, language,() => TvDbClient.Episodes.GetAsync(episodeTvdbId, cancellationToken)); + return TryGetValue(cacheKey, language, () => TvDbClient.Episodes.GetAsync(episodeTvdbId, cancellationToken)); } public async Task> GetAllEpisodesAsync(int tvdbId, string language, @@ -109,7 +109,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb CancellationToken cancellationToken) { var cacheKey = GenerateKey("series", imdbId, language); - return TryGetValue(cacheKey, language,() => TvDbClient.Search.SearchSeriesByImdbIdAsync(imdbId, cancellationToken)); + return TryGetValue(cacheKey, language, () => TvDbClient.Search.SearchSeriesByImdbIdAsync(imdbId, cancellationToken)); } public Task> GetSeriesByZap2ItIdAsync( diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs index f58c58a2e..08c2a74d2 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs @@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb continue; } - var roles = new List {currentActor.Substring(roleStartIndex + 1)}; + var roles = new List { currentActor.Substring(roleStartIndex + 1) }; // Fetch all roles for (var j = i + 1; j < episode.GuestStars.Length; ++j) diff --git a/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs b/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs index 73a049c73..f87d14850 100644 --- a/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs +++ b/MediaBrowser.Providers/Tmdb/Models/General/Profile.cs @@ -2,10 +2,10 @@ namespace MediaBrowser.Providers.Tmdb.Models.General { public class Profile { - public string File_Path { get; set; } - public int Width { get; set; } - public int Height { get; set; } - public object Iso_639_1 { get; set; } - public double Aspect_Ratio { get; set; } + public string File_Path { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public object Iso_639_1 { get; set; } + public double Aspect_Ratio { get; set; } } } diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index bb36229c4..39589f022 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -72,7 +72,7 @@ namespace Rssdp.Infrastructure /// Sets the property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behaviour of derived classes. /// /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification="We do exactly as asked, but CA doesn't seem to like us also setting the IsDisposed property. Too bad, it's a good idea and shouldn't cause an exception or anything likely to interfer with the dispose process.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "We do exactly as asked, but CA doesn't seem to like us also setting the IsDisposed property. Too bad, it's a good idea and shouldn't cause an exception or anything likely to interfer with the dispose process.")] public void Dispose() { IsDisposed = true; diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 0aa985a26..18097ef24 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -8,9 +8,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Net; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Net; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.Net; +using Microsoft.Extensions.Logging; namespace Rssdp.Infrastructure { diff --git a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs index 84cdbe360..e40af703f 100644 --- a/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandlerTests.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupOrElevatedPolicy { var fixture = new Fixture().Customize(new AutoMoqCustomization()); _configurationManagerMock = fixture.Freeze>(); - _requirements = new List {new FirstTimeSetupOrElevatedRequirement()}; + _requirements = new List { new FirstTimeSetupOrElevatedRequirement() }; _sut = fixture.Create(); } @@ -58,7 +58,7 @@ namespace Jellyfin.Api.Tests.Auth.FirstTimeSetupOrElevatedPolicy private static ClaimsPrincipal SetupUser(string role) { - var claims = new[] {new Claim(ClaimTypes.Role, role)}; + var claims = new[] { new Claim(ClaimTypes.Role, role) }; var identity = new ClaimsIdentity(claims); return new ClaimsPrincipal(identity); } diff --git a/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs index e2beea1ad..cd05a8328 100644 --- a/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/RequiresElevationPolicy/RequiresElevationHandlerTests.cs @@ -23,9 +23,9 @@ namespace Jellyfin.Api.Tests.Auth.RequiresElevationPolicy [InlineData(UserRoles.Guest, false)] public async Task ShouldHandleRolesCorrectly(string role, bool shouldSucceed) { - var requirements = new List {new RequiresElevationRequirement()}; + var requirements = new List { new RequiresElevationRequirement() }; - var claims = new[] {new Claim(ClaimTypes.Role, role)}; + var claims = new[] { new Claim(ClaimTypes.Role, role) }; var identity = new ClaimsIdentity(claims); var user = new ClaimsPrincipal(identity); -- cgit v1.2.3 From ee2f911a2b85792c2bfc867d42b7d58b847de6ea Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 00:10:16 +0100 Subject: Remove unnecessary CommonProcess abstraction --- Emby.Server.Implementations/ApplicationHost.cs | 11 +- .../Diagnostics/CommonProcess.cs | 152 --------------------- .../Diagnostics/ProcessFactory.cs | 5 +- .../LiveTv/EmbyTV/EmbyTV.cs | 18 ++- .../LiveTv/EmbyTV/EncodedRecorder.cs | 23 ++-- .../Extensions/ProcessExtensions.cs | 66 +++++++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 31 +++-- .../Subtitles/SubtitleEncoder.cs | 13 +- MediaBrowser.Model/Diagnostics/IProcess.cs | 23 ---- MediaBrowser.Model/Diagnostics/IProcessFactory.cs | 19 +-- 10 files changed, 120 insertions(+), 241 deletions(-) delete mode 100644 Emby.Server.Implementations/Diagnostics/CommonProcess.cs create mode 100644 MediaBrowser.Common/Extensions/ProcessExtensions.cs delete mode 100644 MediaBrowser.Model/Diagnostics/IProcess.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index d6a572818..bc637b02f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1727,15 +1727,15 @@ namespace Emby.Server.Implementations throw new NotSupportedException(); } - var process = ProcessFactory.Create(new ProcessOptions + var process = ProcessFactory.Create(new ProcessStartInfo { FileName = url, - EnableRaisingEvents = true, UseShellExecute = true, ErrorDialog = false }); - process.Exited += ProcessExited; + process.EnableRaisingEvents = true; + process.Exited += (sender, args) => ((Process)sender).Dispose(); ; try { @@ -1748,11 +1748,6 @@ namespace Emby.Server.Implementations } } - private static void ProcessExited(object sender, EventArgs e) - { - ((IProcess)sender).Dispose(); - } - public virtual void EnableLoopback(string appName) { } diff --git a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs deleted file mode 100644 index bfa49ac5f..000000000 --- a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs +++ /dev/null @@ -1,152 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Diagnostics; - -namespace Emby.Server.Implementations.Diagnostics -{ - public class CommonProcess : IProcess - { - private readonly Process _process; - - private bool _disposed = false; - private bool _hasExited; - - public CommonProcess(ProcessOptions options) - { - StartInfo = options; - - var startInfo = new ProcessStartInfo - { - Arguments = options.Arguments, - FileName = options.FileName, - WorkingDirectory = options.WorkingDirectory, - UseShellExecute = options.UseShellExecute, - CreateNoWindow = options.CreateNoWindow, - RedirectStandardError = options.RedirectStandardError, - RedirectStandardInput = options.RedirectStandardInput, - RedirectStandardOutput = options.RedirectStandardOutput, - ErrorDialog = options.ErrorDialog - }; - - - if (options.IsHidden) - { - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - } - - _process = new Process - { - StartInfo = startInfo - }; - - if (options.EnableRaisingEvents) - { - _process.EnableRaisingEvents = true; - _process.Exited += OnProcessExited; - } - } - - public event EventHandler Exited; - - public ProcessOptions StartInfo { get; } - - public StreamWriter StandardInput => _process.StandardInput; - - public StreamReader StandardError => _process.StandardError; - - public StreamReader StandardOutput => _process.StandardOutput; - - public int ExitCode => _process.ExitCode; - - private bool HasExited - { - get - { - if (_hasExited) - { - return true; - } - - try - { - _hasExited = _process.HasExited; - } - catch (InvalidOperationException) - { - _hasExited = true; - } - - return _hasExited; - } - } - - public void Start() - { - _process.Start(); - } - - public void Kill() - { - _process.Kill(); - } - - public bool WaitForExit(int timeMs) - { - return _process.WaitForExit(timeMs); - } - - public Task WaitForExitAsync(int timeMs) - { - // Note: For this function to work correctly, the option EnableRisingEvents needs to be set to true. - - if (HasExited) - { - return Task.FromResult(true); - } - - timeMs = Math.Max(0, timeMs); - - var tcs = new TaskCompletionSource(); - - var cancellationToken = new CancellationTokenSource(timeMs).Token; - - _process.Exited += (sender, args) => tcs.TrySetResult(true); - - cancellationToken.Register(() => tcs.TrySetResult(HasExited)); - - return tcs.Task; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - _process?.Dispose(); - } - - _disposed = true; - } - - private void OnProcessExited(object sender, EventArgs e) - { - _hasExited = true; - Exited?.Invoke(this, e); - } - } -} diff --git a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs b/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs index 02ad3c1a8..00172e17a 100644 --- a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs +++ b/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs @@ -1,14 +1,15 @@ #pragma warning disable CS1591 +using System.Diagnostics; using MediaBrowser.Model.Diagnostics; namespace Emby.Server.Implementations.Diagnostics { public class ProcessFactory : IProcessFactory { - public IProcess Create(ProcessOptions options) + public Process Create(ProcessStartInfo startInfo) { - return new CommonProcess(options); + return new Process { StartInfo = startInfo }; } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 139aa19a4..0f54022c8 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -1683,19 +1684,19 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { Arguments = GetPostProcessArguments(path, options.RecordingPostProcessorArguments), CreateNoWindow = true, - EnableRaisingEvents = true, ErrorDialog = false, FileName = options.RecordingPostProcessor, - IsHidden = true, + WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false }); _logger.LogInformation("Running recording post processor {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + process.EnableRaisingEvents = true; process.Exited += Process_Exited; process.Start(); } @@ -1712,11 +1713,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void Process_Exited(object sender, EventArgs e) { - using (var process = (IProcess)sender) + try { - _logger.LogInformation("Recording post-processing script completed with exit code {ExitCode}", process.ExitCode); - - process.Dispose(); + var exitCode = ((Process)sender).ExitCode; + _logger.LogInformation("Recording post-processing script completed with exit code {ExitCode}", exitCode); + } + finally + { + ((Process)sender).Dispose(); } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 8590c56df..3591384de 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; @@ -30,7 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private bool _hasExited; private Stream _logFileStream; private string _targetPath; - private IProcess _process; + private Process _process; private readonly IProcessFactory _processFactory; private readonly IJsonSerializer _json; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); @@ -80,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _targetPath = targetFile; Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - var process = _processFactory.Create(new ProcessOptions + _process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -91,14 +92,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV FileName = _mediaEncoder.EncoderPath, Arguments = GetCommandLineArgs(mediaSource, inputFile, targetFile, duration), - IsHidden = true, - ErrorDialog = false, - EnableRaisingEvents = true + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false }); - _process = process; - - var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; + var commandLineLogMessage = _process.StartInfo.FileName + " " + _process.StartInfo.Arguments; _logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); @@ -110,16 +108,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); - process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile); + _process.EnableRaisingEvents = true; + _process.Exited += (sender, args) => OnFfMpegProcessExited(_process, inputFile); - process.Start(); + _process.Start(); cancellationToken.Register(Stop); onStarted(); // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - StartStreamingLog(process.StandardError.BaseStream, _logFileStream); + StartStreamingLog(_process.StandardError.BaseStream, _logFileStream); _logger.LogInformation("ffmpeg recording process started for {0}", _targetPath); @@ -293,7 +292,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV /// /// Processes the exited. /// - private void OnFfMpegProcessExited(IProcess process, string inputFile) + private void OnFfMpegProcessExited(Process process, string inputFile) { _hasExited = true; diff --git a/MediaBrowser.Common/Extensions/ProcessExtensions.cs b/MediaBrowser.Common/Extensions/ProcessExtensions.cs new file mode 100644 index 000000000..9fa0efdff --- /dev/null +++ b/MediaBrowser.Common/Extensions/ProcessExtensions.cs @@ -0,0 +1,66 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.Extensions +{ + /// + /// Extension methods for . + /// + public static class ProcessExtensions + { + /// + /// Gets a value indicating whether the associated process has been terminated using + /// . This is safe to call even if there is no operating system process + /// associated with the . + /// + /// The process to check the exit status for. + /// + /// True if the operating system process referenced by the component has + /// terminated, or if there is no associated operating system process; otherwise, false. + /// + public static bool HasExitedSafe(this Process process) + { + try + { + return process.HasExited; + } + catch (InvalidOperationException) + { + return true; + } + } + + /// + /// Asynchronously wait for the process to exit. + /// + /// The process to wait for. + /// A timeout, in milliseconds, after which to stop waiting for the task. + /// True if the task exited normally, false if the timeout elapsed before the process exited. + public static async Task WaitForExitAsync(this Process process, int timeMs) + { + if (!process.EnableRaisingEvents) + { + throw new InvalidOperationException("EnableRisingEvents must be enabled to async wait for a task to exit."); + } + + // Add an event handler for the process exit event + var tcs = new TaskCompletionSource(); + process.Exited += (sender, args) => tcs.TrySetResult(true); + + // Return immediately if the process has already exited + if (process.HasExitedSafe()) + { + return true; + } + + // Add an additional timeout then await + using (var cancelTokenSource = new CancellationTokenSource(Math.Max(0, timeMs))) + using (var cancelRegistration = cancelTokenSource.Token.Register(() => tcs.TrySetResult(process.HasExitedSafe()))) + { + return await tcs.Task.ConfigureAwait(false); + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4123f0203..dbb7dea07 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -13,7 +13,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; @@ -22,6 +21,8 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; +using System.Diagnostics; +using MediaBrowser.Model.Diagnostics; namespace MediaBrowser.MediaEncoding.Encoder { @@ -362,7 +363,7 @@ namespace MediaBrowser.MediaEncoding.Encoder : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format"; args = string.Format(args, probeSizeArgument, inputPath).Trim(); - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -374,10 +375,10 @@ namespace MediaBrowser.MediaEncoding.Encoder Arguments = args, - IsHidden = true, + WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - EnableRaisingEvents = true }); + process.EnableRaisingEvents = true; if (forceEnableLogging) { @@ -571,16 +572,16 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, FileName = _ffmpegPath, Arguments = args, - IsHidden = true, + WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - EnableRaisingEvents = true }); + process.EnableRaisingEvents = true; _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -700,16 +701,16 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, FileName = _ffmpegPath, Arguments = args, - IsHidden = true, - ErrorDialog = false, - EnableRaisingEvents = true + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false }); + process.EnableRaisingEvents = true; _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments); @@ -949,14 +950,14 @@ namespace MediaBrowser.MediaEncoding.Encoder private bool _disposed = false; - public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder) + public ProcessWrapper(Process process, MediaEncoder mediaEncoder) { Process = process; _mediaEncoder = mediaEncoder; Process.Exited += OnProcessExited; } - public IProcess Process { get; } + public Process Process { get; } public bool HasExited { get; private set; } @@ -964,7 +965,7 @@ namespace MediaBrowser.MediaEncoding.Encoder void OnProcessExited(object sender, EventArgs e) { - var process = (IProcess)sender; + var process = (Process)sender; HasExited = true; @@ -979,7 +980,7 @@ namespace MediaBrowser.MediaEncoding.Encoder DisposeProcess(process); } - private void DisposeProcess(IProcess process) + private void DisposeProcess(Process process) { lock (_mediaEncoder._runningProcessesLock) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 6284e0fd9..50ff834c6 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -429,14 +430,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles encodingParam = " -sub_charenc " + encodingParam; } - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), - EnableRaisingEvents = true, - IsHidden = true, + WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }); @@ -453,6 +453,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } + process.EnableRaisingEvents = true; var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) @@ -578,14 +579,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles outputCodec, outputPath); - var process = _processFactory.Create(new ProcessOptions + var process = _processFactory.Create(new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, - EnableRaisingEvents = true, FileName = _mediaEncoder.EncoderPath, Arguments = processArgs, - IsHidden = true, + WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }); @@ -602,6 +602,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } + process.EnableRaisingEvents = true; var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) diff --git a/MediaBrowser.Model/Diagnostics/IProcess.cs b/MediaBrowser.Model/Diagnostics/IProcess.cs deleted file mode 100644 index 514d1e737..000000000 --- a/MediaBrowser.Model/Diagnostics/IProcess.cs +++ /dev/null @@ -1,23 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Model.Diagnostics -{ - public interface IProcess : IDisposable - { - event EventHandler Exited; - - void Kill(); - bool WaitForExit(int timeMs); - Task WaitForExitAsync(int timeMs); - int ExitCode { get; } - void Start(); - StreamWriter StandardInput { get; } - StreamReader StandardError { get; } - StreamReader StandardOutput { get; } - ProcessOptions StartInfo { get; } - } -} diff --git a/MediaBrowser.Model/Diagnostics/IProcessFactory.cs b/MediaBrowser.Model/Diagnostics/IProcessFactory.cs index 57082acc5..d95227797 100644 --- a/MediaBrowser.Model/Diagnostics/IProcessFactory.cs +++ b/MediaBrowser.Model/Diagnostics/IProcessFactory.cs @@ -1,24 +1,11 @@ #pragma warning disable CS1591 +using System.Diagnostics; + namespace MediaBrowser.Model.Diagnostics { public interface IProcessFactory { - IProcess Create(ProcessOptions options); - } - - public class ProcessOptions - { - public string FileName { get; set; } - public string Arguments { get; set; } - public string WorkingDirectory { get; set; } - public bool CreateNoWindow { get; set; } - public bool UseShellExecute { get; set; } - public bool EnableRaisingEvents { get; set; } - public bool ErrorDialog { get; set; } - public bool RedirectStandardError { get; set; } - public bool RedirectStandardInput { get; set; } - public bool RedirectStandardOutput { get; set; } - public bool IsHidden { get; set; } + Process Create(ProcessStartInfo options); } } -- cgit v1.2.3 From b947d98266371de7c9fd081e2038f53b3c67e859 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 00:45:48 +0100 Subject: Delete unnecessary ProcessFactory abstraction --- Emby.Server.Implementations/ApplicationHost.cs | 20 +++-------- .../Diagnostics/ProcessFactory.cs | 15 -------- .../LiveTv/EmbyTV/EmbyTV.cs | 14 +++----- .../LiveTv/EmbyTV/EncodedRecorder.cs | 40 ++++++++++------------ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 22 +++++------- .../Subtitles/SubtitleEncoder.cs | 18 ++++------ MediaBrowser.Model/Diagnostics/IProcessFactory.cs | 11 ------ 7 files changed, 44 insertions(+), 96 deletions(-) delete mode 100644 Emby.Server.Implementations/Diagnostics/ProcessFactory.cs delete mode 100644 MediaBrowser.Model/Diagnostics/IProcessFactory.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bc637b02f..f6c08bba8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -30,7 +30,6 @@ using Emby.Server.Implementations.Configuration; using Emby.Server.Implementations.Cryptography; using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Devices; -using Emby.Server.Implementations.Diagnostics; using Emby.Server.Implementations.Dto; using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer.Security; @@ -85,7 +84,6 @@ using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Cryptography; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; @@ -336,8 +334,6 @@ namespace Emby.Server.Implementations internal IImageEncoder ImageEncoder { get; private set; } - protected IProcessFactory ProcessFactory { get; private set; } - protected readonly IXmlSerializer XmlSerializer; protected ISocketFactory SocketFactory { get; private set; } @@ -685,9 +681,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(XmlSerializer); - ProcessFactory = new ProcessFactory(); - serviceCollection.AddSingleton(ProcessFactory); - serviceCollection.AddSingleton(typeof(IStreamHelper), typeof(StreamHelper)); var cryptoProvider = new CryptographyProvider(); @@ -748,7 +741,6 @@ namespace Emby.Server.Implementations LoggerFactory.CreateLogger(), ServerConfigurationManager, FileSystemManager, - ProcessFactory, LocalizationManager, () => SubtitleEncoder, startupConfig, @@ -868,8 +860,7 @@ namespace Emby.Server.Implementations FileSystemManager, MediaEncoder, HttpClient, - MediaSourceManager, - ProcessFactory); + MediaSourceManager); serviceCollection.AddSingleton(SubtitleEncoder); serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); @@ -1727,15 +1718,14 @@ namespace Emby.Server.Implementations throw new NotSupportedException(); } - var process = ProcessFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { FileName = url, UseShellExecute = true, ErrorDialog = false - }); - - process.EnableRaisingEvents = true; - process.Exited += (sender, args) => ((Process)sender).Dispose(); ; + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; + process.Exited += (sender, args) => ((Process)sender).Dispose(); try { diff --git a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs b/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs deleted file mode 100644 index 00172e17a..000000000 --- a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -#pragma warning disable CS1591 - -using System.Diagnostics; -using MediaBrowser.Model.Diagnostics; - -namespace Emby.Server.Implementations.Diagnostics -{ - public class ProcessFactory : IProcessFactory - { - public Process Create(ProcessStartInfo startInfo) - { - return new Process { StartInfo = startInfo }; - } - } -} diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 0f54022c8..e2ca0986b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -26,7 +26,6 @@ using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; @@ -62,7 +61,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly ILibraryManager _libraryManager; private readonly IProviderManager _providerManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IProcessFactory _processFactory; private readonly IMediaSourceManager _mediaSourceManager; private readonly IStreamHelper _streamHelper; @@ -89,8 +87,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, - IMediaEncoder mediaEncoder, - IProcessFactory processFactory) + IMediaEncoder mediaEncoder) { Current = this; @@ -103,7 +100,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _libraryMonitor = libraryMonitor; _providerManager = providerManager; _mediaEncoder = mediaEncoder; - _processFactory = processFactory; _liveTvManager = (LiveTvManager)liveTvManager; _jsonSerializer = jsonSerializer; _mediaSourceManager = mediaSourceManager; @@ -1663,7 +1659,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (mediaSource.RequiresLooping || !(mediaSource.Container ?? string.Empty).EndsWith("ts", StringComparison.OrdinalIgnoreCase) || (mediaSource.Protocol != MediaProtocol.File && mediaSource.Protocol != MediaProtocol.Http)) { - return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config); + return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _config); } return new DirectRecorder(_logger, _httpClient, _streamHelper); @@ -1684,7 +1680,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { Arguments = GetPostProcessArguments(path, options.RecordingPostProcessorArguments), CreateNoWindow = true, @@ -1692,11 +1688,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV FileName = options.RecordingPostProcessor, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false - }); + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogInformation("Running recording post processor {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - process.EnableRaisingEvents = true; process.Exited += Process_Exited; process.Start(); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3591384de..55d1f810b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -15,7 +15,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; @@ -32,7 +31,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private Stream _logFileStream; private string _targetPath; private Process _process; - private readonly IProcessFactory _processFactory; private readonly IJsonSerializer _json; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); private readonly IServerConfigurationManager _config; @@ -42,14 +40,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, - IProcessFactory processFactory, IServerConfigurationManager config) { _logger = logger; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; - _processFactory = processFactory; _config = config; } @@ -81,7 +77,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _targetPath = targetFile; Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - _process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -94,7 +90,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false - }); + }; + _process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; var commandLineLogMessage = _process.StartInfo.FileName + " " + _process.StartInfo.Arguments; _logger.LogInformation(commandLineLogMessage); @@ -108,7 +105,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); - _process.EnableRaisingEvents = true; _process.Exited += (sender, args) => OnFfMpegProcessExited(_process, inputFile); _process.Start(); @@ -297,24 +293,24 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _hasExited = true; _logFileStream?.Dispose(); - _logFileStream = null; + _logFileStream = null; - var exitCode = process.ExitCode; + var exitCode = process.ExitCode; - _logger.LogInformation("FFMpeg recording exited with code {ExitCode} for {Path}", exitCode, _targetPath); + _logger.LogInformation("FFMpeg recording exited with code {ExitCode} for {Path}", exitCode, _targetPath); - if (exitCode == 0) - { - _taskCompletionSource.TrySetResult(true); - } - else - { - _taskCompletionSource.TrySetException( - new Exception( - string.Format( - CultureInfo.InvariantCulture, - "Recording for {0} failed. Exit code {1}", - _targetPath, + if (exitCode == 0) + { + _taskCompletionSource.TrySetResult(true); + } + else + { + _taskCompletionSource.TrySetException( + new Exception( + string.Format( + CultureInfo.InvariantCulture, + "Recording for {0} failed. Exit code {1}", + _targetPath, exitCode))); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index dbb7dea07..62a6c69ca 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -22,7 +22,6 @@ using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using System.Diagnostics; -using MediaBrowser.Model.Diagnostics; namespace MediaBrowser.MediaEncoding.Encoder { @@ -39,7 +38,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly ILogger _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; - private readonly IProcessFactory _processFactory; private readonly ILocalizationManager _localization; private readonly Func _subtitleEncoder; private readonly IConfiguration _configuration; @@ -59,7 +57,6 @@ namespace MediaBrowser.MediaEncoding.Encoder ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, - IProcessFactory processFactory, ILocalizationManager localization, Func subtitleEncoder, IConfiguration configuration, @@ -68,7 +65,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger = logger; _configurationManager = configurationManager; _fileSystem = fileSystem; - _processFactory = processFactory; _localization = localization; _startupOptionFFmpegPath = startupOptionsFFmpegPath; _subtitleEncoder = subtitleEncoder; @@ -363,7 +359,7 @@ namespace MediaBrowser.MediaEncoding.Encoder : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format"; args = string.Format(args, probeSizeArgument, inputPath).Trim(); - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -377,8 +373,8 @@ namespace MediaBrowser.MediaEncoding.Encoder WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - }); - process.EnableRaisingEvents = true; + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; if (forceEnableLogging) { @@ -572,7 +568,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -580,8 +576,8 @@ namespace MediaBrowser.MediaEncoding.Encoder Arguments = args, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - }); - process.EnableRaisingEvents = true; + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -701,7 +697,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -709,8 +705,8 @@ namespace MediaBrowser.MediaEncoding.Encoder Arguments = args, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false - }); - process.EnableRaisingEvents = true; + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 50ff834c6..e2be2ea57 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -13,7 +13,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; @@ -32,7 +31,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IMediaEncoder _mediaEncoder; private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IProcessFactory _processFactory; public SubtitleEncoder( ILibraryManager libraryManager, @@ -41,8 +39,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles IFileSystem fileSystem, IMediaEncoder mediaEncoder, IHttpClient httpClient, - IMediaSourceManager mediaSourceManager, - IProcessFactory processFactory) + IMediaSourceManager mediaSourceManager) { _libraryManager = libraryManager; _logger = logger; @@ -51,7 +48,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles _mediaEncoder = mediaEncoder; _httpClient = httpClient; _mediaSourceManager = mediaSourceManager; - _processFactory = processFactory; } private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); @@ -430,7 +426,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles encodingParam = " -sub_charenc " + encodingParam; } - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -438,7 +434,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false - }); + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -453,7 +450,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } - process.EnableRaisingEvents = true; var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) @@ -579,7 +575,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles outputCodec, outputPath); - var process = _processFactory.Create(new ProcessStartInfo + var processStartInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, @@ -587,7 +583,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles Arguments = processArgs, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false - }); + }; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -602,7 +599,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } - process.EnableRaisingEvents = true; var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) diff --git a/MediaBrowser.Model/Diagnostics/IProcessFactory.cs b/MediaBrowser.Model/Diagnostics/IProcessFactory.cs deleted file mode 100644 index d95227797..000000000 --- a/MediaBrowser.Model/Diagnostics/IProcessFactory.cs +++ /dev/null @@ -1,11 +0,0 @@ -#pragma warning disable CS1591 - -using System.Diagnostics; - -namespace MediaBrowser.Model.Diagnostics -{ - public interface IProcessFactory - { - Process Create(ProcessStartInfo options); - } -} -- cgit v1.2.3 From 7447ea89609fe79be3c5d282a23fc6d7d2bddd66 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 00:49:22 +0100 Subject: Make sure Process objects are all disposed correctly --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 13 ++++++++++--- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 6 ++---- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 55d1f810b..46fb47b7b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -290,9 +290,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV /// private void OnFfMpegProcessExited(Process process, string inputFile) { - _hasExited = true; + try + { + _hasExited = true; - _logFileStream?.Dispose(); + _logFileStream?.Dispose(); _logFileStream = null; var exitCode = process.ExitCode; @@ -311,7 +313,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV CultureInfo.InvariantCulture, "Recording for {0} failed. Exit code {1}", _targetPath, - exitCode))); + exitCode))); + } + } + finally + { + process.Dispose(); } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index e2be2ea57..1736d79cf 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -436,6 +436,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles ErrorDialog = false }; var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; + process.Exited += (sender, args) => ((Process)sender).Dispose(); _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -468,8 +469,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles var exitCode = ranToCompletion ? process.ExitCode : -1; - process.Dispose(); - var failed = false; if (exitCode == -1) @@ -585,6 +584,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles ErrorDialog = false }; var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; + process.Exited += (sender, args) => ((Process)sender).Dispose(); _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -617,8 +617,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles var exitCode = ranToCompletion ? process.ExitCode : -1; - process.Dispose(); - var failed = false; if (exitCode == -1) -- cgit v1.2.3 From 97c36d11d4e52a8f33d48e382467b6c6068bb6ad Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 01:09:09 +0100 Subject: Use a TimeSpan instead of ms and support providing a custom CancellationToken --- .../Extensions/ProcessExtensions.cs | 23 +++++++++++++++++----- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 ++-- .../Subtitles/SubtitleEncoder.cs | 4 ++-- 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Common/Extensions/ProcessExtensions.cs b/MediaBrowser.Common/Extensions/ProcessExtensions.cs index 9fa0efdff..938ced106 100644 --- a/MediaBrowser.Common/Extensions/ProcessExtensions.cs +++ b/MediaBrowser.Common/Extensions/ProcessExtensions.cs @@ -36,9 +36,23 @@ namespace MediaBrowser.Common.Extensions /// Asynchronously wait for the process to exit. /// /// The process to wait for. - /// A timeout, in milliseconds, after which to stop waiting for the task. + /// The duration to wait before cancelling waiting for the task. /// True if the task exited normally, false if the timeout elapsed before the process exited. - public static async Task WaitForExitAsync(this Process process, int timeMs) + public static async Task WaitForExitAsync(this Process process, TimeSpan timeout) + { + using (var cancelTokenSource = new CancellationTokenSource(timeout)) + { + return await WaitForExitAsync(process, cancelTokenSource.Token); + } + } + + /// + /// Asynchronously wait for the process to exit. + /// + /// The process to wait for. + /// A to observe while waiting for the process to exit. + /// True if the task exited normally, false if cancelled before the process exited. + public static async Task WaitForExitAsync(this Process process, CancellationToken cancelToken) { if (!process.EnableRaisingEvents) { @@ -55,9 +69,8 @@ namespace MediaBrowser.Common.Extensions return true; } - // Add an additional timeout then await - using (var cancelTokenSource = new CancellationTokenSource(Math.Max(0, timeMs))) - using (var cancelRegistration = cancelTokenSource.Token.Register(() => tcs.TrySetResult(process.HasExitedSafe()))) + // Register with the cancellation token then await + using (var cancelRegistration = cancelToken.Register(() => tcs.TrySetResult(process.HasExitedSafe()))) { return await tcs.Task.ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62a6c69ca..855b1c754 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -596,7 +596,7 @@ namespace MediaBrowser.MediaEncoding.Encoder timeoutMs = DefaultImageExtractionTimeout; } - ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false); + ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMilliseconds(timeoutMs)).ConfigureAwait(false); if (!ranToCompletion) { @@ -729,7 +729,7 @@ namespace MediaBrowser.MediaEncoding.Encoder while (isResponsive) { - if (await process.WaitForExitAsync(30000).ConfigureAwait(false)) + if (await process.WaitForExitAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false)) { ranToCompletion = true; break; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 1736d79cf..f1f0bfeb1 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -451,7 +451,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } - var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); + var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); if (!ranToCompletion) { @@ -599,7 +599,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } - var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); + var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); if (!ranToCompletion) { -- cgit v1.2.3 From 48bbcbb426b15724ccae05c71d418c8ce80cfb68 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 01:09:25 +0100 Subject: Use WaitForExitAsync extension method in AttachmentExtractor --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index c530c9fd8..cb1d8d7bb 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -166,19 +166,15 @@ namespace MediaBrowser.MediaEncoding.Attachments }; var process = new Process { - StartInfo = startInfo + StartInfo = startInfo, + EnableRaisingEvents = true }; _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); process.Start(); - var processTcs = new TaskCompletionSource(); - process.EnableRaisingEvents = true; - process.Exited += (sender, args) => processTcs.TrySetResult(true); - var unregister = cancellationToken.Register(() => processTcs.TrySetResult(process.HasExited)); - var ranToCompletion = await processTcs.Task.ConfigureAwait(false); - unregister.Dispose(); + var ranToCompletion = await process.WaitForExitAsync(cancellationToken); if (!ranToCompletion) { -- cgit v1.2.3 From d705931e816db63b560efad51b8d0b79564aa260 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 01:42:28 +0100 Subject: Dispose of process correctly in AttachmentExtractor --- .../Attachments/AttachmentExtractor.cs | 40 ++++++++++------------ 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index cb1d8d7bb..d97634731 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -164,34 +164,32 @@ namespace MediaBrowser.MediaEncoding.Attachments WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }; - var process = new Process - { - StartInfo = startInfo, - EnableRaisingEvents = true - }; - _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); + int exitCode; - process.Start(); + using (var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }) + { + _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); - var ranToCompletion = await process.WaitForExitAsync(cancellationToken); + process.Start(); - if (!ranToCompletion) - { - try - { - _logger.LogWarning("Killing ffmpeg attachment extraction process"); - process.Kill(); - } - catch (Exception ex) + var ranToCompletion = await process.WaitForExitAsync(cancellationToken); + + if (!ranToCompletion) { - _logger.LogError(ex, "Error killing attachment extraction process"); + try + { + _logger.LogWarning("Killing ffmpeg attachment extraction process"); + process.Kill(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error killing attachment extraction process"); + } } - } - - var exitCode = ranToCompletion ? process.ExitCode : -1; - process.Dispose(); + exitCode = ranToCompletion ? process.ExitCode : -1; + } var failed = false; -- cgit v1.2.3 From 1f5caa46c53dde25ecf4482715333c049cb7e085 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 27 Mar 2020 01:53:08 +0100 Subject: Fix some more issues with disposing Process instances --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 8 +- .../Subtitles/SubtitleEncoder.cs | 94 ++++++++++++---------- 2 files changed, 54 insertions(+), 48 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 855b1c754..b3a45991e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -577,10 +577,10 @@ namespace MediaBrowser.MediaEncoding.Encoder WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; - _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + _logger.LogDebug("{0} {1}", processStartInfo.FileName, processStartInfo.Arguments); + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; using (var processWrapper = new ProcessWrapper(process, this)) { bool ranToCompletion; @@ -706,14 +706,14 @@ namespace MediaBrowser.MediaEncoding.Encoder WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; - _logger.LogInformation(process.StartInfo.FileName + " " + process.StartInfo.Arguments); + _logger.LogInformation(processStartInfo.FileName + " " + processStartInfo.Arguments); await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); bool ranToCompletion = false; + var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; using (var processWrapper = new ProcessWrapper(process, this)) { try diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f1f0bfeb1..a6982be5b 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -435,39 +435,42 @@ namespace MediaBrowser.MediaEncoding.Subtitles WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; - process.Exited += (sender, args) => ((Process)sender).Dispose(); - _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + int exitCode; - try - { - process.Start(); - } - catch (Exception ex) + using (var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }) { - _logger.LogError(ex, "Error starting ffmpeg"); - - throw; - } + _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); - - if (!ranToCompletion) - { try { - _logger.LogInformation("Killing ffmpeg subtitle conversion process"); - - process.Kill(); + process.Start(); } catch (Exception ex) { - _logger.LogError(ex, "Error killing subtitle conversion process"); + _logger.LogError(ex, "Error starting ffmpeg"); + + throw; } - } - var exitCode = ranToCompletion ? process.ExitCode : -1; + var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); + + if (!ranToCompletion) + { + try + { + _logger.LogInformation("Killing ffmpeg subtitle conversion process"); + + process.Kill(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error killing subtitle conversion process"); + } + } + + exitCode = ranToCompletion ? process.ExitCode : -1; + } var failed = false; @@ -583,39 +586,42 @@ namespace MediaBrowser.MediaEncoding.Subtitles WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; - process.Exited += (sender, args) => ((Process)sender).Dispose(); - _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); + int exitCode; - try - { - process.Start(); - } - catch (Exception ex) + using (var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }) { - _logger.LogError(ex, "Error starting ffmpeg"); - - throw; - } + _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); - var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); - - if (!ranToCompletion) - { try { - _logger.LogWarning("Killing ffmpeg subtitle extraction process"); - - process.Kill(); + process.Start(); } catch (Exception ex) { - _logger.LogError(ex, "Error killing subtitle extraction process"); + _logger.LogError(ex, "Error starting ffmpeg"); + + throw; } - } - var exitCode = ranToCompletion ? process.ExitCode : -1; + var ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMinutes(5)).ConfigureAwait(false); + + if (!ranToCompletion) + { + try + { + _logger.LogWarning("Killing ffmpeg subtitle extraction process"); + + process.Kill(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error killing subtitle extraction process"); + } + } + + exitCode = ranToCompletion ? process.ExitCode : -1; + } var failed = false; -- cgit v1.2.3 From 0af353404cfbd941cdf7c8f334292db6c38ec74a Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Mon, 30 Mar 2020 14:46:05 +0800 Subject: fix the UTF-16 error while burning ass/ssa subtitles --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 4 +++- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index c6748d712..e22934f79 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -946,7 +946,7 @@ namespace MediaBrowser.Api.Playback.Hls gopArg = string.Format( CultureInfo.InvariantCulture, " -g {0} -keyint_min {0} -sc_threshold 0", - state.SegmentLength * Math.Ceiling(Convert.ToDecimal(framerate)) + Math.Ceiling(state.SegmentLength * framerate.Value) ); } @@ -980,6 +980,8 @@ namespace MediaBrowser.Api.Playback.Hls args += EncodingHelper.GetGraphicalSubtitleParam(state, encodingOptions, codec); } + // -start_at_zero is necessary to use with -ss when seeking, + // otherwise the target position cannot be determined. if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)) { args += " -start_at_zero"; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index a4a7595d2..5c2dc927b 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -730,6 +730,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles { var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName; + // UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding + if ((path.EndsWith(".ass") || path.EndsWith(".ssa")) + && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase) + || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase))) + { + charset = ""; + } + _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); return charset; -- cgit v1.2.3 From db2366066029fa8e261d308d9db845070c0b9ca4 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Mon, 30 Mar 2020 15:53:49 +0800 Subject: prefer to use libfdk_aac for better audio quality --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 5 +++++ MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 1 + 2 files changed, 6 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 342c76414..2037a27fa 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -424,6 +424,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase)) { + // Prefer to use libfdk_aac for better audio quality while using the custom build FFmpeg + if (_mediaEncoder.SupportsEncoder("libfdk_aac")) + { + return "libfdk_aac"; + } return "aac -strict experimental"; } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f5decdc0d..6e036d24c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -42,6 +42,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "libvpx", "libvpx-vp9", "aac", + "libfdk_aac", "libmp3lame", "libopus", "libvorbis", -- cgit v1.2.3 From 0e195d2e49f4ee9979182603a356fdb7af8d98cf Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 3 Apr 2020 20:20:55 -0400 Subject: Add missing call to ConfigureAwait() --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index d97634731..48240d5b6 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.MediaEncoding.Attachments process.Start(); - var ranToCompletion = await process.WaitForExitAsync(cancellationToken); + var ranToCompletion = await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); if (!ranToCompletion) { -- cgit v1.2.3 From 17e8813378c2fe1a83d1eddb829dae68f8c71bfe Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 11 Apr 2020 10:53:13 -0400 Subject: Use ActivatorUtilities to construct MediaEncoder and update constructor to inject EncodingHelper correctly --- Emby.Server.Implementations/ApplicationHost.cs | 16 ++++------------ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5b93981f0..ad0a69b19 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -88,7 +88,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -106,7 +105,6 @@ using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; @@ -614,17 +612,11 @@ namespace Emby.Server.Implementations serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(); - // TODO: Add StartupOptions.FFmpegPath to IConfiguration so this doesn't need to be constructed manually + // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required + // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(provider => - new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - provider.GetRequiredService>(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService, - provider.GetRequiredService(), - _startupOptions.FFmpegPath)); + ActivatorUtilities.CreateInstance(provider, _startupOptions.FFmpegPath ?? string.Empty)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f3f2b86ee..c5bba8780 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -40,8 +40,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IFileSystem _fileSystem; private readonly IProcessFactory _processFactory; private readonly ILocalizationManager _localization; - private readonly Func _subtitleEncoder; - private readonly IConfiguration _configuration; + private readonly Lazy _encodingHelperFactory; private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); @@ -49,8 +48,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); - private EncodingHelper _encodingHelper; - private string _ffmpegPath; private string _ffprobePath; @@ -60,8 +57,7 @@ namespace MediaBrowser.MediaEncoding.Encoder IFileSystem fileSystem, IProcessFactory processFactory, ILocalizationManager localization, - Func subtitleEncoder, - IConfiguration configuration, + Lazy encodingHelperFactory, string startupOptionsFFmpegPath) { _logger = logger; @@ -69,15 +65,11 @@ namespace MediaBrowser.MediaEncoding.Encoder _fileSystem = fileSystem; _processFactory = processFactory; _localization = localization; + _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = startupOptionsFFmpegPath; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; } - private EncodingHelper EncodingHelper - => LazyInitializer.EnsureInitialized( - ref _encodingHelper, - () => new EncodingHelper(this, _fileSystem, _subtitleEncoder(), _configuration)); + private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; /// public string EncoderPath => _ffmpegPath; -- cgit v1.2.3 From 7152b55747f508e69bb6417bd583ba15c0e591a4 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 11 Apr 2020 13:25:50 -0400 Subject: Use a separate line for each property initializer --- Emby.Server.Implementations/ApplicationHost.cs | 13 ++++-- .../LiveTv/EmbyTV/EmbyTV.cs | 21 +++++---- .../LiveTv/EmbyTV/EncodedRecorder.cs | 8 +++- .../Attachments/AttachmentExtractor.cs | 23 +++++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 54 +++++++++++++--------- .../Subtitles/SubtitleEncoder.cs | 48 ++++++++++--------- 6 files changed, 97 insertions(+), 70 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 2f7c0a3eb..12423361a 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1700,13 +1700,16 @@ namespace Emby.Server.Implementations throw new NotSupportedException(); } - var processStartInfo = new ProcessStartInfo + var process = new Process { - FileName = url, - UseShellExecute = true, - ErrorDialog = false + StartInfo = new ProcessStartInfo + { + FileName = url, + UseShellExecute = true, + ErrorDialog = false + }, + EnableRaisingEvents = true }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; process.Exited += (sender, args) => ((Process)sender).Dispose(); try diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 4d777081b..900f12062 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1680,16 +1680,19 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - var processStartInfo = new ProcessStartInfo - { - Arguments = GetPostProcessArguments(path, options.RecordingPostProcessorArguments), - CreateNoWindow = true, - ErrorDialog = false, - FileName = options.RecordingPostProcessor, - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = false + var process = new Process + { + StartInfo = new ProcessStartInfo + { + Arguments = GetPostProcessArguments(path, options.RecordingPostProcessorArguments), + CreateNoWindow = true, + ErrorDialog = false, + FileName = options.RecordingPostProcessor, + WindowStyle = ProcessWindowStyle.Hidden, + UseShellExecute = false + }, + EnableRaisingEvents = true }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; _logger.LogInformation("Running recording post processor {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 4738272be..29d17e2bb 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -90,9 +90,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }; - _process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; - var commandLineLogMessage = _process.StartInfo.FileName + " " + _process.StartInfo.Arguments; + var commandLineLogMessage = processStartInfo.FileName + " " + processStartInfo.Arguments; _logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); @@ -104,6 +103,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); + _process = new Process + { + StartInfo = processStartInfo, + EnableRaisingEvents = true + }; _process.Exited += (sender, args) => OnFfMpegProcessExited(_process, inputFile); _process.Start(); diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 8d27c33c0..84eb3b373 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -155,19 +155,22 @@ namespace MediaBrowser.MediaEncoding.Attachments inputPath, attachmentStreamIndex, outputPath); - var startInfo = new ProcessStartInfo - { - Arguments = processArgs, - FileName = _mediaEncoder.EncoderPath, - UseShellExecute = false, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }; int exitCode; - using (var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }) + using (var process = new Process + { + StartInfo = new ProcessStartInfo + { + Arguments = processArgs, + FileName = _mediaEncoder.EncoderPath, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4042e64f6..c2bfac9d6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -359,30 +359,33 @@ namespace MediaBrowser.MediaEncoding.Encoder : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format"; args = string.Format(args, probeSizeArgument, inputPath).Trim(); - var processStartInfo = new ProcessStartInfo + var process = new Process { - CreateNoWindow = true, - UseShellExecute = false, + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, - // Must consume both or ffmpeg may hang due to deadlocks. See comments below. - RedirectStandardOutput = true, + // Must consume both or ffmpeg may hang due to deadlocks. See comments below. + RedirectStandardOutput = true, - FileName = _ffprobePath, - Arguments = args, + FileName = _ffprobePath, + Arguments = args, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + }, + EnableRaisingEvents = true }; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; if (forceEnableLogging) { - _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + _logger.LogInformation("{ProcessFileName} {ProcessArgs}", process.StartInfo.FileName, process.StartInfo.Arguments); } else { - _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + _logger.LogDebug("{ProcessFileName} {ProcessArgs}", process.StartInfo.FileName, process.StartInfo.Arguments); } using (var processWrapper = new ProcessWrapper(process, this)) @@ -568,19 +571,22 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var processStartInfo = new ProcessStartInfo + var process = new Process { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _ffmpegPath, - Arguments = args, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false, + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = _ffmpegPath, + Arguments = args, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + }, + EnableRaisingEvents = true }; - _logger.LogDebug("{0} {1}", processStartInfo.FileName, processStartInfo.Arguments); + _logger.LogDebug("{ProcessFileName} {ProcessArguments}", process.StartInfo.FileName, process.StartInfo.Arguments); - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; using (var processWrapper = new ProcessWrapper(process, this)) { bool ranToCompletion; @@ -713,7 +719,11 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion = false; - var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }; + var process = new Process + { + StartInfo = processStartInfo, + EnableRaisingEvents = true + }; using (var processWrapper = new ProcessWrapper(process, this)) { try diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index b1397d79d..a84dc30c8 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -426,19 +426,21 @@ namespace MediaBrowser.MediaEncoding.Subtitles encodingParam = " -sub_charenc " + encodingParam; } - var processStartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }; - int exitCode; - using (var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }) + using (var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -577,19 +579,21 @@ namespace MediaBrowser.MediaEncoding.Subtitles outputCodec, outputPath); - var processStartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = processArgs, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }; - int exitCode; - using (var process = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true }) + using (var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = processArgs, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); -- cgit v1.2.3 From 411328827808e115ce207f4c985c9dea1c7211e7 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 11 Apr 2020 13:46:31 -0400 Subject: Fix style issues --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 3 +- .../Attachments/AttachmentExtractor.cs | 22 +++++------ .../Subtitles/SubtitleEncoder.cs | 44 +++++++++++----------- 3 files changed, 35 insertions(+), 34 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 29d17e2bb..bc86cc59a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -293,7 +293,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV /// private void OnFfMpegProcessExited(Process process, string inputFile) { - using (process) { + using (process) + { _hasExited = true; _logFileStream?.Dispose(); diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 84eb3b373..3f177a9fa 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -159,18 +159,18 @@ namespace MediaBrowser.MediaEncoding.Attachments int exitCode; using (var process = new Process - { - StartInfo = new ProcessStartInfo { - Arguments = processArgs, - FileName = _mediaEncoder.EncoderPath, - UseShellExecute = false, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - EnableRaisingEvents = true - }) + StartInfo = new ProcessStartInfo + { + Arguments = processArgs, + FileName = _mediaEncoder.EncoderPath, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index a84dc30c8..ba171295e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -429,18 +429,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles int exitCode; using (var process = new Process - { - StartInfo = new ProcessStartInfo { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - EnableRaisingEvents = true - }) + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -582,18 +582,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles int exitCode; using (var process = new Process - { - StartInfo = new ProcessStartInfo { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = processArgs, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - EnableRaisingEvents = true - }) + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = processArgs, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); -- cgit v1.2.3 From a73e1f18b670ac7c9f0f9c3049e7fbbeddb61942 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 19 Apr 2020 11:16:09 +0200 Subject: Minor improvements --- MediaBrowser.Api/UserLibrary/ItemsService.cs | 4 ++-- MediaBrowser.Controller/Entities/BaseItem.cs | 5 ++--- MediaBrowser.Controller/Entities/Folder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index ac59c3030..c4d44042b 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -242,11 +242,11 @@ namespace MediaBrowser.Api.UserLibrary return folder.GetItems(GetItemsQuery(request, dtoOptions, user)); } - var itemsArray = folder.GetChildren(user, true).ToArray(); + var itemsArray = folder.GetChildren(user, true); return new QueryResult { Items = itemsArray, - TotalRecordCount = itemsArray.Length, + TotalRecordCount = itemsArray.Count, StartIndex = 0 }; } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 56a361e0e..b9e1fe79d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2741,7 +2741,7 @@ namespace MediaBrowser.Controller.Entities { var list = GetEtagValues(user); - return string.Join("|", list.ToArray()).GetMD5().ToString("N", CultureInfo.InvariantCulture); + return string.Join("|", list).GetMD5().ToString("N", CultureInfo.InvariantCulture); } protected virtual List GetEtagValues(User user) @@ -2784,8 +2784,7 @@ namespace MediaBrowser.Controller.Entities return true; } - var view = this as IHasCollectionType; - if (view != null) + if (this is IHasCollectionType view) { if (string.Equals(view.CollectionType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index bb48605e5..a468e0c35 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -864,7 +864,7 @@ namespace MediaBrowser.Controller.Entities return SortItemsByRequest(query, result); } - return result.ToArray(); + return result; } return GetItemsInternal(query).Items; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index c2bfac9d6..359330449 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -478,7 +478,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex) { - _logger.LogError(ex, "I-frame image extraction failed, will attempt standard way. Input: {arguments}", inputArgument); + _logger.LogError(ex, "I-frame image extraction failed, will attempt standard way. Input: {Arguments}", inputArgument); } } @@ -969,7 +969,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public int? ExitCode { get; private set; } - void OnProcessExited(object sender, EventArgs e) + private void OnProcessExited(object sender, EventArgs e) { var process = (Process)sender; -- cgit v1.2.3 From c5f163293fb29145245393b976f02aae53217944 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Tue, 21 Apr 2020 16:21:09 -0400 Subject: Add properties to all project files This is required for SonarCloud analysis to run --- DvdLib/DvdLib.csproj | 5 +++++ Emby.Dlna/Emby.Dlna.csproj | 5 +++++ Emby.Drawing/Emby.Drawing.csproj | 5 +++++ Emby.Naming/Emby.Naming.csproj | 5 +++++ Emby.Notifications/Emby.Notifications.csproj | 5 +++++ Emby.Photos/Emby.Photos.csproj | 6 ++++++ Emby.Server.Implementations/Emby.Server.Implementations.csproj | 5 +++++ Jellyfin.Api/Jellyfin.Api.csproj | 5 +++++ Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 5 +++++ Jellyfin.Server/Jellyfin.Server.csproj | 5 +++++ MediaBrowser.Api/MediaBrowser.Api.csproj | 5 +++++ MediaBrowser.Common/MediaBrowser.Common.csproj | 5 +++++ MediaBrowser.Controller/MediaBrowser.Controller.csproj | 5 +++++ MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj | 5 +++++ MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 5 +++++ MediaBrowser.Model/MediaBrowser.Model.csproj | 5 +++++ MediaBrowser.Providers/MediaBrowser.Providers.csproj | 5 +++++ MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 5 +++++ MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 5 +++++ RSSDP/RSSDP.csproj | 5 +++++ tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 5 +++++ tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 5 +++++ tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj | 5 +++++ .../Jellyfin.MediaEncoding.Tests.csproj | 5 +++++ tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 5 +++++ .../Jellyfin.Server.Implementations.Tests.csproj | 5 +++++ 26 files changed, 131 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index f4df6a9f5..72a50124b 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -1,5 +1,10 @@ + + + {713F42B5-878E-499D-A878-E4C652B1D5E8} + + diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 0cabe43d5..42a5f95c1 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -1,5 +1,10 @@ + + + {805844AB-E92F-45E6-9D99-4F6D48D129A5} + + diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index b7090b262..f48507b34 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -1,5 +1,10 @@ + + + {08FFF49B-F175-4807-A2B5-73B0EBD9F716} + + netstandard2.1 false diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 4e08170a4..c017e76c7 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -1,5 +1,10 @@  + + + {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2} + + netstandard2.1 false diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index e6bf785bf..1d430a5e5 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -1,5 +1,10 @@ + + + {2E030C33-6923-4530-9E54-FA29FA6AD1A9} + + netstandard2.1 false diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index cc3fbb43f..dbe01257f 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -1,4 +1,10 @@ + + + + {89AB4548-770D-41FD-A891-8DAFF44F452C} + + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index d46b9507b..765aa1759 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -1,5 +1,10 @@  + + + {E383961B-9356-4D5D-8233-9A1079D03055} + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 8f23ef9d0..a582a209c 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -1,5 +1,10 @@ + + + {DFBEFB4C-DA19-4143-98B7-27320C7F7163} + + netstandard2.1 true diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index d0a99e1e2..6326278f5 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -1,5 +1,10 @@ + + + {154872D9-6C12-4007-96E3-8F70A58386CE} + + netstandard2.1 false diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 02ae202b4..270cdeaaf 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -1,5 +1,10 @@ + + + {07E39F42-A2C6-4B32-AF8C-725F957A73FF} + + jellyfin Exe diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 0d62cf8c5..d703bdb05 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -1,5 +1,10 @@ + + + {4FD51AC5-2C16-4308-A993-C3A84F3B4582} + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 3b0347802..69864106c 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -1,5 +1,10 @@  + + + {9142EEFA-7570-41E1-BFCC-468BB571AF2F} + + Jellyfin Contributors Jellyfin.Common diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 662ab2535..4e7d02737 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -1,5 +1,10 @@ + + + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2} + + Jellyfin Contributors Jellyfin.Controller diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 71eb62693..24104d779 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -1,5 +1,10 @@ + + + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392} + + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index a312dcd70..af8bee301 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -1,5 +1,10 @@  + + + {960295EE-4AF4-4440-A525-B4C295B01A61} + + netstandard2.1 false diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 27486c68f..b41d0af1d 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -1,5 +1,10 @@ + + + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B} + + Jellyfin Contributors Jellyfin.Model diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 330a4d1e5..1b3df63b6 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -1,5 +1,10 @@  + + + {442B5058-DCAF-4263-BB6A-F21E31120A1B} + + diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index da52b852a..bcaee50f2 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1,5 +1,10 @@ + + + {5624B7B5-B5A7-41D8-9F10-CC5611109619} + + diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index e26282095..45fd9add9 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -1,5 +1,10 @@ + + + {23499896-B135-4527-8574-C26E926EA99E} + + diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 9753ae9b1..e3f3127b6 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -1,5 +1,10 @@ + + + {21002819-C39A-4D3E-BE83-2A276A77FB1F} + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index b159db2bd..fb76f34d0 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -1,5 +1,10 @@ + + + {A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 81a2242e7..cd41c5604 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -1,5 +1,10 @@ + + + {DF194677-DFD3-42AF-9F75-D44D5A416478} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 30994dee6..407fe2eda 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -1,5 +1,10 @@ + + + {462584F7-5023-4019-9EAC-B98CA458C0A0} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 78a020ad5..276c50ca3 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -1,5 +1,10 @@ + + + {28464062-0939-4AA7-9F7B-24DDDA61A7C0} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index f404b3e46..ac0c970c1 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -1,5 +1,10 @@ + + + {3998657B-1CCC-49DD-A19F-275DC8495F57} + + netcoreapp3.1 false diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index b7865439c..ba7ecb3d1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -1,5 +1,10 @@  + + + {2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE} + + netcoreapp3.1 false -- cgit v1.2.3 From 8f02fb9a4f062e2b6d980b6645a85e2681298dfa Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Wed, 22 Apr 2020 13:09:59 -0400 Subject: Remove unused usings This addresses the new issues identified in SonarCloud analysis --- Emby.Drawing/ImageProcessor.cs | 1 - MediaBrowser.Common/IApplicationHost.cs | 2 -- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - 3 files changed, 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 903b958a4..ba14b4dca 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -8,7 +8,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index eabf8f3d7..e8d9282e4 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Updates; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace MediaBrowser.Common diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 2cc89b0dc..992ad146d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -19,7 +19,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.Diagnostics; -- cgit v1.2.3 From cee587d6e358cbb16b8cd27b55f492c145476c5a Mon Sep 17 00:00:00 2001 From: Max Git Date: Mon, 27 Apr 2020 03:25:57 +0200 Subject: Try harder to find ffmpeg in app directory. While here do some cleanup --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 992ad146d..1377502dd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -113,7 +113,7 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableEncoders(validator.GetEncoders()); } - _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, _ffmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty); } /// @@ -126,7 +126,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { string newPath; - _logger.LogInformation("Attempting to update encoder path to {0}. pathType: {1}", path ?? string.Empty, pathType ?? string.Empty); + _logger.LogInformation("Attempting to update encoder path to {Path}. pathType: {PathType}", path ?? string.Empty, pathType ?? string.Empty); if (!string.Equals(pathType, "custom", StringComparison.OrdinalIgnoreCase)) { @@ -180,7 +180,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!rc) { - _logger.LogWarning("FFmpeg: {0}: Failed version check: {1}", location, path); + _logger.LogWarning("FFmpeg: {Location}: Failed version check: {Path}", location, path); } // ToDo - Enable the ffmpeg validator. At the moment any version can be used. @@ -191,18 +191,18 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - _logger.LogWarning("FFmpeg: {0}: File not found: {1}", location, path); + _logger.LogWarning("FFmpeg: {Location}: File not found: {Path}", location, path); } } return rc; } - private string GetEncoderPathFromDirectory(string path, string filename) + private string GetEncoderPathFromDirectory(string path, string filename, bool recursive = false) { try { - var files = _fileSystem.GetFilePaths(path); + var files = _fileSystem.GetFilePaths(path, recursive); var excludeExtensions = new[] { ".c" }; @@ -223,7 +223,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// private string ExistsOnSystemPath(string fileName) { - string inJellyfinPath = GetEncoderPathFromDirectory(System.AppContext.BaseDirectory, fileName); + var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true); if (!string.IsNullOrEmpty(inJellyfinPath)) { return inJellyfinPath; @@ -892,7 +892,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return minSizeVobs.Count == 0 ? vobs.Select(i => i.FullName) : minSizeVobs.Select(i => i.FullName); } - _logger.LogWarning("Could not determine vob file list for {0} using DvdLib. Will scan using file sizes.", path); + _logger.LogWarning("Could not determine vob file list for {Path} using DvdLib. Will scan using file sizes.", path); } var files = allVobs -- cgit v1.2.3 From a262ecd9c77b0e906288de0890aee2d5dcad6ae4 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 9 May 2020 19:49:55 +0200 Subject: Add positionning cues to WebVTT writer --- MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs index 2e328ba63..de35acbba 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs @@ -7,14 +7,25 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { + /// + /// Subtitle writer for the WebVTT format. + /// public class VttWriter : ISubtitleWriter { + /// public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken) { using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { writer.WriteLine("WEBVTT"); writer.WriteLine(string.Empty); + writer.WriteLine("REGION"); + writer.WriteLine("id:subtitle"); + writer.WriteLine("width:80%"); + writer.WriteLine("lines:3"); + writer.WriteLine("regionanchor:50%,100%"); + writer.WriteLine("viewportanchor:50%,90%"); + writer.WriteLine(string.Empty); foreach (var trackEvent in info.TrackEvents) { cancellationToken.ThrowIfCancellationRequested(); @@ -22,13 +33,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles var startTime = TimeSpan.FromTicks(trackEvent.StartPositionTicks); var endTime = TimeSpan.FromTicks(trackEvent.EndPositionTicks); - // make sure the start and end times are different and seqential + // make sure the start and end times are different and sequential if (endTime.TotalMilliseconds <= startTime.TotalMilliseconds) { endTime = startTime.Add(TimeSpan.FromMilliseconds(1)); } - writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", startTime, endTime); + writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff} region:subtitle", startTime, endTime); var text = trackEvent.Text; -- cgit v1.2.3 From 428e1b04fc942b66dafaa04081d3b9dc5de62f1d Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 14 May 2020 18:11:32 +0200 Subject: Add color transfer to ffprobe results --- MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 7 +++++++ MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 5 +++++ 2 files changed, 12 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 0b2f1d231..fa51e61a2 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -278,5 +278,12 @@ namespace MediaBrowser.MediaEncoding.Probing /// The disposition. [JsonPropertyName("disposition")] public IReadOnlyDictionary Disposition { get; set; } + + /// + /// Gets or sets the color transfer. + /// + /// The color transfer. + [JsonPropertyName("color_transfer")] + public string ColorTransfer { get; set; } } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index b24d97f4e..41daa22d6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -695,6 +695,11 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.RefFrames = streamInfo.Refs; } + + if (!string.IsNullOrEmpty(streamInfo.ColorTransfer)) + { + stream.ColorTransfer = streamInfo.ColorTransfer; + } } else { -- cgit v1.2.3 From 2e18142bb32554cf162827ab1ca7a8040107baea Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 14 May 2020 18:52:42 +0200 Subject: Add color primaries to ffprobe output --- MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 7 +++++++ MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 5 +++++ 2 files changed, 12 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index fa51e61a2..d7b0e0e64 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -285,5 +285,12 @@ namespace MediaBrowser.MediaEncoding.Probing /// The color transfer. [JsonPropertyName("color_transfer")] public string ColorTransfer { get; set; } + + /// + /// Gets or sets the color transfer. + /// + /// The color transfer. + [JsonPropertyName("color_primaries")] + public string ColorPrimaries { get; set; } } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 41daa22d6..d3f8094b9 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -700,6 +700,11 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.ColorTransfer = streamInfo.ColorTransfer; } + + if (!string.IsNullOrEmpty(streamInfo.ColorPrimaries)) + { + stream.ColorPrimaries = streamInfo.ColorPrimaries; + } } else { -- cgit v1.2.3 From 9314434bbf79250f1e545b459c545f57d5acc67c Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 16 May 2020 17:35:34 +0200 Subject: Fix suggestions --- MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 4 ++-- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index d7b0e0e64..a2ea0766a 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -287,9 +287,9 @@ namespace MediaBrowser.MediaEncoding.Probing public string ColorTransfer { get; set; } /// - /// Gets or sets the color transfer. + /// Gets or sets the color primaries. /// - /// The color transfer. + /// The color primaries. [JsonPropertyName("color_primaries")] public string ColorPrimaries { get; set; } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index dd17623bd..d340f9ef7 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Model.Entities var colorTransfer = ColorTransfer; if (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) - || string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) + || string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) { return "HDR"; } -- cgit v1.2.3 From 10e381f66f957ffa2e8339a02b0c970086673739 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 25 May 2020 23:52:51 +0200 Subject: Fix some 'bugs' flagged by sonarcloud --- DvdLib/Ifo/Program.cs | 2 +- Emby.Dlna/ContentDirectory/ContentDirectory.cs | 8 +--- Emby.Dlna/Main/DlnaEntryPoint.cs | 10 ++--- Emby.Dlna/PlayTo/Device.cs | 20 ++++----- Emby.Dlna/PlayTo/PlayToController.cs | 19 +++++---- Emby.Dlna/Ssdp/Extensions.cs | 14 ++----- .../EntryPoints/LibraryChangedNotifier.cs | 4 +- .../EntryPoints/RecordingNotifier.cs | 18 ++++---- .../EntryPoints/ServerEventNotifier.cs | 48 +++++++++++----------- .../HttpServer/HttpResultFactory.cs | 12 ++++-- .../LiveTv/EmbyTV/EmbyTV.cs | 13 ++---- .../LiveTv/EmbyTV/EncodedRecorder.cs | 4 +- .../LiveTv/LiveTvManager.cs | 20 +++------ .../SocketSharp/WebSocketSharpRequest.cs | 5 ++- MediaBrowser.Api/Images/ImageService.cs | 3 +- .../Sessions/SessionInfoWebSocketListener.cs | 28 ++++++------- .../Net/BasePeriodicWebSocketListener.cs | 25 +++++++---- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 6 ++- 18 files changed, 126 insertions(+), 133 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Program.cs b/DvdLib/Ifo/Program.cs index 9f6251270..3d94fa7dc 100644 --- a/DvdLib/Ifo/Program.cs +++ b/DvdLib/Ifo/Program.cs @@ -6,7 +6,7 @@ namespace DvdLib.Ifo { public class Program { - public readonly List Cells; + public IReadOnlyList Cells { get; } public Program(List cells) { diff --git a/Emby.Dlna/ContentDirectory/ContentDirectory.cs b/Emby.Dlna/ContentDirectory/ContentDirectory.cs index 64cd308a2..66805b7c8 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectory.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectory.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using System.Linq; using System.Threading.Tasks; using Emby.Dlna.Service; using MediaBrowser.Common.Net; @@ -136,12 +137,7 @@ namespace Emby.Dlna.ContentDirectory } } - foreach (var user in _userManager.Users) - { - return user; - } - - return null; + return _userManager.Users.FirstOrDefault(); } } } diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index c5d60b2a0..bcab4adba 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -133,20 +133,20 @@ namespace Emby.Dlna.Main { await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false); - ReloadComponents(); + await ReloadComponents().ConfigureAwait(false); - _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; + _config.NamedConfigurationUpdated += OnNamedConfigurationUpdated; } - void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + private async void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) { - ReloadComponents(); + await ReloadComponents().ConfigureAwait(false); } } - private async void ReloadComponents() + private async Task ReloadComponents() { var options = _config.GetDlnaConfiguration(); diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 6abc3a82c..c7431d143 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -34,7 +34,7 @@ namespace Emby.Dlna.PlayTo { get { - RefreshVolumeIfNeeded(); + RefreshVolumeIfNeeded().GetAwaiter().GetResult(); return _volume; } set => _volume = value; @@ -76,24 +76,24 @@ namespace Emby.Dlna.PlayTo private DateTime _lastVolumeRefresh; private bool _volumeRefreshActive; - private void RefreshVolumeIfNeeded() + private Task RefreshVolumeIfNeeded() { - if (!_volumeRefreshActive) - { - return; - } - - if (DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5)) + if (_volumeRefreshActive + && DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5)) { _lastVolumeRefresh = DateTime.UtcNow; - RefreshVolume(CancellationToken.None); + return RefreshVolume(); } + + return Task.CompletedTask; } - private async void RefreshVolume(CancellationToken cancellationToken) + private async Task RefreshVolume(CancellationToken cancellationToken = default) { if (_disposed) + { return; + } try { diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 9d7c0d365..7403a2a16 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -146,11 +146,14 @@ namespace Emby.Dlna.PlayTo { var positionTicks = GetProgressPositionTicks(streamInfo); - ReportPlaybackStopped(streamInfo, positionTicks); + await ReportPlaybackStopped(streamInfo, positionTicks).ConfigureAwait(false); } streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager); - if (streamInfo.Item == null) return; + if (streamInfo.Item == null) + { + return; + } var newItemProgress = GetProgressInfo(streamInfo); @@ -173,11 +176,14 @@ namespace Emby.Dlna.PlayTo { var streamInfo = StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager); - if (streamInfo.Item == null) return; + if (streamInfo.Item == null) + { + return; + } var positionTicks = GetProgressPositionTicks(streamInfo); - ReportPlaybackStopped(streamInfo, positionTicks); + await ReportPlaybackStopped(streamInfo, positionTicks).ConfigureAwait(false); var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false); @@ -185,7 +191,7 @@ namespace Emby.Dlna.PlayTo (_device.Duration == null ? (long?)null : _device.Duration.Value.Ticks) : mediaSource.RunTimeTicks; - var playedToCompletion = (positionTicks.HasValue && positionTicks.Value == 0); + var playedToCompletion = positionTicks.HasValue && positionTicks.Value == 0; if (!playedToCompletion && duration.HasValue && positionTicks.HasValue) { @@ -210,7 +216,7 @@ namespace Emby.Dlna.PlayTo } } - private async void ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks) + private async Task ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks) { try { @@ -220,7 +226,6 @@ namespace Emby.Dlna.PlayTo SessionId = _session.Id, PositionTicks = positionTicks, MediaSourceId = streamInfo.MediaSourceId - }).ConfigureAwait(false); } catch (Exception ex) diff --git a/Emby.Dlna/Ssdp/Extensions.cs b/Emby.Dlna/Ssdp/Extensions.cs index 10c1f321b..613d332b2 100644 --- a/Emby.Dlna/Ssdp/Extensions.cs +++ b/Emby.Dlna/Ssdp/Extensions.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System.Linq; using System.Xml.Linq; namespace Emby.Dlna.Ssdp @@ -10,24 +11,17 @@ namespace Emby.Dlna.Ssdp { var node = container.Element(name); - return node == null ? null : node.Value; + return node?.Value; } public static string GetAttributeValue(this XElement container, XName name) { var node = container.Attribute(name); - return node == null ? null : node.Value; + return node?.Value; } public static string GetDescendantValue(this XElement container, XName name) - { - foreach (var node in container.Descendants(name)) - { - return node.Value; - } - - return null; - } + => container.Descendants(name).FirstOrDefault()?.Value; } } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 8e3236407..9bc2b62ec 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -302,7 +302,7 @@ namespace Emby.Server.Implementations.EntryPoints .Select(x => x.First()) .ToList(); - SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); + SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None).GetAwaiter().GetResult(); if (LibraryUpdateTimer != null) { @@ -327,7 +327,7 @@ namespace Emby.Server.Implementations.EntryPoints /// The folders added to. /// The folders removed from. /// The cancellation token. - private async void SendChangeNotifications(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, CancellationToken cancellationToken) + private async Task SendChangeNotifications(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, CancellationToken cancellationToken) { var userIds = _sessionManager.Sessions .Select(i => i.UserId) diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 41c0c5115..997571a91 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -42,27 +42,27 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - private void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) { - SendMessage("SeriesTimerCreated", e.Argument); + await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false); } - private void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) { - SendMessage("TimerCreated", e.Argument); + await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false); } - private void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) { - SendMessage("SeriesTimerCancelled", e.Argument); + await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false); } - private void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) { - SendMessage("TimerCancelled", e.Argument); + await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false); } - private async void SendMessage(string name, TimerEventInfo info) + private async Task SendMessage(string name, TimerEventInfo info) { var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id).ToList(); diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index e1dbb663b..dea85d299 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -85,29 +85,29 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - private void OnPackageInstalling(object sender, InstallationEventArgs e) + private async void OnPackageInstalling(object sender, InstallationEventArgs e) { - SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo); + await SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo).ConfigureAwait(false); } - private void OnPackageInstallationCancelled(object sender, InstallationEventArgs e) + private async void OnPackageInstallationCancelled(object sender, InstallationEventArgs e) { - SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo); + await SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo).ConfigureAwait(false); } - private void OnPackageInstallationCompleted(object sender, InstallationEventArgs e) + private async void OnPackageInstallationCompleted(object sender, InstallationEventArgs e) { - SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo); + await SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo).ConfigureAwait(false); } - private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) + private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) { - SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo); + await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false); } - private void OnTaskCompleted(object sender, TaskCompletionEventArgs e) + private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e) { - SendMessageToAdminSessions("ScheduledTaskEnded", e.Result); + await SendMessageToAdminSessions("ScheduledTaskEnded", e.Result).ConfigureAwait(false); } /// @@ -115,9 +115,9 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The sender. /// The e. - private void OnPluginUninstalled(object sender, GenericEventArgs e) + private async void OnPluginUninstalled(object sender, GenericEventArgs e) { - SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo()); + await SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo()).ConfigureAwait(false); } /// @@ -125,9 +125,9 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The source of the event. /// The instance containing the event data. - private void OnHasPendingRestartChanged(object sender, EventArgs e) + private async void OnHasPendingRestartChanged(object sender, EventArgs e) { - _sessionManager.SendRestartRequiredNotification(CancellationToken.None); + await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false); } /// @@ -135,11 +135,11 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The sender. /// The e. - private void OnUserUpdated(object sender, GenericEventArgs e) + private async void OnUserUpdated(object sender, GenericEventArgs e) { var dto = _userManager.GetUserDto(e.Argument); - SendMessageToUserSession(e.Argument, "UserUpdated", dto); + await SendMessageToUserSession(e.Argument, "UserUpdated", dto).ConfigureAwait(false); } /// @@ -147,26 +147,26 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The sender. /// The e. - private void OnUserDeleted(object sender, GenericEventArgs e) + private async void OnUserDeleted(object sender, GenericEventArgs e) { - SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)); + await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false); } - private void OnUserPolicyUpdated(object sender, GenericEventArgs e) + private async void OnUserPolicyUpdated(object sender, GenericEventArgs e) { var dto = _userManager.GetUserDto(e.Argument); - SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto); + await SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto).ConfigureAwait(false); } - private void OnUserConfigurationUpdated(object sender, GenericEventArgs e) + private async void OnUserConfigurationUpdated(object sender, GenericEventArgs e) { var dto = _userManager.GetUserDto(e.Argument); - SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto); + await SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto).ConfigureAwait(false); } - private async void SendMessageToAdminSessions(string name, T data) + private async Task SendMessageToAdminSessions(string name, T data) { try { @@ -178,7 +178,7 @@ namespace Emby.Server.Implementations.EntryPoints } } - private async void SendMessageToUserSession(User user, string name, T data) + private async Task SendMessageToUserSession(User user, string name, T data) { try { diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 2e9ecc4ae..cffae7b1c 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -255,16 +255,20 @@ namespace Emby.Server.Implementations.HttpServer { var acceptEncoding = request.Headers[HeaderNames.AcceptEncoding].ToString(); - if (string.IsNullOrEmpty(acceptEncoding)) + if (!string.IsNullOrEmpty(acceptEncoding)) { - //if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1) + // if (_brotliCompressor != null && acceptEncoding.IndexOf("br", StringComparison.OrdinalIgnoreCase) != -1) // return "br"; - if (acceptEncoding.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1) + if (acceptEncoding.Contains("deflate", StringComparison.OrdinalIgnoreCase)) + { return "deflate"; + } - if (acceptEncoding.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1) + if (acceptEncoding.Contains("gzip", StringComparison.OrdinalIgnoreCase)) + { return "gzip"; + } } return null; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 3efe1ee25..5a5dc3329 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -140,11 +140,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) + private async void OnNamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { if (string.Equals(e.Key, "livetv", StringComparison.OrdinalIgnoreCase)) { - OnRecordingFoldersChanged(); + await CreateRecordingFolders().ConfigureAwait(false); } } @@ -155,11 +155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return CreateRecordingFolders(); } - private async void OnRecordingFoldersChanged() - { - await CreateRecordingFolders().ConfigureAwait(false); - } - internal async Task CreateRecordingFolders() { try @@ -1334,7 +1329,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV await CreateRecordingFolders().ConfigureAwait(false); TriggerRefresh(recordPath); - EnforceKeepUpTo(timer, seriesPath); + await EnforceKeepUpTo(timer, seriesPath).ConfigureAwait(false); }; await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false); @@ -1494,7 +1489,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return item; } - private async void EnforceKeepUpTo(TimerInfo timer, string seriesPath) + private async Task EnforceKeepUpTo(TimerInfo timer, string seriesPath) { if (string.IsNullOrWhiteSpace(timer.SeriesTimerId)) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index bc86cc59a..70dd8f321 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -117,7 +117,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV onStarted(); // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - StartStreamingLog(_process.StandardError.BaseStream, _logFileStream); + _ = StartStreamingLog(_process.StandardError.BaseStream, _logFileStream); _logger.LogInformation("ffmpeg recording process started for {0}", _targetPath); @@ -321,7 +321,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private async void StartStreamingLog(Stream source, Stream target) + private async Task StartStreamingLog(Stream source, Stream target) { try { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1b10f2d27..a3dd45a53 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -788,22 +788,12 @@ namespace Emby.Server.Implementations.LiveTv if (query.OrderBy.Count == 0) { - if (query.IsAiring ?? false) - { - // Unless something else was specified, order by start date to take advantage of a specialized index - query.OrderBy = new[] - { - (ItemSortBy.StartDate, SortOrder.Ascending) - }; - } - else + + // Unless something else was specified, order by start date to take advantage of a specialized index + query.OrderBy = new[] { - // Unless something else was specified, order by start date to take advantage of a specialized index - query.OrderBy = new[] - { - (ItemSortBy.StartDate, SortOrder.Ascending) - }; - } + (ItemSortBy.StartDate, SortOrder.Ascending) + }; } RemoveFields(options); diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs index ee5131c1f..5554aa97f 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs @@ -208,8 +208,9 @@ namespace Emby.Server.Implementations.SocketSharp private static string GetQueryStringContentType(HttpRequest httpReq) { - ReadOnlySpan format = httpReq.Query["format"].ToString(); - if (format == null) + string formatStr = httpReq.Query["format"].ToString(); + ReadOnlySpan format = formatStr; + if (formatStr == null) { const int FormatMaxLength = 4; ReadOnlySpan pi = httpReq.Path.ToString(); diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 2e9b3e6cb..eaff22fff 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -555,8 +555,7 @@ namespace MediaBrowser.Api.Images var imageInfo = GetImageInfo(request, item); if (imageInfo == null) { - var displayText = item == null ? itemId.ToString() : item.Name; - throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", displayText, request.Type)); + throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type)); } bool cropwhitespace; diff --git a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs index 0e74c9267..175984575 100644 --- a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs @@ -40,39 +40,39 @@ namespace MediaBrowser.Api.Sessions _sessionManager.SessionActivity += OnSessionManagerSessionActivity; } - private void OnSessionManagerSessionActivity(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionActivity(object sender, SessionEventArgs e) { - SendData(false); + await SendData(false).ConfigureAwait(false); } - private void OnSessionManagerCapabilitiesChanged(object sender, SessionEventArgs e) + private async void OnSessionManagerCapabilitiesChanged(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - private void OnSessionManagerPlaybackProgress(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackProgress(object sender, PlaybackProgressEventArgs e) { - SendData(!e.IsAutomated); + await SendData(!e.IsAutomated).ConfigureAwait(false); } - private void OnSessionManagerPlaybackStopped(object sender, PlaybackStopEventArgs e) + private async void OnSessionManagerPlaybackStopped(object sender, PlaybackStopEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - private void OnSessionManagerPlaybackStart(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackStart(object sender, PlaybackProgressEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - private void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } - private void OnSessionManagerSessionStarted(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionStarted(object sender, SessionEventArgs e) { - SendData(true); + await SendData(true).ConfigureAwait(false); } /// diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index 1162bff13..5be656bdb 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -104,7 +104,7 @@ namespace MediaBrowser.Controller.Net } } - protected void SendData(bool force) + protected async Task SendData(bool force) { Tuple[] tuples; @@ -128,13 +128,18 @@ namespace MediaBrowser.Controller.Net .ToArray(); } - foreach (var tuple in tuples) + IEnumerable GetTasks() { - SendData(tuple); + foreach (var tuple in tuples) + { + yield return SendData(tuple); + } } + + await Task.WhenAll(GetTasks()).ConfigureAwait(false); } - private async void SendData(Tuple tuple) + private async Task SendData(Tuple tuple) { var connection = tuple.Item1; @@ -148,11 +153,13 @@ namespace MediaBrowser.Controller.Net if (data != null) { - await connection.SendAsync(new WebSocketMessage - { - MessageType = Name, - Data = data - }, cancellationToken).ConfigureAwait(false); + await connection.SendAsync( + new WebSocketMessage + { + MessageType = Name, + Data = data + }, + cancellationToken).ConfigureAwait(false); state.DateLastSendUtc = DateTime.UtcNow; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 293cf5ea5..f44cf1452 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -33,10 +33,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { continue; } + if (line.StartsWith("[")) + { break; - if (string.IsNullOrEmpty(line)) - continue; + } + var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) }; eventIndex++; var sections = line.Substring(10).Split(','); -- cgit v1.2.3 From b4b93995f7f05971bd8532cadc9b80db07de9ab3 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Thu, 9 Apr 2020 00:15:01 +0800 Subject: add more separate hw decoding toggles --- .../MediaEncoding/EncodingHelper.cs | 267 ++++++++++++++++++--- .../MediaEncoding/IMediaEncoder.cs | 15 +- .../Encoder/EncoderValidator.cs | 77 ++++-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 13 + .../Subtitles/SubtitleEncoder.cs | 2 +- .../Configuration/EncodingOptions.cs | 2 + 6 files changed, 330 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 61a330675..807ba4e93 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -103,6 +103,11 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } + if (!_mediaEncoder.SupportsHwaccel("vaapi")) + { + return false; + } + return true; } @@ -444,18 +449,30 @@ namespace MediaBrowser.Controller.MediaEncoding public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions) { var arg = new StringBuilder(); + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); + var outputVideoCodec = GetVideoEncoder(state, encodingOptions); - if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) + if (state.IsVideoRequest && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) { - arg.Append("-hwaccel vaapi -hwaccel_output_format vaapi") - .Append(" -vaapi_device ") - .Append(encodingOptions.VaapiDevice) - .Append(' '); + // While using VAAPI decoder + if ((videoDecoder ?? string.Empty).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) + { + arg.Append("-hwaccel_output_format vaapi") + .Append(" -vaapi_device ") + .Append(encodingOptions.VaapiDevice) + .Append(" "); + } + // While using SW decoder and VAAPI encoder + else if ((videoDecoder ?? string.Empty).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) == -1 + && (outputVideoCodec ?? string.Empty).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) + { + arg.Append("-vaapi_device ") + .Append(encodingOptions.VaapiDevice) + .Append(" "); + } } - if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (state.IsVideoRequest && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); var outputVideoCodec = GetVideoEncoder(state, encodingOptions); @@ -1655,7 +1672,7 @@ namespace MediaBrowser.Controller.MediaEncoding For software decoding and hardware encoding option, frames must be hwuploaded into hardware with fixed frame size. */ - if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)) + if ((videoDecoder ?? string.Empty).IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1) { retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\""; } @@ -2511,16 +2528,15 @@ namespace MediaBrowser.Controller.MediaEncoding /// protected string GetHardwareAcceleratedVideoDecoder(EncodingJobInfo state, EncodingOptions encodingOptions) { + var videoType = state.MediaSource.VideoType ?? VideoType.VideoFile; + var videoStream = state.VideoStream; + var IsColorDepth10 = (videoStream.Profile ?? string.Empty).IndexOf("10", StringComparison.OrdinalIgnoreCase) != -1; + if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { return null; } - return GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions); - } - - public string GetHardwareAcceleratedVideoDecoder(VideoType videoType, MediaStream videoStream, EncodingOptions encodingOptions) - { // Only use alternative encoders for video files. // When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully // Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this. @@ -2533,6 +2549,14 @@ namespace MediaBrowser.Controller.MediaEncoding && !string.IsNullOrEmpty(videoStream.Codec) && !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType)) { + // Only hevc and vp9 formats have 10-bit hardware decoder support now. + if (IsColorDepth10 && !(string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.Codec, "h265", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.Codec, "vp9", StringComparison.OrdinalIgnoreCase))) + { + return null; + } + if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { switch (videoStream.Codec.ToLowerInvariant()) @@ -2554,8 +2578,17 @@ namespace MediaBrowser.Controller.MediaEncoding case "h265": if (_mediaEncoder.SupportsDecoder("hevc_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) { - //return "-c:v hevc_qsv -load_plugin hevc_hw "; - return "-c:v hevc_qsv"; + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v hevc_qsv "; + } + + return null; + } + + return "-c:v hevc_qsv "; } break; case "mpeg2video": @@ -2570,6 +2603,28 @@ namespace MediaBrowser.Controller.MediaEncoding return "-c:v vc1_qsv"; } break; + case "vp8": + if (_mediaEncoder.SupportsDecoder("vp8_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v vp8_qsv "; + } + break; + case "vp9": + if (_mediaEncoder.SupportsDecoder("vp9_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) + { + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v vp9_qsv "; + } + + return null; + } + + return "-c:v vp9_qsv "; + } + break; } } @@ -2594,7 +2649,17 @@ namespace MediaBrowser.Controller.MediaEncoding case "h265": if (_mediaEncoder.SupportsDecoder("hevc_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) { - return "-c:v hevc_cuvid"; + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v hevc_cuvid "; + } + + return null; + } + + return "-c:v hevc_cuvid "; } break; case "mpeg2video": @@ -2615,6 +2680,28 @@ namespace MediaBrowser.Controller.MediaEncoding return "-c:v mpeg4_cuvid"; } break; + case "vp8": + if (_mediaEncoder.SupportsDecoder("vp8_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v vp8_cuvid "; + } + break; + case "vp9": + if (_mediaEncoder.SupportsDecoder("vp9_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) + { + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v vp9_cuvid "; + } + + return null; + } + + return "-c:v vp9_cuvid "; + } + break; } } @@ -2633,7 +2720,17 @@ namespace MediaBrowser.Controller.MediaEncoding case "h265": if (_mediaEncoder.SupportsDecoder("hevc_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) { - return "-c:v hevc_mediacodec"; + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v hevc_mediacodec "; + } + + return null; + } + + return "-c:v hevc_mediacodec "; } break; case "mpeg2video": @@ -2657,7 +2754,17 @@ namespace MediaBrowser.Controller.MediaEncoding case "vp9": if (_mediaEncoder.SupportsDecoder("vp9_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) { - return "-c:v vp9_mediacodec"; + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return "-c:v vp9_mediacodec "; + } + + return null; + } + + return "-c:v vp9_mediacodec "; } break; } @@ -2697,27 +2804,133 @@ namespace MediaBrowser.Controller.MediaEncoding else if (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase)) { - if (Environment.OSVersion.Platform == PlatformID.Win32NT) + switch (videoStream.Codec.ToLowerInvariant()) { - if (Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1)) - return "-hwaccel d3d11va"; - else - return "-hwaccel dxva2"; + case "avc": + case "h264": + return GetHwaccelType(state, encodingOptions, "h264"); + case "hevc": + case "h265": + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return GetHwaccelType(state, encodingOptions, "hevc"); + } + + return null; + } + + return GetHwaccelType(state, encodingOptions, "hevc"); + case "mpeg2video": + return GetHwaccelType(state, encodingOptions, "mpeg2video"); + case "vc1": + return GetHwaccelType(state, encodingOptions, "vc1"); + case "mpeg4": + return GetHwaccelType(state, encodingOptions, "mpeg4"); + case "vp9": + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return GetHwaccelType(state, encodingOptions, "vp9"); + } + + return null; + } + + return GetHwaccelType(state, encodingOptions, "vp9"); } - else + } + + else if (string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) + { + switch (videoStream.Codec.ToLowerInvariant()) { - return "-hwaccel vaapi"; + case "avc": + case "h264": + return GetHwaccelType(state, encodingOptions, "h264"); + case "hevc": + case "h265": + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return GetHwaccelType(state, encodingOptions, "hevc"); + } + + return null; + } + + return GetHwaccelType(state, encodingOptions, "hevc"); + case "mpeg2video": + return GetHwaccelType(state, encodingOptions, "mpeg2video"); + case "vc1": + return GetHwaccelType(state, encodingOptions, "vc1"); + case "vp8": + return GetHwaccelType(state, encodingOptions, "vp8"); + case "vp9": + if (IsColorDepth10) + { + if (encodingOptions.EnableDecodingColorDepth10) + { + return GetHwaccelType(state, encodingOptions, "vp9"); + } + + return null; + } + + return GetHwaccelType(state, encodingOptions, "vp9"); } } } + var whichCodec = videoStream.Codec.ToLowerInvariant(); + switch (whichCodec) + { + case "avc": + whichCodec = "h264"; + break; + case "h265": + whichCodec = "hevc"; + break; + } + // Avoid a second attempt if no hardware acceleration is being used - encodingOptions.HardwareDecodingCodecs = Array.Empty(); + encodingOptions.HardwareDecodingCodecs = encodingOptions.HardwareDecodingCodecs.Where(val => val != whichCodec).ToArray(); // leave blank so ffmpeg will decide return null; } + /// + /// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system + /// + public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec) + { + var IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; + var IsNewWindows = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1); + var IsDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va"); + + if ((IsDxvaSupported || IsVaapiSupported(state)) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase)) + { + if (!IsWindows) + { + return "-hwaccel vaapi "; + } + else if (IsWindows && IsNewWindows) + { + return "-hwaccel d3d11va "; + } + else if (IsWindows && !IsNewWindows) + { + return "-hwaccel dxva2 "; + } + } + + return null; + } + public string GetSubtitleEmbedArguments(EncodingJobInfo state) { if (state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Embed) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 37f0b11a7..6fa3bed48 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -26,6 +26,13 @@ namespace MediaBrowser.Controller.MediaEncoding /// The encoder path. string EncoderPath { get; } + /// + /// Supportses the encoder. + /// + /// The encoder. + /// true if XXXX, false otherwise. + bool SupportsEncoder(string encoder); + /// /// Supportses the decoder. /// @@ -33,6 +40,13 @@ namespace MediaBrowser.Controller.MediaEncoding /// true if XXXX, false otherwise. bool SupportsDecoder(string decoder); + /// + /// Supportses the hwaccel. + /// + /// The hwaccel. + /// true if XXXX, false otherwise. + bool SupportsHwaccel(string hwaccel); + /// /// Extracts the audio image. /// @@ -98,7 +112,6 @@ namespace MediaBrowser.Controller.MediaEncoding void SetFFmpegPath(); void UpdateEncoderPath(string path, string pathType); - bool SupportsEncoder(string encoder); IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber); } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 6e036d24c..e329f605d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -14,23 +14,38 @@ namespace MediaBrowser.MediaEncoding.Encoder private static readonly string[] requiredDecoders = new[] { + "h264", + "hevc", "mpeg2video", + "mpeg4", + "msmpeg4", + "dts", + "ac3", + "aac", + "mp3", "h264_qsv", "hevc_qsv", "mpeg2_qsv", - "mpeg2_mmal", - "mpeg4_mmal", "vc1_qsv", - "vc1_mmal", + "vp8_qsv", + "vp9_qsv", "h264_cuvid", "hevc_cuvid", - "dts", - "ac3", - "aac", - "mp3", - "h264", + "mpeg2_cuvid", + "vc1_cuvid", + "mpeg4_cuvid", + "vp8_cuvid", + "vp9_cuvid", "h264_mmal", - "hevc" + "mpeg2_mmal", + "mpeg4_mmal", + "vc1_mmal", + "h264_mediacodec", + "hevc_mediacodec", + "mpeg2_mediacodec", + "mpeg4_mediacodec", + "vp8_mediacodec", + "vp9_mediacodec" }; private static readonly string[] requiredEncoders = new[] @@ -43,22 +58,22 @@ namespace MediaBrowser.MediaEncoding.Encoder "libvpx-vp9", "aac", "libfdk_aac", + "ac3", "libmp3lame", "libopus", "libvorbis", "srt", - "h264_nvenc", - "hevc_nvenc", + "h264_amf", + "hevc_amf", "h264_qsv", "hevc_qsv", - "h264_omx", - "hevc_omx", + "h264_nvenc", + "hevc_nvenc", "h264_vaapi", "hevc_vaapi", - "h264_v4l2m2m", - "ac3", - "h264_amf", - "hevc_amf" + "h264_omx", + "hevc_omx", + "h264_v4l2m2m" }; // Try and use the individual library versions to determine a FFmpeg version @@ -159,6 +174,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public IEnumerable GetEncoders() => GetCodecs(Codec.Encoder); + public IEnumerable GetHwaccels() => GetHwaccelTypes(); + /// /// Using the output from "ffmpeg -version" work out the FFmpeg version. /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy @@ -218,6 +235,32 @@ namespace MediaBrowser.MediaEncoding.Encoder Decoder } + private IEnumerable GetHwaccelTypes() + { + string output = null; + try + { + output = GetProcessOutput(_encoderPath, "-hwaccels"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error detecting available hwaccel types"); + } + + if (string.IsNullOrWhiteSpace(output)) + { + return Enumerable.Empty(); + } + + var found = output.Split(new char[] {'\r','\n'},StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); + + found.RemoveAt(0); + + _logger.LogInformation("Available hwaccel types: {Types}", found); + + return found; + } + private IEnumerable GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 1377502dd..4cc971809 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -111,6 +111,7 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); + SetAvailableHwaccels(validator.GetHwaccels()); } _logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty); @@ -257,6 +258,13 @@ namespace MediaBrowser.MediaEncoding.Encoder //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } + private List _hwaccels = new List(); + public void SetAvailableHwaccels(IEnumerable list) + { + _hwaccels = list.ToList(); + //_logger.Info("Supported hwaccels: {0}", string.Join(",", list.ToArray())); + } + public bool SupportsEncoder(string encoder) { return _encoders.Contains(encoder, StringComparer.OrdinalIgnoreCase); @@ -267,6 +275,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); } + public bool SupportsHwaccel(string hwaccel) + { + return _hwaccels.Contains(hwaccel, StringComparer.OrdinalIgnoreCase); + } + public bool CanEncodeToAudioCodec(string codec) { if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index ba171295e..7d85f6ef7 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -737,7 +737,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName; // UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding - if ((path.EndsWith(".ass") || path.EndsWith(".ssa")) + if ((path.EndsWith(".ass") || path.EndsWith(".ssa") || path.EndsWith(".srt")) && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase) || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase))) { diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 648568fd7..dfc0deea9 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -25,6 +25,7 @@ namespace MediaBrowser.Model.Configuration public int H265Crf { get; set; } public string EncoderPreset { get; set; } public string DeinterlaceMethod { get; set; } + public bool EnableDecodingColorDepth10 { get; set; } public bool EnableHardwareEncoding { get; set; } public bool EnableSubtitleExtraction { get; set; } @@ -41,6 +42,7 @@ namespace MediaBrowser.Model.Configuration H264Crf = 23; H265Crf = 28; DeinterlaceMethod = "yadif"; + EnableDecodingColorDepth10 = true; EnableHardwareEncoding = true; EnableSubtitleExtraction = true; HardwareDecodingCodecs = new string[] { "h264", "vc1" }; -- cgit v1.2.3 From 1ff95289ef88d058e09b8189b579a35351b26f82 Mon Sep 17 00:00:00 2001 From: artiume Date: Mon, 25 May 2020 17:58:29 -0400 Subject: Update EncoderValidator.cs --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index e329f605d..be77a855d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -46,6 +46,12 @@ namespace MediaBrowser.MediaEncoding.Encoder "mpeg4_mediacodec", "vp8_mediacodec", "vp9_mediacodec" + "h264_videotoolbox", + "hevc_videotoolbox", + "mpeg2_videotoolbox", + "mpeg4_videotoolbox", + "vp8_videotoolbox", + "vp9_videotoolbox" }; private static readonly string[] requiredEncoders = new[] @@ -74,6 +80,8 @@ namespace MediaBrowser.MediaEncoding.Encoder "h264_omx", "hevc_omx", "h264_v4l2m2m" + "h264_videotoolbox" + "hevc_videotoolbox" }; // Try and use the individual library versions to determine a FFmpeg version @@ -252,7 +260,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty(); } - var found = output.Split(new char[] {'\r','\n'},StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); + var found = output.Split(new char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); found.RemoveAt(0); -- cgit v1.2.3 From 407de0209ef0f78d5a8ec3f9af2557010124d9cb Mon Sep 17 00:00:00 2001 From: artiume Date: Mon, 25 May 2020 18:01:00 -0400 Subject: Update MediaEncoder.cs --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4cc971809..c51b8c110 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -258,7 +258,7 @@ namespace MediaBrowser.MediaEncoding.Encoder //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } - private List _hwaccels = new List(); + private List _hwaccels = Array.Empty(); public void SetAvailableHwaccels(IEnumerable list) { _hwaccels = list.ToList(); -- cgit v1.2.3 From 3c8237975924c326cfe460872654730f30e999db Mon Sep 17 00:00:00 2001 From: artiume Date: Mon, 25 May 2020 18:14:22 -0400 Subject: Update EncoderValidator.cs --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index be77a855d..89f33b048 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -51,7 +51,8 @@ namespace MediaBrowser.MediaEncoding.Encoder "mpeg2_videotoolbox", "mpeg4_videotoolbox", "vp8_videotoolbox", - "vp9_videotoolbox" + "vp9_videotoolbox", + "vc1_videotoolbox" }; private static readonly string[] requiredEncoders = new[] -- cgit v1.2.3 From 628734931ceb87f265320cf83b3fd29710a03c2b Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 26 May 2020 18:41:38 +0300 Subject: Fix missing commas and merge defects --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 3 --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 6 +++--- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 50acc35f2..94fa5c6c0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -475,9 +475,6 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.IsVideoRequest && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); - var outputVideoCodec = GetVideoEncoder(state, encodingOptions); - var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; if (!hasTextSubs) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 89f33b048..f155379a0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "mpeg2_mediacodec", "mpeg4_mediacodec", "vp8_mediacodec", - "vp9_mediacodec" + "vp9_mediacodec", "h264_videotoolbox", "hevc_videotoolbox", "mpeg2_videotoolbox", @@ -80,8 +80,8 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc_vaapi", "h264_omx", "hevc_omx", - "h264_v4l2m2m" - "h264_videotoolbox" + "h264_v4l2m2m", + "h264_videotoolbox", "hevc_videotoolbox" }; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index c51b8c110..4cc971809 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -258,7 +258,7 @@ namespace MediaBrowser.MediaEncoding.Encoder //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } - private List _hwaccels = Array.Empty(); + private List _hwaccels = new List(); public void SetAvailableHwaccels(IEnumerable list) { _hwaccels = list.ToList(); -- cgit v1.2.3 From aa17a53e83a61c23b7cd33d0294f3ccfe1000daf Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 26 May 2020 19:05:44 +0300 Subject: Skip only line saying "Hardware acceleration methods:" instead of some random one --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f155379a0..8910249af 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -261,10 +261,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty(); } - var found = output.Split(new char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); - - found.RemoveAt(0); - + var found = output.Split(new char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries).Skip(1).Distinct().ToList(); _logger.LogInformation("Available hwaccel types: {Types}", found); return found; -- cgit v1.2.3 From e103d087d316bc19bf6227b21e8d9dfd091fd6a7 Mon Sep 17 00:00:00 2001 From: Max Git Date: Mon, 1 Jun 2020 07:10:15 +0200 Subject: Try harder at detecting FFmpeg version and enable the validation --- .../Encoder/EncoderValidator.cs | 120 ++++++++++++++++----- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 3 - .../EncoderValidatorTests.cs | 7 +- 3 files changed, 97 insertions(+), 33 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 6e036d24c..d13d6045e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -12,7 +13,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { private const string DefaultEncoderPath = "ffmpeg"; - private static readonly string[] requiredDecoders = new[] + private static readonly string[] _requiredDecoders = new[] { "mpeg2video", "h264_qsv", @@ -33,7 +34,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc" }; - private static readonly string[] requiredEncoders = new[] + private static readonly string[] _requiredEncoders = new[] { "libx264", "libx265", @@ -61,7 +62,19 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc_amf" }; - // Try and use the individual library versions to determine a FFmpeg version + // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below + private static readonly IReadOnlyDictionary _ffmpegMinimumLibraryVersions = new Dictionary + { + {"libavutil", 56.14}, + {"libavcodec", 58.18 }, + {"libavformat", 58.12 }, + {"libavdevice", 58.3 }, + {"libavfilter", 7.16 }, + {"libswscale", 5.1 }, + {"libswresample", 3.1}, + {"libpostproc", 55.1 } + }; + // This lookup table is to be maintained with the following command line: // $ ffmpeg -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' private static readonly IReadOnlyDictionary _ffmpegVersionMap = new Dictionary @@ -123,32 +136,36 @@ namespace MediaBrowser.MediaEncoding.Encoder // Work out what the version under test is var version = GetFFmpegVersion(versionOutput); - _logger.LogInformation("Found ffmpeg version {0}", version != null ? version.ToString() : "unknown"); + _logger.LogInformation("Found ffmpeg version {Version}", version != null ? version.ToString() : "unknown"); if (version == null) { - if (MinVersion != null && MaxVersion != null) // Version is unknown + if (MaxVersion != null) // Version is unknown { if (MinVersion == MaxVersion) { - _logger.LogWarning("FFmpeg validation: We recommend ffmpeg version {0}", MinVersion); + _logger.LogWarning("FFmpeg validation: We recommend version {MinVersion}", MinVersion); } else { - _logger.LogWarning("FFmpeg validation: We recommend a minimum of {0} and maximum of {1}", MinVersion, MaxVersion); + _logger.LogWarning("FFmpeg validation: We recommend a minimum of {MinVersion} and maximum of {MaxVersion}", MinVersion, MaxVersion); } } + else + { + _logger.LogWarning("FFmpeg validation: We recommend minimum version {MinVersion}", MinVersion); + } return false; } - else if (MinVersion != null && version < MinVersion) // Version is below what we recommend + else if (version < MinVersion) // Version is below what we recommend { - _logger.LogWarning("FFmpeg validation: The minimum recommended ffmpeg version is {0}", MinVersion); + _logger.LogWarning("FFmpeg validation: The minimum recommended version is {MinVersion}", MinVersion); return false; } else if (MaxVersion != null && version > MaxVersion) // Version is above what we recommend { - _logger.LogWarning("FFmpeg validation: The maximum recommended ffmpeg version is {0}", MaxVersion); + _logger.LogWarning("FFmpeg validation: The maximum recommended version is {MaxVersion}", MaxVersion); return false; } @@ -162,13 +179,12 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Using the output from "ffmpeg -version" work out the FFmpeg version. /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy - /// to parse. If this is not available, then we try to match known library versions to FFmpeg versions. - /// If that fails then we use one of the main libraries to determine if it's new/older than the latest - /// we have stored. + /// to parse. If this is not available, then we try to match known library versions to FFmpeg versions. + /// If that fails then we test the libraries to determine if they're newer than our minimum versions. /// /// /// - internal static Version GetFFmpegVersion(string output) + internal Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output var match = Regex.Match(output, @"^ffmpeg version n?((?:\d+\.?)+)"); @@ -179,37 +195,87 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - // Create a reduced version string and lookup key from dictionary - var reducedVersion = GetLibrariesVersionString(output); + if (!TryGetFFmpegLibraryVersions(output, out string versionString, out IReadOnlyDictionary versionMap)) + { + _logger.LogError("No ffmpeg library versions found"); + + return null; + } + + // First try to lookup the full version string + if (_ffmpegVersionMap.TryGetValue(versionString, out Version version)) + { + return version; + } + + // Then try to test for minimum library versions + return TestMinimumFFmpegLibraryVersions(versionMap); + } + } + + private Version TestMinimumFFmpegLibraryVersions(IReadOnlyDictionary versionMap) + { + var allVersionsValidated = true; - // Try to lookup the string and return Key, otherwise if not found returns null - return _ffmpegVersionMap.TryGetValue(reducedVersion, out Version version) ? version : null; + foreach (var minimumVersion in _ffmpegMinimumLibraryVersions) + { + if (versionMap.TryGetValue(minimumVersion.Key, out var foundVersion)) + { + if (foundVersion >= minimumVersion.Value) + { + _logger.LogInformation("Found {Library} version {FoundVersion} ({MinimumVersion})", minimumVersion.Key, foundVersion, minimumVersion.Value); + } + else + { + _logger.LogWarning("Found {Library} version {FoundVersion} lower than recommended version {MinimumVersion}", minimumVersion.Key, foundVersion, minimumVersion.Value); + allVersionsValidated = false; + } + } + else + { + _logger.LogError("{Library} version not found", minimumVersion.Key); + allVersionsValidated = false; + } } + + return allVersionsValidated ? MinVersion : null; } /// /// Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output - /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc." /// /// + /// + /// /// - private static string GetLibrariesVersionString(string output) + private static bool TryGetFFmpegLibraryVersions(string output, out string versionString, out IReadOnlyDictionary versionMap) { - var rc = new StringBuilder(144); - foreach (Match m in Regex.Matches( + var sb = new StringBuilder(144); + + var map = new Dictionary(); + + foreach (Match match in Regex.Matches( output, @"((?lib\w+)\s+(?\d+)\.\s*(?\d+))", RegexOptions.Multiline)) { - rc.Append(m.Groups["name"]) + sb.Append(match.Groups["name"]) .Append('=') - .Append(m.Groups["major"]) + .Append(match.Groups["major"]) .Append('.') - .Append(m.Groups["minor"]) + .Append(match.Groups["minor"]) .Append(','); + + var str = $"{match.Groups["major"]}.{match.Groups["minor"]}"; + var versionNumber = double.Parse(str, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture); + + map.Add(match.Groups["name"].Value, versionNumber); } - return rc.Length == 0 ? null : rc.ToString(); + versionString = sb.ToString(); + versionMap = map as IReadOnlyDictionary; + + return sb.Length > 0; } private enum Codec @@ -236,7 +302,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty(); } - var required = codec == Codec.Encoder ? requiredEncoders : requiredDecoders; + var required = codec == Codec.Encoder ? _requiredEncoders : _requiredDecoders; var found = Regex .Matches(output, @"^\s\S{6}\s(?[\w|-]+)\s+.+$", RegexOptions.Multiline) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 1377502dd..2abd31a50 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -183,9 +183,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogWarning("FFmpeg: {Location}: Failed version check: {Path}", location, path); } - // ToDo - Enable the ffmpeg validator. At the moment any version can be used. - rc = true; - _ffmpegPath = path; EncoderLocation = location; } diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index e0f1f236c..ae389efcd 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -17,7 +17,7 @@ namespace Jellyfin.MediaEncoding.Tests yield return new object?[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4) }; - yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, null }; + yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, new Version(4, 0) }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); @@ -27,7 +27,8 @@ namespace Jellyfin.MediaEncoding.Tests [ClassData(typeof(GetFFmpegVersionTestData))] public void GetFFmpegVersionTest(string versionOutput, Version? version) { - Assert.Equal(version, EncoderValidator.GetFFmpegVersion(versionOutput)); + var val = new EncoderValidator(new NullLogger()); + Assert.Equal(version, val.GetFFmpegVersion(versionOutput)); } [Theory] @@ -35,7 +36,7 @@ namespace Jellyfin.MediaEncoding.Tests [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV414Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV404Output, true)] - [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)] + [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, true)] public void ValidateVersionInternalTest(string versionOutput, bool valid) { var val = new EncoderValidator(new NullLogger()); -- cgit v1.2.3 From 480fd0a66a7d8e47542e89b4751b9cf59b5faa9b Mon Sep 17 00:00:00 2001 From: rotvel Date: Mon, 1 Jun 2020 16:00:58 +0200 Subject: Update MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs Co-authored-by: Cody Robibero --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index d13d6045e..801479eed 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -65,14 +65,14 @@ namespace MediaBrowser.MediaEncoding.Encoder // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below private static readonly IReadOnlyDictionary _ffmpegMinimumLibraryVersions = new Dictionary { - {"libavutil", 56.14}, - {"libavcodec", 58.18 }, - {"libavformat", 58.12 }, - {"libavdevice", 58.3 }, - {"libavfilter", 7.16 }, - {"libswscale", 5.1 }, - {"libswresample", 3.1}, - {"libpostproc", 55.1 } + { "libavutil", 56.14 }, + { "libavcodec", 58.18 }, + { "libavformat", 58.12 }, + { "libavdevice", 58.3 }, + { "libavfilter", 7.16 }, + { "libswscale", 5.1 }, + { "libswresample", 3.1 }, + { "libpostproc", 55.1 } }; // This lookup table is to be maintained with the following command line: -- cgit v1.2.3 From 44957c5a9a11fcd6e4567c7d31bc39d79c709068 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 5 Jun 2020 18:15:56 -0600 Subject: Use typed logger where possible --- Emby.Dlna/ConnectionManager/ConnectionManager.cs | 2 +- Emby.Dlna/DlnaManager.cs | 4 ++-- Emby.Dlna/Main/DlnaEntryPoint.cs | 10 ++++++---- Emby.Dlna/PlayTo/PlayToManager.cs | 3 ++- Emby.Dlna/Service/BaseService.cs | 4 ++-- Emby.Drawing/ImageProcessor.cs | 2 +- Emby.Notifications/NotificationEntryPoint.cs | 2 +- Emby.Notifications/NotificationManager.cs | 2 +- Emby.Photos/PhotoProvider.cs | 2 +- .../AppBase/BaseConfigurationManager.cs | 4 ++-- Emby.Server.Implementations/ApplicationHost.cs | 2 +- Emby.Server.Implementations/Browser/BrowserLauncher.cs | 2 +- Emby.Server.Implementations/Channels/ChannelManager.cs | 2 +- .../Channels/RefreshChannelsScheduledTask.cs | 2 +- Emby.Server.Implementations/Collections/CollectionManager.cs | 6 +++--- Emby.Server.Implementations/Data/BaseSqliteRepository.cs | 4 ++-- Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs | 2 +- Emby.Server.Implementations/Devices/DeviceId.cs | 4 ++-- Emby.Server.Implementations/Dto/DtoService.cs | 2 +- .../EntryPoints/ExternalPortForwarding.cs | 2 +- .../EntryPoints/LibraryChangedNotifier.cs | 2 +- Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs | 2 +- Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs | 2 +- .../HttpClientManager/HttpClientManager.cs | 2 +- Emby.Server.Implementations/HttpServer/HttpListenerHost.cs | 4 ++-- Emby.Server.Implementations/HttpServer/HttpResultFactory.cs | 4 ++-- Emby.Server.Implementations/HttpServer/Security/AuthService.cs | 2 +- Emby.Server.Implementations/HttpServer/WebSocketConnection.cs | 2 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 +- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- Emby.Server.Implementations/Library/MediaSourceManager.cs | 2 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 2 +- .../Library/Resolvers/TV/SeasonResolver.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 4 ++-- Emby.Server.Implementations/Library/SearchEngine.cs | 2 +- Emby.Server.Implementations/Library/UserDataManager.cs | 2 +- Emby.Server.Implementations/Library/UserManager.cs | 2 +- .../Library/Validators/ArtistsPostScanTask.cs | 4 ++-- .../Library/Validators/ArtistsValidator.cs | 4 ++-- .../Library/Validators/GenresPostScanTask.cs | 4 ++-- .../Library/Validators/GenresValidator.cs | 4 ++-- .../Library/Validators/MusicGenresPostScanTask.cs | 4 ++-- .../Library/Validators/MusicGenresValidator.cs | 4 ++-- .../Library/Validators/StudiosPostScanTask.cs | 4 ++-- .../Library/Validators/StudiosValidator.cs | 4 ++-- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 +- Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 +- Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs | 2 +- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 2 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs | 4 ++-- Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs | 1 + .../Localization/LocalizationManager.cs | 2 +- Emby.Server.Implementations/MediaEncoder/EncodingManager.cs | 2 +- Emby.Server.Implementations/Networking/NetworkManager.cs | 2 +- Emby.Server.Implementations/Playlists/PlaylistManager.cs | 2 +- Emby.Server.Implementations/ResourceFileManager.cs | 2 +- Emby.Server.Implementations/ScheduledTasks/TaskManager.cs | 2 +- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 4 ++-- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 2 +- .../ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs | 2 +- .../ScheduledTasks/Tasks/PluginUpdateTask.cs | 2 +- Emby.Server.Implementations/Services/ServiceController.cs | 2 +- Emby.Server.Implementations/Session/SessionManager.cs | 2 +- .../Session/SessionWebSocketListener.cs | 2 +- Emby.Server.Implementations/Session/WebSocketController.cs | 2 +- .../SocketSharp/WebSocketSharpRequest.cs | 2 +- Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs | 2 +- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 +- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 2 +- .../Migrations/Routines/DisableTranscodingThrottling.cs | 2 +- Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs | 2 +- MediaBrowser.Api/ApiEntryPoint.cs | 2 +- MediaBrowser.Api/Music/AlbumsService.cs | 10 ++++++---- MediaBrowser.Api/SimilarItemsHelper.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 3 ++- MediaBrowser.Controller/Entities/UserView.cs | 3 ++- MediaBrowser.Controller/Entities/UserViewBuilder.cs | 4 ++-- MediaBrowser.Controller/IO/FileData.cs | 3 ++- MediaBrowser.Controller/Library/Profiler.cs | 2 +- MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs | 4 ++-- MediaBrowser.Controller/Session/SessionInfo.cs | 1 + .../Images/InternalMetadataFolderImageProvider.cs | 2 +- MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs | 4 ++-- MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs | 2 +- MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs | 2 +- MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs | 4 ++-- MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs | 4 ++-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 4 ++-- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 1 + MediaBrowser.Providers/Manager/MetadataService.cs | 4 ++-- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs | 2 +- MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs | 3 ++- MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs | 2 +- MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs | 2 +- MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs | 2 +- MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbEpisodeImageProvider.cs | 2 +- MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbPersonImageProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbSeasonImageProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbSeriesImageProvider.cs | 2 +- MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs | 2 +- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 2 +- MediaBrowser.Providers/TV/SeriesMetadataService.cs | 3 ++- MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 2 +- MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs | 2 +- MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs | 2 +- MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs | 4 ++-- MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs | 4 ++-- MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs | 4 ++-- MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs | 6 +++--- MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 +- MediaBrowser.XbmcMetadata/EntryPoint.cs | 2 +- MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs | 4 ++-- MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 6 +++--- 128 files changed, 179 insertions(+), 166 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/ConnectionManager/ConnectionManager.cs b/Emby.Dlna/ConnectionManager/ConnectionManager.cs index e32cc11bf..480dd3a79 100644 --- a/Emby.Dlna/ConnectionManager/ConnectionManager.cs +++ b/Emby.Dlna/ConnectionManager/ConnectionManager.cs @@ -18,7 +18,7 @@ namespace Emby.Dlna.ConnectionManager public ConnectionManager( IDlnaManager dlna, IServerConfigurationManager config, - ILogger logger, + ILogger logger, IHttpClient httpClient) : base(logger, httpClient) { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 10f881fe7..a85e5c35e 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -31,7 +31,7 @@ namespace Emby.Dlna private readonly IApplicationPaths _appPaths; private readonly IXmlSerializer _xmlSerializer; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; private readonly IServerApplicationHost _appHost; private static readonly Assembly _assembly = typeof(DlnaManager).Assembly; @@ -49,7 +49,7 @@ namespace Emby.Dlna _xmlSerializer = xmlSerializer; _fileSystem = fileSystem; _appPaths = appPaths; - _logger = loggerFactory.CreateLogger("Dlna"); + _logger = loggerFactory.CreateLogger(); _jsonSerializer = jsonSerializer; _appHost = appHost; } diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index bcab4adba..47b235e59 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -33,7 +33,7 @@ namespace Emby.Dlna.Main public class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup { private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; private PlayToManager _manager; @@ -65,7 +65,8 @@ namespace Emby.Dlna.Main public static DlnaEntryPoint Current; - public DlnaEntryPoint(IServerConfigurationManager config, + public DlnaEntryPoint( + IServerConfigurationManager config, ILoggerFactory loggerFactory, IServerApplicationHost appHost, ISessionManager sessionManager, @@ -99,7 +100,7 @@ namespace Emby.Dlna.Main _mediaEncoder = mediaEncoder; _socketFactory = socketFactory; _networkManager = networkManager; - _logger = loggerFactory.CreateLogger("Dlna"); + _logger = loggerFactory.CreateLogger(); ContentDirectory = new ContentDirectory.ContentDirectory( dlnaManager, @@ -347,7 +348,8 @@ namespace Emby.Dlna.Main try { - _manager = new PlayToManager(_logger, + _manager = new PlayToManager( + _logger, _sessionManager, _libraryManager, _userManager, diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index bbedd1485..9b0339e5d 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -184,7 +184,8 @@ namespace Emby.Dlna.PlayTo serverAddress = _appHost.GetLocalApiUrl(info.LocalIpAddress); } - controller = new PlayToController(sessionInfo, + controller = new PlayToController( + sessionInfo, _sessionManager, _libraryManager, _logger, diff --git a/Emby.Dlna/Service/BaseService.cs b/Emby.Dlna/Service/BaseService.cs index 3704bedcd..4ecffa293 100644 --- a/Emby.Dlna/Service/BaseService.cs +++ b/Emby.Dlna/Service/BaseService.cs @@ -12,12 +12,12 @@ namespace Emby.Dlna.Service protected IHttpClient HttpClient; protected ILogger Logger; - protected BaseService(ILogger logger, IHttpClient httpClient) + protected BaseService(ILogger logger, IHttpClient httpClient) { Logger = logger; HttpClient = httpClient; - EventManager = new EventManager(Logger, HttpClient); + EventManager = new EventManager(logger, HttpClient); } public EventSubscriptionResponse CancelEventSubscription(string subscriptionId) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 47778acac..c9fc8d55a 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -28,7 +28,7 @@ namespace Emby.Drawing private static readonly HashSet _transparentImageTypes = new HashSet(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" }; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs index 869b7407e..b923fd26c 100644 --- a/Emby.Notifications/NotificationEntryPoint.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -25,7 +25,7 @@ namespace Emby.Notifications /// public class NotificationEntryPoint : IServerEntryPoint { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; private readonly INotificationManager _notificationManager; diff --git a/Emby.Notifications/NotificationManager.cs b/Emby.Notifications/NotificationManager.cs index 639a5e1aa..2792a8f0b 100644 --- a/Emby.Notifications/NotificationManager.cs +++ b/Emby.Notifications/NotificationManager.cs @@ -21,7 +21,7 @@ namespace Emby.Notifications /// public class NotificationManager : INotificationManager { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly IServerConfigurationManager _config; diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 987cb7fb2..58baa1e50 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -22,7 +22,7 @@ namespace Emby.Photos /// public class PhotoProvider : ICustomMetadataProvider, IForcedProvider, IHasItemChangeMonitor { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IImageProcessor _imageProcessor; // These are causing taglib to hang diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 080cfbbd1..d4a8268b9 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.AppBase CommonApplicationPaths = applicationPaths; XmlSerializer = xmlSerializer; _fileSystem = fileSystem; - Logger = loggerFactory.CreateLogger(GetType().Name); + Logger = loggerFactory.CreateLogger(); UpdateCachePath(); } @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.AppBase /// Gets the logger. /// /// The logger. - protected ILogger Logger { get; private set; } + protected ILogger Logger { get; private set; } /// /// Gets the XML serializer. diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index be4e05a64..184c6f399 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -173,7 +173,7 @@ namespace Emby.Server.Implementations /// /// Gets the logger. /// - protected ILogger Logger { get; } + protected ILogger Logger { get; } private IPlugin[] _plugins; diff --git a/Emby.Server.Implementations/Browser/BrowserLauncher.cs b/Emby.Server.Implementations/Browser/BrowserLauncher.cs index 7f7c6a0be..7a0294e07 100644 --- a/Emby.Server.Implementations/Browser/BrowserLauncher.cs +++ b/Emby.Server.Implementations/Browser/BrowserLauncher.cs @@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Browser } catch (Exception ex) { - var logger = appHost.Resolve(); + var logger = appHost.Resolve>(); logger?.LogError(ex, "Failed to open browser window with URL {URL}", relativeUrl); } } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 04fe0bacb..f9eea66b4 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Channels private readonly IUserDataManager _userDataManager; private readonly IDtoService _dtoService; private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly IJsonSerializer _jsonSerializer; diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index 54b621e25..e5dde48d8 100644 --- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Channels public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask { private readonly IChannelManager _channelManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 7c518d483..cba3975cf 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Collections private readonly ILibraryManager _libraryManager; private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _iLibraryMonitor; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IProviderManager _providerManager; private readonly ILocalizationManager _localizationManager; private readonly IApplicationPaths _appPaths; @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.Collections _libraryManager = libraryManager; _fileSystem = fileSystem; _iLibraryMonitor = iLibraryMonitor; - _logger = loggerFactory.CreateLogger(nameof(CollectionManager)); + _logger = loggerFactory.CreateLogger(); _providerManager = providerManager; _localizationManager = localizationManager; _appPaths = appPaths; @@ -370,7 +370,7 @@ namespace Emby.Server.Implementations.Collections { private readonly CollectionManager _collectionManager; private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 0654132f4..f816fd54f 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Data /// Initializes a new instance of the class. /// /// The logger. - protected BaseSqliteRepository(ILogger logger) + protected BaseSqliteRepository(ILogger logger) { Logger = logger; } @@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Data /// Gets the logger. /// /// The logger. - protected ILogger Logger { get; } + protected ILogger Logger { get; } /// /// Gets the default connection flags. diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs index 37c678a5d..6c9bcff0f 100644 --- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs +++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Data public class CleanDatabaseScheduledTask : ILibraryPostScanTask { private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger logger) { diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index f0d43e665..fa6ac95fd 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Devices public class DeviceId { private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly object _syncLock = new object(); @@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.Devices public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory) { _appPaths = appPaths; - _logger = loggerFactory.CreateLogger("SystemId"); + _logger = loggerFactory.CreateLogger(); } public string Value => _id ?? (_id = GetDeviceId()); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 38c4f940d..f9841082c 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Dto { public class DtoService : IDtoService { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IUserDataManager _userDataRepository; private readonly IItemRepository _itemRepo; diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 878cee23c..9fce49425 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.EntryPoints public class ExternalPortForwarding : IServerEntryPoint { private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly IDeviceDiscovery _deviceDiscovery; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 9bc2b62ec..b9992ae73 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// The library changed sync lock. diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 997571a91..b64439802 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ILiveTvManager _liveTvManager; private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; - private readonly ILogger _logger; + private readonly ILogger _logger; public RecordingNotifier( ISessionManager sessionManager, diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 5bc1a81aa..ecdce89ce 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; private readonly IConfiguration _config; diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index d66bb7638..87977494a 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.HttpClientManager /// public class HttpClientManager : IHttpClient { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IApplicationHost _appHost; diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 7de4f168c..17994d199 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.HttpServer /// public const string DefaultRedirectKey = "HttpListenerHost:DefaultRedirectPath"; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; @@ -397,7 +397,7 @@ namespace Emby.Server.Implementations.HttpServer var response = context.Response; var localPath = context.Request.Path.ToString(); - var req = new WebSocketSharpRequest(request, response, request.Path, _logger); + var req = new WebSocketSharpRequest(request, response, request.Path); return RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted); } diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 9d5969583..cc4797790 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.HttpServer /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IJsonSerializer _jsonSerializer; private readonly IStreamHelper _streamHelper; @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.HttpServer _fileSystem = fileSystem; _jsonSerializer = jsonSerializer; _streamHelper = streamHelper; - _logger = loggerfactory.CreateLogger("HttpResultFactory"); + _logger = loggerfactory.CreateLogger(); } /// diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 256b24924..9bb29586e 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.HttpServer.Security public User Authenticate(HttpRequest request, IAuthenticationAttributes authAttributes) { - var req = new WebSocketSharpRequest(request, null, request.Path, _logger); + var req = new WebSocketSharpRequest(request, null, request.Path); var user = ValidateUser(req, authAttributes); return user; } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 0680c5ffe..c64d57339 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.HttpServer /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// The json serializer options. diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index eb5e190aa..49bca7dac 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.IO { public class LibraryMonitor : ILibraryMonitor { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 7461ec4f1..2bcfc82b6 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.IO /// public class ManagedFileSystem : IFileSystem { - protected ILogger Logger; + protected ILogger Logger; private readonly List _shortcutHandlers = new List(); private readonly string _tempPath; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 677030b82..8c6be8e04 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.Library /// public class LibraryManager : ILibraryManager { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ITaskManager _taskManager; private readonly IUserManager _userManager; private readonly IUserDataManager _userDataRepository; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index a5e5981b8..00826c7cb 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.Library private readonly ILibraryManager _libraryManager; private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IUserDataManager _userDataManager; private readonly IMediaEncoder _mediaEncoder; private readonly ILocalizationManager _localizationManager; diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 6c9ba7c27..ebfe95d0a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -109,7 +109,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio IEnumerable list, bool allowSubfolders, IDirectoryService directoryService, - ILogger logger, + ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 18145b7f1..7f8800a64 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV private readonly IServerConfigurationManager _config; private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index dd6bd8ee8..4180dad36 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV public class SeriesResolver : FolderResolver { private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; /// @@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV IEnumerable fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem, - ILogger logger, + ILogger logger, ILibraryManager libraryManager, bool isTvContentType) { diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 59a77607d..bde77ee8e 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Library { public class SearchEngine : ISearchEngine { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index a9772a078..d8694b07d 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -26,7 +26,7 @@ namespace Emby.Server.Implementations.Library private readonly ConcurrentDictionary _userData = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly IUserManager _userManager; private readonly IUserDataRepository _repository; diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 140155d0e..531e00666 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.Library private readonly object _policySyncLock = new object(); private readonly object _configSyncLock = new object(); - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IUserRepository _userRepository; private readonly IXmlSerializer _xmlSerializer; private readonly IJsonSerializer _jsonSerializer; diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs index 2af8ff5cb..d51f9aaa7 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The _library manager. /// private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The item repository. public ArtistsPostScanTask( ILibraryManager libraryManager, - ILogger logger, + ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs index 1497f4a3a..8a6bd5e78 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.Library.Validators /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The library manager. /// The logger. /// The item repository. - public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) + public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; _logger = logger; diff --git a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs index 251785dfd..d21d2887b 100644 --- a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The _library manager. /// private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The item repository. public GenresPostScanTask( ILibraryManager libraryManager, - ILogger logger, + ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs index b0cd5f87a..e59c62e23 100644 --- a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.Library.Validators /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The library manager. /// The logger. /// The item repository. - public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) + public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; _logger = logger; diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs index 9d8690116..be119866b 100644 --- a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The library manager. /// private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The item repository. public MusicGenresPostScanTask( ILibraryManager libraryManager, - ILogger logger, + ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs index 5ee4ca72e..1ecf4c87c 100644 --- a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs @@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Validators /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The library manager. /// The logger. /// The item repository. - public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) + public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; _logger = logger; diff --git a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs index 2f8f906b9..c682b156b 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Library.Validators /// private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; /// @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The item repository. public StudiosPostScanTask( ILibraryManager libraryManager, - ILogger logger, + ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs index 15e7a0dbb..7a6cd11df 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.Library.Validators /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. @@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Validators /// The library manager. /// The logger. /// The item repository. - public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) + public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) { _libraryManager = libraryManager; _logger = logger; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 5a5dc3329..f9b71939b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private const int TunerDiscoveryDurationMs = 3000; private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _config; private readonly IJsonSerializer _jsonSerializer; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 89b81fd96..02f18060d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { public class SchedulesDirect : IListingsProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1); diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 07f8539c5..077b5c7e5 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -26,7 +26,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { private readonly IServerConfigurationManager _config; private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IZipClient _zipClient; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index a59c1090e..49ad73af3 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -26,7 +26,7 @@ namespace Emby.Server.Implementations.LiveTv private const string ServiceName = "Emby"; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IImageProcessor _imageProcessor; private readonly IDtoService _dtoService; private readonly IApplicationHost _appHost; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index dbd0e6f2e..a88e0f31f 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.LiveTv private const string EtagKey = "ProgramEtag"; private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IItemRepository _itemRepo; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 7f63991d0..f3fc41352 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.LiveTv private const string StreamIdDelimeterString = "_"; private readonly ILiveTvManager _liveTvManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerApplicationHost _appHost; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 80ee1ee33..ba3594efd 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -22,14 +22,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public abstract class BaseTunerHost { protected readonly IServerConfigurationManager Config; - protected readonly ILogger Logger; + protected readonly ILogger Logger; protected IJsonSerializer JsonSerializer; protected readonly IFileSystem FileSystem; private readonly ConcurrentDictionary _channelCache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem) + protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem) { Config = config; Logger = logger; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 4e4f1d7f6..c3336ca92 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Emby.Server.Implementations.Library; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index e2a634e1a..62a23118f 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Localization private readonly IServerConfigurationManager _configurationManager; private readonly IJsonSerializer _jsonSerializer; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly Dictionary> _allParentalRatings = new Dictionary>(StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 7b7575707..438bbe24a 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.MediaEncoder { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IMediaEncoder _encoder; private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index d1a28e7a1..45864bb42 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Networking { public class NetworkManager : INetworkManager { - private readonly ILogger _logger; + private readonly ILogger _logger; private IPAddress[] _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index c51eb0586..8d022d6c4 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Playlists private readonly ILibraryManager _libraryManager; private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _iLibraryMonitor; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly IProviderManager _providerManager; private readonly IConfiguration _appConfig; diff --git a/Emby.Server.Implementations/ResourceFileManager.cs b/Emby.Server.Implementations/ResourceFileManager.cs index d192be921..22fc62293 100644 --- a/Emby.Server.Implementations/ResourceFileManager.cs +++ b/Emby.Server.Implementations/ResourceFileManager.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations public class ResourceFileManager : IResourceFileManager { private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; public ResourceFileManager(ILogger logger, IFileSystem fileSystem) { diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index efefa5506..94220ac5d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private readonly IJsonSerializer _jsonSerializer; private readonly IApplicationPaths _applicationPaths; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; /// diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index fae049914..9028222dd 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// The _logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// The _library manager. @@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.ScheduledTasks IFileSystem fileSystem, ILocalizationManager localization) { - _logger = loggerFactory.CreateLogger(GetType().Name); + _logger = loggerFactory.CreateLogger(); _libraryManager = libraryManager; _itemRepo = itemRepo; _appPaths = appPaths; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index a6c13eaef..966b549b2 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// The application paths. private IApplicationPaths ApplicationPaths { get; set; } - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index 0d36b82c0..53cf9a0a5 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index acab3aeea..7388086fb 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// The _logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IInstallationManager _installationManager; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/Services/ServiceController.cs b/Emby.Server.Implementations/Services/ServiceController.cs index ad6015c1c..e688278b5 100644 --- a/Emby.Server.Implementations/Services/ServiceController.cs +++ b/Emby.Server.Implementations/Services/ServiceController.cs @@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Services public class ServiceController { - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 5c480e842..506e6739f 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Session /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index e7b4b0ec3..ef32c692c 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Session /// /// The _logger /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; private readonly IHttpServer _httpServer; diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index a0274acd2..94604ca1e 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Session { public sealed class WebSocketController : ISessionController, IDisposable { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ISessionManager _sessionManager; private readonly SessionInfo _session; diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs index aa76901a4..ae1a8d0b7 100644 --- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs +++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs @@ -26,7 +26,7 @@ namespace Emby.Server.Implementations.SocketSharp private Dictionary _items; private string _responseContentType; - public WebSocketSharpRequest(HttpRequest httpRequest, HttpResponse httpResponse, string operationName, ILogger logger) + public WebSocketSharpRequest(HttpRequest httpRequest, HttpResponse httpResponse, string operationName) { this.OperationName = operationName; this.Request = httpRequest; diff --git a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs index 129262e53..1bfc9a9a5 100644 --- a/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs +++ b/Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.SyncPlay /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// The user manager. diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 178f32c31..80326fddf 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Updates /// /// The logger. /// - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index ccee5c5b9..ba9a5809f 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -21,7 +21,7 @@ namespace Jellyfin.Drawing.Skia private static readonly HashSet _transparentImageTypes = new HashSet(StringComparer.OrdinalIgnoreCase) { ".png", ".gif", ".webp" }; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; /// diff --git a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs index b2e957d5b..c18aa1629 100644 --- a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs +++ b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs @@ -10,7 +10,7 @@ namespace Jellyfin.Server.Migrations.Routines /// internal class DisableTranscodingThrottling : IMigrationRoutine { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _configManager; public DisableTranscodingThrottling(ILogger logger, IConfigurationManager configManager) diff --git a/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs b/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs index e95536388..2ebef0241 100644 --- a/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs +++ b/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Server.Migrations.Routines internal class RemoveDuplicateExtras : IMigrationRoutine { private const string DbFilename = "library.db"; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerApplicationPaths _paths; public RemoveDuplicateExtras(ILogger logger, IServerApplicationPaths paths) diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index c7485a2e9..9e651fb19 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Api /// /// The logger. /// - private ILogger _logger; + private ILogger _logger; /// /// The configuration manager. diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index 58c95d053..f257d1014 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -67,12 +67,13 @@ namespace MediaBrowser.Api.Music { var dtoOptions = GetDtoOptions(_authContext, request); - var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, + var result = SimilarItemsHelper.GetSimilarItemsResult( + dtoOptions, + _userManager, _itemRepo, _libraryManager, _userDataRepository, _dtoService, - Logger, request, new[] { typeof(MusicArtist) }, SimilarItemsHelper.GetSimiliarityScore); @@ -88,12 +89,13 @@ namespace MediaBrowser.Api.Music { var dtoOptions = GetDtoOptions(_authContext, request); - var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, + var result = SimilarItemsHelper.GetSimilarItemsResult( + dtoOptions, + _userManager, _itemRepo, _libraryManager, _userDataRepository, _dtoService, - Logger, request, new[] { typeof(MusicAlbum) }, GetAlbumSimilarityScore); diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 44bb24ef2..dcd22280a 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Api /// public static class SimilarItemsHelper { - internal static QueryResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func, List, BaseItem, int> getSimilarityScore) + internal static QueryResult GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func, List, BaseItem, int> getSimilarityScore) { var user = !request.UserId.Equals(Guid.Empty) ? userManager.GetUserById(request.UserId) : null; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f4b71d8bf..2c789e386 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -557,7 +557,8 @@ namespace MediaBrowser.Controller.Entities /// /// The logger /// - public static ILogger Logger { get; set; } + public static ILoggerFactory LoggerFactory { get; set; } + public static ILogger Logger { get; set; } public static ILibraryManager LibraryManager { get; set; } public static IServerConfigurationManager ConfigurationManager { get; set; } public static IProviderManager ProviderManager { get; set; } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 4ce9ec6f8..86cff632c 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -5,6 +5,7 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Querying; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities { @@ -66,7 +67,7 @@ namespace MediaBrowser.Controller.Entities parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent; } - return new UserViewBuilder(UserViewManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager) + return new UserViewBuilder(UserViewManager, LibraryManager, LoggerFactory.CreateLogger(), UserDataManager, TVSeriesManager, ConfigurationManager) .GetUserItems(parent, this, CollectionType, query); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 435a1e8da..3d91a0d0e 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities { private readonly IUserViewManager _userViewManager; private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IUserDataManager _userDataManager; private readonly ITVSeriesManager _tvSeriesManager; private readonly IServerConfigurationManager _config; @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Entities public UserViewBuilder( IUserViewManager userViewManager, ILibraryManager libraryManager, - ILogger logger, + ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config) diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 4bbb60283..666a3f76b 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -35,7 +35,8 @@ namespace MediaBrowser.Controller.IO /// if set to true [resolve shortcuts]. /// Dictionary{System.StringFileSystemInfo}. /// path - public static FileSystemMetadata[] GetFilteredFileSystemEntries(IDirectoryService directoryService, + public static FileSystemMetadata[] GetFilteredFileSystemEntries( + IDirectoryService directoryService, string path, IFileSystem fileSystem, IServerApplicationHost appHost, diff --git a/MediaBrowser.Controller/Library/Profiler.cs b/MediaBrowser.Controller/Library/Profiler.cs index 46a97d181..0febef3d3 100644 --- a/MediaBrowser.Controller/Library/Profiler.cs +++ b/MediaBrowser.Controller/Library/Profiler.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Library /// /// The _logger /// - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index 5be656bdb..7dca793c6 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -40,9 +40,9 @@ namespace MediaBrowser.Controller.Net /// /// The logger /// - protected ILogger Logger; + protected ILogger> Logger; - protected BasePeriodicWebSocketListener(ILogger logger) + protected BasePeriodicWebSocketListener(ILogger> logger) { if (logger == null) { diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 2ba7c9fec..ecc910872 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index 795933ce9..5137e4c68 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.LocalMetadata.Images { private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; public InternalMetadataFolderImageProvider( IServerConfigurationManager config, diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index d4b98182f..9621cfa4e 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// /// The logger /// - protected ILogger Logger { get; private set; } + protected ILogger> Logger { get; private set; } protected IProviderManager ProviderManager { get; private set; } private Dictionary _validProviderIds; @@ -32,7 +32,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// Initializes a new instance of the class. /// /// The logger. - public BaseItemXmlParser(ILogger logger, IProviderManager providerManager) + public BaseItemXmlParser(ILogger> logger, IProviderManager providerManager) { Logger = logger; ProviderManager = providerManager; diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs index 127334625..ca11a079d 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.LocalMetadata.Parsers item.Item.LinkedChildren = list.ToArray(); } - public BoxSetXmlParser(ILogger logger, IProviderManager providerManager) + public BoxSetXmlParser(ILogger logger, IProviderManager providerManager) : base(logger, providerManager) { } diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index 5608a0be9..54710cd82 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.LocalMetadata.Parsers item.LinkedChildren = list.ToArray(); } - public PlaylistXmlParser(ILogger logger, IProviderManager providerManager) + public PlaylistXmlParser(ILogger logger, IProviderManager providerManager) : base(logger, providerManager) { } diff --git a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs index b2e3bc9e2..2d115a591 100644 --- a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs @@ -13,10 +13,10 @@ namespace MediaBrowser.LocalMetadata.Providers /// public class BoxSetXmlProvider : BaseXmlProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IProviderManager _providerManager; - public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager) + public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager) : base(fileSystem) { _logger = logger; diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs index df8107bad..d4e2bc8e5 100644 --- a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs @@ -10,12 +10,12 @@ namespace MediaBrowser.LocalMetadata.Providers { public class PlaylistXmlProvider : BaseXmlProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IProviderManager _providerManager; public PlaylistXmlProvider( IFileSystem fileSystem, - ILogger logger, + ILogger logger, IProviderManager providerManager) : base(fileSystem) { diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index ba1d850e3..071902393 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.LocalMetadata.Savers { private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) + public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) { FileSystem = fileSystem; ConfigurationManager = configurationManager; @@ -36,7 +36,7 @@ namespace MediaBrowser.LocalMetadata.Savers protected ILibraryManager LibraryManager { get; private set; } protected IUserManager UserManager { get; private set; } protected IUserDataManager UserDataManager { get; private set; } - protected ILogger Logger { get; private set; } + protected ILogger Logger { get; private set; } public string Name => XmlProviderUtils.Name; diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 3f177a9fa..a82f2108f 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.MediaEncoding.Attachments { public class AttachmentExtractor : IAttachmentExtractor, IDisposable { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 1377502dd..26bd202ba 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// internal const int DefaultImageExtractionTimeout = 5000; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index ba171295e..f08af6045 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles public class SubtitleEncoder : ISubtitleEncoder { private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 3ab621ba4..f21ac2d65 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -15,6 +15,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; +using MediaBrowser.Providers.Tmdb.Models.General; using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Manager diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index c49aa407a..2997ba064 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -20,12 +20,12 @@ namespace MediaBrowser.Providers.Manager where TIdType : ItemLookupInfo, new() { protected readonly IServerConfigurationManager ServerConfigurationManager; - protected readonly ILogger Logger; + protected readonly ILogger> Logger; protected readonly IProviderManager ProviderManager; protected readonly IFileSystem FileSystem; protected readonly ILibraryManager LibraryManager; - protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager) + protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger> logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager) { ServerConfigurationManager = serverConfigurationManager; Logger = logger; diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 400ec8d29..13a4436e1 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Manager /// public class ProviderManager : IProviderManager, IDisposable { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IHttpClient _httpClient; private readonly ILibraryMonitor _libraryMonitor; private readonly IFileSystem _fileSystem; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 6982568eb..81103575d 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.MediaInfo IPreRefreshProvider, IHasItemChangeMonitor { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IIsoManager _isoManager; private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 77c0e9b4e..f35e82bb5 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -25,7 +25,8 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager = subtitleManager; } - public async Task> DownloadSubtitles(Video video, + public async Task> DownloadSubtitles( + Video video, List mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 2615f2dbb..fb87030ff 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IServerConfigurationManager _config; private readonly ISubtitleManager _subtitleManager; private readonly IMediaSourceManager _mediaSourceManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IJsonSerializer _json; private readonly ILocalizationManager _localization; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index f40570040..08e503a71 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Providers.MediaInfo public class VideoImageProvider : IDynamicImageProvider, IHasOrder { private readonly IMediaEncoder _mediaEncoder; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; public VideoImageProvider(IMediaEncoder mediaEncoder, ILogger logger, IFileSystem fileSystem) diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index ae837c591..9fc86b213 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Playlists IPreRefreshProvider, IHasItemChangeMonitor { - private ILogger _logger; + private readonly ILogger _logger; private IFileSystem _fileSystem; public PlaylistItemsProvider(IFileSystem fileSystem, ILogger logger) diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 31cdaf616..9d0d14969 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music private readonly IHttpClient _httpClient; private readonly IApplicationHost _appHost; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly string _musicBrainzBaseUrl; diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs index 6118a9c53..7a6fdc5f4 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public class TvdbEpisodeImageProvider : IRemoteImageProvider { private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TvdbClientManager _tvdbClientManager; public TvdbEpisodeImageProvider(IHttpClient httpClient, ILogger logger, TvdbClientManager tvdbClientManager) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs index 08c2a74d2..1f8b82ecd 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public class TvdbEpisodeProvider : IRemoteMetadataProvider, IHasOrder { private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TvdbClientManager _tvdbClientManager; public TvdbEpisodeProvider(IHttpClient httpClient, ILogger logger, TvdbClientManager tvdbClientManager) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs index c1cdc90e9..961cb5970 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public class TvdbPersonImageProvider : IRemoteImageProvider, IHasOrder { private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly TvdbClientManager _tvdbClientManager; diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs index a5d183df7..cd22514b4 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder { private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TvdbClientManager _tvdbClientManager; public TvdbSeasonImageProvider(IHttpClient httpClient, ILogger logger, TvdbClientManager tvdbClientManager) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs index 1bad60756..3fd98b828 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public class TvdbSeriesImageProvider : IRemoteImageProvider, IHasOrder { private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TvdbClientManager _tvdbClientManager; public TvdbSeriesImageProvider(IHttpClient httpClient, ILogger logger, TvdbClientManager tvdbClientManager) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs index f6cd249f5..35152610a 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb { internal static TvdbSeriesProvider Current { get; private set; } private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localizationManager; private readonly TvdbClientManager _tvdbClientManager; diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 127d29c04..c6ffc460c 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Subtitles { public class SubtitleManager : ISubtitleManager { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _monitor; private readonly IMediaSourceManager _mediaSourceManager; diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 5e75a8125..a91d5d707 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -42,7 +42,8 @@ namespace MediaBrowser.Providers.TV await seasonProvider.Run(item, cancellationToken).ConfigureAwait(false); // TODO why does it not register this itself omg - var provider = new MissingEpisodeProvider(Logger, + var provider = new MissingEpisodeProvider( + Logger, ServerConfigurationManager, LibraryManager, _localization, diff --git a/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs index dd3783ffb..e17f5efdf 100644 --- a/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Providers.Tmdb.BoxSets internal static TmdbBoxSetProvider Current; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IJsonSerializer _json; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; diff --git a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs index e2fd5b9e3..3787d4003 100644 --- a/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Tmdb/Movies/TmdbMovieProvider.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Tmdb.Movies private readonly IHttpClient _httpClient; private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; private readonly IApplicationHost _appHost; diff --git a/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs index 588001169..1f09badbc 100644 --- a/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Tmdb/People/TmdbPersonProvider.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Providers.Tmdb.People private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; private readonly IHttpClient _httpClient; - private readonly ILogger _logger; + private readonly ILogger _logger; public TmdbPersonProvider( IFileSystem fileSystem, diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs index 558c8149e..b0174a587 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeImageProvider.cs @@ -24,8 +24,8 @@ namespace MediaBrowser.Providers.Tmdb.TV IRemoteImageProvider, IHasOrder { - public TmdbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory) - : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory) + public TmdbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogger logger) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logger) { } public IEnumerable GetSupportedImages(BaseItem item) diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs index a17f5d17a..330b9f42b 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProvider.cs @@ -25,8 +25,8 @@ namespace MediaBrowser.Providers.Tmdb.TV IRemoteMetadataProvider, IHasOrder { - public TmdbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory) - : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory) + public TmdbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogger logger) + : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, logger) { } public async Task> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs index e87fe9332..3937ebc95 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -24,14 +24,14 @@ namespace MediaBrowser.Providers.Tmdb.TV private readonly ILocalizationManager _localization; private readonly ILogger _logger; - protected TmdbEpisodeProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory) + protected TmdbEpisodeProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILogger logger) { _httpClient = httpClient; _configurationManager = configurationManager; _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _localization = localization; - _logger = loggerFactory.CreateLogger(GetType().Name); + _logger = logger; } protected ILogger Logger => _logger; diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs index 5ad331971..832b64941 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeasonProvider.cs @@ -29,18 +29,18 @@ namespace MediaBrowser.Providers.Tmdb.TV private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; - private readonly ILogger _logger; + private readonly ILogger _logger; internal static TmdbSeasonProvider Current { get; private set; } - public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory) + public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILogger logger) { _httpClient = httpClient; _configurationManager = configurationManager; _fileSystem = fileSystem; _localization = localization; _jsonSerializer = jsonSerializer; - _logger = loggerFactory.CreateLogger(GetType().Name); + _logger = logger; Current = this; } diff --git a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs index 6e3c26c26..649c5474b 100644 --- a/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Tmdb/TV/TmdbSeriesProvider.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Tmdb.TV private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ILocalizationManager _localization; private readonly IHttpClient _httpClient; private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 55fc463d0..63cbfd9e4 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.WebDashboard.Api /// Gets or sets the logger. /// /// The logger. - private readonly ILogger _logger; + private readonly ILogger _logger; /// /// Gets or sets the HTTP result factory. diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index 571953b47..11b36285c 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.XbmcMetadata public sealed class EntryPoint : IServerEntryPoint { private readonly IUserDataManager _userDataManager; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IProviderManager _providerManager; private readonly IConfigurationManager _config; diff --git a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs index 4b1ee4c9c..433a936d9 100644 --- a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.XbmcMetadata.Providers /// public class AlbumNfoProvider : BaseNfoProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs index 3bbfa6e83..d69cdc90a 100644 --- a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.XbmcMetadata.Providers /// public class ArtistNfoProvider : BaseNfoProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs index 84c99664a..2b1589d47 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs @@ -15,12 +15,12 @@ namespace MediaBrowser.XbmcMetadata.Providers public abstract class BaseVideoNfoProvider : BaseNfoProvider where T : Video, new() { - private readonly ILogger _logger; + private readonly ILogger> _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; public BaseVideoNfoProvider( - ILogger logger, + ILogger> logger, IFileSystem fileSystem, IConfigurationManager config, IProviderManager providerManager) diff --git a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs index b2dc2e38e..26983b1a6 100644 --- a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.XbmcMetadata.Providers /// public class EpisodeNfoProvider : BaseNfoProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs index 63ddd6025..0603fd0d1 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.XbmcMetadata.Providers /// public class SeasonNfoProvider : BaseNfoProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs index d65914542..7e059e0aa 100644 --- a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.XbmcMetadata.Providers /// public class SeriesNfoProvider : BaseNfoProvider { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 90e8b4b99..3602ec14c 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -105,7 +105,7 @@ namespace MediaBrowser.XbmcMetadata.Savers ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, - ILogger logger) + ILogger logger) { Logger = logger; UserDataManager = userDataManager; @@ -125,7 +125,7 @@ namespace MediaBrowser.XbmcMetadata.Savers protected IUserDataManager UserDataManager { get; } - protected ILogger Logger { get; } + protected ILogger Logger { get; } protected ItemUpdateType MinimumUpdateType { @@ -974,7 +974,7 @@ namespace MediaBrowser.XbmcMetadata.Savers => string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - private void AddCustomTags(string path, List xmlTagsUsed, XmlWriter writer, ILogger logger) + private void AddCustomTags(string path, List xmlTagsUsed, XmlWriter writer, ILogger logger) { var settings = new XmlReaderSettings() { -- cgit v1.2.3 From 22a860a8068f502c3b5324c71573af2525a84fca Mon Sep 17 00:00:00 2001 From: aled Date: Sat, 6 Jun 2020 20:17:49 +0100 Subject: Fix a small number of compile warnings --- .../Data/SqliteItemRepository.cs | 6 +-- .../Library/Resolvers/Movies/BoxSetResolver.cs | 2 +- .../Library/Resolvers/Movies/MovieResolver.cs | 4 +- .../Library/Resolvers/TV/SeriesResolver.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 16 ++++---- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- MediaBrowser.Api/Library/LibraryService.cs | 6 +-- MediaBrowser.Api/Movies/MoviesService.cs | 4 +- .../Entities/Audio/MusicAlbum.cs | 4 +- .../Entities/Audio/MusicArtist.cs | 2 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 2 +- MediaBrowser.Controller/Entities/TV/Series.cs | 6 +-- MediaBrowser.Controller/Entities/Trailer.cs | 2 +- .../Entities/UserViewBuilder.cs | 6 +-- MediaBrowser.Controller/Entities/Video.cs | 8 ++-- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 6 +-- .../Parsers/BaseItemXmlParser.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 10 ++--- MediaBrowser.Model/Entities/MetadataProvider.cs | 41 ++++++++++++++++++ MediaBrowser.Model/Entities/MetadataProviders.cs | 41 ------------------ .../Entities/ProviderIdsExtensions.cs | 6 +-- .../MediaInfo/FFProbeAudioInfo.cs | 10 ++--- MediaBrowser.Providers/Movies/MovieExternalIds.cs | 4 +- MediaBrowser.Providers/Music/Extensions.cs | 18 ++++---- .../Plugins/AudioDb/AlbumImageProvider.cs | 2 +- .../Plugins/AudioDb/AlbumProvider.cs | 8 ++-- .../Plugins/AudioDb/ArtistImageProvider.cs | 2 +- .../Plugins/AudioDb/ArtistProvider.cs | 4 +- .../Plugins/AudioDb/ExternalIds.cs | 8 ++-- .../Plugins/MusicBrainz/AlbumProvider.cs | 10 ++--- .../Plugins/MusicBrainz/ArtistProvider.cs | 6 +-- .../Plugins/MusicBrainz/ExternalIds.cs | 12 +++--- .../Plugins/Omdb/OmdbEpisodeProvider.cs | 4 +- .../Plugins/Omdb/OmdbImageProvider.cs | 2 +- .../Plugins/Omdb/OmdbItemProvider.cs | 18 ++++---- .../Plugins/Omdb/OmdbProvider.cs | 6 +-- .../Plugins/TheTvdb/TvdbClientManager.cs | 2 +- .../Plugins/TheTvdb/TvdbEpisodeImageProvider.cs | 4 +- .../Plugins/TheTvdb/TvdbEpisodeProvider.cs | 6 +-- .../Plugins/TheTvdb/TvdbPersonImageProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbSeasonImageProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbSeriesImageProvider.cs | 2 +- .../Plugins/TheTvdb/TvdbSeriesProvider.cs | 42 +++++++++---------- .../Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs | 2 +- .../Tmdb/BoxSets/TmdbBoxSetImageProvider.cs | 2 +- .../Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 10 ++--- .../Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs | 16 ++++---- .../Plugins/Tmdb/Movies/TmdbImageProvider.cs | 4 +- .../Plugins/Tmdb/Movies/TmdbMovieExternalId.cs | 2 +- .../Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 6 +-- .../Plugins/Tmdb/Movies/TmdbSearch.cs | 4 +- .../Plugins/Tmdb/People/TmdbPersonExternalId.cs | 2 +- .../Plugins/Tmdb/People/TmdbPersonImageProvider.cs | 2 +- .../Plugins/Tmdb/People/TmdbPersonProvider.cs | 16 ++++---- .../Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbEpisodeProvider.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeriesExternalId.cs | 2 +- .../Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbSeriesProvider.cs | 36 ++++++++-------- .../TV/MissingEpisodeProvider.cs | 2 +- MediaBrowser.Providers/TV/TvExternalIds.cs | 8 ++-- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 6 +-- .../Parsers/MovieNfoParser.cs | 6 +-- .../Parsers/SeriesNfoParser.cs | 6 +-- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 48 +++++++++++----------- MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs | 2 +- 69 files changed, 275 insertions(+), 275 deletions(-) create mode 100644 MediaBrowser.Model/Entities/MetadataProvider.cs delete mode 100644 MediaBrowser.Model/Entities/MetadataProviders.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 18d235c87..03581dae2 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2734,7 +2734,7 @@ namespace Emby.Server.Implementations.Data foreach (var providerId in newItem.ProviderIds) { - if (providerId.Key == MetadataProviders.TmdbCollection.ToString()) + if (providerId.Key == MetadataProvider.TmdbCollection.ToString()) { continue; } @@ -4324,7 +4324,7 @@ namespace Emby.Server.Implementations.Data var index = 0; foreach (var pair in query.ExcludeProviderIds) { - if (string.Equals(pair.Key, MetadataProviders.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Key, MetadataProvider.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) { continue; } @@ -4353,7 +4353,7 @@ namespace Emby.Server.Implementations.Data var index = 0; foreach (var pair in query.HasAnyProviderId) { - if (string.Equals(pair.Key, MetadataProviders.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) + if (string.Equals(pair.Key, MetadataProvider.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index e4bc4a469..295e9e120 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -69,7 +69,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrEmpty(id)) { - item.SetProviderId(MetadataProviders.Tmdb, id); + item.SetProviderId(MetadataProvider.Tmdb, id); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index cb67c8aa7..baf0e3cf9 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -350,7 +350,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrWhiteSpace(tmdbid)) { - item.SetProviderId(MetadataProviders.Tmdb, tmdbid); + item.SetProviderId(MetadataProvider.Tmdb, tmdbid); } } @@ -361,7 +361,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrWhiteSpace(imdbid)) { - item.SetProviderId(MetadataProviders.Imdb, imdbid); + item.SetProviderId(MetadataProvider.Imdb, imdbid); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index dd6bd8ee8..b2627f044 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -217,7 +217,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if (!string.IsNullOrEmpty(id)) { - item.SetProviderId(MetadataProviders.Tvdb, id); + item.SetProviderId(MetadataProvider.Tvdb, id); } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 5a5dc3329..0ee2872c4 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1893,22 +1893,22 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteStartDocument(true); writer.WriteStartElement("tvshow"); string id; - if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id)) + if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id)) { writer.WriteElementString("id", id); } - if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id)) + if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out id)) { writer.WriteElementString("imdb_id", id); } - if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out id)) + if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out id)) { writer.WriteElementString("tmdbid", id); } - if (timer.SeriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out id)) + if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out id)) { writer.WriteElementString("zap2itid", id); } @@ -2075,14 +2075,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString("credits", person); } - var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); + var tmdbCollection = item.GetProviderId(MetadataProvider.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) { writer.WriteElementString("collectionnumber", tmdbCollection); } - var imdb = item.GetProviderId(MetadataProviders.Imdb); + var imdb = item.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdb)) { if (!isSeriesEpisode) @@ -2096,7 +2096,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV lockData = false; } - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + var tvdb = item.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdb)) { writer.WriteElementString("tvdbid", tvdb); @@ -2105,7 +2105,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV lockData = false; } - var tmdb = item.GetProviderId(MetadataProviders.Tmdb); + var tmdb = item.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdb)) { writer.WriteElementString("tmdbid", tmdb); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 89b81fd96..d82d554eb 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -342,7 +342,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { info.SeriesId = programId.Substring(0, 10); - info.SeriesProviderIds[MetadataProviders.Zap2It.ToString()] = info.SeriesId; + info.SeriesProviderIds[MetadataProvider.Zap2It.ToString()] = info.SeriesId; if (details.metadata != null) { diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index c0146dfee..9d53a2610 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -655,7 +655,7 @@ namespace MediaBrowser.Api.Library EnableImages = false } - }).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray(); + }).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProvider.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray(); foreach (var item in series) { @@ -688,11 +688,11 @@ namespace MediaBrowser.Api.Library if (!string.IsNullOrWhiteSpace(request.ImdbId)) { - movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)).ToList(); + movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProvider.Imdb), StringComparison.OrdinalIgnoreCase)).ToList(); } else if (!string.IsNullOrWhiteSpace(request.TmdbId)) { - movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)).ToList(); + movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProvider.Tmdb), StringComparison.OrdinalIgnoreCase)).ToList(); } else { diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index cdd027634..a9c7f5d6f 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -273,7 +273,7 @@ namespace MediaBrowser.Api.Movies EnableGroupByMetadataKey = true, DtoOptions = dtoOptions - }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) + }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) .Select(x => x.First()) .Take(itemLimit) .ToList(); @@ -314,7 +314,7 @@ namespace MediaBrowser.Api.Movies EnableGroupByMetadataKey = true, DtoOptions = dtoOptions - }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) + }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) .Select(x => x.First()) .Take(itemLimit) .ToList(); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index c216176e7..b702bdb71 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -97,14 +97,14 @@ namespace MediaBrowser.Controller.Entities.Audio list.Insert(0, albumArtist + "-" + Name); } - var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); + var id = this.GetProviderId(MetadataProvider.MusicBrainzAlbum); if (!string.IsNullOrEmpty(id)) { list.Insert(0, "MusicAlbum-Musicbrainz-" + id); } - id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + id = this.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup); if (!string.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 5e3056ccb..31136e004 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Controller.Entities.Audio private static List GetUserDataKeys(MusicArtist item) { var list = new List(); - var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); + var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist); if (!string.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 11dc472b6..d5c9ff025 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.Controller.Entities.Movies { var list = base.GetRelatedUrls(); - var imdbId = this.GetProviderId(MetadataProviders.Imdb); + var imdbId = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { list.Add(new ExternalUrl diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 2475b2b7e..6f1c2501f 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -164,13 +164,13 @@ namespace MediaBrowser.Controller.Entities.TV { var list = base.GetUserDataKeys(); - var key = this.GetProviderId(MetadataProviders.Imdb); + var key = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); } - key = this.GetProviderId(MetadataProviders.Tvdb); + key = this.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); @@ -493,7 +493,7 @@ namespace MediaBrowser.Controller.Entities.TV { var list = base.GetRelatedUrls(); - var imdbId = this.GetProviderId(MetadataProviders.Imdb); + var imdbId = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { list.Add(new ExternalUrl diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 0b8be90cd..7159b5b1a 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Entities { var list = base.GetRelatedUrls(); - var imdbId = this.GetProviderId(MetadataProviders.Imdb); + var imdbId = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { list.Add(new ExternalUrl diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 435a1e8da..029602196 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -611,7 +611,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasImdbId.Value; - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Imdb)); + var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Imdb)); if (hasValue != filterValue) { @@ -623,7 +623,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasTmdbId.Value; - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb)); + var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tmdb)); if (hasValue != filterValue) { @@ -635,7 +635,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasTvdbId.Value; - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tvdb)); + var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tvdb)); if (hasValue != filterValue) { diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index c3ea7f347..72eb67a06 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -272,13 +272,13 @@ namespace MediaBrowser.Controller.Entities { if (ExtraType.HasValue) { - var key = this.GetProviderId(MetadataProviders.Tmdb); + var key = this.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, GetUserDataKey(key)); } - key = this.GetProviderId(MetadataProviders.Imdb); + key = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, GetUserDataKey(key)); @@ -286,13 +286,13 @@ namespace MediaBrowser.Controller.Entities } else { - var key = this.GetProviderId(MetadataProviders.Imdb); + var key = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); } - key = this.GetProviderId(MetadataProviders.Tmdb); + key = this.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 13df85aed..e89bc05aa 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -26,13 +26,13 @@ namespace MediaBrowser.Controller.LiveTv if (!IsSeries) { - var key = this.GetProviderId(MetadataProviders.Imdb); + var key = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); } - key = this.GetProviderId(MetadataProviders.Tmdb); + key = this.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(key)) { list.Insert(0, key); @@ -253,7 +253,7 @@ namespace MediaBrowser.Controller.LiveTv { var list = base.GetRelatedUrls(); - var imdbId = this.GetProviderId(MetadataProviders.Imdb); + var imdbId = this.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { if (IsMovie) diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index d4b98182f..2e0dade07 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -543,7 +543,7 @@ namespace MediaBrowser.LocalMetadata.Parsers var tmdbCollection = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(tmdbCollection)) { - item.SetProviderId(MetadataProviders.TmdbCollection, tmdbCollection); + item.SetProviderId(MetadataProvider.TmdbCollection, tmdbCollection); } break; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index d3f8094b9..9386d6524 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1057,23 +1057,23 @@ namespace MediaBrowser.MediaEncoding.Probing // These support mulitple values, but for now we only store the first. var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mb); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - audio.SetProviderId(MetadataProviders.MusicBrainzArtist, mb); + audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, mb); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, mb); + audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - audio.SetProviderId(MetadataProviders.MusicBrainzTrack, mb); + audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } private string GetMultipleMusicBrainzId(string value) diff --git a/MediaBrowser.Model/Entities/MetadataProvider.cs b/MediaBrowser.Model/Entities/MetadataProvider.cs new file mode 100644 index 000000000..bcc2b48e7 --- /dev/null +++ b/MediaBrowser.Model/Entities/MetadataProvider.cs @@ -0,0 +1,41 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Entities +{ + /// + /// Enum MetadataProviders + /// + public enum MetadataProvider + { + /// + /// The imdb + /// + Imdb = 2, + /// + /// The TMDB + /// + Tmdb = 3, + /// + /// The TVDB + /// + Tvdb = 4, + /// + /// The tvcom + /// + Tvcom = 5, + /// + /// Tmdb Collection Id + /// + TmdbCollection = 7, + MusicBrainzAlbum = 8, + MusicBrainzAlbumArtist = 9, + MusicBrainzArtist = 10, + MusicBrainzReleaseGroup = 11, + Zap2It = 12, + TvRage = 15, + AudioDbArtist = 16, + AudioDbAlbum = 17, + MusicBrainzTrack = 18, + TvMaze = 19 + } +} diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs deleted file mode 100644 index 1a44a1661..000000000 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ /dev/null @@ -1,41 +0,0 @@ -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Entities -{ - /// - /// Enum MetadataProviders - /// - public enum MetadataProviders - { - /// - /// The imdb - /// - Imdb = 2, - /// - /// The TMDB - /// - Tmdb = 3, - /// - /// The TVDB - /// - Tvdb = 4, - /// - /// The tvcom - /// - Tvcom = 5, - /// - /// Tmdb Collection Id - /// - TmdbCollection = 7, - MusicBrainzAlbum = 8, - MusicBrainzAlbumArtist = 9, - MusicBrainzArtist = 10, - MusicBrainzReleaseGroup = 11, - Zap2It = 12, - TvRage = 15, - AudioDbArtist = 16, - AudioDbAlbum = 17, - MusicBrainzTrack = 18, - TvMaze = 19 - } -} diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index e089dd1e5..9c11fe0ad 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Model.Entities /// The instance. /// The provider. /// true if [has provider identifier] [the specified instance]; otherwise, false. - public static bool HasProviderId(this IHasProviderIds instance, MetadataProviders provider) + public static bool HasProviderId(this IHasProviderIds instance, MetadataProvider provider) { return !string.IsNullOrEmpty(instance.GetProviderId(provider.ToString())); } @@ -25,7 +25,7 @@ namespace MediaBrowser.Model.Entities /// The instance. /// The provider. /// System.String. - public static string? GetProviderId(this IHasProviderIds instance, MetadataProviders provider) + public static string? GetProviderId(this IHasProviderIds instance, MetadataProvider provider) { return instance.GetProviderId(provider.ToString()); } @@ -94,7 +94,7 @@ namespace MediaBrowser.Model.Entities /// The instance. /// The provider. /// The value. - public static void SetProviderId(this IHasProviderIds instance, MetadataProviders provider, string value) + public static void SetProviderId(this IHasProviderIds instance, MetadataProvider provider, string value) { instance.SetProviderId(provider.ToString(), value); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 207d75524..16d914e2d 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -158,11 +158,11 @@ namespace MediaBrowser.Providers.MediaInfo audio.SetStudios(data.Studios); } - audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist)); - audio.SetProviderId(MetadataProviders.MusicBrainzArtist, data.GetProviderId(MetadataProviders.MusicBrainzArtist)); - audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, data.GetProviderId(MetadataProviders.MusicBrainzAlbum)); - audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup)); - audio.SetProviderId(MetadataProviders.MusicBrainzTrack, data.GetProviderId(MetadataProviders.MusicBrainzTrack)); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist)); + audio.SetProviderId(MetadataProvider.MusicBrainzArtist, data.GetProviderId(MetadataProvider.MusicBrainzArtist)); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, data.GetProviderId(MetadataProvider.MusicBrainzAlbum)); + audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup)); + audio.SetProviderId(MetadataProvider.MusicBrainzTrack, data.GetProviderId(MetadataProvider.MusicBrainzTrack)); } } } diff --git a/MediaBrowser.Providers/Movies/MovieExternalIds.cs b/MediaBrowser.Providers/Movies/MovieExternalIds.cs index 55810b1ed..1f07deacf 100644 --- a/MediaBrowser.Providers/Movies/MovieExternalIds.cs +++ b/MediaBrowser.Providers/Movies/MovieExternalIds.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Movies public string Name => "IMDb"; /// - public string Key => MetadataProviders.Imdb.ToString(); + public string Key => MetadataProvider.Imdb.ToString(); /// public string UrlFormatString => "https://www.imdb.com/title/{0}"; @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Movies public string Name => "IMDb"; /// - public string Key => MetadataProviders.Imdb.ToString(); + public string Key => MetadataProvider.Imdb.ToString(); /// public string UrlFormatString => "https://www.imdb.com/name/{0}"; diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/Extensions.cs index ea1efe266..a1d5aa826 100644 --- a/MediaBrowser.Providers/Music/Extensions.cs +++ b/MediaBrowser.Providers/Music/Extensions.cs @@ -21,11 +21,11 @@ namespace MediaBrowser.Providers.Music public static string GetReleaseGroupId(this AlbumInfo info) { - var id = info.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + var id = info.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup); if (string.IsNullOrEmpty(id)) { - return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup)) + return info.SongInfos.Select(i => i.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); } @@ -34,11 +34,11 @@ namespace MediaBrowser.Providers.Music public static string GetReleaseId(this AlbumInfo info) { - var id = info.GetProviderId(MetadataProviders.MusicBrainzAlbum); + var id = info.GetProviderId(MetadataProvider.MusicBrainzAlbum); if (string.IsNullOrEmpty(id)) { - return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbum)) + return info.SongInfos.Select(i => i.GetProviderId(MetadataProvider.MusicBrainzAlbum)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); } @@ -47,16 +47,16 @@ namespace MediaBrowser.Providers.Music public static string GetMusicBrainzArtistId(this AlbumInfo info) { - info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzAlbumArtist.ToString(), out string id); + info.ProviderIds.TryGetValue(MetadataProvider.MusicBrainzAlbumArtist.ToString(), out string id); if (string.IsNullOrEmpty(id)) { - info.ArtistProviderIds.TryGetValue(MetadataProviders.MusicBrainzArtist.ToString(), out id); + info.ArtistProviderIds.TryGetValue(MetadataProvider.MusicBrainzArtist.ToString(), out id); } if (string.IsNullOrEmpty(id)) { - return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist)) + return info.SongInfos.Select(i => i.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); } @@ -65,11 +65,11 @@ namespace MediaBrowser.Providers.Music public static string GetMusicBrainzArtistId(this ArtistInfo info) { - info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzArtist.ToString(), out var id); + info.ProviderIds.TryGetValue(MetadataProvider.MusicBrainzArtist.ToString(), out var id); if (string.IsNullOrEmpty(id)) { - return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist)) + return info.SongInfos.Select(i => i.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist)) .FirstOrDefault(i => !string.IsNullOrEmpty(i)); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index dee2d59f0..3c314acb3 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb /// public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) { - var id = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + var id = item.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup); if (!string.IsNullOrWhiteSpace(id)) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 1a0e87871..b1a54f22f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -104,11 +104,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb item.Genres = new[] { result.strGenre }; } - item.SetProviderId(MetadataProviders.AudioDbArtist, result.idArtist); - item.SetProviderId(MetadataProviders.AudioDbAlbum, result.idAlbum); + item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist); + item.SetProviderId(MetadataProvider.AudioDbAlbum, result.idAlbum); - item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID); - item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, result.strMusicBrainzID); + item.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID); + item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, result.strMusicBrainzID); string overview = null; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index 18afd5dd5..04cdab66a 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb /// public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) { - var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); + var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist); if (!string.IsNullOrWhiteSpace(id)) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index df0f3df8f..d8a18a6bc 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -92,8 +92,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb item.Genres = new[] { result.strGenre }; } - item.SetProviderId(MetadataProviders.AudioDbArtist, result.idArtist); - item.SetProviderId(MetadataProviders.MusicBrainzArtist, result.strMusicBrainzID); + item.SetProviderId(MetadataProvider.AudioDbArtist, result.idArtist); + item.SetProviderId(MetadataProvider.MusicBrainzArtist, result.strMusicBrainzID); string overview = null; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs b/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs index 2d8cb431c..478ea5190 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public string Name => "TheAudioDb"; /// - public string Key => MetadataProviders.AudioDbAlbum.ToString(); + public string Key => MetadataProvider.AudioDbAlbum.ToString(); /// public string UrlFormatString => "https://www.theaudiodb.com/album/{0}"; @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public string Name => "TheAudioDb Album"; /// - public string Key => MetadataProviders.AudioDbAlbum.ToString(); + public string Key => MetadataProvider.AudioDbAlbum.ToString(); /// public string UrlFormatString => "https://www.theaudiodb.com/album/{0}"; @@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public string Name => "TheAudioDb"; /// - public string Key => MetadataProviders.AudioDbArtist.ToString(); + public string Key => MetadataProvider.AudioDbArtist.ToString(); /// public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}"; @@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public string Name => "TheAudioDb Artist"; /// - public string Key => MetadataProviders.AudioDbArtist.ToString(); + public string Key => MetadataProvider.AudioDbArtist.ToString(); /// public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}"; diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 31cdaf616..10dc73924 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -163,17 +163,17 @@ namespace MediaBrowser.Providers.Music Name = i.Artists[0].Item1 }; - result.AlbumArtist.SetProviderId(MetadataProviders.MusicBrainzArtist, i.Artists[0].Item2); + result.AlbumArtist.SetProviderId(MetadataProvider.MusicBrainzArtist, i.Artists[0].Item2); } if (!string.IsNullOrWhiteSpace(i.ReleaseId)) { - result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseId); + result.SetProviderId(MetadataProvider.MusicBrainzAlbum, i.ReleaseId); } if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId)) { - result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId); + result.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, i.ReleaseGroupId); } return result; @@ -247,12 +247,12 @@ namespace MediaBrowser.Providers.Music { if (!string.IsNullOrEmpty(releaseId)) { - result.Item.SetProviderId(MetadataProviders.MusicBrainzAlbum, releaseId); + result.Item.SetProviderId(MetadataProvider.MusicBrainzAlbum, releaseId); } if (!string.IsNullOrEmpty(releaseGroupId)) { - result.Item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, releaseGroupId); + result.Item.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, releaseGroupId); } } diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index 260a3b6e7..9d93dbdd1 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -216,7 +216,7 @@ namespace MediaBrowser.Providers.Music } } - result.SetProviderId(MetadataProviders.MusicBrainzArtist, artistId); + result.SetProviderId(MetadataProvider.MusicBrainzArtist, artistId); if (string.IsNullOrWhiteSpace(artistId) || string.IsNullOrWhiteSpace(result.Name)) { @@ -249,7 +249,7 @@ namespace MediaBrowser.Providers.Music if (singleResult != null) { - musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); + musicBrainzId = singleResult.GetProviderId(MetadataProvider.MusicBrainzArtist); result.Item.Overview = singleResult.Overview; if (Plugin.Instance.Configuration.ReplaceArtistName) @@ -262,7 +262,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrWhiteSpace(musicBrainzId)) { result.HasMetadata = true; - result.Item.SetProviderId(MetadataProviders.MusicBrainzArtist, musicBrainzId); + result.Item.SetProviderId(MetadataProvider.MusicBrainzArtist, musicBrainzId); } return result; diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs index 03565a34c..3be6f570b 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ExternalIds.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Providers.Music public string Name => "MusicBrainz Release Group"; /// - public string Key => MetadataProviders.MusicBrainzReleaseGroup.ToString(); + public string Key => MetadataProvider.MusicBrainzReleaseGroup.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release-group/{0}"; @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Music public string Name => "MusicBrainz Album Artist"; /// - public string Key => MetadataProviders.MusicBrainzAlbumArtist.ToString(); + public string Key => MetadataProvider.MusicBrainzAlbumArtist.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}"; @@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Music public string Name => "MusicBrainz Album"; /// - public string Key => MetadataProviders.MusicBrainzAlbum.ToString(); + public string Key => MetadataProvider.MusicBrainzAlbum.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/release/{0}"; @@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.Music public string Name => "MusicBrainz"; /// - public string Key => MetadataProviders.MusicBrainzArtist.ToString(); + public string Key => MetadataProvider.MusicBrainzArtist.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}"; @@ -72,7 +72,7 @@ namespace MediaBrowser.Providers.Music /// - public string Key => MetadataProviders.MusicBrainzArtist.ToString(); + public string Key => MetadataProvider.MusicBrainzArtist.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/artist/{0}"; @@ -87,7 +87,7 @@ namespace MediaBrowser.Providers.Music public string Name => "MusicBrainz Track"; /// - public string Key => MetadataProviders.MusicBrainzTrack.ToString(); + public string Key => MetadataProvider.MusicBrainzTrack.ToString(); /// public string UrlFormatString => Plugin.Instance.Configuration.Server + "/track/{0}"; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs index f0328e8d8..b074a1b0a 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs @@ -63,12 +63,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb return result; } - if (info.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out string seriesImdbId) && !string.IsNullOrEmpty(seriesImdbId)) + if (info.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string seriesImdbId) && !string.IsNullOrEmpty(seriesImdbId)) { if (info.IndexNumber.HasValue && info.ParentIndexNumber.HasValue) { result.HasMetadata = await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager) - .FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, info.GetProviderId(MetadataProviders.Imdb), seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); + .FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, info.GetProviderId(MetadataProvider.Imdb), seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs index 3cf4c3d50..d78a37784 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) { - var imdbId = item.GetProviderId(MetadataProviders.Imdb); + var imdbId = item.GetProviderId(MetadataProvider.Imdb); var list = new List(); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 35a840f00..4a29ba4d0 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -68,12 +68,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb { var episodeSearchInfo = searchInfo as EpisodeInfo; - var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); + var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); var urlQuery = "plot=full&r=json"; if (type == "episode" && episodeSearchInfo != null) { - episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); + episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out imdbId); } var name = searchInfo.Name; @@ -165,7 +165,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value; } - item.SetProviderId(MetadataProviders.Imdb, result.imdbID); + item.SetProviderId(MetadataProvider.Imdb, result.imdbID); if (result.Year.Length > 0 && int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) @@ -210,7 +210,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb QueriedById = true }; - var imdbId = info.GetProviderId(MetadataProviders.Imdb); + var imdbId = info.GetProviderId(MetadataProvider.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { imdbId = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false); @@ -219,7 +219,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (!string.IsNullOrEmpty(imdbId)) { - result.Item.SetProviderId(MetadataProviders.Imdb, imdbId); + result.Item.SetProviderId(MetadataProvider.Imdb, imdbId); result.HasMetadata = true; await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); @@ -242,7 +242,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb QueriedById = true }; - var imdbId = info.GetProviderId(MetadataProviders.Imdb); + var imdbId = info.GetProviderId(MetadataProvider.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false); @@ -251,7 +251,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (!string.IsNullOrEmpty(imdbId)) { - result.Item.SetProviderId(MetadataProviders.Imdb, imdbId); + result.Item.SetProviderId(MetadataProvider.Imdb, imdbId); result.HasMetadata = true; await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); @@ -264,14 +264,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb { var results = await GetSearchResultsInternal(info, "movie", false, cancellationToken).ConfigureAwait(false); var first = results.FirstOrDefault(); - return first == null ? null : first.GetProviderId(MetadataProviders.Imdb); + return first == null ? null : first.GetProviderId(MetadataProvider.Imdb); } private async Task GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken) { var results = await GetSearchResultsInternal(info, "series", false, cancellationToken).ConfigureAwait(false); var first = results.FirstOrDefault(); - return first == null ? null : first.GetProviderId(MetadataProviders.Imdb); + return first == null ? null : first.GetProviderId(MetadataProvider.Imdb); } public Task GetImageResponse(string url, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index dcc003dca..19b4bd1e3 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (!string.IsNullOrWhiteSpace(result.imdbID)) { - item.SetProviderId(MetadataProviders.Imdb, result.imdbID); + item.SetProviderId(MetadataProvider.Imdb, result.imdbID); } ParseAdditionalMetadata(itemResult, result); @@ -195,7 +195,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (!string.IsNullOrWhiteSpace(result.imdbID)) { - item.SetProviderId(MetadataProviders.Imdb, result.imdbID); + item.SetProviderId(MetadataProvider.Imdb, result.imdbID); } ParseAdditionalMetadata(itemResult, result); @@ -243,7 +243,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb internal static bool IsValidSeries(Dictionary seriesProviderIds) { - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out string id) && !string.IsNullOrEmpty(id)) + if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string id) && !string.IsNullOrEmpty(id)) { // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet. if (!string.IsNullOrWhiteSpace(id)) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs index 24d60deb9..38e887be1 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb string language, CancellationToken cancellationToken) { - searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), + searchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out var seriesTvdbId); var episodeQuery = new EpisodeQuery(); diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs index 6118a9c53..770f6d34b 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb "Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}", episodeInfo.ParentIndexNumber, episodeInfo.IndexNumber, - series.GetProviderId(MetadataProviders.Tvdb)); + series.GetProviderId(MetadataProvider.Tvdb)); return imageResult; } @@ -85,7 +85,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb } catch (TvDbServerException e) { - _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}", series.GetProviderId(MetadataProviders.Tvdb)); + _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}", series.GetProviderId(MetadataProvider.Tvdb)); } } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs index 5a4827d2f..451444382 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb QueriedById = true }; - string seriesTvdbId = searchInfo.GetProviderId(MetadataProviders.Tvdb); + string seriesTvdbId = searchInfo.GetProviderId(MetadataProvider.Tvdb); string episodeTvdbId = null; try { @@ -143,8 +143,8 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb result.ResetPeople(); var item = result.Item; - item.SetProviderId(MetadataProviders.Tvdb, episode.Id.ToString()); - item.SetProviderId(MetadataProviders.Imdb, episode.ImdbId); + item.SetProviderId(MetadataProvider.Tvdb, episode.Id.ToString()); + item.SetProviderId(MetadataProvider.Imdb, episode.ImdbId); if (string.Equals(id.SeriesDisplayOrder, "dvd", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs index 77425f1d2..19ca3dc90 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb private async Task GetImageFromSeriesData(Series series, string personName, CancellationToken cancellationToken) { - var tvdbId = Convert.ToInt32(series.GetProviderId(MetadataProviders.Tvdb)); + var tvdbId = Convert.ToInt32(series.GetProviderId(MetadataProvider.Tvdb)); try { diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs index 7abcd29ec..c820ea5ea 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb return Array.Empty(); } - var tvdbId = Convert.ToInt32(series.GetProviderId(MetadataProviders.Tvdb)); + var tvdbId = Convert.ToInt32(series.GetProviderId(MetadataProvider.Tvdb)); var seasonNumber = season.IndexNumber.Value; var language = item.GetPreferredMetadataLanguage(); var remoteImages = new List(); diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs index f65707291..54aa53173 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var language = item.GetPreferredMetadataLanguage(); var remoteImages = new List(); var keyTypes = new[] { KeyType.Poster, KeyType.Series, KeyType.Fanart }; - var tvdbId = Convert.ToInt32(item.GetProviderId(MetadataProviders.Tvdb)); + var tvdbId = Convert.ToInt32(item.GetProviderId(MetadataProvider.Tvdb)); foreach (KeyType keyType in keyTypes) { var imageQuery = new ImagesQuery diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs index d4fcad643..541471561 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs @@ -95,22 +95,22 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb { var series = result.Item; - if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out var tvdbId) && !string.IsNullOrEmpty(tvdbId)) + if (seriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out var tvdbId) && !string.IsNullOrEmpty(tvdbId)) { - series.SetProviderId(MetadataProviders.Tvdb, tvdbId); + series.SetProviderId(MetadataProvider.Tvdb, tvdbId); } - if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out var imdbId) && !string.IsNullOrEmpty(imdbId)) + if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out var imdbId) && !string.IsNullOrEmpty(imdbId)) { - series.SetProviderId(MetadataProviders.Imdb, imdbId); - tvdbId = await GetSeriesByRemoteId(imdbId, MetadataProviders.Imdb.ToString(), metadataLanguage, + series.SetProviderId(MetadataProvider.Imdb, imdbId); + tvdbId = await GetSeriesByRemoteId(imdbId, MetadataProvider.Imdb.ToString(), metadataLanguage, cancellationToken).ConfigureAwait(false); } - if (seriesProviderIds.TryGetValue(MetadataProviders.Zap2It.ToString(), out var zap2It) && !string.IsNullOrEmpty(zap2It)) + if (seriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out var zap2It) && !string.IsNullOrEmpty(zap2It)) { - series.SetProviderId(MetadataProviders.Zap2It, zap2It); - tvdbId = await GetSeriesByRemoteId(zap2It, MetadataProviders.Zap2It.ToString(), metadataLanguage, + series.SetProviderId(MetadataProvider.Zap2It, zap2It); + tvdbId = await GetSeriesByRemoteId(zap2It, MetadataProvider.Zap2It.ToString(), metadataLanguage, cancellationToken).ConfigureAwait(false); } @@ -150,7 +150,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb try { - if (string.Equals(idType, MetadataProviders.Zap2It.ToString(), StringComparison.OrdinalIgnoreCase)) + if (string.Equals(idType, MetadataProvider.Zap2It.ToString(), StringComparison.OrdinalIgnoreCase)) { result = await _tvdbClientManager.GetSeriesByZap2ItIdAsync(id, language, cancellationToken) .ConfigureAwait(false); @@ -176,9 +176,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb /// True, if the dictionary contains a valid TV provider ID, otherwise false. internal static bool IsValidSeries(Dictionary seriesProviderIds) { - return seriesProviderIds.ContainsKey(MetadataProviders.Tvdb.ToString()) || - seriesProviderIds.ContainsKey(MetadataProviders.Imdb.ToString()) || - seriesProviderIds.ContainsKey(MetadataProviders.Zap2It.ToString()); + return seriesProviderIds.ContainsKey(MetadataProvider.Tvdb.ToString()) || + seriesProviderIds.ContainsKey(MetadataProvider.Imdb.ToString()) || + seriesProviderIds.ContainsKey(MetadataProvider.Zap2It.ToString()); } /// @@ -255,15 +255,15 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var seriesSesult = await _tvdbClientManager.GetSeriesByIdAsync(seriesSearchResult.Id, language, cancellationToken) .ConfigureAwait(false); - remoteSearchResult.SetProviderId(MetadataProviders.Imdb, seriesSesult.Data.ImdbId); - remoteSearchResult.SetProviderId(MetadataProviders.Zap2It, seriesSesult.Data.Zap2itId); + remoteSearchResult.SetProviderId(MetadataProvider.Imdb, seriesSesult.Data.ImdbId); + remoteSearchResult.SetProviderId(MetadataProvider.Zap2It, seriesSesult.Data.Zap2itId); } catch (TvDbServerException e) { _logger.LogError(e, "Unable to retrieve series with id {TvdbId}", seriesSearchResult.Id); } - remoteSearchResult.SetProviderId(MetadataProviders.Tvdb, seriesSearchResult.Id.ToString()); + remoteSearchResult.SetProviderId(MetadataProvider.Tvdb, seriesSearchResult.Id.ToString()); list.Add(new Tuple, RemoteSearchResult>(tvdbTitles, remoteSearchResult)); } @@ -325,15 +325,15 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb private void MapSeriesToResult(MetadataResult result, TvDbSharper.Dto.Series tvdbSeries, string metadataLanguage) { Series series = result.Item; - series.SetProviderId(MetadataProviders.Tvdb, tvdbSeries.Id.ToString()); + series.SetProviderId(MetadataProvider.Tvdb, tvdbSeries.Id.ToString()); series.Name = tvdbSeries.SeriesName; series.Overview = (tvdbSeries.Overview ?? string.Empty).Trim(); result.ResultLanguage = metadataLanguage; series.AirDays = TVUtils.GetAirDays(tvdbSeries.AirsDayOfWeek); series.AirTime = tvdbSeries.AirsTime; series.CommunityRating = (float?)tvdbSeries.SiteRating; - series.SetProviderId(MetadataProviders.Imdb, tvdbSeries.ImdbId); - series.SetProviderId(MetadataProviders.Zap2It, tvdbSeries.Zap2itId); + series.SetProviderId(MetadataProvider.Imdb, tvdbSeries.ImdbId); + series.SetProviderId(MetadataProvider.Zap2It, tvdbSeries.Zap2itId); if (Enum.TryParse(tvdbSeries.Status, true, out SeriesStatus seriesStatus)) { series.Status = seriesStatus; @@ -411,7 +411,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public async Task Identify(SeriesInfo info) { - if (!string.IsNullOrWhiteSpace(info.GetProviderId(MetadataProviders.Tvdb))) + if (!string.IsNullOrWhiteSpace(info.GetProviderId(MetadataProvider.Tvdb))) { return; } @@ -423,8 +423,8 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb if (entry != null) { - var id = entry.GetProviderId(MetadataProviders.Tvdb); - info.SetProviderId(MetadataProviders.Tvdb, id); + var id = entry.GetProviderId(MetadataProvider.Tvdb); + info.SetProviderId(MetadataProvider.Tvdb, id); } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs index a260406da..ad0851cef 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetExternalId.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public string Name => TmdbUtils.ProviderName; /// - public string Key => MetadataProviders.TmdbCollection.ToString(); + public string Key => MetadataProvider.TmdbCollection.ToString(); /// public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "collection/{0}"; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs index c47c8d4e9..23eb00b5c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) { - var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = item.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs index 05c1e3c9d..d3b4bdcff 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public async Task> GetSearchResults(BoxSetInfo searchInfo, CancellationToken cancellationToken) { - var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { @@ -82,7 +82,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].File_Path) }; - result.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture)); + result.SetProviderId(MetadataProvider.Tmdb, info.Id.ToString(_usCulture)); return new[] { result }; } @@ -92,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public async Task> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken) { - var tmdbId = id.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = id.GetProviderId(MetadataProvider.Tmdb); // We don't already have an Id, need to fetch it if (string.IsNullOrEmpty(tmdbId)) @@ -103,7 +103,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets if (searchResult != null) { - tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + tmdbId = searchResult.GetProviderId(MetadataProvider.Tmdb); } } @@ -150,7 +150,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets Overview = obj.Overview }; - item.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture)); + item.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture)); return item; } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs index e1edb50e4..60f37dc17 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -38,8 +38,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies public async Task> GetMetadata(ItemLookupInfo itemId, CancellationToken cancellationToken) { - var tmdbId = itemId.GetProviderId(MetadataProviders.Tmdb); - var imdbId = itemId.GetProviderId(MetadataProviders.Imdb); + var tmdbId = itemId.GetProviderId(MetadataProvider.Tmdb); + var imdbId = itemId.GetProviderId(MetadataProvider.Imdb); // Don't search for music video id's because it is very easy to misidentify. if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo)) @@ -50,7 +50,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (searchResult != null) { - tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + tmdbId = searchResult.GetProviderId(MetadataProvider.Tmdb); } } @@ -146,12 +146,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies .ToArray(); } - movie.SetProviderId(MetadataProviders.Tmdb, movieData.Id.ToString(_usCulture)); - movie.SetProviderId(MetadataProviders.Imdb, movieData.Imdb_Id); + movie.SetProviderId(MetadataProvider.Tmdb, movieData.Id.ToString(_usCulture)); + movie.SetProviderId(MetadataProvider.Imdb, movieData.Imdb_Id); if (movieData.Belongs_To_Collection != null) { - movie.SetProviderId(MetadataProviders.TmdbCollection, + movie.SetProviderId(MetadataProvider.TmdbCollection, movieData.Belongs_To_Collection.Id.ToString(CultureInfo.InvariantCulture)); if (movie is Movie movieItem) @@ -240,7 +240,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (actor.Id > 0) { - personInfo.SetProviderId(MetadataProviders.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture)); + personInfo.SetProviderId(MetadataProvider.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture)); } resultItem.AddPerson(personInfo); @@ -282,7 +282,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (person.Id > 0) { - personInfo.SetProviderId(MetadataProviders.Tmdb, person.Id.ToString(CultureInfo.InvariantCulture)); + personInfo.SetProviderId(MetadataProvider.Tmdb, person.Id.ToString(CultureInfo.InvariantCulture)); } resultItem.AddPerson(personInfo); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs index 3f77860f1..a11c89459 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs @@ -158,11 +158,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies /// Task{MovieImages}. private async Task FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken) { - var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = item.GetProviderId(MetadataProvider.Tmdb); if (string.IsNullOrWhiteSpace(tmdbId)) { - var imdbId = item.GetProviderId(MetadataProviders.Imdb); + var imdbId = item.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrWhiteSpace(imdbId)) { var movieInfo = await TmdbMovieProvider.Current.FetchMainResult(imdbId, false, language, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs index a3fac29e5..7aec27e97 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieExternalId.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies public string Name => TmdbUtils.ProviderName; /// - public string Key => MetadataProviders.Tmdb.ToString(); + public string Key => MetadataProvider.Tmdb.ToString(); /// public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "movie/{0}"; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index d2b5967e4..6830968ee 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies public async Task> GetMovieSearchResults(ItemLookupInfo searchInfo, CancellationToken cancellationToken) { - var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { @@ -100,11 +100,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture)); if (!string.IsNullOrWhiteSpace(obj.Imdb_Id)) { - remoteResult.SetProviderId(MetadataProviders.Imdb, obj.Imdb_Id); + remoteResult.SetProviderId(MetadataProvider.Imdb, obj.Imdb_Id); } return new[] { remoteResult }; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs index 1131e0c72..717aa4eef 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs @@ -199,7 +199,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - remoteResult.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return remoteResult; @@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - remoteResult.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return remoteResult; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs index c7b04e42b..70cd1cd95 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonExternalId.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public string Name => TmdbUtils.ProviderName; /// - public string Key => MetadataProviders.Tmdb.ToString(); + public string Key => MetadataProvider.Tmdb.ToString(); /// public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "person/{0}"; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs index e385207d9..525c0072b 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) { var person = (Person)item; - var id = person.GetProviderId(MetadataProviders.Tmdb); + var id = person.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index bf91406b7..6869788f7 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public async Task> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken) { - var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); @@ -80,8 +80,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].File_Path) }; - result.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture)); - result.SetProviderId(MetadataProviders.Imdb, info.Imdb_Id); + result.SetProviderId(MetadataProvider.Tmdb, info.Id.ToString(_usCulture)); + result.SetProviderId(MetadataProvider.Imdb, info.Imdb_Id); return new[] { result }; } @@ -123,14 +123,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : baseImageUrl + i.Profile_Path }; - result.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture)); + result.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return result; } public async Task> GetMetadata(PersonLookupInfo id, CancellationToken cancellationToken) { - var tmdbId = id.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = id.GetProviderId(MetadataProvider.Tmdb); // We don't already have an Id, need to fetch it if (string.IsNullOrEmpty(tmdbId)) @@ -185,11 +185,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People item.EndDate = date.ToUniversalTime(); } - item.SetProviderId(MetadataProviders.Tmdb, info.Id.ToString(_usCulture)); + item.SetProviderId(MetadataProvider.Tmdb, info.Id.ToString(_usCulture)); if (!string.IsNullOrEmpty(info.Imdb_Id)) { - item.SetProviderId(MetadataProviders.Imdb, info.Imdb_Id); + item.SetProviderId(MetadataProvider.Imdb, info.Imdb_Id); } result.HasMetadata = true; @@ -211,7 +211,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People { var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false); - return results.Select(i => i.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault(); + return results.Select(i => i.GetProviderId(MetadataProvider.Tmdb)).FirstOrDefault(); } internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs index 1d7ad4342..3fa47d54b 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var episode = (Controller.Entities.TV.Episode)item; var series = episode.Series; - var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tmdb) : null; + var seriesId = series != null ? series.GetProviderId(MetadataProvider.Tmdb) : null; var list = new List(); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index d143cbd10..01b295f86 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV return result; } - info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out string seriesTmdbId); + info.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out string seriesTmdbId); if (string.IsNullOrEmpty(seriesTmdbId)) { @@ -109,7 +109,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (response.External_Ids.Tvdb_Id > 0) { - item.SetProviderId(MetadataProviders.Tvdb, response.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture)); + item.SetProviderId(MetadataProvider.Tvdb, response.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture)); } item.PremiereDate = response.Air_Date; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs index eb659253e..b5456b45c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var season = (Season)item; var series = season.Series; - var seriesId = series?.GetProviderId(MetadataProviders.Tmdb); + var seriesId = series?.GetProviderId(MetadataProvider.Tmdb); if (string.IsNullOrEmpty(seriesId)) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index 060ce5503..8eab09c5c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV { var result = new MetadataResult(); - info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out string seriesTmdbId); + info.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out string seriesTmdbId); var seasonNumber = info.IndexNumber; @@ -73,7 +73,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (seasonInfo.External_Ids.Tvdb_Id > 0) { - result.Item.SetProviderId(MetadataProviders.Tvdb, seasonInfo.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture)); + result.Item.SetProviderId(MetadataProvider.Tvdb, seasonInfo.External_Ids.Tvdb_Id.ToString(CultureInfo.InvariantCulture)); } var credits = seasonInfo.Credits; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs index 41fb96882..705f8041b 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesExternalId.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public string Name => TmdbUtils.ProviderName; /// - public string Key => MetadataProviders.Tmdb.ToString(); + public string Key => MetadataProvider.Tmdb.ToString(); /// public string UrlFormatString => TmdbUtils.BaseTmdbUrl + "tv/{0}"; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs index 30a5295f3..40824d88d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs @@ -151,7 +151,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV private async Task FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer, CancellationToken cancellationToken) { - var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = item.GetProviderId(MetadataProvider.Tmdb); if (string.IsNullOrEmpty(tmdbId)) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index bed26cee9..5904347f0 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public async Task> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { - var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { @@ -85,18 +85,18 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV ImageUrl = string.IsNullOrWhiteSpace(obj.Poster_Path) ? null : tmdbImageUrl + obj.Poster_Path }; - remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.Id.ToString(_usCulture)); - remoteResult.SetProviderId(MetadataProviders.Imdb, obj.External_Ids.Imdb_Id); + remoteResult.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Imdb, obj.External_Ids.Imdb_Id); if (obj.External_Ids.Tvdb_Id > 0) { - remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.External_Ids.Tvdb_Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Tvdb, obj.External_Ids.Tvdb_Id.ToString(_usCulture)); } return new[] { remoteResult }; } - var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); + var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { @@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } } - var tvdbId = searchInfo.GetProviderId(MetadataProviders.Tvdb); + var tvdbId = searchInfo.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdbId)) { @@ -128,11 +128,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var result = new MetadataResult(); result.QueriedById = true; - var tmdbId = info.GetProviderId(MetadataProviders.Tmdb); + var tmdbId = info.GetProviderId(MetadataProvider.Tmdb); if (string.IsNullOrEmpty(tmdbId)) { - var imdbId = info.GetProviderId(MetadataProviders.Imdb); + var imdbId = info.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { @@ -140,14 +140,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (searchResult != null) { - tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + tmdbId = searchResult.GetProviderId(MetadataProvider.Tmdb); } } } if (string.IsNullOrEmpty(tmdbId)) { - var tvdbId = info.GetProviderId(MetadataProviders.Tvdb); + var tvdbId = info.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdbId)) { @@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (searchResult != null) { - tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + tmdbId = searchResult.GetProviderId(MetadataProvider.Tmdb); } } } @@ -169,7 +169,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (searchResult != null) { - tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + tmdbId = searchResult.GetProviderId(MetadataProvider.Tmdb); } } @@ -219,7 +219,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV series.Name = seriesInfo.Name; series.OriginalTitle = seriesInfo.Original_Name; - series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.Id.ToString(_usCulture)); + series.SetProviderId(MetadataProvider.Tmdb, seriesInfo.Id.ToString(_usCulture)); string voteAvg = seriesInfo.Vote_Average.ToString(CultureInfo.InvariantCulture); @@ -261,17 +261,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV { if (!string.IsNullOrWhiteSpace(ids.Imdb_Id)) { - series.SetProviderId(MetadataProviders.Imdb, ids.Imdb_Id); + series.SetProviderId(MetadataProvider.Imdb, ids.Imdb_Id); } if (ids.Tvrage_Id > 0) { - series.SetProviderId(MetadataProviders.TvRage, ids.Tvrage_Id.ToString(_usCulture)); + series.SetProviderId(MetadataProvider.TvRage, ids.Tvrage_Id.ToString(_usCulture)); } if (ids.Tvdb_Id > 0) { - series.SetProviderId(MetadataProviders.Tvdb, ids.Tvdb_Id.ToString(_usCulture)); + series.SetProviderId(MetadataProvider.Tvdb, ids.Tvdb_Id.ToString(_usCulture)); } } @@ -331,7 +331,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (actor.Id > 0) { - personInfo.SetProviderId(MetadataProviders.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture)); + personInfo.SetProviderId(MetadataProvider.Tmdb, actor.Id.ToString(CultureInfo.InvariantCulture)); } seriesResult.AddPerson(personInfo); @@ -540,7 +540,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV ImageUrl = string.IsNullOrWhiteSpace(tv.Poster_Path) ? null : tmdbImageUrl + tv.Poster_Path }; - remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.Id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProvider.Tmdb, tv.Id.ToString(_usCulture)); return remoteResult; } diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 0721c4bb4..aabad3ada 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.TV public async Task Run(Series series, bool addNewItems, CancellationToken cancellationToken) { - var tvdbId = series.GetProviderId(MetadataProviders.Tvdb); + var tvdbId = series.GetProviderId(MetadataProvider.Tvdb); if (string.IsNullOrEmpty(tvdbId)) { return false; diff --git a/MediaBrowser.Providers/TV/TvExternalIds.cs b/MediaBrowser.Providers/TV/TvExternalIds.cs index baf854285..bd59606e7 100644 --- a/MediaBrowser.Providers/TV/TvExternalIds.cs +++ b/MediaBrowser.Providers/TV/TvExternalIds.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Providers.TV public string Name => "Zap2It"; /// - public string Key => MetadataProviders.Zap2It.ToString(); + public string Key => MetadataProvider.Zap2It.ToString(); /// public string UrlFormatString => "http://tvlistings.zap2it.com/overview.html?programSeriesId={0}"; @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.TV public string Name => "TheTVDB"; /// - public string Key => MetadataProviders.Tvdb.ToString(); + public string Key => MetadataProvider.Tvdb.ToString(); /// public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=series&id={0}"; @@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.TV public string Name => "TheTVDB"; /// - public string Key => MetadataProviders.Tvdb.ToString(); + public string Key => MetadataProvider.Tvdb.ToString(); /// public string UrlFormatString => null; @@ -57,7 +57,7 @@ namespace MediaBrowser.Providers.TV public string Name => "TheTVDB"; /// - public string Key => MetadataProviders.Tvdb.ToString(); + public string Key => MetadataProvider.Tvdb.ToString(); /// public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=episode&id={0}"; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 5c8de80f1..d54796537 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -212,7 +212,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var m = Regex.Match(xml, "tt([0-9]{7,8})", RegexOptions.IgnoreCase); if (m.Success) { - item.SetProviderId(MetadataProviders.Imdb, m.Value); + item.SetProviderId(MetadataProvider.Imdb, m.Value); } // Support Tmdb @@ -225,7 +225,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var tmdbId = xml.Substring(index + srch.Length).TrimEnd('/').Split('-')[0]; if (!string.IsNullOrWhiteSpace(tmdbId) && int.TryParse(tmdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { - item.SetProviderId(MetadataProviders.Tmdb, value.ToString(UsCulture)); + item.SetProviderId(MetadataProvider.Tmdb, value.ToString(UsCulture)); } } @@ -240,7 +240,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var tvdbId = xml.Substring(index + srch.Length).TrimEnd('/'); if (!string.IsNullOrWhiteSpace(tvdbId) && int.TryParse(tvdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { - item.SetProviderId(MetadataProviders.Tvdb, value.ToString(UsCulture)); + item.SetProviderId(MetadataProvider.Tvdb, value.ToString(UsCulture)); } } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index c17212f31..b74a9fd8a 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -49,12 +49,12 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(imdbId)) { - item.SetProviderId(MetadataProviders.Imdb, imdbId); + item.SetProviderId(MetadataProvider.Imdb, imdbId); } if (!string.IsNullOrWhiteSpace(tmdbId)) { - item.SetProviderId(MetadataProviders.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId); } break; @@ -67,7 +67,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var tmdbcolid = reader.GetAttribute("tmdbcolid"); if (!string.IsNullOrWhiteSpace(tmdbcolid) && movie != null) { - movie.SetProviderId(MetadataProviders.TmdbCollection, tmdbcolid); + movie.SetProviderId(MetadataProvider.TmdbCollection, tmdbcolid); } var val = reader.ReadInnerXml(); diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index 0954ae206..f079d4a7e 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -51,17 +51,17 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(imdbId)) { - item.SetProviderId(MetadataProviders.Imdb, imdbId); + item.SetProviderId(MetadataProvider.Imdb, imdbId); } if (!string.IsNullOrWhiteSpace(tmdbId)) { - item.SetProviderId(MetadataProviders.Tmdb, tmdbId); + item.SetProviderId(MetadataProvider.Tmdb, tmdbId); } if (!string.IsNullOrWhiteSpace(tvdbId)) { - item.SetProviderId(MetadataProviders.Tvdb, tvdbId); + item.SetProviderId(MetadataProvider.Tvdb, tvdbId); } break; diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 90e8b4b99..f78034455 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -543,15 +543,15 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("aspectratio", hasAspectRatio.AspectRatio); } - var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); + var tmdbCollection = item.GetProviderId(MetadataProvider.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) { writer.WriteElementString("collectionnumber", tmdbCollection); - writtenProviderIds.Add(MetadataProviders.TmdbCollection.ToString()); + writtenProviderIds.Add(MetadataProvider.TmdbCollection.ToString()); } - var imdb = item.GetProviderId(MetadataProviders.Imdb); + var imdb = item.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdb)) { if (item is Series) @@ -563,25 +563,25 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("imdbid", imdb); } - writtenProviderIds.Add(MetadataProviders.Imdb.ToString()); + writtenProviderIds.Add(MetadataProvider.Imdb.ToString()); } // Series xml saver already saves this if (!(item is Series)) { - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + var tvdb = item.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdb)) { writer.WriteElementString("tvdbid", tvdb); - writtenProviderIds.Add(MetadataProviders.Tvdb.ToString()); + writtenProviderIds.Add(MetadataProvider.Tvdb.ToString()); } } - var tmdb = item.GetProviderId(MetadataProviders.Tmdb); + var tmdb = item.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdb)) { writer.WriteElementString("tmdbid", tmdb); - writtenProviderIds.Add(MetadataProviders.Tmdb.ToString()); + writtenProviderIds.Add(MetadataProvider.Tmdb.ToString()); } if (!string.IsNullOrEmpty(item.PreferredMetadataLanguage)) @@ -686,67 +686,67 @@ namespace MediaBrowser.XbmcMetadata.Savers } } - var externalId = item.GetProviderId(MetadataProviders.AudioDbArtist); + var externalId = item.GetProviderId(MetadataProvider.AudioDbArtist); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("audiodbartistid", externalId); - writtenProviderIds.Add(MetadataProviders.AudioDbArtist.ToString()); + writtenProviderIds.Add(MetadataProvider.AudioDbArtist.ToString()); } - externalId = item.GetProviderId(MetadataProviders.AudioDbAlbum); + externalId = item.GetProviderId(MetadataProvider.AudioDbAlbum); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("audiodbalbumid", externalId); - writtenProviderIds.Add(MetadataProviders.AudioDbAlbum.ToString()); + writtenProviderIds.Add(MetadataProvider.AudioDbAlbum.ToString()); } - externalId = item.GetProviderId(MetadataProviders.Zap2It); + externalId = item.GetProviderId(MetadataProvider.Zap2It); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("zap2itid", externalId); - writtenProviderIds.Add(MetadataProviders.Zap2It.ToString()); + writtenProviderIds.Add(MetadataProvider.Zap2It.ToString()); } - externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum); + externalId = item.GetProviderId(MetadataProvider.MusicBrainzAlbum); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("musicbrainzalbumid", externalId); - writtenProviderIds.Add(MetadataProviders.MusicBrainzAlbum.ToString()); + writtenProviderIds.Add(MetadataProvider.MusicBrainzAlbum.ToString()); } - externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist); + externalId = item.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("musicbrainzalbumartistid", externalId); - writtenProviderIds.Add(MetadataProviders.MusicBrainzAlbumArtist.ToString()); + writtenProviderIds.Add(MetadataProvider.MusicBrainzAlbumArtist.ToString()); } - externalId = item.GetProviderId(MetadataProviders.MusicBrainzArtist); + externalId = item.GetProviderId(MetadataProvider.MusicBrainzArtist); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("musicbrainzartistid", externalId); - writtenProviderIds.Add(MetadataProviders.MusicBrainzArtist.ToString()); + writtenProviderIds.Add(MetadataProvider.MusicBrainzArtist.ToString()); } - externalId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + externalId = item.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("musicbrainzreleasegroupid", externalId); - writtenProviderIds.Add(MetadataProviders.MusicBrainzReleaseGroup.ToString()); + writtenProviderIds.Add(MetadataProvider.MusicBrainzReleaseGroup.ToString()); } - externalId = item.GetProviderId(MetadataProviders.TvRage); + externalId = item.GetProviderId(MetadataProvider.TvRage); if (!string.IsNullOrEmpty(externalId)) { writer.WriteElementString("tvrageid", externalId); - writtenProviderIds.Add(MetadataProviders.TvRage.ToString()); + writtenProviderIds.Add(MetadataProvider.TvRage.ToString()); } if (item.ProviderIds != null) diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index eef989a5b..dca796415 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.XbmcMetadata.Savers /// protected override void WriteCustomElements(BaseItem item, XmlWriter writer) { - var imdb = item.GetProviderId(MetadataProviders.Imdb); + var imdb = item.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdb)) { diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs index 2a5d36d40..42285db76 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { var series = (Series)item; - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + var tvdb = item.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdb)) { -- cgit v1.2.3 From 0476acf5d557e7b95de2292d70d41b74deeef9ed Mon Sep 17 00:00:00 2001 From: artiume Date: Fri, 29 May 2020 10:20:47 -0400 Subject: Update EncoderValidator.cs --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 8910249af..4250edfb7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -46,13 +46,13 @@ namespace MediaBrowser.MediaEncoding.Encoder "mpeg4_mediacodec", "vp8_mediacodec", "vp9_mediacodec", - "h264_videotoolbox", - "hevc_videotoolbox", - "mpeg2_videotoolbox", - "mpeg4_videotoolbox", - "vp8_videotoolbox", - "vp9_videotoolbox", - "vc1_videotoolbox" + "h264_opencl", + "hevc_opencl", + "mpeg2_opencl", + "mpeg4_opencl", + "vp8_opencl", + "vp9_opencl", + "vc1_opencl" }; private static readonly string[] requiredEncoders = new[] -- cgit v1.2.3 From 33f70bd5f0626f626b374f43277d49fa8e8ba4f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2020 10:30:11 +0000 Subject: Bump System.Text.Encoding.CodePages from 4.7.0 to 4.7.1 Bumps [System.Text.Encoding.CodePages](https://github.com/dotnet/corefx) from 4.7.0 to 4.7.1. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) Signed-off-by: dependabot[bot] --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index af8bee301..aeb4dbe73 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -23,7 +23,7 @@ - + -- cgit v1.2.3 From acd4389653faff01a9c5266d06979d4c20c7d5f5 Mon Sep 17 00:00:00 2001 From: telans Date: Sun, 14 Jun 2020 21:11:11 +1200 Subject: fix SA1005 --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 6 +-- Emby.Dlna/Didl/DidlBuilder.cs | 16 ++++---- Emby.Dlna/Didl/Filter.cs | 2 +- Emby.Dlna/DlnaManager.cs | 8 ++-- Emby.Dlna/Main/DlnaEntryPoint.cs | 2 +- Emby.Dlna/PlayTo/Device.cs | 2 +- Emby.Dlna/PlayTo/PlayToManager.cs | 2 +- Emby.Dlna/Ssdp/DeviceDiscovery.cs | 2 +- .../Channels/ChannelManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 2 +- .../Data/SqliteUserDataRepository.cs | 2 +- .../Devices/DeviceManager.cs | 2 +- Emby.Server.Implementations/Dto/DtoService.cs | 16 ++++---- .../HttpServer/Security/AuthService.cs | 2 +- .../IO/ManagedFileSystem.cs | 2 +- .../Library/LibraryManager.cs | 4 +- .../Library/LiveStreamHelper.cs | 4 +- .../Library/MediaSourceManager.cs | 4 +- .../Library/Resolvers/Audio/AudioResolver.cs | 4 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 2 +- .../Library/Resolvers/BaseVideoResolver.cs | 4 +- .../Library/Resolvers/SpecialFolderResolver.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 10 ++--- .../LiveTv/Listings/SchedulesDirect.cs | 8 ++-- .../LiveTv/LiveTvManager.cs | 14 +++---- .../LiveTv/TunerHosts/BaseTunerHost.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 4 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 14 +++---- .../LiveTv/TunerHosts/M3uParser.cs | 2 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 20 +++++----- Emby.Server.Implementations/Net/SocketFactory.cs | 2 +- .../Networking/NetworkManager.cs | 2 +- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- .../Services/ResponseHelper.cs | 4 +- .../Services/ServiceController.cs | 6 +-- .../Services/ServicePath.cs | 14 +++---- .../Services/StringMapTypeDeserializer.cs | 2 +- .../Sorting/AiredEpisodeOrderComparer.cs | 2 +- Emby.Server.Implementations/TV/TVSeriesManager.cs | 2 +- MediaBrowser.Api/ItemLookupService.cs | 6 +-- MediaBrowser.Api/Movies/MoviesService.cs | 4 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 10 ++--- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 16 ++++---- .../Progressive/BaseProgressiveStreamingService.cs | 2 +- .../Progressive/ProgressiveStreamWriter.cs | 4 +- MediaBrowser.Api/PluginService.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 14 +++---- .../Entities/BasePluginFolder.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 6 +-- .../Entities/UserViewBuilder.cs | 4 +- MediaBrowser.Controller/IO/FileData.cs | 2 +- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 12 +++--- .../Net/BasePeriodicWebSocketListener.cs | 2 +- MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 2 +- .../Parsers/BaseItemXmlParser.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 8 ++-- .../Probing/ProbeResultNormalizer.cs | 12 +++--- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 6 +-- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 8 ++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 8 ++-- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- .../Manager/ItemImageProvider.cs | 2 +- MediaBrowser.Providers/Manager/MetadataService.cs | 10 ++--- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../MediaInfo/FFProbeAudioInfo.cs | 4 +- .../MediaInfo/FFProbeVideoInfo.cs | 4 +- .../MediaInfo/SubtitleResolver.cs | 4 +- .../Plugins/AudioDb/ArtistProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 4 +- .../Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs | 14 +++---- .../Plugins/Tmdb/Movies/TmdbSearch.cs | 4 +- .../Plugins/Tmdb/People/TmdbPersonProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbEpisodeProvider.cs | 6 +-- .../Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 12 +++--- MediaBrowser.Providers/TV/DummySeasonProvider.cs | 6 +-- RSSDP/HttpParserBase.cs | 20 +++++----- RSSDP/SsdpCommunicationsServer.cs | 6 +-- RSSDP/SsdpDeviceLocator.cs | 2 +- RSSDP/SsdpDevicePublisher.cs | 46 +++++++++++----------- 82 files changed, 247 insertions(+), 247 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 27585eafa..de6b619ba 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -466,12 +466,12 @@ namespace Emby.Dlna.ContentDirectory } else if (search.SearchType == SearchType.Playlist) { - //items = items.OfType(); + // items = items.OfType(); isFolder = true; } else if (search.SearchType == SearchType.MusicAlbum) { - //items = items.OfType(); + // items = items.OfType(); isFolder = true; } @@ -926,7 +926,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMovieCollections(User user, InternalItemsQuery query) { query.Recursive = true; - //query.Parent = parent; + // query.Parent = parent; query.SetUser(user); query.IncludeItemTypes = new[] { typeof(BoxSet).Name }; diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 37f5c9249..6ded76f7d 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -98,21 +98,21 @@ namespace Emby.Dlna.Didl { using (var writer = XmlWriter.Create(builder, settings)) { - //writer.WriteStartDocument(); + // writer.WriteStartDocument(); writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL); writer.WriteAttributeString("xmlns", "dc", null, NS_DC); writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA); writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP); - //didl.SetAttribute("xmlns:sec", NS_SEC); + // didl.SetAttribute("xmlns:sec", NS_SEC); WriteXmlRootAttributes(_profile, writer); WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo); writer.WriteFullEndElement(); - //writer.WriteEndDocument(); + // writer.WriteEndDocument(); } return builder.ToString(); @@ -711,7 +711,7 @@ namespace Emby.Dlna.Didl { // Don't filter on dc:title because not all devices will include it in the filter // MediaMonkey for example won't display content without a title - //if (filter.Contains("dc:title")) + // if (filter.Contains("dc:title")) { AddValue(writer, "dc", "title", GetDisplayName(item, itemStubType, context), NS_DC); } @@ -750,7 +750,7 @@ namespace Emby.Dlna.Didl AddValue(writer, "dc", "description", desc, NS_DC); } } - //if (filter.Contains("upnp:longDescription")) + // if (filter.Contains("upnp:longDescription")) //{ // if (!string.IsNullOrWhiteSpace(item.Overview)) // { @@ -1135,7 +1135,7 @@ namespace Emby.Dlna.Didl if (width == 0 || height == 0) { - //_imageProcessor.GetImageSize(item, imageInfo); + // _imageProcessor.GetImageSize(item, imageInfo); width = null; height = null; } @@ -1145,14 +1145,14 @@ namespace Emby.Dlna.Didl height = null; } - //try + // try //{ // var size = _imageProcessor.GetImageSize(imageInfo); // width = size.Width; // height = size.Height; //} - //catch + // catch //{ //} diff --git a/Emby.Dlna/Didl/Filter.cs b/Emby.Dlna/Didl/Filter.cs index 412259e90..e4177239e 100644 --- a/Emby.Dlna/Didl/Filter.cs +++ b/Emby.Dlna/Didl/Filter.cs @@ -26,7 +26,7 @@ namespace Emby.Dlna.Didl { // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back. return true; - //return _all || ListHelper.ContainsIgnoreCase(_fields, field); + // return _all || ListHelper.ContainsIgnoreCase(_fields, field); } } } diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index a85e5c35e..ac9cd0ed3 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -251,7 +251,7 @@ namespace Emby.Dlna return string.Equals(value, header.Value, StringComparison.OrdinalIgnoreCase); case HeaderMatchType.Substring: var isMatch = value.ToString().IndexOf(header.Value, StringComparison.OrdinalIgnoreCase) != -1; - //_logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch); + // _logger.LogDebug("IsMatch-Substring value: {0} testValue: {1} isMatch: {2}", value, header.Value, isMatch); return isMatch; case HeaderMatchType.Regex: return Regex.IsMatch(value, header.Value, RegexOptions.IgnoreCase); @@ -566,9 +566,9 @@ namespace Emby.Dlna new Foobar2000Profile(), new SharpSmartTvProfile(), new MediaMonkeyProfile(), - //new Windows81Profile(), - //new WindowsMediaCenterProfile(), - //new WindowsPhoneProfile(), + // new Windows81Profile(), + // new WindowsMediaCenterProfile(), + // new WindowsPhoneProfile(), new DirectTvProfile(), new DishHopperJoeyProfile(), new DefaultProfile(), diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 47b235e59..a7b1d384d 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -276,7 +276,7 @@ namespace Emby.Dlna.Main var device = new SsdpRootDevice { - CacheLifetime = TimeSpan.FromSeconds(1800), //How long SSDP clients can cache this info. + CacheLifetime = TimeSpan.FromSeconds(1800), // How long SSDP clients can cache this info. Location = uri, // Must point to the URL that serves your devices UPnP description document. Address = address, SubnetMask = _networkManager.GetLocalIpSubnetMask(address), diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index c7431d143..156a1f382 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -750,7 +750,7 @@ namespace Emby.Dlna.PlayTo if (track == null) { - //If track is null, some vendors do this, use GetMediaInfo instead + // If track is null, some vendors do this, use GetMediaInfo instead return (true, null); } diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 9b0339e5d..cd7612483 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -88,7 +88,7 @@ namespace Emby.Dlna.PlayTo if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 && nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1) { - //_logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location); + // _logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location); return; } diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs index ab5e56ab0..7daac96d1 100644 --- a/Emby.Dlna/Ssdp/DeviceDiscovery.cs +++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs @@ -77,7 +77,7 @@ namespace Emby.Dlna.Ssdp // (Optional) Set the filter so we only see notifications for devices we care about // (can be any search target value i.e device type, uuid value etc - any value that appears in the // DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method). - //_DeviceLocator.NotificationFilter = "upnp:rootdevice"; + // _DeviceLocator.NotificationFilter = "upnp:rootdevice"; // Connect our event handler so we process devices as they are found _deviceLocator.DeviceAvailable += OnDeviceLocatorDeviceAvailable; diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 519c5bbef..c803d9d82 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1072,7 +1072,7 @@ namespace Emby.Server.Implementations.Channels } // was used for status - //if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) + // if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) //{ // item.ExternalEtag = info.Etag; // forceUpdate = true; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 43a593f11..ab1fcc638 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4360,7 +4360,7 @@ namespace Emby.Server.Implementations.Data // TODO this seems to be an idea for a better schema where ProviderIds are their own table // buut this is not implemented - //hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); + // hasProviderIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); // TODO this is a really BAD way to do it since the pair: // Tmdb, 1234 matches Tmdb=1234 but also Tmdb=1234567 diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index b99b74ef8..7e66fa072 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -347,7 +347,7 @@ namespace Emby.Server.Implementations.Data var userData = new UserItemData(); userData.Key = reader[0].ToString(); - //userData.UserId = reader[1].ReadGuidFromBlob(); + // userData.UserId = reader[1].ReadGuidFromBlob(); if (reader[2].SQLiteType != SQLiteType.Null) { diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index f8896d69f..789cdfc11 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.Devices { IEnumerable sessions = _authRepo.Get(new AuthenticationInfoQuery { - //UserId = query.UserId + // UserId = query.UserId HasUser = true }).Items; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 040c982ae..aae8fce84 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -946,7 +946,7 @@ namespace Emby.Server.Implementations.Dto dto.AlbumPrimaryImageTag = GetTagAndFillBlurhash(dto, albumParent, ImageType.Primary); } - //if (options.ContainsField(ItemFields.MediaSourceCount)) + // if (options.ContainsField(ItemFields.MediaSourceCount)) //{ // Songs always have one //} @@ -956,13 +956,13 @@ namespace Emby.Server.Implementations.Dto { dto.Artists = hasArtist.Artists; - //var artistItems = _libraryManager.GetArtists(new InternalItemsQuery + // var artistItems = _libraryManager.GetArtists(new InternalItemsQuery //{ // EnableTotalRecordCount = false, // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } //}); - //dto.ArtistItems = artistItems.Items + // dto.ArtistItems = artistItems.Items // .Select(i => // { // var artist = i.Item1; @@ -975,7 +975,7 @@ namespace Emby.Server.Implementations.Dto // .ToList(); // Include artists that are not in the database yet, e.g., just added via metadata editor - //var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); + // var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); dto.ArtistItems = hasArtist.Artists //.Except(foundArtists, new DistinctNameComparer()) .Select(i => @@ -1009,13 +1009,13 @@ namespace Emby.Server.Implementations.Dto { dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); - //var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery + // var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery //{ // EnableTotalRecordCount = false, // ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) } //}); - //dto.AlbumArtists = artistItems.Items + // dto.AlbumArtists = artistItems.Items // .Select(i => // { // var artist = i.Item1; @@ -1165,7 +1165,7 @@ namespace Emby.Server.Implementations.Dto // this block will add the series poster for episodes without a poster // TODO maybe remove the if statement entirely - //if (options.ContainsField(ItemFields.SeriesPrimaryImage)) + // if (options.ContainsField(ItemFields.SeriesPrimaryImage)) { episodeSeries = episodeSeries ?? episode.Series; if (episodeSeries != null) @@ -1211,7 +1211,7 @@ namespace Emby.Server.Implementations.Dto // this block will add the series poster for seasons without a poster // TODO maybe remove the if statement entirely - //if (options.ContainsField(ItemFields.SeriesPrimaryImage)) + // if (options.ContainsField(ItemFields.SeriesPrimaryImage)) { series = series ?? season.Series; if (series != null) diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 072e94cdd..72959003a 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -225,7 +225,7 @@ namespace Emby.Server.Implementations.HttpServer.Security throw new AuthenticationException("Access token is invalid or expired."); } - //if (!string.IsNullOrEmpty(info.UserId)) + // if (!string.IsNullOrEmpty(info.UserId)) //{ // var user = _userManager.GetUserById(info.UserId); diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 2bcfc82b6..a7bbf6acc 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO { result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; - //if (!result.IsDirectory) + // if (!result.IsDirectory) //{ // result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; //} diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7d74ced6c..4c22a3530 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2595,7 +2595,7 @@ namespace Emby.Server.Implementations.Library Anime series don't generally have a season in their file name, however, tvdb needs a season to correctly get the metadata. Hence, a null season needs to be filled with something. */ - //FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified + // FIXME perhaps this would be better for tvdb parser to ask for season 1 if no season is specified episode.ParentIndexNumber = 1; } @@ -2991,7 +2991,7 @@ namespace Emby.Server.Implementations.Library private static bool ValidateNetworkPath(string path) { - //if (Environment.OSVersion.Platform == PlatformID.Win32NT) + // if (Environment.OSVersion.Platform == PlatformID.Win32NT) //{ // // We can't validate protocol-based paths, so just allow them // if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index ff20ed597..9b9f53049 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Library { mediaInfo = _json.DeserializeFromFile(cacheFilePath); - //_logger.LogDebug("Found cached media info"); + // _logger.LogDebug("Found cached media info"); } catch { @@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.Library Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _json.SerializeToFile(mediaInfo, cacheFilePath); - //_logger.LogDebug("Saved media info to {0}", cacheFilePath); + // _logger.LogDebug("Saved media info to {0}", cacheFilePath); } } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 6fd978844..cee499e78 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -646,7 +646,7 @@ namespace Emby.Server.Implementations.Library { mediaInfo = _jsonSerializer.DeserializeFromFile(cacheFilePath); - //_logger.LogDebug("Found cached media info"); + // _logger.LogDebug("Found cached media info"); } catch (Exception ex) { @@ -682,7 +682,7 @@ namespace Emby.Server.Implementations.Library Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); _jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath); - //_logger.LogDebug("Saved media info to {0}", cacheFilePath); + // _logger.LogDebug("Saved media info to {0}", cacheFilePath); } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index fefc8e789..03059e6d3 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -209,8 +209,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio Name = parseName ? resolvedItem.Name : Path.GetFileNameWithoutExtension(firstMedia.Path), - //AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), - //LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() + // AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), + // LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() }; result.Items.Add(libraryItem); diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index ebfe95d0a..79b6dded3 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio // Args points to an album if parent is an Artist folder or it directly contains music if (args.IsDirectory) { - // if (args.Parent is MusicArtist) return true; //saves us from testing children twice + // if (args.Parent is MusicArtist) return true; // saves us from testing children twice if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager)) { return true; diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index fb75593bd..2f5e46038 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -292,7 +292,7 @@ namespace Emby.Server.Implementations.Library.Resolvers } return true; - //var blurayExtensions = new[] + // var blurayExtensions = new[] //{ // ".mts", // ".m2ts", @@ -300,7 +300,7 @@ namespace Emby.Server.Implementations.Library.Resolvers // ".mpls" //}; - //return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)); + // return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 1030ed39d..cc5a3bd5b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers } if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) { - return new UserRootFolder(); //if we got here and still a root - must be user root + return new UserRootFolder(); // if we got here and still a root - must be user root } if (args.IsVf) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 2f206f74c..732bfd94d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { - //if (args.ContainsFileSystemEntryByName("tvshow.nfo")) + // if (args.ContainsFileSystemEntryByName("tvshow.nfo")) //{ // return new Series // { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 70dd8f321..d8ec107ec 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -183,7 +183,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn"; - //var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? + // var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ? // " -f mp4 -movflags frag_keyframe+empty_moov" : // string.Empty; @@ -206,13 +206,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { return "-codec:a:0 copy"; - //var audioChannels = 2; - //var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); - //if (audioStream != null) + // var audioChannels = 2; + // var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); + // if (audioStream != null) //{ // audioChannels = audioStream.Channels ?? audioChannels; //} - //return "-codec:a:0 aac -strict experimental -ab 320000"; + // return "-codec:a:0 aac -strict experimental -ab 320000"; } private static bool EncodeVideo(MediaSourceInfo mediaSource) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index a65b3ee03..5e147225a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -145,7 +145,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings var programsInfo = new List(); foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs)) { - //_logger.LogDebug("Proccesing Schedule for statio ID " + stationID + + // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID + // " which corresponds to channel " + channelNumber + " and program id " + // schedule.programID + " which says it has images? " + // programDict[schedule.programID].hasImageArtwork); @@ -178,7 +178,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); - //programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? + // programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? // GetProgramImage(ApiUrl, data, "Banner-LO", false) ?? // GetProgramImage(ApiUrl, data, "Banner-LOT", false); @@ -276,7 +276,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings CommunityRating = null, EpisodeTitle = episodeTitle, Audio = audioType, - //IsNew = programInfo.@new ?? false, + // IsNew = programInfo.@new ?? false, IsRepeat = programInfo.@new == null, IsSeries = string.Equals(details.entityType, "episode", StringComparison.OrdinalIgnoreCase), ImageUrl = details.primaryImage, @@ -701,7 +701,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings CancellationToken = cancellationToken, LogErrorResponseBody = true }; - //_logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " + + // _logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " + // httpOptions.RequestContent); using (var response = await Post(httpOptions, false, null).ConfigureAwait(false)) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index e39092f97..ddc8cafac 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -406,8 +406,8 @@ namespace Emby.Server.Implementations.LiveTv if (!(service is EmbyTV.EmbyTV)) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - //mediaSource.SupportsDirectPlay = false; - //mediaSource.SupportsDirectStream = false; + // mediaSource.SupportsDirectPlay = false; + // mediaSource.SupportsDirectStream = false; mediaSource.SupportsTranscoding = true; foreach (var stream in mediaSource.MediaStreams) { @@ -558,7 +558,7 @@ namespace Emby.Server.Implementations.LiveTv } item.ParentId = channel.Id; - //item.ChannelType = channelType; + // item.ChannelType = channelType; item.Audio = info.Audio; item.ChannelId = channel.Id; @@ -1368,10 +1368,10 @@ namespace Emby.Server.Implementations.LiveTv // limit = (query.Limit ?? 10) * 2; limit = null; - //var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray(); - //var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray(); + // var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray(); + // var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray(); - //return new QueryResult + // return new QueryResult //{ // Items = items, // TotalRecordCount = items.Length @@ -1956,7 +1956,7 @@ namespace Emby.Server.Implementations.LiveTv OriginalAirDate = program.PremiereDate, Overview = program.Overview, StartDate = program.StartDate, - //ImagePath = program.ExternalImagePath, + // ImagePath = program.ExternalImagePath, Name = program.Name, OfficialRating = program.OfficialRating }; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index ba3594efd..abdcdd622 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var result = await GetChannelsInternal(tuner, cancellationToken).ConfigureAwait(false); var list = result.ToList(); - //logger.LogInformation("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); + // logger.LogInformation("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); if (!string.IsNullOrEmpty(key) && list.Count > 0) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 25b2c674c..464b06b32 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -502,8 +502,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun SupportsTranscoding = true, IsInfiniteStream = true, IgnoreDts = true, - //IgnoreIndex = true, - //ReadAtNativeFramerate = true + // IgnoreIndex = true, + // ReadAtNativeFramerate = true }; mediaSource.InferTotalBitrate(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 82b1f3cf1..6730751d5 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -117,17 +117,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun taskCompletionSource, LiveStreamCancellationTokenSource.Token).ConfigureAwait(false); - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = tempFile; - //OpenedMediaSource.ReadAtNativeFramerate = true; + // OpenedMediaSource.Protocol = MediaProtocol.File; + // OpenedMediaSource.Path = tempFile; + // OpenedMediaSource.ReadAtNativeFramerate = true; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; - //OpenedMediaSource.SupportsDirectPlay = false; - //OpenedMediaSource.SupportsDirectStream = true; - //OpenedMediaSource.SupportsTranscoding = true; + // OpenedMediaSource.SupportsDirectPlay = false; + // OpenedMediaSource.SupportsDirectStream = true; + // OpenedMediaSource.SupportsTranscoding = true; - //await Task.Delay(5000).ConfigureAwait(false); + // await Task.Delay(5000).ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 59451fccd..883b175d6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -284,7 +284,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) { - //channel.Number = number.ToString(); + // channel.Number = number.ToString(); nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' }); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 322fbbbaa..bc4dcd894 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -103,21 +103,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = tempFile; - //OpenedMediaSource.ReadAtNativeFramerate = true; + // OpenedMediaSource.Protocol = MediaProtocol.File; + // OpenedMediaSource.Path = tempFile; + // OpenedMediaSource.ReadAtNativeFramerate = true; MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; - //OpenedMediaSource.Path = TempFilePath; - //OpenedMediaSource.Protocol = MediaProtocol.File; + // OpenedMediaSource.Path = TempFilePath; + // OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = _tempFilePath; - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.SupportsDirectPlay = false; - //OpenedMediaSource.SupportsDirectStream = true; - //OpenedMediaSource.SupportsTranscoding = true; + // OpenedMediaSource.Path = _tempFilePath; + // OpenedMediaSource.Protocol = MediaProtocol.File; + // OpenedMediaSource.SupportsDirectPlay = false; + // OpenedMediaSource.SupportsDirectStream = true; + // OpenedMediaSource.SupportsTranscoding = true; await taskCompletionSource.Task.ConfigureAwait(false); if (taskCompletionSource.Task.Exception != null) { diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index f347540c7..fd863d25a 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.Net try { - //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); + // retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); var localIp = IPAddress.Any; diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 45864bb42..2909cdd0d 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -167,7 +167,7 @@ namespace Emby.Server.Implementations.Networking foreach (var subnet_Match in subnets) { - //logger.LogDebug("subnet_Match:" + subnet_Match); + // logger.LogDebug("subnet_Match:" + subnet_Match); if (endpoint.StartsWith(subnet_Match + ".", StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 9028222dd..3854be703 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -163,7 +163,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (ObjectDisposedException) { - //TODO Investigate and properly fix. + // TODO Investigate and properly fix. break; } } diff --git a/Emby.Server.Implementations/Services/ResponseHelper.cs b/Emby.Server.Implementations/Services/ResponseHelper.cs index f2b1d06f3..3f1672e94 100644 --- a/Emby.Server.Implementations/Services/ResponseHelper.cs +++ b/Emby.Server.Implementations/Services/ResponseHelper.cs @@ -59,8 +59,8 @@ namespace Emby.Server.Implementations.Services } } - //ContentType='text/html' is the default for a HttpResponse - //Do not override if another has been set + // ContentType='text/html' is the default for a HttpResponse + // Do not override if another has been set if (response.ContentType == null || response.ContentType == "text/html") { response.ContentType = defaultContentType; diff --git a/Emby.Server.Implementations/Services/ServiceController.cs b/Emby.Server.Implementations/Services/ServiceController.cs index e688278b5..b84e47140 100644 --- a/Emby.Server.Implementations/Services/ServiceController.cs +++ b/Emby.Server.Implementations/Services/ServiceController.cs @@ -59,8 +59,8 @@ namespace Emby.Server.Implementations.Services ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions); - //var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>)); - //var responseType = returnMarker != null ? + // var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>)); + // var responseType = returnMarker != null ? // GetGenericArguments(returnMarker)[0] // : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ? // mi.ReturnType @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Services serviceRequiresContext.Request = req; } - //Executes the service and returns the result + // Executes the service and returns the result return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName()); } } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 278379a92..43869f98a 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -118,7 +118,7 @@ namespace Emby.Server.Implementations.Services var componentsList = new List(); - //We only split on '.' if the restPath has them. Allows for /{action}.{type} + // We only split on '.' if the restPath has them. Allows for /{action}.{type} var hasSeparators = new List(); foreach (var component in this.restPath.Split(PathSeperatorChar)) { @@ -298,12 +298,12 @@ namespace Emby.Server.Implementations.Services return -1; } - //Routes with least wildcard matches get the highest score + // Routes with least wildcard matches get the highest score var score = Math.Max((100 - wildcardMatchCount), 1) * 1000 - //Routes with less variable (and more literal) matches + // Routes with less variable (and more literal) matches + Math.Max((10 - VariableArgsCount), 1) * 100; - //Exact verb match is better than ANY + // Exact verb match is better than ANY if (Verbs.Length == 1 && string.Equals(httpMethod, Verbs[0], StringComparison.OrdinalIgnoreCase)) { score += 10; @@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.Services + variableName + " on " + RequestType.GetMethodName()); } - var value = requestComponents.Length > pathIx ? requestComponents[pathIx] : null; //wildcard has arg mismatch + var value = requestComponents.Length > pathIx ? requestComponents[pathIx] : null; // wildcard has arg mismatch if (value != null && this.isWildcard[i]) { if (i == this.TotalComponentsCount - 1) @@ -519,8 +519,8 @@ namespace Emby.Server.Implementations.Services if (queryStringAndFormData != null) { - //Query String and form data can override variable path matches - //path variables < query string < form data + // Query String and form data can override variable path matches + // path variables < query string < form data foreach (var name in queryStringAndFormData) { requestKeyValuesMap[name.Key] = name.Value; diff --git a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs index ab22fe019..d3d27ae58 100644 --- a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs +++ b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.Services if (propertySerializerEntry.PropertyType == typeof(bool)) { - //InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value + // InputExtensions.cs#530 MVC Checkbox helper emits extra hidden input field, generating 2 values, first is the real value propertyTextValue = StringExtensions.LeftPart(propertyTextValue, ',').ToString(); } diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 67e31f7f6..2b7d818be 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Sorting if (val != 0) { - //return val; + // return val; } } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 6999668d1..ba6c4f261 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -149,7 +149,7 @@ namespace Emby.Server.Implementations.TV var allNextUp = seriesKeys .Select(i => GetNextUp(i, currentUser, dtoOptions)); - //allNextUp = allNextUp.OrderByDescending(i => i.Item1); + // allNextUp = allNextUp.OrderByDescending(i => i.Item1); // If viewing all next up for all series, remove first episodes // But if that returns empty, keep those first episodes (avoid completely empty view) diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 68e3dfa59..862411209 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -220,7 +220,7 @@ namespace MediaBrowser.Api { var item = _libraryManager.GetItemById(new Guid(request.Id)); - //foreach (var key in request.ProviderIds) + // foreach (var key in request.ProviderIds) //{ // var value = key.Value; @@ -233,8 +233,8 @@ namespace MediaBrowser.Api // Since the refresh process won't erase provider Ids, we need to set this explicitly now. item.ProviderIds = request.ProviderIds; - //item.ProductionYear = request.ProductionYear; - //item.Name = request.Name; + // item.ProductionYear = request.ProductionYear; + // item.Name = request.Name; return _providerManager.RefreshFullItem( item, diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 2d61299c7..281c7e613 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -161,8 +161,8 @@ namespace MediaBrowser.Api.Movies IncludeItemTypes = new[] { typeof(Movie).Name, - //typeof(Trailer).Name, - //typeof(LiveTvProgram).Name + // typeof(Trailer).Name, + // typeof(LiveTvProgram).Name }, // IsMovie = true OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple(i, SortOrder.Descending)).ToArray(), diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 957e4ae91..2eb6198c0 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -216,7 +216,7 @@ namespace MediaBrowser.Api.Playback UseShellExecute = false, // Must consume both stdout and stderr or deadlocks may occur - //RedirectStandardOutput = true, + // RedirectStandardOutput = true, RedirectStandardError = true, RedirectStandardInput = true, @@ -685,7 +685,7 @@ namespace MediaBrowser.Api.Playback state.User = UserManager.GetUserById(auth.UserId); } - //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 || + // if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 || // (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 || // (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1) //{ @@ -716,9 +716,9 @@ namespace MediaBrowser.Api.Playback state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); - //var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ?? + // var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ?? // item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null); - //if (primaryImage != null) + // if (primaryImage != null) //{ // state.AlbumCoverPath = primaryImage.Path; //} @@ -885,7 +885,7 @@ namespace MediaBrowser.Api.Playback if (transcodingProfile != null) { state.EstimateContentLength = transcodingProfile.EstimateContentLength; - //state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; + // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; if (state.VideoRequest != null) diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 627421aac..c2d49a93b 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -178,7 +178,7 @@ namespace MediaBrowser.Api.Playback.Hls var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture); text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase); - //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase); + // text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase); return text; } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 0a6ed2786..c0dfcf4c1 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -257,7 +257,7 @@ namespace MediaBrowser.Api.Playback.Hls throw; } - //await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false); + // await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false); } else { @@ -277,8 +277,8 @@ namespace MediaBrowser.Api.Playback.Hls } } - //Logger.LogInformation("waiting for {0}", segmentPath); - //while (!File.Exists(segmentPath)) + // Logger.LogInformation("waiting for {0}", segmentPath); + // while (!File.Exists(segmentPath)) //{ // await Task.Delay(50, cancellationToken).ConfigureAwait(false); //} @@ -717,7 +717,7 @@ namespace MediaBrowser.Api.Playback.Hls // Having problems in android return false; - //return state.VideoRequest.VideoBitRate.HasValue; + // return state.VideoRequest.VideoBitRate.HasValue; } /// @@ -972,7 +972,7 @@ namespace MediaBrowser.Api.Playback.Hls var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); - //if ((Request.UserAgent ?? string.Empty).IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1) + // if ((Request.UserAgent ?? string.Empty).IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1) //{ // queryString = string.Empty; //} @@ -1100,7 +1100,7 @@ namespace MediaBrowser.Api.Playback.Hls } } - //args += " -flags -global_header"; + // args += " -flags -global_header"; } else { @@ -1142,7 +1142,7 @@ namespace MediaBrowser.Api.Playback.Hls args += " " + keyFrameArg + gopArg; } - //args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0"; + // args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0"; var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; @@ -1164,7 +1164,7 @@ namespace MediaBrowser.Api.Playback.Hls args += " -start_at_zero"; } - //args += " -flags -global_header"; + // args += " -flags -global_header"; } if (!string.IsNullOrEmpty(state.OutputVideoSync)) diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index c7bf055fb..43cde440c 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -231,7 +231,7 @@ namespace MediaBrowser.Api.Playback.Progressive } //// Not static but transcode cache file exists - //if (isTranscodeCached && state.VideoRequest == null) + // if (isTranscodeCached && state.VideoRequest == null) //{ // var contentType = state.GetMimeType(outputPath); diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index a53b848f9..ffc5e1554 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -96,8 +96,8 @@ namespace MediaBrowser.Api.Playback.Progressive bytesRead = await CopyToInternalAsyncWithSyncRead(inputStream, outputStream, cancellationToken).ConfigureAwait(false); } - //var position = fs.Position; - //_logger.LogDebug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); + // var position = fs.Position; + // _logger.LogDebug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); if (bytesRead == 0) { diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 7f74511ee..fd1075727 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.Api public Stream RequestStream { get; set; } } - //TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins, + // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins, // delete all these registration endpoints. They are only kept for compatibility. [Route("/Registrations/{Name}", "GET", Summary = "Gets registration status for a feature", IsHidden = true)] [Authenticated] diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 0eabb4b7a..52fe83af0 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -300,7 +300,7 @@ namespace MediaBrowser.Controller.Entities { get { - //if (IsOffline) + // if (IsOffline) //{ // return LocationType.Offline; //} @@ -676,7 +676,7 @@ namespace MediaBrowser.Controller.Entities /// System.String. protected virtual string CreateSortName() { - if (Name == null) return null; //some items may not have name filled in properly + if (Name == null) return null; // some items may not have name filled in properly if (!EnableAlphaNumericSorting) { @@ -736,7 +736,7 @@ namespace MediaBrowser.Controller.Entities builder.Append(chunkBuilder); } - //logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); + // logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); return builder.ToString().RemoveDiacritics(); } @@ -1011,7 +1011,7 @@ namespace MediaBrowser.Controller.Entities return PlayAccess.None; } - //if (!user.IsParentalScheduleAllowed()) + // if (!user.IsParentalScheduleAllowed()) //{ // return PlayAccess.None; //} @@ -2175,7 +2175,7 @@ namespace MediaBrowser.Controller.Entities var data = UserDataManager.GetUserData(user, this); - //I think it is okay to do this here. + // I think it is okay to do this here. // if this is only called when a user is manually forcing something to un-played // then it probably is what we want to do... data.PlayCount = 0; @@ -2760,8 +2760,8 @@ namespace MediaBrowser.Controller.Entities newOptions.ForceSave = true; } - //var parentId = Id; - //if (!video.IsOwnedItem || video.ParentId != parentId) + // var parentId = Id; + // if (!video.IsOwnedItem || video.ParentId != parentId) //{ // video.IsOwnedItem = true; // video.ParentId = parentId; diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index 62d172fcc..106385bc6 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public override bool SupportsPeople => false; - //public override double? GetDefaultPrimaryImageAspectRatio() + // public override double? GetDefaultPrimaryImageAspectRatio() //{ // double value = 16; // value /= 9; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 4af74f9cd..366b3bd70 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -213,8 +213,8 @@ namespace MediaBrowser.Controller.Entities /// protected virtual List LoadChildren() { - //logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path); - //just load our children from the repo - the library will be validated and maintained in other processes + // logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path); + // just load our children from the repo - the library will be validated and maintained in other processes return GetCachedChildren(); } @@ -1223,7 +1223,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException(nameof(user)); } - //the true root should return our users root folder children + // the true root should return our users root folder children if (IsPhysicalRoot) { return LibraryManager.GetUserRootFolder().GetChildren(user, includeLinkedChildren); diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index bf0e56cf7..8162fb4eb 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities { var user = query.User; - //if (query.IncludeItemTypes != null && + // if (query.IncludeItemTypes != null && // query.IncludeItemTypes.Length == 1 && // string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase)) //{ @@ -424,7 +424,7 @@ namespace MediaBrowser.Controller.Entities { return new QueryResult { - Items = result.Items, //TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem. + Items = result.Items, // TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem. TotalRecordCount = result.TotalRecordCount }; } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 666a3f76b..848e4fb16 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Controller.IO if (string.IsNullOrEmpty(newPath)) { - //invalid shortcut - could be old or target could just be unavailable + // invalid shortcut - could be old or target could just be unavailable logger.LogWarning("Encountered invalid shortcut: " + fullName); continue; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 5b901d223..e17db34c6 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -147,7 +147,7 @@ namespace MediaBrowser.Controller.LiveTv public override string ContainingFolderPath => Path; //[JsonIgnore] - //public override string MediaType + // public override string MediaType //{ // get // { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index e7f613916..23cb3dbbc 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -768,7 +768,7 @@ namespace MediaBrowser.Controller.MediaEncoding { case "veryslow": - param += "-preset slow"; //lossless is only supported on maxwell and newer(2014+) + param += "-preset slow"; // lossless is only supported on maxwell and newer(2014+) break; case "slow": @@ -999,7 +999,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (string.IsNullOrEmpty(videoStream.Profile)) { - //return false; + // return false; } var requestedProfile = requestedProfiles[0]; @@ -1072,7 +1072,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (!videoStream.Level.HasValue) { - //return false; + // return false; } if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel) @@ -1930,11 +1930,11 @@ namespace MediaBrowser.Controller.MediaEncoding break; case Video3DFormat.FullSideBySide: filter = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; - //fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth. + // fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth. break; case Video3DFormat.HalfTopAndBottom: filter = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; - //htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth + // htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth break; case Video3DFormat.FullTopAndBottom: filter = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; @@ -2553,7 +2553,7 @@ namespace MediaBrowser.Controller.MediaEncoding case "h265": if (_mediaEncoder.SupportsDecoder("hevc_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) { - //return "-c:v hevc_qsv -load_plugin hevc_hw "; + // return "-c:v hevc_qsv -load_plugin hevc_hw "; return "-c:v hevc_qsv"; } break; diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index 7dca793c6..bba20c153 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Net } catch (ObjectDisposedException) { - //TODO Investigate and properly fix. + // TODO Investigate and properly fix. } lock (_activeConnections) diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index a6553563f..4770d2bee 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.LocalMetadata public string Name => XmlProviderUtils.Name; - //After Nfo + // After Nfo public virtual int Order => 1; } diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 4f1112396..9fb28c334 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -78,10 +78,10 @@ namespace MediaBrowser.LocalMetadata.Parsers } } - //Additional Mappings + // Additional Mappings _validProviderIds.Add("IMDB", "Imdb"); - //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); + // Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 26bd202ba..18e4a38c6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -247,14 +247,14 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetAvailableEncoders(IEnumerable list) { _encoders = list.ToList(); - //_logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); + // _logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } private List _decoders = new List(); public void SetAvailableDecoders(IEnumerable list) { _decoders = list.ToList(); - //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); + // _logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } public bool SupportsEncoder(string encoder) @@ -500,11 +500,11 @@ namespace MediaBrowser.MediaEncoding.Encoder break; case Video3DFormat.FullSideBySide: vf = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - //fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to 600. + // fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to 600. break; case Video3DFormat.HalfTopAndBottom: vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - //htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600 + // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600 break; case Video3DFormat.FullTopAndBottom: vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 9386d6524..ed5f77053 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -562,7 +562,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (string.Equals(streamInfo.CodecName, "mov_text", StringComparison.OrdinalIgnoreCase)) { // Edit: but these are also sometimes subtitles? - //return null; + // return null; } var stream = new MediaStream @@ -684,7 +684,7 @@ namespace MediaBrowser.MediaEncoding.Probing stream.BitDepth = streamInfo.BitsPerRawSample; } - //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || + // stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase); @@ -953,8 +953,8 @@ namespace MediaBrowser.MediaEncoding.Probing audio.People = peoples.ToArray(); } - //var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); - //if (!string.IsNullOrWhiteSpace(conductor)) + // var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); + // if (!string.IsNullOrWhiteSpace(conductor)) //{ // foreach (var person in Split(conductor, false)) // { @@ -962,8 +962,8 @@ namespace MediaBrowser.MediaEncoding.Probing // } //} - //var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); - //if (!string.IsNullOrWhiteSpace(lyricist)) + // var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); + // if (!string.IsNullOrWhiteSpace(lyricist)) //{ // foreach (var person in Split(lyricist, false)) // { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index b94d45165..ebacc7d9f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -130,10 +130,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - //if (header.Length > 0) - //subtitle.Header = header.ToString(); + // if (header.Length > 0) + // subtitle.Header = header.ToString(); - //subtitle.Renumber(1); + // subtitle.Renumber(1); } trackInfo.TrackEvents = trackEvents.ToArray(); return trackInfo; diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index b055ad41a..a579f8464 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -79,11 +79,11 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.InteractiveTransferMode | DlnaFlags.DlnaV15; - //if (isDirectStream) + // if (isDirectStream) //{ // flagValue = flagValue | DlnaFlags.ByteBasedSeek; //} - //else if (runtimeTicks.HasValue) + // else if (runtimeTicks.HasValue) //{ // flagValue = flagValue | DlnaFlags.TimeBasedSeek; //} @@ -148,11 +148,11 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.InteractiveTransferMode | DlnaFlags.DlnaV15; - //if (isDirectStream) + // if (isDirectStream) //{ // flagValue = flagValue | DlnaFlags.ByteBasedSeek; //} - //else if (runtimeTicks.HasValue) + // else if (runtimeTicks.HasValue) //{ // flagValue = flagValue | DlnaFlags.TimeBasedSeek; //} diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a18ad36c5..8ebd30b72 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -781,7 +781,7 @@ namespace MediaBrowser.Model.Dlna if (!ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)) { - //LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item); + // LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item); applyConditions = false; break; } @@ -825,7 +825,7 @@ namespace MediaBrowser.Model.Dlna if (!ConditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio)) { - //LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item); + // LogConditionFailure(options.Profile, "VideoCodecProfile.ApplyConditions", applyCondition, item); applyConditions = false; break; } @@ -1046,7 +1046,7 @@ namespace MediaBrowser.Model.Dlna { if (!ConditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isInterlaced, refFrames, numVideoStreams, numAudioStreams, videoCodecTag, isAvc)) { - //LogConditionFailure(profile, "VideoCodecProfile.ApplyConditions", applyCondition, mediaSource); + // LogConditionFailure(profile, "VideoCodecProfile.ApplyConditions", applyCondition, mediaSource); applyConditions = false; break; } @@ -1092,7 +1092,7 @@ namespace MediaBrowser.Model.Dlna { if (!ConditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioSampleRate, audioBitDepth, audioProfile, isSecondaryAudio)) { - //LogConditionFailure(profile, "VideoAudioCodecProfile.ApplyConditions", applyCondition, mediaSource); + // LogConditionFailure(profile, "VideoAudioCodecProfile.ApplyConditions", applyCondition, mediaSource); applyConditions = false; break; } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index fa09cc513..12eaa184c 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Model.Entities { if (Type == MediaStreamType.Audio) { - //if (!string.IsNullOrEmpty(Title)) + // if (!string.IsNullOrEmpty(Title)) //{ // return AddLanguageIfNeeded(Title); //} diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 48e1c94ad..ee9a32966 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -506,7 +506,7 @@ namespace MediaBrowser.Providers.Manager return false; } - //if (!item.IsSaveLocalMetadataEnabled()) + // if (!item.IsSaveLocalMetadataEnabled()) //{ // return true; //} diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 4ea711a2a..73fb63743 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Manager ApplySearchResult(id, refreshOptions.SearchResult); } - //await FindIdentities(id, cancellationToken).ConfigureAwait(false); + // await FindIdentities(id, cancellationToken).ConfigureAwait(false); id.IsAutomated = refreshOptions.IsAutomated; var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); @@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.Manager private void AddPersonImage(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken) { - //if (libraryOptions.DownloadImagesInAdvance) + // if (libraryOptions.DownloadImagesInAdvance) //{ // try // { @@ -772,14 +772,14 @@ namespace MediaBrowser.Providers.Manager } } - //var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0; + // var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0; foreach (var provider in customProviders.Where(i => !(i is IPreRefreshProvider))) { await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false); } - //ImportUserData(item, userDataList, cancellationToken); + // ImportUserData(item, userDataList, cancellationToken); return refreshResult; } @@ -906,7 +906,7 @@ namespace MediaBrowser.Providers.Manager { var hasChanged = changeMonitor.HasChanged(item, directoryService); - //if (hasChanged) + // if (hasChanged) //{ // logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name); //} diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index eeb74ec96..31c239e24 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -831,7 +831,7 @@ namespace MediaBrowser.Providers.Manager } } - //_logger.LogDebug("Returning search results {0}", _json.SerializeToString(resultList)); + // _logger.LogDebug("Returning search results {0}", _json.SerializeToString(resultList)); return resultList; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 3b6c8ff72..1e7ae5e74 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -91,8 +91,8 @@ namespace MediaBrowser.Providers.MediaInfo audio.RunTimeTicks = mediaInfo.RunTimeTicks; audio.Size = mediaInfo.Size; - //var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.'); - //audio.Container = extension; + // var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.'); + // audio.Container = extension; FetchDataFromTags(audio, mediaInfo); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 933cf03d6..ccbe27c1f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.MediaInfo mediaAttachments = mediaInfo.MediaAttachments; video.TotalBitrate = mediaInfo.Bitrate; - //video.FormatName = (mediaInfo.Container ?? string.Empty) + // video.FormatName = (mediaInfo.Container ?? string.Empty) // .Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase); // For dvd's this may not always be accurate, so don't set the runtime if the item already has one @@ -283,7 +283,7 @@ namespace MediaBrowser.Providers.MediaInfo { var video = (Video)item; - //video.PlayableStreamFileNames = blurayInfo.Files.ToList(); + // video.PlayableStreamFileNames = blurayInfo.Files.ToList(); // Use BD Info if it has multiple m2ts. Otherwise, treat it like a video file and rely more on ffprobe output if (blurayInfo.Files.Length > 1) diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index 2bbe8a968..c0eee54fe 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -189,9 +189,9 @@ namespace MediaBrowser.Providers.MediaInfo filename = filename.Replace(" ", string.Empty); // can't normalize this due to languages such as pt-br - //filename = filename.Replace("-", string.Empty); + // filename = filename.Replace("-", string.Empty); - //filename = filename.Replace(".", string.Empty); + // filename = filename.Replace(".", string.Empty); return filename; } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index d8a18a6bc..fdba779be 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb private void ProcessResult(MusicArtist item, Artist result, string preferredLanguage) { - //item.HomePageUrl = result.strWebsite; + // item.HomePageUrl = result.strWebsite; if (!string.IsNullOrEmpty(result.strGenre)) { diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 19b4bd1e3..fe5f0e9bf 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) && voteCount >= 0) { - //item.VoteCount = voteCount; + // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) @@ -178,7 +178,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) && voteCount >= 0) { - //item.VoteCount = voteCount; + // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs index 60f37dc17..2f75f7cba 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies movie.Overview = string.IsNullOrWhiteSpace(movieData.Overview) ? null : WebUtility.HtmlDecode(movieData.Overview); movie.Overview = movie.Overview != null ? movie.Overview.Replace("\n\n", "\n") : null; - //movie.HomePageUrl = movieData.homepage; + // movie.HomePageUrl = movieData.homepage; if (!string.IsNullOrEmpty(movieData.Tagline)) { @@ -167,7 +167,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies movie.CommunityRating = rating; } - //movie.VoteCount = movieData.vote_count; + // movie.VoteCount = movieData.vote_count; if (movieData.Releases != null && movieData.Releases.Countries != null) { @@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - //studios + // studios if (movieData.Production_Companies != null) { movie.SetStudios(movieData.Production_Companies.Select(c => c.Name)); @@ -219,8 +219,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies resultItem.ResetPeople(); var tmdbImageUrl = settings.images.GetImageUrl("original"); - //Actors, Directors, Writers - all in People - //actors come from cast + // Actors, Directors, Writers - all in People + // actors come from cast if (movieData.Casts != null && movieData.Casts.Cast != null) { foreach (var actor in movieData.Casts.Cast.OrderBy(a => a.Order)) @@ -247,7 +247,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - //and the rest from crew + // and the rest from crew if (movieData.Casts?.Crew != null) { var keepTypes = new[] @@ -289,7 +289,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } - //if (movieData.keywords != null && movieData.keywords.keywords != null) + // if (movieData.keywords != null && movieData.keywords.keywords != null) //{ // movie.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList(); //} diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs index e1e34afb9..3e52c72e0 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (results.Count == 0) { - //try in english if wasn't before + // try in english if wasn't before if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); @@ -128,7 +128,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { - //one more time, in english + // one more time, in english results = await GetSearchResults(name2, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index 3f28483f7..6b63ff664 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -167,7 +167,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People // TODO: This should go in PersonMetadataService, not each person provider item.Name = id.Name; - //item.HomePageUrl = info.homepage; + // item.HomePageUrl = info.homepage; if (!string.IsNullOrWhiteSpace(info.Place_Of_Birth)) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index 01b295f86..b4d092c89 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -141,8 +141,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var credits = response.Credits; if (credits != null) { - //Actors, Directors, Writers - all in People - //actors come from cast + // Actors, Directors, Writers - all in People + // actors come from cast if (credits.Cast != null) { foreach (var actor in credits.Cast.OrderBy(a => a.Order)) @@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } } - //and the rest from crew + // and the rest from crew if (credits.Crew != null) { var keepTypes = new[] diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index c7cd672b4..2cc82d5f6 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV result.Item = new Season(); // Don't use moviedb season names for now until if/when we have field-level configuration - //result.Item.Name = seasonInfo.name; + // result.Item.Name = seasonInfo.name; result.Item.Name = info.Name; @@ -79,17 +79,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var credits = seasonInfo.Credits; if (credits != null) { - //Actors, Directors, Writers - all in People - //actors come from cast + // Actors, Directors, Writers - all in People + // actors come from cast if (credits.Cast != null) { - //foreach (var actor in credits.cast.OrderBy(a => a.order)) result.Item.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order }); + // foreach (var actor in credits.cast.OrderBy(a => a.order)) result.Item.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order }); } - //and the rest from crew + // and the rest from crew if (credits.Crew != null) { - //foreach (var person in credits.crew) result.Item.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department }); + // foreach (var person in credits.crew) result.Item.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department }); } } diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index 6a1e6df8f..6e0511971 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -40,11 +40,11 @@ namespace MediaBrowser.Providers.TV if (hasNewSeasons) { - //var directoryService = new DirectoryService(_fileSystem); + // var directoryService = new DirectoryService(_fileSystem); - //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); + // await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); - //await series.ValidateChildren(new SimpleProgress(), cancellationToken, new MetadataRefreshOptions(directoryService)) + // await series.ValidateChildren(new SimpleProgress(), cancellationToken, new MetadataRefreshOptions(directoryService)) // .ConfigureAwait(false); } diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 773a06cdb..c2eb0bf92 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -46,7 +46,7 @@ namespace Rssdp.Infrastructure { var lines = data.Split(LineTerminators, StringSplitOptions.None); - //First line is the 'request' line containing http protocol details like method, uri, http version etc. + // First line is the 'request' line containing http protocol details like method, uri, http version etc. ParseStatusLine(lines[0], message); ParseHeaders(headers, retVal.Headers, lines); @@ -93,16 +93,16 @@ namespace Rssdp.Infrastructure /// A reference to a collection for the message content, to which the parsed header will be added. private void ParseHeader(string line, System.Net.Http.Headers.HttpHeaders headers, System.Net.Http.Headers.HttpHeaders contentHeaders) { - //Header format is - //name: value + // Header format is + // name: value var headerKeySeparatorIndex = line.IndexOf(":", StringComparison.OrdinalIgnoreCase); var headerName = line.Substring(0, headerKeySeparatorIndex).Trim(); var headerValue = line.Substring(headerKeySeparatorIndex + 1).Trim(); - //Not sure how to determine where request headers and and content headers begin, - //at least not without a known set of headers (general headers first the content headers) - //which seems like a bad way of doing it. So we'll assume if it's a known content header put it there - //else use request headers. + // Not sure how to determine where request headers and and content headers begin, + // at least not without a known set of headers (general headers first the content headers) + // which seems like a bad way of doing it. So we'll assume if it's a known content header put it there + // else use request headers. var values = ParseValues(headerValue); var headersToAddTo = IsContentHeader(headerName) ? contentHeaders : headers; @@ -115,13 +115,13 @@ namespace Rssdp.Infrastructure private int ParseHeaders(System.Net.Http.Headers.HttpHeaders headers, System.Net.Http.Headers.HttpHeaders contentHeaders, string[] lines) { - //Blank line separates headers from content, so read headers until we find blank line. + // Blank line separates headers from content, so read headers until we find blank line. int lineIndex = 1; string line = null, nextLine = null; while (lineIndex + 1 < lines.Length && !String.IsNullOrEmpty((line = lines[lineIndex++]))) { - //If the following line starts with space or tab (or any whitespace), it is really part of this header but split for human readability. - //Combine these lines into a single comma separated style header for easier parsing. + // If the following line starts with space or tab (or any whitespace), it is really part of this header but split for human readability. + // Combine these lines into a single comma separated style header for easier parsing. while (lineIndex < lines.Length && !String.IsNullOrEmpty((nextLine = lines[lineIndex]))) { if (nextLine.Length > 0 && Char.IsWhiteSpace(nextLine[0])) diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 18097ef24..328e6137a 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -485,9 +485,9 @@ namespace Rssdp.Infrastructure private void OnRequestReceived(HttpRequestMessage data, IPEndPoint remoteEndPoint, IPAddress receivedOnLocalIpAddress) { - //SSDP specification says only * is currently used but other uri's might - //be implemented in the future and should be ignored unless understood. - //Section 4.2 - http://tools.ietf.org/html/draft-cai-ssdp-v1-03#page-11 + // SSDP specification says only * is currently used but other uri's might + // be implemented in the future and should be ignored unless understood. + // Section 4.2 - http://tools.ietf.org/html/draft-cai-ssdp-v1-03#page-11 if (data.RequestUri.ToString() != "*") { return; diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index 59a2710d5..4651d3bb6 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -337,7 +337,7 @@ namespace Rssdp.Infrastructure values["HOST"] = "239.255.255.250:1900"; values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2"; - //values["X-EMBY-SERVERID"] = _appHost.SystemId; + // values["X-EMBY-SERVERID"] = _appHost.SystemId; values["MAN"] = "\"ssdp:discover\""; diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 53b740052..6a8cda835 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -205,25 +205,25 @@ namespace Rssdp.Infrastructure return; } - //WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget)); + // WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget)); if (IsDuplicateSearchRequest(searchTarget, remoteEndPoint)) { - //WriteTrace("Search Request is Duplicate, ignoring."); + // WriteTrace("Search Request is Duplicate, ignoring."); return; } - //Wait on random interval up to MX, as per SSDP spec. - //Also, as per UPnP 1.1/SSDP spec ignore missing/bank MX header. If over 120, assume random value between 0 and 120. - //Using 16 as minimum as that's often the minimum system clock frequency anyway. + // Wait on random interval up to MX, as per SSDP spec. + // Also, as per UPnP 1.1/SSDP spec ignore missing/bank MX header. If over 120, assume random value between 0 and 120. + // Using 16 as minimum as that's often the minimum system clock frequency anyway. int maxWaitInterval = 0; if (String.IsNullOrEmpty(mx)) { - //Windows Explorer is poorly behaved and doesn't supply an MX header value. - //if (this.SupportPnpRootDevice) + // Windows Explorer is poorly behaved and doesn't supply an MX header value. + // if (this.SupportPnpRootDevice) mx = "1"; - //else - //return; + // else + // return; } if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) return; @@ -231,10 +231,10 @@ namespace Rssdp.Infrastructure if (maxWaitInterval > 120) maxWaitInterval = _Random.Next(0, 120); - //Do not block synchronously as that may tie up a threadpool thread for several seconds. + // Do not block synchronously as that may tie up a threadpool thread for several seconds. Task.Delay(_Random.Next(16, (maxWaitInterval * 1000))).ContinueWith((parentTask) => { - //Copying devices to local array here to avoid threading issues/enumerator exceptions. + // Copying devices to local array here to avoid threading issues/enumerator exceptions. IEnumerable devices = null; lock (_Devices) { @@ -251,7 +251,7 @@ namespace Rssdp.Infrastructure if (devices != null) { var deviceList = devices.ToList(); - //WriteTrace(String.Format("Sending {0} search responses", deviceList.Count)); + // WriteTrace(String.Format("Sending {0} search responses", deviceList.Count)); foreach (var device in deviceList) { @@ -264,7 +264,7 @@ namespace Rssdp.Infrastructure } else { - //WriteTrace(String.Format("Sending 0 search responses.")); + // WriteTrace(String.Format("Sending 0 search responses.")); } }); } @@ -308,7 +308,7 @@ namespace Rssdp.Infrastructure { var rootDevice = device.ToRootDevice(); - //var additionalheaders = FormatCustomHeadersForResponse(device); + // var additionalheaders = FormatCustomHeadersForResponse(device); const string header = "HTTP/1.1 200 OK"; @@ -338,7 +338,7 @@ namespace Rssdp.Infrastructure } - //WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device); + // WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device); } private bool IsDuplicateSearchRequest(string searchTarget, IPEndPoint endPoint) @@ -384,7 +384,7 @@ namespace Rssdp.Infrastructure { if (IsDisposed) return; - //WriteTrace("Begin Sending Alive Notifications For All Devices"); + // WriteTrace("Begin Sending Alive Notifications For All Devices"); SsdpRootDevice[] devices; lock (_Devices) @@ -399,7 +399,7 @@ namespace Rssdp.Infrastructure SendAliveNotifications(device, true, CancellationToken.None); } - //WriteTrace("Completed Sending Alive Notifications For All Devices"); + // WriteTrace("Completed Sending Alive Notifications For All Devices"); } catch (ObjectDisposedException ex) { @@ -448,7 +448,7 @@ namespace Rssdp.Infrastructure _CommsServer.SendMulticastMessage(message, _sendOnlyMatchedHost ? rootDevice.Address : null, cancellationToken); - //WriteTrace(String.Format("Sent alive notification"), device); + // WriteTrace(String.Format("Sent alive notification"), device); } private Task SendByeByeNotifications(SsdpDevice device, bool isRoot, CancellationToken cancellationToken) @@ -533,7 +533,7 @@ namespace Rssdp.Infrastructure { LogFunction(text); } - //System.Diagnostics.Debug.WriteLine(text, "SSDP Publisher"); + // System.Diagnostics.Debug.WriteLine(text, "SSDP Publisher"); } private void WriteTrace(string text, SsdpDevice device) @@ -551,13 +551,13 @@ namespace Rssdp.Infrastructure if (string.Equals(e.Message.Method.Method, SsdpConstants.MSearchMethod, StringComparison.OrdinalIgnoreCase)) { - //According to SSDP/UPnP spec, ignore message if missing these headers. + // According to SSDP/UPnP spec, ignore message if missing these headers. // Edit: But some devices do it anyway - //if (!e.Message.Headers.Contains("MX")) + // if (!e.Message.Headers.Contains("MX")) // WriteTrace("Ignoring search request - missing MX header."); - //else if (!e.Message.Headers.Contains("MAN")) + // else if (!e.Message.Headers.Contains("MAN")) // WriteTrace("Ignoring search request - missing MAN header."); - //else + // else ProcessSearchRequest(GetFirstHeaderValue(e.Message.Headers, "MX"), GetFirstHeaderValue(e.Message.Headers, "ST"), e.ReceivedFrom, e.LocalIpAddress, CancellationToken.None); } } -- cgit v1.2.3 From 3d9049ef08b797c270dea7d1f64d2806a65be953 Mon Sep 17 00:00:00 2001 From: telans Date: Sun, 14 Jun 2020 21:35:49 +1200 Subject: fix SA1508 --- Emby.Dlna/Didl/Filter.cs | 1 - Emby.Dlna/DlnaManager.cs | 1 - Emby.Dlna/Eventing/EventManager.cs | 1 - Emby.Dlna/PlayTo/Device.cs | 3 --- Emby.Dlna/PlayTo/PlayToManager.cs | 2 -- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 1 - Emby.Server.Implementations/Data/BaseSqliteRepository.cs | 1 - Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs | 1 - Emby.Server.Implementations/Data/SqliteItemRepository.cs | 7 ------- Emby.Server.Implementations/Dto/DtoService.cs | 3 --- Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs | 1 - Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs | 2 -- Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs | 1 - Emby.Server.Implementations/HttpServer/HttpResultFactory.cs | 1 - Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 -- .../Images/CollectionFolderImageProvider.cs | 1 - Emby.Server.Implementations/Images/DynamicImageProvider.cs | 1 - Emby.Server.Implementations/Library/LibraryManager.cs | 1 - Emby.Server.Implementations/Library/MediaSourceManager.cs | 2 -- .../Library/Resolvers/SpecialFolderResolver.cs | 1 - Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs | 1 - Emby.Server.Implementations/Library/SearchEngine.cs | 1 - Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs | 1 - Emby.Server.Implementations/Library/Validators/StudiosValidator.cs | 1 - Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 1 - Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs | 1 - Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 6 ------ Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs | 2 -- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 --- Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs | 2 -- Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs | 1 - Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs | 1 - Emby.Server.Implementations/Net/SocketFactory.cs | 2 -- Emby.Server.Implementations/Security/AuthenticationRepository.cs | 4 ---- Emby.Server.Implementations/TV/TVSeriesManager.cs | 1 - Jellyfin.Data/Entities/Artwork.cs | 1 - Jellyfin.Data/Entities/Book.cs | 1 - Jellyfin.Data/Entities/BookMetadata.cs | 1 - Jellyfin.Data/Entities/Chapter.cs | 1 - Jellyfin.Data/Entities/Collection.cs | 1 - Jellyfin.Data/Entities/CollectionItem.cs | 1 - Jellyfin.Data/Entities/Company.cs | 1 - Jellyfin.Data/Entities/CompanyMetadata.cs | 1 - Jellyfin.Data/Entities/CustomItem.cs | 1 - Jellyfin.Data/Entities/CustomItemMetadata.cs | 1 - Jellyfin.Data/Entities/Episode.cs | 1 - Jellyfin.Data/Entities/EpisodeMetadata.cs | 1 - Jellyfin.Data/Entities/Genre.cs | 1 - Jellyfin.Data/Entities/Library.cs | 1 - Jellyfin.Data/Entities/LibraryItem.cs | 1 - Jellyfin.Data/Entities/LibraryRoot.cs | 1 - Jellyfin.Data/Entities/MediaFile.cs | 1 - Jellyfin.Data/Entities/MediaFileStream.cs | 1 - Jellyfin.Data/Entities/Metadata.cs | 1 - Jellyfin.Data/Entities/MetadataProvider.cs | 1 - Jellyfin.Data/Entities/MetadataProviderId.cs | 1 - Jellyfin.Data/Entities/Movie.cs | 1 - Jellyfin.Data/Entities/MovieMetadata.cs | 1 - Jellyfin.Data/Entities/MusicAlbum.cs | 1 - Jellyfin.Data/Entities/MusicAlbumMetadata.cs | 1 - Jellyfin.Data/Entities/Person.cs | 1 - Jellyfin.Data/Entities/PersonRole.cs | 1 - Jellyfin.Data/Entities/Photo.cs | 1 - Jellyfin.Data/Entities/PhotoMetadata.cs | 1 - Jellyfin.Data/Entities/ProviderMapping.cs | 1 - Jellyfin.Data/Entities/Rating.cs | 1 - Jellyfin.Data/Entities/RatingSource.cs | 1 - Jellyfin.Data/Entities/Release.cs | 1 - Jellyfin.Data/Entities/Season.cs | 1 - Jellyfin.Data/Entities/SeasonMetadata.cs | 1 - Jellyfin.Data/Entities/Series.cs | 1 - Jellyfin.Data/Entities/SeriesMetadata.cs | 1 - Jellyfin.Data/Entities/Track.cs | 1 - Jellyfin.Data/Entities/TrackMetadata.cs | 1 - MediaBrowser.Api/BaseApiService.cs | 3 --- MediaBrowser.Api/ChannelService.cs | 1 - MediaBrowser.Api/ConfigurationService.cs | 2 -- MediaBrowser.Api/Devices/DeviceService.cs | 1 - MediaBrowser.Api/EnvironmentService.cs | 1 - MediaBrowser.Api/FilterService.cs | 2 -- MediaBrowser.Api/IHasItemFields.cs | 1 - MediaBrowser.Api/Images/ImageService.cs | 1 - MediaBrowser.Api/Images/RemoteImageService.cs | 1 - MediaBrowser.Api/Library/LibraryService.cs | 3 --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 7 ------- MediaBrowser.Api/Movies/CollectionService.cs | 1 - MediaBrowser.Api/Movies/MoviesService.cs | 4 ---- MediaBrowser.Api/Movies/TrailersService.cs | 1 - MediaBrowser.Api/Music/InstantMixService.cs | 1 - MediaBrowser.Api/Playback/MediaInfoService.cs | 3 --- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 1 - MediaBrowser.Api/Playback/UniversalAudioService.cs | 1 - MediaBrowser.Api/PlaylistService.cs | 1 - MediaBrowser.Api/SearchService.cs | 1 - MediaBrowser.Api/SimilarItemsHelper.cs | 1 - MediaBrowser.Api/System/SystemService.cs | 5 ----- MediaBrowser.Api/TvShowsService.cs | 2 -- MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs | 1 - MediaBrowser.Api/UserLibrary/UserViewsService.cs | 1 - MediaBrowser.Controller/Channels/ISearchableChannel.cs | 2 -- MediaBrowser.Controller/Entities/BaseItem.cs | 4 ---- MediaBrowser.Controller/Entities/Folder.cs | 4 ---- MediaBrowser.Controller/Entities/UserViewBuilder.cs | 4 ---- MediaBrowser.Controller/Entities/Video.cs | 1 - MediaBrowser.Controller/IO/FileData.cs | 1 - MediaBrowser.Controller/Library/ItemResolveArgs.cs | 2 -- MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs | 2 -- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 1 - MediaBrowser.Controller/Persistence/IUserDataRepository.cs | 1 - MediaBrowser.Controller/Plugins/IServerEntryPoint.cs | 1 - MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs | 3 --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 1 - MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 3 --- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 1 - MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs | 1 - MediaBrowser.Model/Dlna/ProfileCondition.cs | 1 - MediaBrowser.Model/Dlna/SortCriteria.cs | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 4 ---- MediaBrowser.Model/Entities/MediaStream.cs | 1 - MediaBrowser.Model/Entities/PackageReviewInfo.cs | 1 - MediaBrowser.Model/LiveTv/TimerInfoDto.cs | 1 - MediaBrowser.Model/Net/HttpException.cs | 1 - MediaBrowser.Model/Providers/RemoteSearchResult.cs | 1 - MediaBrowser.Providers/Manager/ItemImageProvider.cs | 2 -- MediaBrowser.Providers/Manager/ProviderManager.cs | 1 - MediaBrowser.Providers/Manager/ProviderUtils.cs | 1 - MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs | 1 - MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs | 1 - MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs | 1 - MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs | 1 - MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs | 1 - MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 3 --- MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs | 3 --- MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs | 1 - MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs | 1 - MediaBrowser.Providers/Studios/StudiosImageProvider.cs | 1 - MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 3 --- MediaBrowser.Providers/TV/TvExternalIds.cs | 1 - MediaBrowser.WebDashboard/jellyfin-web | 1 + RSSDP/DeviceAvailableEventArgs.cs | 1 - RSSDP/DeviceEventArgs.cs | 1 - RSSDP/HttpRequestParser.cs | 1 - RSSDP/ISsdpCommunicationsServer.cs | 1 - RSSDP/SsdpCommunicationsServer.cs | 2 -- RSSDP/SsdpConstants.cs | 1 - RSSDP/SsdpDevice.cs | 1 - RSSDP/SsdpDeviceLocator.cs | 2 -- RSSDP/SsdpDevicePublisher.cs | 1 - 150 files changed, 1 insertion(+), 226 deletions(-) create mode 120000 MediaBrowser.WebDashboard/jellyfin-web (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Didl/Filter.cs b/Emby.Dlna/Didl/Filter.cs index e4177239e..b730d9db2 100644 --- a/Emby.Dlna/Didl/Filter.cs +++ b/Emby.Dlna/Didl/Filter.cs @@ -12,7 +12,6 @@ namespace Emby.Dlna.Didl public Filter() : this("*") { - } public Filter(string filter) diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index ac9cd0ed3..e5f483950 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -88,7 +88,6 @@ namespace Emby.Dlna .Select(i => i.Item2) .ToList(); } - } public DeviceProfile GetDefaultProfile() diff --git a/Emby.Dlna/Eventing/EventManager.cs b/Emby.Dlna/Eventing/EventManager.cs index efbb53b64..5a51569e2 100644 --- a/Emby.Dlna/Eventing/EventManager.cs +++ b/Emby.Dlna/Eventing/EventManager.cs @@ -169,7 +169,6 @@ namespace Emby.Dlna.Eventing { using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false)) { - } } catch (OperationCanceledException) diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 156a1f382..86b72e264 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -794,7 +794,6 @@ namespace Emby.Dlna.PlayTo } catch (XmlException) { - } // first try to add a root node with a dlna namesapce @@ -806,7 +805,6 @@ namespace Emby.Dlna.PlayTo } catch (XmlException) { - } // some devices send back invalid xml @@ -816,7 +814,6 @@ namespace Emby.Dlna.PlayTo } catch (XmlException) { - } return null; diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index cd7612483..c0500eb68 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -112,7 +112,6 @@ namespace Emby.Dlna.PlayTo } catch (OperationCanceledException) { - } catch (Exception ex) { @@ -243,7 +242,6 @@ namespace Emby.Dlna.PlayTo } catch { - } _sessionLock.Dispose(); diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 8c1362007..ab262bebf 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -91,7 +91,6 @@ namespace Emby.Dlna.PlayTo using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false)) { - } } diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index f816fd54f..53c9ccdbf 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -162,7 +162,6 @@ namespace Emby.Server.Implementations.Data } return false; - }, ReadTransactionMode); } diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs index 6c9bcff0f..3de9d6371 100644 --- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs +++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs @@ -51,7 +51,6 @@ namespace Emby.Server.Implementations.Data _libraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false - }); } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index ab1fcc638..d33125661 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -321,7 +321,6 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); - }, TransactionMode); connection.RunQueries(postQueries); @@ -2044,7 +2043,6 @@ namespace Emby.Server.Implementations.Data db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); InsertChapters(idBlob, chapters, db); - }, TransactionMode); } } @@ -4789,7 +4787,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type connection.RunInTransaction(db => { connection.ExecuteAll(sql); - }, TransactionMode); } } @@ -5180,7 +5177,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } } - } LogQueryTime("GetItemValueNames", commandText, now); @@ -5631,7 +5627,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); InsertPeople(itemIdBlob, people, db); - }, TransactionMode); } } @@ -5788,7 +5783,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob); InsertMediaStreams(itemIdBlob, streams, db); - }, TransactionMode); } } @@ -6134,7 +6128,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob); InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken); - }, TransactionMode); } } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index aae8fce84..41ff7e3ab 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -593,7 +593,6 @@ namespace Emby.Server.Implementations.Dto _logger.LogError(ex, "Error getting person {Name}", c); return null; } - }).Where(i => i != null) .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .Select(x => x.First()) @@ -1000,7 +999,6 @@ namespace Emby.Server.Implementations.Dto } return null; - }).Where(i => i != null).ToArray(); } @@ -1051,7 +1049,6 @@ namespace Emby.Server.Implementations.Dto } return null; - }).Where(i => i != null).ToArray(); } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 02ae55071..c1068522a 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -132,7 +132,6 @@ namespace Emby.Server.Implementations.EntryPoints } catch { - } } } diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 083fe4237..826d4d8dc 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -159,7 +159,6 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception) { - } } @@ -175,7 +174,6 @@ namespace Emby.Server.Implementations.EntryPoints } catch (Exception) { - } } diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index ecdce89ce..b207397bd 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -43,7 +43,6 @@ namespace Emby.Server.Implementations.EntryPoints _logger = logger; _appHost = appHost; _config = configuration; - } /// diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index cc4797790..d254d394f 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -580,7 +580,6 @@ namespace Emby.Server.Implementations.HttpServer } catch (NotSupportedException) { - } } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 49bca7dac..a32b03aaa 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -266,7 +266,6 @@ namespace Emby.Server.Implementations.IO { DisposeWatcher(newWatcher, false); } - } catch (Exception ex) { @@ -393,7 +392,6 @@ namespace Emby.Server.Implementations.IO } return false; - })) { monitorPath = false; diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index dc8062b45..da88b8d8a 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -71,7 +71,6 @@ namespace Emby.Server.Implementations.Images new ValueTuple(ItemSortBy.Random, SortOrder.Ascending) }, IncludeItemTypes = includeItemTypes - }); } diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index ca0aa4a9f..462eb03a8 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -78,7 +78,6 @@ namespace Emby.Server.Implementations.Images } return i; - }).GroupBy(x => x.Id) .Select(x => x.First()); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 4c22a3530..1d4651da2 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2861,7 +2861,6 @@ namespace Emby.Server.Implementations.Library _logger.LogError(ex, "Error getting person"); return null; } - }).Where(i => i != null).ToList(); } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index cee499e78..919261027 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -436,7 +436,6 @@ namespace Emby.Server.Implementations.Library } return 1; - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) .ThenByDescending(i => { @@ -620,7 +619,6 @@ namespace Emby.Server.Implementations.Library MediaSource = mediaSource, ExtractChapters = false, MediaType = DlnaProfileType.Video - }, cancellationToken).ConfigureAwait(false); mediaSource.MediaStreams = info.MediaStreams; diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index cc5a3bd5b..4819f2fc0 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -73,7 +73,6 @@ namespace Emby.Server.Implementations.Library.Resolvers { return false; } - }) .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) .FirstOrDefault(); diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 7f8800a64..c43a0ec6b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -94,7 +94,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV _localization.GetLocalizedString("NameSeasonNumber"), seasonNumber, args.GetLibraryOptions().PreferredMetadataLanguage); - } return season; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index f37cb3e9d..b8c42cdf8 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -207,7 +207,6 @@ namespace Emby.Server.Implementations.Library return mediaItems.Select(i => new SearchHintInfo { Item = i - }).ToList(); } } diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs index 8a6bd5e78..d4c8c35e6 100644 --- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs @@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Library.Validators _libraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false - }, false); } diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs index 7a6cd11df..ca35adfff 100644 --- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -92,7 +92,6 @@ namespace Emby.Server.Implementations.Library.Validators _libraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false - }, false); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 9fb5aec29..7b0fcbc9e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1547,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IsFolder = false, Recursive = true, DtoOptions = new DtoOptions(true) - }) .Where(i => i.IsFileProtocol && File.Exists(i.Path)) .Skip(seriesTimer.KeepUpTo - 1) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 5e147225a..fdd305f86 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -1218,7 +1218,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings public string programID { get; set; } public List data { get; set; } } - } } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ddc8cafac..42e93b7ff 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1168,7 +1168,6 @@ namespace Emby.Server.Implementations.LiveTv IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, ChannelIds = new Guid[] { currentChannel.Id }, DtoOptions = new DtoOptions(true) - }).Cast().ToDictionary(i => i.Id); var newPrograms = new List(); @@ -1738,7 +1737,6 @@ namespace Emby.Server.Implementations.LiveTv var results = await GetTimers(new TimerQuery { Id = id - }, cancellationToken).ConfigureAwait(false); return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); @@ -1790,7 +1788,6 @@ namespace Emby.Server.Implementations.LiveTv .Select(i => { return i.Item1; - }) .ToArray(); @@ -1845,7 +1842,6 @@ namespace Emby.Server.Implementations.LiveTv } return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName); - }) .ToArray(); @@ -1878,7 +1874,6 @@ namespace Emby.Server.Implementations.LiveTv OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) }, TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id }, DtoOptions = options - }) : new List(); RemoveFields(options); @@ -2456,7 +2451,6 @@ namespace Emby.Server.Implementations.LiveTv UserId = user.Id, IsRecordingsFolder = true, RefreshLatestChannelItems = refreshChannels - }).Items); return folders.Cast().ToList(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index abdcdd622..a8d34d19c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -99,7 +99,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (IOException) { - } } } @@ -116,7 +115,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (IOException) { - } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 464b06b32..f14fcde2a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -111,7 +111,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun ChannelType = ChannelType.TV, IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), Path = i.URL - }).Cast().ToList(); } @@ -481,7 +480,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Height = height, BitRate = videoBitrate, NalLengthSize = nal - }, new MediaStream { @@ -722,7 +720,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } } - } catch (OperationCanceledException) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 4e4f1d7f6..4decdc24f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -220,11 +220,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } catch (IOException) { - } catch (ArgumentException) { - } catch (Exception ex) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index f7c9c736e..ff42a9747 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -127,7 +127,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) { - } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 883b175d6..c798c0a85 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -210,7 +210,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } } - } if (!IsValidChannelNumber(numberString)) diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index fd863d25a..177721658 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Net } catch (SocketException) { - } try @@ -109,7 +108,6 @@ namespace Emby.Server.Implementations.Net } catch (SocketException) { - } try diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs index 750890ec8..9c1be9a1a 100644 --- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs +++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs @@ -61,7 +61,6 @@ namespace Emby.Server.Implementations.Security AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames); AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames); AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames); - }, TransactionMode); connection.RunQueries(new[] @@ -107,7 +106,6 @@ namespace Emby.Server.Implementations.Security statement.MoveNext(); } - }, TransactionMode); } } @@ -367,7 +365,6 @@ namespace Emby.Server.Implementations.Security return result; } - }, ReadTransactionMode); } } @@ -398,7 +395,6 @@ namespace Emby.Server.Implementations.Security statement.MoveNext(); } - }, TransactionMode); } } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index ba6c4f261..db056cc38 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -225,7 +225,6 @@ namespace Emby.Server.Implementations.TV ParentIndexNumberNotEquals = 0, MinSortName = lastWatchedEpisode?.SortName, DtoOptions = dtoOptions - }).Cast().FirstOrDefault(); }; diff --git a/Jellyfin.Data/Entities/Artwork.cs b/Jellyfin.Data/Entities/Artwork.cs index bf3029368..214fb4cb1 100644 --- a/Jellyfin.Data/Entities/Artwork.cs +++ b/Jellyfin.Data/Entities/Artwork.cs @@ -189,7 +189,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Book.cs b/Jellyfin.Data/Entities/Book.cs index 42d24e31d..faefc7400 100644 --- a/Jellyfin.Data/Entities/Book.cs +++ b/Jellyfin.Data/Entities/Book.cs @@ -63,7 +63,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Release_Releases_Id")] public virtual ICollection Releases { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/BookMetadata.cs b/Jellyfin.Data/Entities/BookMetadata.cs index d52fe7605..dd389b64a 100644 --- a/Jellyfin.Data/Entities/BookMetadata.cs +++ b/Jellyfin.Data/Entities/BookMetadata.cs @@ -101,7 +101,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Company_Publishers_Id")] public virtual ICollection Publishers { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs index d48cb9b62..9b3a5e827 100644 --- a/Jellyfin.Data/Entities/Chapter.cs +++ b/Jellyfin.Data/Entities/Chapter.cs @@ -257,7 +257,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Collection.cs b/Jellyfin.Data/Entities/Collection.cs index e2fa3a5bd..c040cfe33 100644 --- a/Jellyfin.Data/Entities/Collection.cs +++ b/Jellyfin.Data/Entities/Collection.cs @@ -114,7 +114,6 @@ namespace Jellyfin.Data.Entities *************************************************************************/ [ForeignKey("CollectionItem_CollectionItem_Id")] public virtual ICollection CollectionItem { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/CollectionItem.cs b/Jellyfin.Data/Entities/CollectionItem.cs index 4a3d06639..c5e54c3a2 100644 --- a/Jellyfin.Data/Entities/CollectionItem.cs +++ b/Jellyfin.Data/Entities/CollectionItem.cs @@ -137,7 +137,6 @@ namespace Jellyfin.Data.Entities /// [ForeignKey("CollectionItem_Previous_Id")] public virtual CollectionItem Previous { get; set; } - } } diff --git a/Jellyfin.Data/Entities/Company.cs b/Jellyfin.Data/Entities/Company.cs index 0650271c6..7d6f3b207 100644 --- a/Jellyfin.Data/Entities/Company.cs +++ b/Jellyfin.Data/Entities/Company.cs @@ -131,7 +131,6 @@ namespace Jellyfin.Data.Entities public virtual ICollection CompanyMetadata { get; protected set; } [ForeignKey("Company_Parent_Id")] public virtual Company Parent { get; set; } - } } diff --git a/Jellyfin.Data/Entities/CompanyMetadata.cs b/Jellyfin.Data/Entities/CompanyMetadata.cs index b3ec9c1a7..1ad03b4f9 100644 --- a/Jellyfin.Data/Entities/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/CompanyMetadata.cs @@ -210,7 +210,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/CustomItem.cs b/Jellyfin.Data/Entities/CustomItem.cs index 2006717bf..5f6fc3a23 100644 --- a/Jellyfin.Data/Entities/CustomItem.cs +++ b/Jellyfin.Data/Entities/CustomItem.cs @@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Release_Releases_Id")] public virtual ICollection Releases { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/CustomItemMetadata.cs b/Jellyfin.Data/Entities/CustomItemMetadata.cs index e09e4467a..ee37aaaa9 100644 --- a/Jellyfin.Data/Entities/CustomItemMetadata.cs +++ b/Jellyfin.Data/Entities/CustomItemMetadata.cs @@ -61,7 +61,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Episode.cs b/Jellyfin.Data/Entities/Episode.cs index 6f6baa14d..88531205f 100644 --- a/Jellyfin.Data/Entities/Episode.cs +++ b/Jellyfin.Data/Entities/Episode.cs @@ -104,7 +104,6 @@ namespace Jellyfin.Data.Entities public virtual ICollection Releases { get; protected set; } [ForeignKey("EpisodeMetadata_EpisodeMetadata_Id")] public virtual ICollection EpisodeMetadata { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/EpisodeMetadata.cs b/Jellyfin.Data/Entities/EpisodeMetadata.cs index e5431bf22..0aa4b4270 100644 --- a/Jellyfin.Data/Entities/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/EpisodeMetadata.cs @@ -173,7 +173,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Genre.cs b/Jellyfin.Data/Entities/Genre.cs index 38f289a8e..ff0710671 100644 --- a/Jellyfin.Data/Entities/Genre.cs +++ b/Jellyfin.Data/Entities/Genre.cs @@ -146,7 +146,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Library.cs b/Jellyfin.Data/Entities/Library.cs index c11c09e91..a5cc5c8da 100644 --- a/Jellyfin.Data/Entities/Library.cs +++ b/Jellyfin.Data/Entities/Library.cs @@ -141,7 +141,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/LibraryItem.cs b/Jellyfin.Data/Entities/LibraryItem.cs index af6c640b9..c2ba7059d 100644 --- a/Jellyfin.Data/Entities/LibraryItem.cs +++ b/Jellyfin.Data/Entities/LibraryItem.cs @@ -164,7 +164,6 @@ namespace Jellyfin.Data.Entities /// [ForeignKey("LibraryRoot_Id")] public virtual LibraryRoot LibraryRoot { get; set; } - } } diff --git a/Jellyfin.Data/Entities/LibraryRoot.cs b/Jellyfin.Data/Entities/LibraryRoot.cs index bbc23e1c9..7823db02a 100644 --- a/Jellyfin.Data/Entities/LibraryRoot.cs +++ b/Jellyfin.Data/Entities/LibraryRoot.cs @@ -186,7 +186,6 @@ namespace Jellyfin.Data.Entities /// [ForeignKey("Library_Id")] public virtual Library Library { get; set; } - } } diff --git a/Jellyfin.Data/Entities/MediaFile.cs b/Jellyfin.Data/Entities/MediaFile.cs index 719539e5c..94c39a28a 100644 --- a/Jellyfin.Data/Entities/MediaFile.cs +++ b/Jellyfin.Data/Entities/MediaFile.cs @@ -194,7 +194,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("MediaFileStream_MediaFileStreams_Id")] public virtual ICollection MediaFileStreams { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/MediaFileStream.cs b/Jellyfin.Data/Entities/MediaFileStream.cs index 7b3399731..723977fdf 100644 --- a/Jellyfin.Data/Entities/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/MediaFileStream.cs @@ -143,7 +143,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Metadata.cs b/Jellyfin.Data/Entities/Metadata.cs index 467ee6822..6558642cf 100644 --- a/Jellyfin.Data/Entities/Metadata.cs +++ b/Jellyfin.Data/Entities/Metadata.cs @@ -374,7 +374,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("PersonRole_PersonRoles_Id")] public virtual ICollection Sources { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/MetadataProvider.cs b/Jellyfin.Data/Entities/MetadataProvider.cs index 4e4f107fb..bf9689709 100644 --- a/Jellyfin.Data/Entities/MetadataProvider.cs +++ b/Jellyfin.Data/Entities/MetadataProvider.cs @@ -141,7 +141,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/MetadataProviderId.cs b/Jellyfin.Data/Entities/MetadataProviderId.cs index 926f223de..c49c6f42e 100644 --- a/Jellyfin.Data/Entities/MetadataProviderId.cs +++ b/Jellyfin.Data/Entities/MetadataProviderId.cs @@ -173,7 +173,6 @@ namespace Jellyfin.Data.Entities /// [ForeignKey("MetadataProvider_Id")] public virtual MetadataProvider MetadataProvider { get; set; } - } } diff --git a/Jellyfin.Data/Entities/Movie.cs b/Jellyfin.Data/Entities/Movie.cs index b359b42fc..ad2504b0d 100644 --- a/Jellyfin.Data/Entities/Movie.cs +++ b/Jellyfin.Data/Entities/Movie.cs @@ -63,7 +63,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("MovieMetadata_MovieMetadata_Id")] public virtual ICollection MovieMetadata { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/MovieMetadata.cs b/Jellyfin.Data/Entities/MovieMetadata.cs index 319ae94e5..1f8f1c2a0 100644 --- a/Jellyfin.Data/Entities/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/MovieMetadata.cs @@ -217,7 +217,6 @@ namespace Jellyfin.Data.Entities *************************************************************************/ [ForeignKey("Company_Studios_Id")] public virtual ICollection Studios { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/MusicAlbum.cs b/Jellyfin.Data/Entities/MusicAlbum.cs index 00cb8fe00..e07f4357b 100644 --- a/Jellyfin.Data/Entities/MusicAlbum.cs +++ b/Jellyfin.Data/Entities/MusicAlbum.cs @@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Track_Tracks_Id")] public virtual ICollection Tracks { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs index b52ca6564..7743890a6 100644 --- a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs @@ -181,7 +181,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Company_Labels_Id")] public virtual ICollection Labels { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/Person.cs b/Jellyfin.Data/Entities/Person.cs index d893b7e39..f71418819 100644 --- a/Jellyfin.Data/Entities/Person.cs +++ b/Jellyfin.Data/Entities/Person.cs @@ -296,7 +296,6 @@ namespace Jellyfin.Data.Entities *************************************************************************/ [ForeignKey("MetadataProviderId_Sources_Id")] public virtual ICollection Sources { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/PersonRole.cs b/Jellyfin.Data/Entities/PersonRole.cs index 9bd12c7fb..a3d047115 100644 --- a/Jellyfin.Data/Entities/PersonRole.cs +++ b/Jellyfin.Data/Entities/PersonRole.cs @@ -203,7 +203,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("MetadataProviderId_Sources_Id")] public virtual ICollection Sources { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/Photo.cs b/Jellyfin.Data/Entities/Photo.cs index 7abe62891..226730126 100644 --- a/Jellyfin.Data/Entities/Photo.cs +++ b/Jellyfin.Data/Entities/Photo.cs @@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Release_Releases_Id")] public virtual ICollection Releases { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/PhotoMetadata.cs b/Jellyfin.Data/Entities/PhotoMetadata.cs index c5502f707..2bb239cdd 100644 --- a/Jellyfin.Data/Entities/PhotoMetadata.cs +++ b/Jellyfin.Data/Entities/PhotoMetadata.cs @@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/ProviderMapping.cs b/Jellyfin.Data/Entities/ProviderMapping.cs index e479341ad..e86d9737f 100644 --- a/Jellyfin.Data/Entities/ProviderMapping.cs +++ b/Jellyfin.Data/Entities/ProviderMapping.cs @@ -111,7 +111,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Rating.cs b/Jellyfin.Data/Entities/Rating.cs index f70ea8b33..0c8b99ca2 100644 --- a/Jellyfin.Data/Entities/Rating.cs +++ b/Jellyfin.Data/Entities/Rating.cs @@ -181,7 +181,6 @@ namespace Jellyfin.Data.Entities /// [ForeignKey("RatingSource_RatingType_Id")] public virtual RatingSource RatingType { get; set; } - } } diff --git a/Jellyfin.Data/Entities/RatingSource.cs b/Jellyfin.Data/Entities/RatingSource.cs index 070f1ae27..c829042b5 100644 --- a/Jellyfin.Data/Entities/RatingSource.cs +++ b/Jellyfin.Data/Entities/RatingSource.cs @@ -225,7 +225,6 @@ namespace Jellyfin.Data.Entities *************************************************************************/ [ForeignKey("MetadataProviderId_Source_Id")] public virtual MetadataProviderId Source { get; set; } - } } diff --git a/Jellyfin.Data/Entities/Release.cs b/Jellyfin.Data/Entities/Release.cs index d1928fcf7..35fcbb4b7 100644 --- a/Jellyfin.Data/Entities/Release.cs +++ b/Jellyfin.Data/Entities/Release.cs @@ -182,7 +182,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Chapter_Chapters_Id")] public virtual ICollection Chapters { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/Season.cs b/Jellyfin.Data/Entities/Season.cs index 96e89cde0..2a861b660 100644 --- a/Jellyfin.Data/Entities/Season.cs +++ b/Jellyfin.Data/Entities/Season.cs @@ -105,7 +105,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Episode_Episodes_Id")] public virtual ICollection Episodes { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/SeasonMetadata.cs b/Jellyfin.Data/Entities/SeasonMetadata.cs index 64ecbfbfa..10320c6bb 100644 --- a/Jellyfin.Data/Entities/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/SeasonMetadata.cs @@ -100,7 +100,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/Jellyfin.Data/Entities/Series.cs b/Jellyfin.Data/Entities/Series.cs index 4f25c38b7..cf1d6b781 100644 --- a/Jellyfin.Data/Entities/Series.cs +++ b/Jellyfin.Data/Entities/Series.cs @@ -153,7 +153,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("Season_Seasons_Id")] public virtual ICollection Seasons { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/SeriesMetadata.cs b/Jellyfin.Data/Entities/SeriesMetadata.cs index 52691783f..bb31c2e4e 100644 --- a/Jellyfin.Data/Entities/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/SeriesMetadata.cs @@ -217,7 +217,6 @@ namespace Jellyfin.Data.Entities *************************************************************************/ [ForeignKey("Company_Networks_Id")] public virtual ICollection Networks { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/Track.cs b/Jellyfin.Data/Entities/Track.cs index 079d73d2b..c9e8fd1c3 100644 --- a/Jellyfin.Data/Entities/Track.cs +++ b/Jellyfin.Data/Entities/Track.cs @@ -106,7 +106,6 @@ namespace Jellyfin.Data.Entities [ForeignKey("TrackMetadata_TrackMetadata_Id")] public virtual ICollection TrackMetadata { get; protected set; } - } } diff --git a/Jellyfin.Data/Entities/TrackMetadata.cs b/Jellyfin.Data/Entities/TrackMetadata.cs index 86c9161f6..7b99c0683 100644 --- a/Jellyfin.Data/Entities/TrackMetadata.cs +++ b/Jellyfin.Data/Entities/TrackMetadata.cs @@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities /************************************************************************* * Navigation properties *************************************************************************/ - } } diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 2ece16ee1..a91a9b580 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -268,7 +268,6 @@ namespace MediaBrowser.Api Name = name.Replace(BaseItem.SlugChar, '&'), IncludeItemTypes = new[] { typeof(T).Name }, DtoOptions = dtoOptions - }).OfType().FirstOrDefault(); result ??= libraryManager.GetItemList(new InternalItemsQuery @@ -276,7 +275,6 @@ namespace MediaBrowser.Api Name = name.Replace(BaseItem.SlugChar, '/'), IncludeItemTypes = new[] { typeof(T).Name }, DtoOptions = dtoOptions - }).OfType().FirstOrDefault(); result ??= libraryManager.GetItemList(new InternalItemsQuery @@ -284,7 +282,6 @@ namespace MediaBrowser.Api Name = name.Replace(BaseItem.SlugChar, '?'), IncludeItemTypes = new[] { typeof(T).Name }, DtoOptions = dtoOptions - }).OfType().FirstOrDefault(); return result; diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs index fd9b8c396..3cab9fb66 100644 --- a/MediaBrowser.Api/ChannelService.cs +++ b/MediaBrowser.Api/ChannelService.cs @@ -240,7 +240,6 @@ namespace MediaBrowser.Api { Fields = request.GetItemFields() } - }; foreach (var filter in request.GetFilters()) diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index 316be04a0..3ad51de8d 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -17,7 +17,6 @@ namespace MediaBrowser.Api [Authenticated] public class GetConfiguration : IReturn { - } [Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")] @@ -51,7 +50,6 @@ namespace MediaBrowser.Api [Authenticated(Roles = "Admin")] public class GetDefaultMetadataOptions : IReturn { - } [Route("/System/MediaEncoder/Path", "POST", Summary = "Updates the path to the media encoder")] diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs index dd3f3e738..18860983e 100644 --- a/MediaBrowser.Api/Devices/DeviceService.cs +++ b/MediaBrowser.Api/Devices/DeviceService.cs @@ -92,7 +92,6 @@ namespace MediaBrowser.Api.Devices var sessions = _authRepo.Get(new AuthenticationInfoQuery { DeviceId = request.Id - }).Items; foreach (var session in sessions) diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 82d471412..fddf78465 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -100,7 +100,6 @@ namespace MediaBrowser.Api [Route("/Environment/DefaultDirectoryBrowser", "GET", Summary = "Gets the parent path of a given path")] public class GetDefaultDirectoryBrowser : IReturn { - } /// diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs index bd67ec41f..833a684a5 100644 --- a/MediaBrowser.Api/FilterService.cs +++ b/MediaBrowser.Api/FilterService.cs @@ -150,7 +150,6 @@ namespace MediaBrowser.Api { Name = i.Item1.Name, Id = i.Item1.Id - }).ToArray(); } else @@ -159,7 +158,6 @@ namespace MediaBrowser.Api { Name = i.Item1.Name, Id = i.Item1.Id - }).ToArray(); } diff --git a/MediaBrowser.Api/IHasItemFields.cs b/MediaBrowser.Api/IHasItemFields.cs index 85b4a7e2d..6359de77d 100644 --- a/MediaBrowser.Api/IHasItemFields.cs +++ b/MediaBrowser.Api/IHasItemFields.cs @@ -43,7 +43,6 @@ namespace MediaBrowser.Api } return null; - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); } } diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 0b8ddeacd..6f2956c5d 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -743,7 +743,6 @@ namespace MediaBrowser.Api.Images Path = imageResult.Item1, FileShare = FileShare.Read - }).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 358ac30fa..2633a5d3c 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -152,7 +152,6 @@ namespace MediaBrowser.Api.Images IncludeAllLanguages = request.IncludeAllLanguages, IncludeDisabledProviders = true, ImageType = request.Type - }, CancellationToken.None).ConfigureAwait(false); var imagesList = images.ToArray(); diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 2b4694925..284a2c11b 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -562,7 +562,6 @@ namespace MediaBrowser.Api.Library _authContext) { Request = Request, - }.GetSimilarItemsResult(request); } @@ -660,7 +659,6 @@ namespace MediaBrowser.Api.Library { EnableImages = false } - }).Where(i => string.Equals(request.TvdbId, i.GetProviderId(MetadataProvider.Tvdb), StringComparison.OrdinalIgnoreCase)).ToArray(); foreach (var item in series) @@ -689,7 +687,6 @@ namespace MediaBrowser.Api.Library { EnableImages = false } - }); if (!string.IsNullOrWhiteSpace(request.ImdbId)) diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 279fd6ee9..b00a5fec8 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -679,7 +679,6 @@ namespace MediaBrowser.Api.LiveTv [Authenticated] public class GetTunerHostTypes : IReturn> { - } [Route("/LiveTv/Tuners/Discvover", "GET")] @@ -826,7 +825,6 @@ namespace MediaBrowser.Api.LiveTv { Name = i.Name, Id = i.Id - }).ToList(), Mappings = mappings, @@ -845,7 +843,6 @@ namespace MediaBrowser.Api.LiveTv { Url = "https://json.schedulesdirect.org/20141201/available/countries", BufferContent = false - }).ConfigureAwait(false); return ResultFactory.GetResult(Request, response, "application/json"); @@ -958,7 +955,6 @@ namespace MediaBrowser.Api.LiveTv SortBy = request.GetOrderBy(), SortOrder = request.SortOrder ?? SortOrder.Ascending, AddCurrentProgram = request.AddCurrentProgram - }, options, CancellationToken.None); var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId); @@ -1113,7 +1109,6 @@ namespace MediaBrowser.Api.LiveTv Fields = request.GetItemFields(), ImageTypeLimit = request.ImageTypeLimit, EnableImages = request.EnableImages - }, options); return ToOptimizedResult(result); @@ -1152,7 +1147,6 @@ namespace MediaBrowser.Api.LiveTv SeriesTimerId = request.SeriesTimerId, IsActive = request.IsActive, IsScheduled = request.IsScheduled - }, CancellationToken.None).ConfigureAwait(false); return ToOptimizedResult(result); @@ -1188,7 +1182,6 @@ namespace MediaBrowser.Api.LiveTv { SortOrder = request.SortOrder, SortBy = request.SortBy - }, CancellationToken.None).ConfigureAwait(false); return ToOptimizedResult(result); diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs index 95a37dfc5..e9629439d 100644 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ b/MediaBrowser.Api/Movies/CollectionService.cs @@ -79,7 +79,6 @@ namespace MediaBrowser.Api.Movies ParentId = parentId, ItemIdList = SplitValue(request.Ids, ','), UserIds = new[] { userId } - }); var dtoOptions = GetDtoOptions(_authContext, request); diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 281c7e613..88ca0aa23 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -194,7 +194,6 @@ namespace MediaBrowser.Api.Movies ParentId = parentIdGuid, Recursive = true, DtoOptions = dtoOptions - }); var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList(); @@ -279,7 +278,6 @@ namespace MediaBrowser.Api.Movies IsMovie = true, EnableGroupByMetadataKey = true, DtoOptions = dtoOptions - }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) .Select(x => x.First()) .Take(itemLimit) @@ -320,7 +318,6 @@ namespace MediaBrowser.Api.Movies IsMovie = true, EnableGroupByMetadataKey = true, DtoOptions = dtoOptions - }).GroupBy(i => i.GetProviderId(MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)) .Select(x => x.First()) .Take(itemLimit) @@ -360,7 +357,6 @@ namespace MediaBrowser.Api.Movies SimilarTo = item, EnableGroupByMetadataKey = true, DtoOptions = dtoOptions - }); if (similar.Count > 0) diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 0b5334235..a7758b100 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -82,7 +82,6 @@ namespace MediaBrowser.Api.Movies _authContext) { Request = Request, - }.Get(getItems); } } diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs index 7d10c9427..ebd3eb64a 100644 --- a/MediaBrowser.Api/Music/InstantMixService.cs +++ b/MediaBrowser.Api/Music/InstantMixService.cs @@ -192,6 +192,5 @@ namespace MediaBrowser.Api.Music return result; } - } } diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2c6534cc0..2dc62fda7 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -646,7 +646,6 @@ namespace MediaBrowser.Api.Playback } return 1; - }).ThenBy(i => { // Let's assume direct streaming a file is just as desirable as direct playing a remote url @@ -656,7 +655,6 @@ namespace MediaBrowser.Api.Playback } return 1; - }).ThenBy(i => { return i.Protocol switch @@ -672,7 +670,6 @@ namespace MediaBrowser.Api.Playback } return 1; - }).ThenBy(originalList.IndexOf) .ToArray(); } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 4de81655c..a35e6c201 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -59,7 +59,6 @@ namespace MediaBrowser.Api.Playback.Progressive [Route("/Videos/{Id}/stream", "HEAD")] public class GetVideoStream : VideoStreamRequest { - } /// diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index a3b319d44..b2d101a5b 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -259,7 +259,6 @@ namespace MediaBrowser.Api.Playback UserId = request.UserId, DeviceProfile = deviceProfile, MediaSourceId = request.MediaSourceId - }).ConfigureAwait(false); var mediaSource = playbackInfoResult.MediaSources[0]; diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs index 953b00e35..d5def03be 100644 --- a/MediaBrowser.Api/PlaylistService.cs +++ b/MediaBrowser.Api/PlaylistService.cs @@ -161,7 +161,6 @@ namespace MediaBrowser.Api ItemIdList = GetGuids(request.Ids), UserId = request.UserId, MediaType = request.MediaType - }).ConfigureAwait(false); return ToOptimizedResult(result); diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index e9d339c6e..4a2f96ed8 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -180,7 +180,6 @@ namespace MediaBrowser.Api IsNews = request.IsNews, IsSeries = request.IsSeries, IsSports = request.IsSports - }); return new SearchHintResult diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index dcd22280a..90c324ff3 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -218,6 +218,5 @@ namespace MediaBrowser.Api return points; } - } } diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index c57cc93d5..4f10a4ad2 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -24,20 +24,17 @@ namespace MediaBrowser.Api.System [Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)] public class GetSystemInfo : IReturn { - } [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")] public class GetPublicSystemInfo : IReturn { - } [Route("/System/Ping", "POST")] [Route("/System/Ping", "GET")] public class PingSystem : IReturnVoid { - } /// @@ -83,7 +80,6 @@ namespace MediaBrowser.Api.System [Authenticated] public class GetWakeOnLanInfo : IReturn { - } /// @@ -153,7 +149,6 @@ namespace MediaBrowser.Api.System DateModified = _fileSystem.GetLastWriteTimeUtc(i), Name = i.Name, Size = i.Length - }).OrderByDescending(i => i.DateModified) .ThenByDescending(i => i.DateCreated) .ThenBy(i => i.Name) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 0c23d8b29..23062b67b 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -306,7 +306,6 @@ namespace MediaBrowser.Api ParentId = parentIdGuid, Recursive = true, DtoOptions = options - }); var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user); @@ -390,7 +389,6 @@ namespace MediaBrowser.Api IsMissing = request.IsMissing, IsSpecialSeason = request.IsSpecialSeason, AdjacentTo = request.AdjacentTo - }); var dtoOptions = GetDtoOptions(_authContext, request); diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index a1ec08467..4802849f4 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -322,7 +322,6 @@ namespace MediaBrowser.Api.UserLibrary { ibnItems = ibnItems.Take(request.Limit.Value); } - } var tuples = ibnItems.Select(i => new Tuple>(i, new List())); diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 0fffb0622..73d5ec6de 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -129,7 +129,6 @@ namespace MediaBrowser.Api.UserLibrary { Name = i.Name, Id = i.Id.ToString("N", CultureInfo.InvariantCulture) - }) .OrderBy(i => i.Name) .ToArray(); diff --git a/MediaBrowser.Controller/Channels/ISearchableChannel.cs b/MediaBrowser.Controller/Channels/ISearchableChannel.cs index d5b76a160..48043ad7a 100644 --- a/MediaBrowser.Controller/Channels/ISearchableChannel.cs +++ b/MediaBrowser.Controller/Channels/ISearchableChannel.cs @@ -35,12 +35,10 @@ namespace MediaBrowser.Controller.Channels public interface IDisableMediaSourceDisplay { - } public interface ISupportsMediaProbe { - } public interface IHasFolderAttributes diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 52fe83af0..3b08bd237 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -767,7 +767,6 @@ namespace MediaBrowser.Controller.Entities get => GetParent() as Folder; set { - } } @@ -1064,7 +1063,6 @@ namespace MediaBrowser.Controller.Entities } return 1; - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) .ThenByDescending(i => { @@ -1347,12 +1345,10 @@ namespace MediaBrowser.Controller.Entities protected virtual void TriggerOnRefreshStart() { - } protected virtual void TriggerOnRefreshComplete() { - } /// diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 366b3bd70..3a01b4379 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -500,7 +500,6 @@ namespace MediaBrowser.Controller.Entities if (series != null) { await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - } await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false); } @@ -615,7 +614,6 @@ namespace MediaBrowser.Controller.Entities { EnableImages = false } - }); return result.TotalRecordCount; @@ -1629,7 +1627,6 @@ namespace MediaBrowser.Controller.Entities Recursive = true, IsFolder = false, EnableTotalRecordCount = false - }); // Sweep through recursively and update status @@ -1647,7 +1644,6 @@ namespace MediaBrowser.Controller.Entities IsFolder = false, IsVirtualItem = false, EnableTotalRecordCount = false - }); return itemsResult diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 8162fb4eb..dbfef0777 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -270,7 +270,6 @@ namespace MediaBrowser.Controller.Entities _logger.LogError(ex, "Error getting genre"); return null; } - }) .Where(i => i != null) .Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent)); @@ -347,7 +346,6 @@ namespace MediaBrowser.Controller.Entities Limit = query.Limit, StartIndex = query.StartIndex, UserId = query.User.Id - }, parentFolders, query.DtoOptions); return result; @@ -384,7 +382,6 @@ namespace MediaBrowser.Controller.Entities IncludeItemTypes = new[] { typeof(Series).Name }, Recursive = true, EnableTotalRecordCount = false - }).Items .SelectMany(i => i.Genres) .DistinctNames() @@ -399,7 +396,6 @@ namespace MediaBrowser.Controller.Entities _logger.LogError(ex, "Error getting genre"); return null; } - }) .Where(i => i != null) .Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent)); diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 72eb67a06..4cfa0e74d 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -535,7 +535,6 @@ namespace MediaBrowser.Controller.Entities { ItemId = Id, Index = DefaultVideoStreamIndex.Value - }).FirstOrDefault(); } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 848e4fb16..aa7373815 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -118,7 +118,6 @@ namespace MediaBrowser.Controller.IO } return returnResult; } - } } diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 0222b926e..cca85cd3b 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -89,7 +89,6 @@ namespace MediaBrowser.Controller.Library return parentDir.Length > _appPaths.RootFolderPath.Length && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); - } } @@ -129,7 +128,6 @@ namespace MediaBrowser.Controller.Library } return item != null; - } return false; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs index df8f91eec..92b8ee67c 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs @@ -9,12 +9,10 @@ namespace MediaBrowser.Controller.LiveTv { public LiveTvConflictException() { - } public LiveTvConflictException(string message) : base(message) { - } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 23cb3dbbc..0ca42c0e0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -759,7 +759,6 @@ namespace MediaBrowser.Controller.MediaEncoding } param += " -look_ahead 0"; - } else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc) || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index a4bdf60d7..4c327eeef 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -44,6 +44,5 @@ namespace MediaBrowser.Controller.Persistence /// /// void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken); - } } diff --git a/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs b/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs index 1e8654c4d..b44e2531e 100644 --- a/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs +++ b/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs @@ -22,6 +22,5 @@ namespace MediaBrowser.Controller.Plugins /// public interface IRunBeforeStartup { - } } diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 9fb28c334..0ceb55c57 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -255,7 +255,6 @@ namespace MediaBrowser.LocalMetadata.Parsers } return null; - }).Where(i => i.HasValue).Select(i => i.Value).ToArray(); } @@ -680,7 +679,6 @@ namespace MediaBrowser.LocalMetadata.Parsers } break; - } } } @@ -1260,6 +1258,5 @@ namespace MediaBrowser.LocalMetadata.Parsers { return val.Split(separators, options); } - } } diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index a82f2108f..f02999370 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -269,7 +269,6 @@ namespace MediaBrowser.MediaEncoding.Attachments if (disposing) { - } _disposed = true; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 18e4a38c6..a4896d5f9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -920,7 +920,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var fileParts = _fileSystem.GetFileNameWithoutExtension(f).Split('_'); return fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase); - }).ToList(); // If this resulted in not getting any vobs, just take them all diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ed5f77053..7d57a691e 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -413,7 +413,6 @@ namespace MediaBrowser.MediaEncoding.Probing .Where(i => !string.IsNullOrWhiteSpace(i)) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); - } else if (string.Equals(key, "screenwriters", StringComparison.OrdinalIgnoreCase)) { @@ -425,7 +424,6 @@ namespace MediaBrowser.MediaEncoding.Probing Type = PersonType.Writer }); } - } else if (string.Equals(key, "producers", StringComparison.OrdinalIgnoreCase)) { @@ -1028,7 +1026,6 @@ namespace MediaBrowser.MediaEncoding.Probing audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true) .DistinctNames() .ToArray(); - } if (audio.AlbumArtists.Length == 0) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index ebacc7d9f..bae2f5417 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -261,7 +261,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles text += ""; } } - } text = text.Replace(@"{\i1}", ""); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f08af6045..7e9894f0a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -640,7 +640,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles } catch (FileNotFoundException) { - } catch (IOException ex) { diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 10e9179c0..c03a8060f 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -158,7 +158,6 @@ namespace MediaBrowser.Model.Dlna return new MediaFormatProfile[] { ValueOf(string.Format("VC1_TS_HD_DTS{0}", suffix)) }; } - } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Dlna/ProfileCondition.cs b/MediaBrowser.Model/Dlna/ProfileCondition.cs index f8b5dee81..4b39d6875 100644 --- a/MediaBrowser.Model/Dlna/ProfileCondition.cs +++ b/MediaBrowser.Model/Dlna/ProfileCondition.cs @@ -15,7 +15,6 @@ namespace MediaBrowser.Model.Dlna public ProfileCondition(ProfileConditionType condition, ProfileConditionValue property, string value) : this(condition, property, value, false) { - } public ProfileCondition(ProfileConditionType condition, ProfileConditionValue property, string value, bool isRequired) diff --git a/MediaBrowser.Model/Dlna/SortCriteria.cs b/MediaBrowser.Model/Dlna/SortCriteria.cs index 3f8985fdc..1f7fa76ad 100644 --- a/MediaBrowser.Model/Dlna/SortCriteria.cs +++ b/MediaBrowser.Model/Dlna/SortCriteria.cs @@ -10,7 +10,6 @@ namespace MediaBrowser.Model.Dlna public SortCriteria(string value) { - } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 8ebd30b72..3fe5cf774 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -109,7 +109,6 @@ namespace MediaBrowser.Model.Dlna } return 1; - }).ThenBy(i => { switch (i.PlayMethod) @@ -121,7 +120,6 @@ namespace MediaBrowser.Model.Dlna default: return 1; } - }).ThenBy(i => { switch (i.MediaSource.Protocol) @@ -131,7 +129,6 @@ namespace MediaBrowser.Model.Dlna default: return 1; } - }).ThenBy(i => { if (maxBitrate > 0) @@ -143,7 +140,6 @@ namespace MediaBrowser.Model.Dlna } return 0; - }).ThenBy(streams.IndexOf); } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 12eaa184c..3db72f78a 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -208,7 +208,6 @@ namespace MediaBrowser.Model.Entities if (Type == MediaStreamType.Video) { - } return null; diff --git a/MediaBrowser.Model/Entities/PackageReviewInfo.cs b/MediaBrowser.Model/Entities/PackageReviewInfo.cs index 1ebbc3323..5b22b34ac 100644 --- a/MediaBrowser.Model/Entities/PackageReviewInfo.cs +++ b/MediaBrowser.Model/Entities/PackageReviewInfo.cs @@ -36,6 +36,5 @@ namespace MediaBrowser.Model.Entities /// Gets or sets the time of review. /// public DateTime timestamp { get; set; } - } } diff --git a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs index 19039d448..0b9b4141a 100644 --- a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs @@ -41,6 +41,5 @@ namespace MediaBrowser.Model.LiveTv /// /// The program information. public BaseItemDto ProgramInfo { get; set; } - } } diff --git a/MediaBrowser.Model/Net/HttpException.cs b/MediaBrowser.Model/Net/HttpException.cs index 4b15e30f0..48ff5d51c 100644 --- a/MediaBrowser.Model/Net/HttpException.cs +++ b/MediaBrowser.Model/Net/HttpException.cs @@ -28,7 +28,6 @@ namespace MediaBrowser.Model.Net public HttpException(string message, Exception innerException) : base(message, innerException) { - } /// diff --git a/MediaBrowser.Model/Providers/RemoteSearchResult.cs b/MediaBrowser.Model/Providers/RemoteSearchResult.cs index c96eb0b59..989741c01 100644 --- a/MediaBrowser.Model/Providers/RemoteSearchResult.cs +++ b/MediaBrowser.Model/Providers/RemoteSearchResult.cs @@ -51,6 +51,5 @@ namespace MediaBrowser.Model.Providers public RemoteSearchResult[] Artists { get; set; } - } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index ee9a32966..7901503d3 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -335,7 +335,6 @@ namespace MediaBrowser.Providers.Manager } catch (FileNotFoundException) { - } } @@ -529,7 +528,6 @@ namespace MediaBrowser.Providers.Manager { Path = path, Type = imageType - }, newIndex); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 31c239e24..5853c7714 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -905,7 +905,6 @@ namespace MediaBrowser.Providers.Manager i.UrlFormatString, value) }; - }).Where(i => i != null).Concat(item.GetRelatedUrls()); } diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 7f2a1410b..60410032e 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -111,7 +111,6 @@ namespace MediaBrowser.Providers.Manager if (replaceData || targetResult.People == null || targetResult.People.Count == 0) { targetResult.People = sourceResult.People; - } else if (targetResult.People != null && sourceResult.People != null) { diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 7023ef706..ba87e0570 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -79,7 +79,6 @@ namespace MediaBrowser.Providers.MediaInfo } catch { - } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 1e7ae5e74..73c89e815 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -63,7 +63,6 @@ namespace MediaBrowser.Providers.MediaInfo Path = path, Protocol = protocol } - }, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index c0eee54fe..1477488d7 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -60,7 +60,6 @@ namespace MediaBrowser.Providers.MediaInfo } catch (IOException) { - } return streams; diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs index c9edcc8e9..30de1391d 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs @@ -247,7 +247,6 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb ProductionYear = firstAired.Year, SearchProviderName = Name, ImageUrl = TvdbUtils.BannerUrl + seriesSearchResult.Banner - }; try diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs index 2f75f7cba..2c6e08921 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -304,6 +304,5 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies }).ToArray(); } } - } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 64d3ecd7b..faeb48b12 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -149,7 +149,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies Url = string.Format(TmdbConfigUrl, TmdbUtils.ApiKey), CancellationToken = cancellationToken, AcceptHeader = TmdbUtils.AcceptHeader - }).ConfigureAwait(false)) { using (Stream json = response.Content) @@ -344,7 +343,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies AcceptHeader = TmdbUtils.AcceptHeader, CacheMode = cacheMode, CacheLength = cacheLength - }).ConfigureAwait(false)) { using (var json = response.Content) @@ -389,7 +387,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies AcceptHeader = TmdbUtils.AcceptHeader, CacheMode = cacheMode, CacheLength = cacheLength - }).ConfigureAwait(false)) { using (var json = response.Content) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs index 3e52c72e0..c5dc060c0 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs @@ -203,7 +203,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return remoteResult; - }) .ToList(); } @@ -224,7 +223,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies Url = url3, CancellationToken = cancellationToken, AcceptHeader = TmdbUtils.AcceptHeader - }).ConfigureAwait(false)) { using (var json = response.Content) @@ -256,7 +254,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return remoteResult; - }) .ToList(); } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index 6b63ff664..654e42a90 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -232,7 +232,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People Url = url, CancellationToken = cancellationToken, AcceptHeader = TmdbUtils.AcceptHeader - }).ConfigureAwait(false)) { using (var json = response.Content) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs index f82f5f2ab..ab1f9dab5 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -127,7 +127,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV Url = url, CancellationToken = cancellationToken, AcceptHeader = TmdbUtils.AcceptHeader - }).ConfigureAwait(false)) { using (var json = response.Content) diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index cbef27a09..e92e5ceab 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -201,6 +201,5 @@ namespace MediaBrowser.Providers.Studios } } } - } } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index c6ffc460c..8086533eb 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -311,7 +311,6 @@ namespace MediaBrowser.Providers.Subtitles Index = index, ItemId = item.Id, Type = MediaStreamType.Subtitle - }).First(); var path = stream.Path; @@ -365,9 +364,7 @@ namespace MediaBrowser.Providers.Subtitles { Name = i.Name, Id = GetProviderId(i.Name) - }).ToArray(); } - } } diff --git a/MediaBrowser.Providers/TV/TvExternalIds.cs b/MediaBrowser.Providers/TV/TvExternalIds.cs index bd59606e7..ec7873eaa 100644 --- a/MediaBrowser.Providers/TV/TvExternalIds.cs +++ b/MediaBrowser.Providers/TV/TvExternalIds.cs @@ -33,7 +33,6 @@ namespace MediaBrowser.Providers.TV /// public bool Supports(IHasProviderIds item) => item is Series; - } public class TvdbSeasonExternalId : IExternalId diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web new file mode 120000 index 000000000..a1757cfbb --- /dev/null +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -0,0 +1 @@ +/home/telans/src/jellyfin-web/dist/ \ No newline at end of file diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs index 21ac7c631..439cee467 100644 --- a/RSSDP/DeviceAvailableEventArgs.cs +++ b/RSSDP/DeviceAvailableEventArgs.cs @@ -54,6 +54,5 @@ namespace Rssdp } #endregion - } } diff --git a/RSSDP/DeviceEventArgs.cs b/RSSDP/DeviceEventArgs.cs index 05eb4a256..faeff8347 100644 --- a/RSSDP/DeviceEventArgs.cs +++ b/RSSDP/DeviceEventArgs.cs @@ -41,6 +41,5 @@ namespace Rssdp } #endregion - } } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index 279ef883c..3fc328b8c 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -85,6 +85,5 @@ namespace Rssdp.Infrastructure } #endregion - } } diff --git a/RSSDP/ISsdpCommunicationsServer.cs b/RSSDP/ISsdpCommunicationsServer.cs index 8cf65df11..02c3af0e5 100644 --- a/RSSDP/ISsdpCommunicationsServer.cs +++ b/RSSDP/ISsdpCommunicationsServer.cs @@ -61,6 +61,5 @@ namespace Rssdp.Infrastructure bool IsShared { get; set; } #endregion - } } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 328e6137a..863f2b15c 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -195,11 +195,9 @@ namespace Rssdp.Infrastructure } catch (ObjectDisposedException) { - } catch (OperationCanceledException) { - } catch (Exception ex) { diff --git a/RSSDP/SsdpConstants.cs b/RSSDP/SsdpConstants.cs index 28a014fce..798f050e1 100644 --- a/RSSDP/SsdpConstants.cs +++ b/RSSDP/SsdpConstants.cs @@ -57,6 +57,5 @@ namespace Rssdp.Infrastructure internal const string SsdpByeByeNotification = "ssdp:byebye"; internal const int UdpResendCount = 3; - } } diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 09f729e83..691ba2a14 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -349,6 +349,5 @@ namespace Rssdp } #endregion - } } diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index 4651d3bb6..a626e13b9 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -120,7 +120,6 @@ namespace Rssdp.Infrastructure } catch (Exception) { - } } @@ -613,6 +612,5 @@ namespace Rssdp.Infrastructure } #endregion - } } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 6a8cda835..5dfb6a8c2 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -335,7 +335,6 @@ namespace Rssdp.Infrastructure } catch (Exception) { - } // WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device); -- cgit v1.2.3 From 11f3a0dc58386c815b34e0579cb37c3557e366f4 Mon Sep 17 00:00:00 2001 From: Max Git Date: Mon, 15 Jun 2020 15:10:59 +0200 Subject: Use Version instead of double. Use correct version number for libavdevice. --- .../Encoder/EncoderValidator.cs | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 801479eed..28471b956 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -63,16 +63,16 @@ namespace MediaBrowser.MediaEncoding.Encoder }; // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below - private static readonly IReadOnlyDictionary _ffmpegMinimumLibraryVersions = new Dictionary + private static readonly IReadOnlyDictionary _ffmpegMinimumLibraryVersions = new Dictionary { - { "libavutil", 56.14 }, - { "libavcodec", 58.18 }, - { "libavformat", 58.12 }, - { "libavdevice", 58.3 }, - { "libavfilter", 7.16 }, - { "libswscale", 5.1 }, - { "libswresample", 3.1 }, - { "libpostproc", 55.1 } + { "libavutil", new Version(56, 14) }, + { "libavcodec", new Version(58, 18) }, + { "libavformat", new Version(58, 12) }, + { "libavdevice", new Version(58, 3) }, + { "libavfilter", new Version(7, 16) }, + { "libswscale", new Version(5, 1) }, + { "libswresample", new Version(3, 1) }, + { "libpostproc", new Version(55, 1) } }; // This lookup table is to be maintained with the following command line: @@ -195,7 +195,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - if (!TryGetFFmpegLibraryVersions(output, out string versionString, out IReadOnlyDictionary versionMap)) + if (!TryGetFFmpegLibraryVersions(output, out string versionString, out IReadOnlyDictionary versionMap)) { _logger.LogError("No ffmpeg library versions found"); @@ -213,7 +213,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - private Version TestMinimumFFmpegLibraryVersions(IReadOnlyDictionary versionMap) + private Version TestMinimumFFmpegLibraryVersions(IReadOnlyDictionary versionMap) { var allVersionsValidated = true; @@ -248,11 +248,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// /// - private static bool TryGetFFmpegLibraryVersions(string output, out string versionString, out IReadOnlyDictionary versionMap) + private static bool TryGetFFmpegLibraryVersions(string output, out string versionString, out IReadOnlyDictionary versionMap) { var sb = new StringBuilder(144); - var map = new Dictionary(); + var map = new Dictionary(); foreach (Match match in Regex.Matches( output, @@ -267,13 +267,14 @@ namespace MediaBrowser.MediaEncoding.Encoder .Append(','); var str = $"{match.Groups["major"]}.{match.Groups["minor"]}"; - var versionNumber = double.Parse(str, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture); - map.Add(match.Groups["name"].Value, versionNumber); + var version = Version.Parse(str); + + map.Add(match.Groups["name"].Value, version); } versionString = sb.ToString(); - versionMap = map as IReadOnlyDictionary; + versionMap = map as IReadOnlyDictionary; return sb.Length > 0; } -- cgit v1.2.3 From ef3200e178e41cede865e0876a6d56171b1f4cce Mon Sep 17 00:00:00 2001 From: Max Git Date: Mon, 15 Jun 2020 19:50:09 +0200 Subject: Remove redundant cast --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 28471b956..a055e57ec 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -274,7 +274,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } versionString = sb.ToString(); - versionMap = map as IReadOnlyDictionary; + versionMap = map; return sb.Length > 0; } -- cgit v1.2.3 From 9018f8d8be10bc4812f7d1bd230a1516eca61eea Mon Sep 17 00:00:00 2001 From: telans Date: Tue, 16 Jun 2020 10:37:52 +1200 Subject: Add full stop at end of comments (SA1629) --- Emby.Dlna/Didl/DidlBuilder.cs | 2 +- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/PlayTo/Device.cs | 2 +- Emby.Naming/Common/MediaType.cs | 6 +- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Data/BaseSqliteRepository.cs | 4 +- .../Data/SqliteDisplayPreferencesRepository.cs | 6 +- .../Data/SqliteItemRepository.cs | 10 +-- .../Data/SqliteUserDataRepository.cs | 6 +- Emby.Server.Implementations/Dto/DtoService.cs | 8 +-- .../HttpClientManager/HttpClientManager.cs | 2 +- .../HttpServer/FileWriter.cs | 4 +- .../HttpServer/HttpListenerHost.cs | 2 +- .../HttpServer/HttpResultFactory.cs | 2 +- .../HttpServer/RangeRequestWriter.cs | 8 +-- .../Library/CoreResolutionIgnoreRule.cs | 2 +- .../Library/IgnorePatterns.cs | 6 +- .../Library/LibraryManager.cs | 14 ++-- .../Library/ResolverHelper.cs | 2 +- .../Library/Resolvers/ItemResolver.cs | 2 +- .../Library/UserDataManager.cs | 4 +- .../LiveTv/RefreshChannelsScheduledTask.cs | 2 +- .../Networking/NetworkManager.cs | 2 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 18 +++--- .../ScheduledTasks/TaskManager.cs | 8 +-- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 8 +-- .../Tasks/DeleteTranscodeFileTask.cs | 2 +- .../ScheduledTasks/Triggers/DailyTrigger.cs | 4 +- .../ScheduledTasks/Triggers/IntervalTrigger.cs | 6 +- .../ScheduledTasks/Triggers/StartupTrigger.cs | 4 +- .../ScheduledTasks/Triggers/WeeklyTrigger.cs | 8 +-- .../Services/ServiceHandler.cs | 2 +- .../Services/UrlExtensions.cs | 2 +- .../Session/SessionManager.cs | 2 +- .../Session/SessionWebSocketListener.cs | 6 +- .../Sorting/AlbumArtistComparer.cs | 2 +- .../Sorting/AlbumComparer.cs | 2 +- .../Sorting/CriticRatingComparer.cs | 2 +- .../Sorting/DateCreatedComparer.cs | 2 +- .../Sorting/DatePlayedComparer.cs | 2 +- .../Sorting/NameComparer.cs | 2 +- .../Sorting/PlayCountComparer.cs | 2 +- .../Sorting/PremiereDateComparer.cs | 2 +- .../Sorting/ProductionYearComparer.cs | 2 +- .../Sorting/RandomComparer.cs | 2 +- .../Sorting/RuntimeComparer.cs | 2 +- .../Sorting/SortNameComparer.cs | 2 +- Emby.Server.Implementations/Udp/UdpServer.cs | 2 +- Jellyfin.Data/Entities/Artwork.cs | 14 ++-- Jellyfin.Data/Entities/Book.cs | 2 +- Jellyfin.Data/Entities/BookMetadata.cs | 4 +- Jellyfin.Data/Entities/Chapter.cs | 20 +++--- Jellyfin.Data/Entities/Collection.cs | 10 +-- Jellyfin.Data/Entities/CollectionItem.cs | 10 +-- Jellyfin.Data/Entities/Company.cs | 8 +-- Jellyfin.Data/Entities/CompanyMetadata.cs | 10 +-- Jellyfin.Data/Entities/CustomItem.cs | 2 +- Jellyfin.Data/Entities/CustomItemMetadata.cs | 2 +- Jellyfin.Data/Entities/Episode.cs | 4 +- Jellyfin.Data/Entities/EpisodeMetadata.cs | 8 +-- Jellyfin.Data/Entities/Genre.cs | 10 +-- Jellyfin.Data/Entities/Library.cs | 10 +-- Jellyfin.Data/Entities/LibraryItem.cs | 16 ++--- Jellyfin.Data/Entities/LibraryRoot.cs | 16 ++--- Jellyfin.Data/Entities/MediaFile.cs | 16 ++--- Jellyfin.Data/Entities/MediaFileStream.cs | 12 ++-- Jellyfin.Data/Entities/Metadata.cs | 30 ++++----- Jellyfin.Data/Entities/MetadataProvider.cs | 10 +-- Jellyfin.Data/Entities/MetadataProviderId.cs | 12 ++-- Jellyfin.Data/Entities/Movie.cs | 2 +- Jellyfin.Data/Entities/MovieMetadata.cs | 10 +-- Jellyfin.Data/Entities/MusicAlbum.cs | 2 +- Jellyfin.Data/Entities/MusicAlbumMetadata.cs | 8 +-- Jellyfin.Data/Entities/Person.cs | 24 +++---- Jellyfin.Data/Entities/PersonRole.cs | 16 ++--- Jellyfin.Data/Entities/Photo.cs | 2 +- Jellyfin.Data/Entities/PhotoMetadata.cs | 2 +- Jellyfin.Data/Entities/ProviderMapping.cs | 6 +- Jellyfin.Data/Entities/Rating.cs | 14 ++-- Jellyfin.Data/Entities/RatingSource.cs | 20 +++--- Jellyfin.Data/Entities/Release.cs | 10 +-- Jellyfin.Data/Entities/Season.cs | 4 +- Jellyfin.Data/Entities/SeasonMetadata.cs | 4 +- Jellyfin.Data/Entities/Series.cs | 10 +-- Jellyfin.Data/Entities/SeriesMetadata.cs | 10 +-- Jellyfin.Data/Entities/Track.cs | 4 +- Jellyfin.Data/Entities/TrackMetadata.cs | 2 +- Jellyfin.Data/Enums/PreferenceKind.cs | 2 +- Jellyfin.Server.Implementations/JellyfinDb.cs | 2 +- MediaBrowser.Api/ApiEntryPoint.cs | 4 +- MediaBrowser.Api/BaseApiService.cs | 2 +- MediaBrowser.Api/ChannelService.cs | 6 +- MediaBrowser.Api/ConfigurationService.cs | 8 +-- MediaBrowser.Api/DisplayPreferencesService.cs | 8 +-- MediaBrowser.Api/EnvironmentService.cs | 12 ++-- MediaBrowser.Api/IHasItemFields.cs | 2 +- MediaBrowser.Api/Images/ImageByNameService.cs | 10 +-- MediaBrowser.Api/Images/ImageRequest.cs | 12 ++-- MediaBrowser.Api/Images/ImageService.cs | 20 +++--- MediaBrowser.Api/Images/RemoteImageService.cs | 2 +- MediaBrowser.Api/Library/LibraryService.cs | 14 ++-- .../Library/LibraryStructureService.cs | 8 +-- MediaBrowser.Api/LiveTv/LiveTvService.cs | 14 ++-- MediaBrowser.Api/LocalizationService.cs | 12 ++-- MediaBrowser.Api/Movies/MoviesService.cs | 4 +- MediaBrowser.Api/Movies/TrailersService.cs | 6 +- MediaBrowser.Api/Music/AlbumsService.cs | 6 +- MediaBrowser.Api/PackageService.cs | 10 +-- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 6 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 2 +- .../Playback/Progressive/AudioService.cs | 4 +- .../Progressive/BaseProgressiveStreamingService.cs | 2 +- .../Playback/Progressive/VideoService.cs | 4 +- .../Playback/StaticRemoteStreamWriter.cs | 6 +- MediaBrowser.Api/Playback/StreamRequest.cs | 2 +- MediaBrowser.Api/PlaylistService.cs | 4 +- MediaBrowser.Api/PluginService.cs | 20 +++--- .../ScheduledTasks/ScheduledTaskService.cs | 12 ++-- .../ScheduledTasksWebSocketListener.cs | 2 +- MediaBrowser.Api/SearchService.cs | 10 +-- .../Sessions/SessionInfoWebSocketListener.cs | 4 +- MediaBrowser.Api/Sessions/SessionService.cs | 4 +- MediaBrowser.Api/SimilarItemsHelper.cs | 8 +-- MediaBrowser.Api/System/ActivityLogService.cs | 2 +- .../System/ActivityLogWebSocketListener.cs | 4 +- MediaBrowser.Api/System/SystemService.cs | 8 +-- MediaBrowser.Api/TvShowsService.cs | 22 +++---- MediaBrowser.Api/UserLibrary/ArtistsService.cs | 4 +- .../UserLibrary/BaseItemsByNameService.cs | 6 +- MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 22 +++---- MediaBrowser.Api/UserLibrary/GenresService.cs | 6 +- MediaBrowser.Api/UserLibrary/ItemsService.cs | 10 +-- MediaBrowser.Api/UserLibrary/PersonsService.cs | 6 +- MediaBrowser.Api/UserLibrary/PlaystateService.cs | 10 +-- MediaBrowser.Api/UserLibrary/StudiosService.cs | 6 +- MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 20 +++--- MediaBrowser.Api/UserLibrary/YearsService.cs | 6 +- MediaBrowser.Api/UserService.cs | 24 +++---- .../Channels/InternalChannelFeatures.cs | 2 +- .../Configuration/IServerConfigurationManager.cs | 2 +- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 +- MediaBrowser.Controller/Dto/IDtoService.cs | 2 +- .../Entities/AggregateFolder.cs | 2 +- MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 +- .../Entities/Audio/MusicAlbum.cs | 2 +- .../Entities/Audio/MusicArtist.cs | 6 +- .../Entities/Audio/MusicGenre.cs | 6 +- MediaBrowser.Controller/Entities/BaseItem.cs | 28 ++++---- .../Entities/CollectionFolder.cs | 4 +- MediaBrowser.Controller/Entities/Extensions.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 12 ++-- MediaBrowser.Controller/Entities/Genre.cs | 6 +- .../Entities/ICollectionFolder.cs | 2 +- .../Entities/IHasAspectRatio.cs | 2 +- .../Entities/IHasDisplayOrder.cs | 2 +- .../Entities/IHasScreenshots.cs | 2 +- MediaBrowser.Controller/Entities/LinkedChild.cs | 2 +- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 2 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 2 +- MediaBrowser.Controller/Entities/Person.cs | 4 +- MediaBrowser.Controller/Entities/Studio.cs | 6 +- MediaBrowser.Controller/Entities/TV/Episode.cs | 4 +- MediaBrowser.Controller/Entities/TV/Season.cs | 6 +- MediaBrowser.Controller/Entities/TV/Series.cs | 4 +- MediaBrowser.Controller/Entities/Trailer.cs | 2 +- MediaBrowser.Controller/Entities/UserItemData.cs | 6 +- MediaBrowser.Controller/Entities/Video.cs | 2 +- MediaBrowser.Controller/Entities/Year.cs | 6 +- .../Extensions/StringExtensions.cs | 2 +- MediaBrowser.Controller/IServerApplicationHost.cs | 2 +- MediaBrowser.Controller/IServerApplicationPaths.cs | 16 ++--- MediaBrowser.Controller/Library/IIntroProvider.cs | 2 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 14 ++-- .../Library/ILibraryPostScanTask.cs | 2 +- MediaBrowser.Controller/Library/IMetadataSaver.cs | 2 +- MediaBrowser.Controller/Library/ISearchEngine.cs | 2 +- .../Library/IUserDataManager.cs | 6 +- MediaBrowser.Controller/Library/IUserManager.cs | 2 +- .../Library/ItemChangeEventArgs.cs | 2 +- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 2 +- .../Library/PlaybackProgressEventArgs.cs | 2 +- MediaBrowser.Controller/Library/Profiler.cs | 8 +-- MediaBrowser.Controller/Library/SearchHintInfo.cs | 2 +- MediaBrowser.Controller/Library/TVUtils.cs | 2 +- .../Library/UserDataSaveEventArgs.cs | 2 +- MediaBrowser.Controller/LiveTv/ChannelInfo.cs | 6 +- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 2 +- MediaBrowser.Controller/LiveTv/ProgramInfo.cs | 6 +- MediaBrowser.Controller/LiveTv/RecordingInfo.cs | 4 +- .../MediaEncoding/EncodingHelper.cs | 14 ++-- .../MediaEncoding/EncodingJobInfo.cs | 18 +++--- .../MediaEncoding/IMediaEncoder.cs | 2 +- .../MediaEncoding/MediaEncoderHelpers.cs | 2 +- .../Net/BasePeriodicWebSocketListener.cs | 10 +-- MediaBrowser.Controller/Net/IHttpResultFactory.cs | 2 +- MediaBrowser.Controller/Net/IHttpServer.cs | 6 +- MediaBrowser.Controller/Net/IWebSocketListener.cs | 2 +- .../Net/WebSocketMessageInfo.cs | 2 +- .../Persistence/IItemRepository.cs | 8 +-- MediaBrowser.Controller/Persistence/IRepository.cs | 4 +- .../Persistence/IUserDataRepository.cs | 6 +- .../Plugins/IPluginConfigurationPage.cs | 8 +-- .../Providers/IMetadataProvider.cs | 2 +- .../Providers/MetadataRefreshMode.cs | 8 +-- .../Providers/MetadataResult.cs | 2 +- .../Providers/VideoContentType.cs | 6 +- .../Resolvers/BaseItemResolver.cs | 4 +- MediaBrowser.Controller/Resolvers/IItemResolver.cs | 2 +- .../Resolvers/ResolverPriority.cs | 10 +-- MediaBrowser.Controller/Session/ISessionManager.cs | 8 +-- .../Sorting/IBaseItemComparer.cs | 2 +- .../Sorting/IUserBaseItemComparer.cs | 2 +- .../Sync/IRemoteSyncProvider.cs | 2 +- .../Parsers/BaseItemXmlParser.cs | 10 +-- .../BdInfo/BdInfoExaminer.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 +- .../Probing/FFProbeHelpers.cs | 8 +-- .../Probing/ProbeResultNormalizer.cs | 10 +-- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/Channels/ChannelFeatures.cs | 2 +- MediaBrowser.Model/Channels/ChannelQuery.cs | 4 +- .../Configuration/BaseApplicationConfiguration.cs | 2 +- .../Configuration/MetadataPluginType.cs | 2 +- .../Configuration/ServerConfiguration.cs | 6 +- .../Configuration/UserConfiguration.cs | 2 +- MediaBrowser.Model/Dlna/AudioOptions.cs | 2 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 26 ++++---- MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs | 8 +-- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 +- MediaBrowser.Model/Dto/ImageOptions.cs | 2 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 2 +- MediaBrowser.Model/Entities/DisplayPreferences.cs | 2 +- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- MediaBrowser.Model/Entities/MetadataProvider.cs | 12 ++-- MediaBrowser.Model/Entities/VirtualFolderInfo.cs | 2 +- MediaBrowser.Model/IO/IZipClient.cs | 2 +- MediaBrowser.Model/LiveTv/ChannelType.cs | 2 +- MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs | 8 +-- MediaBrowser.Model/LiveTv/RecordingQuery.cs | 4 +- MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs | 2 +- MediaBrowser.Model/Net/NetworkShare.cs | 10 +-- .../Notifications/NotificationOption.cs | 2 +- MediaBrowser.Model/Querying/ItemFields.cs | 74 +++++++++++----------- MediaBrowser.Model/Querying/ItemSortBy.cs | 2 +- MediaBrowser.Model/Querying/NextUpQuery.cs | 4 +- MediaBrowser.Model/Querying/QueryResult.cs | 2 +- .../Querying/UpcomingEpisodesQuery.cs | 4 +- MediaBrowser.Model/Search/SearchQuery.cs | 4 +- MediaBrowser.Model/Services/ApiMemberAttribute.cs | 2 +- MediaBrowser.Model/Services/IRequest.cs | 8 +-- .../Services/IRequiresRequestStream.cs | 2 +- MediaBrowser.Model/Session/PlayRequest.cs | 4 +- MediaBrowser.Model/Sync/SyncCategory.cs | 6 +- MediaBrowser.Model/System/SystemInfo.cs | 2 +- MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs | 2 +- MediaBrowser.Model/Tasks/ITaskManager.cs | 2 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 6 +- .../Manager/ItemImageProvider.cs | 4 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../MediaInfo/AudioImageProvider.cs | 2 +- .../MediaInfo/FFProbeAudioInfo.cs | 2 +- .../MediaInfo/FFProbeVideoInfo.cs | 2 +- .../Plugins/Tmdb/Models/Search/MovieResult.cs | 2 +- .../Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 4 +- .../TV/MissingEpisodeProvider.cs | 4 +- RSSDP/DiscoveredSsdpDevice.cs | 2 +- 269 files changed, 816 insertions(+), 816 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 6ded76f7d..0f53bf2a4 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -705,7 +705,7 @@ namespace Emby.Dlna.Didl } /// - /// Adds fields used by both items and folders + /// Adds fields used by both items and folders. /// private void AddCommonFields(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter) { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index e5f483950..6b7063c5d 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -473,7 +473,7 @@ namespace Emby.Dlna /// /// Recreates the object using serialization, to ensure it's not a subclass. - /// If it's a subclass it may not serlialize properly to xml (different root element tag name) + /// If it's a subclass it may not serlialize properly to xml (different root element tag name). /// /// /// diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 86b72e264..6442ac5cc 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -232,7 +232,7 @@ namespace Emby.Dlna.PlayTo } /// - /// Sets volume on a scale of 0-100 + /// Sets volume on a scale of 0-100. /// public async Task SetVolume(int value, CancellationToken cancellationToken) { diff --git a/Emby.Naming/Common/MediaType.cs b/Emby.Naming/Common/MediaType.cs index cc18ce4cd..148833765 100644 --- a/Emby.Naming/Common/MediaType.cs +++ b/Emby.Naming/Common/MediaType.cs @@ -5,17 +5,17 @@ namespace Emby.Naming.Common public enum MediaType { /// - /// The audio + /// The audio. /// Audio = 0, /// - /// The photo + /// The photo. /// Photo = 1, /// - /// The video + /// The video. /// Video = 2 } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5772dd479..23f0571a1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -956,7 +956,7 @@ namespace Emby.Server.Implementations } /// - /// Notifies that the kernel that a change has been made that requires a restart + /// Notifies that the kernel that a change has been made that requires a restart. /// public void NotifyPendingRestart() { diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 53c9ccdbf..8a3716380 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -247,12 +247,12 @@ namespace Emby.Server.Implementations.Data public enum SynchronousMode { /// - /// SQLite continues without syncing as soon as it has handed data off to the operating system + /// SQLite continues without syncing as soon as it has handed data off to the operating system. /// Off = 0, /// - /// SQLite database engine will still sync at the most critical moments + /// SQLite database engine will still sync at the most critical moments. /// Normal = 1, diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs index 63d0321b7..5597155a8 100644 --- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs @@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Opens the connection to the database + /// Opens the connection to the database. /// /// Task. private void InitializeInternal() @@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Save the display preferences associated with an item in the repo + /// Save the display preferences associated with an item in the repo. /// /// The display preferences. /// The user id. @@ -122,7 +122,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Save all display preferences associated with a user in the repo + /// Save all display preferences associated with a user in the repo. /// /// The display preferences. /// The user id. diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d33125661..13b581fc0 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Data protected override TempStoreMode TempStore => TempStoreMode.Memory; /// - /// Opens the connection to the database + /// Opens the connection to the database. /// public void Initialize(SqliteUserDataRepository userDataRepo, IUserManager userManager) { @@ -548,7 +548,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Save a standard item in the repo + /// Save a standard item in the repo. /// /// The item. /// The cancellation token. @@ -1204,7 +1204,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Internal retrieve from items or users table + /// Internal retrieve from items or users table. /// /// The id. /// BaseItem. @@ -1918,7 +1918,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Gets chapters for an item + /// Gets chapters for an item. /// /// The item. /// IEnumerable{ChapterInfo}. @@ -1946,7 +1946,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Gets a single chapter for an item + /// Gets a single chapter for an item. /// /// The item. /// The index. diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 7e66fa072..663c226a2 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -235,7 +235,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Persist all user data for the specified user + /// Persist all user data for the specified user. /// private void PersistAllUserData(long internalUserId, UserItemData[] userDataList, CancellationToken cancellationToken) { @@ -309,7 +309,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Return all user-data associated with the given user + /// Return all user-data associated with the given user. /// /// /// @@ -339,7 +339,7 @@ namespace Emby.Server.Implementations.Data } /// - /// Read a row from the specified reader into the provided userData object + /// Read a row from the specified reader into the provided userData object. /// /// private UserItemData ReadRow(IReadOnlyList reader) diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 41ff7e3ab..c3bb7a814 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Dto } /// - /// Converts a BaseItem to a DTOBaseItem + /// Converts a BaseItem to a DTOBaseItem. /// /// The item. /// The fields. @@ -442,7 +442,7 @@ namespace Emby.Server.Implementations.Dto } /// - /// Gets client-side Id of a server-side BaseItem + /// Gets client-side Id of a server-side BaseItem. /// /// The item. /// System.String. @@ -537,7 +537,7 @@ namespace Emby.Server.Implementations.Dto } /// - /// Attaches People DTO's to a DTOBaseItem + /// Attaches People DTO's to a DTOBaseItem. /// /// The dto. /// The item. @@ -725,7 +725,7 @@ namespace Emby.Server.Implementations.Dto } /// - /// Sets simple property values on a DTOBaseItem + /// Sets simple property values on a DTOBaseItem. /// /// The dto. /// The item. diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 87977494a..25adc5812 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.HttpClientManager => SendAsync(options, HttpMethod.Get); /// - /// Performs a GET request and returns the resulting stream + /// Performs a GET request and returns the resulting stream. /// /// The options. /// Task{Stream}. diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs index 0b61e40b0..590eee1b4 100644 --- a/Emby.Server.Implementations/HttpServer/FileWriter.cs +++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs @@ -32,12 +32,12 @@ namespace Emby.Server.Implementations.HttpServer private readonly IFileSystem _fileSystem; /// - /// The _options + /// The _options. /// private readonly IDictionary _options = new Dictionary(); /// - /// The _requested ranges + /// The _requested ranges. /// private List> _requestedRanges; diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 1b6e4b554..ca8cb4087 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -591,7 +591,7 @@ namespace Emby.Server.Implementations.HttpServer } /// - /// Get the default CORS headers + /// Get the default CORS headers. /// /// /// diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index d254d394f..ad31b3e1e 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -692,7 +692,7 @@ namespace Emby.Server.Implementations.HttpServer /// - /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that + /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that. /// /// The date. /// DateTime. diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs index 8b9028f6b..d83869077 100644 --- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -34,17 +34,17 @@ namespace Emby.Server.Implementations.HttpServer private const int BufferSize = 81920; /// - /// The _options + /// The _options. /// private readonly Dictionary _options = new Dictionary(); /// - /// The us culture + /// The us culture. /// private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// - /// Additional HTTP Headers + /// Additional HTTP Headers. /// /// The headers. public IDictionary Headers => _options; @@ -110,7 +110,7 @@ namespace Emby.Server.Implementations.HttpServer } /// - /// The _requested ranges + /// The _requested ranges. /// private List> _requestedRanges; /// diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 218e5a0c6..e140009ea 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library { /// - /// Provides the core resolver ignore rules + /// Provides the core resolver ignore rules. /// public class CoreResolutionIgnoreRule : IResolverIgnoreRule { diff --git a/Emby.Server.Implementations/Library/IgnorePatterns.cs b/Emby.Server.Implementations/Library/IgnorePatterns.cs index d12b5855b..8c4098948 100644 --- a/Emby.Server.Implementations/Library/IgnorePatterns.cs +++ b/Emby.Server.Implementations/Library/IgnorePatterns.cs @@ -4,12 +4,12 @@ using DotNet.Globbing; namespace Emby.Server.Implementations.Library { /// - /// Glob patterns for files to ignore + /// Glob patterns for files to ignore. /// public static class IgnorePatterns { /// - /// Files matching these glob patterns will be ignored + /// Files matching these glob patterns will be ignored. /// public static readonly string[] Patterns = new string[] { @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Library private static readonly Glob[] _globs = Patterns.Select(p => Glob.Parse(p, _globOptions)).ToArray(); /// - /// Returns true if the supplied path should be ignored + /// Returns true if the supplied path should be ignored. /// public static bool ShouldIgnore(string path) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1d4651da2..799ce28a0 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -97,13 +97,13 @@ namespace Emby.Server.Implementations.Library private IIntroProvider[] IntroProviders { get; set; } /// - /// Gets or sets the list of entity resolution ignore rules + /// Gets or sets the list of entity resolution ignore rules. /// /// The entity resolution ignore rules. private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } /// - /// Gets or sets the list of currently registered entity resolvers + /// Gets or sets the list of currently registered entity resolvers. /// /// The entity resolvers enumerable. private IItemResolver[] EntityResolvers { get; set; } @@ -209,12 +209,12 @@ namespace Emby.Server.Implementations.Library } /// - /// The _root folder + /// The _root folder. /// private volatile AggregateFolder _rootFolder; /// - /// The _root folder sync lock + /// The _root folder sync lock. /// private readonly object _rootFolderSyncLock = new object(); @@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Determines whether a path should be ignored based on its contents - called after the contents have been read + /// Determines whether a path should be ignored based on its contents - called after the contents have been read. /// /// The args. /// true if XXXX, false otherwise @@ -909,7 +909,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Gets a Genre + /// Gets a Genre. /// /// The name. /// Task{Genre}. @@ -990,7 +990,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Reloads the root media folder + /// Reloads the root media folder. /// /// The progress. /// The cancellation token. diff --git a/Emby.Server.Implementations/Library/ResolverHelper.cs b/Emby.Server.Implementations/Library/ResolverHelper.cs index 7ca15b4e5..4e4cac75b 100644 --- a/Emby.Server.Implementations/Library/ResolverHelper.cs +++ b/Emby.Server.Implementations/Library/ResolverHelper.cs @@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Ensures DateCreated and DateModified have values + /// Ensures DateCreated and DateModified have values. /// /// The file system. /// The item. diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs index 32ccc7fdd..9ca76095b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Library.Resolvers public virtual ResolverPriority Priority => ResolverPriority.First; /// - /// Sets initial values on the newly resolved item + /// Sets initial values on the newly resolved item. /// /// The item. /// The args. diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 9e17fa672..175b3af57 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -103,7 +103,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Retrieve all user data for the given user + /// Retrieve all user data for the given user. /// /// /// @@ -188,7 +188,7 @@ namespace Emby.Server.Implementations.Library } /// - /// Converts a UserItemData to a DTOUserItemData + /// Converts a UserItemData to a DTOUserItemData. /// /// The data. /// DtoUserItemData. diff --git a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index 8e7d60a15..f1b61f7c7 100644 --- a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.LiveTv } /// - /// Creates the triggers that define when the task will run + /// Creates the triggers that define when the task will run. /// /// IEnumerable{BaseTaskTrigger}. public IEnumerable GetDefaultTriggers() diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 2909cdd0d..d12b5a937 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -411,7 +411,7 @@ namespace Emby.Server.Implementations.Networking } /// - /// Gets a random port number that is currently available + /// Gets a random port number that is currently available. /// /// System.Int32. public int GetRandomUnusedTcpPort() diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index e58c335a8..1995d1309 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -18,7 +18,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks { /// - /// Class ScheduledTaskWorker + /// Class ScheduledTaskWorker. /// public class ScheduledTaskWorker : IScheduledTaskWorker { @@ -111,11 +111,11 @@ namespace Emby.Server.Implementations.ScheduledTasks private bool _readFromFile = false; /// - /// The _last execution result + /// The _last execution result. /// private TaskResult _lastExecutionResult; /// - /// The _last execution result sync lock + /// The _last execution result sync lock. /// private readonly object _lastExecutionResultSyncLock = new object(); /// @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public string Category => ScheduledTask.Category; /// - /// Gets the current cancellation token + /// Gets the current cancellation token. /// /// The current cancellation token source. private CancellationTokenSource CurrentCancellationTokenSource { get; set; } @@ -278,7 +278,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// The _id + /// The _id. /// private string _id; @@ -358,7 +358,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private Task _currentTask; /// - /// Executes the task + /// Executes the task. /// /// Task options. /// Task. @@ -453,7 +453,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stops the task if it is currently executing + /// Stops the task if it is currently executing. /// /// Cannot cancel a Task unless it is in the Running state. public void Cancel() @@ -683,7 +683,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Converts a TaskTriggerInfo into a concrete BaseTaskTrigger + /// Converts a TaskTriggerInfo into a concrete BaseTaskTrigger. /// /// The info. /// BaseTaskTrigger. @@ -753,7 +753,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Disposes each trigger + /// Disposes each trigger. /// private void DisposeTriggers() { diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 94220ac5d..0ad4253e4 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks { /// - /// Class TaskManager + /// Class TaskManager. /// public class TaskManager : ITaskManager { @@ -23,13 +23,13 @@ namespace Emby.Server.Implementations.ScheduledTasks public event EventHandler TaskCompleted; /// - /// Gets the list of Scheduled Tasks + /// Gets the list of Scheduled Tasks. /// /// The scheduled tasks. public IScheduledTaskWorker[] ScheduledTasks { get; private set; } /// - /// The _task queue + /// The _task queue. /// private readonly ConcurrentQueue> _taskQueue = new ConcurrentQueue>(); @@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Cancels if running + /// Cancels if running. /// /// public void CancelIfRunning() diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 966b549b2..e29fcfb5f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.Globalization; namespace Emby.Server.Implementations.ScheduledTasks.Tasks { /// - /// Deletes old cache files + /// Deletes old cache files. /// public class DeleteCacheFileTask : IScheduledTask, IConfigurableScheduledTask { @@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } /// - /// Creates the triggers that define when the task will run + /// Creates the triggers that define when the task will run. /// /// IEnumerable{BaseTaskTrigger}. public IEnumerable GetDefaultTriggers() @@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } /// - /// Returns the task to be executed + /// Returns the task to be executed. /// /// The cancellation token. /// The progress. @@ -93,7 +93,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// - /// Deletes the cache files from directory with a last write time less than a given date + /// Deletes the cache files from directory with a last write time less than a given date. /// /// The task cancellation token. /// The directory. diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index 53cf9a0a5..691408167 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.Globalization; namespace Emby.Server.Implementations.ScheduledTasks.Tasks { /// - /// Deletes all transcoding temp files + /// Deletes all transcoding temp files. /// public class DeleteTranscodeFileTask : IScheduledTask, IConfigurableScheduledTask { diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index c7819d4c0..eb628ec5f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private Timer Timer { get; set; } /// - /// Stars waiting for the trigger action + /// Stars waiting for the trigger action. /// /// The last result. /// The logger. @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stops waiting for the trigger action + /// Stops waiting for the trigger action. /// public void Stop() { diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs index 74cd4ef1e..247a6785a 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks { /// - /// Represents a task trigger that runs repeatedly on an interval + /// Represents a task trigger that runs repeatedly on an interval. /// public class IntervalTrigger : ITaskTrigger { @@ -31,7 +31,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private DateTime _lastStartDate; /// - /// Stars waiting for the trigger action + /// Stars waiting for the trigger action. /// /// The last result. /// The logger. @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stops waiting for the trigger action + /// Stops waiting for the trigger action. /// public void Stop() { diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs index e171a9e9f..96e5d8897 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stars waiting for the trigger action + /// Stars waiting for the trigger action. /// /// The last result. /// The logger. @@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stops waiting for the trigger action + /// Stops waiting for the trigger action. /// public void Stop() { diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs index ad0b57af6..4f1bf5c19 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs @@ -6,12 +6,12 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.ScheduledTasks { /// - /// Represents a task trigger that fires on a weekly basis + /// Represents a task trigger that fires on a weekly basis. /// public class WeeklyTrigger : ITaskTrigger { /// - /// Get the time of day to trigger the task to run + /// Get the time of day to trigger the task to run. /// /// The time of day. public TimeSpan TimeOfDay { get; set; } @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.ScheduledTasks private Timer Timer { get; set; } /// - /// Stars waiting for the trigger action + /// Stars waiting for the trigger action. /// /// The last result. /// The logger. @@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } /// - /// Stops waiting for the trigger action + /// Stops waiting for the trigger action. /// public void Stop() { diff --git a/Emby.Server.Implementations/Services/ServiceHandler.cs b/Emby.Server.Implementations/Services/ServiceHandler.cs index 7f44357e1..a42f88ea0 100644 --- a/Emby.Server.Implementations/Services/ServiceHandler.cs +++ b/Emby.Server.Implementations/Services/ServiceHandler.cs @@ -180,7 +180,7 @@ namespace Emby.Server.Implementations.Services => string.Equals(method, expected, StringComparison.OrdinalIgnoreCase); /// - /// Duplicate params have their values joined together in a comma-delimited string + /// Duplicate params have their values joined together in a comma-delimited string. /// private static Dictionary GetFlattenedRequestParams(HttpRequest request) { diff --git a/Emby.Server.Implementations/Services/UrlExtensions.cs b/Emby.Server.Implementations/Services/UrlExtensions.cs index e3b6aa197..92e36b60e 100644 --- a/Emby.Server.Implementations/Services/UrlExtensions.cs +++ b/Emby.Server.Implementations/Services/UrlExtensions.cs @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations.Services /// Donated by Ivan Korneliuk from his post: /// http://korneliuk.blogspot.com/2012/08/servicestack-reusing-dtos.html /// - /// Modified to only allow using routes matching the supplied HTTP Verb + /// Modified to only allow using routes matching the supplied HTTP Verb. /// public static class UrlExtensions { diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 07e443ef5..75fdedd10 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -843,7 +843,7 @@ namespace Emby.Server.Implementations.Session } /// - /// Used to report that playback has ended for an item + /// Used to report that playback has ended for an item. /// /// The info. /// Task. diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index ef32c692c..a891e03f9 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Session { /// - /// Class SessionWebSocketListener + /// Class SessionWebSocketListener. /// public sealed class SessionWebSocketListener : IWebSocketListener, IDisposable { @@ -34,12 +34,12 @@ namespace Emby.Server.Implementations.Session public const float ForceKeepAliveFactor = 0.75f; /// - /// The _session manager + /// The _session manager. /// private readonly ISessionManager _sessionManager; /// - /// The _logger + /// The _logger. /// private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; diff --git a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs index 0804b01fc..7657cc74e 100644 --- a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class AlbumArtistComparer + /// Class AlbumArtistComparer. /// public class AlbumArtistComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/AlbumComparer.cs b/Emby.Server.Implementations/Sorting/AlbumComparer.cs index 3831a0d2d..7dfdd9ecf 100644 --- a/Emby.Server.Implementations/Sorting/AlbumComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumComparer.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class AlbumComparer + /// Class AlbumComparer. /// public class AlbumComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs index adb78dec5..fa136c36d 100644 --- a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class CriticRatingComparer + /// Class CriticRatingComparer. /// public class CriticRatingComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index 8501bd9ee..ea981e840 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class DateCreatedComparer + /// Class DateCreatedComparer. /// public class DateCreatedComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs index 5e527ea25..16bd2aff8 100644 --- a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class DatePlayedComparer + /// Class DatePlayedComparer. /// public class DatePlayedComparer : IUserBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index 4eb1549f5..da020d8d8 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class NameComparer + /// Class NameComparer. /// public class NameComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs index afbaaf6ab..5c2830322 100644 --- a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class PlayCountComparer + /// Class PlayCountComparer. /// public class PlayCountComparer : IUserBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs index 0c944a7a0..a24dc4030 100644 --- a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class PremiereDateComparer + /// Class PremiereDateComparer. /// public class PremiereDateComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs index 472a07eb3..e2857df0b 100644 --- a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs +++ b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class ProductionYearComparer + /// Class ProductionYearComparer. /// public class ProductionYearComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/RandomComparer.cs b/Emby.Server.Implementations/Sorting/RandomComparer.cs index bde8b4534..7739d0418 100644 --- a/Emby.Server.Implementations/Sorting/RandomComparer.cs +++ b/Emby.Server.Implementations/Sorting/RandomComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class RandomComparer + /// Class RandomComparer. /// public class RandomComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index 1d2bdde26..f165123ea 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class RuntimeComparer + /// Class RuntimeComparer. /// public class RuntimeComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index cc0571c78..93389fc3e 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { /// - /// Class SortNameComparer + /// Class SortNameComparer. /// public class SortNameComparer : IBaseItemComparer { diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index a26f714b1..bf8a436b4 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.Udp public sealed class UdpServer : IDisposable { /// - /// The _logger + /// The _logger. /// private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; diff --git a/Jellyfin.Data/Entities/Artwork.cs b/Jellyfin.Data/Entities/Artwork.cs index 214fb4cb1..891904cc3 100644 --- a/Jellyfin.Data/Entities/Artwork.cs +++ b/Jellyfin.Data/Entities/Artwork.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -77,7 +77,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -101,7 +101,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Path + /// Backing field for Path. /// protected string _Path; /// @@ -139,7 +139,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Kind + /// Backing field for Kind. /// internal Enums.ArtKind _Kind; /// @@ -152,7 +152,7 @@ namespace Jellyfin.Data.Entities partial void GetKind(ref Enums.ArtKind result); /// - /// Indexed, Required + /// Indexed, Required. /// [Required] public Enums.ArtKind Kind @@ -175,7 +175,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Book.cs b/Jellyfin.Data/Entities/Book.cs index faefc7400..c4d12496e 100644 --- a/Jellyfin.Data/Entities/Book.cs +++ b/Jellyfin.Data/Entities/Book.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public Book(Guid urlid, DateTime dateadded) diff --git a/Jellyfin.Data/Entities/BookMetadata.cs b/Jellyfin.Data/Entities/BookMetadata.cs index dd389b64a..474f906a1 100644 --- a/Jellyfin.Data/Entities/BookMetadata.cs +++ b/Jellyfin.Data/Entities/BookMetadata.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for ISBN + /// Backing field for ISBN. /// protected long? _ISBN; /// diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs index 9b3a5e827..5a5cdaa8f 100644 --- a/Jellyfin.Data/Entities/Chapter.cs +++ b/Jellyfin.Data/Entities/Chapter.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// ISO-639-3 3-character language codes /// @@ -60,7 +60,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -73,7 +73,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -98,7 +98,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -135,7 +135,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Language + /// Backing field for Language. /// protected string _Language; /// @@ -149,7 +149,7 @@ namespace Jellyfin.Data.Entities /// /// Required, Min length = 3, Max length = 3 - /// ISO-639-3 3-character language codes + /// ISO-639-3 3-character language codes. /// [Required] [MinLength(3)] @@ -175,7 +175,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for TimeStart + /// Backing field for TimeStart. /// protected long _TimeStart; /// @@ -188,7 +188,7 @@ namespace Jellyfin.Data.Entities partial void GetTimeStart(ref long result); /// - /// Required + /// Required. /// [Required] public long TimeStart @@ -211,7 +211,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for TimeEnd + /// Backing field for TimeEnd. /// protected long? _TimeEnd; /// @@ -243,7 +243,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Collection.cs b/Jellyfin.Data/Entities/Collection.cs index c040cfe33..87c9487c0 100644 --- a/Jellyfin.Data/Entities/Collection.cs +++ b/Jellyfin.Data/Entities/Collection.cs @@ -9,7 +9,7 @@ namespace Jellyfin.Data.Entities partial void Init(); /// - /// Default constructor + /// Default constructor. /// public Collection() { @@ -23,7 +23,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -36,7 +36,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -61,7 +61,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -98,7 +98,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/CollectionItem.cs b/Jellyfin.Data/Entities/CollectionItem.cs index c5e54c3a2..fc3705fe0 100644 --- a/Jellyfin.Data/Entities/CollectionItem.cs +++ b/Jellyfin.Data/Entities/CollectionItem.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -67,7 +67,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -80,7 +80,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -105,7 +105,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] @@ -121,7 +121,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Required + /// Required. /// [ForeignKey("LibraryItem_Id")] public virtual LibraryItem LibraryItem { get; set; } diff --git a/Jellyfin.Data/Entities/Company.cs b/Jellyfin.Data/Entities/Company.cs index 7d6f3b207..2af05b8a1 100644 --- a/Jellyfin.Data/Entities/Company.cs +++ b/Jellyfin.Data/Entities/Company.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -75,7 +75,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -88,7 +88,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -113,7 +113,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/CompanyMetadata.cs b/Jellyfin.Data/Entities/CompanyMetadata.cs index 1ad03b4f9..64d59fbd2 100644 --- a/Jellyfin.Data/Entities/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/CompanyMetadata.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -60,7 +60,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Description + /// Backing field for Description. /// protected string _Description; /// @@ -97,7 +97,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Headquarters + /// Backing field for Headquarters. /// protected string _Headquarters; /// @@ -134,7 +134,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Country + /// Backing field for Country. /// protected string _Country; /// @@ -171,7 +171,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Homepage + /// Backing field for Homepage. /// protected string _Homepage; /// diff --git a/Jellyfin.Data/Entities/CustomItem.cs b/Jellyfin.Data/Entities/CustomItem.cs index 5f6fc3a23..446391591 100644 --- a/Jellyfin.Data/Entities/CustomItem.cs +++ b/Jellyfin.Data/Entities/CustomItem.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public CustomItem(Guid urlid, DateTime dateadded) diff --git a/Jellyfin.Data/Entities/CustomItemMetadata.cs b/Jellyfin.Data/Entities/CustomItemMetadata.cs index ee37aaaa9..b81408aa6 100644 --- a/Jellyfin.Data/Entities/CustomItemMetadata.cs +++ b/Jellyfin.Data/Entities/CustomItemMetadata.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes diff --git a/Jellyfin.Data/Entities/Episode.cs b/Jellyfin.Data/Entities/Episode.cs index 88531205f..132af9bdc 100644 --- a/Jellyfin.Data/Entities/Episode.cs +++ b/Jellyfin.Data/Entities/Episode.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. /// @@ -66,7 +66,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for EpisodeNumber + /// Backing field for EpisodeNumber. /// protected int? _EpisodeNumber; /// diff --git a/Jellyfin.Data/Entities/EpisodeMetadata.cs b/Jellyfin.Data/Entities/EpisodeMetadata.cs index 0aa4b4270..a4e50fca2 100644 --- a/Jellyfin.Data/Entities/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/EpisodeMetadata.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -60,7 +60,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Outline + /// Backing field for Outline. /// protected string _Outline; /// @@ -97,7 +97,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Plot + /// Backing field for Plot. /// protected string _Plot; /// @@ -134,7 +134,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Tagline + /// Backing field for Tagline. /// protected string _Tagline; /// diff --git a/Jellyfin.Data/Entities/Genre.cs b/Jellyfin.Data/Entities/Genre.cs index ff0710671..a38c019fb 100644 --- a/Jellyfin.Data/Entities/Genre.cs +++ b/Jellyfin.Data/Entities/Genre.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -56,7 +56,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -69,7 +69,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -94,7 +94,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// internal string _Name; /// @@ -132,7 +132,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Library.cs b/Jellyfin.Data/Entities/Library.cs index a5cc5c8da..c5609d858 100644 --- a/Jellyfin.Data/Entities/Library.cs +++ b/Jellyfin.Data/Entities/Library.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// public Library(string name) @@ -51,7 +51,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -89,7 +89,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -127,7 +127,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/LibraryItem.cs b/Jellyfin.Data/Entities/LibraryItem.cs index c2ba7059d..b7dad8d7c 100644 --- a/Jellyfin.Data/Entities/LibraryItem.cs +++ b/Jellyfin.Data/Entities/LibraryItem.cs @@ -17,7 +17,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. protected LibraryItem(Guid urlid, DateTime dateadded) @@ -33,7 +33,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -46,7 +46,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -71,7 +71,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for UrlId + /// Backing field for UrlId. /// internal Guid _UrlId; /// @@ -108,7 +108,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for DateAdded + /// Backing field for DateAdded. /// protected DateTime _DateAdded; /// @@ -121,7 +121,7 @@ namespace Jellyfin.Data.Entities partial void GetDateAdded(ref DateTime result); /// - /// Required + /// Required. /// [Required] public DateTime DateAdded @@ -144,7 +144,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] @@ -160,7 +160,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Required + /// Required. /// [ForeignKey("LibraryRoot_Id")] public virtual LibraryRoot LibraryRoot { get; set; } diff --git a/Jellyfin.Data/Entities/LibraryRoot.cs b/Jellyfin.Data/Entities/LibraryRoot.cs index 7823db02a..a84c7de4b 100644 --- a/Jellyfin.Data/Entities/LibraryRoot.cs +++ b/Jellyfin.Data/Entities/LibraryRoot.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// Absolute Path public LibraryRoot(string path) @@ -51,7 +51,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -89,7 +89,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Path + /// Backing field for Path. /// protected string _Path; /// @@ -103,7 +103,7 @@ namespace Jellyfin.Data.Entities /// /// Required, Max length = 65535 - /// Absolute Path + /// Absolute Path. /// [Required] [MaxLength(65535)] @@ -128,7 +128,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for NetworkPath + /// Backing field for NetworkPath. /// protected string _NetworkPath; /// @@ -166,7 +166,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] @@ -182,7 +182,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Required + /// Required. /// [ForeignKey("Library_Id")] public virtual Library Library { get; set; } diff --git a/Jellyfin.Data/Entities/MediaFile.cs b/Jellyfin.Data/Entities/MediaFile.cs index 94c39a28a..d8781bcb2 100644 --- a/Jellyfin.Data/Entities/MediaFile.cs +++ b/Jellyfin.Data/Entities/MediaFile.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// Relative to the LibraryRoot /// @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -77,7 +77,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -102,7 +102,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Path + /// Backing field for Path. /// protected string _Path; /// @@ -116,7 +116,7 @@ namespace Jellyfin.Data.Entities /// /// Required, Max length = 65535 - /// Relative to the LibraryRoot + /// Relative to the LibraryRoot. /// [Required] [MaxLength(65535)] @@ -141,7 +141,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Kind + /// Backing field for Kind. /// protected Enums.MediaFileKind _Kind; /// @@ -154,7 +154,7 @@ namespace Jellyfin.Data.Entities partial void GetKind(ref Enums.MediaFileKind result); /// - /// Required + /// Required. /// [Required] public Enums.MediaFileKind Kind @@ -177,7 +177,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/MediaFileStream.cs b/Jellyfin.Data/Entities/MediaFileStream.cs index 723977fdf..a7a33e255 100644 --- a/Jellyfin.Data/Entities/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/MediaFileStream.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -55,7 +55,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -68,7 +68,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -93,7 +93,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for StreamNumber + /// Backing field for StreamNumber. /// protected int _StreamNumber; /// @@ -106,7 +106,7 @@ namespace Jellyfin.Data.Entities partial void GetStreamNumber(ref int result); /// - /// Required + /// Required. /// [Required] public int StreamNumber @@ -129,7 +129,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Metadata.cs b/Jellyfin.Data/Entities/Metadata.cs index 6558642cf..4282bb9f7 100644 --- a/Jellyfin.Data/Entities/Metadata.cs +++ b/Jellyfin.Data/Entities/Metadata.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -50,7 +50,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -63,7 +63,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -88,7 +88,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Title + /// Backing field for Title. /// protected string _Title; /// @@ -102,7 +102,7 @@ namespace Jellyfin.Data.Entities /// /// Required, Max length = 1024 - /// The title or name of the object + /// The title or name of the object. /// [Required] [MaxLength(1024)] @@ -127,7 +127,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for OriginalTitle + /// Backing field for OriginalTitle. /// protected string _OriginalTitle; /// @@ -164,7 +164,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for SortTitle + /// Backing field for SortTitle. /// protected string _SortTitle; /// @@ -201,7 +201,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Language + /// Backing field for Language. /// protected string _Language; /// @@ -215,7 +215,7 @@ namespace Jellyfin.Data.Entities /// /// Required, Min length = 3, Max length = 3 - /// ISO-639-3 3-character language codes + /// ISO-639-3 3-character language codes. /// [Required] [MinLength(3)] @@ -241,7 +241,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for ReleaseDate + /// Backing field for ReleaseDate. /// protected DateTimeOffset? _ReleaseDate; /// @@ -273,7 +273,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for DateAdded + /// Backing field for DateAdded. /// protected DateTime _DateAdded; /// @@ -286,7 +286,7 @@ namespace Jellyfin.Data.Entities partial void GetDateAdded(ref DateTime result); /// - /// Required + /// Required. /// [Required] public DateTime DateAdded @@ -309,7 +309,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for DateModified + /// Backing field for DateModified. /// protected DateTime _DateModified; /// @@ -322,7 +322,7 @@ namespace Jellyfin.Data.Entities partial void GetDateModified(ref DateTime result); /// - /// Required + /// Required. /// [Required] public DateTime DateModified @@ -345,7 +345,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/MetadataProvider.cs b/Jellyfin.Data/Entities/MetadataProvider.cs index bf9689709..9069d6ad6 100644 --- a/Jellyfin.Data/Entities/MetadataProvider.cs +++ b/Jellyfin.Data/Entities/MetadataProvider.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// public MetadataProvider(string name) @@ -51,7 +51,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -64,7 +64,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -89,7 +89,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -127,7 +127,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/MetadataProviderId.cs b/Jellyfin.Data/Entities/MetadataProviderId.cs index c49c6f42e..5facf1188 100644 --- a/Jellyfin.Data/Entities/MetadataProviderId.cs +++ b/Jellyfin.Data/Entities/MetadataProviderId.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -77,7 +77,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -90,7 +90,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -115,7 +115,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for ProviderId + /// Backing field for ProviderId. /// protected string _ProviderId; /// @@ -153,7 +153,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] @@ -169,7 +169,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Required + /// Required. /// [ForeignKey("MetadataProvider_Id")] public virtual MetadataProvider MetadataProvider { get; set; } diff --git a/Jellyfin.Data/Entities/Movie.cs b/Jellyfin.Data/Entities/Movie.cs index ad2504b0d..64326ca3a 100644 --- a/Jellyfin.Data/Entities/Movie.cs +++ b/Jellyfin.Data/Entities/Movie.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public Movie(Guid urlid, DateTime dateadded) diff --git a/Jellyfin.Data/Entities/MovieMetadata.cs b/Jellyfin.Data/Entities/MovieMetadata.cs index 1f8f1c2a0..f01b208bc 100644 --- a/Jellyfin.Data/Entities/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/MovieMetadata.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -65,7 +65,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Outline + /// Backing field for Outline. /// protected string _Outline; /// @@ -102,7 +102,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Plot + /// Backing field for Plot. /// protected string _Plot; /// @@ -139,7 +139,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Tagline + /// Backing field for Tagline. /// protected string _Tagline; /// @@ -176,7 +176,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Country + /// Backing field for Country. /// protected string _Country; /// diff --git a/Jellyfin.Data/Entities/MusicAlbum.cs b/Jellyfin.Data/Entities/MusicAlbum.cs index e07f4357b..9afea1fb6 100644 --- a/Jellyfin.Data/Entities/MusicAlbum.cs +++ b/Jellyfin.Data/Entities/MusicAlbum.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public MusicAlbum(Guid urlid, DateTime dateadded) diff --git a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs index 7743890a6..0ba594654 100644 --- a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -65,7 +65,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Barcode + /// Backing field for Barcode. /// protected string _Barcode; /// @@ -102,7 +102,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for LabelNumber + /// Backing field for LabelNumber. /// protected string _LabelNumber; /// @@ -139,7 +139,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Country + /// Backing field for Country. /// protected string _Country; /// diff --git a/Jellyfin.Data/Entities/Person.cs b/Jellyfin.Data/Entities/Person.cs index f71418819..8f6fb3a7d 100644 --- a/Jellyfin.Data/Entities/Person.cs +++ b/Jellyfin.Data/Entities/Person.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -59,7 +59,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -72,7 +72,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -97,7 +97,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for UrlId + /// Backing field for UrlId. /// protected Guid _UrlId; /// @@ -110,7 +110,7 @@ namespace Jellyfin.Data.Entities partial void GetUrlId(ref Guid result); /// - /// Required + /// Required. /// [Required] public Guid UrlId @@ -133,7 +133,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -171,7 +171,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for SourceId + /// Backing field for SourceId. /// protected string _SourceId; /// @@ -208,7 +208,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for DateAdded + /// Backing field for DateAdded. /// protected DateTime _DateAdded; /// @@ -221,7 +221,7 @@ namespace Jellyfin.Data.Entities partial void GetDateAdded(ref DateTime result); /// - /// Required + /// Required. /// [Required] public DateTime DateAdded @@ -244,7 +244,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for DateModified + /// Backing field for DateModified. /// protected DateTime _DateModified; /// @@ -257,7 +257,7 @@ namespace Jellyfin.Data.Entities partial void GetDateModified(ref DateTime result); /// - /// Required + /// Required. /// [Required] public DateTime DateModified @@ -280,7 +280,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/PersonRole.cs b/Jellyfin.Data/Entities/PersonRole.cs index a3d047115..9bd477938 100644 --- a/Jellyfin.Data/Entities/PersonRole.cs +++ b/Jellyfin.Data/Entities/PersonRole.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -65,7 +65,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -78,7 +78,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -103,7 +103,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Role + /// Backing field for Role. /// protected string _Role; /// @@ -140,7 +140,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Type + /// Backing field for Type. /// protected Enums.PersonRoleType _Type; /// @@ -153,7 +153,7 @@ namespace Jellyfin.Data.Entities partial void GetType(ref Enums.PersonRoleType result); /// - /// Required + /// Required. /// [Required] public Enums.PersonRoleType Type @@ -176,7 +176,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] @@ -192,7 +192,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Required + /// Required. /// [ForeignKey("Person_Id")] diff --git a/Jellyfin.Data/Entities/Photo.cs b/Jellyfin.Data/Entities/Photo.cs index 226730126..9da55fe43 100644 --- a/Jellyfin.Data/Entities/Photo.cs +++ b/Jellyfin.Data/Entities/Photo.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public Photo(Guid urlid, DateTime dateadded) diff --git a/Jellyfin.Data/Entities/PhotoMetadata.cs b/Jellyfin.Data/Entities/PhotoMetadata.cs index 2bb239cdd..5a9cf5b66 100644 --- a/Jellyfin.Data/Entities/PhotoMetadata.cs +++ b/Jellyfin.Data/Entities/PhotoMetadata.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes diff --git a/Jellyfin.Data/Entities/ProviderMapping.cs b/Jellyfin.Data/Entities/ProviderMapping.cs index e86d9737f..4125eabcd 100644 --- a/Jellyfin.Data/Entities/ProviderMapping.cs +++ b/Jellyfin.Data/Entities/ProviderMapping.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -65,7 +65,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -97,7 +97,7 @@ namespace Jellyfin.Data.Entities public string ProviderData { get; set; } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Rating.cs b/Jellyfin.Data/Entities/Rating.cs index 0c8b99ca2..34f395a22 100644 --- a/Jellyfin.Data/Entities/Rating.cs +++ b/Jellyfin.Data/Entities/Rating.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -55,7 +55,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -68,7 +68,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -93,7 +93,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Value + /// Backing field for Value. /// protected double _Value; /// @@ -106,7 +106,7 @@ namespace Jellyfin.Data.Entities partial void GetValue(ref double result); /// - /// Required + /// Required. /// [Required] public double Value @@ -129,7 +129,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Votes + /// Backing field for Votes. /// protected int? _Votes; /// @@ -161,7 +161,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/RatingSource.cs b/Jellyfin.Data/Entities/RatingSource.cs index c829042b5..5ea6069f9 100644 --- a/Jellyfin.Data/Entities/RatingSource.cs +++ b/Jellyfin.Data/Entities/RatingSource.cs @@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Jellyfin.Data.Entities { /// - /// This is the entity to store review ratings, not age ratings + /// This is the entity to store review ratings, not age ratings. /// public partial class RatingSource { @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -62,7 +62,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -75,7 +75,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -100,7 +100,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -137,7 +137,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for MaximumValue + /// Backing field for MaximumValue. /// protected double _MaximumValue; /// @@ -150,7 +150,7 @@ namespace Jellyfin.Data.Entities partial void GetMaximumValue(ref double result); /// - /// Required + /// Required. /// [Required] public double MaximumValue @@ -173,7 +173,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for MinimumValue + /// Backing field for MinimumValue. /// protected double _MinimumValue; /// @@ -186,7 +186,7 @@ namespace Jellyfin.Data.Entities partial void GetMinimumValue(ref double result); /// - /// Required + /// Required. /// [Required] public double MinimumValue @@ -209,7 +209,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Release.cs b/Jellyfin.Data/Entities/Release.cs index 35fcbb4b7..fe0dbaa54 100644 --- a/Jellyfin.Data/Entities/Release.cs +++ b/Jellyfin.Data/Entities/Release.cs @@ -29,7 +29,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// /// @@ -87,7 +87,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Id + /// Backing field for Id. /// internal int _Id; /// @@ -100,7 +100,7 @@ namespace Jellyfin.Data.Entities partial void GetId(ref int result); /// - /// Identity, Indexed, Required + /// Identity, Indexed, Required. /// [Key] [Required] @@ -125,7 +125,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Name + /// Backing field for Name. /// protected string _Name; /// @@ -163,7 +163,7 @@ namespace Jellyfin.Data.Entities } /// - /// Required, ConcurrenyToken + /// Required, ConcurrenyToken. /// [ConcurrencyCheck] [Required] diff --git a/Jellyfin.Data/Entities/Season.cs b/Jellyfin.Data/Entities/Season.cs index 2a861b660..81f413fa8 100644 --- a/Jellyfin.Data/Entities/Season.cs +++ b/Jellyfin.Data/Entities/Season.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. /// @@ -66,7 +66,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for SeasonNumber + /// Backing field for SeasonNumber. /// protected int? _SeasonNumber; /// diff --git a/Jellyfin.Data/Entities/SeasonMetadata.cs b/Jellyfin.Data/Entities/SeasonMetadata.cs index 10320c6bb..b323984f1 100644 --- a/Jellyfin.Data/Entities/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/SeasonMetadata.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -61,7 +61,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Outline + /// Backing field for Outline. /// protected string _Outline; /// diff --git a/Jellyfin.Data/Entities/Series.cs b/Jellyfin.Data/Entities/Series.cs index cf1d6b781..013c8385f 100644 --- a/Jellyfin.Data/Entities/Series.cs +++ b/Jellyfin.Data/Entities/Series.cs @@ -20,7 +20,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. public Series(Guid urlid, DateTime dateadded) @@ -47,7 +47,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for AirsDayOfWeek + /// Backing field for AirsDayOfWeek. /// protected DayOfWeek? _AirsDayOfWeek; /// @@ -79,7 +79,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for AirsTime + /// Backing field for AirsTime. /// protected DateTimeOffset? _AirsTime; /// @@ -92,7 +92,7 @@ namespace Jellyfin.Data.Entities partial void GetAirsTime(ref DateTimeOffset? result); /// - /// The time the show airs, ignore the date portion + /// The time the show airs, ignore the date portion. /// public DateTimeOffset? AirsTime { @@ -114,7 +114,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for FirstAired + /// Backing field for FirstAired. /// protected DateTimeOffset? _FirstAired; /// diff --git a/Jellyfin.Data/Entities/SeriesMetadata.cs b/Jellyfin.Data/Entities/SeriesMetadata.cs index bb31c2e4e..4666d79ef 100644 --- a/Jellyfin.Data/Entities/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/SeriesMetadata.cs @@ -28,7 +28,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes @@ -65,7 +65,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for Outline + /// Backing field for Outline. /// protected string _Outline; /// @@ -102,7 +102,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Plot + /// Backing field for Plot. /// protected string _Plot; /// @@ -139,7 +139,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Tagline + /// Backing field for Tagline. /// protected string _Tagline; /// @@ -176,7 +176,7 @@ namespace Jellyfin.Data.Entities } /// - /// Backing field for Country + /// Backing field for Country. /// protected string _Country; /// diff --git a/Jellyfin.Data/Entities/Track.cs b/Jellyfin.Data/Entities/Track.cs index c9e8fd1c3..1c3562a65 100644 --- a/Jellyfin.Data/Entities/Track.cs +++ b/Jellyfin.Data/Entities/Track.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// This is whats gets displayed in the Urls and API requests. This could also be a string. /// @@ -66,7 +66,7 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Backing field for TrackNumber + /// Backing field for TrackNumber. /// protected int? _TrackNumber; /// diff --git a/Jellyfin.Data/Entities/TrackMetadata.cs b/Jellyfin.Data/Entities/TrackMetadata.cs index 7b99c0683..05bb953f8 100644 --- a/Jellyfin.Data/Entities/TrackMetadata.cs +++ b/Jellyfin.Data/Entities/TrackMetadata.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Data.Entities } /// - /// Public constructor with required data + /// Public constructor with required data. /// /// The title or name of the object /// ISO-639-3 3-character language codes diff --git a/Jellyfin.Data/Enums/PreferenceKind.cs b/Jellyfin.Data/Enums/PreferenceKind.cs index de8eecc73..a54d789af 100644 --- a/Jellyfin.Data/Enums/PreferenceKind.cs +++ b/Jellyfin.Data/Enums/PreferenceKind.cs @@ -26,7 +26,7 @@ namespace Jellyfin.Data.Enums EnabledDevices = 3, /// - /// A list of enabled channels + /// A list of enabled channels. /// EnabledChannels = 4, diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index f574ebc66..a3fc6291f 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -69,7 +69,7 @@ namespace Jellyfin.Server.Implementations /// /// Repository for global::Jellyfin.Data.Entities.RatingSource - This is the entity to - /// store review ratings, not age ratings + /// store review ratings, not age ratings. /// public virtual DbSet RatingSources { get; set; } public virtual DbSet Releases { get; set; } diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 9e651fb19..b041effb2 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -43,7 +43,7 @@ namespace MediaBrowser.Api private readonly IMediaSourceManager _mediaSourceManager; /// - /// The active transcoding jobs + /// The active transcoding jobs. /// private readonly List _activeTranscodingJobs = new List(); @@ -293,7 +293,7 @@ namespace MediaBrowser.Api /// /// - /// The progressive + /// The progressive. /// /// Called when [transcode failed to start]. /// diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index a91a9b580..63a31a745 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -17,7 +17,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class BaseApiService + /// Class BaseApiService. /// public abstract class BaseApiService : IService, IRequiresRequest { diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs index 3cab9fb66..8c336b1c9 100644 --- a/MediaBrowser.Api/ChannelService.cs +++ b/MediaBrowser.Api/ChannelService.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -90,7 +90,7 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -149,7 +149,7 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs index 3ad51de8d..19369ccca 100644 --- a/MediaBrowser.Api/ConfigurationService.cs +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetConfiguration + /// Class GetConfiguration. /// [Route("/System/Configuration", "GET", Summary = "Gets application configuration")] [Authenticated] @@ -28,7 +28,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateConfiguration + /// Class UpdateConfiguration. /// [Route("/System/Configuration", "POST", Summary = "Updates application configuration")] [Authenticated(Roles = "Admin")] @@ -65,12 +65,12 @@ namespace MediaBrowser.Api public class ConfigurationService : BaseApiService { /// - /// The _json serializer + /// The _json serializer. /// private readonly IJsonSerializer _jsonSerializer; /// - /// The _configuration manager + /// The _configuration manager. /// private readonly IServerConfigurationManager _configurationManager; diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs index 62c4ff43f..c3ed40ad3 100644 --- a/MediaBrowser.Api/DisplayPreferencesService.cs +++ b/MediaBrowser.Api/DisplayPreferencesService.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class UpdateDisplayPreferences + /// Class UpdateDisplayPreferences. /// [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")] public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid @@ -44,17 +44,17 @@ namespace MediaBrowser.Api } /// - /// Class DisplayPreferencesService + /// Class DisplayPreferencesService. /// [Authenticated] public class DisplayPreferencesService : BaseApiService { /// - /// The _display preferences manager + /// The _display preferences manager. /// private readonly IDisplayPreferencesRepository _displayPreferencesManager; /// - /// The _json serializer + /// The _json serializer. /// private readonly IJsonSerializer _jsonSerializer; diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index fddf78465..70acd069e 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -12,7 +12,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetDirectoryContents + /// Class GetDirectoryContents. /// [Route("/Environment/DirectoryContents", "GET", Summary = "Gets the contents of a given directory in the file system")] public class GetDirectoryContents : IReturn> @@ -66,7 +66,7 @@ namespace MediaBrowser.Api } /// - /// Class GetDrives + /// Class GetDrives. /// [Route("/Environment/Drives", "GET", Summary = "Gets available drives from the server's file system")] public class GetDrives : IReturn> @@ -74,7 +74,7 @@ namespace MediaBrowser.Api } /// - /// Class GetNetworkComputers + /// Class GetNetworkComputers. /// [Route("/Environment/NetworkDevices", "GET", Summary = "Gets a list of devices on the network")] public class GetNetworkDevices : IReturn> @@ -103,7 +103,7 @@ namespace MediaBrowser.Api } /// - /// Class EnvironmentService + /// Class EnvironmentService. /// [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)] public class EnvironmentService : BaseApiService @@ -112,7 +112,7 @@ namespace MediaBrowser.Api private const string UncSeparatorString = "\\"; /// - /// The _network manager + /// The _network manager. /// private readonly INetworkManager _networkManager; private readonly IFileSystem _fileSystem; @@ -220,7 +220,7 @@ namespace MediaBrowser.Api } /// - /// Gets the list that is returned when an empty path is supplied + /// Gets the list that is returned when an empty path is supplied. /// /// IEnumerable{FileSystemEntryInfo}. private IEnumerable GetDrives() diff --git a/MediaBrowser.Api/IHasItemFields.cs b/MediaBrowser.Api/IHasItemFields.cs index 6359de77d..ad4f1b489 100644 --- a/MediaBrowser.Api/IHasItemFields.cs +++ b/MediaBrowser.Api/IHasItemFields.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Api { /// - /// Interface IHasItemFields + /// Interface IHasItemFields. /// public interface IHasItemFields { diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs index 45b7d0c10..2d405ac3d 100644 --- a/MediaBrowser.Api/Images/ImageByNameService.cs +++ b/MediaBrowser.Api/Images/ImageByNameService.cs @@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Images { /// - /// Class GetGeneralImage + /// Class GetGeneralImage. /// [Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")] public class GetGeneralImage @@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class GetRatingImage + /// Class GetRatingImage. /// [Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")] public class GetRatingImage @@ -54,7 +54,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class GetMediaInfoImage + /// Class GetMediaInfoImage. /// [Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")] public class GetMediaInfoImage @@ -93,12 +93,12 @@ namespace MediaBrowser.Api.Images } /// - /// Class ImageByNameService + /// Class ImageByNameService. /// public class ImageByNameService : BaseApiService { /// - /// The _app paths + /// The _app paths. /// private readonly IServerApplicationPaths _appPaths; diff --git a/MediaBrowser.Api/Images/ImageRequest.cs b/MediaBrowser.Api/Images/ImageRequest.cs index 71ff09b63..0f3455548 100644 --- a/MediaBrowser.Api/Images/ImageRequest.cs +++ b/MediaBrowser.Api/Images/ImageRequest.cs @@ -4,30 +4,30 @@ using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Images { /// - /// Class ImageRequest + /// Class ImageRequest. /// public class ImageRequest : DeleteImageRequest { /// - /// The max width + /// The max width. /// [ApiMember(Name = "MaxWidth", Description = "The maximum image width to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? MaxWidth { get; set; } /// - /// The max height + /// The max height. /// [ApiMember(Name = "MaxHeight", Description = "The maximum image height to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? MaxHeight { get; set; } /// - /// The width + /// The width. /// [ApiMember(Name = "Width", Description = "The fixed image width to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Width { get; set; } /// - /// The height + /// The height. /// [ApiMember(Name = "Height", Description = "The fixed image height to return.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Height { get; set; } @@ -79,7 +79,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class DeleteImageRequest + /// Class DeleteImageRequest. /// public class DeleteImageRequest { diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 6f2956c5d..8426a9a4f 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class UpdateItemImageIndex + /// Class UpdateItemImageIndex. /// [Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST", Summary = "Updates the index for an item image")] [Authenticated(Roles = "admin")] @@ -94,7 +94,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class GetPersonImage + /// Class GetPersonImage. /// [Route("/Artists/{Name}/Images/{Type}", "GET")] [Route("/Artists/{Name}/Images/{Type}/{Index}", "GET")] @@ -131,7 +131,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class GetUserImage + /// Class GetUserImage. /// [Route("/Users/{Id}/Images/{Type}", "GET")] [Route("/Users/{Id}/Images/{Type}/{Index}", "GET")] @@ -148,7 +148,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class DeleteItemImage + /// Class DeleteItemImage. /// [Route("/Items/{Id}/Images/{Type}", "DELETE")] [Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")] @@ -164,7 +164,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class DeleteUserImage + /// Class DeleteUserImage. /// [Route("/Users/{Id}/Images/{Type}", "DELETE")] [Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")] @@ -180,7 +180,7 @@ namespace MediaBrowser.Api.Images } /// - /// Class PostUserImage + /// Class PostUserImage. /// [Route("/Users/{Id}/Images/{Type}", "POST")] [Route("/Users/{Id}/Images/{Type}/{Index}", "POST")] @@ -195,14 +195,14 @@ namespace MediaBrowser.Api.Images public string Id { get; set; } /// - /// The raw Http Request Input Stream + /// The raw Http Request Input Stream. /// /// The request stream. public Stream RequestStream { get; set; } } /// - /// Class PostItemImage + /// Class PostItemImage. /// [Route("/Items/{Id}/Images/{Type}", "POST")] [Route("/Items/{Id}/Images/{Type}/{Index}", "POST")] @@ -217,14 +217,14 @@ namespace MediaBrowser.Api.Images public string Id { get; set; } /// - /// The raw Http Request Input Stream + /// The raw Http Request Input Stream. /// /// The request stream. public Stream RequestStream { get; set; } } /// - /// Class ImageService + /// Class ImageService. /// public class ImageService : BaseApiService { diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index 2633a5d3c..86464b4b9 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Images public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index eb64abb4d..1ab820680 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class GetCriticReviews + /// Class GetCriticReviews. /// [Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")] [Authenticated] @@ -70,7 +70,7 @@ namespace MediaBrowser.Api.Library public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -78,7 +78,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class GetThemeSongs + /// Class GetThemeSongs. /// [Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")] [Authenticated] @@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class GetThemeVideos + /// Class GetThemeVideos. /// [Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")] [Authenticated] @@ -128,7 +128,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class GetThemeVideos + /// Class GetThemeVideos. /// [Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")] [Authenticated] @@ -205,7 +205,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class GetPhyscialPaths + /// Class GetPhyscialPaths. /// [Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")] [Authenticated(Roles = "Admin")] @@ -312,7 +312,7 @@ namespace MediaBrowser.Api.Library } /// - /// Class LibraryService + /// Class LibraryService. /// public class LibraryService : BaseApiService { diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 1e300814f..b69550ed1 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Library { /// - /// Class GetDefaultVirtualFolders + /// Class GetDefaultVirtualFolders. /// [Route("/Library/VirtualFolders", "GET")] public class GetVirtualFolders : IReturn> @@ -166,18 +166,18 @@ namespace MediaBrowser.Api.Library } /// - /// Class LibraryStructureService + /// Class LibraryStructureService. /// [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)] public class LibraryStructureService : BaseApiService { /// - /// The _app paths + /// The _app paths. /// private readonly IServerApplicationPaths _appPaths; /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; private readonly ILibraryMonitor _libraryMonitor; diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index b00a5fec8..8e13744c4 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -31,7 +31,7 @@ using Microsoft.Net.Http.Headers; namespace MediaBrowser.Api.LiveTv { /// - /// This is insecure right now to avoid windows phone refactoring + /// This is insecure right now to avoid windows phone refactoring. /// [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")] [Authenticated] @@ -72,7 +72,7 @@ namespace MediaBrowser.Api.LiveTv public bool? IsSports { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -100,7 +100,7 @@ namespace MediaBrowser.Api.LiveTv public string EnableImageTypes { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -188,7 +188,7 @@ namespace MediaBrowser.Api.LiveTv public string EnableImageTypes { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -250,7 +250,7 @@ namespace MediaBrowser.Api.LiveTv public string EnableImageTypes { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -410,7 +410,7 @@ namespace MediaBrowser.Api.LiveTv public Guid LibrarySeriesId { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -473,7 +473,7 @@ namespace MediaBrowser.Api.LiveTv public string GenreIds { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs index 6a69d2656..d6b5f5195 100644 --- a/MediaBrowser.Api/LocalizationService.cs +++ b/MediaBrowser.Api/LocalizationService.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetCultures + /// Class GetCultures. /// [Route("/Localization/Cultures", "GET", Summary = "Gets known cultures")] public class GetCultures : IReturn @@ -16,7 +16,7 @@ namespace MediaBrowser.Api } /// - /// Class GetCountries + /// Class GetCountries. /// [Route("/Localization/Countries", "GET", Summary = "Gets known countries")] public class GetCountries : IReturn @@ -24,7 +24,7 @@ namespace MediaBrowser.Api } /// - /// Class ParentalRatings + /// Class ParentalRatings. /// [Route("/Localization/ParentalRatings", "GET", Summary = "Gets known parental ratings")] public class GetParentalRatings : IReturn @@ -32,7 +32,7 @@ namespace MediaBrowser.Api } /// - /// Class ParentalRatings + /// Class ParentalRatings. /// [Route("/Localization/Options", "GET", Summary = "Gets localization options")] public class GetLocalizationOptions : IReturn @@ -40,13 +40,13 @@ namespace MediaBrowser.Api } /// - /// Class CulturesService + /// Class CulturesService. /// [Authenticated(AllowBeforeStartupWizard = true)] public class LocalizationService : BaseApiService { /// - /// The _localization + /// The _localization. /// private readonly ILocalizationManager _localization; diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 88ca0aa23..34cccffa3 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -65,13 +65,13 @@ namespace MediaBrowser.Api.Movies } /// - /// Class MoviesService + /// Class MoviesService. /// [Authenticated] public class MoviesService : BaseApiService { /// - /// The _user manager + /// The _user manager. /// private readonly IUserManager _userManager; diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index a7758b100..ca9f9d03b 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -18,18 +18,18 @@ namespace MediaBrowser.Api.Movies } /// - /// Class TrailersService + /// Class TrailersService. /// [Authenticated] public class TrailersService : BaseApiService { /// - /// The _user manager + /// The _user manager. /// private readonly IUserManager _userManager; /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index f257d1014..74d3cce12 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -27,16 +27,16 @@ namespace MediaBrowser.Api.Music public class AlbumsService : BaseApiService { /// - /// The _user manager + /// The _user manager. /// private readonly IUserManager _userManager; /// - /// The _user data repository + /// The _user data repository. /// private readonly IUserDataManager _userDataRepository; /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; private readonly IItemRepository _itemRepo; diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index 444354a99..a63d06ad5 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetPackage + /// Class GetPackage. /// [Route("/Packages/{Name}", "GET", Summary = "Gets a package, by name or assembly guid")] [Authenticated] @@ -36,7 +36,7 @@ namespace MediaBrowser.Api } /// - /// Class GetPackages + /// Class GetPackages. /// [Route("/Packages", "GET", Summary = "Gets available packages")] [Authenticated] @@ -45,7 +45,7 @@ namespace MediaBrowser.Api } /// - /// Class InstallPackage + /// Class InstallPackage. /// [Route("/Packages/Installed/{Name}", "POST", Summary = "Installs a package")] [Authenticated(Roles = "Admin")] @@ -74,7 +74,7 @@ namespace MediaBrowser.Api } /// - /// Class CancelPackageInstallation + /// Class CancelPackageInstallation. /// [Route("/Packages/Installing/{Id}", "DELETE", Summary = "Cancels a package installation")] [Authenticated(Roles = "Admin")] @@ -89,7 +89,7 @@ namespace MediaBrowser.Api } /// - /// Class PackageService + /// Class PackageService. /// public class PackageService : BaseApiService { diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2eb6198c0..afbafa9d3 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -28,7 +28,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Playback { /// - /// Class BaseStreamingService + /// Class BaseStreamingService. /// public abstract class BaseStreamingService : BaseApiService { diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index c2d49a93b..f41f006fa 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Playback.Hls { /// - /// Class BaseHlsService + /// Class BaseHlsService. /// public abstract class BaseHlsService : BaseStreamingService { diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index 87ccde2e0..8a3d00283 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Playback.Hls { /// - /// Class GetHlsAudioSegment + /// Class GetHlsAudioSegment. /// // Can't require authentication just yet due to seeing some requests come from Chrome without full query string //[Authenticated] @@ -37,7 +37,7 @@ namespace MediaBrowser.Api.Playback.Hls } /// - /// Class GetHlsVideoSegment + /// Class GetHlsVideoSegment. /// [Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")] [Authenticated] @@ -66,7 +66,7 @@ namespace MediaBrowser.Api.Playback.Hls } /// - /// Class GetHlsVideoSegment + /// Class GetHlsVideoSegment. /// // Can't require authentication just yet due to seeing some requests come from Chrome without full query string //[Authenticated] diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index aefb3f019..9562f9953 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Api.Playback.Hls } /// - /// Class VideoHlsService + /// Class VideoHlsService. /// [Authenticated] public class VideoHlsService : BaseHlsService diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index 34c7986ca..d51787df2 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Playback.Progressive { /// - /// Class GetAudioStream + /// Class GetAudioStream. /// [Route("/Audio/{Id}/stream.{Container}", "GET", Summary = "Gets an audio stream")] [Route("/Audio/{Id}/stream", "GET", Summary = "Gets an audio stream")] @@ -26,7 +26,7 @@ namespace MediaBrowser.Api.Playback.Progressive } /// - /// Class AudioService + /// Class AudioService. /// // TODO: In order to autheneticate this in the future, Dlna playback will require updating //[Authenticated] diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 43cde440c..4820cbd92 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -21,7 +21,7 @@ using Microsoft.Net.Http.Headers; namespace MediaBrowser.Api.Playback.Progressive { /// - /// Class BaseProgressiveStreamingService + /// Class BaseProgressiveStreamingService. /// public abstract class BaseProgressiveStreamingService : BaseStreamingService { diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index a35e6c201..c3f6b905c 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Playback.Progressive { /// - /// Class GetVideoStream + /// Class GetVideoStream. /// [Route("/Videos/{Id}/stream.mpegts", "GET")] [Route("/Videos/{Id}/stream.ts", "GET")] @@ -62,7 +62,7 @@ namespace MediaBrowser.Api.Playback.Progressive } /// - /// Class VideoService + /// Class VideoService. /// // TODO: In order to autheneticate this in the future, Dlna playback will require updating //[Authenticated] diff --git a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs index 3b8b29995..7e2e337ad 100644 --- a/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs +++ b/MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs @@ -8,17 +8,17 @@ using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Playback { /// - /// Class StaticRemoteStreamWriter + /// Class StaticRemoteStreamWriter. /// public class StaticRemoteStreamWriter : IAsyncStreamWriter, IHasHeaders { /// - /// The _input stream + /// The _input stream. /// private readonly HttpResponseInfo _response; /// - /// The _options + /// The _options. /// private readonly IDictionary _options = new Dictionary(); diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 9ba8eda91..cfcc98035 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -4,7 +4,7 @@ using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Playback { /// - /// Class StreamRequest + /// Class StreamRequest. /// public class StreamRequest : BaseEncodingJobOptions { diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs index d5def03be..5513c0892 100644 --- a/MediaBrowser.Api/PlaylistService.cs +++ b/MediaBrowser.Api/PlaylistService.cs @@ -95,14 +95,14 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index fd1075727..e9d5b2bc4 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class Plugins + /// Class Plugins. /// [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")] [Authenticated] @@ -25,7 +25,7 @@ namespace MediaBrowser.Api } /// - /// Class UninstallPlugin + /// Class UninstallPlugin. /// [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")] [Authenticated(Roles = "Admin")] @@ -40,7 +40,7 @@ namespace MediaBrowser.Api } /// - /// Class GetPluginConfiguration + /// Class GetPluginConfiguration. /// [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")] [Authenticated] @@ -55,7 +55,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdatePluginConfiguration + /// Class UpdatePluginConfiguration. /// [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")] [Authenticated] @@ -69,7 +69,7 @@ namespace MediaBrowser.Api public string Id { get; set; } /// - /// The raw Http Request Input Stream + /// The raw Http Request Input Stream. /// /// The request stream. public Stream RequestStream { get; set; } @@ -86,7 +86,7 @@ namespace MediaBrowser.Api } /// - /// Class GetPluginSecurityInfo + /// Class GetPluginSecurityInfo. /// [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information", IsHidden = true)] [Authenticated] @@ -95,7 +95,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdatePluginSecurityInfo + /// Class UpdatePluginSecurityInfo. /// [Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information", IsHidden = true)] [Authenticated(Roles = "Admin")] @@ -136,17 +136,17 @@ namespace MediaBrowser.Api public bool IsMBSupporter { get; set; } } /// - /// Class PluginsService + /// Class PluginsService. /// public class PluginService : BaseApiService { /// - /// The _json serializer + /// The _json serializer. /// private readonly IJsonSerializer _jsonSerializer; /// - /// The _app host + /// The _app host. /// private readonly IApplicationHost _appHost; private readonly IInstallationManager _installationManager; diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index e08a8482e..86b00316a 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.ScheduledTasks { /// - /// Class GetScheduledTask + /// Class GetScheduledTask. /// [Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")] public class GetScheduledTask : IReturn @@ -25,7 +25,7 @@ namespace MediaBrowser.Api.ScheduledTasks } /// - /// Class GetScheduledTasks + /// Class GetScheduledTasks. /// [Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")] public class GetScheduledTasks : IReturn @@ -38,7 +38,7 @@ namespace MediaBrowser.Api.ScheduledTasks } /// - /// Class StartScheduledTask + /// Class StartScheduledTask. /// [Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")] public class StartScheduledTask : IReturnVoid @@ -52,7 +52,7 @@ namespace MediaBrowser.Api.ScheduledTasks } /// - /// Class StopScheduledTask + /// Class StopScheduledTask. /// [Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")] public class StopScheduledTask : IReturnVoid @@ -66,7 +66,7 @@ namespace MediaBrowser.Api.ScheduledTasks } /// - /// Class UpdateScheduledTaskTriggers + /// Class UpdateScheduledTaskTriggers. /// [Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")] public class UpdateScheduledTaskTriggers : List, IReturnVoid @@ -80,7 +80,7 @@ namespace MediaBrowser.Api.ScheduledTasks } /// - /// Class ScheduledTasksService + /// Class ScheduledTasksService. /// [Authenticated(Roles = "Admin")] public class ScheduledTaskService : BaseApiService diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index 14b9b3618..25dd39f2d 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.ScheduledTasks { /// - /// Class ScheduledTasksWebSocketListener + /// Class ScheduledTasksWebSocketListener. /// public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index 4a2f96ed8..64ee69300 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -18,7 +18,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetSearchHints + /// Class GetSearchHints. /// [Route("/Search/Hints", "GET", Summary = "Gets search hints based on a search term")] public class GetSearchHints : IReturn @@ -31,7 +31,7 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -45,7 +45,7 @@ namespace MediaBrowser.Api public Guid UserId { get; set; } /// - /// Search characters used to find items + /// Search characters used to find items. /// /// The index by. [ApiMember(Name = "SearchTerm", Description = "The search term to filter on", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] @@ -104,13 +104,13 @@ namespace MediaBrowser.Api } /// - /// Class SearchService + /// Class SearchService. /// [Authenticated] public class SearchService : BaseApiService { /// - /// The _search engine + /// The _search engine. /// private readonly ISearchEngine _searchEngine; private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs index 175984575..2400d6def 100644 --- a/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/Sessions/SessionInfoWebSocketListener.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.Sessions { /// - /// Class SessionInfoWebSocketListener + /// Class SessionInfoWebSocketListener. /// public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { @@ -19,7 +19,7 @@ namespace MediaBrowser.Api.Sessions protected override string Name => "Sessions"; /// - /// The _kernel + /// The _kernel. /// private readonly ISessionManager _sessionManager; diff --git a/MediaBrowser.Api/Sessions/SessionService.cs b/MediaBrowser.Api/Sessions/SessionService.cs index d986eea65..50adc5698 100644 --- a/MediaBrowser.Api/Sessions/SessionService.cs +++ b/MediaBrowser.Api/Sessions/SessionService.cs @@ -46,14 +46,14 @@ namespace MediaBrowser.Api.Sessions public string Id { get; set; } /// - /// Artist, Genre, Studio, Person, or any kind of BaseItem + /// Artist, Genre, Studio, Person, or any kind of BaseItem. /// /// The type of the item. [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] public string ItemType { get; set; } /// - /// Artist name, genre name, item Id, etc + /// Artist name, genre name, item Id, etc. /// /// The item identifier. [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 90c324ff3..7ed70f5d7 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class BaseGetSimilarItemsFromItem + /// Class BaseGetSimilarItemsFromItem. /// public class BaseGetSimilarItemsFromItem : BaseGetSimilarItems { @@ -50,14 +50,14 @@ namespace MediaBrowser.Api public Guid UserId { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -65,7 +65,7 @@ namespace MediaBrowser.Api } /// - /// Class SimilarItemsHelper + /// Class SimilarItemsHelper. /// public static class SimilarItemsHelper { diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs index a6bacad4f..7ca31c21a 100644 --- a/MediaBrowser.Api/System/ActivityLogService.cs +++ b/MediaBrowser.Api/System/ActivityLogService.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Api.System public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs index 8e4860be4..39976371a 100644 --- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs +++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.System { /// - /// Class SessionInfoWebSocketListener + /// Class SessionInfoWebSocketListener. /// public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener { @@ -19,7 +19,7 @@ namespace MediaBrowser.Api.System protected override string Name => "ActivityLogEntry"; /// - /// The _kernel + /// The _kernel. /// private readonly IActivityManager _activityManager; diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index 4f10a4ad2..e0e20d828 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -18,7 +18,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.System { /// - /// Class GetSystemInfo + /// Class GetSystemInfo. /// [Route("/System/Info", "GET", Summary = "Gets information about the server")] [Authenticated(EscapeParentalControl = true, AllowBeforeStartupWizard = true)] @@ -38,7 +38,7 @@ namespace MediaBrowser.Api.System } /// - /// Class RestartApplication + /// Class RestartApplication. /// [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] [Authenticated(Roles = "Admin", AllowLocal = true)] @@ -83,12 +83,12 @@ namespace MediaBrowser.Api.System } /// - /// Class SystemInfoService + /// Class SystemInfoService. /// public class SystemService : BaseApiService { /// - /// The _app host + /// The _app host. /// private readonly IServerApplicationHost _appHost; private readonly IApplicationPaths _appPaths; diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 23062b67b..6177c2e2e 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetNextUpEpisodes + /// Class GetNextUpEpisodes. /// [Route("/Shows/NextUp", "GET", Summary = "Gets a list of next up episodes")] public class GetNextUpEpisodes : IReturn>, IHasDtoOptions @@ -39,14 +39,14 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -99,14 +99,14 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -143,7 +143,7 @@ namespace MediaBrowser.Api public Guid UserId { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -175,7 +175,7 @@ namespace MediaBrowser.Api public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] @@ -211,7 +211,7 @@ namespace MediaBrowser.Api public Guid UserId { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -243,18 +243,18 @@ namespace MediaBrowser.Api } /// - /// Class TvShowsService + /// Class TvShowsService. /// [Authenticated] public class TvShowsService : BaseApiService { /// - /// The _user manager + /// The _user manager. /// private readonly IUserManager _userManager; /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index bef91d54d..9875e0208 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetArtists + /// Class GetArtists. /// [Route("/Artists", "GET", Summary = "Gets all artists from a given item, folder, or the entire library")] public class GetArtists : GetItemsByName @@ -45,7 +45,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class ArtistsService + /// Class ArtistsService. /// [Authenticated] public class ArtistsService : BaseItemsByNameService diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 4802849f4..a68c6fb6d 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class BaseItemsByNameService + /// Class BaseItemsByNameService. /// /// The type of the T item type. public abstract class BaseItemsByNameService : BaseApiService @@ -52,7 +52,7 @@ namespace MediaBrowser.Api.UserLibrary protected IUserManager UserManager { get; } /// - /// Gets the library manager + /// Gets the library manager. /// protected ILibraryManager LibraryManager { get; } @@ -375,7 +375,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetItemsByName + /// Class GetItemsByName. /// public class GetItemsByName : BaseItemsRequest, IReturn> { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index 7561b5c89..5a4394425 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -111,14 +111,14 @@ namespace MediaBrowser.Api.UserLibrary public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } /// - /// Whether or not to perform the query recursively + /// Whether or not to perform the query recursively. /// /// true if recursive; otherwise, false. [ApiMember(Name = "Recursive", Description = "When searching within folders, this determines whether or not the search will be recursive. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] @@ -141,7 +141,7 @@ namespace MediaBrowser.Api.UserLibrary public string ParentId { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -162,14 +162,14 @@ namespace MediaBrowser.Api.UserLibrary public string IncludeItemTypes { get; set; } /// - /// Filters to apply to the results + /// Filters to apply to the results. /// /// The filters. [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Filters { get; set; } /// - /// Gets or sets the Isfavorite option + /// Gets or sets the Isfavorite option. /// /// IsFavorite [ApiMember(Name = "IsFavorite", Description = "Optional filter by items that are marked as favorite, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] @@ -190,7 +190,7 @@ namespace MediaBrowser.Api.UserLibrary public string ImageTypes { get; set; } /// - /// What to sort the results by + /// What to sort the results by. /// /// The sort by. [ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -200,7 +200,7 @@ namespace MediaBrowser.Api.UserLibrary public bool? IsPlayed { get; set; } /// - /// Limit results to items containing specific genres + /// Limit results to items containing specific genres. /// /// The genres. [ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -215,7 +215,7 @@ namespace MediaBrowser.Api.UserLibrary public string Tags { get; set; } /// - /// Limit results to items containing specific years + /// Limit results to items containing specific years. /// /// The years. [ApiMember(Name = "Years", Description = "Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] @@ -234,7 +234,7 @@ namespace MediaBrowser.Api.UserLibrary public string EnableImageTypes { get; set; } /// - /// Limit results to items containing a specific person + /// Limit results to items containing a specific person. /// /// The person. [ApiMember(Name = "Person", Description = "Optional. If specified, results will be filtered to include only those containing the specified person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] @@ -244,14 +244,14 @@ namespace MediaBrowser.Api.UserLibrary public string PersonIds { get; set; } /// - /// If the Person filter is used, this can also be used to restrict to a specific person type + /// If the Person filter is used, this can also be used to restrict to a specific person type. /// /// The type of the person. [ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string PersonTypes { get; set; } /// - /// Limit results to items containing specific studios + /// Limit results to items containing specific studios. /// /// The studios. [ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 1fa272a5f..7bdfbac98 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetGenres + /// Class GetGenres. /// [Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")] public class GetGenres : GetItemsByName @@ -22,7 +22,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetGenre + /// Class GetGenre. /// [Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")] public class GetGenre : IReturn @@ -43,7 +43,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GenresService + /// Class GenresService. /// [Authenticated] public class GenresService : BaseItemsByNameService diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 49d534c36..7efe0552c 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -20,7 +20,7 @@ using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetItems + /// Class GetItems. /// [Route("/Items", "GET", Summary = "Gets items based on a query.")] [Route("/Users/{UserId}/Items", "GET", Summary = "Gets items based on a query.")] @@ -34,18 +34,18 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class ItemsService + /// Class ItemsService. /// [Authenticated] public class ItemsService : BaseApiService { /// - /// The _user manager + /// The _user manager. /// private readonly IUserManager _userManager; /// - /// The _library manager + /// The _library manager. /// private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; @@ -496,7 +496,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class DateCreatedComparer + /// Class DateCreatedComparer. /// public class DateCreatedComparer : IComparer { diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index 3204e5219..7924339ed 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetPersons + /// Class GetPersons. /// [Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")] public class GetPersons : GetItemsByName @@ -22,7 +22,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetPerson + /// Class GetPerson. /// [Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")] public class GetPerson : IReturn @@ -43,7 +43,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class PersonsService + /// Class PersonsService. /// [Authenticated] public class PersonsService : BaseItemsByNameService diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index ab231626b..d809cc2e7 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class MarkPlayedItem + /// Class MarkPlayedItem. /// [Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")] public class MarkPlayedItem : IReturn @@ -38,7 +38,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class MarkUnplayedItem + /// Class MarkUnplayedItem. /// [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")] public class MarkUnplayedItem : IReturn @@ -81,7 +81,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class OnPlaybackStart + /// Class OnPlaybackStart. /// [Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")] public class OnPlaybackStart : IReturnVoid @@ -123,7 +123,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class OnPlaybackProgress + /// Class OnPlaybackProgress. /// [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")] public class OnPlaybackProgress : IReturnVoid @@ -181,7 +181,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class OnPlaybackStopped + /// Class OnPlaybackStopped. /// [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")] public class OnPlaybackStopped : IReturnVoid diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 683ce5d09..66350955f 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetStudios + /// Class GetStudios. /// [Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")] public class GetStudios : GetItemsByName @@ -21,7 +21,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetStudio + /// Class GetStudio. /// [Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")] public class GetStudio : IReturn @@ -42,7 +42,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class StudiosService + /// Class StudiosService. /// [Authenticated] public class StudiosService : BaseItemsByNameService diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index f75852885..f9cbba410 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetItem + /// Class GetItem. /// [Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")] public class GetItem : IReturn @@ -41,7 +41,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetItem + /// Class GetItem. /// [Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")] public class GetRootFolder : IReturn @@ -55,7 +55,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetIntros + /// Class GetIntros. /// [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")] public class GetIntros : IReturn> @@ -76,7 +76,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class MarkFavoriteItem + /// Class MarkFavoriteItem. /// [Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")] public class MarkFavoriteItem : IReturn @@ -97,7 +97,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class UnmarkFavoriteItem + /// Class UnmarkFavoriteItem. /// [Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")] public class UnmarkFavoriteItem : IReturn @@ -118,7 +118,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class ClearUserItemRating + /// Class ClearUserItemRating. /// [Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")] public class DeleteUserItemRating : IReturn @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class UpdateUserItemRating + /// Class UpdateUserItemRating. /// [Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")] public class UpdateUserItemRating : IReturn @@ -167,7 +167,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetLocalTrailers + /// Class GetLocalTrailers. /// [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")] public class GetLocalTrailers : IReturn @@ -188,7 +188,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetSpecialFeatures + /// Class GetSpecialFeatures. /// [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")] public class GetSpecialFeatures : IReturn @@ -259,7 +259,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class UserLibraryService + /// Class UserLibraryService. /// [Authenticated] public class UserLibraryService : BaseApiService diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs index d023ee90a..0523f89fa 100644 --- a/MediaBrowser.Api/UserLibrary/YearsService.cs +++ b/MediaBrowser.Api/UserLibrary/YearsService.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { /// - /// Class GetYears + /// Class GetYears. /// [Route("/Years", "GET", Summary = "Gets all years from a given item, folder, or the entire library")] public class GetYears : GetItemsByName @@ -21,7 +21,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class GetYear + /// Class GetYear. /// [Route("/Years/{Year}", "GET", Summary = "Gets a year")] public class GetYear : IReturn @@ -42,7 +42,7 @@ namespace MediaBrowser.Api.UserLibrary } /// - /// Class YearsService + /// Class YearsService. /// [Authenticated] public class YearsService : BaseItemsByNameService diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 9cb9baf63..131def554 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Api { /// - /// Class GetUsers + /// Class GetUsers. /// [Route("/Users", "GET", Summary = "Gets a list of users")] [Authenticated] @@ -41,7 +41,7 @@ namespace MediaBrowser.Api } /// - /// Class GetUser + /// Class GetUser. /// [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")] [Authenticated(EscapeParentalControl = true)] @@ -56,7 +56,7 @@ namespace MediaBrowser.Api } /// - /// Class DeleteUser + /// Class DeleteUser. /// [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")] [Authenticated(Roles = "Admin")] @@ -71,7 +71,7 @@ namespace MediaBrowser.Api } /// - /// Class AuthenticateUser + /// Class AuthenticateUser. /// [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")] public class AuthenticateUser : IReturn @@ -95,7 +95,7 @@ namespace MediaBrowser.Api } /// - /// Class AuthenticateUser + /// Class AuthenticateUser. /// [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")] public class AuthenticateUserByName : IReturn @@ -119,7 +119,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateUserPassword + /// Class UpdateUserPassword. /// [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")] [Authenticated] @@ -149,7 +149,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateUserEasyPassword + /// Class UpdateUserEasyPassword. /// [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")] [Authenticated] @@ -177,7 +177,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateUser + /// Class UpdateUser. /// [Route("/Users/{Id}", "POST", Summary = "Updates a user")] [Authenticated] @@ -186,7 +186,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateUser + /// Class UpdateUser. /// [Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")] [Authenticated(Roles = "admin")] @@ -197,7 +197,7 @@ namespace MediaBrowser.Api } /// - /// Class UpdateUser + /// Class UpdateUser. /// [Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")] [Authenticated] @@ -208,7 +208,7 @@ namespace MediaBrowser.Api } /// - /// Class CreateUser + /// Class CreateUser. /// [Route("/Users/New", "POST", Summary = "Creates a user")] [Authenticated(Roles = "Admin")] @@ -236,7 +236,7 @@ namespace MediaBrowser.Api } /// - /// Class UsersService + /// Class UsersService. /// public class UserService : BaseApiService { diff --git a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs index 60455e68a..1f4a26064 100644 --- a/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs +++ b/MediaBrowser.Controller/Channels/InternalChannelFeatures.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Channels public List ContentTypes { get; set; } /// - /// Represents the maximum number of records the channel allows retrieving at a time + /// Represents the maximum number of records the channel allows retrieving at a time. /// public int? MaxPageSize { get; set; } diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs index 6660743e6..a5c5e3bcc 100644 --- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs +++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs @@ -4,7 +4,7 @@ using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Configuration { /// - /// Interface IServerConfigurationManager + /// Interface IServerConfigurationManager. /// public interface IServerConfigurationManager : IConfigurationManager { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index f1873d539..488692c03 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -10,7 +10,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Drawing { /// - /// Interface IImageProcessor + /// Interface IImageProcessor. /// public interface IImageProcessor { diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index 56e6c47c4..0dadc283e 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Dto { /// - /// Interface IDtoService + /// Interface IDtoService. /// public interface IDtoService { diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 54540e892..67858b844 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.Entities public override bool SupportsPlayedStatus => false; /// - /// The _virtual children + /// The _virtual children. /// private readonly ConcurrentBag _virtualChildren = new ConcurrentBag(); diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index a8ea2157d..b3e241a15 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities.Audio { /// - /// Class Audio + /// Class Audio. /// public class Audio : BaseItem, IHasAlbumArtist, diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index f7b2f9549..e563f398b 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -15,7 +15,7 @@ using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider; namespace MediaBrowser.Controller.Entities.Audio { /// - /// Class MusicAlbum + /// Class MusicAlbum. /// public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 63db3cfab..56c3c38dc 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -15,7 +15,7 @@ using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider; namespace MediaBrowser.Controller.Entities.Audio { /// - /// Class MusicArtist + /// Class MusicArtist. /// public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo { @@ -111,7 +111,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -201,7 +201,7 @@ namespace MediaBrowser.Controller.Entities.Audio } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 537e9630b..49a4cbae2 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities.Audio { /// - /// Class MusicGenre + /// Class MusicGenre. /// public class MusicGenre : BaseItem, IItemByName { @@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -98,7 +98,7 @@ namespace MediaBrowser.Controller.Entities.Audio } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f2de1f2b1..ecbb83d07 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -31,12 +31,12 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities { /// - /// Class BaseItem + /// Class BaseItem. /// public abstract class BaseItem : IHasProviderIds, IHasLookupInfo, IEquatable { /// - /// The supported image extensions + /// The supported image extensions. /// public static readonly string[] SupportedImageExtensions = new[] { ".png", ".jpg", ".jpeg", ".tbn", ".gif" }; @@ -75,7 +75,7 @@ namespace MediaBrowser.Controller.Entities public static char SlugChar = '-'; /// - /// The trailer folder name + /// The trailer folder name. /// public const string TrailerFolderName = "trailers"; public const string ThemeSongsFolderName = "theme-music"; @@ -243,7 +243,7 @@ namespace MediaBrowser.Controller.Entities /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// [JsonIgnore] public virtual string ContainingFolderPath @@ -267,7 +267,7 @@ namespace MediaBrowser.Controller.Entities public string ServiceName { get; set; } /// - /// If this content came from an external service, the id of the content on that service + /// If this content came from an external service, the id of the content on that service. /// [JsonIgnore] public string ExternalId { get; set; } @@ -411,7 +411,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// This is just a helper for convenience + /// This is just a helper for convenience. /// /// The primary image path. [JsonIgnore] @@ -556,7 +556,7 @@ namespace MediaBrowser.Controller.Entities public DateTime DateLastRefreshed { get; set; } /// - /// The logger + /// The logger. /// public static ILoggerFactory LoggerFactory { get; set; } public static ILogger Logger { get; set; } @@ -799,7 +799,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Finds a parent of a given type + /// Finds a parent of a given type. /// /// /// ``0. @@ -1351,7 +1351,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Overrides the base implementation to refresh metadata for local trailers + /// Overrides the base implementation to refresh metadata for local trailers. /// /// The options. /// The cancellation token. @@ -1753,7 +1753,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Determines if a given user has access to this item + /// Determines if a given user has access to this item. /// /// The user. /// true if [is parental allowed] [the specified user]; otherwise, false. @@ -2059,7 +2059,7 @@ namespace MediaBrowser.Controller.Entities public virtual bool EnableRememberingTrackSelections => true; /// - /// Adds a studio to the item + /// Adds a studio to the item. /// /// The name. /// @@ -2095,7 +2095,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Adds a genre to the item + /// Adds a genre to the item. /// /// The name. /// @@ -2190,7 +2190,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Gets an image + /// Gets an image. /// /// The type. /// Index of the image. @@ -2506,7 +2506,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Gets the file system path to delete when the item is to be deleted + /// Gets the file system path to delete when the item is to be deleted. /// /// public virtual IEnumerable GetDeletePaths() diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index e5adf88d1..35a6cef95 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Entities { /// /// Specialized Folder class that points to a subset of the physical folders in the system. - /// It is created from the user-specific folders within the system root + /// It is created from the user-specific folders within the system root. /// public class CollectionFolder : Folder, ICollectionFolder { @@ -140,7 +140,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Allow different display preferences for each collection folder + /// Allow different display preferences for each collection folder. /// /// The display prefs id. [JsonIgnore] diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index d2ca11740..3a34c668c 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { /// - /// Class Extensions + /// Class Extensions. /// public static class Extensions { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 3a01b4379..34e5d78e7 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -31,7 +31,7 @@ using Series = MediaBrowser.Controller.Entities.TV.Series; namespace MediaBrowser.Controller.Entities { /// - /// Class Folder + /// Class Folder. /// public class Folder : BaseItem { @@ -172,7 +172,7 @@ namespace MediaBrowser.Controller.Entities public virtual IEnumerable Children => LoadChildren(); /// - /// thread-safe access to all recursive children of this folder - without regard to user + /// thread-safe access to all recursive children of this folder - without regard to user. /// /// The recursive children. [JsonIgnore] @@ -229,7 +229,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Validates that the children of the folder still exist + /// Validates that the children of the folder still exist. /// /// The progress. /// The cancellation token. @@ -570,7 +570,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Get the children of this folder from the actual file system + /// Get the children of this folder from the actual file system. /// /// IEnumerable{BaseItem}. protected virtual IEnumerable GetNonCachedChildren(IDirectoryService directoryService) @@ -582,7 +582,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Get our children from the repo - stubbed for now + /// Get our children from the repo - stubbed for now. /// /// IEnumerable{BaseItem}. protected List GetCachedChildren() @@ -1286,7 +1286,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// Gets allowed recursive children of an item + /// Gets allowed recursive children of an item. /// /// The user. /// if set to true [include linked children]. diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 773c7df34..852cf4684 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities { /// - /// Class Genre + /// Class Genre. /// public class Genre : BaseItem, IItemByName { @@ -31,7 +31,7 @@ namespace MediaBrowser.Controller.Entities /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs index 4f0760746..245b23ff0 100644 --- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs @@ -3,7 +3,7 @@ using System; namespace MediaBrowser.Controller.Entities { /// - /// This is just a marker interface to denote top level folders + /// This is just a marker interface to denote top level folders. /// public interface ICollectionFolder : IHasCollectionType { diff --git a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs index 149c1e5ab..d7d007668 100644 --- a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs +++ b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs @@ -1,7 +1,7 @@ namespace MediaBrowser.Controller.Entities { /// - /// Interface IHasAspectRatio + /// Interface IHasAspectRatio. /// public interface IHasAspectRatio { diff --git a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs index abee75a28..13226b234 100644 --- a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs +++ b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs @@ -1,7 +1,7 @@ namespace MediaBrowser.Controller.Entities { /// - /// Interface IHasDisplayOrder + /// Interface IHasDisplayOrder. /// public interface IHasDisplayOrder { diff --git a/MediaBrowser.Controller/Entities/IHasScreenshots.cs b/MediaBrowser.Controller/Entities/IHasScreenshots.cs index 0975242f5..b027a0cb1 100644 --- a/MediaBrowser.Controller/Entities/IHasScreenshots.cs +++ b/MediaBrowser.Controller/Entities/IHasScreenshots.cs @@ -1,7 +1,7 @@ namespace MediaBrowser.Controller.Entities { /// - /// Interface IHasScreenshots + /// Interface IHasScreenshots. /// public interface IHasScreenshots { diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs index d88c31007..fbce74aab 100644 --- a/MediaBrowser.Controller/Entities/LinkedChild.cs +++ b/MediaBrowser.Controller/Entities/LinkedChild.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities public string Id { get; set; } /// - /// Serves as a cache + /// Serves as a cache. /// public Guid? ItemId { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index be71bcc3c..70c48b6f1 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Entities.Movies { /// - /// Class BoxSet + /// Class BoxSet. /// public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo { diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 26a165025..53badac4d 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities.Movies { /// - /// Class Movie + /// Class Movie. /// public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo, ISupportsBoxSetGrouping { diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 9e4f9d47e..69bd7659c 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Entities /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -118,7 +118,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 068032317..f81b6f194 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities { /// - /// Class Studio + /// Class Studio. /// public class Studio : BaseItem, IItemByName { @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Entities /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 4ec60e7cd..82e7d49fb 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -12,7 +12,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities.TV { /// - /// Class Episode + /// Class Episode. /// public class Episode : Video, IHasTrailers, IHasLookupInfo, IHasSeries { @@ -101,7 +101,7 @@ namespace MediaBrowser.Controller.Entities.TV } /// - /// This Episode's Series Instance + /// This Episode's Series Instance. /// /// The series. [JsonIgnore] diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 7dfd1a759..9f0658776 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Entities.TV { /// - /// Class Season + /// Class Season. /// public class Season : Folder, IHasSeries, IHasLookupInfo { @@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Entities.TV } /// - /// This Episode's Series Instance + /// This Episode's Series Instance. /// /// The series. [JsonIgnore] @@ -225,7 +225,7 @@ namespace MediaBrowser.Controller.Entities.TV } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// /// true if XXXX, false otherwise. public override bool BeforeMetadataRefresh(bool replaceAllMetdata) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a519089b3..9263a156a 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -17,7 +17,7 @@ using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider; namespace MediaBrowser.Controller.Entities.TV { /// - /// Class Series + /// Class Series. /// public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IMetadataContainer { @@ -54,7 +54,7 @@ namespace MediaBrowser.Controller.Entities.TV public IReadOnlyList RemoteTrailerIds { get; set; } /// - /// airdate, dvd or absolute + /// airdate, dvd or absolute. /// public string DisplayOrder { get; set; } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index c327d17c9..6b544afc6 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -9,7 +9,7 @@ using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities { /// - /// Class Trailer + /// Class Trailer. /// public class Trailer : Video, IHasLookupInfo { diff --git a/MediaBrowser.Controller/Entities/UserItemData.cs b/MediaBrowser.Controller/Entities/UserItemData.cs index ab425ee0f..81f4850a5 100644 --- a/MediaBrowser.Controller/Entities/UserItemData.cs +++ b/MediaBrowser.Controller/Entities/UserItemData.cs @@ -4,7 +4,7 @@ using System.Text.Json.Serialization; namespace MediaBrowser.Controller.Entities { /// - /// Class UserItemData + /// Class UserItemData. /// public class UserItemData { @@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities public string Key { get; set; } /// - /// The _rating + /// The _rating. /// private double? _rating; /// - /// Gets or sets the users 0-10 rating + /// Gets or sets the users 0-10 rating. /// /// The rating. /// Rating;A 0 to 10 rating is required for UserItemData. diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 4cfa0e74d..4efeede19 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Controller.Entities { /// - /// Class Video + /// Class Video. /// public class Video : BaseItem, IHasAspectRatio, diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index a01ef5c31..c961da643 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities { /// - /// Class Year + /// Class Year. /// public class Year : BaseItem, IItemByName { @@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Entities /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] @@ -107,7 +107,7 @@ namespace MediaBrowser.Controller.Entities } /// - /// This is called before any metadata refresh and returns true or false indicating if changes were made + /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// public override bool BeforeMetadataRefresh(bool replaceAllMetdata) { diff --git a/MediaBrowser.Controller/Extensions/StringExtensions.cs b/MediaBrowser.Controller/Extensions/StringExtensions.cs index b1aaf6534..e09543e14 100644 --- a/MediaBrowser.Controller/Extensions/StringExtensions.cs +++ b/MediaBrowser.Controller/Extensions/StringExtensions.cs @@ -7,7 +7,7 @@ using System.Text.RegularExpressions; namespace MediaBrowser.Controller.Extensions { /// - /// Class BaseExtensions + /// Class BaseExtensions. /// public static class StringExtensions { diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index d1d6c74b8..abdb0f695 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller { /// - /// Interface IServerApplicationHost + /// Interface IServerApplicationHost. /// public interface IServerApplicationHost : IApplicationHost { diff --git a/MediaBrowser.Controller/IServerApplicationPaths.cs b/MediaBrowser.Controller/IServerApplicationPaths.cs index c35a22ac7..155bf9177 100644 --- a/MediaBrowser.Controller/IServerApplicationPaths.cs +++ b/MediaBrowser.Controller/IServerApplicationPaths.cs @@ -5,7 +5,7 @@ namespace MediaBrowser.Controller public interface IServerApplicationPaths : IApplicationPaths { /// - /// Gets the path to the base root media directory + /// Gets the path to the base root media directory. /// /// The root folder path. string RootFolderPath { get; } @@ -17,13 +17,13 @@ namespace MediaBrowser.Controller string DefaultUserViewsPath { get; } /// - /// Gets the path to the People directory + /// Gets the path to the People directory. /// /// The people path. string PeoplePath { get; } /// - /// Gets the path to the Genre directory + /// Gets the path to the Genre directory. /// /// The genre path. string GenrePath { get; } @@ -35,25 +35,25 @@ namespace MediaBrowser.Controller string MusicGenrePath { get; } /// - /// Gets the path to the Studio directory + /// Gets the path to the Studio directory. /// /// The studio path. string StudioPath { get; } /// - /// Gets the path to the Year directory + /// Gets the path to the Year directory. /// /// The year path. string YearPath { get; } /// - /// Gets the path to the General IBN directory + /// Gets the path to the General IBN directory. /// /// The general path. string GeneralPath { get; } /// - /// Gets the path to the Ratings IBN directory + /// Gets the path to the Ratings IBN directory. /// /// The ratings path. string RatingsPath { get; } @@ -65,7 +65,7 @@ namespace MediaBrowser.Controller string MediaInfoImagesPath { get; } /// - /// Gets the path to the user configuration directory + /// Gets the path to the user configuration directory. /// /// The user configuration directory path. string UserConfigurationDirectoryPath { get; } diff --git a/MediaBrowser.Controller/Library/IIntroProvider.cs b/MediaBrowser.Controller/Library/IIntroProvider.cs index aa7001611..d45493d40 100644 --- a/MediaBrowser.Controller/Library/IIntroProvider.cs +++ b/MediaBrowser.Controller/Library/IIntroProvider.cs @@ -5,7 +5,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Library { /// - /// Class BaseIntroProvider + /// Class BaseIntroProvider. /// public interface IIntroProvider { diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index d7237039e..47c080ebd 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -21,7 +21,7 @@ using Person = MediaBrowser.Controller.Entities.Person; namespace MediaBrowser.Controller.Library { /// - /// Interface ILibraryManager + /// Interface ILibraryManager. /// public interface ILibraryManager { @@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Library bool allowIgnorePath = true); /// - /// Resolves a set of files into a list of BaseItem + /// Resolves a set of files into a list of BaseItem. /// IEnumerable ResolvePaths( IEnumerable files, @@ -54,7 +54,7 @@ namespace MediaBrowser.Controller.Library AggregateFolder RootFolder { get; } /// - /// Gets a Person + /// Gets a Person. /// /// The name. /// Task{Person}. @@ -75,14 +75,14 @@ namespace MediaBrowser.Controller.Library MusicArtist GetArtist(string name); MusicArtist GetArtist(string name, DtoOptions options); /// - /// Gets a Studio + /// Gets a Studio. /// /// The name. /// Task{Studio}. Studio GetStudio(string name); /// - /// Gets a Genre + /// Gets a Genre. /// /// The name. /// Task{Genre}. @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Library MusicGenre GetMusicGenre(string name); /// - /// Gets a Year + /// Gets a Year. /// /// The value. /// Task{Year}. @@ -113,7 +113,7 @@ namespace MediaBrowser.Controller.Library Task ValidatePeople(CancellationToken cancellationToken, IProgress progress); /// - /// Reloads the root media folder + /// Reloads the root media folder. /// /// The progress. /// The cancellation token. diff --git a/MediaBrowser.Controller/Library/ILibraryPostScanTask.cs b/MediaBrowser.Controller/Library/ILibraryPostScanTask.cs index cba5e8fd7..4032e9d83 100644 --- a/MediaBrowser.Controller/Library/ILibraryPostScanTask.cs +++ b/MediaBrowser.Controller/Library/ILibraryPostScanTask.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Controller.Library { /// - /// An interface for tasks that run after the media library scan + /// An interface for tasks that run after the media library scan. /// public interface ILibraryPostScanTask { diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs index dd119984e..027cc5b40 100644 --- a/MediaBrowser.Controller/Library/IMetadataSaver.cs +++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs @@ -4,7 +4,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Library { /// - /// Interface IMetadataSaver + /// Interface IMetadataSaver. /// public interface IMetadataSaver { diff --git a/MediaBrowser.Controller/Library/ISearchEngine.cs b/MediaBrowser.Controller/Library/ISearchEngine.cs index 8498b92ae..31dcbba5b 100644 --- a/MediaBrowser.Controller/Library/ISearchEngine.cs +++ b/MediaBrowser.Controller/Library/ISearchEngine.cs @@ -4,7 +4,7 @@ using MediaBrowser.Model.Search; namespace MediaBrowser.Controller.Library { /// - /// Interface ILibrarySearchEngine + /// Interface ILibrarySearchEngine. /// public interface ISearchEngine { diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index f5ccad671..d08ad4cac 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -42,14 +42,14 @@ namespace MediaBrowser.Controller.Library UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions dto_options); /// - /// Get all user data for the given user + /// Get all user data for the given user. /// /// /// List GetAllUserData(Guid userId); /// - /// Save the all provided user data for the given user + /// Save the all provided user data for the given user. /// /// /// @@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Library void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken); /// - /// Updates playstate for an item and returns true or false indicating if it was played to completion + /// Updates playstate for an item and returns true or false indicating if it was played to completion. /// bool UpdatePlayState(BaseItem item, UserItemData data, long? positionTicks); } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index b5b2e4729..fe3e4f9e6 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Library { /// - /// Interface IUserManager + /// Interface IUserManager. /// public interface IUserManager { diff --git a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs index c9671de47..b5c48321b 100644 --- a/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs +++ b/MediaBrowser.Controller/Library/ItemChangeEventArgs.cs @@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Library { /// - /// Class ItemChangeEventArgs + /// Class ItemChangeEventArgs. /// public class ItemChangeEventArgs { diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index cca85cd3b..7c1463862 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library public class ItemResolveArgs : EventArgs { /// - /// The _app paths + /// The _app paths. /// private readonly IServerApplicationPaths _appPaths; diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs index b4e205184..abe129484 100644 --- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs +++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Library { /// - /// Holds information about a playback progress event + /// Holds information about a playback progress event. /// public class PlaybackProgressEventArgs : EventArgs { diff --git a/MediaBrowser.Controller/Library/Profiler.cs b/MediaBrowser.Controller/Library/Profiler.cs index 0febef3d3..a566de338 100644 --- a/MediaBrowser.Controller/Library/Profiler.cs +++ b/MediaBrowser.Controller/Library/Profiler.cs @@ -5,21 +5,21 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Library { /// - /// Class Profiler + /// Class Profiler. /// public class Profiler : IDisposable { /// - /// The name + /// The name. /// readonly string _name; /// - /// The stopwatch + /// The stopwatch. /// readonly Stopwatch _stopwatch; /// - /// The _logger + /// The _logger. /// private readonly ILogger _logger; diff --git a/MediaBrowser.Controller/Library/SearchHintInfo.cs b/MediaBrowser.Controller/Library/SearchHintInfo.cs index 692431e34..897c2b7f4 100644 --- a/MediaBrowser.Controller/Library/SearchHintInfo.cs +++ b/MediaBrowser.Controller/Library/SearchHintInfo.cs @@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Library { /// - /// Class SearchHintInfo + /// Class SearchHintInfo. /// public class SearchHintInfo { diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index fd5fb6748..ebdcfbdb3 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -3,7 +3,7 @@ using System; namespace MediaBrowser.Controller.Library { /// - /// Class TVUtils + /// Class TVUtils. /// public static class TVUtils { diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs index 3e7351b8b..fa0192784 100644 --- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs +++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Library { /// - /// Class UserDataSaveEventArgs + /// Class UserDataSaveEventArgs. /// public class UserDataSaveEventArgs : EventArgs { diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs index 70477fce7..1b7095c7b 100644 --- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs @@ -3,7 +3,7 @@ using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Controller.LiveTv { /// - /// Class ChannelInfo + /// Class ChannelInfo. /// public class ChannelInfo { @@ -44,13 +44,13 @@ namespace MediaBrowser.Controller.LiveTv public ChannelType ChannelType { get; set; } /// - /// Supply the image path if it can be accessed directly from the file system + /// Supply the image path if it can be accessed directly from the file system. /// /// The image path. public string ImagePath { get; set; } /// - /// Supply the image url if it can be downloaded + /// Supply the image url if it can be downloaded. /// /// The image URL. public string ImageUrl { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index bc3bf78f0..aa24d5ab8 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -14,7 +14,7 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.LiveTv { /// - /// Manages all live tv services installed on the server + /// Manages all live tv services installed on the server. /// public interface ILiveTvManager { diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index e17db34c6..472b061e6 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -140,7 +140,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself + /// If the item is a folder, it returns the folder itself. /// /// The containing folder path. [JsonIgnore] diff --git a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs index 5d0f13192..b847140f5 100644 --- a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.LiveTv public string ChannelId { get; set; } /// - /// Name of the program + /// Name of the program. /// public string Name { get; set; } @@ -95,13 +95,13 @@ namespace MediaBrowser.Controller.LiveTv public string EpisodeTitle { get; set; } /// - /// Supply the image path if it can be accessed directly from the file system + /// Supply the image path if it can be accessed directly from the file system. /// /// The image path. public string ImagePath { get; set; } /// - /// Supply the image url if it can be downloaded + /// Supply the image url if it can be downloaded. /// /// The image URL. public string ImageUrl { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs index 432388d6b..b9e0218ab 100644 --- a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs @@ -169,13 +169,13 @@ namespace MediaBrowser.Controller.LiveTv public float? CommunityRating { get; set; } /// - /// Supply the image path if it can be accessed directly from the file system + /// Supply the image path if it can be accessed directly from the file system. /// /// The image path. public string ImagePath { get; set; } /// - /// Supply the image url if it can be downloaded + /// Supply the image url if it can be downloaded. /// /// The image URL. public string ImageUrl { get; set; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 0ca42c0e0..680d92c2d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Gets the name of the output video codec + /// Gets the name of the output video codec. /// public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions) { @@ -285,7 +285,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Infers the audio codec based on the url + /// Infers the audio codec based on the url. /// public string InferAudioCodec(string container) { @@ -703,7 +703,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Gets the video bitrate to specify on the command line + /// Gets the video bitrate to specify on the command line. /// public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset) { @@ -1300,7 +1300,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Gets the number of audio channels to specify on the command line + /// Gets the number of audio channels to specify on the command line. /// /// The state. /// The audio stream. @@ -1486,7 +1486,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Determines which stream will be used for playback + /// Determines which stream will be used for playback. /// /// All stream. /// Index of the desired. @@ -1961,7 +1961,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// If we're going to put a fixed size on the command line, this will calculate it + /// If we're going to put a fixed size on the command line, this will calculate it. /// public string GetOutputSizeParam( EncodingJobInfo state, @@ -2505,7 +2505,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Gets the name of the output video codec + /// Gets the name of the output video codec. /// protected string GetHardwareAcceleratedVideoDecoder(EncodingJobInfo state, EncodingOptions encodingOptions) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index acf1aae89..32973619d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -418,7 +418,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public double? TargetVideoLevel { @@ -441,7 +441,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetVideoBitDepth { @@ -476,7 +476,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public float? TargetFramerate { @@ -508,7 +508,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetPacketLength { @@ -524,7 +524,7 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public string TargetVideoProfile { @@ -679,20 +679,20 @@ namespace MediaBrowser.Controller.MediaEncoding } /// - /// Enum TranscodingJobType + /// Enum TranscodingJobType. /// public enum TranscodingJobType { /// - /// The progressive + /// The progressive. /// Progressive, /// - /// The HLS + /// The HLS. /// Hls, /// - /// The dash + /// The dash. /// Dash } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 37f0b11a7..e33c4ad0b 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.System; namespace MediaBrowser.Controller.MediaEncoding { /// - /// Interface IMediaEncoder + /// Interface IMediaEncoder. /// public interface IMediaEncoder : ITranscoderSupport { diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 5cedc3d57..6c9bbb043 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.MediaEncoding { /// - /// Class MediaEncoderHelpers + /// Class MediaEncoderHelpers. /// public static class MediaEncoderHelpers { diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index df90c399b..9e262d31e 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Net { /// - /// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received + /// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received. /// /// The type of the T return data type. /// The type of the T state type. @@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Net where TReturnDataType : class { /// - /// The _active connections + /// The _active connections. /// private readonly List> _activeConnections = new List>(); @@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Net protected abstract Task GetDataToSend(); /// - /// The logger + /// The logger. /// protected ILogger> Logger; @@ -78,7 +78,7 @@ namespace MediaBrowser.Controller.Net } /// - /// Starts sending messages over a web socket + /// Starts sending messages over a web socket. /// /// The message. private void Start(WebSocketMessageInfo message) @@ -180,7 +180,7 @@ namespace MediaBrowser.Controller.Net } /// - /// Stops sending messages over a web socket + /// Stops sending messages over a web socket. /// /// The message. private void Stop(WebSocketMessageInfo message) diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs index 25404fa78..609bd5f59 100644 --- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs +++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Services; namespace MediaBrowser.Controller.Net { /// - /// Interface IHttpResultFactory + /// Interface IHttpResultFactory. /// public interface IHttpResultFactory { diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index efb5f4ac3..e6609fae3 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -29,19 +29,19 @@ namespace MediaBrowser.Controller.Net void Init(IEnumerable serviceTypes, IEnumerable listener, IEnumerable urlPrefixes); /// - /// If set, all requests will respond with this message + /// If set, all requests will respond with this message. /// string GlobalResponse { get; set; } /// - /// The HTTP request handler + /// The HTTP request handler. /// /// /// Task RequestHandler(HttpContext context); /// - /// Get the default CORS headers + /// Get the default CORS headers. /// /// /// diff --git a/MediaBrowser.Controller/Net/IWebSocketListener.cs b/MediaBrowser.Controller/Net/IWebSocketListener.cs index 0f472a2bc..7250a57b0 100644 --- a/MediaBrowser.Controller/Net/IWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/IWebSocketListener.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Controller.Net { /// - ///This is an interface for listening to messages coming through a web socket connection + ///This is an interface for listening to messages coming through a web socket connection. /// public interface IWebSocketListener { diff --git a/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs b/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs index 5bf39cae6..be0b3ddc3 100644 --- a/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs +++ b/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs @@ -3,7 +3,7 @@ using MediaBrowser.Model.Net; namespace MediaBrowser.Controller.Net { /// - /// Class WebSocketMessageInfo + /// Class WebSocketMessageInfo. /// public class WebSocketMessageInfo : WebSocketMessage { diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 75fc43a04..0ae1b8bbf 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -9,12 +9,12 @@ using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Persistence { /// - /// Provides an interface to implement an Item repository + /// Provides an interface to implement an Item repository. /// public interface IItemRepository : IRepository { /// - /// Saves an item + /// Saves an item. /// /// The item. /// The cancellation token. @@ -43,14 +43,14 @@ namespace MediaBrowser.Controller.Persistence BaseItem RetrieveItem(Guid id); /// - /// Gets chapters for an item + /// Gets chapters for an item. /// /// /// List GetChapters(BaseItem id); /// - /// Gets a single chapter for an item + /// Gets a single chapter for an item. /// /// /// diff --git a/MediaBrowser.Controller/Persistence/IRepository.cs b/MediaBrowser.Controller/Persistence/IRepository.cs index 56bf1dd5a..42f285076 100644 --- a/MediaBrowser.Controller/Persistence/IRepository.cs +++ b/MediaBrowser.Controller/Persistence/IRepository.cs @@ -3,12 +3,12 @@ using System; namespace MediaBrowser.Controller.Persistence { /// - /// Provides a base interface for all the repository interfaces + /// Provides a base interface for all the repository interfaces. /// public interface IRepository : IDisposable { /// - /// Gets the name of the repository + /// Gets the name of the repository. /// /// The name. string Name { get; } diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 4c327eeef..ba7c9fd50 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -5,7 +5,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Persistence { /// - /// Provides an interface to implement a UserData repository + /// Provides an interface to implement a UserData repository. /// public interface IUserDataRepository : IRepository { @@ -30,14 +30,14 @@ namespace MediaBrowser.Controller.Persistence UserItemData GetUserData(long userId, List keys); /// - /// Return all user data associated with the given user + /// Return all user data associated with the given user. /// /// /// List GetAllUserData(long userId); /// - /// Save all user data associated with the given user + /// Save all user data associated with the given user. /// /// /// diff --git a/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs b/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs index c156da924..077f5ab63 100644 --- a/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs +++ b/MediaBrowser.Controller/Plugins/IPluginConfigurationPage.cs @@ -4,7 +4,7 @@ using MediaBrowser.Common.Plugins; namespace MediaBrowser.Controller.Plugins { /// - /// Interface IConfigurationPage + /// Interface IConfigurationPage. /// public interface IPluginConfigurationPage { @@ -34,16 +34,16 @@ namespace MediaBrowser.Controller.Plugins } /// - /// Enum ConfigurationPageType + /// Enum ConfigurationPageType. /// public enum ConfigurationPageType { /// - /// The plugin configuration + /// The plugin configuration. /// PluginConfiguration, /// - /// The none + /// The none. /// None } diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs index 3e595ff93..62b16dadd 100644 --- a/MediaBrowser.Controller/Providers/IMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs @@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Providers { /// - /// Marker interface + /// Marker interface. /// public interface IMetadataProvider { diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs b/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs index 02152ee33..6d49b5510 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs @@ -3,22 +3,22 @@ namespace MediaBrowser.Controller.Providers public enum MetadataRefreshMode { /// - /// The none + /// The none. /// None = 0, /// - /// The validation only + /// The validation only. /// ValidationOnly = 1, /// - /// Providers will be executed based on default rules + /// Providers will be executed based on default rules. /// Default = 2, /// - /// All providers will be executed to search for new metadata + /// All providers will be executed to search for new metadata. /// FullRefresh = 3 } diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 59adaedfa..83efed2a1 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Providers } /// - /// Not only does this clear, but initializes the list so that services can differentiate between a null list and zero people + /// Not only does this clear, but initializes the list so that services can differentiate between a null list and zero people. /// public void ResetPeople() { diff --git a/MediaBrowser.Controller/Providers/VideoContentType.cs b/MediaBrowser.Controller/Providers/VideoContentType.cs index c3b8964a3..49d587f6c 100644 --- a/MediaBrowser.Controller/Providers/VideoContentType.cs +++ b/MediaBrowser.Controller/Providers/VideoContentType.cs @@ -1,17 +1,17 @@ namespace MediaBrowser.Controller.Providers { /// - /// Enum VideoContentType + /// Enum VideoContentType. /// public enum VideoContentType { /// - /// The episode + /// The episode. /// Episode = 0, /// - /// The movie + /// The movie. /// Movie = 1 } diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index 637a7e3f0..67acdd9a3 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Resolvers { /// - /// Class ItemResolver + /// Class ItemResolver. /// /// public abstract class ItemResolver : IItemResolver @@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.Resolvers public virtual ResolverPriority Priority => ResolverPriority.First; /// - /// Sets initial values on the newly resolved item + /// Sets initial values on the newly resolved item. /// /// The item. /// The args. diff --git a/MediaBrowser.Controller/Resolvers/IItemResolver.cs b/MediaBrowser.Controller/Resolvers/IItemResolver.cs index 16e37d249..2e82b51f1 100644 --- a/MediaBrowser.Controller/Resolvers/IItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/IItemResolver.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.Resolvers { /// - /// Interface IItemResolver + /// Interface IItemResolver. /// public interface IItemResolver { diff --git a/MediaBrowser.Controller/Resolvers/ResolverPriority.cs b/MediaBrowser.Controller/Resolvers/ResolverPriority.cs index e39310095..1911e5c1d 100644 --- a/MediaBrowser.Controller/Resolvers/ResolverPriority.cs +++ b/MediaBrowser.Controller/Resolvers/ResolverPriority.cs @@ -1,25 +1,25 @@ namespace MediaBrowser.Controller.Resolvers { /// - /// Enum ResolverPriority + /// Enum ResolverPriority. /// public enum ResolverPriority { /// - /// The first + /// The first. /// First = 1, /// - /// The second + /// The second. /// Second = 2, /// - /// The third + /// The third. /// Third = 3, Fourth = 4, /// - /// The last + /// The last. /// Last = 5 } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 1fdb588eb..e54f21050 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.SyncPlay; namespace MediaBrowser.Controller.Session { /// - /// Interface ISessionManager + /// Interface ISessionManager. /// public interface ISessionManager { @@ -79,14 +79,14 @@ namespace MediaBrowser.Controller.Session void UpdateDeviceName(string sessionId, string reportedDeviceName); /// - /// Used to report that playback has started for an item + /// Used to report that playback has started for an item. /// /// The info. /// Task. Task OnPlaybackStart(PlaybackStartInfo info); /// - /// Used to report playback progress for an item + /// Used to report playback progress for an item. /// /// The info. /// Task. @@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Session Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated); /// - /// Used to report that playback has ended for an item + /// Used to report that playback has ended for an item. /// /// The info. /// Task. diff --git a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs index 31087edec..727cbe639 100644 --- a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs @@ -4,7 +4,7 @@ using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Sorting { /// - /// Interface IBaseItemComparer + /// Interface IBaseItemComparer. /// public interface IBaseItemComparer : IComparer { diff --git a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs index 6f75d16de..6d03d97ae 100644 --- a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs @@ -3,7 +3,7 @@ using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Sorting { /// - /// Represents a BaseItem comparer that requires a User to perform it's comparison + /// Represents a BaseItem comparer that requires a User to perform it's comparison. /// public interface IUserBaseItemComparer : IBaseItemComparer { diff --git a/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs b/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs index c0b62b753..b2c53365c 100644 --- a/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs +++ b/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs @@ -1,7 +1,7 @@ namespace MediaBrowser.Controller.Sync { /// - /// A marker interface + /// A marker interface. /// public interface IRemoteSyncProvider { diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 0ceb55c57..da5a3d5bc 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -14,14 +14,14 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.LocalMetadata.Parsers { /// - /// Provides a base class for parsing metadata xml + /// Provides a base class for parsing metadata xml. /// /// public class BaseItemXmlParser where T : BaseItem { /// - /// The logger + /// The logger. /// protected ILogger> Logger { get; private set; } protected IProviderManager ProviderManager { get; private set; } @@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } /// - /// Fetches metadata for an item from one xml file + /// Fetches metadata for an item from one xml file. /// /// The item. /// The metadata file. @@ -124,7 +124,7 @@ namespace MediaBrowser.LocalMetadata.Parsers private readonly CultureInfo _usCulture = new CultureInfo("en-US"); /// - /// Fetches metadata from one Xml Element + /// Fetches metadata from one Xml Element. /// /// The reader. /// The item result. @@ -1230,7 +1230,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// - /// Used to split names of comma or pipe delimeted genres and people + /// Used to split names of comma or pipe delimeted genres and people. /// /// The value. /// IEnumerable{System.String}. diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index 3260f3051..e6359f4fb 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -9,7 +9,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.BdInfo { /// - /// Class BdInfoExaminer + /// Class BdInfoExaminer. /// public class BdInfoExaminer : IBlurayExaminer { diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a4896d5f9..59fd6b848 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -25,7 +25,7 @@ using System.Diagnostics; namespace MediaBrowser.MediaEncoding.Encoder { /// - /// Class MediaEncoder + /// Class MediaEncoder. /// public class MediaEncoder : IMediaEncoder, IDisposable { @@ -425,7 +425,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } /// - /// The us culture + /// The us culture. /// protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 78dc7b607..3aa296f7f 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets a string from an FFProbeResult tags dictionary + /// Gets a string from an FFProbeResult tags dictionary. /// /// The tags. /// The key. @@ -52,7 +52,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets an int from an FFProbeResult tags dictionary + /// Gets an int from an FFProbeResult tags dictionary. /// /// The tags. /// The key. @@ -73,7 +73,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets a DateTime from an FFProbeResult tags dictionary + /// Gets a DateTime from an FFProbeResult tags dictionary. /// /// The tags. /// The key. @@ -94,7 +94,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Converts a dictionary to case insensitive + /// Converts a dictionary to case insensitive. /// /// The dict. /// Dictionary{System.StringSystem.String}. diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 7d57a691e..4c48c038f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -515,7 +515,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Converts ffprobe stream info to our MediaAttachment class + /// Converts ffprobe stream info to our MediaAttachment class. /// /// The stream info. /// MediaAttachments. @@ -548,7 +548,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Converts ffprobe stream info to our MediaStream class + /// Converts ffprobe stream info to our MediaStream class. /// /// if set to true [is info]. /// The stream info. @@ -767,7 +767,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets a string from an FFProbeResult tags dictionary + /// Gets a string from an FFProbeResult tags dictionary. /// /// The tags. /// The key. @@ -1154,7 +1154,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets the studios from the tags collection + /// Gets the studios from the tags collection. /// /// The info. /// The tags. @@ -1191,7 +1191,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets the genres from the tags collection + /// Gets the genres from the tags collection. /// /// The information. /// The tags. diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 7e9894f0a..763d7f641 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -344,7 +344,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } /// - /// The _semaphoreLocks + /// The _semaphoreLocks. /// private readonly ConcurrentDictionary _semaphoreLocks = new ConcurrentDictionary(); diff --git a/MediaBrowser.Model/Channels/ChannelFeatures.cs b/MediaBrowser.Model/Channels/ChannelFeatures.cs index 496102d83..a55754edd 100644 --- a/MediaBrowser.Model/Channels/ChannelFeatures.cs +++ b/MediaBrowser.Model/Channels/ChannelFeatures.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Model.Channels public ChannelMediaContentType[] ContentTypes { get; set; } /// - /// Represents the maximum number of records the channel allows retrieving at a time + /// Represents the maximum number of records the channel allows retrieving at a time. /// public int? MaxPageSize { get; set; } diff --git a/MediaBrowser.Model/Channels/ChannelQuery.cs b/MediaBrowser.Model/Channels/ChannelQuery.cs index d11260039..fd90e7f06 100644 --- a/MediaBrowser.Model/Channels/ChannelQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelQuery.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Channels public class ChannelQuery { /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } @@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Channels public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index cdd322c94..54f4fb293 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Configuration public class BaseApplicationConfiguration { /// - /// The number of days we should retain log files + /// The number of days we should retain log files. /// /// The log file retention days. public int LogFileRetentionDays { get; set; } diff --git a/MediaBrowser.Model/Configuration/MetadataPluginType.cs b/MediaBrowser.Model/Configuration/MetadataPluginType.cs index bff12799f..4c5e95266 100644 --- a/MediaBrowser.Model/Configuration/MetadataPluginType.cs +++ b/MediaBrowser.Model/Configuration/MetadataPluginType.cs @@ -3,7 +3,7 @@ namespace MediaBrowser.Model.Configuration { /// - /// Enum MetadataPluginType + /// Enum MetadataPluginType. /// public enum MetadataPluginType { diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index afbe02dd3..742887620 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -111,19 +111,19 @@ namespace MediaBrowser.Model.Configuration public string MetadataCountryCode { get; set; } /// - /// Characters to be replaced with a ' ' in strings to create a sort name + /// Characters to be replaced with a ' ' in strings to create a sort name. /// /// The sort replace characters. public string[] SortReplaceCharacters { get; set; } /// - /// Characters to be removed from strings to create a sort name + /// Characters to be removed from strings to create a sort name. /// /// The sort remove characters. public string[] SortRemoveCharacters { get; set; } /// - /// Words to be removed from strings to create a sort name + /// Words to be removed from strings to create a sort name. /// /// The sort remove words. public string[] SortRemoveWords { get; set; } diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 85d864eec..d236ac215 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -7,7 +7,7 @@ using Jellyfin.Data.Enums; namespace MediaBrowser.Model.Configuration { /// - /// Class UserConfiguration + /// Class UserConfiguration. /// public class UserConfiguration { diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index fc555c5f7..baa99b903 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Model.Dlna public int? MaxAudioChannels { get; set; } /// - /// The application's configured quality setting + /// The application's configured quality setting. /// public long? MaxBitrate { get; set; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 244463803..28d8a6439 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -465,7 +465,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Returns the audio stream that will be used + /// Returns the audio stream that will be used. /// public MediaStream TargetAudioStream { @@ -481,7 +481,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Returns the video stream that will be used + /// Returns the video stream that will be used. /// public MediaStream TargetVideoStream { @@ -497,7 +497,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetAudioSampleRate { @@ -509,7 +509,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetAudioBitDepth { @@ -532,7 +532,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetVideoBitDepth { @@ -579,7 +579,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public float? TargetFramerate { @@ -593,7 +593,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public double? TargetVideoLevel { @@ -680,7 +680,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public int? TargetPacketLength { @@ -694,7 +694,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio sample rate that will be in the output stream + /// Predicts the audio sample rate that will be in the output stream. /// public string TargetVideoProfile { @@ -732,7 +732,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio bitrate that will be in the output stream + /// Predicts the audio bitrate that will be in the output stream. /// public int? TargetAudioBitrate { @@ -746,7 +746,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio channels that will be in the output stream + /// Predicts the audio channels that will be in the output stream. /// public int? TargetAudioChannels { @@ -787,7 +787,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio codec that will be in the output stream + /// Predicts the audio codec that will be in the output stream. /// public string[] TargetAudioCodec { @@ -840,7 +840,7 @@ namespace MediaBrowser.Model.Dlna } /// - /// Predicts the audio channels that will be in the output stream + /// Predicts the audio channels that will be in the output stream. /// public long? TargetSize { diff --git a/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs b/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs index 7b0204590..e7fe8d6af 100644 --- a/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs +++ b/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs @@ -5,22 +5,22 @@ namespace MediaBrowser.Model.Dlna public enum SubtitleDeliveryMethod { /// - /// The encode + /// The encode. /// Encode = 0, /// - /// The embed + /// The embed. /// Embed = 1, /// - /// The external + /// The external. /// External = 2, /// - /// The HLS + /// The HLS. /// Hls = 3 } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index c7f8f0584..cad18b5c8 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -308,7 +308,7 @@ namespace MediaBrowser.Model.Dto public int? LocalTrailerCount { get; set; } /// - /// User data for this item based on the user it's being requested for + /// User data for this item based on the user it's being requested for. /// /// The user data. public UserItemDataDto UserData { get; set; } diff --git a/MediaBrowser.Model/Dto/ImageOptions.cs b/MediaBrowser.Model/Dto/ImageOptions.cs index 158e622a8..3f4405f1e 100644 --- a/MediaBrowser.Model/Dto/ImageOptions.cs +++ b/MediaBrowser.Model/Dto/ImageOptions.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Model.Dto /// /// Gets or sets the image tag. - /// If set this will result in strong, unconditional response caching + /// If set this will result in strong, unconditional response caching. /// /// The hash. public string Tag { get; set; } diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 74c2cb4f4..e78e60d52 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Model.Dto public string Name { get; set; } /// - /// Differentiate internet url vs local network + /// Differentiate internet url vs local network. /// public bool IsRemote { get; set; } diff --git a/MediaBrowser.Model/Entities/DisplayPreferences.cs b/MediaBrowser.Model/Entities/DisplayPreferences.cs index 0e5db01dd..7e5c5be3b 100644 --- a/MediaBrowser.Model/Entities/DisplayPreferences.cs +++ b/MediaBrowser.Model/Entities/DisplayPreferences.cs @@ -104,7 +104,7 @@ namespace MediaBrowser.Model.Entities public bool ShowSidebar { get; set; } /// - /// Gets or sets the client + /// Gets or sets the client. /// public string Client { get; set; } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 3db72f78a..33c14ec1b 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Entities { /// - /// Class MediaStream + /// Class MediaStream. /// public class MediaStream { diff --git a/MediaBrowser.Model/Entities/MetadataProvider.cs b/MediaBrowser.Model/Entities/MetadataProvider.cs index bcc2b48e7..7fecf67b8 100644 --- a/MediaBrowser.Model/Entities/MetadataProvider.cs +++ b/MediaBrowser.Model/Entities/MetadataProvider.cs @@ -3,28 +3,28 @@ namespace MediaBrowser.Model.Entities { /// - /// Enum MetadataProviders + /// Enum MetadataProviders. /// public enum MetadataProvider { /// - /// The imdb + /// The imdb. /// Imdb = 2, /// - /// The TMDB + /// The TMDB. /// Tmdb = 3, /// - /// The TVDB + /// The TVDB. /// Tvdb = 4, /// - /// The tvcom + /// The tvcom. /// Tvcom = 5, /// - /// Tmdb Collection Id + /// Tmdb Collection Id. /// TmdbCollection = 7, MusicBrainzAlbum = 8, diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index 2de02e403..662fa1f78 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Configuration; namespace MediaBrowser.Model.Entities { /// - /// Used to hold information about a user's list of configured virtual folders + /// Used to hold information about a user's list of configured virtual folders. /// public class VirtualFolderInfo { diff --git a/MediaBrowser.Model/IO/IZipClient.cs b/MediaBrowser.Model/IO/IZipClient.cs index 83e8a018d..2daa54f22 100644 --- a/MediaBrowser.Model/IO/IZipClient.cs +++ b/MediaBrowser.Model/IO/IZipClient.cs @@ -5,7 +5,7 @@ using System.IO; namespace MediaBrowser.Model.IO { /// - /// Interface IZipClient + /// Interface IZipClient. /// public interface IZipClient { diff --git a/MediaBrowser.Model/LiveTv/ChannelType.cs b/MediaBrowser.Model/LiveTv/ChannelType.cs index b6974cb08..f4c55cb6d 100644 --- a/MediaBrowser.Model/LiveTv/ChannelType.cs +++ b/MediaBrowser.Model/LiveTv/ChannelType.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Model.LiveTv public enum ChannelType { /// - /// The TV + /// The TV. /// TV, diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs index d1a94d8b3..3c5c39a16 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.Model.LiveTv public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } @@ -67,13 +67,13 @@ namespace MediaBrowser.Model.LiveTv public bool EnableUserData { get; set; } /// - /// Used to specific whether to return news or not + /// Used to specific whether to return news or not. /// /// If set to null, all programs will be returned public bool? IsNews { get; set; } /// - /// Used to specific whether to return movies or not + /// Used to specific whether to return movies or not. /// /// If set to null, all programs will be returned public bool? IsMovie { get; set; } @@ -93,7 +93,7 @@ namespace MediaBrowser.Model.LiveTv public string[] SortBy { get; set; } /// - /// The sort order to return results with + /// The sort order to return results with. /// /// The sort order. public SortOrder? SortOrder { get; set; } diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 264982930..de50adcec 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Model.LiveTv public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } @@ -61,7 +61,7 @@ namespace MediaBrowser.Model.LiveTv public string SeriesTimerId { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs b/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs index bda46dd2b..b899a464b 100644 --- a/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs +++ b/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.Model.LiveTv public class SeriesTimerQuery { /// - /// Gets or sets the sort by - SortName, Priority + /// Gets or sets the sort by - SortName, Priority. /// /// The sort by. public string? SortBy { get; set; } diff --git a/MediaBrowser.Model/Net/NetworkShare.cs b/MediaBrowser.Model/Net/NetworkShare.cs index a40cf73e4..6344cbe21 100644 --- a/MediaBrowser.Model/Net/NetworkShare.cs +++ b/MediaBrowser.Model/Net/NetworkShare.cs @@ -6,27 +6,27 @@ namespace MediaBrowser.Model.Net public class NetworkShare { /// - /// The name of the computer that this share belongs to + /// The name of the computer that this share belongs to. /// public string Server { get; set; } /// - /// Share name + /// Share name. /// public string Name { get; set; } /// - /// Local path + /// Local path. /// public string Path { get; set; } /// - /// Share type + /// Share type. /// public NetworkShareType ShareType { get; set; } /// - /// Comment + /// Comment. /// public string Remark { get; set; } } diff --git a/MediaBrowser.Model/Notifications/NotificationOption.cs b/MediaBrowser.Model/Notifications/NotificationOption.cs index 144949a3b..ea363d9b1 100644 --- a/MediaBrowser.Model/Notifications/NotificationOption.cs +++ b/MediaBrowser.Model/Notifications/NotificationOption.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Model.Notifications public string Type { get; set; } /// - /// User Ids to not monitor (it's opt out) + /// User Ids to not monitor (it's opt out). /// public string[] DisabledMonitorUsers { get; set; } diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index d7cc5ebbe..731d22aaf 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -8,198 +8,198 @@ namespace MediaBrowser.Model.Querying public enum ItemFields { /// - /// The air time + /// The air time. /// AirTime, /// - /// The can delete + /// The can delete. /// CanDelete, /// - /// The can download + /// The can download. /// CanDownload, /// - /// The channel information + /// The channel information. /// ChannelInfo, /// - /// The chapters + /// The chapters. /// Chapters, ChildCount, /// - /// The cumulative run time ticks + /// The cumulative run time ticks. /// CumulativeRunTimeTicks, /// - /// The custom rating + /// The custom rating. /// CustomRating, /// - /// The date created of the item + /// The date created of the item. /// DateCreated, /// - /// The date last media added + /// The date last media added. /// DateLastMediaAdded, /// - /// Item display preferences + /// Item display preferences. /// DisplayPreferencesId, /// - /// The etag + /// The etag. /// Etag, /// - /// The external urls + /// The external urls. /// ExternalUrls, /// - /// Genres + /// Genres. /// Genres, /// - /// The home page URL + /// The home page URL. /// HomePageUrl, /// - /// The item counts + /// The item counts. /// ItemCounts, /// - /// The media source count + /// The media source count. /// MediaSourceCount, /// - /// The media versions + /// The media versions. /// MediaSources, OriginalTitle, /// - /// The item overview + /// The item overview. /// Overview, /// - /// The id of the item's parent + /// The id of the item's parent. /// ParentId, /// - /// The physical path of the item + /// The physical path of the item. /// Path, /// - /// The list of people for the item + /// The list of people for the item. /// People, PlayAccess, /// - /// The production locations + /// The production locations. /// ProductionLocations, /// - /// Imdb, tmdb, etc + /// Imdb, tmdb, etc. /// ProviderIds, /// - /// The aspect ratio of the primary image + /// The aspect ratio of the primary image. /// PrimaryImageAspectRatio, RecursiveItemCount, /// - /// The settings + /// The settings. /// Settings, /// - /// The screenshot image tags + /// The screenshot image tags. /// ScreenshotImageTags, SeriesPrimaryImage, /// - /// The series studio + /// The series studio. /// SeriesStudio, /// - /// The sort name of the item + /// The sort name of the item. /// SortName, /// - /// The special episode numbers + /// The special episode numbers. /// SpecialEpisodeNumbers, /// - /// The studios of the item + /// The studios of the item. /// Studios, BasicSyncInfo, /// - /// The synchronize information + /// The synchronize information. /// SyncInfo, /// - /// The taglines of the item + /// The taglines of the item. /// Taglines, /// - /// The tags + /// The tags. /// Tags, /// - /// The trailer url of the item + /// The trailer url of the item. /// RemoteTrailers, /// - /// The media streams + /// The media streams. /// MediaStreams, /// - /// The season user data + /// The season user data. /// SeasonUserData, /// - /// The service name + /// The service name. /// ServiceName, ThemeSongIds, diff --git a/MediaBrowser.Model/Querying/ItemSortBy.cs b/MediaBrowser.Model/Querying/ItemSortBy.cs index edf71c1a7..0b846bb96 100644 --- a/MediaBrowser.Model/Querying/ItemSortBy.cs +++ b/MediaBrowser.Model/Querying/ItemSortBy.cs @@ -3,7 +3,7 @@ namespace MediaBrowser.Model.Querying { /// - /// These represent sort orders that are known by the core + /// These represent sort orders that are known by the core. /// public static class ItemSortBy { diff --git a/MediaBrowser.Model/Querying/NextUpQuery.cs b/MediaBrowser.Model/Querying/NextUpQuery.cs index 0df86cb22..ee13ffc16 100644 --- a/MediaBrowser.Model/Querying/NextUpQuery.cs +++ b/MediaBrowser.Model/Querying/NextUpQuery.cs @@ -33,13 +33,13 @@ namespace MediaBrowser.Model.Querying public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } diff --git a/MediaBrowser.Model/Querying/QueryResult.cs b/MediaBrowser.Model/Querying/QueryResult.cs index 42586243d..490f48b84 100644 --- a/MediaBrowser.Model/Querying/QueryResult.cs +++ b/MediaBrowser.Model/Querying/QueryResult.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Querying public IReadOnlyList Items { get; set; } /// - /// The total number of records available + /// The total number of records available. /// /// The total record count. public int TotalRecordCount { get; set; } diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs index ed1aa7ac6..12d537492 100644 --- a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs +++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs @@ -26,13 +26,13 @@ namespace MediaBrowser.Model.Querying public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } /// - /// Fields to return within the items, in addition to basic information + /// Fields to return within the items, in addition to basic information. /// /// The fields. public ItemFields[] Fields { get; set; } diff --git a/MediaBrowser.Model/Search/SearchQuery.cs b/MediaBrowser.Model/Search/SearchQuery.cs index 4470f1ad9..c58b13c35 100644 --- a/MediaBrowser.Model/Search/SearchQuery.cs +++ b/MediaBrowser.Model/Search/SearchQuery.cs @@ -8,7 +8,7 @@ namespace MediaBrowser.Model.Search public class SearchQuery { /// - /// The user to localize search results for + /// The user to localize search results for. /// /// The user id. public Guid UserId { get; set; } @@ -26,7 +26,7 @@ namespace MediaBrowser.Model.Search public int? StartIndex { get; set; } /// - /// The maximum number of items to return + /// The maximum number of items to return. /// /// The limit. public int? Limit { get; set; } diff --git a/MediaBrowser.Model/Services/ApiMemberAttribute.cs b/MediaBrowser.Model/Services/ApiMemberAttribute.cs index 7c23eee44..63f3ecd55 100644 --- a/MediaBrowser.Model/Services/ApiMemberAttribute.cs +++ b/MediaBrowser.Model/Services/ApiMemberAttribute.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Model.Services public string Route { get; set; } /// - /// Whether to exclude this property from being included in the ModelSchema + /// Whether to exclude this property from being included in the ModelSchema. /// public bool ExcludeInSchema { get; set; } } diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs index f413f1e17..d8eddf27c 100644 --- a/MediaBrowser.Model/Services/IRequest.cs +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Model.Services string Verb { get; } /// - /// The request ContentType + /// The request ContentType. /// string ContentType { get; } @@ -32,7 +32,7 @@ namespace MediaBrowser.Model.Services string UserAgent { get; } /// - /// The expected Response ContentType for this request + /// The expected Response ContentType for this request. /// string ResponseContentType { get; set; } @@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Services string RemoteIp { get; } /// - /// The value of the Authorization Header used to send the Api Key, null if not available + /// The value of the Authorization Header used to send the Api Key, null if not available. /// string Authorization { get; } @@ -68,7 +68,7 @@ namespace MediaBrowser.Model.Services long ContentLength { get; } /// - /// The value of the Referrer, null if not available + /// The value of the Referrer, null if not available. /// Uri UrlReferrer { get; } } diff --git a/MediaBrowser.Model/Services/IRequiresRequestStream.cs b/MediaBrowser.Model/Services/IRequiresRequestStream.cs index 622626edc..3e5f2da42 100644 --- a/MediaBrowser.Model/Services/IRequiresRequestStream.cs +++ b/MediaBrowser.Model/Services/IRequiresRequestStream.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Services public interface IRequiresRequestStream { /// - /// The raw Http Request Input Stream + /// The raw Http Request Input Stream. /// Stream RequestStream { get; set; } } diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs index 62b68b49e..66775e735 100644 --- a/MediaBrowser.Model/Session/PlayRequest.cs +++ b/MediaBrowser.Model/Session/PlayRequest.cs @@ -7,7 +7,7 @@ using MediaBrowser.Model.Services; namespace MediaBrowser.Model.Session { /// - /// Class PlayRequest + /// Class PlayRequest. /// public class PlayRequest { @@ -19,7 +19,7 @@ namespace MediaBrowser.Model.Session public Guid[] ItemIds { get; set; } /// - /// Gets or sets the start position ticks that the first item should be played at + /// Gets or sets the start position ticks that the first item should be played at. /// /// The start position ticks. [ApiMember(Name = "StartPositionTicks", Description = "The starting position of the first item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] diff --git a/MediaBrowser.Model/Sync/SyncCategory.cs b/MediaBrowser.Model/Sync/SyncCategory.cs index 215ac301e..80ad5f56e 100644 --- a/MediaBrowser.Model/Sync/SyncCategory.cs +++ b/MediaBrowser.Model/Sync/SyncCategory.cs @@ -5,15 +5,15 @@ namespace MediaBrowser.Model.Sync public enum SyncCategory { /// - /// The latest + /// The latest. /// Latest = 0, /// - /// The next up + /// The next up. /// NextUp = 1, /// - /// The resume + /// The resume. /// Resume = 2 } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index a67c38c3a..18ca74ee3 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Model.System }; /// - /// Class SystemInfo + /// Class SystemInfo. /// public class SystemInfo : PublicSystemInfo { diff --git a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs index c79d7fe75..b08acba2c 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Model.Tasks double? CurrentProgress { get; } /// - /// Gets the triggers that define when the task will run + /// Gets the triggers that define when the task will run. /// /// The triggers. /// value diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index 4a7f579ec..363773ff7 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Tasks public interface ITaskManager : IDisposable { /// - /// Gets the list of Scheduled Tasks + /// Gets the list of Scheduled Tasks. /// /// The scheduled tasks. IScheduledTaskWorker[] ScheduledTasks { get; } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 3c94f6215..b16462936 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -24,19 +24,19 @@ using Season = MediaBrowser.Controller.Entities.TV.Season; namespace MediaBrowser.Providers.Manager { /// - /// Class ImageSaver + /// Class ImageSaver. /// public class ImageSaver { private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// - /// The _config + /// The _config. /// private readonly IServerConfigurationManager _config; /// - /// The _directory watchers + /// The _directory watchers. /// private readonly ILibraryMonitor _libraryMonitor; private readonly IFileSystem _fileSystem; diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 7901503d3..1091c3326 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -168,7 +168,7 @@ namespace MediaBrowser.Providers.Manager } /// - /// Image types that are only one per item + /// Image types that are only one per item. /// private readonly ImageType[] _singularImages = { @@ -189,7 +189,7 @@ namespace MediaBrowser.Providers.Manager } /// - /// Determines if an item already contains the given images + /// Determines if an item already contains the given images. /// /// The item. /// The images. diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 5853c7714..989a4b5d1 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -38,7 +38,7 @@ using Series = MediaBrowser.Controller.Entities.TV.Series; namespace MediaBrowser.Providers.Manager { /// - /// Class ProviderManager + /// Class ProviderManager. /// public class ProviderManager : IProviderManager, IDisposable { diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index ba87e0570..8f3df2760 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.IO; namespace MediaBrowser.Providers.MediaInfo { /// - /// Uses ffmpeg to create video images + /// Uses ffmpeg to create video images. /// public class AudioImageProvider : IDynamicImageProvider { diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 73c89e815..de377086a 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -99,7 +99,7 @@ namespace MediaBrowser.Providers.MediaInfo } /// - /// Fetches data from the tags dictionary + /// Fetches data from the tags dictionary. /// /// The audio. /// The data. diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index ccbe27c1f..29e6d7854 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -342,7 +342,7 @@ namespace MediaBrowser.Providers.MediaInfo } /// - /// Gets information about the longest playlist on a bdrom + /// Gets information about the longest playlist on a bdrom. /// /// The path. /// VideoStream. diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/MovieResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/MovieResult.cs index 51c26a61c..c0a880bc9 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/MovieResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/MovieResult.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Search /// The vote_average. public double Vote_Average { get; set; } /// - /// For collection search results + /// For collection search results. /// public string Name { get; set; } /// diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index faeb48b12..3c0922f39 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -25,7 +25,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { /// - /// Class MovieDbProvider + /// Class MovieDbProvider. /// public class TmdbMovieProvider : IRemoteMetadataProvider, IHasOrder { @@ -129,7 +129,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies public string Name => TmdbUtils.ProviderName; /// - /// The _TMDB settings task + /// The _TMDB settings task. /// private TmdbSettingsResult _tmdbSettings; diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index aabad3ada..26259f1aa 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.TV /// /// Returns true if a series has any seasons or episodes without season or episode numbers - /// If this data is missing no virtual items will be added in order to prevent possible duplicates + /// If this data is missing no virtual items will be added in order to prevent possible duplicates. /// private bool HasInvalidContent(IList allItems) { @@ -171,7 +171,7 @@ namespace MediaBrowser.Providers.TV } /// - /// Removes the virtual entry after a corresponding physical version has been added + /// Removes the virtual entry after a corresponding physical version has been added. /// private bool RemoveObsoleteOrMissingEpisodes( IEnumerable allRecursiveChildren, diff --git a/RSSDP/DiscoveredSsdpDevice.cs b/RSSDP/DiscoveredSsdpDevice.cs index 1244ce523..d7561fc93 100644 --- a/RSSDP/DiscoveredSsdpDevice.cs +++ b/RSSDP/DiscoveredSsdpDevice.cs @@ -55,7 +55,7 @@ namespace Rssdp } /// - /// Returns the headers from the SSDP device response message + /// Returns the headers from the SSDP device response message. /// public HttpHeaders ResponseHeaders { get; set; } -- cgit v1.2.3 From e6c197b96991a619d58e816ee56c23644c4a1de1 Mon Sep 17 00:00:00 2001 From: Max Git Date: Tue, 16 Jun 2020 01:09:41 +0200 Subject: Cleanup --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index a055e57ec..be4625505 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; -- cgit v1.2.3 From 247f9c61e60ef774675cb4d6d1734d2ccdc6ee7a Mon Sep 17 00:00:00 2001 From: telans Date: Tue, 16 Jun 2020 09:43:52 +1200 Subject: fix SA1513/SA1516 --- DvdLib/Ifo/Cell.cs | 1 + DvdLib/Ifo/Chapter.cs | 2 + DvdLib/Ifo/Dvd.cs | 1 + DvdLib/Ifo/ProgramChain.cs | 4 + DvdLib/Ifo/Title.cs | 4 + Emby.Dlna/ContentDirectory/ControlHandler.cs | 1 + Emby.Dlna/Didl/DidlBuilder.cs | 3 + Emby.Dlna/DlnaManager.cs | 3 + Emby.Dlna/Eventing/EventManager.cs | 1 + Emby.Dlna/Eventing/EventSubscription.cs | 3 + Emby.Dlna/Main/DlnaEntryPoint.cs | 2 + Emby.Dlna/PlayTo/Device.cs | 2 + Emby.Dlna/PlayTo/PlayToController.cs | 5 + Emby.Dlna/PlayTo/PlayToManager.cs | 1 + Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs | 1 + Emby.Dlna/PlayTo/uBaseObject.cs | 2 + Emby.Dlna/Server/DescriptionXmlBuilder.cs | 5 + Emby.Dlna/Service/BaseControlHandler.cs | 4 + Emby.Dlna/Service/ServiceXmlBuilder.cs | 1 + Emby.Naming/AudioBook/AudioBookFilePathParser.cs | 1 + .../Data/SqliteItemRepository.cs | 115 ++++++++++++++++++++ .../Data/SqliteUserDataRepository.cs | 3 + .../Devices/DeviceManager.cs | 1 + Emby.Server.Implementations/Dto/DtoService.cs | 11 ++ .../HttpServer/HttpListenerHost.cs | 1 + .../HttpServer/RangeRequestWriter.cs | 7 ++ .../HttpServer/Security/AuthService.cs | 1 + .../HttpServer/Security/AuthorizationContext.cs | 2 + .../IO/ManagedFileSystem.cs | 2 + .../Library/ExclusiveLiveStream.cs | 2 + .../Library/LibraryManager.cs | 2 + .../Library/MediaSourceManager.cs | 5 + .../Library/Resolvers/SpecialFolderResolver.cs | 2 + .../Library/Resolvers/TV/EpisodeResolver.cs | 1 + .../Library/SearchEngine.cs | 1 + .../LiveTv/Listings/SchedulesDirect.cs | 118 +++++++++++++++++++++ .../LiveTv/Listings/XmlTvListingsProvider.cs | 1 + .../LiveTv/LiveTvManager.cs | 12 +++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 19 ++++ .../LiveTv/TunerHosts/LiveStream.cs | 3 + .../Playlists/PlaylistManager.cs | 1 + .../ScheduledTasks/ScheduledTaskWorker.cs | 5 + .../Services/ServiceMethod.cs | 1 + .../Services/ServicePath.cs | 3 + .../Services/StringMapTypeDeserializer.cs | 2 + .../Services/SwaggerService.cs | 34 ++++++ .../Session/SessionWebSocketListener.cs | 1 + .../Sorting/PremiereDateComparer.cs | 1 + Emby.Server.Implementations/TV/TVSeriesManager.cs | 1 + Jellyfin.Data/Entities/Artwork.cs | 3 + Jellyfin.Data/Entities/BookMetadata.cs | 1 + Jellyfin.Data/Entities/Chapter.cs | 5 + Jellyfin.Data/Entities/Collection.cs | 2 + Jellyfin.Data/Entities/CollectionItem.cs | 1 + Jellyfin.Data/Entities/Company.cs | 1 + Jellyfin.Data/Entities/CompanyMetadata.cs | 4 + Jellyfin.Data/Entities/Episode.cs | 1 + Jellyfin.Data/Entities/EpisodeMetadata.cs | 3 + Jellyfin.Data/Entities/Genre.cs | 2 + Jellyfin.Data/Entities/Library.cs | 2 + Jellyfin.Data/Entities/LibraryItem.cs | 3 + Jellyfin.Data/Entities/LibraryRoot.cs | 3 + Jellyfin.Data/Entities/MediaFile.cs | 3 + Jellyfin.Data/Entities/MediaFileStream.cs | 2 + Jellyfin.Data/Entities/Metadata.cs | 8 ++ Jellyfin.Data/Entities/MetadataProvider.cs | 2 + Jellyfin.Data/Entities/MetadataProviderId.cs | 2 + Jellyfin.Data/Entities/MovieMetadata.cs | 4 + Jellyfin.Data/Entities/MusicAlbumMetadata.cs | 3 + Jellyfin.Data/Entities/Person.cs | 6 ++ Jellyfin.Data/Entities/PersonRole.cs | 3 + Jellyfin.Data/Entities/Rating.cs | 3 + Jellyfin.Data/Entities/RatingSource.cs | 4 + Jellyfin.Data/Entities/Release.cs | 2 + Jellyfin.Data/Entities/Season.cs | 1 + Jellyfin.Data/Entities/SeasonMetadata.cs | 1 + Jellyfin.Data/Entities/Series.cs | 3 + Jellyfin.Data/Entities/SeriesMetadata.cs | 4 + Jellyfin.Data/Entities/Track.cs | 1 + Jellyfin.Server.Implementations/JellyfinDb.cs | 39 +++++++ MediaBrowser.Api/EnvironmentService.cs | 1 + MediaBrowser.Api/FilterService.cs | 6 ++ MediaBrowser.Api/IHasDtoOptions.cs | 1 + MediaBrowser.Api/Library/LibraryService.cs | 11 ++ MediaBrowser.Api/LiveTv/LiveTvService.cs | 15 +++ MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 + MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 1 + MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 + MediaBrowser.Api/Playback/MediaInfoService.cs | 2 + .../Progressive/BaseProgressiveStreamingService.cs | 6 ++ .../Progressive/ProgressiveStreamWriter.cs | 2 + MediaBrowser.Api/Playback/StreamRequest.cs | 4 + MediaBrowser.Api/Playback/UniversalAudioService.cs | 20 ++++ MediaBrowser.Api/PluginService.cs | 9 ++ MediaBrowser.Api/SimilarItemsHelper.cs | 4 + MediaBrowser.Api/Subtitles/SubtitleService.cs | 2 + MediaBrowser.Api/SuggestionsService.cs | 5 + MediaBrowser.Api/TranscodingJob.cs | 8 ++ MediaBrowser.Api/TvShowsService.cs | 1 + .../UserLibrary/BaseItemsByNameService.cs | 1 + MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 3 + MediaBrowser.Api/UserLibrary/UserViewsService.cs | 3 + .../Authentication/IAuthenticationProvider.cs | 3 + .../Authentication/IPasswordResetProvider.cs | 3 + .../Channels/ChannelItemInfo.cs | 11 ++ .../Collections/CollectionCreationOptions.cs | 1 + MediaBrowser.Controller/Drawing/ImageHelper.cs | 1 + .../Drawing/ImageProcessingOptions.cs | 7 ++ MediaBrowser.Controller/Dto/DtoOptions.cs | 6 ++ .../Entities/AggregateFolder.cs | 1 + MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 + .../Entities/Audio/MusicAlbum.cs | 1 + .../Entities/Audio/MusicArtist.cs | 1 + .../Entities/Audio/MusicGenre.cs | 2 + MediaBrowser.Controller/Entities/AudioBook.cs | 2 + MediaBrowser.Controller/Entities/BaseItem.cs | 16 +++ .../Entities/CollectionFolder.cs | 3 + MediaBrowser.Controller/Entities/Folder.cs | 21 ++++ MediaBrowser.Controller/Entities/Genre.cs | 2 + .../Entities/IHasMediaSources.cs | 2 + .../Entities/IHasProgramAttributes.cs | 8 ++ MediaBrowser.Controller/Entities/IHasSeries.cs | 3 + .../Entities/InternalItemsQuery.cs | 103 ++++++++++++++++++ MediaBrowser.Controller/Entities/LinkedChild.cs | 3 + MediaBrowser.Controller/Entities/PeopleHelper.cs | 1 + MediaBrowser.Controller/Entities/Person.cs | 2 + MediaBrowser.Controller/Entities/Photo.cs | 11 ++ MediaBrowser.Controller/Entities/Share.cs | 1 + MediaBrowser.Controller/Entities/Studio.cs | 2 + MediaBrowser.Controller/Entities/TV/Episode.cs | 6 ++ MediaBrowser.Controller/Entities/TV/Season.cs | 1 + MediaBrowser.Controller/Entities/TV/Series.cs | 2 + MediaBrowser.Controller/Entities/UserItemData.cs | 1 + .../Entities/UserViewBuilder.cs | 2 + MediaBrowser.Controller/Entities/Video.cs | 10 ++ MediaBrowser.Controller/Entities/Year.cs | 1 + MediaBrowser.Controller/IO/FileData.cs | 3 + MediaBrowser.Controller/Library/DeleteOptions.cs | 1 + MediaBrowser.Controller/Library/ILiveStream.cs | 5 + MediaBrowser.Controller/Library/ItemResolveArgs.cs | 2 + .../Library/PlaybackProgressEventArgs.cs | 9 ++ MediaBrowser.Controller/Library/Profiler.cs | 1 + MediaBrowser.Controller/Library/TVUtils.cs | 1 + MediaBrowser.Controller/LiveTv/ChannelInfo.cs | 3 + MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 3 + MediaBrowser.Controller/LiveTv/ITunerHost.cs | 1 + .../LiveTv/LiveTvConflictException.cs | 1 + MediaBrowser.Controller/LiveTv/ProgramInfo.cs | 1 + MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs | 1 + MediaBrowser.Controller/LiveTv/TimerInfo.cs | 7 ++ .../LiveTv/TunerChannelMapping.cs | 3 + .../MediaEncoding/EncodingHelper.cs | 28 +++++ .../MediaEncoding/EncodingJobInfo.cs | 8 ++ .../MediaEncoding/EncodingJobOptions.cs | 10 ++ .../MediaEncoding/MediaInfoRequest.cs | 4 + .../Net/AuthenticatedAttribute.cs | 3 + .../Net/BasePeriodicWebSocketListener.cs | 2 + MediaBrowser.Controller/Net/StaticResultOptions.cs | 5 + .../Providers/ImageRefreshOptions.cs | 2 + .../Providers/MetadataResult.cs | 1 + MediaBrowser.Controller/Resolvers/IItemResolver.cs | 1 + .../Security/AuthenticationInfo.cs | 1 + .../Session/AuthenticationRequest.cs | 8 ++ MediaBrowser.Controller/Session/SessionInfo.cs | 5 + .../Subtitles/SubtitleResponse.cs | 3 + .../Subtitles/SubtitleSearchRequest.cs | 12 +++ MediaBrowser.Controller/Sync/SyncedFileInfo.cs | 1 + MediaBrowser.Controller/SyncPlay/GroupInfo.cs | 1 + .../Images/EpisodeLocalImageProvider.cs | 1 + .../Parsers/BaseItemXmlParser.cs | 48 +++++++++ .../Parsers/BoxSetXmlParser.cs | 2 + .../Parsers/PlaylistXmlParser.cs | 2 + MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 7 ++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + .../Probing/ProbeResultNormalizer.cs | 13 +++ MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 4 + MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 5 + MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 4 + .../Subtitles/SubtitleEncoder.cs | 9 ++ MediaBrowser.Model/Configuration/LibraryOptions.cs | 23 ++++ .../Configuration/UserConfiguration.cs | 4 + .../Configuration/XbmcMetadataOptions.cs | 1 + MediaBrowser.Model/Dlna/AudioOptions.cs | 1 + MediaBrowser.Model/Dlna/DeviceProfile.cs | 21 ++++ .../Dlna/MediaFormatProfileResolver.cs | 13 +++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 21 ++++ MediaBrowser.Model/Dlna/StreamInfo.cs | 20 ++++ MediaBrowser.Model/Dto/BaseItemDto.cs | 25 +++++ MediaBrowser.Model/Dto/MediaSourceInfo.cs | 21 ++++ MediaBrowser.Model/Dto/MetadataEditorInfo.cs | 4 + MediaBrowser.Model/Dto/NameIdPair.cs | 1 + MediaBrowser.Model/Entities/MediaStream.cs | 13 +++ MediaBrowser.Model/Entities/MediaUrl.cs | 1 + MediaBrowser.Model/Entities/VirtualFolderInfo.cs | 1 + MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs | 1 + MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs | 2 + MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 34 ++++++ MediaBrowser.Model/LiveTv/RecordingQuery.cs | 9 ++ MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs | 11 ++ MediaBrowser.Model/MediaInfo/MediaInfo.cs | 8 ++ .../MediaInfo/PlaybackInfoRequest.cs | 6 ++ MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs | 10 ++ MediaBrowser.Model/Providers/SubtitleOptions.cs | 6 ++ .../Providers/SubtitleProviderInfo.cs | 1 + MediaBrowser.Model/Querying/QueryFilters.cs | 5 + MediaBrowser.Model/Search/SearchHint.cs | 1 + MediaBrowser.Model/Search/SearchQuery.cs | 7 ++ MediaBrowser.Model/Services/IRequest.cs | 4 + MediaBrowser.Model/Services/IService.cs | 2 + MediaBrowser.Model/Session/ClientCapabilities.cs | 4 + MediaBrowser.Model/Session/PlayRequest.cs | 3 + MediaBrowser.Model/Session/PlaybackProgressInfo.cs | 2 + MediaBrowser.Model/Session/PlaybackStopInfo.cs | 1 + MediaBrowser.Model/Session/TranscodingInfo.cs | 8 ++ MediaBrowser.Model/Sync/SyncJob.cs | 2 + MediaBrowser.Model/Users/UserAction.cs | 6 ++ MediaBrowser.Model/Users/UserPolicy.cs | 20 ++++ MediaBrowser.Providers/Manager/ImageSaver.cs | 5 + .../Manager/ItemImageProvider.cs | 3 + MediaBrowser.Providers/Manager/MetadataService.cs | 7 ++ MediaBrowser.Providers/Manager/ProviderManager.cs | 1 + MediaBrowser.Providers/Manager/ProviderUtils.cs | 1 + .../MediaInfo/AudioImageProvider.cs | 1 + .../MediaInfo/FFProbeVideoInfo.cs | 3 + .../MediaInfo/VideoImageProvider.cs | 2 + .../Movies/MovieMetadataService.cs | 2 + .../Movies/TrailerMetadataService.cs | 2 + .../Playlists/PlaylistItemsProvider.cs | 4 + .../Plugins/AudioDb/AlbumProvider.cs | 37 +++++++ .../Plugins/AudioDb/ArtistProvider.cs | 40 +++++++ .../Plugins/MusicBrainz/AlbumProvider.cs | 13 +++ .../Plugins/MusicBrainz/ArtistProvider.cs | 6 ++ .../Plugins/Omdb/OmdbItemProvider.cs | 22 ++++ .../Tmdb/Models/Collections/CollectionImages.cs | 1 + .../Tmdb/Models/Collections/CollectionResult.cs | 6 ++ .../Plugins/Tmdb/Models/Collections/Part.cs | 4 + .../Plugins/Tmdb/Models/General/Backdrop.cs | 6 ++ .../Plugins/Tmdb/Models/General/Crew.cs | 5 + .../Plugins/Tmdb/Models/General/ExternalIds.cs | 4 + .../Plugins/Tmdb/Models/General/Genre.cs | 1 + .../Plugins/Tmdb/Models/General/Images.cs | 1 + .../Plugins/Tmdb/Models/General/Keyword.cs | 1 + .../Plugins/Tmdb/Models/General/Poster.cs | 6 ++ .../Plugins/Tmdb/Models/General/Profile.cs | 4 + .../Plugins/Tmdb/Models/General/Still.cs | 7 ++ .../Plugins/Tmdb/Models/General/Video.cs | 7 ++ .../Tmdb/Models/Movies/BelongsToCollection.cs | 3 + .../Plugins/Tmdb/Models/Movies/Cast.cs | 5 + .../Plugins/Tmdb/Models/Movies/Casts.cs | 1 + .../Plugins/Tmdb/Models/Movies/Country.cs | 2 + .../Plugins/Tmdb/Models/Movies/MovieResult.cs | 29 +++++ .../Tmdb/Models/Movies/ProductionCompany.cs | 1 + .../Tmdb/Models/Movies/ProductionCountry.cs | 1 + .../Plugins/Tmdb/Models/Movies/SpokenLanguage.cs | 1 + .../Plugins/Tmdb/Models/Movies/Youtube.cs | 2 + .../Plugins/Tmdb/Models/People/PersonResult.cs | 13 +++ .../Plugins/Tmdb/Models/Search/TvResult.cs | 8 ++ .../Plugins/Tmdb/Models/TV/Cast.cs | 5 + .../Plugins/Tmdb/Models/TV/ContentRating.cs | 1 + .../Plugins/Tmdb/Models/TV/CreatedBy.cs | 2 + .../Plugins/Tmdb/Models/TV/Credits.cs | 1 + .../Plugins/Tmdb/Models/TV/Episode.cs | 7 ++ .../Plugins/Tmdb/Models/TV/EpisodeCredits.cs | 2 + .../Plugins/Tmdb/Models/TV/EpisodeResult.cs | 13 +++ .../Plugins/Tmdb/Models/TV/GuestStar.cs | 5 + .../Plugins/Tmdb/Models/TV/Network.cs | 1 + .../Plugins/Tmdb/Models/TV/Season.cs | 4 + .../Plugins/Tmdb/Models/TV/SeasonResult.cs | 10 ++ .../Plugins/Tmdb/Models/TV/SeriesResult.cs | 29 +++++ .../Plugins/Tmdb/Movies/TmdbImageProvider.cs | 3 + .../Plugins/Tmdb/Movies/TmdbSettings.cs | 3 + .../Plugins/Tmdb/People/TmdbPersonImageProvider.cs | 3 + .../Plugins/Tmdb/People/TmdbPersonProvider.cs | 1 + .../Subtitles/SubtitleManager.cs | 1 + MediaBrowser.Providers/TV/DummySeasonProvider.cs | 1 + MediaBrowser.Providers/TV/SeriesMetadataService.cs | 2 + RSSDP/DiscoveredSsdpDevice.cs | 1 + RSSDP/HttpParserBase.cs | 1 + RSSDP/SsdpCommunicationsServer.cs | 1 + RSSDP/SsdpDevice.cs | 4 + RSSDP/SsdpDeviceLocator.cs | 1 + RSSDP/SsdpDevicePublisher.cs | 3 + RSSDP/SsdpEmbeddedDevice.cs | 1 + 283 files changed, 1810 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Cell.cs b/DvdLib/Ifo/Cell.cs index 2eab400f7..ea0b50e43 100644 --- a/DvdLib/Ifo/Cell.cs +++ b/DvdLib/Ifo/Cell.cs @@ -7,6 +7,7 @@ namespace DvdLib.Ifo public class Cell { public CellPlaybackInfo PlaybackInfo { get; private set; } + public CellPositionInfo PositionInfo { get; private set; } internal void ParsePlayback(BinaryReader br) diff --git a/DvdLib/Ifo/Chapter.cs b/DvdLib/Ifo/Chapter.cs index 1e69429f8..e786cb553 100644 --- a/DvdLib/Ifo/Chapter.cs +++ b/DvdLib/Ifo/Chapter.cs @@ -5,7 +5,9 @@ namespace DvdLib.Ifo public class Chapter { public ushort ProgramChainNumber { get; private set; } + public ushort ProgramNumber { get; private set; } + public uint ChapterNumber { get; private set; } public Chapter(ushort pgcNum, ushort programNum, uint chapterNum) diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index ca20baa73..1252bab50 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -125,6 +125,7 @@ namespace DvdLib.Ifo if (titleNum + 1 < numTitles && vtsFs.Position == (baseAddr + offsets[titleNum + 1])) break; chapNum++; } + while (vtsFs.Position < (baseAddr + endaddr)); } diff --git a/DvdLib/Ifo/ProgramChain.cs b/DvdLib/Ifo/ProgramChain.cs index 4860360af..8048f4bbd 100644 --- a/DvdLib/Ifo/ProgramChain.cs +++ b/DvdLib/Ifo/ProgramChain.cs @@ -22,7 +22,9 @@ namespace DvdLib.Ifo public readonly List Cells; public DvdTime PlaybackTime { get; private set; } + public UserOperation ProhibitedUserOperations { get; private set; } + public byte[] AudioStreamControl { get; private set; } // 8*2 entries public byte[] SubpictureStreamControl { get; private set; } // 32*4 entries @@ -33,9 +35,11 @@ namespace DvdLib.Ifo private ushort _goupProgramNumber; public ProgramPlaybackMode PlaybackMode { get; private set; } + public uint ProgramCount { get; private set; } public byte StillTime { get; private set; } + public byte[] Palette { get; private set; } // 16*4 entries private ushort _commandTableOffset; diff --git a/DvdLib/Ifo/Title.cs b/DvdLib/Ifo/Title.cs index abf806d2c..4af3af754 100644 --- a/DvdLib/Ifo/Title.cs +++ b/DvdLib/Ifo/Title.cs @@ -8,8 +8,11 @@ namespace DvdLib.Ifo public class Title { public uint TitleNumber { get; private set; } + public uint AngleCount { get; private set; } + public ushort ChapterCount { get; private set; } + public byte VideoTitleSetNumber { get; private set; } private ushort _parentalManagementMask; @@ -17,6 +20,7 @@ namespace DvdLib.Ifo private uint _vtsStartSector; // relative to start of entire disk public ProgramChain EntryProgramChain { get; private set; } + public readonly List ProgramChains; public readonly List Chapters; diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index de6b619ba..291de5245 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -1357,6 +1357,7 @@ namespace Emby.Dlna.ContentDirectory internal class ServerItem { public BaseItem Item { get; set; } + public StubType? StubType { get; set; } public ServerItem(BaseItem item) diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 6ded76f7d..aa7a11815 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -765,6 +765,7 @@ namespace Emby.Dlna.Didl { AddValue(writer, "dc", "rating", item.OfficialRating, NS_DC); } + if (filter.Contains("upnp:rating")) { AddValue(writer, "upnp", "rating", item.OfficialRating, NS_UPNP); @@ -1052,10 +1053,12 @@ namespace Emby.Dlna.Didl { return GetImageInfo(item, ImageType.Primary); } + if (item.HasImage(ImageType.Thumb)) { return GetImageInfo(item, ImageType.Thumb); } + if (item.HasImage(ImageType.Backdrop)) { if (item is Channel) diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index e5f483950..ef8df854b 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -438,6 +438,7 @@ namespace Emby.Dlna { throw new ArgumentException("Profile is missing Id"); } + if (string.IsNullOrEmpty(profile.Name)) { throw new ArgumentException("Profile is missing Name"); @@ -463,6 +464,7 @@ namespace Emby.Dlna { _profiles[path] = new Tuple(GetInternalProfileInfo(_fileSystem.GetFileInfo(path), type), profile); } + SerializeToXml(profile, path); } @@ -492,6 +494,7 @@ namespace Emby.Dlna class InternalProfileInfo { internal DeviceProfileInfo Info { get; set; } + internal string Path { get; set; } } diff --git a/Emby.Dlna/Eventing/EventManager.cs b/Emby.Dlna/Eventing/EventManager.cs index 5a51569e2..edccfd190 100644 --- a/Emby.Dlna/Eventing/EventManager.cs +++ b/Emby.Dlna/Eventing/EventManager.cs @@ -150,6 +150,7 @@ namespace Emby.Dlna.Eventing builder.Append(""); builder.Append(""); } + builder.Append(""); var options = new HttpRequestOptions diff --git a/Emby.Dlna/Eventing/EventSubscription.cs b/Emby.Dlna/Eventing/EventSubscription.cs index 51eaee9d7..40d73ee0e 100644 --- a/Emby.Dlna/Eventing/EventSubscription.cs +++ b/Emby.Dlna/Eventing/EventSubscription.cs @@ -7,10 +7,13 @@ namespace Emby.Dlna.Eventing public class EventSubscription { public string Id { get; set; } + public string CallbackUrl { get; set; } + public string NotificationType { get; set; } public DateTime SubscriptionTime { get; set; } + public int TimeoutSeconds { get; set; } public long TriggerCount { get; set; } diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index a7b1d384d..b965a09b9 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -320,6 +320,7 @@ namespace Emby.Dlna.Main { guid = text.GetMD5(); } + return guid.ToString("N", CultureInfo.InvariantCulture); } @@ -388,6 +389,7 @@ namespace Emby.Dlna.Main { _logger.LogError(ex, "Error disposing PlayTo manager"); } + _manager = null; } } diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 86b72e264..12757a123 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -37,6 +37,7 @@ namespace Emby.Dlna.PlayTo RefreshVolumeIfNeeded().GetAwaiter().GetResult(); return _volume; } + set => _volume = value; } @@ -494,6 +495,7 @@ namespace Emby.Dlna.PlayTo return; } } + RestartTimerInactive(); } } diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index f1c69196a..92a93d434 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -425,6 +425,7 @@ namespace Emby.Dlna.PlayTo await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false); return; } + await SeekAfterTransportChange(newPosition, CancellationToken.None).ConfigureAwait(false); } } @@ -713,6 +714,7 @@ namespace Emby.Dlna.PlayTo throw new ArgumentException("Volume argument cannot be null"); } + default: return Task.CompletedTask; } @@ -798,12 +800,15 @@ namespace Emby.Dlna.PlayTo public int? SubtitleStreamIndex { get; set; } public string DeviceProfileId { get; set; } + public string DeviceId { get; set; } public string MediaSourceId { get; set; } + public string LiveStreamId { get; set; } public BaseItem Item { get; set; } + private MediaSourceInfo MediaSource; private IMediaSourceManager _mediaSourceManager; diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index c0500eb68..240c8a7d9 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -132,6 +132,7 @@ namespace Emby.Dlna.PlayTo usn = usn.Substring(index); found = true; } + index = usn.IndexOf("::", StringComparison.OrdinalIgnoreCase); if (index != -1) { diff --git a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs index 3b169e599..fa42b80e8 100644 --- a/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs +++ b/Emby.Dlna/PlayTo/PlaybackStoppedEventArgs.cs @@ -12,6 +12,7 @@ namespace Emby.Dlna.PlayTo public class MediaChangedEventArgs : EventArgs { public uBaseObject OldMediaInfo { get; set; } + public uBaseObject NewMediaInfo { get; set; } } } diff --git a/Emby.Dlna/PlayTo/uBaseObject.cs b/Emby.Dlna/PlayTo/uBaseObject.cs index a8ed5692c..05c19299f 100644 --- a/Emby.Dlna/PlayTo/uBaseObject.cs +++ b/Emby.Dlna/PlayTo/uBaseObject.cs @@ -44,10 +44,12 @@ namespace Emby.Dlna.PlayTo { return MediaBrowser.Model.Entities.MediaType.Audio; } + if (classType.IndexOf(MediaBrowser.Model.Entities.MediaType.Video, StringComparison.Ordinal) != -1) { return MediaBrowser.Model.Entities.MediaType.Video; } + if (classType.IndexOf("image", StringComparison.Ordinal) != -1) { return MediaBrowser.Model.Entities.MediaType.Photo; diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 5ecc81a2f..7143c3109 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -134,6 +134,7 @@ namespace Emby.Dlna.Server return result; } } + return c.ToString(CultureInfo.InvariantCulture); } @@ -157,18 +158,22 @@ namespace Emby.Dlna.Server { break; } + if (stringBuilder == null) { stringBuilder = new StringBuilder(); } + stringBuilder.Append(str, num, num2 - num); stringBuilder.Append(GetEscapeSequence(str[num2])); num = num2 + 1; } + if (stringBuilder == null) { return str; } + stringBuilder.Append(str, num, length - num); return stringBuilder.ToString(); } diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 161a3434c..699d325ea 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -18,6 +18,7 @@ namespace Emby.Dlna.Service private const string NS_SOAPENV = "http://schemas.xmlsoap.org/soap/envelope/"; protected IServerConfigurationManager Config { get; } + protected ILogger Logger { get; } protected BaseControlHandler(IServerConfigurationManager config, ILogger logger) @@ -135,6 +136,7 @@ namespace Emby.Dlna.Service break; } + default: { await reader.SkipAsync().ConfigureAwait(false); @@ -211,7 +213,9 @@ namespace Emby.Dlna.Service private class ControlRequestInfo { public string LocalName { get; set; } + public string NamespaceURI { get; set; } + public Dictionary Headers { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); } diff --git a/Emby.Dlna/Service/ServiceXmlBuilder.cs b/Emby.Dlna/Service/ServiceXmlBuilder.cs index 62ffd9e42..af557aa14 100644 --- a/Emby.Dlna/Service/ServiceXmlBuilder.cs +++ b/Emby.Dlna/Service/ServiceXmlBuilder.cs @@ -80,6 +80,7 @@ namespace Emby.Dlna.Service { builder.Append("" + DescriptionXmlBuilder.Escape(allowedValue) + ""); } + builder.Append(""); } diff --git a/Emby.Naming/AudioBook/AudioBookFilePathParser.cs b/Emby.Naming/AudioBook/AudioBookFilePathParser.cs index 5494df9d6..3c874c62c 100644 --- a/Emby.Naming/AudioBook/AudioBookFilePathParser.cs +++ b/Emby.Naming/AudioBook/AudioBookFilePathParser.cs @@ -64,6 +64,7 @@ namespace Emby.Naming.AudioBook { result.ChapterNumber = int.Parse(matches[0].Groups[0].Value); } + if (matches.Count > 1) { result.PartNumber = int.Parse(matches[matches.Count - 1].Groups[0].Value); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d33125661..f09ecaa29 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -793,6 +793,7 @@ namespace Emby.Server.Implementations.Data { saveItemStatement.TryBindNull("@Width"); } + if (item.Height > 0) { saveItemStatement.TryBind("@Height", item.Height); @@ -932,6 +933,7 @@ namespace Emby.Server.Implementations.Data { saveItemStatement.TryBindNull("@SeriesName"); } + if (string.IsNullOrWhiteSpace(userDataKey)) { saveItemStatement.TryBindNull("@UserDataKey"); @@ -1007,6 +1009,7 @@ namespace Emby.Server.Implementations.Data { artists = string.Join("|", hasArtists.Artists); } + saveItemStatement.TryBind("@Artists", artists); string albumArtists = null; @@ -1106,6 +1109,7 @@ namespace Emby.Server.Implementations.Data { continue; } + str.Append(ToValueString(i) + "|"); } @@ -1366,6 +1370,7 @@ namespace Emby.Server.Implementations.Data hasStartDate.StartDate = reader[index].ReadDateTime(); } } + index++; } @@ -1373,12 +1378,14 @@ namespace Emby.Server.Implementations.Data { item.EndDate = reader[index].TryReadDateTime(); } + index++; if (!reader.IsDBNull(index)) { item.ChannelId = new Guid(reader.GetString(index)); } + index++; if (enableProgramAttributes) @@ -1389,24 +1396,28 @@ namespace Emby.Server.Implementations.Data { hasProgramAttributes.IsMovie = reader.GetBoolean(index); } + index++; if (!reader.IsDBNull(index)) { hasProgramAttributes.IsSeries = reader.GetBoolean(index); } + index++; if (!reader.IsDBNull(index)) { hasProgramAttributes.EpisodeTitle = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { hasProgramAttributes.IsRepeat = reader.GetBoolean(index); } + index++; } else @@ -1419,6 +1430,7 @@ namespace Emby.Server.Implementations.Data { item.CommunityRating = reader.GetFloat(index); } + index++; if (HasField(query, ItemFields.CustomRating)) @@ -1427,6 +1439,7 @@ namespace Emby.Server.Implementations.Data { item.CustomRating = reader.GetString(index); } + index++; } @@ -1434,6 +1447,7 @@ namespace Emby.Server.Implementations.Data { item.IndexNumber = reader.GetInt32(index); } + index++; if (HasField(query, ItemFields.Settings)) @@ -1442,18 +1456,21 @@ namespace Emby.Server.Implementations.Data { item.IsLocked = reader.GetBoolean(index); } + index++; if (!reader.IsDBNull(index)) { item.PreferredMetadataLanguage = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { item.PreferredMetadataCountryCode = reader.GetString(index); } + index++; } @@ -1463,6 +1480,7 @@ namespace Emby.Server.Implementations.Data { item.Width = reader.GetInt32(index); } + index++; } @@ -1472,6 +1490,7 @@ namespace Emby.Server.Implementations.Data { item.Height = reader.GetInt32(index); } + index++; } @@ -1481,6 +1500,7 @@ namespace Emby.Server.Implementations.Data { item.DateLastRefreshed = reader[index].ReadDateTime(); } + index++; } @@ -1488,18 +1508,21 @@ namespace Emby.Server.Implementations.Data { item.Name = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { item.Path = RestorePath(reader.GetString(index)); } + index++; if (!reader.IsDBNull(index)) { item.PremiereDate = reader[index].TryReadDateTime(); } + index++; if (HasField(query, ItemFields.Overview)) @@ -1508,6 +1531,7 @@ namespace Emby.Server.Implementations.Data { item.Overview = reader.GetString(index); } + index++; } @@ -1515,18 +1539,21 @@ namespace Emby.Server.Implementations.Data { item.ParentIndexNumber = reader.GetInt32(index); } + index++; if (!reader.IsDBNull(index)) { item.ProductionYear = reader.GetInt32(index); } + index++; if (!reader.IsDBNull(index)) { item.OfficialRating = reader.GetString(index); } + index++; if (HasField(query, ItemFields.SortName)) @@ -1535,6 +1562,7 @@ namespace Emby.Server.Implementations.Data { item.ForcedSortName = reader.GetString(index); } + index++; } @@ -1542,12 +1570,14 @@ namespace Emby.Server.Implementations.Data { item.RunTimeTicks = reader.GetInt64(index); } + index++; if (!reader.IsDBNull(index)) { item.Size = reader.GetInt64(index); } + index++; if (HasField(query, ItemFields.DateCreated)) @@ -1556,6 +1586,7 @@ namespace Emby.Server.Implementations.Data { item.DateCreated = reader[index].ReadDateTime(); } + index++; } @@ -1563,6 +1594,7 @@ namespace Emby.Server.Implementations.Data { item.DateModified = reader[index].ReadDateTime(); } + index++; item.Id = reader.GetGuid(index); @@ -1574,6 +1606,7 @@ namespace Emby.Server.Implementations.Data { item.Genres = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + index++; } @@ -1581,6 +1614,7 @@ namespace Emby.Server.Implementations.Data { item.ParentId = reader.GetGuid(index); } + index++; if (!reader.IsDBNull(index)) @@ -1590,6 +1624,7 @@ namespace Emby.Server.Implementations.Data item.Audio = audio; } } + index++; // TODO: Even if not needed by apps, the server needs it internally @@ -1603,6 +1638,7 @@ namespace Emby.Server.Implementations.Data liveTvChannel.ServiceName = reader.GetString(index); } } + index++; } @@ -1610,6 +1646,7 @@ namespace Emby.Server.Implementations.Data { item.IsInMixedFolder = reader.GetBoolean(index); } + index++; if (HasField(query, ItemFields.DateLastSaved)) @@ -1618,6 +1655,7 @@ namespace Emby.Server.Implementations.Data { item.DateLastSaved = reader[index].ReadDateTime(); } + index++; } @@ -1635,8 +1673,10 @@ namespace Emby.Server.Implementations.Data } } } + item.LockedFields = GetLockedFields(reader.GetString(index)).ToArray(); } + index++; } @@ -1646,6 +1686,7 @@ namespace Emby.Server.Implementations.Data { item.Studios = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + index++; } @@ -1655,6 +1696,7 @@ namespace Emby.Server.Implementations.Data { item.Tags = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + index++; } @@ -1674,9 +1716,11 @@ namespace Emby.Server.Implementations.Data } } } + trailer.TrailerTypes = GetTrailerTypes(reader.GetString(index)).ToArray(); } } + index++; } @@ -1686,6 +1730,7 @@ namespace Emby.Server.Implementations.Data { item.OriginalTitle = reader.GetString(index); } + index++; } @@ -1696,6 +1741,7 @@ namespace Emby.Server.Implementations.Data video.PrimaryVersionId = reader.GetString(index); } } + index++; if (HasField(query, ItemFields.DateLastMediaAdded)) @@ -1704,6 +1750,7 @@ namespace Emby.Server.Implementations.Data { folder.DateLastMediaAdded = reader[index].TryReadDateTime(); } + index++; } @@ -1711,18 +1758,21 @@ namespace Emby.Server.Implementations.Data { item.Album = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { item.CriticRating = reader.GetFloat(index); } + index++; if (!reader.IsDBNull(index)) { item.IsVirtualItem = reader.GetBoolean(index); } + index++; if (item is IHasSeries hasSeriesName) @@ -1732,6 +1782,7 @@ namespace Emby.Server.Implementations.Data hasSeriesName.SeriesName = reader.GetString(index); } } + index++; if (hasEpisodeAttributes) @@ -1742,6 +1793,7 @@ namespace Emby.Server.Implementations.Data { episode.SeasonName = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { @@ -1752,6 +1804,7 @@ namespace Emby.Server.Implementations.Data { index++; } + index++; } @@ -1765,6 +1818,7 @@ namespace Emby.Server.Implementations.Data hasSeries.SeriesId = reader.GetGuid(index); } } + index++; } @@ -1774,6 +1828,7 @@ namespace Emby.Server.Implementations.Data { item.PresentationUniqueKey = reader.GetString(index); } + index++; } @@ -1783,6 +1838,7 @@ namespace Emby.Server.Implementations.Data { item.InheritedParentalRatingValue = reader.GetInt32(index); } + index++; } @@ -1792,6 +1848,7 @@ namespace Emby.Server.Implementations.Data { item.ExternalSeriesId = reader.GetString(index); } + index++; } @@ -1801,6 +1858,7 @@ namespace Emby.Server.Implementations.Data { item.Tagline = reader.GetString(index); } + index++; } @@ -1808,6 +1866,7 @@ namespace Emby.Server.Implementations.Data { DeserializeProviderIds(reader.GetString(index), item); } + index++; if (query.DtoOptions.EnableImages) @@ -1816,6 +1875,7 @@ namespace Emby.Server.Implementations.Data { DeserializeImages(reader.GetString(index), item); } + index++; } @@ -1825,6 +1885,7 @@ namespace Emby.Server.Implementations.Data { item.ProductionLocations = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } + index++; } @@ -1834,6 +1895,7 @@ namespace Emby.Server.Implementations.Data { item.ExtraIds = SplitToGuids(reader.GetString(index)); } + index++; } @@ -1841,6 +1903,7 @@ namespace Emby.Server.Implementations.Data { item.TotalBitrate = reader.GetInt32(index); } + index++; if (!reader.IsDBNull(index)) @@ -1850,6 +1913,7 @@ namespace Emby.Server.Implementations.Data item.ExtraType = extraType; } } + index++; if (hasArtistFields) @@ -1858,12 +1922,14 @@ namespace Emby.Server.Implementations.Data { hasArtists.Artists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + index++; if (item is IHasAlbumArtist hasAlbumArtists && !reader.IsDBNull(index)) { hasAlbumArtists.AlbumArtists = reader.GetString(index).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + index++; } @@ -1871,6 +1937,7 @@ namespace Emby.Server.Implementations.Data { item.ExternalId = reader.GetString(index); } + index++; if (HasField(query, ItemFields.SeriesPresentationUniqueKey)) @@ -1882,6 +1949,7 @@ namespace Emby.Server.Implementations.Data hasSeries.SeriesPresentationUniqueKey = reader.GetString(index); } } + index++; } @@ -1891,6 +1959,7 @@ namespace Emby.Server.Implementations.Data { program.ShowId = reader.GetString(index); } + index++; } @@ -1898,6 +1967,7 @@ namespace Emby.Server.Implementations.Data { item.OwnerId = reader.GetGuid(index); } + index++; return item; @@ -2473,6 +2543,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@SearchTermStartsWith", searchTerm + "%"); } + if (commandText.IndexOf("@SearchTermContains", StringComparison.OrdinalIgnoreCase) != -1) { statement.TryBind("@SearchTermContains", "%" + searchTerm + "%"); @@ -2743,6 +2814,7 @@ namespace Emby.Server.Implementations.Data { items[i] = newItem; } + return; } } @@ -2835,6 +2907,7 @@ namespace Emby.Server.Implementations.Data { statementTexts.Add(commandText); } + if (query.EnableTotalRecordCount) { commandText = string.Empty; @@ -3239,6 +3312,7 @@ namespace Emby.Server.Implementations.Data { statementTexts.Add(commandText); } + if (query.EnableTotalRecordCount) { commandText = string.Empty; @@ -3592,11 +3666,13 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("IndexNumber=@IndexNumber"); statement?.TryBind("@IndexNumber", query.IndexNumber.Value); } + if (query.ParentIndexNumber.HasValue) { whereClauses.Add("ParentIndexNumber=@ParentIndexNumber"); statement?.TryBind("@ParentIndexNumber", query.ParentIndexNumber.Value); } + if (query.ParentIndexNumberNotEquals.HasValue) { whereClauses.Add("(ParentIndexNumber<>@ParentIndexNumberNotEquals or ParentIndexNumber is null)"); @@ -3882,6 +3958,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, artistId.ToByteArray()); } + index++; } @@ -3902,6 +3979,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, artistId.ToByteArray()); } + index++; } @@ -3922,8 +4000,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, artistId.ToByteArray()); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -3941,8 +4021,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, albumId.ToByteArray()); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -3960,8 +4042,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, artistId.ToByteArray()); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -3979,8 +4063,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, genreId.ToByteArray()); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -3996,8 +4082,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@Genre" + index, GetCleanValue(item)); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4013,8 +4101,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@Tag" + index, GetCleanValue(item)); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4030,8 +4120,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@ExcludeTag" + index, GetCleanValue(item)); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4050,8 +4142,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, studioId.ToByteArray()); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4067,8 +4161,10 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@OfficialRating" + index, item); } + index++; } + var clause = "(" + string.Join(" OR ", clauses) + ")"; whereClauses.Add(clause); } @@ -4243,6 +4339,7 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@IsVirtualItem", isVirtualItem.Value); } } + if (query.IsSpecialSeason.HasValue) { if (query.IsSpecialSeason.Value) @@ -4254,6 +4351,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("IndexNumber <> 0"); } } + if (query.IsUnaired.HasValue) { if (query.IsUnaired.Value) @@ -4265,6 +4363,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("PremiereDate < DATETIME('now')"); } } + var queryMediaTypes = query.MediaTypes.Where(IsValidMediaType).ToArray(); if (queryMediaTypes.Length == 1) { @@ -4280,6 +4379,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("MediaType in (" + val + ")"); } + if (query.ItemIds.Length > 0) { var includeIds = new List(); @@ -4292,11 +4392,13 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@IncludeId" + index, id); } + index++; } whereClauses.Add("(" + string.Join(" OR ", includeIds) + ")"); } + if (query.ExcludeItemIds.Length > 0) { var excludeIds = new List(); @@ -4309,6 +4411,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind("@ExcludeId" + index, id); } + index++; } @@ -4333,6 +4436,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%"); } + index++; break; @@ -4375,6 +4479,7 @@ namespace Emby.Server.Implementations.Data { statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%"); } + index++; break; @@ -4425,6 +4530,7 @@ namespace Emby.Server.Implementations.Data { whereClauses.Add("(TopParentId=@TopParentId)"); } + if (statement != null) { statement.TryBind("@TopParentId", queryTopParentIds[0].ToString("N", CultureInfo.InvariantCulture)); @@ -4462,11 +4568,13 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@AncestorId", query.AncestorIds[0]); } } + if (query.AncestorIds.Length > 1) { var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } + if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) { var inClause = "select guid from TypedBaseItems where PresentationUniqueKey=@AncestorWithPresentationUniqueKey"; @@ -4495,6 +4603,7 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@UnratedType", query.BlockUnratedItems[0].ToString()); } } + if (query.BlockUnratedItems.Length > 1) { var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'")); @@ -4969,6 +5078,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.TryBind("@ItemId", query.ItemId.ToByteArray()); } } + if (!query.AppearsInItemId.Equals(Guid.Empty)) { whereClauses.Add("Name in (Select Name from People where ItemId=@AppearsInItemId)"); @@ -4977,6 +5087,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToByteArray()); } } + var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList(); if (queryPersonTypes.Count == 1) @@ -4993,6 +5104,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type whereClauses.Add("PersonType in (" + val + ")"); } + var queryExcludePersonTypes = query.ExcludePersonTypes.Where(IsValidPersonType).ToList(); if (queryExcludePersonTypes.Count == 1) @@ -5009,6 +5121,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type whereClauses.Add("PersonType not in (" + val + ")"); } + if (query.MaxListOrder.HasValue) { whereClauses.Add("ListOrder<=@MaxListOrder"); @@ -5017,6 +5130,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.TryBind("@MaxListOrder", query.MaxListOrder.Value); } } + if (!string.IsNullOrWhiteSpace(query.NameContains)) { whereClauses.Add("Name like @NameContains"); @@ -5156,6 +5270,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))"; } + if (excludeItemTypes.Count > 0) { var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'")); diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 7e66fa072..023125c92 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -135,10 +135,12 @@ namespace Emby.Server.Implementations.Data { throw new ArgumentNullException(nameof(userData)); } + if (internalUserId <= 0) { throw new ArgumentNullException(nameof(internalUserId)); } + if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); @@ -153,6 +155,7 @@ namespace Emby.Server.Implementations.Data { throw new ArgumentNullException(nameof(userData)); } + if (internalUserId <= 0) { throw new ArgumentNullException(nameof(internalUserId)); diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index 789cdfc11..e75745cc6 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -169,6 +169,7 @@ namespace Emby.Server.Implementations.Devices { throw new ArgumentException("user not found"); } + if (string.IsNullOrEmpty(deviceId)) { throw new ArgumentNullException(nameof(deviceId)); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 41ff7e3ab..f5a58cc6d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -277,6 +277,7 @@ namespace Emby.Server.Implementations.Dto dto.EpisodeTitle = dto.Name; dto.Name = dto.SeriesName; } + liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user); } @@ -292,6 +293,7 @@ namespace Emby.Server.Implementations.Dto { continue; } + var containers = container.Split(new[] { ',' }); if (containers.Length < 2) { @@ -456,6 +458,7 @@ namespace Emby.Server.Implementations.Dto { dto.SeriesName = item.SeriesName; } + private static void SetPhotoProperties(BaseItemDto dto, Photo item) { dto.CameraMake = item.CameraMake; @@ -554,22 +557,27 @@ namespace Emby.Server.Implementations.Dto { return 0; } + if (i.IsType(PersonType.GuestStar)) { return 1; } + if (i.IsType(PersonType.Director)) { return 2; } + if (i.IsType(PersonType.Writer)) { return 3; } + if (i.IsType(PersonType.Producer)) { return 4; } + if (i.IsType(PersonType.Composer)) { return 4; @@ -1346,6 +1354,7 @@ namespace Emby.Server.Implementations.Dto dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image); } } + if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null) { var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art); @@ -1356,6 +1365,7 @@ namespace Emby.Server.Implementations.Dto dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image); } } + if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView)) { var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb); @@ -1366,6 +1376,7 @@ namespace Emby.Server.Implementations.Dto dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image); } } + if (backdropLimit > 0 && !((dto.BackdropImageTags != null && dto.BackdropImageTags.Length > 0) || (dto.ParentBackdropImageTags != null && dto.ParentBackdropImageTags.Length > 0))) { var images = allImages.Where(i => i.Type == ImageType.Backdrop).Take(backdropLimit).ToList(); diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 1b6e4b554..e52acc548 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -453,6 +453,7 @@ namespace Emby.Server.Implementations.HttpServer { httpRes.Headers.Add(key, value); } + httpRes.ContentType = "text/plain"; await httpRes.WriteAsync(string.Empty, cancellationToken).ConfigureAwait(false); return; diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs index 8b9028f6b..94cedb918 100644 --- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -20,15 +20,21 @@ namespace Emby.Server.Implementations.HttpServer /// /// The source stream. private Stream SourceStream { get; set; } + private string RangeHeader { get; set; } + private bool IsHeadRequest { get; set; } private long RangeStart { get; set; } + private long RangeEnd { get; set; } + private long RangeLength { get; set; } + private long TotalContentLength { get; set; } public Action OnComplete { get; set; } + private readonly ILogger _logger; private const int BufferSize = 81920; @@ -139,6 +145,7 @@ namespace Emby.Server.Implementations.HttpServer { start = long.Parse(vals[0], UsCulture); } + if (!string.IsNullOrEmpty(vals[1])) { end = long.Parse(vals[1], UsCulture); diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 72959003a..2e6ff65a6 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -140,6 +140,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { return true; } + if (authAttribtues.AllowLocalOnly && request.IsLocal) { return true; diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index 4dffcd92d..bbade00ff 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -71,6 +71,7 @@ namespace Emby.Server.Implementations.HttpServer.Security { token = httpReq.Headers["X-MediaBrowser-Token"]; } + if (string.IsNullOrEmpty(token)) { token = httpReq.QueryString["api_key"]; @@ -160,6 +161,7 @@ namespace Emby.Server.Implementations.HttpServer.Security _authRepo.Update(tokenInfo); } } + httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo; } diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index a7bbf6acc..a3a3f91b7 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -628,6 +628,7 @@ namespace Emby.Server.Implementations.IO { return false; } + return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase); }); } @@ -682,6 +683,7 @@ namespace Emby.Server.Implementations.IO { return false; } + return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase); }); } diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs index 9a7186898..ab39a7223 100644 --- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs +++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs @@ -12,11 +12,13 @@ namespace Emby.Server.Implementations.Library public class ExclusiveLiveStream : ILiveStream { public int ConsumerCount { get; set; } + public string OriginalStreamId { get; set; } public string TunerHostId => null; public bool EnableStreamSharing { get; set; } + public MediaSourceInfo MediaSource { get; set; } public string UniqueId { get; private set; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1d4651da2..46f433282 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2784,10 +2784,12 @@ namespace Emby.Server.Implementations.Library { throw new ArgumentNullException(nameof(path)); } + if (string.IsNullOrWhiteSpace(from)) { throw new ArgumentNullException(nameof(from)); } + if (string.IsNullOrWhiteSpace(to)) { throw new ArgumentNullException(nameof(to)); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 919261027..ceb36b389 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -205,22 +205,27 @@ namespace Emby.Server.Implementations.Library { return MediaProtocol.Rtsp; } + if (path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase)) { return MediaProtocol.Rtmp; } + if (path.StartsWith("Http", StringComparison.OrdinalIgnoreCase)) { return MediaProtocol.Http; } + if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase)) { return MediaProtocol.Rtp; } + if (path.StartsWith("ftp", StringComparison.OrdinalIgnoreCase)) { return MediaProtocol.Ftp; } + if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase)) { return MediaProtocol.Udp; diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 4819f2fc0..99f304190 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -41,10 +41,12 @@ namespace Emby.Server.Implementations.Library.Resolvers { return new AggregateFolder(); } + if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) { return new UserRootFolder(); // if we got here and still a root - must be user root } + if (args.IsVf) { return new CollectionFolder diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 7f477a0f0..2f7af60c0 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -55,6 +55,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV episode.SeriesId = series.Id; episode.SeriesName = series.Name; } + if (season != null) { episode.SeasonId = season.Id; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index b8c42cdf8..3df9cc06f 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -194,6 +194,7 @@ namespace Emby.Server.Implementations.Library { searchQuery.AncestorIds = new[] { searchQuery.ParentId }; } + searchQuery.ParentId = Guid.Empty; searchQuery.IncludeItemsByName = true; searchQuery.IncludeItemTypes = Array.Empty(); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index fdd305f86..3709f8fe4 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -212,6 +212,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { channelNumber = map.channel; } + if (string.IsNullOrWhiteSpace(channelNumber)) { channelNumber = map.atscMajor + "." + map.atscMinor; @@ -400,6 +401,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { date = DateTime.SpecifyKind(date, DateTimeKind.Utc); } + return date; } @@ -622,6 +624,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings _lastErrorResponse = DateTime.UtcNow; } } + throw; } finally @@ -805,11 +808,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings { throw new ArgumentException("Username is required"); } + if (string.IsNullOrEmpty(info.Password)) { throw new ArgumentException("Password is required"); } } + if (validateListings) { if (string.IsNullOrEmpty(info.ListingsId)) @@ -932,24 +937,35 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class Token { public int code { get; set; } + public string message { get; set; } + public string serverID { get; set; } + public string token { get; set; } } + public class Lineup { public string lineup { get; set; } + public string name { get; set; } + public string transport { get; set; } + public string location { get; set; } + public string uri { get; set; } } public class Lineups { public int code { get; set; } + public string serverID { get; set; } + public string datetime { get; set; } + public List lineups { get; set; } } @@ -957,8 +973,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class Headends { public string headend { get; set; } + public string transport { get; set; } + public string location { get; set; } + public List lineups { get; set; } } @@ -967,59 +986,83 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class Map { public string stationID { get; set; } + public string channel { get; set; } + public string logicalChannelNumber { get; set; } + public int uhfVhf { get; set; } + public int atscMajor { get; set; } + public int atscMinor { get; set; } } public class Broadcaster { public string city { get; set; } + public string state { get; set; } + public string postalcode { get; set; } + public string country { get; set; } } public class Logo { public string URL { get; set; } + public int height { get; set; } + public int width { get; set; } + public string md5 { get; set; } } public class Station { public string stationID { get; set; } + public string name { get; set; } + public string callsign { get; set; } + public List broadcastLanguage { get; set; } + public List descriptionLanguage { get; set; } + public Broadcaster broadcaster { get; set; } + public string affiliate { get; set; } + public Logo logo { get; set; } + public bool? isCommercialFree { get; set; } } public class Metadata { public string lineup { get; set; } + public string modified { get; set; } + public string transport { get; set; } } public class Channel { public List map { get; set; } + public List stations { get; set; } + public Metadata metadata { get; set; } } public class RequestScheduleForChannel { public string stationID { get; set; } + public List date { get; set; } } @@ -1029,29 +1072,43 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class Rating { public string body { get; set; } + public string code { get; set; } } public class Multipart { public int partNumber { get; set; } + public int totalParts { get; set; } } public class Program { public string programID { get; set; } + public string airDateTime { get; set; } + public int duration { get; set; } + public string md5 { get; set; } + public List audioProperties { get; set; } + public List videoProperties { get; set; } + public List ratings { get; set; } + public bool? @new { get; set; } + public Multipart multipart { get; set; } + public string liveTapeDelay { get; set; } + public bool premiere { get; set; } + public bool repeat { get; set; } + public string isPremiereOrFinale { get; set; } } @@ -1060,16 +1117,22 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class MetadataSchedule { public string modified { get; set; } + public string md5 { get; set; } + public string startDate { get; set; } + public string endDate { get; set; } + public int days { get; set; } } public class Day { public string stationID { get; set; } + public List programs { get; set; } + public MetadataSchedule metadata { get; set; } public Day() @@ -1092,24 +1155,28 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class Description100 { public string descriptionLanguage { get; set; } + public string description { get; set; } } public class Description1000 { public string descriptionLanguage { get; set; } + public string description { get; set; } } public class DescriptionsProgram { public List description100 { get; set; } + public List description1000 { get; set; } } public class Gracenote { public int season { get; set; } + public int episode { get; set; } } @@ -1121,101 +1188,152 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class ContentRating { public string body { get; set; } + public string code { get; set; } } public class Cast { public string billingOrder { get; set; } + public string role { get; set; } + public string nameId { get; set; } + public string personId { get; set; } + public string name { get; set; } + public string characterName { get; set; } } public class Crew { public string billingOrder { get; set; } + public string role { get; set; } + public string nameId { get; set; } + public string personId { get; set; } + public string name { get; set; } } public class QualityRating { public string ratingsBody { get; set; } + public string rating { get; set; } + public string minRating { get; set; } + public string maxRating { get; set; } + public string increment { get; set; } } public class Movie { public string year { get; set; } + public int duration { get; set; } + public List qualityRating { get; set; } } public class Recommendation { public string programID { get; set; } + public string title120 { get; set; } } public class ProgramDetails { public string audience { get; set; } + public string programID { get; set; } + public List titles { get; set; } + public EventDetails eventDetails { get; set; } + public DescriptionsProgram descriptions { get; set; } + public string originalAirDate { get; set; } + public List<string> genres { get; set; } + public string episodeTitle150 { get; set; } + public List<MetadataPrograms> metadata { get; set; } + public List<ContentRating> contentRating { get; set; } + public List<Cast> cast { get; set; } + public List<Crew> crew { get; set; } + public string entityType { get; set; } + public string showType { get; set; } + public bool hasImageArtwork { get; set; } + public string primaryImage { get; set; } + public string thumbImage { get; set; } + public string backdropImage { get; set; } + public string bannerImage { get; set; } + public string imageID { get; set; } + public string md5 { get; set; } + public List<string> contentAdvisory { get; set; } + public Movie movie { get; set; } + public List<Recommendation> recommendations { get; set; } } public class Caption { public string content { get; set; } + public string lang { get; set; } } public class ImageData { public string width { get; set; } + public string height { get; set; } + public string uri { get; set; } + public string size { get; set; } + public string aspect { get; set; } + public string category { get; set; } + public string text { get; set; } + public string primary { get; set; } + public string tier { get; set; } + public Caption caption { get; set; } } public class ShowImages { public string programID { get; set; } + public List<ImageData> data { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 077b5c7e5..0a93c4674 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -224,6 +224,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { uniqueString = "-" + programInfo.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture); } + if (programInfo.EpisodeNumber.HasValue) { uniqueString = "-" + programInfo.EpisodeNumber.Value.ToString(CultureInfo.InvariantCulture); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 42e93b7ff..4c1de3bcc 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -556,6 +556,7 @@ namespace Emby.Server.Implementations.LiveTv { forceUpdate = true; } + item.ParentId = channel.Id; // item.ChannelType = channelType; @@ -575,6 +576,7 @@ namespace Emby.Server.Implementations.LiveTv { forceUpdate = true; } + item.ExternalSeriesId = seriesId; var isSeries = info.IsSeries || !string.IsNullOrEmpty(info.EpisodeTitle); @@ -589,30 +591,37 @@ namespace Emby.Server.Implementations.LiveTv { tags.Add("Live"); } + if (info.IsPremiere) { tags.Add("Premiere"); } + if (info.IsNews) { tags.Add("News"); } + if (info.IsSports) { tags.Add("Sports"); } + if (info.IsKids) { tags.Add("Kids"); } + if (info.IsRepeat) { tags.Add("Repeat"); } + if (info.IsMovie) { tags.Add("Movie"); } + if (isSeries) { tags.Add("Series"); @@ -635,6 +644,7 @@ namespace Emby.Server.Implementations.LiveTv { forceUpdate = true; } + item.IsSeries = isSeries; item.Name = info.Name; @@ -652,12 +662,14 @@ namespace Emby.Server.Implementations.LiveTv { forceUpdate = true; } + item.StartDate = info.StartDate; if (item.EndDate != info.EndDate) { forceUpdate = true; } + item.EndDate = info.EndDate; item.ProductionYear = info.ProductionYear; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index f14fcde2a..dff113a2a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -170,6 +170,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _modelCache[cacheKey] = response; } } + return response; } @@ -201,6 +202,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var name = line.Substring(0, index - 1); var currentChannel = line.Substring(index + 7); if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } + tuners.Add(new LiveTvTunerInfo { Name = name, @@ -229,11 +231,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun inside = true; continue; } + if (let == '>') { inside = false; continue; } + if (!inside) { buffer[bufferIndex] = let; @@ -331,12 +335,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private class Channels { public string GuideNumber { get; set; } + public string GuideName { get; set; } + public string VideoCodec { get; set; } + public string AudioCodec { get; set; } + public string URL { get; set; } + public bool Favorite { get; set; } + public bool DRM { get; set; } + public int HD { get; set; } } @@ -657,13 +668,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public class DiscoverResponse { public string FriendlyName { get; set; } + public string ModelNumber { get; set; } + public string FirmwareName { get; set; } + public string FirmwareVersion { get; set; } + public string DeviceID { get; set; } + public string DeviceAuth { get; set; } + public string BaseURL { get; set; } + public string LineupURL { get; set; } + public int TunerCount { get; set; } public bool SupportsTranscoding diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 4decdc24f..0333e723b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -58,12 +58,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts protected virtual int EmptyReadLimit => 1000; public MediaSourceInfo OriginalMediaSource { get; set; } + public MediaSourceInfo MediaSource { get; set; } public int ConsumerCount { get; set; } public string OriginalStreamId { get; set; } + public bool EnableStreamSharing { get; set; } + public string UniqueId { get; } public string TunerHostId { get; } diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 184d64e60..ac816ccd9 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -401,6 +401,7 @@ namespace Emby.Server.Implementations.Playlists { entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value); } + playlist.PlaylistEntries.Add(entry); } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index e58c335a8..2031a1c6d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -143,12 +143,14 @@ namespace Emby.Server.Implementations.ScheduledTasks Logger.LogError(ex, "Error deserializing {File}", path); } } + _readFromFile = true; } } return _lastExecutionResult; } + private set { _lastExecutionResult = value; @@ -261,6 +263,7 @@ namespace Emby.Server.Implementations.ScheduledTasks var triggers = InternalTriggers; return triggers.Select(i => i.Item1).ToArray(); } + set { if (value == null) @@ -640,6 +643,7 @@ namespace Emby.Server.Implementations.ScheduledTasks Logger.LogError(ex, "Error calling CancellationToken.Cancel();"); } } + var task = _currentTask; if (task != null) { @@ -675,6 +679,7 @@ namespace Emby.Server.Implementations.ScheduledTasks Logger.LogError(ex, "Error calling CancellationToken.Dispose();"); } } + if (wassRunning) { OnTaskCompleted(startTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, null); diff --git a/Emby.Server.Implementations/Services/ServiceMethod.cs b/Emby.Server.Implementations/Services/ServiceMethod.cs index 59ee5908f..5116cc04f 100644 --- a/Emby.Server.Implementations/Services/ServiceMethod.cs +++ b/Emby.Server.Implementations/Services/ServiceMethod.cs @@ -9,6 +9,7 @@ namespace Emby.Server.Implementations.Services public string Id { get; set; } public ActionInvokerFn ServiceAction { get; set; } + public MediaBrowser.Model.Services.IHasRequestFilter[] RequestFilters { get; set; } public static string Key(Type serviceType, string method, string requestDtoName) diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 43869f98a..3b7ffaf2c 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -62,7 +62,9 @@ namespace Emby.Server.Implementations.Services public string Path => this.restPath; public string Summary { get; private set; } + public string Description { get; private set; } + public bool IsHidden { get; private set; } public static string[] GetPathPartsForMatching(string pathInfo) @@ -159,6 +161,7 @@ namespace Emby.Server.Implementations.Services this.isWildcard[i] = true; variableName = variableName.Substring(0, variableName.Length - 1); } + this.variablesNames[i] = variableName; this.VariableArgsCount++; } diff --git a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs index d3d27ae58..165bb0fc4 100644 --- a/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs +++ b/Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs @@ -22,7 +22,9 @@ namespace Emby.Server.Implementations.Services } public Action<object, object> PropertySetFn { get; private set; } + public Func<string, object> PropertyParseStringFn { get; private set; } + public Type PropertyType { get; private set; } } diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs index 16142a70d..4f011a678 100644 --- a/Emby.Server.Implementations/Services/SwaggerService.cs +++ b/Emby.Server.Implementations/Services/SwaggerService.cs @@ -18,13 +18,21 @@ namespace Emby.Server.Implementations.Services public class SwaggerSpec { public string swagger { get; set; } + public string[] schemes { get; set; } + public SwaggerInfo info { get; set; } + public string host { get; set; } + public string basePath { get; set; } + public SwaggerTag[] tags { get; set; } + public IDictionary<string, Dictionary<string, SwaggerMethod>> paths { get; set; } + public Dictionary<string, SwaggerDefinition> definitions { get; set; } + public SwaggerComponents components { get; set; } } @@ -36,15 +44,20 @@ namespace Emby.Server.Implementations.Services public class SwaggerSecurityScheme { public string name { get; set; } + public string type { get; set; } + public string @in { get; set; } } public class SwaggerInfo { public string description { get; set; } + public string version { get; set; } + public string title { get; set; } + public string termsOfService { get; set; } public SwaggerConcactInfo contact { get; set; } @@ -53,36 +66,52 @@ namespace Emby.Server.Implementations.Services public class SwaggerConcactInfo { public string email { get; set; } + public string name { get; set; } + public string url { get; set; } } public class SwaggerTag { public string description { get; set; } + public string name { get; set; } } public class SwaggerMethod { public string summary { get; set; } + public string description { get; set; } + public string[] tags { get; set; } + public string operationId { get; set; } + public string[] consumes { get; set; } + public string[] produces { get; set; } + public SwaggerParam[] parameters { get; set; } + public Dictionary<string, SwaggerResponse> responses { get; set; } + public Dictionary<string, string[]>[] security { get; set; } } public class SwaggerParam { public string @in { get; set; } + public string name { get; set; } + public string description { get; set; } + public bool required { get; set; } + public string type { get; set; } + public string collectionFormat { get; set; } } @@ -97,15 +126,20 @@ namespace Emby.Server.Implementations.Services public class SwaggerDefinition { public string type { get; set; } + public Dictionary<string, SwaggerProperty> properties { get; set; } } public class SwaggerProperty { public string type { get; set; } + public string format { get; set; } + public string description { get; set; } + public string[] @enum { get; set; } + public string @default { get; set; } } diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index ef32c692c..1e8b25e38 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -167,6 +167,7 @@ namespace Emby.Server.Implementations.Session _logger.LogWarning("Multiple attempts to keep alive single WebSocket {0}", webSocket); return; } + webSocket.Closed += OnWebSocketClosed; webSocket.LastKeepAliveDate = DateTime.UtcNow; diff --git a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs index 0c944a7a0..491057a85 100644 --- a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -44,6 +44,7 @@ namespace Emby.Server.Implementations.Sorting // Don't blow up if the item has a bad ProductionYear, just return MinValue } } + return DateTime.MinValue; } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index db056cc38..21c12ae79 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -256,6 +256,7 @@ namespace Emby.Server.Implementations.TV { items = items.Skip(query.StartIndex.Value); } + if (query.Limit.HasValue) { items = items.Take(query.Limit.Value); diff --git a/Jellyfin.Data/Entities/Artwork.cs b/Jellyfin.Data/Entities/Artwork.cs index 214fb4cb1..bebcc37d3 100644 --- a/Jellyfin.Data/Entities/Artwork.cs +++ b/Jellyfin.Data/Entities/Artwork.cs @@ -89,6 +89,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -127,6 +128,7 @@ namespace Jellyfin.Data.Entities GetPath(ref value); return (_Path = value); } + set { string oldValue = _Path; @@ -163,6 +165,7 @@ namespace Jellyfin.Data.Entities GetKind(ref value); return (_Kind = value); } + set { Enums.ArtKind oldValue = _Kind; diff --git a/Jellyfin.Data/Entities/BookMetadata.cs b/Jellyfin.Data/Entities/BookMetadata.cs index dd389b64a..6c72c2732 100644 --- a/Jellyfin.Data/Entities/BookMetadata.cs +++ b/Jellyfin.Data/Entities/BookMetadata.cs @@ -84,6 +84,7 @@ namespace Jellyfin.Data.Entities GetISBN(ref value); return (_ISBN = value); } + set { long? oldValue = _ISBN; diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs index 9b3a5e827..3d59fe6b8 100644 --- a/Jellyfin.Data/Entities/Chapter.cs +++ b/Jellyfin.Data/Entities/Chapter.cs @@ -86,6 +86,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -123,6 +124,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; @@ -163,6 +165,7 @@ namespace Jellyfin.Data.Entities GetLanguage(ref value); return (_Language = value); } + set { string oldValue = _Language; @@ -199,6 +202,7 @@ namespace Jellyfin.Data.Entities GetTimeStart(ref value); return (_TimeStart = value); } + set { long oldValue = _TimeStart; @@ -231,6 +235,7 @@ namespace Jellyfin.Data.Entities GetTimeEnd(ref value); return (_TimeEnd = value); } + set { long? oldValue = _TimeEnd; diff --git a/Jellyfin.Data/Entities/Collection.cs b/Jellyfin.Data/Entities/Collection.cs index c040cfe33..caf20f916 100644 --- a/Jellyfin.Data/Entities/Collection.cs +++ b/Jellyfin.Data/Entities/Collection.cs @@ -49,6 +49,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -86,6 +87,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; diff --git a/Jellyfin.Data/Entities/CollectionItem.cs b/Jellyfin.Data/Entities/CollectionItem.cs index c5e54c3a2..1a1078050 100644 --- a/Jellyfin.Data/Entities/CollectionItem.cs +++ b/Jellyfin.Data/Entities/CollectionItem.cs @@ -93,6 +93,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; diff --git a/Jellyfin.Data/Entities/Company.cs b/Jellyfin.Data/Entities/Company.cs index 7d6f3b207..eefc581c6 100644 --- a/Jellyfin.Data/Entities/Company.cs +++ b/Jellyfin.Data/Entities/Company.cs @@ -101,6 +101,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; diff --git a/Jellyfin.Data/Entities/CompanyMetadata.cs b/Jellyfin.Data/Entities/CompanyMetadata.cs index 1ad03b4f9..6a601c6e3 100644 --- a/Jellyfin.Data/Entities/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/CompanyMetadata.cs @@ -85,6 +85,7 @@ namespace Jellyfin.Data.Entities GetDescription(ref value); return (_Description = value); } + set { string oldValue = _Description; @@ -122,6 +123,7 @@ namespace Jellyfin.Data.Entities GetHeadquarters(ref value); return (_Headquarters = value); } + set { string oldValue = _Headquarters; @@ -159,6 +161,7 @@ namespace Jellyfin.Data.Entities GetCountry(ref value); return (_Country = value); } + set { string oldValue = _Country; @@ -196,6 +199,7 @@ namespace Jellyfin.Data.Entities GetHomepage(ref value); return (_Homepage = value); } + set { string oldValue = _Homepage; diff --git a/Jellyfin.Data/Entities/Episode.cs b/Jellyfin.Data/Entities/Episode.cs index 88531205f..6f4353a6f 100644 --- a/Jellyfin.Data/Entities/Episode.cs +++ b/Jellyfin.Data/Entities/Episode.cs @@ -86,6 +86,7 @@ namespace Jellyfin.Data.Entities GetEpisodeNumber(ref value); return (_EpisodeNumber = value); } + set { int? oldValue = _EpisodeNumber; diff --git a/Jellyfin.Data/Entities/EpisodeMetadata.cs b/Jellyfin.Data/Entities/EpisodeMetadata.cs index 0aa4b4270..17057cb1d 100644 --- a/Jellyfin.Data/Entities/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/EpisodeMetadata.cs @@ -85,6 +85,7 @@ namespace Jellyfin.Data.Entities GetOutline(ref value); return (_Outline = value); } + set { string oldValue = _Outline; @@ -122,6 +123,7 @@ namespace Jellyfin.Data.Entities GetPlot(ref value); return (_Plot = value); } + set { string oldValue = _Plot; @@ -159,6 +161,7 @@ namespace Jellyfin.Data.Entities GetTagline(ref value); return (_Tagline = value); } + set { string oldValue = _Tagline; diff --git a/Jellyfin.Data/Entities/Genre.cs b/Jellyfin.Data/Entities/Genre.cs index ff0710671..b56e35667 100644 --- a/Jellyfin.Data/Entities/Genre.cs +++ b/Jellyfin.Data/Entities/Genre.cs @@ -82,6 +82,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -120,6 +121,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; diff --git a/Jellyfin.Data/Entities/Library.cs b/Jellyfin.Data/Entities/Library.cs index a5cc5c8da..4c7f7e7b7 100644 --- a/Jellyfin.Data/Entities/Library.cs +++ b/Jellyfin.Data/Entities/Library.cs @@ -77,6 +77,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -115,6 +116,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; diff --git a/Jellyfin.Data/Entities/LibraryItem.cs b/Jellyfin.Data/Entities/LibraryItem.cs index c2ba7059d..bfc2f7ddb 100644 --- a/Jellyfin.Data/Entities/LibraryItem.cs +++ b/Jellyfin.Data/Entities/LibraryItem.cs @@ -59,6 +59,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -96,6 +97,7 @@ namespace Jellyfin.Data.Entities GetUrlId(ref value); return (_UrlId = value); } + set { Guid oldValue = _UrlId; @@ -132,6 +134,7 @@ namespace Jellyfin.Data.Entities GetDateAdded(ref value); return (_DateAdded = value); } + internal set { DateTime oldValue = _DateAdded; diff --git a/Jellyfin.Data/Entities/LibraryRoot.cs b/Jellyfin.Data/Entities/LibraryRoot.cs index 7823db02a..fa1e6f14c 100644 --- a/Jellyfin.Data/Entities/LibraryRoot.cs +++ b/Jellyfin.Data/Entities/LibraryRoot.cs @@ -77,6 +77,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -116,6 +117,7 @@ namespace Jellyfin.Data.Entities GetPath(ref value); return (_Path = value); } + set { string oldValue = _Path; @@ -154,6 +156,7 @@ namespace Jellyfin.Data.Entities GetNetworkPath(ref value); return (_NetworkPath = value); } + set { string oldValue = _NetworkPath; diff --git a/Jellyfin.Data/Entities/MediaFile.cs b/Jellyfin.Data/Entities/MediaFile.cs index 94c39a28a..1c14c6c87 100644 --- a/Jellyfin.Data/Entities/MediaFile.cs +++ b/Jellyfin.Data/Entities/MediaFile.cs @@ -90,6 +90,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -129,6 +130,7 @@ namespace Jellyfin.Data.Entities GetPath(ref value); return (_Path = value); } + set { string oldValue = _Path; @@ -165,6 +167,7 @@ namespace Jellyfin.Data.Entities GetKind(ref value); return (_Kind = value); } + set { Enums.MediaFileKind oldValue = _Kind; diff --git a/Jellyfin.Data/Entities/MediaFileStream.cs b/Jellyfin.Data/Entities/MediaFileStream.cs index 723977fdf..8819ddcd0 100644 --- a/Jellyfin.Data/Entities/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/MediaFileStream.cs @@ -81,6 +81,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -117,6 +118,7 @@ namespace Jellyfin.Data.Entities GetStreamNumber(ref value); return (_StreamNumber = value); } + set { int oldValue = _StreamNumber; diff --git a/Jellyfin.Data/Entities/Metadata.cs b/Jellyfin.Data/Entities/Metadata.cs index 6558642cf..4e5868e75 100644 --- a/Jellyfin.Data/Entities/Metadata.cs +++ b/Jellyfin.Data/Entities/Metadata.cs @@ -76,6 +76,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -115,6 +116,7 @@ namespace Jellyfin.Data.Entities GetTitle(ref value); return (_Title = value); } + set { string oldValue = _Title; @@ -152,6 +154,7 @@ namespace Jellyfin.Data.Entities GetOriginalTitle(ref value); return (_OriginalTitle = value); } + set { string oldValue = _OriginalTitle; @@ -189,6 +192,7 @@ namespace Jellyfin.Data.Entities GetSortTitle(ref value); return (_SortTitle = value); } + set { string oldValue = _SortTitle; @@ -229,6 +233,7 @@ namespace Jellyfin.Data.Entities GetLanguage(ref value); return (_Language = value); } + set { string oldValue = _Language; @@ -261,6 +266,7 @@ namespace Jellyfin.Data.Entities GetReleaseDate(ref value); return (_ReleaseDate = value); } + set { DateTimeOffset? oldValue = _ReleaseDate; @@ -297,6 +303,7 @@ namespace Jellyfin.Data.Entities GetDateAdded(ref value); return (_DateAdded = value); } + internal set { DateTime oldValue = _DateAdded; @@ -333,6 +340,7 @@ namespace Jellyfin.Data.Entities GetDateModified(ref value); return (_DateModified = value); } + internal set { DateTime oldValue = _DateModified; diff --git a/Jellyfin.Data/Entities/MetadataProvider.cs b/Jellyfin.Data/Entities/MetadataProvider.cs index bf9689709..9b09fc5a6 100644 --- a/Jellyfin.Data/Entities/MetadataProvider.cs +++ b/Jellyfin.Data/Entities/MetadataProvider.cs @@ -77,6 +77,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -115,6 +116,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; diff --git a/Jellyfin.Data/Entities/MetadataProviderId.cs b/Jellyfin.Data/Entities/MetadataProviderId.cs index c49c6f42e..bcd2bad54 100644 --- a/Jellyfin.Data/Entities/MetadataProviderId.cs +++ b/Jellyfin.Data/Entities/MetadataProviderId.cs @@ -103,6 +103,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -141,6 +142,7 @@ namespace Jellyfin.Data.Entities GetProviderId(ref value); return (_ProviderId = value); } + set { string oldValue = _ProviderId; diff --git a/Jellyfin.Data/Entities/MovieMetadata.cs b/Jellyfin.Data/Entities/MovieMetadata.cs index 1f8f1c2a0..6c9156a2d 100644 --- a/Jellyfin.Data/Entities/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/MovieMetadata.cs @@ -90,6 +90,7 @@ namespace Jellyfin.Data.Entities GetOutline(ref value); return (_Outline = value); } + set { string oldValue = _Outline; @@ -127,6 +128,7 @@ namespace Jellyfin.Data.Entities GetPlot(ref value); return (_Plot = value); } + set { string oldValue = _Plot; @@ -164,6 +166,7 @@ namespace Jellyfin.Data.Entities GetTagline(ref value); return (_Tagline = value); } + set { string oldValue = _Tagline; @@ -201,6 +204,7 @@ namespace Jellyfin.Data.Entities GetCountry(ref value); return (_Country = value); } + set { string oldValue = _Country; diff --git a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs index 7743890a6..cf0363b7d 100644 --- a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs @@ -90,6 +90,7 @@ namespace Jellyfin.Data.Entities GetBarcode(ref value); return (_Barcode = value); } + set { string oldValue = _Barcode; @@ -127,6 +128,7 @@ namespace Jellyfin.Data.Entities GetLabelNumber(ref value); return (_LabelNumber = value); } + set { string oldValue = _LabelNumber; @@ -164,6 +166,7 @@ namespace Jellyfin.Data.Entities GetCountry(ref value); return (_Country = value); } + set { string oldValue = _Country; diff --git a/Jellyfin.Data/Entities/Person.cs b/Jellyfin.Data/Entities/Person.cs index f71418819..9cc568e6e 100644 --- a/Jellyfin.Data/Entities/Person.cs +++ b/Jellyfin.Data/Entities/Person.cs @@ -85,6 +85,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -121,6 +122,7 @@ namespace Jellyfin.Data.Entities GetUrlId(ref value); return (_UrlId = value); } + set { Guid oldValue = _UrlId; @@ -159,6 +161,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; @@ -196,6 +199,7 @@ namespace Jellyfin.Data.Entities GetSourceId(ref value); return (_SourceId = value); } + set { string oldValue = _SourceId; @@ -232,6 +236,7 @@ namespace Jellyfin.Data.Entities GetDateAdded(ref value); return (_DateAdded = value); } + internal set { DateTime oldValue = _DateAdded; @@ -268,6 +273,7 @@ namespace Jellyfin.Data.Entities GetDateModified(ref value); return (_DateModified = value); } + internal set { DateTime oldValue = _DateModified; diff --git a/Jellyfin.Data/Entities/PersonRole.cs b/Jellyfin.Data/Entities/PersonRole.cs index a3d047115..e0492ea6a 100644 --- a/Jellyfin.Data/Entities/PersonRole.cs +++ b/Jellyfin.Data/Entities/PersonRole.cs @@ -91,6 +91,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -128,6 +129,7 @@ namespace Jellyfin.Data.Entities GetRole(ref value); return (_Role = value); } + set { string oldValue = _Role; @@ -164,6 +166,7 @@ namespace Jellyfin.Data.Entities GetType(ref value); return (_Type = value); } + set { Enums.PersonRoleType oldValue = _Type; diff --git a/Jellyfin.Data/Entities/Rating.cs b/Jellyfin.Data/Entities/Rating.cs index 0c8b99ca2..490090bfa 100644 --- a/Jellyfin.Data/Entities/Rating.cs +++ b/Jellyfin.Data/Entities/Rating.cs @@ -81,6 +81,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -117,6 +118,7 @@ namespace Jellyfin.Data.Entities GetValue(ref value); return (_Value = value); } + set { double oldValue = _Value; @@ -149,6 +151,7 @@ namespace Jellyfin.Data.Entities GetVotes(ref value); return (_Votes = value); } + set { int? oldValue = _Votes; diff --git a/Jellyfin.Data/Entities/RatingSource.cs b/Jellyfin.Data/Entities/RatingSource.cs index c829042b5..cf8af2270 100644 --- a/Jellyfin.Data/Entities/RatingSource.cs +++ b/Jellyfin.Data/Entities/RatingSource.cs @@ -88,6 +88,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -125,6 +126,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; @@ -161,6 +163,7 @@ namespace Jellyfin.Data.Entities GetMaximumValue(ref value); return (_MaximumValue = value); } + set { double oldValue = _MaximumValue; @@ -197,6 +200,7 @@ namespace Jellyfin.Data.Entities GetMinimumValue(ref value); return (_MinimumValue = value); } + set { double oldValue = _MinimumValue; diff --git a/Jellyfin.Data/Entities/Release.cs b/Jellyfin.Data/Entities/Release.cs index 35fcbb4b7..6be524a0f 100644 --- a/Jellyfin.Data/Entities/Release.cs +++ b/Jellyfin.Data/Entities/Release.cs @@ -113,6 +113,7 @@ namespace Jellyfin.Data.Entities GetId(ref value); return (_Id = value); } + protected set { int oldValue = _Id; @@ -151,6 +152,7 @@ namespace Jellyfin.Data.Entities GetName(ref value); return (_Name = value); } + set { string oldValue = _Name; diff --git a/Jellyfin.Data/Entities/Season.cs b/Jellyfin.Data/Entities/Season.cs index 2a861b660..631adb12c 100644 --- a/Jellyfin.Data/Entities/Season.cs +++ b/Jellyfin.Data/Entities/Season.cs @@ -86,6 +86,7 @@ namespace Jellyfin.Data.Entities GetSeasonNumber(ref value); return (_SeasonNumber = value); } + set { int? oldValue = _SeasonNumber; diff --git a/Jellyfin.Data/Entities/SeasonMetadata.cs b/Jellyfin.Data/Entities/SeasonMetadata.cs index 10320c6bb..2efbf6467 100644 --- a/Jellyfin.Data/Entities/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/SeasonMetadata.cs @@ -86,6 +86,7 @@ namespace Jellyfin.Data.Entities GetOutline(ref value); return (_Outline = value); } + set { string oldValue = _Outline; diff --git a/Jellyfin.Data/Entities/Series.cs b/Jellyfin.Data/Entities/Series.cs index cf1d6b781..386d3a8ac 100644 --- a/Jellyfin.Data/Entities/Series.cs +++ b/Jellyfin.Data/Entities/Series.cs @@ -67,6 +67,7 @@ namespace Jellyfin.Data.Entities GetAirsDayOfWeek(ref value); return (_AirsDayOfWeek = value); } + set { DayOfWeek? oldValue = _AirsDayOfWeek; @@ -102,6 +103,7 @@ namespace Jellyfin.Data.Entities GetAirsTime(ref value); return (_AirsTime = value); } + set { DateTimeOffset? oldValue = _AirsTime; @@ -134,6 +136,7 @@ namespace Jellyfin.Data.Entities GetFirstAired(ref value); return (_FirstAired = value); } + set { DateTimeOffset? oldValue = _FirstAired; diff --git a/Jellyfin.Data/Entities/SeriesMetadata.cs b/Jellyfin.Data/Entities/SeriesMetadata.cs index bb31c2e4e..f49c5a3b2 100644 --- a/Jellyfin.Data/Entities/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/SeriesMetadata.cs @@ -90,6 +90,7 @@ namespace Jellyfin.Data.Entities GetOutline(ref value); return (_Outline = value); } + set { string oldValue = _Outline; @@ -127,6 +128,7 @@ namespace Jellyfin.Data.Entities GetPlot(ref value); return (_Plot = value); } + set { string oldValue = _Plot; @@ -164,6 +166,7 @@ namespace Jellyfin.Data.Entities GetTagline(ref value); return (_Tagline = value); } + set { string oldValue = _Tagline; @@ -201,6 +204,7 @@ namespace Jellyfin.Data.Entities GetCountry(ref value); return (_Country = value); } + set { string oldValue = _Country; diff --git a/Jellyfin.Data/Entities/Track.cs b/Jellyfin.Data/Entities/Track.cs index c9e8fd1c3..fc9dfb370 100644 --- a/Jellyfin.Data/Entities/Track.cs +++ b/Jellyfin.Data/Entities/Track.cs @@ -86,6 +86,7 @@ namespace Jellyfin.Data.Entities GetTrackNumber(ref value); return (_TrackNumber = value); } + set { int? oldValue = _TrackNumber; diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index f574ebc66..d77cd432b 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -34,37 +34,69 @@ namespace Jellyfin.Server.Implementations public virtual DbSet<Preference> Preferences { get; set; } public virtual DbSet<User> Users { get; set; } + /*public virtual DbSet<Artwork> Artwork { get; set; } + public virtual DbSet<Book> Books { get; set; } + public virtual DbSet<BookMetadata> BookMetadata { get; set; } + public virtual DbSet<Chapter> Chapters { get; set; } + public virtual DbSet<Collection> Collections { get; set; } + public virtual DbSet<CollectionItem> CollectionItems { get; set; } + public virtual DbSet<Company> Companies { get; set; } + public virtual DbSet<CompanyMetadata> CompanyMetadata { get; set; } + public virtual DbSet<CustomItem> CustomItems { get; set; } + public virtual DbSet<CustomItemMetadata> CustomItemMetadata { get; set; } + public virtual DbSet<Episode> Episodes { get; set; } + public virtual DbSet<EpisodeMetadata> EpisodeMetadata { get; set; } + public virtual DbSet<Genre> Genres { get; set; } + public virtual DbSet<Group> Groups { get; set; } + public virtual DbSet<Library> Libraries { get; set; } + public virtual DbSet<LibraryItem> LibraryItems { get; set; } + public virtual DbSet<LibraryRoot> LibraryRoot { get; set; } + public virtual DbSet<MediaFile> MediaFiles { get; set; } + public virtual DbSet<MediaFileStream> MediaFileStream { get; set; } + public virtual DbSet<Metadata> Metadata { get; set; } + public virtual DbSet<MetadataProvider> MetadataProviders { get; set; } + public virtual DbSet<MetadataProviderId> MetadataProviderIds { get; set; } + public virtual DbSet<Movie> Movies { get; set; } + public virtual DbSet<MovieMetadata> MovieMetadata { get; set; } + public virtual DbSet<MusicAlbum> MusicAlbums { get; set; } + public virtual DbSet<MusicAlbumMetadata> MusicAlbumMetadata { get; set; } + public virtual DbSet<Person> People { get; set; } + public virtual DbSet<PersonRole> PersonRoles { get; set; } + public virtual DbSet<Photo> Photo { get; set; } + public virtual DbSet<PhotoMetadata> PhotoMetadata { get; set; } + public virtual DbSet<ProviderMapping> ProviderMappings { get; set; } + public virtual DbSet<Rating> Ratings { get; set; } /// <summary> @@ -72,12 +104,19 @@ namespace Jellyfin.Server.Implementations /// store review ratings, not age ratings /// </summary> public virtual DbSet<RatingSource> RatingSources { get; set; } + public virtual DbSet<Release> Releases { get; set; } + public virtual DbSet<Season> Seasons { get; set; } + public virtual DbSet<SeasonMetadata> SeasonMetadata { get; set; } + public virtual DbSet<Series> Series { get; set; } + public virtual DbSet<SeriesMetadata> SeriesMetadata { get; set; } + public virtual DbSet<Track> Tracks { get; set; } + public virtual DbSet<TrackMetadata> TrackMetadata { get; set; }*/ /// <inheritdoc/> diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index fddf78465..765774dee 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -50,6 +50,7 @@ namespace MediaBrowser.Api public string Path { get; set; } public bool ValidateWriteable { get; set; } + public bool? IsFile { get; set; } } diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs index 833a684a5..1b736c77d 100644 --- a/MediaBrowser.Api/FilterService.cs +++ b/MediaBrowser.Api/FilterService.cs @@ -73,11 +73,17 @@ namespace MediaBrowser.Api } public bool? IsAiring { get; set; } + public bool? IsMovie { get; set; } + public bool? IsSports { get; set; } + public bool? IsKids { get; set; } + public bool? IsNews { get; set; } + public bool? IsSeries { get; set; } + public bool? Recursive { get; set; } } diff --git a/MediaBrowser.Api/IHasDtoOptions.cs b/MediaBrowser.Api/IHasDtoOptions.cs index 03d3b3692..33d498e8b 100644 --- a/MediaBrowser.Api/IHasDtoOptions.cs +++ b/MediaBrowser.Api/IHasDtoOptions.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Api public interface IHasDtoOptions : IHasItemFields { bool? EnableImages { get; set; } + bool? EnableUserData { get; set; } int? ImageTypeLimit { get; set; } diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index eb64abb4d..46bc43605 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -285,29 +285,38 @@ namespace MediaBrowser.Api.Library public class GetLibraryOptionsInfo : IReturn<LibraryOptionsResult> { public string LibraryContentType { get; set; } + public bool IsNewLibrary { get; set; } } public class LibraryOptionInfo { public string Name { get; set; } + public bool DefaultEnabled { get; set; } } public class LibraryOptionsResult { public LibraryOptionInfo[] MetadataSavers { get; set; } + public LibraryOptionInfo[] MetadataReaders { get; set; } + public LibraryOptionInfo[] SubtitleFetchers { get; set; } + public LibraryTypeOptions[] TypeOptions { get; set; } } public class LibraryTypeOptions { public string Type { get; set; } + public LibraryOptionInfo[] MetadataFetchers { get; set; } + public LibraryOptionInfo[] ImageFetchers { get; set; } + public ImageType[] SupportedImageTypes { get; set; } + public ImageOption[] DefaultImageOptions { get; set; } } @@ -1036,6 +1045,7 @@ namespace MediaBrowser.Api.Library { break; } + item = parent; } @@ -1093,6 +1103,7 @@ namespace MediaBrowser.Api.Library { break; } + item = parent; } diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index b00a5fec8..84141e9ae 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -200,10 +200,15 @@ namespace MediaBrowser.Api.LiveTv public bool? EnableUserData { get; set; } public bool? IsMovie { get; set; } + public bool? IsSeries { get; set; } + public bool? IsKids { get; set; } + public bool? IsSports { get; set; } + public bool? IsNews { get; set; } + public bool? IsLibraryItem { get; set; } public GetRecordings() @@ -348,6 +353,7 @@ namespace MediaBrowser.Api.LiveTv [ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? HasAired { get; set; } + public bool? IsAiring { get; set; } [ApiMember(Name = "MaxStartDate", Description = "Optional. The maximum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")] @@ -407,6 +413,7 @@ namespace MediaBrowser.Api.LiveTv public bool? EnableUserData { get; set; } public string SeriesTimerId { get; set; } + public Guid LibrarySeriesId { get; set; } /// <summary> @@ -601,7 +608,9 @@ namespace MediaBrowser.Api.LiveTv public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo> { public bool ValidateLogin { get; set; } + public bool ValidateListings { get; set; } + public string Pw { get; set; } } @@ -650,15 +659,20 @@ namespace MediaBrowser.Api.LiveTv { [ApiMember(Name = "Id", Description = "Provider id", IsRequired = true, DataType = "string", ParameterType = "query")] public string ProviderId { get; set; } + public string TunerChannelId { get; set; } + public string ProviderChannelId { get; set; } } public class ChannelMappingOptions { public List<TunerChannelMapping> TunerChannels { get; set; } + public List<NameIdPair> ProviderChannels { get; set; } + public NameValuePair[] Mappings { get; set; } + public string ProviderName { get; set; } } @@ -666,6 +680,7 @@ namespace MediaBrowser.Api.LiveTv public class GetLiveStreamFile { public string Id { get; set; } + public string Container { get; set; } } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2eb6198c0..009a957b6 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -303,6 +303,7 @@ namespace MediaBrowser.Api.Playback { StartThrottler(state, transcodingJob); } + Logger.LogDebug("StartFfMpeg() finished successfully"); return transcodingJob; @@ -608,6 +609,7 @@ namespace MediaBrowser.Api.Playback { throw new ArgumentException("Invalid timeseek header"); } + int index = value.IndexOf('-'); value = index == -1 ? value.Substring(Npt.Length) @@ -639,8 +641,10 @@ namespace MediaBrowser.Api.Playback { throw new ArgumentException("Invalid timeseek header"); } + timeFactor /= 60; } + return TimeSpan.FromSeconds(secondsSum).Ticks; } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index c2d49a93b..5a2bf2ea3 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -146,6 +146,7 @@ namespace MediaBrowser.Api.Playback.Hls { ApiEntryPoint.Instance.OnTranscodeEndRequest(job); } + return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>()); } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index c0dfcf4c1..fe5f980b1 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -234,6 +234,7 @@ namespace MediaBrowser.Api.Playback.Hls Logger.LogDebug("Starting transcoding because segmentGap is {0} and max allowed gap is {1}. requestedIndex={2}", requestedIndex - currentTranscodingIndex.Value, segmentGapRequiringTranscodingChange, requestedIndex); startTranscoding = true; } + if (startTranscoding) { // If the playlist doesn't already exist, startup ffmpeg @@ -518,6 +519,7 @@ namespace MediaBrowser.Api.Playback.Hls { Logger.LogDebug("serving {0} as it's on disk and transcoding stopped", segmentPath); } + cancellationToken.ThrowIfCancellationRequested(); } else diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2dc62fda7..b7ca1a031 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -551,10 +551,12 @@ namespace MediaBrowser.Api.Playback { mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; } + if (!allowAudioStreamCopy) { mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; } + mediaSource.TranscodingContainer = streamInfo.Container; mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol; } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 43cde440c..85c7e0e7d 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -88,14 +88,17 @@ namespace MediaBrowser.Api.Playback.Progressive { return ".ts"; } + if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase)) { return ".ogv"; } + if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase)) { return ".webm"; } + if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase)) { return ".asf"; @@ -111,14 +114,17 @@ namespace MediaBrowser.Api.Playback.Progressive { return ".aac"; } + if (string.Equals("mp3", audioCodec, StringComparison.OrdinalIgnoreCase)) { return ".mp3"; } + if (string.Equals("vorbis", audioCodec, StringComparison.OrdinalIgnoreCase)) { return ".ogg"; } + if (string.Equals("wma", audioCodec, StringComparison.OrdinalIgnoreCase)) { return ".wma"; diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index ffc5e1554..b70fff128 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -23,6 +23,7 @@ namespace MediaBrowser.Api.Playback.Progressive private long _bytesWritten = 0; public long StartPosition { get; set; } + public bool AllowEndOfFile = true; private readonly IDirectStreamProvider _directStreamProvider; @@ -105,6 +106,7 @@ namespace MediaBrowser.Api.Playback.Progressive { eofCount++; } + await Task.Delay(100, cancellationToken).ConfigureAwait(false); } else diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 9ba8eda91..397898a7e 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -12,11 +12,15 @@ namespace MediaBrowser.Api.Playback public string DeviceProfileId { get; set; } public string Params { get; set; } + public string PlaySessionId { get; set; } + public string Tag { get; set; } + public string SegmentContainer { get; set; } public int? SegmentLength { get; set; } + public int? MinSegments { get; set; } } diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index b2d101a5b..d5d78cf37 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -37,10 +37,13 @@ namespace MediaBrowser.Api.Playback public string DeviceId { get; set; } public Guid UserId { get; set; } + public string AudioCodec { get; set; } + public string Container { get; set; } public int? MaxAudioChannels { get; set; } + public int? TranscodingAudioChannels { get; set; } public long? MaxStreamingBitrate { get; set; } @@ -49,12 +52,17 @@ namespace MediaBrowser.Api.Playback public long? StartTimeTicks { get; set; } public string TranscodingContainer { get; set; } + public string TranscodingProtocol { get; set; } + public int? MaxAudioSampleRate { get; set; } + public int? MaxAudioBitDepth { get; set; } public bool EnableRedirection { get; set; } + public bool EnableRemoteMedia { get; set; } + public bool BreakOnNonKeyFrames { get; set; } public BaseUniversalRequest() @@ -114,16 +122,27 @@ namespace MediaBrowser.Api.Playback } protected IHttpClient HttpClient { get; private set; } + protected IUserManager UserManager { get; private set; } + protected ILibraryManager LibraryManager { get; private set; } + protected IIsoManager IsoManager { get; private set; } + protected IMediaEncoder MediaEncoder { get; private set; } + protected IFileSystem FileSystem { get; private set; } + protected IDlnaManager DlnaManager { get; private set; } + protected IDeviceManager DeviceManager { get; private set; } + protected IMediaSourceManager MediaSourceManager { get; private set; } + protected IJsonSerializer JsonSerializer { get; private set; } + protected IAuthorizationContext AuthorizationContext { get; private set; } + protected INetworkManager NetworkManager { get; private set; } public Task<object> Get(GetUniversalAudioStream request) @@ -328,6 +347,7 @@ namespace MediaBrowser.Api.Playback { return await service.Head(newRequest).ConfigureAwait(false); } + return await service.Get(newRequest).ConfigureAwait(false); } else diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index fd1075727..1d092a5d4 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -115,24 +115,33 @@ namespace MediaBrowser.Api public class RegistrationInfo { public string Name { get; set; } + public DateTime ExpirationDate { get; set; } + public bool IsTrial { get; set; } + public bool IsRegistered { get; set; } } public class MBRegistrationRecord { public DateTime ExpirationDate { get; set; } + public bool IsRegistered { get; set; } + public bool RegChecked { get; set; } + public bool RegError { get; set; } + public bool TrialVersion { get; set; } + public bool IsValid { get; set; } } public class PluginSecurityInfo { public string SupporterKey { get; set; } + public bool IsMBSupporter { get; set; } } /// <summary> diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 90c324ff3..c4df0a7ed 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -179,18 +179,22 @@ namespace MediaBrowser.Api { return 5; } + if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) { return 3; } + if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase)) { return 3; } + if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) { return 3; } + if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) { return 2; diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index f2968c6b5..a70da8e56 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -97,6 +97,7 @@ namespace MediaBrowser.Api.Subtitles [ApiMember(Name = "CopyTimestamps", Description = "CopyTimestamps", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } + public bool AddVttTimeMap { get; set; } } @@ -214,6 +215,7 @@ namespace MediaBrowser.Api.Subtitles { request.Format = "json"; } + if (string.IsNullOrEmpty(request.Format)) { var item = (Video)_libraryManager.GetItemById(request.Id); diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs index 32d3bde5c..17afa8e79 100644 --- a/MediaBrowser.Api/SuggestionsService.cs +++ b/MediaBrowser.Api/SuggestionsService.cs @@ -18,10 +18,15 @@ namespace MediaBrowser.Api public class GetSuggestedItems : IReturn<QueryResult<BaseItemDto>> { public string MediaType { get; set; } + public string Type { get; set; } + public Guid UserId { get; set; } + public bool EnableTotalRecordCount { get; set; } + public int? StartIndex { get; set; } + public int? Limit { get; set; } public string[] GetMediaTypes() diff --git a/MediaBrowser.Api/TranscodingJob.cs b/MediaBrowser.Api/TranscodingJob.cs index 8c24e3ce1..bfc311a27 100644 --- a/MediaBrowser.Api/TranscodingJob.cs +++ b/MediaBrowser.Api/TranscodingJob.cs @@ -32,6 +32,7 @@ namespace MediaBrowser.Api /// </summary> /// <value>The path.</value> public MediaSourceInfo MediaSource { get; set; } + public string Path { get; set; } /// <summary> /// Gets or sets the type. @@ -43,6 +44,7 @@ namespace MediaBrowser.Api /// </summary> /// <value>The process.</value> public Process Process { get; set; } + public ILogger Logger { get; private set; } /// <summary> /// Gets or sets the active request count. @@ -62,18 +64,23 @@ namespace MediaBrowser.Api public object ProcessLock = new object(); public bool HasExited { get; set; } + public bool IsUserPaused { get; set; } public string Id { get; set; } public float? Framerate { get; set; } + public double? CompletionPercentage { get; set; } public long? BytesDownloaded { get; set; } + public long? BytesTranscoded { get; set; } + public int? BitRate { get; set; } public long? TranscodingPositionTicks { get; set; } + public long? DownloadPositionTicks { get; set; } public TranscodingThrottler TranscodingThrottler { get; set; } @@ -81,6 +88,7 @@ namespace MediaBrowser.Api private readonly object _timerLock = new object(); public DateTime LastPingDate { get; set; } + public int PingTimeout { get; set; } public TranscodingJob(ILogger logger) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 23062b67b..3e8daef03 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -73,6 +73,7 @@ namespace MediaBrowser.Api [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } + public bool EnableTotalRecordCount { get; set; } public GetNextUpEpisodes() diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 4802849f4..3d9db90bd 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -210,6 +210,7 @@ namespace MediaBrowser.Api.UserLibrary { SetItemCounts(dto, i.Item2); } + return dto; }); diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index 7561b5c89..d9b52b10e 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -322,8 +322,11 @@ namespace MediaBrowser.Api.UserLibrary public bool? CollapseBoxSetItems { get; set; } public int? MinWidth { get; set; } + public int? MinHeight { get; set; } + public int? MaxWidth { get; set; } + public int? MaxHeight { get; set; } /// <summary> diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs index 73d5ec6de..6f1620ddd 100644 --- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs +++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs @@ -27,6 +27,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? IncludeExternalContent { get; set; } + public bool IncludeHidden { get; set; } public string PresetViews { get; set; } @@ -80,6 +81,7 @@ namespace MediaBrowser.Api.UserLibrary { query.IncludeExternalContent = request.IncludeExternalContent.Value; } + query.IncludeHidden = request.IncludeHidden; if (!string.IsNullOrWhiteSpace(request.PresetViews)) @@ -140,6 +142,7 @@ namespace MediaBrowser.Api.UserLibrary class SpecialViewOption { public string Name { get; set; } + public string Id { get; set; } } } diff --git a/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs b/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs index c0324a384..b10233c71 100644 --- a/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs +++ b/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs @@ -7,7 +7,9 @@ namespace MediaBrowser.Controller.Authentication public interface IAuthenticationProvider { string Name { get; } + bool IsEnabled { get; } + Task<ProviderAuthenticationResult> Authenticate(string username, string password); bool HasPassword(User user); Task ChangePassword(User user, string newPassword); @@ -28,6 +30,7 @@ namespace MediaBrowser.Controller.Authentication public class ProviderAuthenticationResult { public string Username { get; set; } + public string DisplayName { get; set; } } } diff --git a/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs b/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs index d9b814f69..693df80ac 100644 --- a/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs +++ b/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs @@ -8,7 +8,9 @@ namespace MediaBrowser.Controller.Authentication public interface IPasswordResetProvider { string Name { get; } + bool IsEnabled { get; } + Task<ForgotPasswordResult> StartForgotPasswordProcess(User user, bool isInNetwork); Task<PinRedeemResult> RedeemPasswordResetPin(string pin); } @@ -16,6 +18,7 @@ namespace MediaBrowser.Controller.Authentication public class PasswordPinCreationResult { public string PinFile { get; set; } + public DateTime ExpirationDate { get; set; } } } diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs index aff68883b..00d4d9cb3 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs @@ -24,7 +24,9 @@ namespace MediaBrowser.Controller.Channels public string Overview { get; set; } public List<string> Genres { get; set; } + public List<string> Studios { get; set; } + public List<string> Tags { get; set; } public List<PersonInfo> People { get; set; } @@ -34,26 +36,33 @@ namespace MediaBrowser.Controller.Channels public long? RunTimeTicks { get; set; } public string ImageUrl { get; set; } + public string OriginalTitle { get; set; } public ChannelMediaType MediaType { get; set; } + public ChannelFolderType FolderType { get; set; } public ChannelMediaContentType ContentType { get; set; } + public ExtraType ExtraType { get; set; } + public List<TrailerType> TrailerTypes { get; set; } public Dictionary<string, string> ProviderIds { get; set; } public DateTime? PremiereDate { get; set; } + public int? ProductionYear { get; set; } public DateTime? DateCreated { get; set; } public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } public int? IndexNumber { get; set; } + public int? ParentIndexNumber { get; set; } public List<MediaSourceInfo> MediaSources { get; set; } @@ -63,7 +72,9 @@ namespace MediaBrowser.Controller.Channels public List<string> Artists { get; set; } public List<string> AlbumArtists { get; set; } + public bool IsLiveStream { get; set; } + public string Etag { get; set; } public ChannelItemInfo() diff --git a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs index 51fe4ce29..1e7549d2b 100644 --- a/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs +++ b/MediaBrowser.Controller/Collections/CollectionCreationOptions.cs @@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.Collections public Dictionary<string, string> ProviderIds { get; set; } public string[] ItemIdList { get; set; } + public Guid[] UserIds { get; set; } public CollectionCreationOptions() diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index c87a248b5..e1273fe7f 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -16,6 +16,7 @@ namespace MediaBrowser.Controller.Drawing return newSize; } + return GetSizeEstimate(options); } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index 870e0278e..31d2c1bd4 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.Drawing } public Guid ItemId { get; set; } + public BaseItem Item { get; set; } public ItemImageInfo Image { get; set; } @@ -38,12 +39,15 @@ namespace MediaBrowser.Controller.Drawing public bool AddPlayedIndicator { get; set; } public int? UnplayedCount { get; set; } + public int? Blur { get; set; } public double PercentPlayed { get; set; } public string BackgroundColor { get; set; } + public string ForegroundLayer { get; set; } + public bool RequiresAutoOrientation { get; set; } private bool HasDefaultOptions(string originalImagePath) @@ -73,14 +77,17 @@ namespace MediaBrowser.Controller.Drawing { return false; } + if (Height.HasValue && !sizeValue.Height.Equals(Height.Value)) { return false; } + if (MaxWidth.HasValue && sizeValue.Width > MaxWidth.Value) { return false; } + if (MaxHeight.HasValue && sizeValue.Height > MaxHeight.Value) { return false; diff --git a/MediaBrowser.Controller/Dto/DtoOptions.cs b/MediaBrowser.Controller/Dto/DtoOptions.cs index cdaf95f5c..cf301f1e4 100644 --- a/MediaBrowser.Controller/Dto/DtoOptions.cs +++ b/MediaBrowser.Controller/Dto/DtoOptions.cs @@ -14,11 +14,17 @@ namespace MediaBrowser.Controller.Dto }; public ItemFields[] Fields { get; set; } + public ImageType[] ImageTypes { get; set; } + public int ImageTypeLimit { get; set; } + public bool EnableImages { get; set; } + public bool AddProgramRecordingInfo { get; set; } + public bool EnableUserData { get; set; } + public bool AddCurrentProgram { get; set; } public DtoOptions() diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 54540e892..fd0dc31cc 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -195,6 +195,7 @@ namespace MediaBrowser.Controller.Entities return child; } } + return null; } } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index a8ea2157d..7d10e6831 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -93,6 +93,7 @@ namespace MediaBrowser.Controller.Entities.Audio { songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; } + songKey += Name; if (!string.IsNullOrEmpty(Album)) @@ -117,6 +118,7 @@ namespace MediaBrowser.Controller.Entities.Audio { return UnratedItem.Music; } + return base.GetBlockUnratedType(); } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index f7b2f9549..c3514e0f6 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -56,6 +56,7 @@ namespace MediaBrowser.Controller.Entities.Audio { return LibraryManager.GetArtist(name, options); } + return null; } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 63db3cfab..cbba1914a 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -135,6 +135,7 @@ namespace MediaBrowser.Controller.Entities.Audio list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string CreatePresentationUniqueKey() { return "Artist-" + (Name ?? string.Empty).RemoveDiacritics(); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 537e9630b..61f35b942 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Controller.Entities.Audio list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string CreatePresentationUniqueKey() { return GetUserDataKeys()[0]; @@ -94,6 +95,7 @@ namespace MediaBrowser.Controller.Entities.Audio Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); return true; } + return base.RequiresRefresh(); } diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs index 4adaf4c6e..11ff8a257 100644 --- a/MediaBrowser.Controller/Entities/AudioBook.cs +++ b/MediaBrowser.Controller/Entities/AudioBook.cs @@ -24,10 +24,12 @@ namespace MediaBrowser.Controller.Entities { return SeriesName; } + public string FindSeriesName() { return SeriesName; } + public string FindSeriesPresentationUniqueKey() { return SeriesPresentationUniqueKey; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f2de1f2b1..d356cdfd6 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -108,6 +108,7 @@ namespace MediaBrowser.Controller.Entities public string PreferredMetadataLanguage { get; set; } public long? Size { get; set; } + public string Container { get; set; } [JsonIgnore] @@ -448,6 +449,7 @@ namespace MediaBrowser.Controller.Entities // hack alert return true; } + if (SourceType == SourceType.Channel) { // hack alert @@ -559,15 +561,25 @@ namespace MediaBrowser.Controller.Entities /// The logger /// </summary> public static ILoggerFactory LoggerFactory { get; set; } + public static ILogger<BaseItem> Logger { get; set; } + public static ILibraryManager LibraryManager { get; set; } + public static IServerConfigurationManager ConfigurationManager { get; set; } + public static IProviderManager ProviderManager { get; set; } + public static ILocalizationManager LocalizationManager { get; set; } + public static IItemRepository ItemRepository { get; set; } + public static IFileSystem FileSystem { get; set; } + public static IUserDataManager UserDataManager { get; set; } + public static IChannelManager ChannelManager { get; set; } + public static IMediaSourceManager MediaSourceManager { get; set; } /// <summary> @@ -644,8 +656,10 @@ namespace MediaBrowser.Controller.Entities _sortName = CreateSortName(); } } + return _sortName; } + set => _sortName = value; } @@ -814,6 +828,7 @@ namespace MediaBrowser.Controller.Entities return item; } } + return null; } @@ -837,6 +852,7 @@ namespace MediaBrowser.Controller.Entities { return null; } + return LibraryManager.GetItemById(id); } } diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index e5adf88d1..5023c1603 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -23,7 +23,9 @@ namespace MediaBrowser.Controller.Entities public class CollectionFolder : Folder, ICollectionFolder { public static IXmlSerializer XmlSerializer { get; set; } + public static IJsonSerializer JsonSerializer { get; set; } + public static IServerApplicationHost ApplicationHost { get; set; } public CollectionFolder() @@ -155,6 +157,7 @@ namespace MediaBrowser.Controller.Entities } public string[] PhysicalLocationsList { get; set; } + public Guid[] PhysicalFolderIds { get; set; } protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 3a01b4379..77551702a 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -126,10 +126,12 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (this is UserView) { return false; } + return true; } @@ -156,6 +158,7 @@ namespace MediaBrowser.Controller.Entities { item.DateCreated = DateTime.UtcNow; } + if (item.DateModified == DateTime.MinValue) { item.DateModified = DateTime.UtcNow; @@ -501,6 +504,7 @@ namespace MediaBrowser.Controller.Entities { await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); } + await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false); } @@ -939,6 +943,7 @@ namespace MediaBrowser.Controller.Entities { items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1); } + if (!string.IsNullOrEmpty(query.NameStartsWith)) { items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.OrdinalIgnoreCase)); @@ -989,18 +994,22 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (queryParent is Series) { return false; } + if (queryParent is Season) { return false; } + if (queryParent is MusicAlbum) { return false; } + if (queryParent is MusicArtist) { return false; @@ -1030,22 +1039,27 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (request.IsFavoriteOrLiked.HasValue) { return false; } + if (request.IsLiked.HasValue) { return false; } + if (request.IsPlayed.HasValue) { return false; } + if (request.IsResumable.HasValue) { return false; } + if (request.IsFolder.HasValue) { return false; @@ -1391,6 +1405,7 @@ namespace MediaBrowser.Controller.Entities list.Add(child); } } + return list; } @@ -1413,6 +1428,7 @@ namespace MediaBrowser.Controller.Entities return true; } } + return false; } @@ -1665,22 +1681,27 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (this is UserView) { return false; } + if (this is UserRootFolder) { return false; } + if (this is Channel) { return false; } + if (SourceType != SourceType.Library) { return false; } + var iItemByName = this as IItemByName; if (iItemByName != null) { diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 773c7df34..55634aa5e 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Entities list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string CreatePresentationUniqueKey() { return GetUserDataKeys()[0]; @@ -92,6 +93,7 @@ namespace MediaBrowser.Controller.Entities Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); return true; } + return base.RequiresRefresh(); } diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index 4635b9062..213c0a794 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -13,7 +13,9 @@ namespace MediaBrowser.Controller.Entities List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); List<MediaStream> GetMediaStreams(); Guid Id { get; set; } + long? RunTimeTicks { get; set; } + string Path { get; } } } diff --git a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs b/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs index 777b40828..fd1c19c97 100644 --- a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs +++ b/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs @@ -5,13 +5,21 @@ namespace MediaBrowser.Controller.Entities public interface IHasProgramAttributes { bool IsMovie { get; set; } + bool IsSports { get; } + bool IsNews { get; } + bool IsKids { get; } + bool IsRepeat { get; set; } + bool IsSeries { get; set; } + ProgramAudio? Audio { get; set; } + string EpisodeTitle { get; set; } + string ServiceName { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/IHasSeries.cs b/MediaBrowser.Controller/Entities/IHasSeries.cs index 7da53f730..475a2ab85 100644 --- a/MediaBrowser.Controller/Entities/IHasSeries.cs +++ b/MediaBrowser.Controller/Entities/IHasSeries.cs @@ -9,11 +9,14 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The name of the series.</value> string SeriesName { get; set; } + string FindSeriesName(); string FindSeriesSortName(); Guid SeriesId { get; set; } + Guid FindSeriesId(); string SeriesPresentationUniqueKey { get; set; } + string FindSeriesPresentationUniqueKey(); } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 496bee857..466cda67c 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -21,100 +21,167 @@ namespace MediaBrowser.Controller.Entities public BaseItem SimilarTo { get; set; } public bool? IsFolder { get; set; } + public bool? IsFavorite { get; set; } + public bool? IsFavoriteOrLiked { get; set; } + public bool? IsLiked { get; set; } + public bool? IsPlayed { get; set; } + public bool? IsResumable { get; set; } + public bool? IncludeItemsByName { get; set; } public string[] MediaTypes { get; set; } + public string[] IncludeItemTypes { get; set; } + public string[] ExcludeItemTypes { get; set; } + public string[] ExcludeTags { get; set; } + public string[] ExcludeInheritedTags { get; set; } + public string[] Genres { get; set; } public bool? IsSpecialSeason { get; set; } + public bool? IsMissing { get; set; } + public bool? IsUnaired { get; set; } + public bool? CollapseBoxSetItems { get; set; } public string NameStartsWithOrGreater { get; set; } + public string NameStartsWith { get; set; } + public string NameLessThan { get; set; } + public string NameContains { get; set; } + public string MinSortName { get; set; } public string PresentationUniqueKey { get; set; } + public string Path { get; set; } + public string Name { get; set; } public string Person { get; set; } + public Guid[] PersonIds { get; set; } + public Guid[] ItemIds { get; set; } + public Guid[] ExcludeItemIds { get; set; } + public string AdjacentTo { get; set; } + public string[] PersonTypes { get; set; } public bool? Is3D { get; set; } + public bool? IsHD { get; set; } + public bool? IsLocked { get; set; } + public bool? IsPlaceHolder { get; set; } public bool? HasImdbId { get; set; } + public bool? HasOverview { get; set; } + public bool? HasTmdbId { get; set; } + public bool? HasOfficialRating { get; set; } + public bool? HasTvdbId { get; set; } + public bool? HasThemeSong { get; set; } + public bool? HasThemeVideo { get; set; } + public bool? HasSubtitles { get; set; } + public bool? HasSpecialFeature { get; set; } + public bool? HasTrailer { get; set; } + public bool? HasParentalRating { get; set; } public Guid[] StudioIds { get; set; } + public Guid[] GenreIds { get; set; } + public ImageType[] ImageTypes { get; set; } + public VideoType[] VideoTypes { get; set; } + public UnratedItem[] BlockUnratedItems { get; set; } + public int[] Years { get; set; } + public string[] Tags { get; set; } + public string[] OfficialRatings { get; set; } public DateTime? MinPremiereDate { get; set; } + public DateTime? MaxPremiereDate { get; set; } + public DateTime? MinStartDate { get; set; } + public DateTime? MaxStartDate { get; set; } + public DateTime? MinEndDate { get; set; } + public DateTime? MaxEndDate { get; set; } + public bool? IsAiring { get; set; } public bool? IsMovie { get; set; } + public bool? IsSports { get; set; } + public bool? IsKids { get; set; } + public bool? IsNews { get; set; } + public bool? IsSeries { get; set; } + public int? MinIndexNumber { get; set; } + public int? AiredDuringSeason { get; set; } + public double? MinCriticRating { get; set; } + public double? MinCommunityRating { get; set; } public Guid[] ChannelIds { get; set; } public int? ParentIndexNumber { get; set; } + public int? ParentIndexNumberNotEquals { get; set; } + public int? IndexNumber { get; set; } + public int? MinParentalRating { get; set; } + public int? MaxParentalRating { get; set; } public bool? HasDeadParentId { get; set; } + public bool? IsVirtualItem { get; set; } public Guid ParentId { get; set; } + public string ParentType { get; set; } + public Guid[] AncestorIds { get; set; } + public Guid[] TopParentIds { get; set; } public BaseItem Parent @@ -135,41 +202,65 @@ namespace MediaBrowser.Controller.Entities } public string[] PresetViews { get; set; } + public TrailerType[] TrailerTypes { get; set; } + public SourceType[] SourceTypes { get; set; } public SeriesStatus[] SeriesStatuses { get; set; } + public string ExternalSeriesId { get; set; } + public string ExternalId { get; set; } public Guid[] AlbumIds { get; set; } + public Guid[] ArtistIds { get; set; } + public Guid[] ExcludeArtistIds { get; set; } + public string AncestorWithPresentationUniqueKey { get; set; } + public string SeriesPresentationUniqueKey { get; set; } public bool GroupByPresentationUniqueKey { get; set; } + public bool GroupBySeriesPresentationUniqueKey { get; set; } + public bool EnableTotalRecordCount { get; set; } + public bool ForceDirect { get; set; } + public Dictionary<string, string> ExcludeProviderIds { get; set; } + public bool EnableGroupByMetadataKey { get; set; } + public bool? HasChapterImages { get; set; } public IReadOnlyList<(string, SortOrder)> OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } + public DateTime? MinDateLastSaved { get; set; } + public DateTime? MinDateLastSavedForUser { get; set; } public DtoOptions DtoOptions { get; set; } + public int MinSimilarityScore { get; set; } + public string HasNoAudioTrackWithLanguage { get; set; } + public string HasNoInternalSubtitleTrackWithLanguage { get; set; } + public string HasNoExternalSubtitleTrackWithLanguage { get; set; } + public string HasNoSubtitleTrackWithLanguage { get; set; } + public bool? IsDeadArtist { get; set; } + public bool? IsDeadStudio { get; set; } + public bool? IsDeadPerson { get; set; } public InternalItemsQuery() @@ -240,17 +331,29 @@ namespace MediaBrowser.Controller.Entities } public Dictionary<string, string> HasAnyProviderId { get; set; } + public Guid[] AlbumArtistIds { get; set; } + public Guid[] BoxSetLibraryFolders { get; set; } + public Guid[] ContributingArtistIds { get; set; } + public bool? HasAired { get; set; } + public bool? HasOwnerId { get; set; } + public bool? Is4K { get; set; } + public int? MaxHeight { get; set; } + public int? MaxWidth { get; set; } + public int? MinHeight { get; set; } + public int? MinWidth { get; set; } + public string SearchTerm { get; set; } + public string SeriesTimerId { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs index d88c31007..cb698794b 100644 --- a/MediaBrowser.Controller/Entities/LinkedChild.cs +++ b/MediaBrowser.Controller/Entities/LinkedChild.cs @@ -9,7 +9,9 @@ namespace MediaBrowser.Controller.Entities public class LinkedChild { public string Path { get; set; } + public LinkedChildType Type { get; set; } + public string LibraryItemId { get; set; } [JsonIgnore] @@ -63,6 +65,7 @@ namespace MediaBrowser.Controller.Entities { return _fileSystem.AreEqual(x.Path, y.Path); } + return false; } diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 2fb613768..c39495759 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -113,6 +113,7 @@ namespace MediaBrowser.Controller.Entities return true; } } + return false; } } diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 9e4f9d47e..56106a266 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Entities list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string CreatePresentationUniqueKey() { return GetUserDataKeys()[0]; @@ -114,6 +115,7 @@ namespace MediaBrowser.Controller.Entities Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); return true; } + return base.RequiresRefresh(); } diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 5ebc9f16a..82d0826c5 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.Entities return photoAlbum; } } + return null; } } @@ -68,17 +69,27 @@ namespace MediaBrowser.Controller.Entities } public string CameraMake { get; set; } + public string CameraModel { get; set; } + public string Software { get; set; } + public double? ExposureTime { get; set; } + public double? FocalLength { get; set; } + public ImageOrientation? Orientation { get; set; } + public double? Aperture { get; set; } + public double? ShutterSpeed { get; set; } public double? Latitude { get; set; } + public double? Longitude { get; set; } + public double? Altitude { get; set; } + public int? IsoSpeedRating { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Share.cs b/MediaBrowser.Controller/Entities/Share.cs index c17789ccc..a51f2b452 100644 --- a/MediaBrowser.Controller/Entities/Share.cs +++ b/MediaBrowser.Controller/Entities/Share.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Controller.Entities public class Share { public string UserId { get; set; } + public bool CanEdit { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 068032317..b5ee1e952 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Controller.Entities list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); return list; } + public override string CreatePresentationUniqueKey() { return GetUserDataKeys()[0]; @@ -93,6 +94,7 @@ namespace MediaBrowser.Controller.Entities Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); return true; } + return base.RequiresRefresh(); } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 4ec60e7cd..ec95c0e66 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -34,7 +34,9 @@ namespace MediaBrowser.Controller.Entities.TV /// </summary> /// <value>The aired season.</value> public int? AirsBeforeSeasonNumber { get; set; } + public int? AirsAfterSeasonNumber { get; set; } + public int? AirsBeforeEpisodeNumber { get; set; } /// <summary> @@ -94,6 +96,7 @@ namespace MediaBrowser.Controller.Entities.TV { take--; } + list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); } @@ -114,6 +117,7 @@ namespace MediaBrowser.Controller.Entities.TV { seriesId = FindSeriesId(); } + return !seriesId.Equals(Guid.Empty) ? (LibraryManager.GetItemById(seriesId) as Series) : null; } } @@ -128,6 +132,7 @@ namespace MediaBrowser.Controller.Entities.TV { seasonId = FindSeasonId(); } + return !seasonId.Equals(Guid.Empty) ? (LibraryManager.GetItemById(seasonId) as Season) : null; } } @@ -160,6 +165,7 @@ namespace MediaBrowser.Controller.Entities.TV { return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture); } + return "Season Unknown"; } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 7dfd1a759..c96acf9ca 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -81,6 +81,7 @@ namespace MediaBrowser.Controller.Entities.TV { seriesId = FindSeriesId(); } + return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series); } } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a519089b3..315da7a3b 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.Entities.TV } public DayOfWeek[] AirDays { get; set; } + public string AirTime { get; set; } [JsonIgnore] @@ -150,6 +151,7 @@ namespace MediaBrowser.Controller.Entities.TV { query.IncludeItemTypes = new[] { typeof(Episode).Name }; } + query.IsVirtualItem = false; query.Limit = 0; var totalRecordCount = LibraryManager.GetCount(query); diff --git a/MediaBrowser.Controller/Entities/UserItemData.cs b/MediaBrowser.Controller/Entities/UserItemData.cs index ab425ee0f..4d8db99c4 100644 --- a/MediaBrowser.Controller/Entities/UserItemData.cs +++ b/MediaBrowser.Controller/Entities/UserItemData.cs @@ -105,6 +105,7 @@ namespace MediaBrowser.Controller.Entities return null; } + set { if (value.HasValue) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index dbfef0777..061e6001c 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -960,6 +960,7 @@ namespace MediaBrowser.Controller.Entities .OfType<Folder>() .Where(UserView.IsEligibleForGrouping); } + return _libraryManager.GetUserRootFolder() .GetChildren(user, true) .OfType<Folder>() @@ -978,6 +979,7 @@ namespace MediaBrowser.Controller.Entities return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); }).ToArray(); } + return GetMediaFolders(user) .Where(i => { diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 4cfa0e74d..8b534f05d 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -28,7 +28,9 @@ namespace MediaBrowser.Controller.Entities public string PrimaryVersionId { get; set; } public string[] AdditionalParts { get; set; } + public string[] LocalAlternateVersions { get; set; } + public LinkedChild[] LinkedAlternateVersions { get; set; } [JsonIgnore] @@ -52,15 +54,18 @@ namespace MediaBrowser.Controller.Entities { return false; } + if (extraType.Value == Model.Entities.ExtraType.ThemeVideo) { return false; } + if (extraType.Value == Model.Entities.ExtraType.Trailer) { return false; } } + return true; } } @@ -196,6 +201,7 @@ namespace MediaBrowser.Controller.Entities return video.MediaSourceCount; } } + return LinkedAlternateVersions.Length + LocalAlternateVersions.Length + 1; } } @@ -390,11 +396,13 @@ namespace MediaBrowser.Controller.Entities AdditionalParts = newVideo.AdditionalParts; updateType |= ItemUpdateType.MetadataImport; } + if (!LocalAlternateVersions.SequenceEqual(newVideo.LocalAlternateVersions, StringComparer.Ordinal)) { LocalAlternateVersions = newVideo.LocalAlternateVersions; updateType |= ItemUpdateType.MetadataImport; } + if (VideoType != newVideo.VideoType) { VideoType = newVideo.VideoType; @@ -416,6 +424,7 @@ namespace MediaBrowser.Controller.Entities .Select(i => i.FullName) .ToArray(); } + if (videoType == VideoType.BluRay) { return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true) @@ -425,6 +434,7 @@ namespace MediaBrowser.Controller.Entities .Select(i => i.FullName) .ToArray(); } + return Array.Empty<string>(); } diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index a01ef5c31..d65b90c25 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -103,6 +103,7 @@ namespace MediaBrowser.Controller.Entities Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); return true; } + return base.RequiresRefresh(); } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index aa7373815..e655f50eb 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.Controller.IO { dict[file.FullName] = file; } + return dict; } @@ -49,6 +50,7 @@ namespace MediaBrowser.Controller.IO { throw new ArgumentNullException(nameof(path)); } + if (args == null) { throw new ArgumentNullException(nameof(args)); @@ -116,6 +118,7 @@ namespace MediaBrowser.Controller.IO returnResult[index] = value; index++; } + return returnResult; } } diff --git a/MediaBrowser.Controller/Library/DeleteOptions.cs b/MediaBrowser.Controller/Library/DeleteOptions.cs index 751b90481..2944d8259 100644 --- a/MediaBrowser.Controller/Library/DeleteOptions.cs +++ b/MediaBrowser.Controller/Library/DeleteOptions.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Controller.Library public class DeleteOptions { public bool DeleteFileLocation { get; set; } + public bool DeleteFromExternalProvider { get; set; } public DeleteOptions() diff --git a/MediaBrowser.Controller/Library/ILiveStream.cs b/MediaBrowser.Controller/Library/ILiveStream.cs index 734932f17..7c9a9b20e 100644 --- a/MediaBrowser.Controller/Library/ILiveStream.cs +++ b/MediaBrowser.Controller/Library/ILiveStream.cs @@ -9,10 +9,15 @@ namespace MediaBrowser.Controller.Library Task Open(CancellationToken openCancellationToken); Task Close(); int ConsumerCount { get; set; } + string OriginalStreamId { get; set; } + string TunerHostId { get; } + bool EnableStreamSharing { get; } + MediaSourceInfo MediaSource { get; set; } + string UniqueId { get; } } } diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index cca85cd3b..096708ee3 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -129,6 +129,7 @@ namespace MediaBrowser.Controller.Library return item != null; } + return false; } @@ -256,6 +257,7 @@ namespace MediaBrowser.Controller.Library if (args.Path == null && Path == null) return true; return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path); } + return false; } diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs index b4e205184..1ed69975c 100644 --- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs +++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs @@ -13,18 +13,27 @@ namespace MediaBrowser.Controller.Library public class PlaybackProgressEventArgs : EventArgs { public List<User> Users { get; set; } + public long? PlaybackPositionTicks { get; set; } + public BaseItem Item { get; set; } + public BaseItemDto MediaInfo { get; set; } + public string MediaSourceId { get; set; } + public bool IsPaused { get; set; } + public bool IsAutomated { get; set; } public string DeviceId { get; set; } + public string DeviceName { get; set; } + public string ClientName { get; set; } public string PlaySessionId { get; set; } + public SessionInfo Session { get; set; } public PlaybackProgressEventArgs() diff --git a/MediaBrowser.Controller/Library/Profiler.cs b/MediaBrowser.Controller/Library/Profiler.cs index 0febef3d3..c4935868d 100644 --- a/MediaBrowser.Controller/Library/Profiler.cs +++ b/MediaBrowser.Controller/Library/Profiler.cs @@ -67,6 +67,7 @@ namespace MediaBrowser.Controller.Library message = string.Format("{0} took {1} seconds.", _name, ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000")); } + _logger.LogInformation(message); } } diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index fd5fb6748..885488851 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -40,6 +40,7 @@ namespace MediaBrowser.Controller.Library return new DayOfWeek[] { }; } + return null; } } diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs index 70477fce7..384ca62aa 100644 --- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs @@ -67,8 +67,11 @@ namespace MediaBrowser.Controller.LiveTv public bool? IsFavorite { get; set; } public bool? IsHD { get; set; } + public string AudioCodec { get; set; } + public string VideoCodec { get; set; } + public string[] Tags { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index bc3bf78f0..4ac40fe88 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -286,8 +286,11 @@ namespace MediaBrowser.Controller.LiveTv public class ActiveRecordingInfo { public string Id { get; set; } + public string Path { get; set; } + public TimerInfo Timer { get; set; } + public CancellationTokenSource CancellationTokenSource { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 240ba8c23..3679e4f78 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -50,6 +50,7 @@ namespace MediaBrowser.Controller.LiveTv get; } } + public interface IConfigurableTunerHost { /// <summary> diff --git a/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs index 92b8ee67c..0e09d1aeb 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Controller.LiveTv public LiveTvConflictException() { } + public LiveTvConflictException(string message) : base(message) { diff --git a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs index 5d0f13192..aa7ad6ff7 100644 --- a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs @@ -199,6 +199,7 @@ namespace MediaBrowser.Controller.LiveTv public string Etag { get; set; } public Dictionary<string, string> ProviderIds { get; set; } + public Dictionary<string, string> SeriesProviderIds { get; set; } public ProgramInfo() diff --git a/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs b/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs index 4fbd496c5..6e7acaae3 100644 --- a/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs @@ -57,6 +57,7 @@ namespace MediaBrowser.Controller.LiveTv public bool RecordAnyChannel { get; set; } public int KeepUpTo { get; set; } + public KeepUntil KeepUntil { get; set; } public bool SkipEpisodesInLibrary { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index 46774b2b7..df98bb6af 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -18,7 +18,9 @@ namespace MediaBrowser.Controller.LiveTv } public Dictionary<string, string> ProviderIds { get; set; } + public Dictionary<string, string> SeriesProviderIds { get; set; } + public string[] Tags { get; set; } /// <summary> @@ -146,10 +148,15 @@ namespace MediaBrowser.Controller.LiveTv public bool IsRepeat { get; set; } public string HomePageUrl { get; set; } + public float? CommunityRating { get; set; } + public string OfficialRating { get; set; } + public string[] Genres { get; set; } + public string RecordingPath { get; set; } + public KeepUntil KeepUntil { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs index cb02da635..df3f55c26 100644 --- a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs +++ b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs @@ -3,8 +3,11 @@ namespace MediaBrowser.Controller.LiveTv public class TunerChannelMapping { public string Name { get; set; } + public string ProviderChannelName { get; set; } + public string ProviderChannelId { get; set; } + public string Id { get; set; } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ec90d28f7..4fff46f4e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1699,6 +1699,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return (null, null); } + if (!videoHeight.HasValue && !requestedHeight.HasValue) { return (null, null); @@ -2569,8 +2570,10 @@ namespace MediaBrowser.Controller.MediaEncoding encodingOptions.HardwareDecodingCodecs = Array.Empty<string>(); return null; } + return "-c:v h264_qsv"; } + break; case "hevc": case "h265": @@ -2579,18 +2582,21 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_qsv"; } + break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_qsv"; } + break; case "vc1": if (_mediaEncoder.SupportsDecoder("vc1_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vc1_qsv"; } + break; case "vp8": if (_mediaEncoder.SupportsDecoder("vp8_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase)) @@ -2615,8 +2621,16 @@ namespace MediaBrowser.Controller.MediaEncoding case "h264": if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase)) { + // cuvid decoder does not support 10-bit input. + if ((videoStream.BitDepth ?? 8) > 8) + { + encodingOptions.HardwareDecodingCodecs = Array.Empty<string>(); + return null; + } + return "-c:v h264_cuvid"; } + break; case "hevc": case "h265": @@ -2625,24 +2639,28 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_cuvid"; } + break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_cuvid"; } + break; case "vc1": if (_mediaEncoder.SupportsDecoder("vc1_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vc1_cuvid"; } + break; case "mpeg4": if (_mediaEncoder.SupportsDecoder("mpeg4_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg4_cuvid"; } + break; case "vp8": if (_mediaEncoder.SupportsDecoder("vp8_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase)) @@ -2669,6 +2687,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-c:v h264_mediacodec"; } + break; case "hevc": case "h265": @@ -2677,24 +2696,28 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_mediacodec"; } + break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_mediacodec"; } + break; case "mpeg4": if (_mediaEncoder.SupportsDecoder("mpeg4_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg4_mediacodec"; } + break; case "vp8": if (_mediaEncoder.SupportsDecoder("vp8_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase)) { return "-c:v vp8_mediacodec"; } + break; case "vp9": if (_mediaEncoder.SupportsDecoder("vp9_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) @@ -2702,6 +2725,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_mediacodec"; } + break; } } @@ -2715,24 +2739,28 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-c:v h264_mmal"; } + break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_mmal"; } + break; case "mpeg4": if (_mediaEncoder.SupportsDecoder("mpeg4_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg4_mmal"; } + break; case "vc1": if (_mediaEncoder.SupportsDecoder("vc1_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vc1_mmal"; } + break; } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index acf1aae89..0d6654f85 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -127,13 +127,19 @@ namespace MediaBrowser.Controller.MediaEncoding public string AlbumCoverPath { get; set; } public string InputAudioSync { get; set; } + public string InputVideoSync { get; set; } + public TransportStreamTimestamp InputTimestamp { get; set; } public MediaStream AudioStream { get; set; } + public string[] SupportedAudioCodecs { get; set; } + public string[] SupportedVideoCodecs { get; set; } + public string InputContainer { get; set; } + public IsoType? IsoType { get; set; } public BaseEncodingJobOptions BaseRequest { get; set; } @@ -293,6 +299,7 @@ namespace MediaBrowser.Controller.MediaEncoding } public bool IsVideoRequest { get; set; } + public TranscodingJobType TranscodingType { get; set; } public EncodingJobInfo(TranscodingJobType jobType) @@ -672,6 +679,7 @@ namespace MediaBrowser.Controller.MediaEncoding } public IProgress<double> Progress { get; set; } + public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) { Progress.Report(percentComplete.Value); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index addc88174..8f6fcb9ab 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -9,9 +9,11 @@ namespace MediaBrowser.Controller.MediaEncoding public class EncodingJobOptions : BaseEncodingJobOptions { public string OutputDirectory { get; set; } + public string ItemId { get; set; } public string TempDirectory { get; set; } + public bool ReadInputAtNativeFramerate { get; set; } /// <summary> @@ -47,6 +49,7 @@ namespace MediaBrowser.Controller.MediaEncoding { SubtitleStreamIndex = info.SubtitleStreamIndex; } + StreamOptions = info.StreamOptions; } } @@ -81,7 +84,9 @@ namespace MediaBrowser.Controller.MediaEncoding public bool EnableAutoStreamCopy { get; set; } public bool AllowVideoStreamCopy { get; set; } + public bool AllowAudioStreamCopy { get; set; } + public bool BreakOnNonKeyFrames { get; set; } /// <summary> @@ -197,10 +202,15 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "MaxVideoBitDepth", Description = "Optional.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? MaxVideoBitDepth { get; set; } + public bool RequireAvc { get; set; } + public bool DeInterlace { get; set; } + public bool RequireNonAnamorphic { get; set; } + public int? TranscodingMaxAudioChannels { get; set; } + public int? CpuCoreLimit { get; set; } public string LiveStreamId { get; set; } diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs index b78ef0b80..39a47792a 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs @@ -8,9 +8,13 @@ namespace MediaBrowser.Controller.MediaEncoding public class MediaInfoRequest { public MediaSourceInfo MediaSource { get; set; } + public bool ExtractChapters { get; set; } + public DlnaProfileType MediaType { get; set; } + public IIsoMount MountedIso { get; set; } + public string[] PlayableStreamFileNames { get; set; } public MediaInfoRequest() diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index 29fb81e32..ba3c715b8 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -58,8 +58,11 @@ namespace MediaBrowser.Controller.Net public interface IAuthenticationAttributes { bool EscapeParentalControl { get; } + bool AllowBeforeStartupWizard { get; } + bool AllowLocal { get; } + bool AllowLocalOnly { get; } string[] GetRoles(); diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index df90c399b..43016e1c9 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -254,7 +254,9 @@ namespace MediaBrowser.Controller.Net public class WebSocketListenerState { public DateTime DateLastSendUtc { get; set; } + public long InitialDelayMs { get; set; } + public long IntervalMs { get; set; } } } diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs index 071beaed1..85772e036 100644 --- a/MediaBrowser.Controller/Net/StaticResultOptions.cs +++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs @@ -8,8 +8,11 @@ namespace MediaBrowser.Controller.Net public class StaticResultOptions { public string ContentType { get; set; } + public TimeSpan? CacheDuration { get; set; } + public DateTime? DateLastModified { get; set; } + public Func<Task<Stream>> ContentFactory { get; set; } public bool IsHeadRequest { get; set; } @@ -17,9 +20,11 @@ namespace MediaBrowser.Controller.Net public IDictionary<string, string> ResponseHeaders { get; set; } public Action OnComplete { get; set; } + public Action OnError { get; set; } public string Path { get; set; } + public long? ContentLength { get; set; } public FileShare FileShare { get; set; } diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs index aac41369c..3f8c409f5 100644 --- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs @@ -7,11 +7,13 @@ namespace MediaBrowser.Controller.Providers public class ImageRefreshOptions { public MetadataRefreshMode ImageRefreshMode { get; set; } + public IDirectoryService DirectoryService { get; private set; } public bool ReplaceAllImages { get; set; } public ImageType[] ReplaceImages { get; set; } + public bool IsAutomated { get; set; } public ImageRefreshOptions(IDirectoryService directoryService) diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 59adaedfa..af955774f 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -48,6 +48,7 @@ namespace MediaBrowser.Controller.Providers { People = new List<PersonInfo>(); } + People.Clear(); } diff --git a/MediaBrowser.Controller/Resolvers/IItemResolver.cs b/MediaBrowser.Controller/Resolvers/IItemResolver.cs index 16e37d249..751ca8098 100644 --- a/MediaBrowser.Controller/Resolvers/IItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/IItemResolver.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.Controller.Resolvers public class MultiItemResolverResult { public List<BaseItem> Items { get; set; } + public List<FileSystemMetadata> ExtraFiles { get; set; } public MultiItemResolverResult() diff --git a/MediaBrowser.Controller/Security/AuthenticationInfo.cs b/MediaBrowser.Controller/Security/AuthenticationInfo.cs index 828213588..1d0b959b7 100644 --- a/MediaBrowser.Controller/Security/AuthenticationInfo.cs +++ b/MediaBrowser.Controller/Security/AuthenticationInfo.cs @@ -65,6 +65,7 @@ namespace MediaBrowser.Controller.Security public DateTime? DateRevoked { get; set; } public DateTime DateLastActivity { get; set; } + public string UserName { get; set; } } } diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs index a28f47a9c..685ca3bdd 100644 --- a/MediaBrowser.Controller/Session/AuthenticationRequest.cs +++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs @@ -5,13 +5,21 @@ namespace MediaBrowser.Controller.Session public class AuthenticationRequest { public string Username { get; set; } + public Guid UserId { get; set; } + public string Password { get; set; } + public string PasswordSha1 { get; set; } + public string App { get; set; } + public string AppVersion { get; set; } + public string DeviceId { get; set; } + public string DeviceName { get; set; } + public string RemoteEndPoint { get; set; } } } diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 2ba7c9fec..36bc11be4 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -61,6 +61,7 @@ namespace MediaBrowser.Controller.Session { return Array.Empty<string>(); } + return Capabilities.PlayableMediaTypes; } } @@ -154,6 +155,7 @@ namespace MediaBrowser.Controller.Session return true; } } + if (controllers.Length > 0) { return false; @@ -255,6 +257,7 @@ namespace MediaBrowser.Controller.Session return true; } } + return false; } @@ -292,6 +295,7 @@ namespace MediaBrowser.Controller.Session { return; } + if (progressInfo.IsPaused) { return; @@ -334,6 +338,7 @@ namespace MediaBrowser.Controller.Session _progressTimer.Dispose(); _progressTimer = null; } + _lastProgressInfo = null; } } diff --git a/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs b/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs index b8ba35a5f..ad6025927 100644 --- a/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs +++ b/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs @@ -5,8 +5,11 @@ namespace MediaBrowser.Controller.Subtitles public class SubtitleResponse { public string Language { get; set; } + public string Format { get; set; } + public bool IsForced { get; set; } + public Stream Stream { get; set; } } } diff --git a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs index 61dc72258..a202723b9 100644 --- a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs +++ b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs @@ -8,23 +8,35 @@ namespace MediaBrowser.Controller.Subtitles public class SubtitleSearchRequest : IHasProviderIds { public string Language { get; set; } + public string TwoLetterISOLanguageName { get; set; } public VideoContentType ContentType { get; set; } public string MediaPath { get; set; } + public string SeriesName { get; set; } + public string Name { get; set; } + public int? IndexNumber { get; set; } + public int? IndexNumberEnd { get; set; } + public int? ParentIndexNumber { get; set; } + public int? ProductionYear { get; set; } + public long? RuntimeTicks { get; set; } + public bool IsPerfectMatch { get; set; } + public Dictionary<string, string> ProviderIds { get; set; } public bool SearchAllProviders { get; set; } + public string[] DisabledSubtitleFetchers { get; set; } + public string[] SubtitleFetcherOrder { get; set; } public SubtitleSearchRequest() diff --git a/MediaBrowser.Controller/Sync/SyncedFileInfo.cs b/MediaBrowser.Controller/Sync/SyncedFileInfo.cs index 2ff40addb..687a46d78 100644 --- a/MediaBrowser.Controller/Sync/SyncedFileInfo.cs +++ b/MediaBrowser.Controller/Sync/SyncedFileInfo.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Controller.Sync /// </summary> /// <value>The path.</value> public string Path { get; set; } + public string[] PathParts { get; set; } /// <summary> /// Gets or sets the protocol. diff --git a/MediaBrowser.Controller/SyncPlay/GroupInfo.cs b/MediaBrowser.Controller/SyncPlay/GroupInfo.cs index ef8df7d02..d0fac1efa 100644 --- a/MediaBrowser.Controller/SyncPlay/GroupInfo.cs +++ b/MediaBrowser.Controller/SyncPlay/GroupInfo.cs @@ -122,6 +122,7 @@ namespace MediaBrowser.Controller.SyncPlay { max = Math.Max(max, session.Ping); } + return max; } diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index 2f4cca5ff..9d23d80b8 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -75,6 +75,7 @@ namespace MediaBrowser.LocalMetadata.Images } } } + return list; } } diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 0ceb55c57..f954d4192 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -24,6 +24,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// The logger /// </summary> protected ILogger<BaseItemXmlParser<T>> Logger { get; private set; } + protected IProviderManager ProviderManager { get; private set; } private Dictionary<string, string> _validProviderIds; @@ -150,6 +151,7 @@ namespace MediaBrowser.LocalMetadata.Parsers Logger.LogWarning("Invalid Added value found: " + val); } } + break; } @@ -161,6 +163,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.OriginalTitle = val; } + break; } @@ -191,6 +194,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.ForcedSortName = val; } + break; } @@ -274,6 +278,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -290,6 +295,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -302,6 +308,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.OfficialRating = rating; } + break; } @@ -313,6 +320,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.CustomRating = val; } + break; } @@ -327,6 +335,7 @@ namespace MediaBrowser.LocalMetadata.Parsers item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } } + break; } @@ -339,6 +348,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { hasAspectRatio.AspectRatio = val; } + break; } @@ -350,6 +360,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } + break; } @@ -361,8 +372,10 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + item.AddStudio(name); } + break; } @@ -374,8 +387,10 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + itemResult.AddPerson(p); } + break; } case "Writer": @@ -386,8 +401,10 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + itemResult.AddPerson(p); } + break; } @@ -411,9 +428,11 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + itemResult.AddPerson(p); } } + break; } @@ -425,8 +444,10 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + itemResult.AddPerson(p); } + break; } @@ -438,6 +459,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.AddTrailerUrl(val); } + break; } @@ -453,6 +475,7 @@ namespace MediaBrowser.LocalMetadata.Parsers hasDisplayOrder.DisplayOrder = val; } } + break; } @@ -469,6 +492,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -501,6 +525,7 @@ namespace MediaBrowser.LocalMetadata.Parsers item.CommunityRating = val; } } + break; } @@ -544,6 +569,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.SetProviderId(MetadataProvider.TmdbCollection, tmdbCollection); } + break; case "Genres": @@ -559,6 +585,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -575,6 +602,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -591,6 +619,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -607,6 +636,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -627,6 +657,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; } @@ -659,6 +690,7 @@ namespace MediaBrowser.LocalMetadata.Parsers video.Video3DFormat = Video3DFormat.MVC; } } + break; } @@ -682,6 +714,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } } } + private void FetchFromSharesNode(XmlReader reader, IHasShares item) { var list = new List<Share>(); @@ -716,6 +749,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; } + default: { reader.Skip(); @@ -791,6 +825,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { } + break; } @@ -831,8 +866,10 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.Tagline = val; } + break; } + default: reader.Skip(); break; @@ -870,6 +907,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.AddGenre(genre); } + break; } @@ -907,6 +945,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { tags.Add(tag); } + break; } @@ -949,6 +988,7 @@ namespace MediaBrowser.LocalMetadata.Parsers reader.Read(); continue; } + using (var subtree = reader.ReadSubtree()) { foreach (var person in GetPersonsFromXmlNode(subtree)) @@ -957,9 +997,11 @@ namespace MediaBrowser.LocalMetadata.Parsers { continue; } + item.AddPerson(person); } } + break; } @@ -995,6 +1037,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.AddTrailerUrl(val); } + break; } @@ -1035,6 +1078,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { item.AddStudio(studio); } + break; } @@ -1084,6 +1128,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { type = val; } + break; } @@ -1095,6 +1140,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { role = val; } + break; } case "SortOrder": @@ -1108,6 +1154,7 @@ namespace MediaBrowser.LocalMetadata.Parsers sortOrder = intVal; } } + break; } @@ -1206,6 +1253,7 @@ namespace MediaBrowser.LocalMetadata.Parsers item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase); break; } + default: { reader.Skip(); diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs index ca11a079d..dd4eefa50 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; default: @@ -69,6 +70,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; } + default: { reader.Skip(); diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index 54710cd82..941ed1b95 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { reader.Read(); } + break; default: @@ -77,6 +78,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; } + default: { reader.Skip(); diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 071902393..70fd63ff3 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -32,10 +32,15 @@ namespace MediaBrowser.LocalMetadata.Savers } protected IFileSystem FileSystem { get; private set; } + protected IServerConfigurationManager ConfigurationManager { get; private set; } + protected ILibraryManager LibraryManager { get; private set; } + protected IUserManager UserManager { get; private set; } + protected IUserDataManager UserDataManager { get; private set; } + protected ILogger<BaseXmlSaver> Logger { get; private set; } public string Name => XmlProviderUtils.Name; @@ -185,6 +190,7 @@ namespace MediaBrowser.LocalMetadata.Savers { writer.WriteElementString("OriginalTitle", item.OriginalTitle); } + if (!string.IsNullOrEmpty(item.CustomRating)) { writer.WriteElementString("CustomRating", item.CustomRating); @@ -278,6 +284,7 @@ namespace MediaBrowser.LocalMetadata.Savers { writer.WriteElementString("Language", item.PreferredMetadataLanguage); } + if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode)) { writer.WriteElementString("CountryCode", item.PreferredMetadataCountryCode); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 82f6ce15e..a8df27d38 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -229,6 +229,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { return inJellyfinPath; } + var values = Environment.GetEnvironmentVariable("PATH"); foreach (var path in values.Split(Path.PathSeparator)) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 7d57a691e..918694e66 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -93,6 +93,7 @@ namespace MediaBrowser.MediaEncoding.Probing { overview = FFProbeHelpers.GetDictionaryValue(tags, "description"); } + if (string.IsNullOrWhiteSpace(overview)) { overview = FFProbeHelpers.GetDictionaryValue(tags, "desc"); @@ -274,10 +275,12 @@ namespace MediaBrowser.MediaEncoding.Probing reader.Read(); continue; } + using (var subtree = reader.ReadSubtree()) { ReadFromDictNode(subtree, info); } + break; default: reader.Skip(); @@ -319,6 +322,7 @@ namespace MediaBrowser.MediaEncoding.Probing { ProcessPairs(currentKey, pairs, info); } + currentKey = reader.ReadElementContentAsString(); pairs = new List<NameValuePair>(); break; @@ -332,6 +336,7 @@ namespace MediaBrowser.MediaEncoding.Probing Value = value }); } + break; case "array": if (reader.IsEmptyElement) @@ -339,6 +344,7 @@ namespace MediaBrowser.MediaEncoding.Probing reader.Read(); continue; } + using (var subtree = reader.ReadSubtree()) { if (!string.IsNullOrWhiteSpace(currentKey)) @@ -346,6 +352,7 @@ namespace MediaBrowser.MediaEncoding.Probing pairs.AddRange(ReadValueArray(subtree)); } } + break; default: reader.Skip(); @@ -381,6 +388,7 @@ namespace MediaBrowser.MediaEncoding.Probing reader.Read(); continue; } + using (var subtree = reader.ReadSubtree()) { var dict = GetNameValuePair(subtree); @@ -389,6 +397,7 @@ namespace MediaBrowser.MediaEncoding.Probing pairs.Add(dict); } } + break; default: reader.Skip(); @@ -948,6 +957,7 @@ namespace MediaBrowser.MediaEncoding.Probing { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer }); } + audio.People = peoples.ToArray(); } @@ -979,6 +989,7 @@ namespace MediaBrowser.MediaEncoding.Probing { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer }); } + audio.People = peoples.ToArray(); } @@ -1012,6 +1023,7 @@ namespace MediaBrowser.MediaEncoding.Probing { albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist"); } + if (string.IsNullOrWhiteSpace(albumArtist)) { albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); @@ -1175,6 +1187,7 @@ namespace MediaBrowser.MediaEncoding.Probing { continue; } + if (info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) { continue; diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index f44cf1452..0e2d70017 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -23,6 +23,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles string line; while (reader.ReadLine() != "[Events]") { } + var headers = ParseFieldHeaders(reader.ReadLine()); while ((line = reader.ReadLine()) != null) @@ -56,6 +57,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles trackEvents.Add(subEvent); } } + trackInfo.TrackEvents = trackEvents.ToArray(); return trackInfo; } @@ -112,11 +114,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles { pre = s.Substring(0, 5) + "}"; } + int indexOfEnd = p.Text.IndexOf('}'); p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1); indexOfBegin = p.Text.IndexOf('{'); } + p.Text = pre + p.Text; } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index c98dd1502..a8d383a2a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { continue; } + var subEvent = new SubtitleTrackEvent { Id = line }; line = reader.ReadLine(); @@ -52,6 +53,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.LogWarning("Unrecognized line in srt: {0}", line); continue; } + subEvent.StartPositionTicks = GetTicks(time[0]); var endTime = time[1]; var idx = endTime.IndexOf(" ", StringComparison.Ordinal); @@ -65,8 +67,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles { break; } + multiline.Add(line); } + subEvent.Text = string.Join(ParserValues.NewLine, multiline); subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, @"\{(?:\\\d?[\w.-]+(?:\([^\)]*\)|&H?[0-9A-Fa-f]+&|))+\}", string.Empty, RegexOptions.IgnoreCase); @@ -76,6 +80,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles trackEvents.Add(subEvent); } } + trackInfo.TrackEvents = trackEvents.ToArray(); return trackInfo; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index bae2f5417..9a8fcc431 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -135,6 +135,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // subtitle.Renumber(1); } + trackInfo.TrackEvents = trackEvents.ToArray(); return trackInfo; } @@ -302,6 +303,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return count; index = text.IndexOf(tag, index + 1); } + return count; } @@ -329,6 +331,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { rest = string.Empty; } + extraTags += " size=\"" + fontSize.Substring(2) + "\""; } else if (rest.StartsWith("fn") && rest.Length > 2) @@ -344,6 +347,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { rest = string.Empty; } + extraTags += " face=\"" + fontName.Substring(2) + "\""; } else if (rest.StartsWith("c") && rest.Length > 2) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index e35a626d8..b9d526a22 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -115,6 +115,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { throw new ArgumentNullException(nameof(item)); } + if (string.IsNullOrWhiteSpace(mediaSourceId)) { throw new ArgumentNullException(nameof(mediaSourceId)); @@ -271,8 +272,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles } public string Path { get; set; } + public MediaProtocol Protocol { get; set; } + public string Format { get; set; } + public bool IsExternal { get; set; } } @@ -287,10 +291,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { return new SrtParser(_logger); } + if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) { return new SsaParser(); } + if (string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase)) { return new AssParser(); @@ -315,14 +321,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles { return new JsonWriter(); } + if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { return new SrtWriter(); } + if (string.Equals(format, SubtitleFormat.VTT, StringComparison.OrdinalIgnoreCase)) { return new VttWriter(); } + if (string.Equals(format, SubtitleFormat.TTML, StringComparison.OrdinalIgnoreCase)) { return new TtmlWriter(); diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 4229a4335..890469d36 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -10,17 +10,27 @@ namespace MediaBrowser.Model.Configuration public class LibraryOptions { public bool EnablePhotos { get; set; } + public bool EnableRealtimeMonitor { get; set; } + public bool EnableChapterImageExtraction { get; set; } + public bool ExtractChapterImagesDuringLibraryScan { get; set; } + public bool DownloadImagesInAdvance { get; set; } + public MediaPathInfo[] PathInfos { get; set; } public bool SaveLocalMetadata { get; set; } + public bool EnableInternetProviders { get; set; } + public bool ImportMissingEpisodes { get; set; } + public bool EnableAutomaticSeriesGrouping { get; set; } + public bool EnableEmbeddedTitles { get; set; } + public bool EnableEmbeddedEpisodeInfos { get; set; } public int AutomaticRefreshIntervalDays { get; set; } @@ -38,17 +48,25 @@ namespace MediaBrowser.Model.Configuration public string MetadataCountryCode { get; set; } public string SeasonZeroDisplayName { get; set; } + public string[] MetadataSavers { get; set; } + public string[] DisabledLocalMetadataReaders { get; set; } + public string[] LocalMetadataReaderOrder { get; set; } public string[] DisabledSubtitleFetchers { get; set; } + public string[] SubtitleFetcherOrder { get; set; } public bool SkipSubtitlesIfEmbeddedSubtitlesPresent { get; set; } + public bool SkipSubtitlesIfAudioTrackMatches { get; set; } + public string[] SubtitleDownloadLanguages { get; set; } + public bool RequirePerfectSubtitleMatch { get; set; } + public bool SaveSubtitlesWithMedia { get; set; } public TypeOptions[] TypeOptions { get; set; } @@ -89,17 +107,22 @@ namespace MediaBrowser.Model.Configuration public class MediaPathInfo { public string Path { get; set; } + public string NetworkPath { get; set; } } public class TypeOptions { public string Type { get; set; } + public string[] MetadataFetchers { get; set; } + public string[] MetadataFetcherOrder { get; set; } public string[] ImageFetchers { get; set; } + public string[] ImageFetcherOrder { get; set; } + public ImageOption[] ImageOptions { get; set; } public ImageOption GetImageOptions(ImageType type) diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 85d864eec..a5179f3ca 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -34,6 +34,7 @@ namespace MediaBrowser.Model.Configuration public string[] GroupedFolders { get; set; } public SubtitlePlaybackMode SubtitleMode { get; set; } + public bool DisplayCollectionsView { get; set; } public bool EnableLocalPassword { get; set; } @@ -41,12 +42,15 @@ namespace MediaBrowser.Model.Configuration public string[] OrderedViews { get; set; } public string[] LatestItemsExcludes { get; set; } + public string[] MyMediaExcludes { get; set; } public bool HidePlayedInLatest { get; set; } public bool RememberAudioSelections { get; set; } + public bool RememberSubtitleSelections { get; set; } + public bool EnableNextEpisodeAutoPlay { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs index c48a38192..4d5f996f8 100644 --- a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Model.Configuration public string ReleaseDateFormat { get; set; } public bool SaveImagePathsInNfo { get; set; } + public bool EnablePathSubstitution { get; set; } public bool EnableExtraThumbsDuplication { get; set; } diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index fc555c5f7..1468b0414 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -85,6 +85,7 @@ namespace MediaBrowser.Model.Dlna { return Profile.MaxStaticMusicBitrate; } + return Profile.MaxStaticBitrate; } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 6462ffdc1..7e921b1fd 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -27,16 +27,25 @@ namespace MediaBrowser.Model.Dlna public DeviceIdentification Identification { get; set; } public string FriendlyName { get; set; } + public string Manufacturer { get; set; } + public string ManufacturerUrl { get; set; } + public string ModelName { get; set; } + public string ModelDescription { get; set; } + public string ModelNumber { get; set; } + public string ModelUrl { get; set; } + public string SerialNumber { get; set; } public bool EnableAlbumArtInDidl { get; set; } + public bool EnableSingleAlbumArtLimit { get; set; } + public bool EnableSingleSubtitleLimit { get; set; } public string SupportedMediaTypes { get; set; } @@ -46,15 +55,19 @@ namespace MediaBrowser.Model.Dlna public string AlbumArtPn { get; set; } public int MaxAlbumArtWidth { get; set; } + public int MaxAlbumArtHeight { get; set; } public int? MaxIconWidth { get; set; } + public int? MaxIconHeight { get; set; } public long? MaxStreamingBitrate { get; set; } + public long? MaxStaticBitrate { get; set; } public int? MusicStreamingTranscodingBitrate { get; set; } + public int? MaxStaticMusicBitrate { get; set; } /// <summary> @@ -65,10 +78,13 @@ namespace MediaBrowser.Model.Dlna public string ProtocolInfo { get; set; } public int TimelineOffsetSeconds { get; set; } + public bool RequiresPlainVideoItems { get; set; } + public bool RequiresPlainFolders { get; set; } public bool EnableMSMediaReceiverRegistrar { get; set; } + public bool IgnoreTranscodeByteRangeRequests { get; set; } public XmlAttribute[] XmlRootAttributes { get; set; } @@ -88,6 +104,7 @@ namespace MediaBrowser.Model.Dlna public ContainerProfile[] ContainerProfiles { get; set; } public CodecProfile[] CodecProfiles { get; set; } + public ResponseProfile[] ResponseProfiles { get; set; } public SubtitleProfile[] SubtitleProfiles { get; set; } @@ -169,6 +186,7 @@ namespace MediaBrowser.Model.Dlna return i; } + return null; } @@ -209,6 +227,7 @@ namespace MediaBrowser.Model.Dlna return i; } + return null; } @@ -254,6 +273,7 @@ namespace MediaBrowser.Model.Dlna return i; } + return null; } @@ -318,6 +338,7 @@ namespace MediaBrowser.Model.Dlna return i; } + return null; } } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index c03a8060f..47cc89210 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -107,6 +107,7 @@ namespace MediaBrowser.Model.Dlna return list.ToArray(); } + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase)) @@ -150,8 +151,10 @@ namespace MediaBrowser.Model.Dlna { return new MediaFormatProfile[] { MediaFormatProfile.VC1_TS_AP_L2_AC3_ISO }; } + return new MediaFormatProfile[] { MediaFormatProfile.VC1_TS_AP_L1_AC3_ISO }; } + if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase)) { suffix = string.Equals(suffix, "_ISO", StringComparison.OrdinalIgnoreCase) ? suffix : "_T"; @@ -190,10 +193,12 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.AVC_MP4_MP_SD_AC3; } + if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { return MediaFormatProfile.AVC_MP4_MP_SD_MPEG1_L3; } + if (width.HasValue && height.HasValue) { if ((width.Value <= 720) && (height.Value <= 576)) @@ -277,6 +282,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.WMVMED_FULL; } + return MediaFormatProfile.WMVMED_PRO; } } @@ -285,6 +291,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.WMVHIGH_FULL; } + return MediaFormatProfile.WMVHIGH_PRO; } @@ -342,6 +349,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.WMA_BASE; } + return MediaFormatProfile.WMA_FULL; } @@ -353,14 +361,17 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.LPCM16_44_MONO; } + if (frequency.Value == 44100 && channels.Value == 2) { return MediaFormatProfile.LPCM16_44_STEREO; } + if (frequency.Value == 48000 && channels.Value == 1) { return MediaFormatProfile.LPCM16_48_MONO; } + if (frequency.Value == 48000 && channels.Value == 2) { return MediaFormatProfile.LPCM16_48_STEREO; @@ -378,6 +389,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.AAC_ISO_320; } + return MediaFormatProfile.AAC_ISO; } @@ -387,6 +399,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.AAC_ADTS_320; } + return MediaFormatProfile.AAC_ADTS; } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 3fe5cf774..06bd24476 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -627,10 +627,12 @@ namespace MediaBrowser.Model.Dlna { playlistItem.MinSegments = transcodingProfile.MinSegments; } + if (transcodingProfile.SegmentLength > 0) { playlistItem.SegmentLength = transcodingProfile.SegmentLength; } + playlistItem.SubProtocol = transcodingProfile.Protocol; if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels) @@ -947,6 +949,7 @@ namespace MediaBrowser.Model.Dlna { return (PlayMethod.DirectPlay, new List<TranscodeReason>()); } + if (options.ForceDirectStream) { return (PlayMethod.DirectStream, new List<TranscodeReason>()); @@ -1261,6 +1264,7 @@ namespace MediaBrowser.Model.Dlna return true; } } + return false; } @@ -1363,14 +1367,17 @@ namespace MediaBrowser.Model.Dlna { throw new ArgumentException("ItemId is required"); } + if (string.IsNullOrEmpty(options.DeviceId)) { throw new ArgumentException("DeviceId is required"); } + if (options.Profile == null) { throw new ArgumentException("Profile is required"); } + if (options.MediaSources == null) { throw new ArgumentException("MediaSources is required"); @@ -1418,6 +1425,7 @@ namespace MediaBrowser.Model.Dlna item.AudioBitrate = Math.Max(num, item.AudioBitrate ?? num); } } + break; } case ProfileConditionValue.AudioChannels: @@ -1452,6 +1460,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "audiochannels", Math.Max(num, item.GetTargetAudioChannels(qualifier) ?? num).ToString(CultureInfo.InvariantCulture)); } } + break; } case ProfileConditionValue.IsAvc: @@ -1472,6 +1481,7 @@ namespace MediaBrowser.Model.Dlna item.RequireAvc = true; } } + break; } case ProfileConditionValue.IsAnamorphic: @@ -1492,6 +1502,7 @@ namespace MediaBrowser.Model.Dlna item.RequireNonAnamorphic = true; } } + break; } case ProfileConditionValue.IsInterlaced: @@ -1522,6 +1533,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "deinterlace", "true"); } } + break; } case ProfileConditionValue.AudioProfile: @@ -1567,6 +1579,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "maxrefframes", Math.Max(num, item.GetTargetRefFrames(qualifier) ?? num).ToString(CultureInfo.InvariantCulture)); } } + break; } case ProfileConditionValue.VideoBitDepth: @@ -1601,6 +1614,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "videobitdepth", Math.Max(num, item.GetTargetVideoBitDepth(qualifier) ?? num).ToString(CultureInfo.InvariantCulture)); } } + break; } case ProfileConditionValue.VideoProfile: @@ -1623,6 +1637,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "profile", string.Join(",", values)); } } + break; } case ProfileConditionValue.Height: @@ -1647,6 +1662,7 @@ namespace MediaBrowser.Model.Dlna item.MaxHeight = Math.Max(num, item.MaxHeight ?? num); } } + break; } case ProfileConditionValue.VideoBitrate: @@ -1671,6 +1687,7 @@ namespace MediaBrowser.Model.Dlna item.VideoBitrate = Math.Max(num, item.VideoBitrate ?? num); } } + break; } case ProfileConditionValue.VideoFramerate: @@ -1695,6 +1712,7 @@ namespace MediaBrowser.Model.Dlna item.MaxFramerate = Math.Max(num, item.MaxFramerate ?? num); } } + break; } case ProfileConditionValue.VideoLevel: @@ -1719,6 +1737,7 @@ namespace MediaBrowser.Model.Dlna item.SetOption(qualifier, "level", Math.Max(num, item.GetTargetVideoLevel(qualifier) ?? num).ToString(CultureInfo.InvariantCulture)); } } + break; } case ProfileConditionValue.Width: @@ -1743,8 +1762,10 @@ namespace MediaBrowser.Model.Dlna item.MaxWidth = Math.Max(num, item.MaxWidth ?? num); } } + break; } + default: break; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 244463803..9e9d0b7e1 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -69,6 +69,7 @@ namespace MediaBrowser.Model.Dlna public Guid ItemId { get; set; } public PlayMethod PlayMethod { get; set; } + public EncodingContext Context { get; set; } public DlnaProfileType MediaType { get; set; } @@ -80,15 +81,23 @@ namespace MediaBrowser.Model.Dlna public long StartPositionTicks { get; set; } public int? SegmentLength { get; set; } + public int? MinSegments { get; set; } + public bool BreakOnNonKeyFrames { get; set; } public bool RequireAvc { get; set; } + public bool RequireNonAnamorphic { get; set; } + public bool CopyTimestamps { get; set; } + public bool EnableMpegtsM2TsMode { get; set; } + public bool EnableSubtitlesInManifest { get; set; } + public string[] AudioCodecs { get; set; } + public string[] VideoCodecs { get; set; } public int? AudioStreamIndex { get; set; } @@ -96,6 +105,7 @@ namespace MediaBrowser.Model.Dlna public int? SubtitleStreamIndex { get; set; } public int? TranscodingMaxAudioChannels { get; set; } + public int? GlobalMaxAudioChannels { get; set; } public int? AudioBitrate { get; set; } @@ -103,12 +113,15 @@ namespace MediaBrowser.Model.Dlna public int? VideoBitrate { get; set; } public int? MaxWidth { get; set; } + public int? MaxHeight { get; set; } public float? MaxFramerate { get; set; } public DeviceProfile DeviceProfile { get; set; } + public string DeviceProfileId { get; set; } + public string DeviceId { get; set; } public long? RunTimeTicks { get; set; } @@ -120,10 +133,13 @@ namespace MediaBrowser.Model.Dlna public MediaSourceInfo MediaSource { get; set; } public string[] SubtitleCodecs { get; set; } + public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; } + public string SubtitleFormat { get; set; } public string PlaySessionId { get; set; } + public TranscodeReason[] TranscodeReasons { get; set; } public Dictionary<string, string> StreamOptions { get; private set; } @@ -160,11 +176,13 @@ namespace MediaBrowser.Model.Dlna { continue; } + if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) { continue; } + if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase)) { @@ -993,6 +1011,7 @@ namespace MediaBrowser.Model.Dlna { return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); } + return GetMediaStreamCount(MediaStreamType.Video, 1); } } @@ -1005,6 +1024,7 @@ namespace MediaBrowser.Model.Dlna { return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); } + return GetMediaStreamCount(MediaStreamType.Audio, 1); } } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index c7f8f0584..62005b901 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -62,17 +62,23 @@ namespace MediaBrowser.Model.Dto public DateTime? DateCreated { get; set; } public DateTime? DateLastMediaAdded { get; set; } + public string ExtraType { get; set; } public int? AirsBeforeSeasonNumber { get; set; } + public int? AirsAfterSeasonNumber { get; set; } + public int? AirsBeforeEpisodeNumber { get; set; } + public bool? CanDelete { get; set; } + public bool? CanDownload { get; set; } public bool? HasSubtitles { get; set; } public string PreferredMetadataLanguage { get; set; } + public string PreferredMetadataCountryCode { get; set; } /// <summary> @@ -87,6 +93,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The name of the sort.</value> public string SortName { get; set; } + public string ForcedSortName { get; set; } /// <summary> @@ -146,6 +153,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The channel identifier.</value> public Guid ChannelId { get; set; } + public string ChannelName { get; set; } /// <summary> @@ -213,6 +221,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The number.</value> public string Number { get; set; } + public string ChannelNumber { get; set; } /// <summary> @@ -467,6 +476,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The part count.</value> public int? PartCount { get; set; } + public int? MediaSourceCount { get; set; } /// <summary> @@ -599,6 +609,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The series count.</value> public int? SeriesCount { get; set; } + public int? ProgramCount { get; set; } /// <summary> /// Gets or sets the episode count. @@ -615,6 +626,7 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The album count.</value> public int? AlbumCount { get; set; } + public int? ArtistCount { get; set; } /// <summary> /// Gets or sets the music video count. @@ -629,18 +641,31 @@ namespace MediaBrowser.Model.Dto public bool? LockData { get; set; } public int? Width { get; set; } + public int? Height { get; set; } + public string CameraMake { get; set; } + public string CameraModel { get; set; } + public string Software { get; set; } + public double? ExposureTime { get; set; } + public double? FocalLength { get; set; } + public ImageOrientation? ImageOrientation { get; set; } + public double? Aperture { get; set; } + public double? ShutterSpeed { get; set; } + public double? Latitude { get; set; } + public double? Longitude { get; set; } + public double? Altitude { get; set; } + public int? IsoSpeedRating { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 74c2cb4f4..0c9e11f8f 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -13,16 +13,19 @@ namespace MediaBrowser.Model.Dto public class MediaSourceInfo { public MediaProtocol Protocol { get; set; } + public string Id { get; set; } public string Path { get; set; } public string EncoderPath { get; set; } + public MediaProtocol? EncoderProtocol { get; set; } public MediaSourceType Type { get; set; } public string Container { get; set; } + public long? Size { get; set; } public string Name { get; set; } @@ -33,19 +36,33 @@ namespace MediaBrowser.Model.Dto public bool IsRemote { get; set; } public string ETag { get; set; } + public long? RunTimeTicks { get; set; } + public bool ReadAtNativeFramerate { get; set; } + public bool IgnoreDts { get; set; } + public bool IgnoreIndex { get; set; } + public bool GenPtsInput { get; set; } + public bool SupportsTranscoding { get; set; } + public bool SupportsDirectStream { get; set; } + public bool SupportsDirectPlay { get; set; } + public bool IsInfiniteStream { get; set; } + public bool RequiresOpening { get; set; } + public string OpenToken { get; set; } + public bool RequiresClosing { get; set; } + public string LiveStreamId { get; set; } + public int? BufferMs { get; set; } public bool RequiresLooping { get; set; } @@ -67,10 +84,13 @@ namespace MediaBrowser.Model.Dto public int? Bitrate { get; set; } public TransportStreamTimestamp? Timestamp { get; set; } + public Dictionary<string, string> RequiredHttpHeaders { get; set; } public string TranscodingUrl { get; set; } + public string TranscodingSubProtocol { get; set; } + public string TranscodingContainer { get; set; } public int? AnalyzeDurationMs { get; set; } @@ -118,6 +138,7 @@ namespace MediaBrowser.Model.Dto public TranscodeReason[] TranscodeReasons { get; set; } public int? DefaultAudioStreamIndex { get; set; } + public int? DefaultSubtitleStreamIndex { get; set; } public MediaStream GetDefaultAudioStream(int? defaultIndex) diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs index 1d840a300..e4f38d6af 100644 --- a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs +++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs @@ -11,11 +11,15 @@ namespace MediaBrowser.Model.Dto public class MetadataEditorInfo { public ParentalRating[] ParentalRatingOptions { get; set; } + public CountryInfo[] Countries { get; set; } + public CultureDto[] Cultures { get; set; } + public ExternalIdInfo[] ExternalIdInfos { get; set; } public string ContentType { get; set; } + public NameValuePair[] ContentTypeOptions { get; set; } public MetadataEditorInfo() diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs index efb2c157c..45c2fb35d 100644 --- a/MediaBrowser.Model/Dto/NameIdPair.cs +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -23,6 +23,7 @@ namespace MediaBrowser.Model.Dto public class NameGuidPair { public string Name { get; set; } + public Guid Id { get; set; } } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 3db72f78a..f0f7bf838 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -125,6 +125,7 @@ namespace MediaBrowser.Model.Entities { attributes.Add(StringHelper.FirstToUpper(Language)); } + if (!string.IsNullOrEmpty(Codec) && !string.Equals(Codec, "dca", StringComparison.OrdinalIgnoreCase)) { attributes.Add(AudioCodec.GetFriendlyName(Codec)); @@ -142,6 +143,7 @@ namespace MediaBrowser.Model.Entities { attributes.Add(Channels.Value.ToString(CultureInfo.InvariantCulture) + " ch"); } + if (IsDefault) { attributes.Add("Default"); @@ -227,30 +229,37 @@ namespace MediaBrowser.Model.Entities { return "4K"; } + if (width >= 2500) { if (i.IsInterlaced) { return "1440i"; } + return "1440p"; } + if (width >= 1900 || height >= 1000) { if (i.IsInterlaced) { return "1080i"; } + return "1080p"; } + if (width >= 1260 || height >= 700) { if (i.IsInterlaced) { return "720i"; } + return "720p"; } + if (width >= 700 || height >= 440) { @@ -258,11 +267,13 @@ namespace MediaBrowser.Model.Entities { return "480i"; } + return "480p"; } return "SD"; } + return null; } @@ -448,6 +459,7 @@ namespace MediaBrowser.Model.Entities { return false; } + if (string.Equals(fromCodec, "ssa", StringComparison.OrdinalIgnoreCase)) { return false; @@ -458,6 +470,7 @@ namespace MediaBrowser.Model.Entities { return false; } + if (string.Equals(toCodec, "ssa", StringComparison.OrdinalIgnoreCase)) { return false; diff --git a/MediaBrowser.Model/Entities/MediaUrl.cs b/MediaBrowser.Model/Entities/MediaUrl.cs index 74f982437..80ceaa765 100644 --- a/MediaBrowser.Model/Entities/MediaUrl.cs +++ b/MediaBrowser.Model/Entities/MediaUrl.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Entities public class MediaUrl { public string Url { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index 2de02e403..f8df05761 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -52,6 +52,7 @@ namespace MediaBrowser.Model.Entities public string PrimaryImageItemId { get; set; } public double? RefreshProgress { get; set; } + public string RefreshStatus { get; set; } } } diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs index 45970cf6b..07e76d960 100644 --- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs @@ -124,6 +124,7 @@ namespace MediaBrowser.Model.LiveTv /// </summary> /// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value> public bool IsPostPaddingRequired { get; set; } + public KeepUntil KeepUntil { get; set; } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs index d1a94d8b3..fe2390689 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs @@ -64,6 +64,7 @@ namespace MediaBrowser.Model.LiveTv /// </summary> /// <value><c>true</c> if [add current program]; otherwise, <c>false</c>.</value> public bool AddCurrentProgram { get; set; } + public bool EnableUserData { get; set; } /// <summary> @@ -88,6 +89,7 @@ namespace MediaBrowser.Model.LiveTv /// </summary> /// <value><c>null</c> if [is sports] contains no value, <c>true</c> if [is sports]; otherwise, <c>false</c>.</value> public bool? IsSports { get; set; } + public bool? IsSeries { get; set; } public string[] SortBy { get; set; } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 69c43efd4..789de3198 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -9,21 +9,29 @@ namespace MediaBrowser.Model.LiveTv public class LiveTvOptions { public int? GuideDays { get; set; } + public string RecordingPath { get; set; } + public string MovieRecordingPath { get; set; } + public string SeriesRecordingPath { get; set; } + public bool EnableRecordingSubfolders { get; set; } + public bool EnableOriginalAudioWithEncodedRecordings { get; set; } public TunerHostInfo[] TunerHosts { get; set; } + public ListingsProviderInfo[] ListingProviders { get; set; } public int PrePaddingSeconds { get; set; } + public int PostPaddingSeconds { get; set; } public string[] MediaLocationsCreated { get; set; } public string RecordingPostProcessor { get; set; } + public string RecordingPostProcessorArguments { get; set; } public LiveTvOptions() @@ -38,15 +46,25 @@ namespace MediaBrowser.Model.LiveTv public class TunerHostInfo { public string Id { get; set; } + public string Url { get; set; } + public string Type { get; set; } + public string DeviceId { get; set; } + public string FriendlyName { get; set; } + public bool ImportFavoritesOnly { get; set; } + public bool AllowHWTranscoding { get; set; } + public bool EnableStreamLooping { get; set; } + public string Source { get; set; } + public int TunerCount { get; set; } + public string UserAgent { get; set; } public TunerHostInfo() @@ -58,23 +76,39 @@ namespace MediaBrowser.Model.LiveTv public class ListingsProviderInfo { public string Id { get; set; } + public string Type { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public string ListingsId { get; set; } + public string ZipCode { get; set; } + public string Country { get; set; } + public string Path { get; set; } public string[] EnabledTuners { get; set; } + public bool EnableAllTuners { get; set; } + public string[] NewsCategories { get; set; } + public string[] SportsCategories { get; set; } + public string[] KidsCategories { get; set; } + public string[] MovieCategories { get; set; } + public NameValuePair[] ChannelMappings { get; set; } + public string MoviePrefix { get; set; } + public string PreferredLanguage { get; set; } + public string UserAgent { get; set; } public ListingsProviderInfo() diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 264982930..25755483a 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -65,14 +65,23 @@ namespace MediaBrowser.Model.LiveTv /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } + public bool? EnableImages { get; set; } + public bool? IsLibraryItem { get; set; } + public bool? IsNews { get; set; } + public bool? IsMovie { get; set; } + public bool? IsSeries { get; set; } + public bool? IsKids { get; set; } + public bool? IsSports { get; set; } + public int? ImageTypeLimit { get; set; } + public ImageType[] EnableImageTypes { get; set; } public bool EnableTotalRecordCount { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs index cce508809..83bda5d56 100644 --- a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs +++ b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs @@ -32,18 +32,29 @@ namespace MediaBrowser.Model.MediaInfo } public string OpenToken { get; set; } + public Guid UserId { get; set; } + public string PlaySessionId { get; set; } + public long? MaxStreamingBitrate { get; set; } + public long? StartTimeTicks { get; set; } + public int? AudioStreamIndex { get; set; } + public int? SubtitleStreamIndex { get; set; } + public int? MaxAudioChannels { get; set; } + public Guid ItemId { get; set; } + public DeviceProfile DeviceProfile { get; set; } public bool EnableDirectPlay { get; set; } + public bool EnableDirectStream { get; set; } + public MediaProtocol[] DirectPlayProtocols { get; set; } } } diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index 97b979935..472055c22 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -35,13 +35,21 @@ namespace MediaBrowser.Model.MediaInfo /// </summary> /// <value>The studios.</value> public string[] Studios { get; set; } + public string[] Genres { get; set; } + public string ShowName { get; set; } + public int? IndexNumber { get; set; } + public int? ParentIndexNumber { get; set; } + public int? ProductionYear { get; set; } + public DateTime? PremiereDate { get; set; } + public BaseItemPerson[] People { get; set; } + public Dictionary<string, string> ProviderIds { get; set; } /// <summary> diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs index 82e13e0eb..321685677 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs @@ -29,11 +29,17 @@ namespace MediaBrowser.Model.MediaInfo public DeviceProfile DeviceProfile { get; set; } public bool EnableDirectPlay { get; set; } + public bool EnableDirectStream { get; set; } + public bool EnableTranscoding { get; set; } + public bool AllowVideoStreamCopy { get; set; } + public bool AllowAudioStreamCopy { get; set; } + public bool IsPlayback { get; set; } + public bool AutoOpenLiveStream { get; set; } public MediaProtocol[] DirectPlayProtocols { get; set; } diff --git a/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs b/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs index d9f7a852c..a8d88d8a1 100644 --- a/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs +++ b/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs @@ -8,15 +8,25 @@ namespace MediaBrowser.Model.Providers public class RemoteSubtitleInfo { public string ThreeLetterISOLanguageName { get; set; } + public string Id { get; set; } + public string ProviderName { get; set; } + public string Name { get; set; } + public string Format { get; set; } + public string Author { get; set; } + public string Comment { get; set; } + public DateTime? DateCreated { get; set; } + public float? CommunityRating { get; set; } + public int? DownloadCount { get; set; } + public bool? IsHashMatch { get; set; } } } diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index c07379570..5702c460b 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -8,13 +8,19 @@ namespace MediaBrowser.Model.Providers public class SubtitleOptions { public bool SkipIfEmbeddedSubtitlesPresent { get; set; } + public bool SkipIfAudioTrackMatches { get; set; } + public string[] DownloadLanguages { get; set; } + public bool DownloadMovieSubtitles { get; set; } + public bool DownloadEpisodeSubtitles { get; set; } public string OpenSubtitlesUsername { get; set; } + public string OpenSubtitlesPasswordHash { get; set; } + public bool IsOpenSubtitleVipAccount { get; set; } public bool RequirePerfectMatch { get; set; } diff --git a/MediaBrowser.Model/Providers/SubtitleProviderInfo.cs b/MediaBrowser.Model/Providers/SubtitleProviderInfo.cs index ee25be4b6..7a7e7b9ec 100644 --- a/MediaBrowser.Model/Providers/SubtitleProviderInfo.cs +++ b/MediaBrowser.Model/Providers/SubtitleProviderInfo.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Providers public class SubtitleProviderInfo { public string Name { get; set; } + public string Id { get; set; } } } diff --git a/MediaBrowser.Model/Querying/QueryFilters.cs b/MediaBrowser.Model/Querying/QueryFilters.cs index e04208f76..6e4d25181 100644 --- a/MediaBrowser.Model/Querying/QueryFilters.cs +++ b/MediaBrowser.Model/Querying/QueryFilters.cs @@ -9,8 +9,11 @@ namespace MediaBrowser.Model.Querying public class QueryFiltersLegacy { public string[] Genres { get; set; } + public string[] Tags { get; set; } + public string[] OfficialRatings { get; set; } + public int[] Years { get; set; } public QueryFiltersLegacy() @@ -21,9 +24,11 @@ namespace MediaBrowser.Model.Querying Years = Array.Empty<int>(); } } + public class QueryFilters { public NameGuidPair[] Genres { get; set; } + public string[] Tags { get; set; } public QueryFilters() diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs index c7a721df6..983dbd2bc 100644 --- a/MediaBrowser.Model/Search/SearchHint.cs +++ b/MediaBrowser.Model/Search/SearchHint.cs @@ -100,6 +100,7 @@ namespace MediaBrowser.Model.Search public string MediaType { get; set; } public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Search/SearchQuery.cs b/MediaBrowser.Model/Search/SearchQuery.cs index 4470f1ad9..297199f61 100644 --- a/MediaBrowser.Model/Search/SearchQuery.cs +++ b/MediaBrowser.Model/Search/SearchQuery.cs @@ -32,14 +32,21 @@ namespace MediaBrowser.Model.Search public int? Limit { get; set; } public bool IncludePeople { get; set; } + public bool IncludeMedia { get; set; } + public bool IncludeGenres { get; set; } + public bool IncludeStudios { get; set; } + public bool IncludeArtists { get; set; } public string[] MediaTypes { get; set; } + public string[] IncludeItemTypes { get; set; } + public string[] ExcludeItemTypes { get; set; } + public string ParentId { get; set; } public bool? IsMovie { get; set; } diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs index f413f1e17..89622f311 100644 --- a/MediaBrowser.Model/Services/IRequest.cs +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -76,9 +76,13 @@ namespace MediaBrowser.Model.Services public interface IHttpFile { string Name { get; } + string FileName { get; } + long ContentLength { get; } + string ContentType { get; } + Stream InputStream { get; } } diff --git a/MediaBrowser.Model/Services/IService.cs b/MediaBrowser.Model/Services/IService.cs index a26d39455..5233f57ab 100644 --- a/MediaBrowser.Model/Services/IService.cs +++ b/MediaBrowser.Model/Services/IService.cs @@ -8,6 +8,8 @@ namespace MediaBrowser.Model.Services } public interface IReturn { } + public interface IReturn<T> : IReturn { } + public interface IReturnVoid : IReturn { } } diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs index 51db66d21..d3878ca30 100644 --- a/MediaBrowser.Model/Session/ClientCapabilities.cs +++ b/MediaBrowser.Model/Session/ClientCapabilities.cs @@ -13,15 +13,19 @@ namespace MediaBrowser.Model.Session public string[] SupportedCommands { get; set; } public bool SupportsMediaControl { get; set; } + public bool SupportsContentUploading { get; set; } + public string MessageCallbackUrl { get; set; } public bool SupportsPersistentIdentifier { get; set; } + public bool SupportsSync { get; set; } public DeviceProfile DeviceProfile { get; set; } public string AppStoreUrl { get; set; } + public string IconUrl { get; set; } public ClientCapabilities() diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs index 62b68b49e..1a51e23c9 100644 --- a/MediaBrowser.Model/Session/PlayRequest.cs +++ b/MediaBrowser.Model/Session/PlayRequest.cs @@ -39,8 +39,11 @@ namespace MediaBrowser.Model.Session public Guid ControllingUserId { get; set; } public int? SubtitleStreamIndex { get; set; } + public int? AudioStreamIndex { get; set; } + public string MediaSourceId { get; set; } + public int? StartIndex { get; set; } } } diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index 6b4cfe4f0..21bcabf1d 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -105,6 +105,7 @@ namespace MediaBrowser.Model.Session public RepeatMode RepeatMode { get; set; } public QueueItem[] NowPlayingQueue { get; set; } + public string PlaylistItemId { get; set; } } @@ -118,6 +119,7 @@ namespace MediaBrowser.Model.Session public class QueueItem { public Guid Id { get; set; } + public string PlaylistItemId { get; set; } } } diff --git a/MediaBrowser.Model/Session/PlaybackStopInfo.cs b/MediaBrowser.Model/Session/PlaybackStopInfo.cs index b0827ac99..aa29bb249 100644 --- a/MediaBrowser.Model/Session/PlaybackStopInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackStopInfo.cs @@ -62,6 +62,7 @@ namespace MediaBrowser.Model.Session public string NextMediaType { get; set; } public string PlaylistItemId { get; set; } + public QueueItem[] NowPlayingQueue { get; set; } } } diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index d6dc83413..e832c2f6f 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -8,17 +8,25 @@ namespace MediaBrowser.Model.Session public class TranscodingInfo { public string AudioCodec { get; set; } + public string VideoCodec { get; set; } + public string Container { get; set; } + public bool IsVideoDirect { get; set; } + public bool IsAudioDirect { get; set; } + public int? Bitrate { get; set; } public float? Framerate { get; set; } + public double? CompletionPercentage { get; set; } public int? Width { get; set; } + public int? Height { get; set; } + public int? AudioChannels { get; set; } public TranscodeReason[] TranscodeReasons { get; set; } diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs index 3cc9ff726..b9290b6e8 100644 --- a/MediaBrowser.Model/Sync/SyncJob.cs +++ b/MediaBrowser.Model/Sync/SyncJob.cs @@ -122,7 +122,9 @@ namespace MediaBrowser.Model.Sync public int ItemCount { get; set; } public string ParentName { get; set; } + public string PrimaryImageItemId { get; set; } + public string PrimaryImageTag { get; set; } public SyncJob() diff --git a/MediaBrowser.Model/Users/UserAction.cs b/MediaBrowser.Model/Users/UserAction.cs index 36b8e6ee5..7646db4a8 100644 --- a/MediaBrowser.Model/Users/UserAction.cs +++ b/MediaBrowser.Model/Users/UserAction.cs @@ -8,11 +8,17 @@ namespace MediaBrowser.Model.Users public class UserAction { public string Id { get; set; } + public string ServerId { get; set; } + public Guid UserId { get; set; } + public Guid ItemId { get; set; } + public UserActionType Type { get; set; } + public DateTime Date { get; set; } + public long? PositionTicks { get; set; } } } diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 2fd27d3b9..caf2e0f54 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -35,24 +35,37 @@ namespace MediaBrowser.Model.Users public int? MaxParentalRating { get; set; } public string[] BlockedTags { get; set; } + public bool EnableUserPreferenceAccess { get; set; } + public AccessSchedule[] AccessSchedules { get; set; } + public UnratedItem[] BlockUnratedItems { get; set; } + public bool EnableRemoteControlOfOtherUsers { get; set; } + public bool EnableSharedDeviceControl { get; set; } + public bool EnableRemoteAccess { get; set; } public bool EnableLiveTvManagement { get; set; } + public bool EnableLiveTvAccess { get; set; } public bool EnableMediaPlayback { get; set; } + 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; } + public bool EnableContentDownloading { get; set; } /// <summary> @@ -60,29 +73,36 @@ namespace MediaBrowser.Model.Users /// </summary> /// <value><c>true</c> if [enable synchronize]; otherwise, <c>false</c>.</value> public bool EnableSyncTranscoding { get; set; } + public bool EnableMediaConversion { get; set; } public string[] EnabledDevices { get; set; } + public bool EnableAllDevices { get; set; } public string[] EnabledChannels { get; set; } + public bool EnableAllChannels { get; set; } public string[] EnabledFolders { get; set; } + public bool EnableAllFolders { get; set; } public int InvalidLoginAttemptCount { get; set; } + public int LoginAttemptsBeforeLockout { get; set; } public bool EnablePublicSharing { get; set; } public string[] BlockedMediaFolders { get; set; } + public string[] BlockedChannels { get; set; } public int RemoteClientBitrateLimit { get; set; } [XmlElement(ElementName = "AuthenticationProviderId")] public string AuthenticationProviderId { get; set; } + public string PasswordResetProviderId { get; set; } /// <summary> diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 3c94f6215..2f5aa1819 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -104,6 +104,7 @@ namespace MediaBrowser.Providers.Manager } } } + if (saveLocallyWithMedia.HasValue && !saveLocallyWithMedia.Value) { saveLocally = saveLocallyWithMedia.Value; @@ -147,6 +148,7 @@ namespace MediaBrowser.Providers.Manager { retryPath = retryPaths[currentPathIndex]; } + var savedPath = await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false); savedPaths.Add(savedPath); currentPathIndex++; @@ -460,6 +462,7 @@ namespace MediaBrowser.Providers.Manager { filename = folderName; } + path = Path.Combine(item.GetInternalMetadataPath(), filename + extension); } @@ -551,6 +554,7 @@ namespace MediaBrowser.Providers.Manager { list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)); } + return list.ToArray(); } @@ -619,6 +623,7 @@ namespace MediaBrowser.Providers.Manager { imageFilename = "poster"; } + var folder = Path.GetDirectoryName(item.Path); return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension); diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 7901503d3..3d60979f3 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -58,6 +58,7 @@ namespace MediaBrowser.Providers.Manager { ClearImages(item, ImageType.Backdrop); } + if (refreshOptions.IsReplacingImage(ImageType.Screenshot)) { ClearImages(item, ImageType.Screenshot); @@ -472,6 +473,7 @@ namespace MediaBrowser.Providers.Manager { continue; } + break; } } @@ -585,6 +587,7 @@ namespace MediaBrowser.Providers.Manager { continue; } + break; } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 73fb63743..a3920d26f 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -210,6 +210,7 @@ namespace MediaBrowser.Providers.Manager LibraryManager.UpdatePeople(baseItem, result.People); SavePeopleMetadata(result.People, libraryOptions, cancellationToken); } + result.Item.UpdateToRepository(reason, cancellationToken); } @@ -324,6 +325,7 @@ namespace MediaBrowser.Providers.Manager { return true; } + var folder = item as Folder; if (folder != null) { @@ -422,6 +424,7 @@ namespace MediaBrowser.Providers.Manager { dateLastMediaAdded = childDateCreated; } + any = true; } } @@ -726,6 +729,7 @@ namespace MediaBrowser.Providers.Manager { hasLocalMetadata = true; } + break; } @@ -874,6 +878,7 @@ namespace MediaBrowser.Providers.Manager { return "en"; } + return language; } @@ -924,7 +929,9 @@ namespace MediaBrowser.Providers.Manager public class RefreshResult { public ItemUpdateType UpdateType { get; set; } + public string ErrorMessage { get; set; } + public int Failures { get; set; } } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 5853c7714..5b1192c30 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -787,6 +787,7 @@ namespace MediaBrowser.Providers.Manager { searchInfo.SearchInfo.MetadataLanguage = _configurationManager.Configuration.PreferredMetadataLanguage; } + if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode)) { searchInfo.SearchInfo.MetadataCountryCode = _configurationManager.Configuration.MetadataCountryCode; diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 60410032e..4f49dc1c9 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.Providers.Manager { throw new ArgumentNullException(nameof(source)); } + if (target == null) { throw new ArgumentNullException(nameof(target)); diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index ba87e0570..ef4e1dde9 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -129,6 +129,7 @@ namespace MediaBrowser.Providers.MediaInfo { return false; } + if (!item.IsFileProtocol) { return false; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index ccbe27c1f..54847c8a9 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -404,6 +404,7 @@ namespace MediaBrowser.Providers.MediaInfo video.ProductionYear = data.ProductionYear; } } + if (data.PremiereDate.HasValue) { if (!video.PremiereDate.HasValue || isFullRefresh) @@ -411,6 +412,7 @@ namespace MediaBrowser.Providers.MediaInfo video.PremiereDate = data.PremiereDate; } } + if (data.IndexNumber.HasValue) { if (!video.IndexNumber.HasValue || isFullRefresh) @@ -418,6 +420,7 @@ namespace MediaBrowser.Providers.MediaInfo video.IndexNumber = data.IndexNumber; } } + if (data.ParentIndexNumber.HasValue) { if (!video.ParentIndexNumber.HasValue || isFullRefresh) diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 08e503a71..7f4a8a372 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -93,6 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo { videoIndex++; } + if (mediaStream == imageStream) { break; @@ -132,6 +133,7 @@ namespace MediaBrowser.Providers.MediaInfo { return false; } + if (!item.IsFileProtocol) { return false; diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs index 9faba4798..61d8c8263 100644 --- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs +++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs @@ -28,10 +28,12 @@ namespace MediaBrowser.Providers.Movies { return false; } + if (!item.ProductionYear.HasValue) { return false; } + return base.IsFullLocalMetadata(item); } diff --git a/MediaBrowser.Providers/Movies/TrailerMetadataService.cs b/MediaBrowser.Providers/Movies/TrailerMetadataService.cs index b45d2b745..09519c7a3 100644 --- a/MediaBrowser.Providers/Movies/TrailerMetadataService.cs +++ b/MediaBrowser.Providers/Movies/TrailerMetadataService.cs @@ -28,10 +28,12 @@ namespace MediaBrowser.Providers.Movies { return false; } + if (!item.ProductionYear.HasValue) { return false; } + return base.IsFullLocalMetadata(item); } diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index ed0601c00..4ad4f890a 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -61,18 +61,22 @@ namespace MediaBrowser.Providers.Playlists { return GetWplItems(stream); } + if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase)) { return GetZplItems(stream); } + if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase)) { return GetM3uItems(stream); } + if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase)) { return GetM3u8Items(stream); } + if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase)) { return GetPlsItems(stream); diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index b1a54f22f..96224b366 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -210,42 +210,79 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public class Album { public string idAlbum { get; set; } + public string idArtist { get; set; } + public string strAlbum { get; set; } + public string strArtist { get; set; } + public string intYearReleased { get; set; } + public string strGenre { get; set; } + public string strSubGenre { get; set; } + public string strReleaseFormat { get; set; } + public string intSales { get; set; } + public string strAlbumThumb { get; set; } + public string strAlbumCDart { get; set; } + public string strDescriptionEN { get; set; } + public string strDescriptionDE { get; set; } + public string strDescriptionFR { get; set; } + public string strDescriptionCN { get; set; } + public string strDescriptionIT { get; set; } + public string strDescriptionJP { get; set; } + public string strDescriptionRU { get; set; } + public string strDescriptionES { get; set; } + public string strDescriptionPT { get; set; } + public string strDescriptionSE { get; set; } + public string strDescriptionNL { get; set; } + public string strDescriptionHU { get; set; } + public string strDescriptionNO { get; set; } + public string strDescriptionIL { get; set; } + public string strDescriptionPL { get; set; } + public object intLoved { get; set; } + public object intScore { get; set; } + public string strReview { get; set; } + public object strMood { get; set; } + public object strTheme { get; set; } + public object strSpeed { get; set; } + public object strLocation { get; set; } + public string strMusicBrainzID { get; set; } + public string strMusicBrainzArtistID { get; set; } + public object strItunesID { get; set; } + public object strAmazonID { get; set; } + public string strLocked { get; set; } } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index fdba779be..14bbcddce 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -199,45 +199,85 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public class Artist { public string idArtist { get; set; } + public string strArtist { get; set; } + public string strArtistAlternate { get; set; } + public object idLabel { get; set; } + public string intFormedYear { get; set; } + public string intBornYear { get; set; } + public object intDiedYear { get; set; } + public object strDisbanded { get; set; } + public string strGenre { get; set; } + public string strSubGenre { get; set; } + public string strWebsite { get; set; } + public string strFacebook { get; set; } + public string strTwitter { get; set; } + public string strBiographyEN { get; set; } + public string strBiographyDE { get; set; } + public string strBiographyFR { get; set; } + public string strBiographyCN { get; set; } + public string strBiographyIT { get; set; } + public string strBiographyJP { get; set; } + public string strBiographyRU { get; set; } + public string strBiographyES { get; set; } + public string strBiographyPT { get; set; } + public string strBiographySE { get; set; } + public string strBiographyNL { get; set; } + public string strBiographyHU { get; set; } + public string strBiographyNO { get; set; } + public string strBiographyIL { get; set; } + public string strBiographyPL { get; set; } + public string strGender { get; set; } + public string intMembers { get; set; } + public string strCountry { get; set; } + public string strCountryCode { get; set; } + public string strArtistThumb { get; set; } + public string strArtistLogo { get; set; } + public string strArtistFanart { get; set; } + public string strArtistFanart2 { get; set; } + public string strArtistFanart3 { get; set; } + public string strArtistBanner { get; set; } + public string strMusicBrainzID { get; set; } + public object strLastFMChart { get; set; } + public string strLocked { get; set; } } diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 0a2c7c124..78b500199 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -361,6 +361,7 @@ namespace MediaBrowser.Providers.Music return ParseReleaseList(subReader).ToList(); } } + default: { reader.Skip(); @@ -396,6 +397,7 @@ namespace MediaBrowser.Providers.Music reader.Read(); continue; } + var releaseId = reader.GetAttribute("id"); using (var subReader = reader.ReadSubtree()) @@ -406,8 +408,10 @@ namespace MediaBrowser.Providers.Music yield return release; } } + break; } + default: { reader.Skip(); @@ -453,6 +457,7 @@ namespace MediaBrowser.Providers.Music { result.Year = date.Year; } + break; } case "annotation": @@ -480,6 +485,7 @@ namespace MediaBrowser.Providers.Music break; } + default: { reader.Skip(); @@ -518,6 +524,7 @@ namespace MediaBrowser.Providers.Music return ParseArtistNameCredit(subReader); } } + default: { reader.Skip(); @@ -556,6 +563,7 @@ namespace MediaBrowser.Providers.Music return ParseArtistArtistCredit(subReader, id); } } + default: { reader.Skip(); @@ -593,6 +601,7 @@ namespace MediaBrowser.Providers.Music name = reader.ReadElementContentAsString(); break; } + default: { reader.Skip(); @@ -680,11 +689,13 @@ namespace MediaBrowser.Providers.Music reader.Read(); continue; } + using (var subReader = reader.ReadSubtree()) { return GetFirstReleaseGroupId(subReader); } } + default: { reader.Skip(); @@ -719,6 +730,7 @@ namespace MediaBrowser.Providers.Music { return reader.GetAttribute("id"); } + default: { reader.Skip(); @@ -780,6 +792,7 @@ namespace MediaBrowser.Providers.Music // We retry a finite number of times, and only whilst MB is indicating 503 (throttling) } + while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable); // Log error if unable to query MB database due to throttling diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index 9d93dbdd1..101af162d 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -108,11 +108,13 @@ namespace MediaBrowser.Providers.Music reader.Read(); continue; } + using (var subReader = reader.ReadSubtree()) { return ParseArtistList(subReader).ToList(); } } + default: { reader.Skip(); @@ -150,6 +152,7 @@ namespace MediaBrowser.Providers.Music reader.Read(); continue; } + var mbzId = reader.GetAttribute("id"); using (var subReader = reader.ReadSubtree()) @@ -160,8 +163,10 @@ namespace MediaBrowser.Providers.Music yield return artist; } } + break; } + default: { reader.Skip(); @@ -202,6 +207,7 @@ namespace MediaBrowser.Providers.Music result.Overview = reader.ReadElementContentAsString(); break; } + default: { // there is sort-name if ever needed diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 4a29ba4d0..b12d2a388 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -286,27 +286,49 @@ namespace MediaBrowser.Providers.Plugins.Omdb class SearchResult { public string Title { get; set; } + public string Year { get; set; } + public string Rated { get; set; } + public string Released { get; set; } + public string Season { get; set; } + public string Episode { get; set; } + public string Runtime { get; set; } + public string Genre { get; set; } + public string Director { get; set; } + public string Writer { get; set; } + public string Actors { get; set; } + public string Plot { get; set; } + public string Language { get; set; } + public string Country { get; set; } + public string Awards { get; set; } + public string Poster { get; set; } + public string Metascore { get; set; } + public string imdbRating { get; set; } + public string imdbVotes { get; set; } + public string imdbID { get; set; } + public string seriesID { get; set; } + public string Type { get; set; } + public string Response { get; set; } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionImages.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionImages.cs index 2410ca16b..4ebcaeeb6 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionImages.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionImages.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Collections public class CollectionImages { public List<Backdrop> Backdrops { get; set; } + public List<Poster> Posters { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionResult.cs index 3437552df..9228bec9c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/CollectionResult.cs @@ -5,11 +5,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Collections public class CollectionResult { public int Id { get; set; } + public string Name { get; set; } + public string Overview { get; set; } + public string Poster_Path { get; set; } + public string Backdrop_Path { get; set; } + public List<Part> Parts { get; set; } + public CollectionImages Images { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/Part.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/Part.cs index 462fdab53..3a464e053 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/Part.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Collections/Part.cs @@ -3,9 +3,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Collections public class Part { public string Title { get; set; } + public int Id { get; set; } + public string Release_Date { get; set; } + public string Poster_Path { get; set; } + public string Backdrop_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Backdrop.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Backdrop.cs index 35e3e2112..add7a38d8 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Backdrop.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Backdrop.cs @@ -3,11 +3,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Backdrop { public double Aspect_Ratio { get; set; } + public string File_Path { get; set; } + public int Height { get; set; } + public string Iso_639_1 { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public int Width { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Crew.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Crew.cs index 6a5e74ddb..3f0fe7fad 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Crew.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Crew.cs @@ -3,10 +3,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Crew { public int Id { get; set; } + public string Credit_Id { get; set; } + public string Name { get; set; } + public string Department { get; set; } + public string Job { get; set; } + public string Profile_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/ExternalIds.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/ExternalIds.cs index a083f6e9c..8082a5e58 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/ExternalIds.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/ExternalIds.cs @@ -3,9 +3,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class ExternalIds { public string Imdb_Id { get; set; } + public object Freebase_Id { get; set; } + public string Freebase_Mid { get; set; } + public int Tvdb_Id { get; set; } + public int Tvrage_Id { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Genre.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Genre.cs index 7f1a394c3..d7b18ff8c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Genre.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Genre.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Genre { public int Id { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Images.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Images.cs index 166f9b740..bbeac878a 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Images.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Images.cs @@ -5,6 +5,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Images { public List<Backdrop> Backdrops { get; set; } + public List<Poster> Posters { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Keyword.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Keyword.cs index 72f417be5..07cab86a0 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Keyword.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Keyword.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Keyword { public int Id { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Poster.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Poster.cs index 0cf04a6ce..3ac89a77d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Poster.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Poster.cs @@ -3,11 +3,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Poster { public double Aspect_Ratio { get; set; } + public string File_Path { get; set; } + public int Height { get; set; } + public string Iso_639_1 { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public int Width { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Profile.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Profile.cs index b45cfc30f..57edbe74c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Profile.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Profile.cs @@ -3,9 +3,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Profile { public string File_Path { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public object Iso_639_1 { get; set; } + public double Aspect_Ratio { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Still.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Still.cs index 9fc82cfee..1507c6577 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Still.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Still.cs @@ -3,12 +3,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Still { public double Aspect_Ratio { get; set; } + public string File_Path { get; set; } + public int Height { get; set; } + public string Id { get; set; } + public string Iso_639_1 { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public int Width { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Video.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Video.cs index 19bfd62f6..e0fef6cce 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Video.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Video.cs @@ -3,12 +3,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General public class Video { public string Id { get; set; } + public string Iso_639_1 { get; set; } + public string Iso_3166_1 { get; set; } + public string Key { get; set; } + public string Name { get; set; } + public string Site { get; set; } + public string Size { get; set; } + public string Type { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/BelongsToCollection.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/BelongsToCollection.cs index aaca57f05..af5bc9282 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/BelongsToCollection.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/BelongsToCollection.cs @@ -3,8 +3,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class BelongsToCollection { public int Id { get; set; } + public string Name { get; set; } + public string Poster_Path { get; set; } + public string Backdrop_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Cast.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Cast.cs index d70f218aa..6775350b7 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Cast.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Cast.cs @@ -3,10 +3,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class Cast { public int Id { get; set; } + public string Name { get; set; } + public string Character { get; set; } + public int Order { get; set; } + public int Cast_Id { get; set; } + public string Profile_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Casts.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Casts.cs index c41699bc7..5601de85e 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Casts.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Casts.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class Casts { public List<Cast> Cast { get; set; } + public List<Crew> Crew { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Country.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Country.cs index 71d1f7c24..f4cbc41f6 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Country.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Country.cs @@ -5,7 +5,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class Country { public string Iso_3166_1 { get; set; } + public string Certification { get; set; } + public DateTime Release_Date { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/MovieResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/MovieResult.cs index 2a9b9779a..8e25e4fb3 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/MovieResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/MovieResult.cs @@ -6,34 +6,63 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class MovieResult { public bool Adult { get; set; } + public string Backdrop_Path { get; set; } + public BelongsToCollection Belongs_To_Collection { get; set; } + public int Budget { get; set; } + public List<Genre> Genres { get; set; } + public string Homepage { get; set; } + public int Id { get; set; } + public string Imdb_Id { get; set; } + public string Original_Title { get; set; } + public string Original_Name { get; set; } + public string Overview { get; set; } + public double Popularity { get; set; } + public string Poster_Path { get; set; } + public List<ProductionCompany> Production_Companies { get; set; } + public List<ProductionCountry> Production_Countries { get; set; } + public string Release_Date { get; set; } + public int Revenue { get; set; } + public int Runtime { get; set; } + public List<SpokenLanguage> Spoken_Languages { get; set; } + public string Status { get; set; } + public string Tagline { get; set; } + public string Title { get; set; } + public string Name { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public Casts Casts { get; set; } + public Releases Releases { get; set; } + public Images Images { get; set; } + public Keywords Keywords { get; set; } + public Trailers Trailers { get; set; } public string GetOriginalTitle() diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCompany.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCompany.cs index 11158ade5..ba8e42fdd 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCompany.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCompany.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class ProductionCompany { public string Name { get; set; } + public int Id { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCountry.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCountry.cs index 43d00fe7a..a313605bd 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCountry.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/ProductionCountry.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class ProductionCountry { public string Iso_3166_1 { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/SpokenLanguage.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/SpokenLanguage.cs index 41defa9d0..9469a41f1 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/SpokenLanguage.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/SpokenLanguage.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class SpokenLanguage { public string Iso_639_1 { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Youtube.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Youtube.cs index 6be4ef5b5..499e368a4 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Youtube.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Youtube.cs @@ -3,7 +3,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies public class Youtube { public string Name { get; set; } + public string Size { get; set; } + public string Source { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonResult.cs index 50c47eefd..076648a6c 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonResult.cs @@ -6,18 +6,31 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.People public class PersonResult { public bool Adult { get; set; } + public List<string> Also_Known_As { get; set; } + public string Biography { get; set; } + public string Birthday { get; set; } + public string Deathday { get; set; } + public string Homepage { get; set; } + public int Id { get; set; } + public string Imdb_Id { get; set; } + public string Name { get; set; } + public string Place_Of_Birth { get; set; } + public double Popularity { get; set; } + public string Profile_Path { get; set; } + public PersonImages Images { get; set; } + public ExternalIds External_Ids { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/TvResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/TvResult.cs index b7fbd294c..c611bcd5f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/TvResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Search/TvResult.cs @@ -3,13 +3,21 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Search public class TvResult { public string Backdrop_Path { get; set; } + public string First_Air_Date { get; set; } + public int Id { get; set; } + public string Original_Name { get; set; } + public string Poster_Path { get; set; } + public double Popularity { get; set; } + public string Name { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Cast.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Cast.cs index 9c770545c..ebf7ba6e4 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Cast.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Cast.cs @@ -3,10 +3,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class Cast { public string Character { get; set; } + public string Credit_Id { get; set; } + public int Id { get; set; } + public string Name { get; set; } + public string Profile_Path { get; set; } + public int Order { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/ContentRating.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/ContentRating.cs index bccb234e7..9de674e7f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/ContentRating.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/ContentRating.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class ContentRating { public string Iso_3166_1 { get; set; } + public string Rating { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/CreatedBy.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/CreatedBy.cs index 35e8eaecb..1ef65bb98 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/CreatedBy.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/CreatedBy.cs @@ -3,7 +3,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class CreatedBy { public int Id { get; set; } + public string Name { get; set; } + public string Profile_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Credits.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Credits.cs index ebf412c2d..836fbcbe5 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Credits.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Credits.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class Credits { public List<Cast> Cast { get; set; } + public List<Crew> Crew { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Episode.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Episode.cs index 8203632b7..a38012e31 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Episode.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Episode.cs @@ -3,12 +3,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class Episode { public string Air_Date { get; set; } + public int Episode_Number { get; set; } + public int Id { get; set; } + public string Name { get; set; } + public string Overview { get; set; } + public string Still_Path { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeCredits.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeCredits.cs index f89859f85..5068e8f9b 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeCredits.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeCredits.cs @@ -6,7 +6,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class EpisodeCredits { public List<Cast> Cast { get; set; } + public List<Crew> Crew { get; set; } + public List<GuestStar> Guest_Stars { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeResult.cs index e25b65d70..a4d6a130e 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/EpisodeResult.cs @@ -6,18 +6,31 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class EpisodeResult { public DateTime Air_Date { get; set; } + public int Episode_Number { get; set; } + public string Name { get; set; } + public string Overview { get; set; } + public int Id { get; set; } + public object Production_Code { get; set; } + public int Season_Number { get; set; } + public string Still_Path { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public StillImages Images { get; set; } + public ExternalIds External_Ids { get; set; } + public EpisodeCredits Credits { get; set; } + public Tmdb.Models.General.Videos Videos { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/GuestStar.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/GuestStar.cs index 260f3f610..da5e63171 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/GuestStar.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/GuestStar.cs @@ -3,10 +3,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class GuestStar { public int Id { get; set; } + public string Name { get; set; } + public string Credit_Id { get; set; } + public string Character { get; set; } + public int Order { get; set; } + public string Profile_Path { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Network.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Network.cs index 5ed310827..0eba92ae2 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Network.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Network.cs @@ -3,6 +3,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class Network { public int Id { get; set; } + public string Name { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Season.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Season.cs index fddf950ee..2e39c5901 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Season.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/Season.cs @@ -3,9 +3,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class Season { public string Air_Date { get; set; } + public int Episode_Count { get; set; } + public int Id { get; set; } + public string Poster_Path { get; set; } + public int Season_Number { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeasonResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeasonResult.cs index 13b4c30f8..328bd1ebc 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeasonResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeasonResult.cs @@ -7,15 +7,25 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class SeasonResult { public DateTime Air_Date { get; set; } + public List<Episode> Episodes { get; set; } + public string Name { get; set; } + public string Overview { get; set; } + public int Id { get; set; } + public string Poster_Path { get; set; } + public int Season_Number { get; set; } + public Credits Credits { get; set; } + public SeasonImages Images { get; set; } + public ExternalIds External_Ids { get; set; } + public General.Videos Videos { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeriesResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeriesResult.cs index 5c1666c77..499249b8e 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeriesResult.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/TV/SeriesResult.cs @@ -7,34 +7,63 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.TV public class SeriesResult { public string Backdrop_Path { get; set; } + public List<CreatedBy> Created_By { get; set; } + public List<int> Episode_Run_Time { get; set; } + public DateTime First_Air_Date { get; set; } + public List<Genre> Genres { get; set; } + public string Homepage { get; set; } + public int Id { get; set; } + public bool In_Production { get; set; } + public List<string> Languages { get; set; } + public DateTime Last_Air_Date { get; set; } + public string Name { get; set; } + public List<Network> Networks { get; set; } + public int Number_Of_Episodes { get; set; } + public int Number_Of_Seasons { get; set; } + public string Original_Name { get; set; } + public List<string> Origin_Country { get; set; } + public string Overview { get; set; } + public string Popularity { get; set; } + public string Poster_Path { get; set; } + public List<Season> Seasons { get; set; } + public string Status { get; set; } + public double Vote_Average { get; set; } + public int Vote_Count { get; set; } + public Credits Credits { get; set; } + public Images Images { get; set; } + public Keywords Keywords { get; set; } + public ExternalIds External_Ids { get; set; } + public General.Videos Videos { get; set; } + public ContentRatings Content_Ratings { get; set; } + public string ResultLanguage { get; set; } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs index a11c89459..8ecd6b917 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs @@ -107,6 +107,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { return 3; } + if (!isLanguageEn) { if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) @@ -114,10 +115,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies return 2; } } + if (string.IsNullOrEmpty(i.Language)) { return isLanguageEn ? 3 : 2; } + return 0; }) .ThenByDescending(i => i.CommunityRating ?? 0) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs index 03669ca67..3a45d4a55 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs @@ -5,8 +5,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies internal class TmdbImageSettings { public List<string> backdrop_sizes { get; set; } + public string secure_base_url { get; set; } + public List<string> poster_sizes { get; set; } + public List<string> profile_sizes { get; set; } public string GetImageUrl(string image) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs index 525c0072b..edd90475d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs @@ -98,6 +98,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People { return 3; } + if (!isLanguageEn) { if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) @@ -105,10 +106,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People return 2; } } + if (string.IsNullOrEmpty(i.Language)) { return isLanguageEn ? 3 : 2; } + return 0; }) .ThenByDescending(i => i.CommunityRating ?? 0) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index 654e42a90..a13d41dc2 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -173,6 +173,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People { item.ProductionLocations = new string[] { info.Place_Of_Birth }; } + item.Overview = info.Biography; if (DateTime.TryParseExact(info.Birthday, "yyyy-MM-dd", new CultureInfo("en-US"), DateTimeStyles.None, out var date)) diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 8086533eb..24c29a219 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -104,6 +104,7 @@ namespace MediaBrowser.Providers.Subtitles _logger.LogError(ex, "Error downloading subtitles from {Provider}", provider.Name); } } + return Array.Empty<RemoteSubtitleInfo>(); } diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index 6e0511971..92c42e9d8 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Providers.TV { seasons = series.Children.OfType<Season>().ToList(); } + var existingSeason = seasons .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber); diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 7a753e832..6d303fab1 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -67,10 +67,12 @@ namespace MediaBrowser.Providers.TV { return false; } + if (!item.ProductionYear.HasValue) { return false; } + return base.IsFullLocalMetadata(item); } diff --git a/RSSDP/DiscoveredSsdpDevice.cs b/RSSDP/DiscoveredSsdpDevice.cs index 1244ce523..9093199dd 100644 --- a/RSSDP/DiscoveredSsdpDevice.cs +++ b/RSSDP/DiscoveredSsdpDevice.cs @@ -45,6 +45,7 @@ namespace Rssdp public DateTimeOffset AsAt { get { return _AsAt; } + set { if (_AsAt != value) diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index c2eb0bf92..e7172cb1c 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -135,6 +135,7 @@ namespace Rssdp.Infrastructure ParseHeader(line, headers, contentHeaders); } + return lineIndex; } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 863f2b15c..fe49fb7d3 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -311,6 +311,7 @@ namespace Rssdp.Infrastructure public bool IsShared { get { return _IsShared; } + set { _IsShared = value; } } diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 691ba2a14..f89bafb19 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -90,6 +90,7 @@ namespace Rssdp { return _DeviceType; } + set { _DeviceType = value; @@ -111,6 +112,7 @@ namespace Rssdp { return _DeviceTypeNamespace; } + set { _DeviceTypeNamespace = value; @@ -130,6 +132,7 @@ namespace Rssdp { return _DeviceVersion; } + set { _DeviceVersion = value; @@ -181,6 +184,7 @@ namespace Rssdp else return _Udn; } + set { _Udn = value; diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index a626e13b9..9b48cf31c 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -579,6 +579,7 @@ namespace Rssdp.Infrastructure return d; } } + return null; } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 5dfb6a8c2..b4cf2fb48 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -156,6 +156,7 @@ namespace Rssdp.Infrastructure public bool SupportPnpRootDevice { get { return _SupportPnpRootDevice; } + set { _SupportPnpRootDevice = value; @@ -564,7 +565,9 @@ namespace Rssdp.Infrastructure private class SearchRequest { public IPEndPoint EndPoint { get; set; } + public DateTime Received { get; set; } + public string SearchTarget { get; set; } public string Key diff --git a/RSSDP/SsdpEmbeddedDevice.cs b/RSSDP/SsdpEmbeddedDevice.cs index 4810703d7..ff644993b 100644 --- a/RSSDP/SsdpEmbeddedDevice.cs +++ b/RSSDP/SsdpEmbeddedDevice.cs @@ -33,6 +33,7 @@ namespace Rssdp { return _RootDevice; } + internal set { _RootDevice = value; -- cgit v1.2.3 From 8de6452967d229624c81e06d992b1cb0cb6715b1 Mon Sep 17 00:00:00 2001 From: telans <telans@protonmail.com> Date: Fri, 19 Jun 2020 22:21:49 +1200 Subject: fix some documentation periods --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 4 ++-- .../Library/Resolvers/TV/SeasonResolver.cs | 4 ++-- Emby.Server.Implementations/ScheduledTasks/TaskManager.cs | 2 +- Jellyfin.Data/Entities/BookMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/Chapter.cs | 4 ++-- Jellyfin.Data/Entities/CompanyMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/CustomItemMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/EpisodeMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/Group.cs | 2 +- Jellyfin.Data/Entities/LibraryRoot.cs | 4 ++-- Jellyfin.Data/Entities/MediaFile.cs | 4 ++-- Jellyfin.Data/Entities/Metadata.cs | 4 ++-- Jellyfin.Data/Entities/MovieMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/MusicAlbumMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/PhotoMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/SeasonMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/SeriesMetadata.cs | 8 ++++---- Jellyfin.Data/Entities/TrackMetadata.cs | 8 ++++---- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 6 +++--- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Net/AuthenticatedAttribute.cs | 6 +++--- MediaBrowser.Controller/Net/SecurityException.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- MediaBrowser.Model/Services/QueryParamCollection.cs | 4 ++-- MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 2 +- 26 files changed, 67 insertions(+), 67 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index da37a8c86..6e5389ad4 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -6308,7 +6308,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type /// Gets the attachment. /// </summary> /// <param name="reader">The reader.</param> - /// <returns>MediaAttachment</returns> + /// <returns>MediaAttachment.</returns> private MediaAttachment GetMediaAttachment(IReadOnlyList<IResultSetValue> reader) { var item = new MediaAttachment diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 893af4cae..edb58e910 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.Library /// <summary> /// Initializes a new instance of the <see cref="LibraryManager" /> class. /// </summary> - /// <param name="appHost">The application host</param> + /// <param name="appHost">The application host.</param> /// <param name="logger">The logger.</param> /// <param name="taskManager">The task manager.</param> /// <param name="userManager">The user manager.</param> @@ -1793,7 +1793,7 @@ namespace Emby.Server.Implementations.Library /// Creates the items. /// </summary> /// <param name="items">The items.</param> - /// <param name="parent">The parent item</param> + /// <param name="parent">The parent item.</param> /// <param name="cancellationToken">The cancellation token.</param> public void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index c43a0ec6b..c8e41001a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -23,8 +23,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// </summary> /// <param name="config">The config.</param> /// <param name="libraryManager">The library manager.</param> - /// <param name="localization">The localization</param> - /// <param name="logger">The logger</param> + /// <param name="localization">The localization.</param> + /// <param name="logger">The logger.</param> public SeasonResolver( IServerConfigurationManager config, ILibraryManager libraryManager, diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 0ad4253e4..3fe15ec68 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// Queues the scheduled task. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="options">Task options</param> + /// <param name="options">Task options.</param> public void QueueScheduledTask<T>(TaskOptions options) where T : IScheduledTask { diff --git a/Jellyfin.Data/Entities/BookMetadata.cs b/Jellyfin.Data/Entities/BookMetadata.cs index 914eda064..dc7146371 100644 --- a/Jellyfin.Data/Entities/BookMetadata.cs +++ b/Jellyfin.Data/Entities/BookMetadata.cs @@ -29,8 +29,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_book0"></param> public BookMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Book _book0) { @@ -51,8 +51,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_book0"></param> public static BookMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Book _book0) { diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs index 77685add6..960853e15 100644 --- a/Jellyfin.Data/Entities/Chapter.cs +++ b/Jellyfin.Data/Entities/Chapter.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="timestart"></param> /// <param name="_release0"></param> public Chapter(string language, long timestart, Release _release0) @@ -47,7 +47,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="timestart"></param> /// <param name="_release0"></param> public static Chapter Create(string language, long timestart, Release _release0) diff --git a/Jellyfin.Data/Entities/CompanyMetadata.cs b/Jellyfin.Data/Entities/CompanyMetadata.cs index 695c7f096..12f213310 100644 --- a/Jellyfin.Data/Entities/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/CompanyMetadata.cs @@ -26,8 +26,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_company0"></param> public CompanyMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Company _company0) { @@ -47,8 +47,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_company0"></param> public static CompanyMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Company _company0) { diff --git a/Jellyfin.Data/Entities/CustomItemMetadata.cs b/Jellyfin.Data/Entities/CustomItemMetadata.cs index b81408aa6..dd66c8f83 100644 --- a/Jellyfin.Data/Entities/CustomItemMetadata.cs +++ b/Jellyfin.Data/Entities/CustomItemMetadata.cs @@ -25,8 +25,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_customitem0"></param> public CustomItemMetadata(string title, string language, DateTime dateadded, DateTime datemodified, CustomItem _customitem0) { @@ -46,8 +46,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_customitem0"></param> public static CustomItemMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, CustomItem _customitem0) { diff --git a/Jellyfin.Data/Entities/EpisodeMetadata.cs b/Jellyfin.Data/Entities/EpisodeMetadata.cs index da5ea43cc..b17e4aa19 100644 --- a/Jellyfin.Data/Entities/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/EpisodeMetadata.cs @@ -26,8 +26,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_episode0"></param> public EpisodeMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Episode _episode0) { @@ -47,8 +47,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_episode0"></param> public static EpisodeMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Episode _episode0) { diff --git a/Jellyfin.Data/Entities/Group.cs b/Jellyfin.Data/Entities/Group.cs index 5cbb126f9..47833378e 100644 --- a/Jellyfin.Data/Entities/Group.cs +++ b/Jellyfin.Data/Entities/Group.cs @@ -99,7 +99,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="name">The name of this group</param> + /// <param name="name">The name of this group.</param> public static Group Create(string name) { return new Group(name); diff --git a/Jellyfin.Data/Entities/LibraryRoot.cs b/Jellyfin.Data/Entities/LibraryRoot.cs index 16fbc92f6..a6f3e49c9 100644 --- a/Jellyfin.Data/Entities/LibraryRoot.cs +++ b/Jellyfin.Data/Entities/LibraryRoot.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="path">Absolute Path</param> + /// <param name="path">Absolute Path.</param> public LibraryRoot(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path)); @@ -40,7 +40,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="path">Absolute Path</param> + /// <param name="path">Absolute Path.</param> public static LibraryRoot Create(string path) { return new LibraryRoot(path); diff --git a/Jellyfin.Data/Entities/MediaFile.cs b/Jellyfin.Data/Entities/MediaFile.cs index 8201eed52..5d9448d41 100644 --- a/Jellyfin.Data/Entities/MediaFile.cs +++ b/Jellyfin.Data/Entities/MediaFile.cs @@ -30,7 +30,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="path">Relative to the LibraryRoot</param> + /// <param name="path">Relative to the LibraryRoot.</param> /// <param name="kind"></param> /// <param name="_release0"></param> public MediaFile(string path, Enums.MediaFileKind kind, Release _release0) @@ -51,7 +51,7 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="path">Relative to the LibraryRoot</param> + /// <param name="path">Relative to the LibraryRoot.</param> /// <param name="kind"></param> /// <param name="_release0"></param> public static MediaFile Create(string path, Enums.MediaFileKind kind, Release _release0) diff --git a/Jellyfin.Data/Entities/Metadata.cs b/Jellyfin.Data/Entities/Metadata.cs index 146c70a10..8446c30b2 100644 --- a/Jellyfin.Data/Entities/Metadata.cs +++ b/Jellyfin.Data/Entities/Metadata.cs @@ -26,8 +26,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> protected Metadata(string title, string language, DateTime dateadded, DateTime datemodified) { if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); diff --git a/Jellyfin.Data/Entities/MovieMetadata.cs b/Jellyfin.Data/Entities/MovieMetadata.cs index 48584dd13..4fda88e8e 100644 --- a/Jellyfin.Data/Entities/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/MovieMetadata.cs @@ -30,8 +30,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_movie0"></param> public MovieMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Movie _movie0) { @@ -52,8 +52,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_movie0"></param> public static MovieMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Movie _movie0) { diff --git a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs index 5847101ca..a5056adc0 100644 --- a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs @@ -30,8 +30,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_musicalbum0"></param> public MusicAlbumMetadata(string title, string language, DateTime dateadded, DateTime datemodified, MusicAlbum _musicalbum0) { @@ -52,8 +52,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_musicalbum0"></param> public static MusicAlbumMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, MusicAlbum _musicalbum0) { diff --git a/Jellyfin.Data/Entities/PhotoMetadata.cs b/Jellyfin.Data/Entities/PhotoMetadata.cs index 5a9cf5b66..4a0b07ff8 100644 --- a/Jellyfin.Data/Entities/PhotoMetadata.cs +++ b/Jellyfin.Data/Entities/PhotoMetadata.cs @@ -26,8 +26,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_photo0"></param> public PhotoMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Photo _photo0) { @@ -47,8 +47,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_photo0"></param> public static PhotoMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Photo _photo0) { diff --git a/Jellyfin.Data/Entities/SeasonMetadata.cs b/Jellyfin.Data/Entities/SeasonMetadata.cs index 865938338..8c72d9952 100644 --- a/Jellyfin.Data/Entities/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/SeasonMetadata.cs @@ -27,8 +27,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_season0"></param> public SeasonMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Season _season0) { @@ -48,8 +48,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_season0"></param> public static SeasonMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Season _season0) { diff --git a/Jellyfin.Data/Entities/SeriesMetadata.cs b/Jellyfin.Data/Entities/SeriesMetadata.cs index bb7426754..2c04ef12f 100644 --- a/Jellyfin.Data/Entities/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/SeriesMetadata.cs @@ -30,8 +30,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_series0"></param> public SeriesMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Series _series0) { @@ -52,8 +52,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_series0"></param> public static SeriesMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Series _series0) { diff --git a/Jellyfin.Data/Entities/TrackMetadata.cs b/Jellyfin.Data/Entities/TrackMetadata.cs index 05bb953f8..55f4a38e0 100644 --- a/Jellyfin.Data/Entities/TrackMetadata.cs +++ b/Jellyfin.Data/Entities/TrackMetadata.cs @@ -26,8 +26,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Public constructor with required data. /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_track0"></param> public TrackMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Track _track0) { @@ -47,8 +47,8 @@ namespace Jellyfin.Data.Entities /// <summary> /// Static create function (for use in LINQ queries, etc.) /// </summary> - /// <param name="title">The title or name of the object</param> - /// <param name="language">ISO-639-3 3-character language codes</param> + /// <param name="title">The title or name of the object.</param> + /// <param name="language">ISO-639-3 3-character language codes.</param> /// <param name="_track0"></param> public static TrackMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Track _track0) { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 488692c03..69d799165 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -30,7 +30,7 @@ namespace MediaBrowser.Controller.Drawing /// Gets the dimensions of the image. /// </summary> /// <param name="path">Path to the image file.</param> - /// <returns>ImageDimensions</returns> + /// <returns>ImageDimensions.</returns> ImageDimensions GetImageDimensions(string path); /// <summary> @@ -38,14 +38,14 @@ namespace MediaBrowser.Controller.Drawing /// </summary> /// <param name="item">The base item.</param> /// <param name="info">The information.</param> - /// <returns>ImageDimensions</returns> + /// <returns>ImageDimensions.</returns> ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info); /// <summary> /// Gets the blurhash of the image. /// </summary> /// <param name="path">Path to the image file.</param> - /// <returns>BlurHash</returns> + /// <returns>BlurHash.</returns> string GetImageBlurHash(string path); /// <summary> diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index d76409afc..7b833c36b 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1371,7 +1371,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>true if a provider reports we changed</returns> + /// <returns>true if a provider reports we changed.</returns> public async Task<ItemUpdateType> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken) { TriggerOnRefreshStart(); diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index ba3c715b8..ad786f97b 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -31,9 +31,9 @@ namespace MediaBrowser.Controller.Net /// <summary> /// The request filter is executed before the service. /// </summary> - /// <param name="request">The http request wrapper</param> - /// <param name="response">The http response wrapper</param> - /// <param name="requestDto">The request DTO</param> + /// <param name="request">The http request wrapper.</param> + /// <param name="response">The http response wrapper.</param> + /// <param name="requestDto">The request DTO.</param> public void RequestFilter(IRequest request, HttpResponse response, object requestDto) { AuthService.Authenticate(request, this); diff --git a/MediaBrowser.Controller/Net/SecurityException.cs b/MediaBrowser.Controller/Net/SecurityException.cs index a5b94ea5e..f0d0b45a0 100644 --- a/MediaBrowser.Controller/Net/SecurityException.cs +++ b/MediaBrowser.Controller/Net/SecurityException.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.Net /// <summary> /// Initializes a new instance of the <see cref="SecurityException"/> class. /// </summary> - /// <param name="message">The message that describes the error</param> + /// <param name="message">The message that describes the error.</param> /// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param> public SecurityException(string message, Exception innerException) : base(message, innerException) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 1183e9fb2..9397a347f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -166,7 +166,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Validates the supplied FQPN to ensure it is a ffmpeg utility. /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. /// </summary> - /// <param name="path">FQPN to test</param> + /// <param name="path">FQPN to test.</param> /// <param name="location">Location (External, Custom, System) of tool</param> /// <returns></returns> private bool ValidatePath(string path, FFmpegLocation location) diff --git a/MediaBrowser.Model/Services/QueryParamCollection.cs b/MediaBrowser.Model/Services/QueryParamCollection.cs index d07ff1548..bdb0cabdf 100644 --- a/MediaBrowser.Model/Services/QueryParamCollection.cs +++ b/MediaBrowser.Model/Services/QueryParamCollection.cs @@ -124,8 +124,8 @@ namespace MediaBrowser.Model.Services /// Gets or sets a query parameter value by name. A query may contain multiple values of the same name /// (i.e. "x=1&x=2"), in which case the value is an array, which works for both getting and setting. /// </summary> - /// <param name="name">The query parameter name</param> - /// <returns>The query parameter value or array of values</returns> + /// <param name="name">The query parameter name.</param> + /// <returns>The query parameter value or array of values.</returns> public string this[string name] { get => Get(name); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 3c0922f39..1961e8bff 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -312,7 +312,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies /// <param name="id">The id.</param> /// <param name="isTmdbId">if set to <c>true</c> [is TMDB identifier].</param> /// <param name="language">The language.</param> - /// <param name="cancellationToken">The cancellation token</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{CompleteMovieData}.</returns> internal async Task<MovieResult> FetchMainResult(string id, bool isTmdbId, string language, CancellationToken cancellationToken) { -- cgit v1.2.3 From 98db8f72e01b608e6c384ecf5b107fc2d105b652 Mon Sep 17 00:00:00 2001 From: telans <telans@protonmail.com> Date: Sat, 20 Jun 2020 20:35:29 +1200 Subject: fix SA1503 for one line if statements --- DvdLib/Ifo/Dvd.cs | 16 +++- DvdLib/Ifo/DvdTime.cs | 10 ++- DvdLib/Ifo/ProgramChain.cs | 11 ++- DvdLib/Ifo/Title.cs | 5 +- Emby.Dlna/PlayTo/PlayToManager.cs | 10 ++- .../Data/SqliteItemRepository.cs | 95 ++++++++++++++++++---- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 +- Emby.Server.Implementations/Net/UdpSocket.cs | 10 ++- .../Playlists/PlaylistManager.cs | 12 ++- .../Services/ServiceController.cs | 5 +- .../Services/ServiceExec.cs | 5 +- .../Services/ServicePath.cs | 5 +- Jellyfin.Data/Entities/Artwork.cs | 19 ++++- Jellyfin.Data/Entities/BookMetadata.cs | 18 +++- Jellyfin.Data/Entities/Chapter.cs | 12 ++- Jellyfin.Data/Entities/CollectionItem.cs | 19 ++++- Jellyfin.Data/Entities/Company.cs | 30 +++++-- Jellyfin.Data/Entities/CompanyMetadata.cs | 19 ++++- Jellyfin.Data/Entities/CustomItemMetadata.cs | 19 ++++- Jellyfin.Data/Entities/Episode.cs | 6 +- Jellyfin.Data/Entities/EpisodeMetadata.cs | 19 ++++- Jellyfin.Data/Entities/Genre.cs | 13 ++- Jellyfin.Data/Entities/Library.cs | 7 +- Jellyfin.Data/Entities/LibraryRoot.cs | 7 +- Jellyfin.Data/Entities/MediaFile.cs | 12 ++- Jellyfin.Data/Entities/MediaFileStream.cs | 7 +- Jellyfin.Data/Entities/Metadata.cs | 12 ++- Jellyfin.Data/Entities/MetadataProvider.cs | 7 +- Jellyfin.Data/Entities/MetadataProviderId.cs | 31 +++++-- Jellyfin.Data/Entities/MovieMetadata.cs | 18 +++- Jellyfin.Data/Entities/MusicAlbumMetadata.cs | 18 +++- Jellyfin.Data/Entities/Person.cs | 6 +- Jellyfin.Data/Entities/PersonRole.cs | 6 +- Jellyfin.Data/Entities/PhotoMetadata.cs | 19 ++++- Jellyfin.Data/Entities/ProviderMapping.cs | 19 ++++- Jellyfin.Data/Entities/Rating.cs | 7 +- Jellyfin.Data/Entities/RatingSource.cs | 7 +- Jellyfin.Data/Entities/Release.cs | 42 ++++++++-- Jellyfin.Data/Entities/Season.cs | 6 +- Jellyfin.Data/Entities/SeasonMetadata.cs | 19 ++++- Jellyfin.Data/Entities/SeriesMetadata.cs | 18 +++- Jellyfin.Data/Entities/Track.cs | 6 +- Jellyfin.Data/Entities/TrackMetadata.cs | 19 ++++- MediaBrowser.Controller/Entities/BaseItem.cs | 5 +- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 6 +- .../Probing/ProbeResultNormalizer.cs | 30 +++++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 5 +- MediaBrowser.Model/Entities/MediaStream.cs | 5 +- MediaBrowser.Model/Services/RouteAttribute.cs | 18 +++- .../Manager/ItemImageProvider.cs | 5 +- .../Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 5 +- .../Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 5 +- RSSDP/DeviceAvailableEventArgs.cs | 5 +- RSSDP/DeviceEventArgs.cs | 5 +- RSSDP/DeviceUnavailableEventArgs.cs | 5 +- RSSDP/DisposableManagedObjectBase.cs | 5 +- RSSDP/HttpParserBase.cs | 27 ++++-- RSSDP/HttpRequestParser.cs | 16 +++- RSSDP/HttpResponseParser.cs | 16 +++- RSSDP/IEnumerableExtensions.cs | 11 ++- RSSDP/SsdpCommunicationsServer.cs | 21 ++++- RSSDP/SsdpDevice.cs | 22 ++++- RSSDP/SsdpDeviceLocator.cs | 84 +++++++++++++++---- RSSDP/SsdpDevicePublisher.cs | 75 ++++++++++++++--- 64 files changed, 843 insertions(+), 193 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index ca20baa73..361319625 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -117,12 +117,19 @@ namespace DvdLib.Ifo uint chapNum = 1; vtsFs.Seek(baseAddr + offsets[titleNum], SeekOrigin.Begin); var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum + 1)); - if (t == null) continue; + if (t == null) + { + continue; + } do { t.Chapters.Add(new Chapter(vtsRead.ReadUInt16(), vtsRead.ReadUInt16(), chapNum)); - if (titleNum + 1 < numTitles && vtsFs.Position == (baseAddr + offsets[titleNum + 1])) break; + if (titleNum + 1 < numTitles && vtsFs.Position == (baseAddr + offsets[titleNum + 1])) + { + break; + } + chapNum++; } while (vtsFs.Position < (baseAddr + endaddr)); @@ -147,7 +154,10 @@ namespace DvdLib.Ifo uint vtsPgcOffset = vtsRead.ReadUInt32(); var t = Titles.FirstOrDefault(vtst => vtst.IsVTSTitle(vtsNum, titleNum)); - if (t != null) t.AddPgc(vtsRead, startByte + vtsPgcOffset, entryPgc, pgcNum); + if (t != null) + { + t.AddPgc(vtsRead, startByte + vtsPgcOffset, entryPgc, pgcNum); + } } } } diff --git a/DvdLib/Ifo/DvdTime.cs b/DvdLib/Ifo/DvdTime.cs index 978af90c2..d23140610 100644 --- a/DvdLib/Ifo/DvdTime.cs +++ b/DvdLib/Ifo/DvdTime.cs @@ -15,8 +15,14 @@ namespace DvdLib.Ifo Second = GetBCDValue(data[2]); Frames = GetBCDValue((byte)(data[3] & 0x3F)); - if ((data[3] & 0x80) != 0) FrameRate = 30; - else if ((data[3] & 0x40) != 0) FrameRate = 25; + if ((data[3] & 0x80) != 0) + { + FrameRate = 30; + } + else if ((data[3] & 0x40) != 0) + { + FrameRate = 25; + } } private static byte GetBCDValue(byte data) diff --git a/DvdLib/Ifo/ProgramChain.cs b/DvdLib/Ifo/ProgramChain.cs index 8048f4bbd..83c0051b9 100644 --- a/DvdLib/Ifo/ProgramChain.cs +++ b/DvdLib/Ifo/ProgramChain.cs @@ -75,8 +75,15 @@ namespace DvdLib.Ifo StillTime = br.ReadByte(); byte pbMode = br.ReadByte(); - if (pbMode == 0) PlaybackMode = ProgramPlaybackMode.Sequential; - else PlaybackMode = ((pbMode & 0x80) == 0) ? ProgramPlaybackMode.Random : ProgramPlaybackMode.Shuffle; + if (pbMode == 0) + { + PlaybackMode = ProgramPlaybackMode.Sequential; + } + else + { + PlaybackMode = ((pbMode & 0x80) == 0) ? ProgramPlaybackMode.Random : ProgramPlaybackMode.Shuffle; + } + ProgramCount = (uint)(pbMode & 0x7F); Palette = br.ReadBytes(64); diff --git a/DvdLib/Ifo/Title.cs b/DvdLib/Ifo/Title.cs index 4af3af754..29a0b95c7 100644 --- a/DvdLib/Ifo/Title.cs +++ b/DvdLib/Ifo/Title.cs @@ -59,7 +59,10 @@ namespace DvdLib.Ifo var pgc = new ProgramChain(pgcNum); pgc.ParseHeader(br); ProgramChains.Add(pgc); - if (entryPgc) EntryProgramChain = pgc; + if (entryPgc) + { + EntryProgramChain = pgc; + } br.BaseStream.Seek(curPos, SeekOrigin.Begin); } diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 240c8a7d9..512589e4d 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -78,9 +78,15 @@ namespace Emby.Dlna.PlayTo var info = e.Argument; - if (!info.Headers.TryGetValue("USN", out string usn)) usn = string.Empty; + if (!info.Headers.TryGetValue("USN", out string usn)) + { + usn = string.Empty; + } - if (!info.Headers.TryGetValue("NT", out string nt)) nt = string.Empty; + if (!info.Headers.TryGetValue("NT", out string nt)) + { + nt = string.Empty; + } string location = info.Location.ToString(); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 6e5389ad4..a6390b1ef 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2775,22 +2775,85 @@ namespace Emby.Server.Implementations.Data private string FixUnicodeChars(string buffer) { - if (buffer.IndexOf('\u2013') > -1) buffer = buffer.Replace('\u2013', '-'); // en dash - if (buffer.IndexOf('\u2014') > -1) buffer = buffer.Replace('\u2014', '-'); // em dash - if (buffer.IndexOf('\u2015') > -1) buffer = buffer.Replace('\u2015', '-'); // horizontal bar - if (buffer.IndexOf('\u2017') > -1) buffer = buffer.Replace('\u2017', '_'); // double low line - if (buffer.IndexOf('\u2018') > -1) buffer = buffer.Replace('\u2018', '\''); // left single quotation mark - if (buffer.IndexOf('\u2019') > -1) buffer = buffer.Replace('\u2019', '\''); // right single quotation mark - if (buffer.IndexOf('\u201a') > -1) buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark - if (buffer.IndexOf('\u201b') > -1) buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark - if (buffer.IndexOf('\u201c') > -1) buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark - if (buffer.IndexOf('\u201d') > -1) buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark - if (buffer.IndexOf('\u201e') > -1) buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark - if (buffer.IndexOf('\u2026') > -1) buffer = buffer.Replace("\u2026", "..."); // horizontal ellipsis - if (buffer.IndexOf('\u2032') > -1) buffer = buffer.Replace('\u2032', '\''); // prime - if (buffer.IndexOf('\u2033') > -1) buffer = buffer.Replace('\u2033', '\"'); // double prime - if (buffer.IndexOf('\u0060') > -1) buffer = buffer.Replace('\u0060', '\''); // grave accent - if (buffer.IndexOf('\u00B4') > -1) buffer = buffer.Replace('\u00B4', '\''); // acute accent + if (buffer.IndexOf('\u2013') > -1) + { + buffer = buffer.Replace('\u2013', '-'); // en dash + } + + if (buffer.IndexOf('\u2014') > -1) + { + buffer = buffer.Replace('\u2014', '-'); // em dash + } + + if (buffer.IndexOf('\u2015') > -1) + { + buffer = buffer.Replace('\u2015', '-'); // horizontal bar + } + + if (buffer.IndexOf('\u2017') > -1) + { + buffer = buffer.Replace('\u2017', '_'); // double low line + } + + if (buffer.IndexOf('\u2018') > -1) + { + buffer = buffer.Replace('\u2018', '\''); // left single quotation mark + } + + if (buffer.IndexOf('\u2019') > -1) + { + buffer = buffer.Replace('\u2019', '\''); // right single quotation mark + } + + if (buffer.IndexOf('\u201a') > -1) + { + buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark + } + + if (buffer.IndexOf('\u201b') > -1) + { + buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark + } + + if (buffer.IndexOf('\u201c') > -1) + { + buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark + } + + if (buffer.IndexOf('\u201d') > -1) + { + buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark + } + + if (buffer.IndexOf('\u201e') > -1) + { + buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark + } + + if (buffer.IndexOf('\u2026') > -1) + { + buffer = buffer.Replace("\u2026", "..."); // horizontal ellipsis + } + + if (buffer.IndexOf('\u2032') > -1) + { + buffer = buffer.Replace('\u2032', '\''); // prime + } + + if (buffer.IndexOf('\u2033') > -1) + { + buffer = buffer.Replace('\u2033', '\"'); // double prime + } + + if (buffer.IndexOf('\u0060') > -1) + { + buffer = buffer.Replace('\u0060', '\''); // grave accent + } + + if (buffer.IndexOf('\u00B4') > -1) + { + buffer = buffer.Replace('\u00B4', '\''); // acute accent + } return buffer; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index db9d24028..2e2488e6e 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -201,7 +201,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); var name = line.Substring(0, index - 1); var currentChannel = line.Substring(index + 7); - if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } + if (currentChannel != "none") + { + status = LiveTvTunerStatus.LiveTv; + } + else + { + status = LiveTvTunerStatus.Available; + } tuners.Add(new LiveTvTunerInfo { diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 848f82d85..b51c03446 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -37,7 +37,10 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, int localPort, IPAddress ip) { - if (socket == null) throw new ArgumentNullException(nameof(socket)); + if (socket == null) + { + throw new ArgumentNullException(nameof(socket)); + } _socket = socket; _localPort = localPort; @@ -103,7 +106,10 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, IPEndPoint endPoint) { - if (socket == null) throw new ArgumentNullException(nameof(socket)); + if (socket == null) + { + throw new ArgumentNullException(nameof(socket)); + } _socket = socket; _socket.Connect(endPoint); diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index ac816ccd9..5dd1af4b8 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -539,13 +539,21 @@ namespace Emby.Server.Implementations.Playlists private static string UnEscape(string content) { - if (content == null) return content; + if (content == null) + { + return content; + } + return content.Replace("&", "&").Replace("'", "'").Replace(""", "\"").Replace(">", ">").Replace("<", "<"); } private static string Escape(string content) { - if (content == null) return null; + if (content == null) + { + return null; + } + return content.Replace("&", "&").Replace("'", "'").Replace("\"", """).Replace(">", ">").Replace("<", "<"); } diff --git a/Emby.Server.Implementations/Services/ServiceController.cs b/Emby.Server.Implementations/Services/ServiceController.cs index b84e47140..857df591a 100644 --- a/Emby.Server.Implementations/Services/ServiceController.cs +++ b/Emby.Server.Implementations/Services/ServiceController.cs @@ -144,7 +144,10 @@ namespace Emby.Server.Implementations.Services var yieldedWildcardMatches = RestPath.GetFirstMatchWildCardHashKeys(matchUsingPathParts); foreach (var potentialHashMatch in yieldedWildcardMatches) { - if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches)) continue; + if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches)) + { + continue; + } var bestScore = -1; RestPath bestMatch = null; diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs index 606f2a240..18d7ab46e 100644 --- a/Emby.Server.Implementations/Services/ServiceExec.cs +++ b/Emby.Server.Implementations/Services/ServiceExec.cs @@ -63,7 +63,10 @@ namespace Emby.Server.Implementations.Services { foreach (var actionCtx in actions) { - if (execMap.ContainsKey(actionCtx.Id)) continue; + if (execMap.ContainsKey(actionCtx.Id)) + { + continue; + } execMap[actionCtx.Id] = actionCtx; } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 14ae126a3..eb0744189 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -124,7 +124,10 @@ namespace Emby.Server.Implementations.Services var hasSeparators = new List<bool>(); foreach (var component in this.restPath.Split(PathSeperatorChar)) { - if (string.IsNullOrEmpty(component)) continue; + if (string.IsNullOrEmpty(component)) + { + continue; + } if (component.IndexOf(VariablePrefix, StringComparison.OrdinalIgnoreCase) != -1 && component.IndexOf(ComponentSeperator) != -1) diff --git a/Jellyfin.Data/Entities/Artwork.cs b/Jellyfin.Data/Entities/Artwork.cs index df071e477..6ed32eac3 100644 --- a/Jellyfin.Data/Entities/Artwork.cs +++ b/Jellyfin.Data/Entities/Artwork.cs @@ -32,17 +32,28 @@ namespace Jellyfin.Data.Entities /// <param name="_personrole1"></param> public Artwork(string path, Enums.ArtKind kind, Metadata _metadata0, PersonRole _personrole1) { - if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path)); + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + this.Path = path; this.Kind = kind; - if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0)); + if (_metadata0 == null) + { + throw new ArgumentNullException(nameof(_metadata0)); + } + _metadata0.Artwork.Add(this); - if (_personrole1 == null) throw new ArgumentNullException(nameof(_personrole1)); - _personrole1.Artwork = this; + if (_personrole1 == null) + { + throw new ArgumentNullException(nameof(_personrole1)); + } + _personrole1.Artwork = this; Init(); } diff --git a/Jellyfin.Data/Entities/BookMetadata.cs b/Jellyfin.Data/Entities/BookMetadata.cs index dc7146371..df43090d3 100644 --- a/Jellyfin.Data/Entities/BookMetadata.cs +++ b/Jellyfin.Data/Entities/BookMetadata.cs @@ -34,13 +34,25 @@ namespace Jellyfin.Data.Entities /// <param name="_book0"></param> public BookMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Book _book0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_book0 == null) throw new ArgumentNullException(nameof(_book0)); + if (_book0 == null) + { + throw new ArgumentNullException(nameof(_book0)); + } + _book0.BookMetadata.Add(this); this.Publishers = new HashSet<Company>(); diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs index 960853e15..4575cdb4d 100644 --- a/Jellyfin.Data/Entities/Chapter.cs +++ b/Jellyfin.Data/Entities/Chapter.cs @@ -32,12 +32,20 @@ namespace Jellyfin.Data.Entities /// <param name="_release0"></param> public Chapter(string language, long timestart, Release _release0) { - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; this.TimeStart = timestart; - if (_release0 == null) throw new ArgumentNullException(nameof(_release0)); + if (_release0 == null) + { + throw new ArgumentNullException(nameof(_release0)); + } + _release0.Chapters.Add(this); diff --git a/Jellyfin.Data/Entities/CollectionItem.cs b/Jellyfin.Data/Entities/CollectionItem.cs index 08b0e99f4..d879806ee 100644 --- a/Jellyfin.Data/Entities/CollectionItem.cs +++ b/Jellyfin.Data/Entities/CollectionItem.cs @@ -38,15 +38,26 @@ namespace Jellyfin.Data.Entities // NOTE: This class has one-to-one associations with CollectionItem. // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - if (_collection0 == null) throw new ArgumentNullException(nameof(_collection0)); + if (_collection0 == null) + { + throw new ArgumentNullException(nameof(_collection0)); + } + _collection0.CollectionItem.Add(this); - if (_collectionitem1 == null) throw new ArgumentNullException(nameof(_collectionitem1)); + if (_collectionitem1 == null) + { + throw new ArgumentNullException(nameof(_collectionitem1)); + } + _collectionitem1.Next = this; - if (_collectionitem2 == null) throw new ArgumentNullException(nameof(_collectionitem2)); - _collectionitem2.Previous = this; + if (_collectionitem2 == null) + { + throw new ArgumentNullException(nameof(_collectionitem2)); + } + _collectionitem2.Previous = this; Init(); } diff --git a/Jellyfin.Data/Entities/Company.cs b/Jellyfin.Data/Entities/Company.cs index 2ac7bcfe5..e905a17da 100644 --- a/Jellyfin.Data/Entities/Company.cs +++ b/Jellyfin.Data/Entities/Company.cs @@ -37,19 +37,39 @@ namespace Jellyfin.Data.Entities /// <param name="_company4"></param> public Company(MovieMetadata _moviemetadata0, SeriesMetadata _seriesmetadata1, MusicAlbumMetadata _musicalbummetadata2, BookMetadata _bookmetadata3, Company _company4) { - if (_moviemetadata0 == null) throw new ArgumentNullException(nameof(_moviemetadata0)); + if (_moviemetadata0 == null) + { + throw new ArgumentNullException(nameof(_moviemetadata0)); + } + _moviemetadata0.Studios.Add(this); - if (_seriesmetadata1 == null) throw new ArgumentNullException(nameof(_seriesmetadata1)); + if (_seriesmetadata1 == null) + { + throw new ArgumentNullException(nameof(_seriesmetadata1)); + } + _seriesmetadata1.Networks.Add(this); - if (_musicalbummetadata2 == null) throw new ArgumentNullException(nameof(_musicalbummetadata2)); + if (_musicalbummetadata2 == null) + { + throw new ArgumentNullException(nameof(_musicalbummetadata2)); + } + _musicalbummetadata2.Labels.Add(this); - if (_bookmetadata3 == null) throw new ArgumentNullException(nameof(_bookmetadata3)); + if (_bookmetadata3 == null) + { + throw new ArgumentNullException(nameof(_bookmetadata3)); + } + _bookmetadata3.Publishers.Add(this); - if (_company4 == null) throw new ArgumentNullException(nameof(_company4)); + if (_company4 == null) + { + throw new ArgumentNullException(nameof(_company4)); + } + _company4.Parent = this; this.CompanyMetadata = new HashSet<CompanyMetadata>(); diff --git a/Jellyfin.Data/Entities/CompanyMetadata.cs b/Jellyfin.Data/Entities/CompanyMetadata.cs index 12f213310..e75349cf2 100644 --- a/Jellyfin.Data/Entities/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/CompanyMetadata.cs @@ -31,15 +31,26 @@ namespace Jellyfin.Data.Entities /// <param name="_company0"></param> public CompanyMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Company _company0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_company0 == null) throw new ArgumentNullException(nameof(_company0)); - _company0.CompanyMetadata.Add(this); + if (_company0 == null) + { + throw new ArgumentNullException(nameof(_company0)); + } + _company0.CompanyMetadata.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/CustomItemMetadata.cs b/Jellyfin.Data/Entities/CustomItemMetadata.cs index dd66c8f83..965ed731f 100644 --- a/Jellyfin.Data/Entities/CustomItemMetadata.cs +++ b/Jellyfin.Data/Entities/CustomItemMetadata.cs @@ -30,15 +30,26 @@ namespace Jellyfin.Data.Entities /// <param name="_customitem0"></param> public CustomItemMetadata(string title, string language, DateTime dateadded, DateTime datemodified, CustomItem _customitem0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_customitem0 == null) throw new ArgumentNullException(nameof(_customitem0)); - _customitem0.CustomItemMetadata.Add(this); + if (_customitem0 == null) + { + throw new ArgumentNullException(nameof(_customitem0)); + } + _customitem0.CustomItemMetadata.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/Episode.cs b/Jellyfin.Data/Entities/Episode.cs index 69106ab79..57fbf894b 100644 --- a/Jellyfin.Data/Entities/Episode.cs +++ b/Jellyfin.Data/Entities/Episode.cs @@ -42,7 +42,11 @@ namespace Jellyfin.Data.Entities this.UrlId = urlid; - if (_season0 == null) throw new ArgumentNullException(nameof(_season0)); + if (_season0 == null) + { + throw new ArgumentNullException(nameof(_season0)); + } + _season0.Episodes.Add(this); this.Releases = new HashSet<Release>(); diff --git a/Jellyfin.Data/Entities/EpisodeMetadata.cs b/Jellyfin.Data/Entities/EpisodeMetadata.cs index b17e4aa19..9a21fd50f 100644 --- a/Jellyfin.Data/Entities/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/EpisodeMetadata.cs @@ -31,15 +31,26 @@ namespace Jellyfin.Data.Entities /// <param name="_episode0"></param> public EpisodeMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Episode _episode0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_episode0 == null) throw new ArgumentNullException(nameof(_episode0)); - _episode0.EpisodeMetadata.Add(this); + if (_episode0 == null) + { + throw new ArgumentNullException(nameof(_episode0)); + } + _episode0.EpisodeMetadata.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/Genre.cs b/Jellyfin.Data/Entities/Genre.cs index 9b2264921..24e6815d8 100644 --- a/Jellyfin.Data/Entities/Genre.cs +++ b/Jellyfin.Data/Entities/Genre.cs @@ -31,12 +31,19 @@ namespace Jellyfin.Data.Entities /// <param name="_metadata0"></param> public Genre(string name, Metadata _metadata0) { - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + this.Name = name; - if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0)); - _metadata0.Genres.Add(this); + if (_metadata0 == null) + { + throw new ArgumentNullException(nameof(_metadata0)); + } + _metadata0.Genres.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/Library.cs b/Jellyfin.Data/Entities/Library.cs index ff94b93f0..d935e43b1 100644 --- a/Jellyfin.Data/Entities/Library.cs +++ b/Jellyfin.Data/Entities/Library.cs @@ -30,9 +30,12 @@ namespace Jellyfin.Data.Entities /// <param name="name"></param> public Library(string name) { - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); - this.Name = name; + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + this.Name = name; Init(); } diff --git a/Jellyfin.Data/Entities/LibraryRoot.cs b/Jellyfin.Data/Entities/LibraryRoot.cs index a6f3e49c9..9695ed638 100644 --- a/Jellyfin.Data/Entities/LibraryRoot.cs +++ b/Jellyfin.Data/Entities/LibraryRoot.cs @@ -30,9 +30,12 @@ namespace Jellyfin.Data.Entities /// <param name="path">Absolute Path.</param> public LibraryRoot(string path) { - if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path)); - this.Path = path; + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + this.Path = path; Init(); } diff --git a/Jellyfin.Data/Entities/MediaFile.cs b/Jellyfin.Data/Entities/MediaFile.cs index 5d9448d41..7382cda95 100644 --- a/Jellyfin.Data/Entities/MediaFile.cs +++ b/Jellyfin.Data/Entities/MediaFile.cs @@ -35,12 +35,20 @@ namespace Jellyfin.Data.Entities /// <param name="_release0"></param> public MediaFile(string path, Enums.MediaFileKind kind, Release _release0) { - if (string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path)); + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + this.Path = path; this.Kind = kind; - if (_release0 == null) throw new ArgumentNullException(nameof(_release0)); + if (_release0 == null) + { + throw new ArgumentNullException(nameof(_release0)); + } + _release0.MediaFiles.Add(this); this.MediaFileStreams = new HashSet<MediaFileStream>(); diff --git a/Jellyfin.Data/Entities/MediaFileStream.cs b/Jellyfin.Data/Entities/MediaFileStream.cs index c018c0cbf..977fd54e1 100644 --- a/Jellyfin.Data/Entities/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/MediaFileStream.cs @@ -33,9 +33,12 @@ namespace Jellyfin.Data.Entities { this.StreamNumber = streamnumber; - if (_mediafile0 == null) throw new ArgumentNullException(nameof(_mediafile0)); - _mediafile0.MediaFileStreams.Add(this); + if (_mediafile0 == null) + { + throw new ArgumentNullException(nameof(_mediafile0)); + } + _mediafile0.MediaFileStreams.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/Metadata.cs b/Jellyfin.Data/Entities/Metadata.cs index 8446c30b2..a4ac6dc54 100644 --- a/Jellyfin.Data/Entities/Metadata.cs +++ b/Jellyfin.Data/Entities/Metadata.cs @@ -30,10 +30,18 @@ namespace Jellyfin.Data.Entities /// <param name="language">ISO-639-3 3-character language codes.</param> protected Metadata(string title, string language, DateTime dateadded, DateTime datemodified) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; this.PersonRoles = new HashSet<PersonRole>(); diff --git a/Jellyfin.Data/Entities/MetadataProvider.cs b/Jellyfin.Data/Entities/MetadataProvider.cs index ae22ccfeb..e93ea97d6 100644 --- a/Jellyfin.Data/Entities/MetadataProvider.cs +++ b/Jellyfin.Data/Entities/MetadataProvider.cs @@ -30,9 +30,12 @@ namespace Jellyfin.Data.Entities /// <param name="name"></param> public MetadataProvider(string name) { - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); - this.Name = name; + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + this.Name = name; Init(); } diff --git a/Jellyfin.Data/Entities/MetadataProviderId.cs b/Jellyfin.Data/Entities/MetadataProviderId.cs index 30683ced3..68f139436 100644 --- a/Jellyfin.Data/Entities/MetadataProviderId.cs +++ b/Jellyfin.Data/Entities/MetadataProviderId.cs @@ -40,21 +40,40 @@ namespace Jellyfin.Data.Entities // NOTE: This class has one-to-one associations with MetadataProviderId. // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - if (string.IsNullOrEmpty(providerid)) throw new ArgumentNullException(nameof(providerid)); + if (string.IsNullOrEmpty(providerid)) + { + throw new ArgumentNullException(nameof(providerid)); + } + this.ProviderId = providerid; - if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0)); + if (_metadata0 == null) + { + throw new ArgumentNullException(nameof(_metadata0)); + } + _metadata0.Sources.Add(this); - if (_person1 == null) throw new ArgumentNullException(nameof(_person1)); + if (_person1 == null) + { + throw new ArgumentNullException(nameof(_person1)); + } + _person1.Sources.Add(this); - if (_personrole2 == null) throw new ArgumentNullException(nameof(_personrole2)); + if (_personrole2 == null) + { + throw new ArgumentNullException(nameof(_personrole2)); + } + _personrole2.Sources.Add(this); - if (_ratingsource3 == null) throw new ArgumentNullException(nameof(_ratingsource3)); - _ratingsource3.Source = this; + if (_ratingsource3 == null) + { + throw new ArgumentNullException(nameof(_ratingsource3)); + } + _ratingsource3.Source = this; Init(); } diff --git a/Jellyfin.Data/Entities/MovieMetadata.cs b/Jellyfin.Data/Entities/MovieMetadata.cs index 4fda88e8e..cbcb78e37 100644 --- a/Jellyfin.Data/Entities/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/MovieMetadata.cs @@ -35,13 +35,25 @@ namespace Jellyfin.Data.Entities /// <param name="_movie0"></param> public MovieMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Movie _movie0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_movie0 == null) throw new ArgumentNullException(nameof(_movie0)); + if (_movie0 == null) + { + throw new ArgumentNullException(nameof(_movie0)); + } + _movie0.MovieMetadata.Add(this); this.Studios = new HashSet<Company>(); diff --git a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs index a5056adc0..bfcbebbe8 100644 --- a/Jellyfin.Data/Entities/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/MusicAlbumMetadata.cs @@ -35,13 +35,25 @@ namespace Jellyfin.Data.Entities /// <param name="_musicalbum0"></param> public MusicAlbumMetadata(string title, string language, DateTime dateadded, DateTime datemodified, MusicAlbum _musicalbum0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_musicalbum0 == null) throw new ArgumentNullException(nameof(_musicalbum0)); + if (_musicalbum0 == null) + { + throw new ArgumentNullException(nameof(_musicalbum0)); + } + _musicalbum0.MusicAlbumMetadata.Add(this); this.Labels = new HashSet<Company>(); diff --git a/Jellyfin.Data/Entities/Person.cs b/Jellyfin.Data/Entities/Person.cs index 206fe7709..b6d91ea86 100644 --- a/Jellyfin.Data/Entities/Person.cs +++ b/Jellyfin.Data/Entities/Person.cs @@ -36,7 +36,11 @@ namespace Jellyfin.Data.Entities { this.UrlId = urlid; - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + this.Name = name; this.Sources = new HashSet<MetadataProviderId>(); diff --git a/Jellyfin.Data/Entities/PersonRole.cs b/Jellyfin.Data/Entities/PersonRole.cs index 928eb74ae..2dd5f116f 100644 --- a/Jellyfin.Data/Entities/PersonRole.cs +++ b/Jellyfin.Data/Entities/PersonRole.cs @@ -42,7 +42,11 @@ namespace Jellyfin.Data.Entities this.Type = type; - if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0)); + if (_metadata0 == null) + { + throw new ArgumentNullException(nameof(_metadata0)); + } + _metadata0.PersonRoles.Add(this); this.Sources = new HashSet<MetadataProviderId>(); diff --git a/Jellyfin.Data/Entities/PhotoMetadata.cs b/Jellyfin.Data/Entities/PhotoMetadata.cs index 4a0b07ff8..b5aec7229 100644 --- a/Jellyfin.Data/Entities/PhotoMetadata.cs +++ b/Jellyfin.Data/Entities/PhotoMetadata.cs @@ -31,15 +31,26 @@ namespace Jellyfin.Data.Entities /// <param name="_photo0"></param> public PhotoMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Photo _photo0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_photo0 == null) throw new ArgumentNullException(nameof(_photo0)); - _photo0.PhotoMetadata.Add(this); + if (_photo0 == null) + { + throw new ArgumentNullException(nameof(_photo0)); + } + _photo0.PhotoMetadata.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/ProviderMapping.cs b/Jellyfin.Data/Entities/ProviderMapping.cs index 4125eabcd..c53e3bf40 100644 --- a/Jellyfin.Data/Entities/ProviderMapping.cs +++ b/Jellyfin.Data/Entities/ProviderMapping.cs @@ -34,15 +34,26 @@ namespace Jellyfin.Data.Entities /// <param name="_group1"></param> public ProviderMapping(string providername, string providersecrets, string providerdata, User _user0, Group _group1) { - if (string.IsNullOrEmpty(providername)) throw new ArgumentNullException(nameof(providername)); + if (string.IsNullOrEmpty(providername)) + { + throw new ArgumentNullException(nameof(providername)); + } + this.ProviderName = providername; - if (string.IsNullOrEmpty(providersecrets)) throw new ArgumentNullException(nameof(providersecrets)); + if (string.IsNullOrEmpty(providersecrets)) + { + throw new ArgumentNullException(nameof(providersecrets)); + } + this.ProviderSecrets = providersecrets; - if (string.IsNullOrEmpty(providerdata)) throw new ArgumentNullException(nameof(providerdata)); - this.ProviderData = providerdata; + if (string.IsNullOrEmpty(providerdata)) + { + throw new ArgumentNullException(nameof(providerdata)); + } + this.ProviderData = providerdata; Init(); } diff --git a/Jellyfin.Data/Entities/Rating.cs b/Jellyfin.Data/Entities/Rating.cs index e00d5297d..49a0d502d 100644 --- a/Jellyfin.Data/Entities/Rating.cs +++ b/Jellyfin.Data/Entities/Rating.cs @@ -33,9 +33,12 @@ namespace Jellyfin.Data.Entities { this.Value = value; - if (_metadata0 == null) throw new ArgumentNullException(nameof(_metadata0)); - _metadata0.Ratings.Add(this); + if (_metadata0 == null) + { + throw new ArgumentNullException(nameof(_metadata0)); + } + _metadata0.Ratings.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/RatingSource.cs b/Jellyfin.Data/Entities/RatingSource.cs index 941f53e52..b62d8b444 100644 --- a/Jellyfin.Data/Entities/RatingSource.cs +++ b/Jellyfin.Data/Entities/RatingSource.cs @@ -39,9 +39,12 @@ namespace Jellyfin.Data.Entities this.MinimumValue = minimumvalue; - if (_rating0 == null) throw new ArgumentNullException(nameof(_rating0)); - _rating0.RatingType = this; + if (_rating0 == null) + { + throw new ArgumentNullException(nameof(_rating0)); + } + _rating0.RatingType = this; Init(); } diff --git a/Jellyfin.Data/Entities/Release.cs b/Jellyfin.Data/Entities/Release.cs index e08c04545..1e9faa5a1 100644 --- a/Jellyfin.Data/Entities/Release.cs +++ b/Jellyfin.Data/Entities/Release.cs @@ -40,25 +40,53 @@ namespace Jellyfin.Data.Entities /// <param name="_photo5"></param> public Release(string name, Movie _movie0, Episode _episode1, Track _track2, CustomItem _customitem3, Book _book4, Photo _photo5) { - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); + } + this.Name = name; - if (_movie0 == null) throw new ArgumentNullException(nameof(_movie0)); + if (_movie0 == null) + { + throw new ArgumentNullException(nameof(_movie0)); + } + _movie0.Releases.Add(this); - if (_episode1 == null) throw new ArgumentNullException(nameof(_episode1)); + if (_episode1 == null) + { + throw new ArgumentNullException(nameof(_episode1)); + } + _episode1.Releases.Add(this); - if (_track2 == null) throw new ArgumentNullException(nameof(_track2)); + if (_track2 == null) + { + throw new ArgumentNullException(nameof(_track2)); + } + _track2.Releases.Add(this); - if (_customitem3 == null) throw new ArgumentNullException(nameof(_customitem3)); + if (_customitem3 == null) + { + throw new ArgumentNullException(nameof(_customitem3)); + } + _customitem3.Releases.Add(this); - if (_book4 == null) throw new ArgumentNullException(nameof(_book4)); + if (_book4 == null) + { + throw new ArgumentNullException(nameof(_book4)); + } + _book4.Releases.Add(this); - if (_photo5 == null) throw new ArgumentNullException(nameof(_photo5)); + if (_photo5 == null) + { + throw new ArgumentNullException(nameof(_photo5)); + } + _photo5.Releases.Add(this); this.MediaFiles = new HashSet<MediaFile>(); diff --git a/Jellyfin.Data/Entities/Season.cs b/Jellyfin.Data/Entities/Season.cs index d71f4b522..4b1e78575 100644 --- a/Jellyfin.Data/Entities/Season.cs +++ b/Jellyfin.Data/Entities/Season.cs @@ -42,7 +42,11 @@ namespace Jellyfin.Data.Entities this.UrlId = urlid; - if (_series0 == null) throw new ArgumentNullException(nameof(_series0)); + if (_series0 == null) + { + throw new ArgumentNullException(nameof(_series0)); + } + _series0.Seasons.Add(this); this.SeasonMetadata = new HashSet<SeasonMetadata>(); diff --git a/Jellyfin.Data/Entities/SeasonMetadata.cs b/Jellyfin.Data/Entities/SeasonMetadata.cs index 8c72d9952..10d19875e 100644 --- a/Jellyfin.Data/Entities/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/SeasonMetadata.cs @@ -32,15 +32,26 @@ namespace Jellyfin.Data.Entities /// <param name="_season0"></param> public SeasonMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Season _season0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_season0 == null) throw new ArgumentNullException(nameof(_season0)); - _season0.SeasonMetadata.Add(this); + if (_season0 == null) + { + throw new ArgumentNullException(nameof(_season0)); + } + _season0.SeasonMetadata.Add(this); Init(); } diff --git a/Jellyfin.Data/Entities/SeriesMetadata.cs b/Jellyfin.Data/Entities/SeriesMetadata.cs index 2c04ef12f..16eb59315 100644 --- a/Jellyfin.Data/Entities/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/SeriesMetadata.cs @@ -35,13 +35,25 @@ namespace Jellyfin.Data.Entities /// <param name="_series0"></param> public SeriesMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Series _series0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_series0 == null) throw new ArgumentNullException(nameof(_series0)); + if (_series0 == null) + { + throw new ArgumentNullException(nameof(_series0)); + } + _series0.SeriesMetadata.Add(this); this.Networks = new HashSet<Company>(); diff --git a/Jellyfin.Data/Entities/Track.cs b/Jellyfin.Data/Entities/Track.cs index e13a53d38..b7d7b5873 100644 --- a/Jellyfin.Data/Entities/Track.cs +++ b/Jellyfin.Data/Entities/Track.cs @@ -42,7 +42,11 @@ namespace Jellyfin.Data.Entities this.UrlId = urlid; - if (_musicalbum0 == null) throw new ArgumentNullException(nameof(_musicalbum0)); + if (_musicalbum0 == null) + { + throw new ArgumentNullException(nameof(_musicalbum0)); + } + _musicalbum0.Tracks.Add(this); this.Releases = new HashSet<Release>(); diff --git a/Jellyfin.Data/Entities/TrackMetadata.cs b/Jellyfin.Data/Entities/TrackMetadata.cs index 55f4a38e0..23e1219aa 100644 --- a/Jellyfin.Data/Entities/TrackMetadata.cs +++ b/Jellyfin.Data/Entities/TrackMetadata.cs @@ -31,15 +31,26 @@ namespace Jellyfin.Data.Entities /// <param name="_track0"></param> public TrackMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Track _track0) { - if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(nameof(title)); + if (string.IsNullOrEmpty(title)) + { + throw new ArgumentNullException(nameof(title)); + } + this.Title = title; - if (string.IsNullOrEmpty(language)) throw new ArgumentNullException(nameof(language)); + if (string.IsNullOrEmpty(language)) + { + throw new ArgumentNullException(nameof(language)); + } + this.Language = language; - if (_track0 == null) throw new ArgumentNullException(nameof(_track0)); - _track0.TrackMetadata.Add(this); + if (_track0 == null) + { + throw new ArgumentNullException(nameof(_track0)); + } + _track0.TrackMetadata.Add(this); Init(); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7b833c36b..2ad1c717c 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -690,7 +690,10 @@ namespace MediaBrowser.Controller.Entities /// <returns>System.String.</returns> protected virtual string CreateSortName() { - if (Name == null) return null; // some items may not have name filled in properly + if (Name == null) + { + return null; // some items may not have name filled in properly + } if (!EnableAlphaNumericSorting) { diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 731c6d667..2e5dcc4c5 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -252,7 +252,11 @@ namespace MediaBrowser.Controller.Library { if (args != null) { - if (args.Path == null && Path == null) return true; + if (args.Path == null && Path == null) + { + return true; + } + return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ba807ab85..190abaa05 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1065,23 +1065,43 @@ namespace MediaBrowser.MediaEncoding.Probing // These support mulitple values, but for now we only store the first. var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); + if (mb == null) + { + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); + } + audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); - if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); + if (mb == null) + { + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); + } + audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); - if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); + if (mb == null) + { + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); + } + audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); - if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); + if (mb == null) + { + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); + } + audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); - if (mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); + if (mb == null) + { + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); + } + audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 06bd24476..cfe862f5a 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -384,7 +384,10 @@ namespace MediaBrowser.Model.Dlna audioCodecProfiles.Add(i); } - if (audioCodecProfiles.Count >= 1) break; + if (audioCodecProfiles.Count >= 1) + { + break; + } } var audioTranscodingConditions = new List<ProfileCondition>(); diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index d8ee79d0d..7a488005e 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -421,7 +421,10 @@ namespace MediaBrowser.Model.Entities { get { - if (Type != MediaStreamType.Subtitle) return false; + if (Type != MediaStreamType.Subtitle) + { + return false; + } if (string.IsNullOrEmpty(Codec) && !IsExternal) { diff --git a/MediaBrowser.Model/Services/RouteAttribute.cs b/MediaBrowser.Model/Services/RouteAttribute.cs index 162576aa7..f8bf51112 100644 --- a/MediaBrowser.Model/Services/RouteAttribute.cs +++ b/MediaBrowser.Model/Services/RouteAttribute.cs @@ -128,9 +128,21 @@ namespace MediaBrowser.Model.Services public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + return Equals((RouteAttribute)obj); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index cf5546602..82ed65ebb 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -113,7 +113,10 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in images) { - if (!IsEnabled(savedOptions, imageType, item)) continue; + if (!IsEnabled(savedOptions, imageType, item)) + { + continue; + } if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType))) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs index 15f0a9004..71799efa4 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -159,7 +159,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets { var mainResult = await FetchMainResult(tmdbId, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); - if (mainResult == null) return; + if (mainResult == null) + { + return; + } var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, preferredMetadataLanguage); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 1961e8bff..1c4cf1da1 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -194,7 +194,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { var mainResult = await FetchMainResult(id, true, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); - if (mainResult == null) return; + if (mainResult == null) + { + return; + } var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage); diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs index 9c57471ca..b7d22a7df 100644 --- a/RSSDP/DeviceAvailableEventArgs.cs +++ b/RSSDP/DeviceAvailableEventArgs.cs @@ -22,7 +22,10 @@ namespace Rssdp /// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception> public DeviceAvailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool isNewlyDiscovered) { - if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice)); + if (discoveredDevice == null) + { + throw new ArgumentNullException(nameof(discoveredDevice)); + } _DiscoveredDevice = discoveredDevice; _IsNewlyDiscovered = isNewlyDiscovered; diff --git a/RSSDP/DeviceEventArgs.cs b/RSSDP/DeviceEventArgs.cs index b124527ca..2455ccbfa 100644 --- a/RSSDP/DeviceEventArgs.cs +++ b/RSSDP/DeviceEventArgs.cs @@ -16,7 +16,10 @@ namespace Rssdp /// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> argument is null.</exception> public DeviceEventArgs(SsdpDevice device) { - if (device == null) throw new ArgumentNullException(nameof(device)); + if (device == null) + { + throw new ArgumentNullException(nameof(device)); + } _Device = device; } diff --git a/RSSDP/DeviceUnavailableEventArgs.cs b/RSSDP/DeviceUnavailableEventArgs.cs index cee59268d..94248f39f 100644 --- a/RSSDP/DeviceUnavailableEventArgs.cs +++ b/RSSDP/DeviceUnavailableEventArgs.cs @@ -19,7 +19,10 @@ namespace Rssdp /// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception> public DeviceUnavailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool expired) { - if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice)); + if (discoveredDevice == null) + { + throw new ArgumentNullException(nameof(discoveredDevice)); + } _DiscoveredDevice = discoveredDevice; _Expired = expired; diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index befa4ccff..628572b17 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -23,7 +23,10 @@ namespace Rssdp.Infrastructure /// <seealso cref="Dispose()"/> protected virtual void ThrowIfDisposed() { - if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().FullName); + if (this.IsDisposed) + { + throw new ObjectDisposedException(this.GetType().FullName); + } } /// <summary> diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index ff97b6db8..058bfbf55 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -31,9 +31,20 @@ namespace Rssdp.Infrastructure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Honestly, it's fine. MemoryStream doesn't mind.")] protected virtual void Parse(T message, System.Net.Http.Headers.HttpHeaders headers, string data) { - if (data == null) throw new ArgumentNullException(nameof(data)); - if (data.Length == 0) throw new ArgumentException("data cannot be an empty string.", nameof(data)); - if (!LineTerminators.Any(data.Contains)) throw new ArgumentException("data is not a valid request, it does not contain any CRLF/LF terminators.", nameof(data)); + if (data == null) + { + throw new ArgumentNullException(nameof(data)); + } + + if (data.Length == 0) + { + throw new ArgumentException("data cannot be an empty string.", nameof(data)); + } + + if (!LineTerminators.Any(data.Contains)) + { + throw new ArgumentException("data is not a valid request, it does not contain any CRLF/LF terminators.", nameof(data)); + } using (var retVal = new ByteArrayContent(Array.Empty<byte>())) { @@ -66,10 +77,16 @@ namespace Rssdp.Infrastructure /// <returns>A <see cref="Version"/> object containing the parsed version data.</returns> protected Version ParseHttpVersion(string versionData) { - if (versionData == null) throw new ArgumentNullException(nameof(versionData)); + if (versionData == null) + { + throw new ArgumentNullException(nameof(versionData)); + } var versionSeparatorIndex = versionData.IndexOf('/'); - if (versionSeparatorIndex <= 0 || versionSeparatorIndex == versionData.Length) throw new ArgumentException("request header line is invalid. Http Version not supplied or incorrect format.", nameof(versionData)); + if (versionSeparatorIndex <= 0 || versionSeparatorIndex == versionData.Length) + { + throw new ArgumentException("request header line is invalid. Http Version not supplied or incorrect format.", nameof(versionData)); + } return Version.Parse(versionData.Substring(versionSeparatorIndex + 1)); } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index 31f042791..6b27fc4df 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -45,11 +45,21 @@ namespace Rssdp.Infrastructure /// <param name="message">Either a <see cref="HttpResponseMessage"/> or <see cref="HttpRequestMessage"/> to assign the parsed values to.</param> protected override void ParseStatusLine(string data, HttpRequestMessage message) { - if (data == null) throw new ArgumentNullException(nameof(data)); - if (message == null) throw new ArgumentNullException(nameof(message)); + if (data == null) + { + throw new ArgumentNullException(nameof(data)); + } + + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } var parts = data.Split(' '); - if (parts.Length < 2) throw new ArgumentException("Status line is invalid. Insufficient status parts.", nameof(data)); + if (parts.Length < 2) + { + throw new ArgumentException("Status line is invalid. Insufficient status parts.", nameof(data)); + } message.Method = new HttpMethod(parts[0].Trim()); Uri requestUri; diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index 02c548d72..0337b3e36 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -57,11 +57,21 @@ namespace Rssdp.Infrastructure /// <param name="message">Either a <see cref="HttpResponseMessage"/> or <see cref="HttpRequestMessage"/> to assign the parsed values to.</param> protected override void ParseStatusLine(string data, HttpResponseMessage message) { - if (data == null) throw new ArgumentNullException(nameof(data)); - if (message == null) throw new ArgumentNullException(nameof(message)); + if (data == null) + { + throw new ArgumentNullException(nameof(data)); + } + + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } var parts = data.Split(' '); - if (parts.Length < 2) throw new ArgumentException("data status line is invalid. Insufficient status parts.", nameof(data)); + if (parts.Length < 2) + { + throw new ArgumentException("data status line is invalid. Insufficient status parts.", nameof(data)); + } message.Version = ParseHttpVersion(parts[0].Trim()); diff --git a/RSSDP/IEnumerableExtensions.cs b/RSSDP/IEnumerableExtensions.cs index 371454893..1f0daad3e 100644 --- a/RSSDP/IEnumerableExtensions.cs +++ b/RSSDP/IEnumerableExtensions.cs @@ -8,8 +8,15 @@ namespace Rssdp.Infrastructure { public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector) { - if (source == null) throw new ArgumentNullException(nameof(source)); - if (selector == null) throw new ArgumentNullException(nameof(selector)); + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (selector == null) + { + throw new ArgumentNullException(nameof(selector)); + } return !source.Any() ? source : source.Concat( diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 12ecf24f3..31ca90424 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -80,8 +80,15 @@ namespace Rssdp.Infrastructure /// <exception cref="ArgumentOutOfRangeException">The <paramref name="multicastTimeToLive"/> argument is less than or equal to zero.</exception> public SsdpCommunicationsServer(ISocketFactory socketFactory, int localPort, int multicastTimeToLive, INetworkManager networkManager, ILogger logger, bool enableMultiSocketBinding) { - if (socketFactory == null) throw new ArgumentNullException(nameof(socketFactory)); - if (multicastTimeToLive <= 0) throw new ArgumentOutOfRangeException(nameof(multicastTimeToLive), "multicastTimeToLive must be greater than zero."); + if (socketFactory == null) + { + throw new ArgumentNullException(nameof(socketFactory)); + } + + if (multicastTimeToLive <= 0) + { + throw new ArgumentOutOfRangeException(nameof(multicastTimeToLive), "multicastTimeToLive must be greater than zero."); + } _BroadcastListenSocketSynchroniser = new object(); _SendSocketSynchroniser = new object(); @@ -151,7 +158,10 @@ namespace Rssdp.Infrastructure /// </summary> public async Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { - if (messageData == null) throw new ArgumentNullException(nameof(messageData)); + if (messageData == null) + { + throw new ArgumentNullException(nameof(messageData)); + } ThrowIfDisposed(); @@ -234,7 +244,10 @@ namespace Rssdp.Infrastructure /// </summary> public async Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken) { - if (message == null) throw new ArgumentNullException(nameof(message)); + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } byte[] messageData = Encoding.UTF8.GetBytes(message); diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 5b7d782b5..42f95862c 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -259,9 +259,20 @@ namespace Rssdp /// <seealso cref="DeviceAdded"/> public void AddDevice(SsdpEmbeddedDevice device) { - if (device == null) throw new ArgumentNullException(nameof(device)); - if (device.RootDevice != null && device.RootDevice != this.ToRootDevice()) throw new InvalidOperationException("This device is already associated with a different root device (has been added as a child in another branch)."); - if (device == this) throw new InvalidOperationException("Can't add device to itself."); + if (device == null) + { + throw new ArgumentNullException(nameof(device)); + } + + if (device.RootDevice != null && device.RootDevice != this.ToRootDevice()) + { + throw new InvalidOperationException("This device is already associated with a different root device (has been added as a child in another branch)."); + } + + if (device == this) + { + throw new InvalidOperationException("Can't add device to itself."); + } bool wasAdded = false; lock (_Devices) @@ -287,7 +298,10 @@ namespace Rssdp /// <seealso cref="DeviceRemoved"/> public void RemoveDevice(SsdpEmbeddedDevice device) { - if (device == null) throw new ArgumentNullException(nameof(device)); + if (device == null) + { + throw new ArgumentNullException(nameof(device)); + } bool wasRemoved = false; lock (_Devices) diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index b117c0b1e..a774ee23c 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -27,7 +27,10 @@ namespace Rssdp.Infrastructure /// </summary> public SsdpDeviceLocator(ISsdpCommunicationsServer communicationsServer) { - if (communicationsServer == null) throw new ArgumentNullException(nameof(communicationsServer)); + if (communicationsServer == null) + { + throw new ArgumentNullException(nameof(communicationsServer)); + } _CommunicationsServer = communicationsServer; _CommunicationsServer.ResponseReceived += CommsServer_ResponseReceived; @@ -140,10 +143,25 @@ namespace Rssdp.Infrastructure private Task SearchAsync(string searchTarget, TimeSpan searchWaitTime, CancellationToken cancellationToken) { - if (searchTarget == null) throw new ArgumentNullException(nameof(searchTarget)); - if (searchTarget.Length == 0) throw new ArgumentException("searchTarget cannot be an empty string.", nameof(searchTarget)); - if (searchWaitTime.TotalSeconds < 0) throw new ArgumentException("searchWaitTime must be a positive time."); - if (searchWaitTime.TotalSeconds > 0 && searchWaitTime.TotalSeconds <= 1) throw new ArgumentException("searchWaitTime must be zero (if you are not using the result and relying entirely in the events), or greater than one second."); + if (searchTarget == null) + { + throw new ArgumentNullException(nameof(searchTarget)); + } + + if (searchTarget.Length == 0) + { + throw new ArgumentException("searchTarget cannot be an empty string.", nameof(searchTarget)); + } + + if (searchWaitTime.TotalSeconds < 0) + { + throw new ArgumentException("searchWaitTime must be a positive time."); + } + + if (searchWaitTime.TotalSeconds > 0 && searchWaitTime.TotalSeconds <= 1) + { + throw new ArgumentException("searchWaitTime must be zero (if you are not using the result and relying entirely in the events), or greater than one second."); + } ThrowIfDisposed(); @@ -192,7 +210,10 @@ namespace Rssdp.Infrastructure /// <seealso cref="DeviceAvailable"/> protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress) { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } var handlers = this.DeviceAvailable; if (handlers != null) @@ -210,11 +231,16 @@ namespace Rssdp.Infrastructure /// <seealso cref="DeviceUnavailable"/> protected virtual void OnDeviceUnavailable(DiscoveredSsdpDevice device, bool expired) { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } var handlers = this.DeviceUnavailable; if (handlers != null) + { handlers(this, new DeviceUnavailableEventArgs(device, expired)); + } } /// <summary> @@ -281,7 +307,10 @@ namespace Rssdp.Infrastructure private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress) { - if (!NotificationTypeMatchesFilter(device)) return; + if (!NotificationTypeMatchesFilter(device)) + { + return; + } OnDeviceAvailable(device, isNewDevice, localIpAddress); } @@ -318,7 +347,10 @@ namespace Rssdp.Infrastructure private void ProcessSearchResponseMessage(HttpResponseMessage message, IPAddress localIpAddress) { - if (!message.IsSuccessStatusCode) return; + if (!message.IsSuccessStatusCode) + { + return; + } var location = GetFirstHeaderUriValue("Location", message); if (location != null) @@ -339,13 +371,20 @@ namespace Rssdp.Infrastructure private void ProcessNotificationMessage(HttpRequestMessage message, IPAddress localIpAddress) { - if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) return; + if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) + { + return; + } var notificationType = GetFirstHeaderStringValue("NTS", message); if (String.Compare(notificationType, SsdpConstants.SsdpKeepAliveNotification, StringComparison.OrdinalIgnoreCase) == 0) + { ProcessAliveNotification(message, localIpAddress); + } else if (String.Compare(notificationType, SsdpConstants.SsdpByeByeNotification, StringComparison.OrdinalIgnoreCase) == 0) + { ProcessByeByeNotification(message); + } } private void ProcessAliveNotification(HttpRequestMessage message, IPAddress localIpAddress) @@ -454,14 +493,20 @@ namespace Rssdp.Infrastructure private TimeSpan CacheAgeFromHeader(System.Net.Http.Headers.CacheControlHeaderValue headerValue) { - if (headerValue == null) return TimeSpan.Zero; + if (headerValue == null) + { + return TimeSpan.Zero; + } return (TimeSpan)(headerValue.MaxAge ?? headerValue.SharedMaxAge ?? TimeSpan.Zero); } private void RemoveExpiredDevicesFromCache() { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } DiscoveredSsdpDevice[] expiredDevices = null; lock (_Devices) @@ -470,7 +515,10 @@ namespace Rssdp.Infrastructure foreach (var device in expiredDevices) { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } _Devices.Remove(device); } @@ -481,7 +529,10 @@ namespace Rssdp.Infrastructure // problems. foreach (var expiredUsn in (from expiredDevice in expiredDevices select expiredDevice.Usn).Distinct()) { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } DeviceDied(expiredUsn, true); } @@ -495,7 +546,10 @@ namespace Rssdp.Infrastructure existingDevices = FindExistingDeviceNotifications(_Devices, deviceUsn); foreach (var existingDevice in existingDevices) { - if (this.IsDisposed) return true; + if (this.IsDisposed) + { + return true; + } _Devices.Remove(existingDevice); } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index b4cf2fb48..1b64d230d 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -40,12 +40,35 @@ namespace Rssdp.Infrastructure public SsdpDevicePublisher(ISsdpCommunicationsServer communicationsServer, INetworkManager networkManager, string osName, string osVersion, bool sendOnlyMatchedHost) { - if (communicationsServer == null) throw new ArgumentNullException(nameof(communicationsServer)); - if (networkManager == null) throw new ArgumentNullException(nameof(networkManager)); - if (osName == null) throw new ArgumentNullException(nameof(osName)); - if (osName.Length == 0) throw new ArgumentException("osName cannot be an empty string.", nameof(osName)); - if (osVersion == null) throw new ArgumentNullException(nameof(osVersion)); - if (osVersion.Length == 0) throw new ArgumentException("osVersion cannot be an empty string.", nameof(osName)); + if (communicationsServer == null) + { + throw new ArgumentNullException(nameof(communicationsServer)); + } + + if (networkManager == null) + { + throw new ArgumentNullException(nameof(networkManager)); + } + + if (osName == null) + { + throw new ArgumentNullException(nameof(osName)); + } + + if (osName.Length == 0) + { + throw new ArgumentException("osName cannot be an empty string.", nameof(osName)); + } + + if (osVersion == null) + { + throw new ArgumentNullException(nameof(osVersion)); + } + + if (osVersion.Length == 0) + { + throw new ArgumentException("osVersion cannot be an empty string.", nameof(osName)); + } _SupportPnpRootDevice = true; _Devices = new List<SsdpRootDevice>(); @@ -82,7 +105,10 @@ namespace Rssdp.Infrastructure [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "t", Justification = "Capture task to local variable supresses compiler warning, but task is not really needed.")] public void AddDevice(SsdpRootDevice device) { - if (device == null) throw new ArgumentNullException(nameof(device)); + if (device == null) + { + throw new ArgumentNullException(nameof(device)); + } ThrowIfDisposed(); @@ -115,7 +141,10 @@ namespace Rssdp.Infrastructure /// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> argument is null.</exception> public async Task RemoveDevice(SsdpRootDevice device) { - if (device == null) throw new ArgumentNullException(nameof(device)); + if (device == null) + { + throw new ArgumentNullException(nameof(device)); + } bool wasRemoved = false; lock (_Devices) @@ -227,10 +256,15 @@ namespace Rssdp.Infrastructure // return; } - if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) return; + if (!Int32.TryParse(mx, out maxWaitInterval) || maxWaitInterval <= 0) + { + return; + } if (maxWaitInterval > 120) + { maxWaitInterval = _Random.Next(0, 120); + } // Do not block synchronously as that may tie up a threadpool thread for several seconds. Task.Delay(_Random.Next(16, (maxWaitInterval * 1000))).ContinueWith((parentTask) => @@ -240,13 +274,21 @@ namespace Rssdp.Infrastructure lock (_Devices) { if (String.Compare(SsdpConstants.SsdpDiscoverAllSTHeader, searchTarget, StringComparison.OrdinalIgnoreCase) == 0) + { devices = GetAllDevicesAsFlatEnumerable().ToArray(); + } else if (String.Compare(SsdpConstants.UpnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 || (this.SupportPnpRootDevice && String.Compare(SsdpConstants.PnpDeviceTypeRootDevice, searchTarget, StringComparison.OrdinalIgnoreCase) == 0)) + { devices = _Devices.ToArray(); + } else if (searchTarget.Trim().StartsWith("uuid:", StringComparison.OrdinalIgnoreCase)) + { devices = (from device in GetAllDevicesAsFlatEnumerable() where String.Compare(device.Uuid, searchTarget.Substring(5), StringComparison.OrdinalIgnoreCase) == 0 select device).ToArray(); + } else if (searchTarget.StartsWith("urn:", StringComparison.OrdinalIgnoreCase)) + { devices = (from device in GetAllDevicesAsFlatEnumerable() where String.Compare(device.FullDeviceType, searchTarget, StringComparison.OrdinalIgnoreCase) == 0 select device).ToArray(); + } } if (devices != null) @@ -382,7 +424,10 @@ namespace Rssdp.Infrastructure { try { - if (IsDisposed) return; + if (IsDisposed) + { + return; + } // WriteTrace("Begin Sending Alive Notifications For All Devices"); @@ -394,7 +439,10 @@ namespace Rssdp.Infrastructure foreach (var device in devices) { - if (IsDisposed) return; + if (IsDisposed) + { + return; + } SendAliveNotifications(device, true, CancellationToken.None); } @@ -547,7 +595,10 @@ namespace Rssdp.Infrastructure private void CommsServer_RequestReceived(object sender, RequestReceivedEventArgs e) { - if (this.IsDisposed) return; + if (this.IsDisposed) + { + return; + } if (string.Equals(e.Message.Method.Method, SsdpConstants.MSearchMethod, StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From 7f307f9082cb4be296e745c2c066334858f000af Mon Sep 17 00:00:00 2001 From: telans <telans@protonmail.com> Date: Sat, 20 Jun 2020 21:12:36 +1200 Subject: brace multiline if statements --- Emby.Dlna/DlnaManager.cs | 18 +++++ Emby.Dlna/PlayTo/Device.cs | 14 ++++ .../Library/Resolvers/Books/BookResolver.cs | 4 ++ .../Services/ResponseHelper.cs | 2 + .../Services/ServiceExec.cs | 4 ++ .../Services/ServicePath.cs | 2 + .../Sorting/DateCreatedComparer.cs | 4 ++ .../Sorting/RuntimeComparer.cs | 4 ++ .../Sorting/SortNameComparer.cs | 4 ++ MediaBrowser.Controller/Entities/BaseItem.cs | 2 + MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 3 + MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 58 +++++++++++++++ .../Dlna/MediaFormatProfileResolver.cs | 83 +++++++++++++++++++++- RSSDP/HttpParserBase.cs | 12 ++++ RSSDP/HttpRequestParser.cs | 4 ++ RSSDP/HttpResponseParser.cs | 4 ++ RSSDP/SsdpCommunicationsServer.cs | 4 ++ RSSDP/SsdpDevice.cs | 12 ++++ RSSDP/SsdpDeviceLocator.cs | 16 +++++ RSSDP/SsdpDevicePublisher.cs | 31 ++++++-- 20 files changed, 280 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index cbe4ea643..5911a73ef 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -140,55 +140,73 @@ namespace Emby.Dlna if (!string.IsNullOrEmpty(profileInfo.DeviceDescription)) { if (deviceInfo.DeviceDescription == null || !IsRegexMatch(deviceInfo.DeviceDescription, profileInfo.DeviceDescription)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.FriendlyName)) { if (deviceInfo.FriendlyName == null || !IsRegexMatch(deviceInfo.FriendlyName, profileInfo.FriendlyName)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.Manufacturer)) { if (deviceInfo.Manufacturer == null || !IsRegexMatch(deviceInfo.Manufacturer, profileInfo.Manufacturer)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.ManufacturerUrl)) { if (deviceInfo.ManufacturerUrl == null || !IsRegexMatch(deviceInfo.ManufacturerUrl, profileInfo.ManufacturerUrl)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.ModelDescription)) { if (deviceInfo.ModelDescription == null || !IsRegexMatch(deviceInfo.ModelDescription, profileInfo.ModelDescription)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.ModelName)) { if (deviceInfo.ModelName == null || !IsRegexMatch(deviceInfo.ModelName, profileInfo.ModelName)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.ModelNumber)) { if (deviceInfo.ModelNumber == null || !IsRegexMatch(deviceInfo.ModelNumber, profileInfo.ModelNumber)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.ModelUrl)) { if (deviceInfo.ModelUrl == null || !IsRegexMatch(deviceInfo.ModelUrl, profileInfo.ModelUrl)) + { return false; + } } if (!string.IsNullOrEmpty(profileInfo.SerialNumber)) { if (deviceInfo.SerialNumber == null || !IsRegexMatch(deviceInfo.SerialNumber, profileInfo.SerialNumber)) + { return false; + } } return true; diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index c86fc4f37..c5080b90f 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -208,7 +208,9 @@ namespace Emby.Dlna.PlayTo var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetMute"); if (command == null) + { return false; + } var service = GetServiceRenderingControl(); @@ -237,7 +239,9 @@ namespace Emby.Dlna.PlayTo var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume"); if (command == null) + { return; + } var service = GetServiceRenderingControl(); @@ -260,7 +264,9 @@ namespace Emby.Dlna.PlayTo var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Seek"); if (command == null) + { return; + } var service = GetAvTransportService(); @@ -285,7 +291,9 @@ namespace Emby.Dlna.PlayTo var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI"); if (command == null) + { return; + } var dictionary = new Dictionary<string, string> { @@ -452,7 +460,9 @@ namespace Emby.Dlna.PlayTo _connectFailureCount = 0; if (_disposed) + { return; + } // If we're not playing anything make sure we don't get data more often than neccessry to keep the Session alive if (transportState.Value == TRANSPORTSTATE.STOPPED) @@ -472,7 +482,9 @@ namespace Emby.Dlna.PlayTo catch (Exception ex) { if (_disposed) + { return; + } _logger.LogError(ex, "Error updating device info for {DeviceName}", Properties.Name); @@ -573,7 +585,9 @@ namespace Emby.Dlna.PlayTo cancellationToken: cancellationToken).ConfigureAwait(false); if (result == null || result.Document == null) + { return; + } var valueNode = result.Document.Descendants(uPnpNamespaces.RenderingControl + "GetMuteResponse") .Select(i => i.Element("CurrentMute")) diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 503de0b4e..86a5d8b7d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -19,7 +19,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books // Only process items that are in a collection folder containing books if (!string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) + { return null; + } if (args.IsDirectory) { @@ -55,7 +57,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books // Don't return a Book if there is more (or less) than one document in the directory if (bookFiles.Count != 1) + { return null; + } return new Book { diff --git a/Emby.Server.Implementations/Services/ResponseHelper.cs b/Emby.Server.Implementations/Services/ResponseHelper.cs index 3f1672e94..a329b531d 100644 --- a/Emby.Server.Implementations/Services/ResponseHelper.cs +++ b/Emby.Server.Implementations/Services/ResponseHelper.cs @@ -40,7 +40,9 @@ namespace Emby.Server.Implementations.Services if (httpResult != null) { if (httpResult.RequestContext == null) + { httpResult.RequestContext = request; + } response.StatusCode = httpResult.Status; } diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs index 18d7ab46e..cbc4b754d 100644 --- a/Emby.Server.Implementations/Services/ServiceExec.cs +++ b/Emby.Server.Implementations/Services/ServiceExec.cs @@ -42,11 +42,15 @@ namespace Emby.Server.Implementations.Services } if (mi.GetParameters().Length != 1) + { continue; + } var actionName = mi.Name; if (!AllVerbs.Contains(actionName, StringComparer.OrdinalIgnoreCase)) + { continue; + } list.Add(mi); } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index eb0744189..89538ae72 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -445,12 +445,14 @@ namespace Emby.Server.Implementations.Services && requestComponents.Length >= this.TotalComponentsCount - this.wildcardCount; if (!isValidWildCardPath) + { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "Path Mismatch: Request Path '{0}' has invalid number of components compared to: '{1}'", pathInfo, this.restPath)); + } } var requestKeyValuesMap = new Dictionary<string, string>(); diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index ea981e840..cbca300d2 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -19,10 +19,14 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } return DateTime.Compare(x.DateCreated, y.DateCreated); } diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index f165123ea..dde44333d 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -19,10 +19,14 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); } diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index 93389fc3e..f745e193b 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -19,10 +19,14 @@ namespace Emby.Server.Implementations.Sorting public int Compare(BaseItem x, BaseItem y) { if (x == null) + { throw new ArgumentNullException(nameof(x)); + } if (y == null) + { throw new ArgumentNullException(nameof(y)); + } return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 2ad1c717c..8e0e63ff0 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2951,7 +2951,9 @@ namespace MediaBrowser.Controller.Entities public IEnumerable<BaseItem> GetTrailers() { if (this is IHasTrailers) + { return ((IHasTrailers)this).LocalTrailerIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName); + } else return Array.Empty<BaseItem>(); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index a8d383a2a..728efa788 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -58,7 +58,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles var endTime = time[1]; var idx = endTime.IndexOf(" ", StringComparison.Ordinal); if (idx > 0) + { endTime = endTime.Substring(0, idx); + } + subEvent.EndPositionTicks = GetTicks(endTime); var multiline = new List<string>(); while ((line = reader.ReadLine()) != null) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 9a8fcc431..630a3dce0 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -41,7 +41,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles lineNumber++; if (!eventsStarted) + { header.AppendLine(line); + } if (line.Trim().ToLowerInvariant() == "[events]") { @@ -62,17 +64,29 @@ namespace MediaBrowser.MediaEncoding.Subtitles for (int i = 0; i < format.Length; i++) { if (format[i].Trim().ToLowerInvariant() == "layer") + { indexLayer = i; + } else if (format[i].Trim().ToLowerInvariant() == "start") + { indexStart = i; + } else if (format[i].Trim().ToLowerInvariant() == "end") + { indexEnd = i; + } else if (format[i].Trim().ToLowerInvariant() == "text") + { indexText = i; + } else if (format[i].Trim().ToLowerInvariant() == "effect") + { indexEffect = i; + } else if (format[i].Trim().ToLowerInvariant() == "style") + { indexStyle = i; + } } } } @@ -89,28 +103,48 @@ namespace MediaBrowser.MediaEncoding.Subtitles string[] splittedLine; if (s.StartsWith("dialogue:")) + { splittedLine = line.Substring(10).Split(','); + } else + { splittedLine = line.Split(','); + } for (int i = 0; i < splittedLine.Length; i++) { if (i == indexStart) + { start = splittedLine[i].Trim(); + } else if (i == indexEnd) + { end = splittedLine[i].Trim(); + } else if (i == indexLayer) + { layer = splittedLine[i]; + } else if (i == indexEffect) + { effect = splittedLine[i]; + } else if (i == indexText) + { text = splittedLine[i]; + } else if (i == indexStyle) + { style = splittedLine[i]; + } else if (i == indexName) + { name = splittedLine[i]; + } else if (i > indexText) + { text += "," + splittedLine[i]; + } } try @@ -169,13 +203,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles CheckAndAddSubTags(ref fontName, ref extraTags, out italic); text = text.Remove(start, end - start + 1); if (italic) + { text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + "><i>"); + } else text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">"); int indexOfEndTag = text.IndexOf("{\\fn}", start); if (indexOfEndTag > 0) + { text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>"); + } else text += "</font>"; } @@ -194,13 +232,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles { text = text.Remove(start, end - start + 1); if (italic) + { text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + "><i>"); + } else text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">"); int indexOfEndTag = text.IndexOf("{\\fs}", start); if (indexOfEndTag > 0) + { text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>"); + } else text += "</font>"; } @@ -226,12 +268,16 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Remove(start, end - start + 1); if (italic) + { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); + } else text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); int indexOfEndTag = text.IndexOf("{\\c}", start); if (indexOfEndTag > 0) + { text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>"); + } else text += "</font>"; } @@ -256,7 +302,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Remove(start, end - start + 1); if (italic) + { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); + } else text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); text += "</font>"; @@ -268,19 +316,25 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Replace(@"{\i0}", "</i>"); text = text.Replace(@"{\i}", "</i>"); if (CountTagInText(text, "<i>") > CountTagInText(text, "</i>")) + { text += "</i>"; + } text = text.Replace(@"{\u1}", "<u>"); text = text.Replace(@"{\u0}", "</u>"); text = text.Replace(@"{\u}", "</u>"); if (CountTagInText(text, "<u>") > CountTagInText(text, "</u>")) + { text += "</u>"; + } text = text.Replace(@"{\b1}", "<b>"); text = text.Replace(@"{\b0}", "</b>"); text = text.Replace(@"{\b}", "</b>"); if (CountTagInText(text, "<b>") > CountTagInText(text, "</b>")) + { text += "</b>"; + } return text; } @@ -288,7 +342,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles private static bool IsInteger(string s) { if (int.TryParse(s, out var i)) + { return true; + } return false; } @@ -300,7 +356,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles { count++; if (index == text.Length) + { return count; + } index = text.IndexOf(tag, index + 1); } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 47cc89210..df10f8c53 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -32,18 +32,25 @@ namespace MediaBrowser.Model.Dlna } if (string.Equals(container, "avi", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.AVI }; + } if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.MATROSKA }; + } if (string.Equals(container, "mpeg2ps", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) - + { return new MediaFormatProfile[] { MediaFormatProfile.MPEG_PS_NTSC, MediaFormatProfile.MPEG_PS_PAL }; + } if (string.Equals(container, "mpeg1video", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.MPEG1 }; + } if (string.Equals(container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "mpegts", StringComparison.OrdinalIgnoreCase) || @@ -54,10 +61,14 @@ namespace MediaBrowser.Model.Dlna } if (string.Equals(container, "flv", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.FLV }; + } if (string.Equals(container, "wtv", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.WTV }; + } if (string.Equals(container, "3gp", StringComparison.OrdinalIgnoreCase)) { @@ -66,7 +77,9 @@ namespace MediaBrowser.Model.Dlna } if (string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.OGV }; + } return Array.Empty<MediaFormatProfile>(); } @@ -111,7 +124,9 @@ namespace MediaBrowser.Model.Dlna if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { MediaFormatProfile.AVC_TS_HD_50_LPCM_T }; + } if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase)) { @@ -134,14 +149,20 @@ namespace MediaBrowser.Model.Dlna } if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) }; + } if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) }; + } if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) }; + } } else if (string.Equals(videoCodec, "vc1", StringComparison.OrdinalIgnoreCase)) { @@ -165,13 +186,24 @@ namespace MediaBrowser.Model.Dlna else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; + } + if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; + } + if (string.Equals(audioCodec, "mp2", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; + } + if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) + { return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; + } } return new MediaFormatProfile[] { }; @@ -187,7 +219,9 @@ namespace MediaBrowser.Model.Dlna if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.AVC_MP4_LPCM; + } if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { @@ -204,12 +238,16 @@ namespace MediaBrowser.Model.Dlna if ((width.Value <= 720) && (height.Value <= 576)) { if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.AVC_MP4_MP_SD_AAC_MULT5; + } } else if ((width.Value <= 1280) && (height.Value <= 720)) { if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.AVC_MP4_MP_HD_720p_AAC; + } } else if ((width.Value <= 1920) && (height.Value <= 1080)) { @@ -226,7 +264,9 @@ namespace MediaBrowser.Model.Dlna if (width.HasValue && height.HasValue && width.Value <= 720 && height.Value <= 576) { if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.MPEG4_P2_MP4_ASP_AAC; + } if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase) || string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { return MediaFormatProfile.MPEG4_P2_MP4_NDSD; @@ -250,15 +290,22 @@ namespace MediaBrowser.Model.Dlna if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.AVC_3GPP_BL_QCIF15_AAC; + } } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.MPEG4_P2_3GPP_SP_L0B_AAC; + } + if (string.Equals(audioCodec, "amrnb", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.MPEG4_P2_3GPP_SP_L0B_AMR; + } } else if (string.Equals(videoCodec, "h263", StringComparison.OrdinalIgnoreCase) && string.Equals(audioCodec, "amrnb", StringComparison.OrdinalIgnoreCase)) { @@ -300,11 +347,19 @@ namespace MediaBrowser.Model.Dlna if (width.HasValue && height.HasValue) { if ((width.Value <= 720) && (height.Value <= 576)) + { return MediaFormatProfile.VC1_ASF_AP_L1_WMA; + } + if ((width.Value <= 1280) && (height.Value <= 720)) + { return MediaFormatProfile.VC1_ASF_AP_L2_WMA; + } + if ((width.Value <= 1920) && (height.Value <= 1080)) + { return MediaFormatProfile.VC1_ASF_AP_L3_WMA; + } } } else if (string.Equals(videoCodec, "mpeg2video", StringComparison.OrdinalIgnoreCase)) @@ -318,27 +373,41 @@ namespace MediaBrowser.Model.Dlna public MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels) { if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) + { return ResolveAudioASFFormat(bitrate); + } if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.MP3; + } if (string.Equals(container, "lpcm", StringComparison.OrdinalIgnoreCase)) + { return ResolveAudioLPCMFormat(frequency, channels); + } if (string.Equals(container, "mp4", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "aac", StringComparison.OrdinalIgnoreCase)) + { return ResolveAudioMP4Format(bitrate); + } if (string.Equals(container, "adts", StringComparison.OrdinalIgnoreCase)) + { return ResolveAudioADTSFormat(bitrate); + } if (string.Equals(container, "flac", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.FLAC; + } if (string.Equals(container, "oga", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.OGG; + } return null; } @@ -410,13 +479,19 @@ namespace MediaBrowser.Model.Dlna return ResolveImageJPGFormat(width, height); if (string.Equals(container, "png", StringComparison.OrdinalIgnoreCase)) + { return ResolveImagePNGFormat(width, height); + } if (string.Equals(container, "gif", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.GIF_LRG; + } if (string.Equals(container, "raw", StringComparison.OrdinalIgnoreCase)) + { return MediaFormatProfile.RAW; + } return null; } @@ -426,10 +501,14 @@ namespace MediaBrowser.Model.Dlna if (width.HasValue && height.HasValue) { if ((width.Value <= 160) && (height.Value <= 160)) + { return MediaFormatProfile.JPEG_TN; + } if ((width.Value <= 640) && (height.Value <= 480)) + { return MediaFormatProfile.JPEG_SM; + } if ((width.Value <= 1024) && (height.Value <= 768)) { @@ -447,7 +526,9 @@ namespace MediaBrowser.Model.Dlna if (width.HasValue && height.HasValue) { if ((width.Value <= 160) && (height.Value <= 160)) + { return MediaFormatProfile.PNG_TN; + } } return MediaFormatProfile.PNG_LRG; diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 058bfbf55..00c2b7b45 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -114,9 +114,13 @@ namespace Rssdp.Infrastructure var headersToAddTo = IsContentHeader(headerName) ? contentHeaders : headers; if (values.Count > 1) + { headersToAddTo.TryAddWithoutValidation(headerName, values); + } else + { headersToAddTo.TryAddWithoutValidation(headerName, values.First()); + } } private int ParseHeaders(System.Net.Http.Headers.HttpHeaders headers, System.Net.Http.Headers.HttpHeaders contentHeaders, string[] lines) @@ -160,7 +164,9 @@ namespace Rssdp.Infrastructure var indexOfSeparator = headerValue.IndexOfAny(SeparatorCharacters); if (indexOfSeparator <= 0) + { values.Add(headerValue); + } else { var segments = headerValue.Split(SeparatorCharacters); @@ -170,7 +176,9 @@ namespace Rssdp.Infrastructure { var segment = segments[segmentIndex]; if (segment.Trim().StartsWith("\"", StringComparison.OrdinalIgnoreCase)) + { segment = CombineQuotedSegments(segments, ref segmentIndex, segment); + } values.Add(segment); } @@ -199,12 +207,16 @@ namespace Rssdp.Infrastructure } if (index + 1 < segments.Length) + { trimmedSegment += "," + segments[index + 1].TrimEnd(); + } } segmentIndex = segments.Length; if (trimmedSegment.StartsWith("\"", StringComparison.OrdinalIgnoreCase) && trimmedSegment.EndsWith("\"", StringComparison.OrdinalIgnoreCase)) + { return trimmedSegment.Substring(1, trimmedSegment.Length - 2); + } else return trimmedSegment; } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index 6b27fc4df..7fa42f466 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -34,7 +34,9 @@ namespace Rssdp.Infrastructure finally { if (retVal != null) + { retVal.Dispose(); + } } } @@ -64,7 +66,9 @@ namespace Rssdp.Infrastructure message.Method = new HttpMethod(parts[0].Trim()); Uri requestUri; if (Uri.TryCreate(parts[1].Trim(), UriKind.RelativeOrAbsolute, out requestUri)) + { message.RequestUri = requestUri; + } else System.Diagnostics.Debug.WriteLine(parts[1]); diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index 0337b3e36..0dd4bb45a 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -34,7 +34,9 @@ namespace Rssdp.Infrastructure catch { if (retVal != null) + { retVal.Dispose(); + } throw; } @@ -77,7 +79,9 @@ namespace Rssdp.Infrastructure int statusCode = -1; if (!Int32.TryParse(parts[1].Trim(), out statusCode)) + { throw new ArgumentException("data status line is invalid. Status code is not a valid integer.", nameof(data)); + } message.StatusCode = (HttpStatusCode)statusCode; diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 31ca90424..e4c4a2017 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -480,17 +480,21 @@ namespace Rssdp.Infrastructure var handlers = this.RequestReceived; if (handlers != null) + { handlers(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnLocalIpAddress)); + } } private void OnResponseReceived(HttpResponseMessage data, IPEndPoint endPoint, IPAddress localIpAddress) { var handlers = this.ResponseReceived; if (handlers != null) + { handlers(this, new ResponseReceivedEventArgs(data, endPoint) { LocalIpAddress = localIpAddress }); + } } } } diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 42f95862c..7030c6ec1 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -55,7 +55,9 @@ namespace Rssdp var rootDevice = device as SsdpRootDevice; if (rootDevice == null) + { rootDevice = ((SsdpEmbeddedDevice)device).RootDevice; + } return rootDevice; } @@ -163,7 +165,9 @@ namespace Rssdp get { if (String.IsNullOrEmpty(_Udn) && !String.IsNullOrEmpty(this.Uuid)) + { return "uuid:" + this.Uuid; + } else return _Udn; } @@ -283,7 +287,9 @@ namespace Rssdp } if (wasAdded) + { OnDeviceAdded(device); + } } /// <summary> @@ -314,7 +320,9 @@ namespace Rssdp } if (wasRemoved) + { OnDeviceRemoved(device); + } } /// <summary> @@ -327,7 +335,9 @@ namespace Rssdp { var handlers = this.DeviceAdded; if (handlers != null) + { handlers(this, new DeviceEventArgs(device)); + } } /// <summary> @@ -340,7 +350,9 @@ namespace Rssdp { var handlers = this.DeviceRemoved; if (handlers != null) + { handlers(this, new DeviceEventArgs(device)); + } } } } diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index a774ee23c..9a31db7a2 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -217,10 +217,12 @@ namespace Rssdp.Infrastructure var handlers = this.DeviceAvailable; if (handlers != null) + { handlers(this, new DeviceAvailableEventArgs(device, isNewDevice) { LocalIpAddress = localIpAddress }); + } } /// <summary> @@ -426,7 +428,9 @@ namespace Rssdp.Infrastructure }; if (NotificationTypeMatchesFilter(deadDevice)) + { OnDeviceUnavailable(deadDevice, false); + } } } } @@ -439,7 +443,9 @@ namespace Rssdp.Infrastructure { message.Headers.TryGetValues(headerName, out values); if (values != null) + { retVal = values.FirstOrDefault(); + } } return retVal; @@ -453,7 +459,9 @@ namespace Rssdp.Infrastructure { message.Headers.TryGetValues(headerName, out values); if (values != null) + { retVal = values.FirstOrDefault(); + } } return retVal; @@ -467,7 +475,9 @@ namespace Rssdp.Infrastructure { request.Headers.TryGetValues(headerName, out values); if (values != null) + { value = values.FirstOrDefault(); + } } Uri retVal; @@ -483,7 +493,9 @@ namespace Rssdp.Infrastructure { response.Headers.TryGetValues(headerName, out values); if (values != null) + { value = values.FirstOrDefault(); + } } Uri retVal; @@ -560,7 +572,9 @@ namespace Rssdp.Infrastructure foreach (var removedDevice in existingDevices) { if (NotificationTypeMatchesFilter(removedDevice)) + { OnDeviceUnavailable(removedDevice, expired); + } } return true; @@ -572,7 +586,9 @@ namespace Rssdp.Infrastructure private TimeSpan SearchTimeToMXValue(TimeSpan searchWaitTime) { if (searchWaitTime.TotalSeconds < 2 || searchWaitTime == TimeSpan.Zero) + { return OneSecond; + } else return searchWaitTime.Subtract(OneSecond); } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 1b64d230d..7c6e87201 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -215,7 +215,9 @@ namespace Rssdp.Infrastructure if (commsServer != null) { if (!commsServer.IsShared) + { commsServer.Dispose(); + } } _RecentSearchRequests = null; @@ -328,7 +330,9 @@ namespace Rssdp.Infrastructure { SendSearchResponse(SsdpConstants.UpnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken); if (this.SupportPnpRootDevice) + { SendSearchResponse(SsdpConstants.PnpDeviceTypeRootDevice, device, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), endPoint, receivedOnlocalIpAddress, cancellationToken); + } } SendSearchResponse(device.Udn, device, device.Udn, endPoint, receivedOnlocalIpAddress, cancellationToken); @@ -394,7 +398,9 @@ namespace Rssdp.Infrastructure { var lastRequest = _RecentSearchRequests[newRequest.Key]; if (lastRequest.IsOld()) + { _RecentSearchRequests[newRequest.Key] = newRequest; + } else isDuplicateRequest = true; } @@ -402,7 +408,9 @@ namespace Rssdp.Infrastructure { _RecentSearchRequests.Add(newRequest.Key, newRequest); if (_RecentSearchRequests.Count > 10) + { CleanUpRecentSearchRequestsAsync(); + } } } @@ -462,7 +470,9 @@ namespace Rssdp.Infrastructure { SendAliveNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken); if (this.SupportPnpRootDevice) + { SendAliveNotification(device, SsdpConstants.PnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.PnpDeviceTypeRootDevice), cancellationToken); + } } SendAliveNotification(device, device.Udn, device.Udn, cancellationToken); @@ -506,7 +516,9 @@ namespace Rssdp.Infrastructure { tasks.Add(SendByeByeNotification(device, SsdpConstants.UpnpDeviceTypeRootDevice, GetUsn(device.Udn, SsdpConstants.UpnpDeviceTypeRootDevice), cancellationToken)); if (this.SupportPnpRootDevice) + { tasks.Add(SendByeByeNotification(device, "pnp:rootdevice", GetUsn(device.Udn, "pnp:rootdevice"), cancellationToken)); + } } tasks.Add(SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken)); @@ -547,20 +559,27 @@ namespace Rssdp.Infrastructure var timer = _RebroadcastAliveNotificationsTimer; _RebroadcastAliveNotificationsTimer = null; if (timer != null) + { timer.Dispose(); + } } private TimeSpan GetMinimumNonZeroCacheLifetime() { - var nonzeroCacheLifetimesQuery = (from device - in _Devices - where device.CacheLifetime != TimeSpan.Zero - select device.CacheLifetime).ToList(); + var nonzeroCacheLifetimesQuery = ( + from device + in _Devices + where device.CacheLifetime != TimeSpan.Zero + select device.CacheLifetime).ToList(); if (nonzeroCacheLifetimesQuery.Any()) + { return nonzeroCacheLifetimesQuery.Min(); + } else + { return TimeSpan.Zero; + } } private string GetFirstHeaderValue(System.Net.Http.Headers.HttpRequestHeaders httpRequestHeaders, string headerName) @@ -568,7 +587,9 @@ namespace Rssdp.Infrastructure string retVal = null; IEnumerable<String> values = null; if (httpRequestHeaders.TryGetValues(headerName, out values) && values != null) + { retVal = values.FirstOrDefault(); + } return retVal; } @@ -588,7 +609,9 @@ namespace Rssdp.Infrastructure { var rootDevice = device as SsdpRootDevice; if (rootDevice != null) + { WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid + " - " + rootDevice.Location); + } else WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid); } -- cgit v1.2.3 From 5bb639a59a9ab4c42804e364c94b34aaca594796 Mon Sep 17 00:00:00 2001 From: telans <telans@protonmail.com> Date: Sat, 20 Jun 2020 21:13:48 +1200 Subject: newlines after braces --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 11 +++++++++++ MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 2 ++ MediaBrowser.Model/Configuration/EncodingOptions.cs | 3 +++ MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs | 2 ++ RSSDP/DisposableManagedObjectBase.cs | 1 + 5 files changed, 19 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8da714858..d3fb6a46d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2603,6 +2603,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-c:v vp8_qsv"; } + break; case "vp9": if (_mediaEncoder.SupportsDecoder("vp9_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) @@ -2610,6 +2611,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_qsv"; } + break; } } @@ -2667,6 +2669,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-c:v vp8_cuvid"; } + break; case "vp9": if (_mediaEncoder.SupportsDecoder("vp9_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase)) @@ -2674,6 +2677,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_cuvid"; } + break; } } @@ -2818,6 +2822,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return "-c:v h264_opencl"; } + break; case "hevc": case "h265": @@ -2826,30 +2831,35 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_opencl"; } + break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_opencl"; } + break; case "mpeg4": if (_mediaEncoder.SupportsDecoder("mpeg4_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg4_opencl"; } + break; case "vc1": if (_mediaEncoder.SupportsDecoder("vc1_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vc1_opencl"; } + break; case "vp8": if (_mediaEncoder.SupportsDecoder("vp8_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vp8_opencl"; } + break; case "vp9": if (_mediaEncoder.SupportsDecoder("vp9_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) @@ -2857,6 +2867,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (isColorDepth10 && !encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_opencl"; } + break; } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 630a3dce0..52b486dc7 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -345,6 +345,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { return true; } + return false; } @@ -359,6 +360,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { return count; } + index = text.IndexOf(tag, index + 1); } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index a790ec42a..9a30f7e9f 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -36,8 +36,11 @@ namespace MediaBrowser.Model.Configuration public string EncoderPreset { get; set; } public string DeinterlaceMethod { get; set; } + public bool EnableDecodingColorDepth10Hevc { get; set; } + public bool EnableDecodingColorDepth10Vp9 { get; set; } + public bool EnableHardwareEncoding { get; set; } public bool EnableSubtitleExtraction { get; set; } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index df10f8c53..398c5db8c 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -222,6 +222,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.AVC_MP4_LPCM; } + if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { @@ -267,6 +268,7 @@ namespace MediaBrowser.Model.Dlna { return MediaFormatProfile.MPEG4_P2_MP4_ASP_AAC; } + if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase) || string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { return MediaFormatProfile.MPEG4_P2_MP4_NDSD; diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 628572b17..66a0c5ec4 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -38,6 +38,7 @@ namespace Rssdp.Infrastructure get; private set; } + public string BuildMessage(string header, Dictionary<string, string> values) { var builder = new StringBuilder(); -- cgit v1.2.3 From 6556bec646a28d08267f30640125865cf42240d0 Mon Sep 17 00:00:00 2001 From: telans <telans@protonmail.com> Date: Sat, 20 Jun 2020 21:19:16 +1200 Subject: brace multiline if statements (cont.) --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 ++ .../Probing/ProbeResultNormalizer.cs | 4 ++++ MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 14 ++++++++++++++ RSSDP/HttpParserBase.cs | 6 ++++++ RSSDP/HttpRequestParser.cs | 2 ++ RSSDP/SsdpDevice.cs | 2 ++ RSSDP/SsdpDeviceLocator.cs | 2 ++ RSSDP/SsdpDevicePublisher.cs | 4 ++++ 8 files changed, 36 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 8e0e63ff0..bf87c0336 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2955,7 +2955,9 @@ namespace MediaBrowser.Controller.Entities return ((IHasTrailers)this).LocalTrailerIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName); } else + { return Array.Empty<BaseItem>(); + } } public virtual bool IsHD => Height >= 720; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 190abaa05..3f21c2bd4 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1384,14 +1384,18 @@ namespace MediaBrowser.MediaEncoding.Probing description = string.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it } else + { throw new Exception(); // Switch to default parsing + } } catch // Default parsing { if (subtitle.Contains(".")) // skip the comment, keep the subtitle description = string.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first else + { description = subtitle.Trim(); // Clean up whitespaces and save it + } } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 52b486dc7..77033c6b4 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -207,7 +207,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + "><i>"); } else + { text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">"); + } int indexOfEndTag = text.IndexOf("{\\fn}", start); if (indexOfEndTag > 0) @@ -215,7 +217,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>"); } else + { text += "</font>"; + } } } @@ -236,7 +240,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + "><i>"); } else + { text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">"); + } int indexOfEndTag = text.IndexOf("{\\fs}", start); if (indexOfEndTag > 0) @@ -244,7 +250,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>"); } else + { text += "</font>"; + } } } } @@ -272,14 +280,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); } else + { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); + } int indexOfEndTag = text.IndexOf("{\\c}", start); if (indexOfEndTag > 0) { text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>"); } else + { text += "</font>"; + } } } @@ -306,7 +318,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); } else + { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); + } text += "</font>"; } } diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 00c2b7b45..a40612bc2 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -140,7 +140,9 @@ namespace Rssdp.Infrastructure lineIndex++; } else + { break; + } } ParseHeader(line, headers, contentHeaders); @@ -184,7 +186,9 @@ namespace Rssdp.Infrastructure } } else + { values.AddRange(segments); + } } return values; @@ -218,7 +222,9 @@ namespace Rssdp.Infrastructure return trimmedSegment.Substring(1, trimmedSegment.Length - 2); } else + { return trimmedSegment; + } } } } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index 7fa42f466..4114195a6 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -70,7 +70,9 @@ namespace Rssdp.Infrastructure message.RequestUri = requestUri; } else + { System.Diagnostics.Debug.WriteLine(parts[1]); + } if (parts.Length >= 3) { diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 7030c6ec1..4005d836d 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -169,7 +169,9 @@ namespace Rssdp return "uuid:" + this.Uuid; } else + { return _Udn; + } } set diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs index 9a31db7a2..38562ce49 100644 --- a/RSSDP/SsdpDeviceLocator.cs +++ b/RSSDP/SsdpDeviceLocator.cs @@ -590,7 +590,9 @@ namespace Rssdp.Infrastructure return OneSecond; } else + { return searchWaitTime.Subtract(OneSecond); + } } private DiscoveredSsdpDevice FindExistingDeviceNotification(IEnumerable<DiscoveredSsdpDevice> devices, string notificationType, string usn) diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 7c6e87201..1a8577d8d 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -402,7 +402,9 @@ namespace Rssdp.Infrastructure _RecentSearchRequests[newRequest.Key] = newRequest; } else + { isDuplicateRequest = true; + } } else { @@ -613,7 +615,9 @@ namespace Rssdp.Infrastructure WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid + " - " + rootDevice.Location); } else + { WriteTrace(text + " " + device.DeviceType + " - " + device.Uuid); + } } private void CommsServer_RequestReceived(object sender, RequestReceivedEventArgs e) -- cgit v1.2.3 From 438977350892179d5dc2259316b0fe27ceb1e5da Mon Sep 17 00:00:00 2001 From: Neil Burrows <neil.burrows@nvable.com> Date: Mon, 29 Jun 2020 17:08:20 +0100 Subject: Respect FFMpeg path passed via Environment Variable --- Emby.Server.Implementations/ApplicationHost.cs | 3 +-- Jellyfin.Server/StartupOptions.cs | 5 +++++ MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs | 5 +++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 7 ++++--- 4 files changed, 15 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 14267b561..8d213ac57 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -568,8 +568,7 @@ namespace Emby.Server.Implementations // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation serviceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>)); - serviceCollection.AddSingleton<IMediaEncoder>(provider => - ActivatorUtilities.CreateInstance<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(provider, _startupOptions.FFmpegPath ?? string.Empty)); + serviceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(); // TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required serviceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>)); diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index a26114e77..41a1430d2 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -101,6 +101,11 @@ namespace Jellyfin.Server config.Add(UdpServer.AddressOverrideConfigKey, PublishedServerUrl.ToString()); } + if (FFmpegPath != null) + { + config.Add(ConfigurationExtensions.FfmpegPathKey, FFmpegPath); + } + return config; } } diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index c0043c0ef..c2932cc4c 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -23,6 +23,11 @@ namespace MediaBrowser.Controller.Extensions /// </summary> public const string FfmpegAnalyzeDurationKey = "FFmpeg:analyzeduration"; + /// <summary> + /// The key for the FFmpeg path option. + /// </summary> + public const string FfmpegPathKey = "ffmpeg"; + /// <summary> /// The key for a setting that indicates whether playlists should allow duplicate entries. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9397a347f..af99f2521 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -21,6 +21,7 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; using System.Diagnostics; +using Microsoft.Extensions.Configuration; namespace MediaBrowser.MediaEncoding.Encoder { @@ -46,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); - private string _ffmpegPath; + private string _ffmpegPath = string.Empty; private string _ffprobePath; public MediaEncoder( @@ -55,14 +56,14 @@ namespace MediaBrowser.MediaEncoding.Encoder IFileSystem fileSystem, ILocalizationManager localization, Lazy<EncodingHelper> encodingHelperFactory, - string startupOptionsFFmpegPath) + IConfiguration config) { _logger = logger; _configurationManager = configurationManager; _fileSystem = fileSystem; _localization = localization; _encodingHelperFactory = encodingHelperFactory; - _startupOptionFFmpegPath = startupOptionsFFmpegPath; + _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? ""; } private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; -- cgit v1.2.3 From 6b532b3da56a3f7fa0ef920a1f14ba8db70bcb35 Mon Sep 17 00:00:00 2001 From: Neil Burrows <neil@pawprint.co.uk> Date: Mon, 29 Jun 2020 20:52:20 +0100 Subject: User string.Empty instead of "" Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index af99f2521..62fdbc618 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _fileSystem = fileSystem; _localization = localization; _encodingHelperFactory = encodingHelperFactory; - _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? ""; + _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; } private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; -- cgit v1.2.3 From f5c53528618f2cd644f0d787c1e367f9886ff79a Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sat, 4 Jul 2020 19:14:49 +0800 Subject: add FFmpeg 4.3 detection and tests --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 1 + tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs | 2 ++ .../EncoderValidatorTestsData.cs | 12 ++++++++++++ 3 files changed, 15 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 4250edfb7..0fd0239b4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -90,6 +90,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // $ ffmpeg -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' private static readonly IReadOnlyDictionary<string, Version> _ffmpegVersionMap = new Dictionary<string, Version> { + { "libavutil=56.51,libavcodec=58.91,libavformat=58.45,libavdevice=58.10,libavfilter=7.85,libswscale=5.7,libswresample=3.7,libpostproc=55.7,", new Version(4, 3) }, { "libavutil=56.31,libavcodec=58.54,libavformat=58.29,libavdevice=58.8,libavfilter=7.57,libswscale=5.5,libswresample=3.5,libpostproc=55.5,", new Version(4, 2) }, { "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3,", new Version(4, 1) }, { "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1,", new Version(4, 0) }, diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index af29fec87..9eb601edf 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -17,6 +17,7 @@ namespace Jellyfin.MediaEncoding.Tests } [Theory] + [InlineData(EncoderValidatorTestsData.FFmpegV43Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV421Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV414Output, true)] @@ -32,6 +33,7 @@ namespace Jellyfin.MediaEncoding.Tests { public IEnumerator<object?[]> GetEnumerator() { + yield return new object?[] { EncoderValidatorTestsData.FFmpegV43Output, new Version(4, 3) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV421Output, new Version(4, 2, 1) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4) }; diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs index c46c9578b..f5ff3d723 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs @@ -2,6 +2,18 @@ namespace Jellyfin.MediaEncoding.Tests { internal static class EncoderValidatorTestsData { + public const string FFmpegV43Output = @"ffmpeg version 4.3 Copyright (c) 2000-2020 the FFmpeg developers +built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) +configuration: --prefix=/usr/lib/jellyfin-ffmpeg --target-os=linux --disable-doc --disable-ffplay --disable-shared --disable-libxcb --disable-vdpau --disable-sdl2 --disable-xlib --enable-gpl --enable-version3 --enable-static --enable-libfontconfig --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libwebp --enable-libx264 --enable-libx265 --enable-libzvbi --arch=amd64 --enable-amf --enable-nvenc --enable-nvdec --enable-vaapi --enable-opencl +libavutil 56. 51.100 / 56. 51.100 +libavcodec 58. 91.100 / 58. 91.100 +libavformat 58. 45.100 / 58. 45.100 +libavdevice 58. 10.100 / 58. 10.100 +libavfilter 7. 85.100 / 7. 85.100 +libswscale 5. 7.100 / 5. 7.100 +libswresample 3. 7.100 / 3. 7.100 +libpostproc 55. 7.100 / 55. 7.100"; + public const string FFmpegV421Output = @"ffmpeg version 4.2.1 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.1.1 (GCC) 20190807 configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt -- cgit v1.2.3 From 6d1b00da648e01a15c0c0384c79d37c824358769 Mon Sep 17 00:00:00 2001 From: Patrick Barron <barronpm@gmail.com> Date: Sat, 4 Jul 2020 11:54:25 -0400 Subject: Use Array.Empty --- Emby.Dlna/Profiles/DefaultProfile.cs | 2 +- Emby.Dlna/Profiles/DenonAvrProfile.cs | 2 +- Emby.Dlna/Profiles/DirectTvProfile.cs | 2 +- Emby.Dlna/Profiles/Foobar2000Profile.cs | 2 +- Emby.Dlna/Profiles/MarantzProfile.cs | 2 +- Emby.Dlna/Profiles/MediaMonkeyProfile.cs | 3 ++- Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs | 3 ++- Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs | 3 ++- Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs | 3 ++- Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs | 3 ++- MediaBrowser.Api/FilterService.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 2 +- MediaBrowser.Controller/Library/TVUtils.cs | 2 +- MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs | 2 +- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 4 ++-- MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs | 2 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 12 ++++++------ MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs | 3 ++- MediaBrowser.Providers/Manager/MetadataService.cs | 4 ++-- 20 files changed, 33 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs index 2347ebd0d..90a23a4a2 100644 --- a/Emby.Dlna/Profiles/DefaultProfile.cs +++ b/Emby.Dlna/Profiles/DefaultProfile.cs @@ -164,7 +164,7 @@ namespace Emby.Dlna.Profiles public void AddXmlRootAttribute(string name, string value) { - var atts = XmlRootAttributes ?? new XmlAttribute[] { }; + var atts = XmlRootAttributes ?? System.Array.Empty<XmlAttribute>(); var list = atts.ToList(); list.Add(new XmlAttribute diff --git a/Emby.Dlna/Profiles/DenonAvrProfile.cs b/Emby.Dlna/Profiles/DenonAvrProfile.cs index 73a87c499..a5ba0f36c 100644 --- a/Emby.Dlna/Profiles/DenonAvrProfile.cs +++ b/Emby.Dlna/Profiles/DenonAvrProfile.cs @@ -28,7 +28,7 @@ namespace Emby.Dlna.Profiles }, }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = System.Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/DirectTvProfile.cs b/Emby.Dlna/Profiles/DirectTvProfile.cs index 5ca388167..f6f98b07d 100644 --- a/Emby.Dlna/Profiles/DirectTvProfile.cs +++ b/Emby.Dlna/Profiles/DirectTvProfile.cs @@ -123,7 +123,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = System.Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/Foobar2000Profile.cs b/Emby.Dlna/Profiles/Foobar2000Profile.cs index ea3de686a..68e959770 100644 --- a/Emby.Dlna/Profiles/Foobar2000Profile.cs +++ b/Emby.Dlna/Profiles/Foobar2000Profile.cs @@ -72,7 +72,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = System.Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/MarantzProfile.cs b/Emby.Dlna/Profiles/MarantzProfile.cs index 6cfcc3b82..24078ab29 100644 --- a/Emby.Dlna/Profiles/MarantzProfile.cs +++ b/Emby.Dlna/Profiles/MarantzProfile.cs @@ -37,7 +37,7 @@ namespace Emby.Dlna.Profiles }, }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = System.Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/MediaMonkeyProfile.cs b/Emby.Dlna/Profiles/MediaMonkeyProfile.cs index 7161af738..28d639b6d 100644 --- a/Emby.Dlna/Profiles/MediaMonkeyProfile.cs +++ b/Emby.Dlna/Profiles/MediaMonkeyProfile.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Dlna; namespace Emby.Dlna.Profiles @@ -37,7 +38,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs index 42b066d52..238fe9f6b 100644 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs +++ b/Emby.Dlna/Profiles/SonyBlurayPlayer2013.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Dlna; namespace Emby.Dlna.Profiles @@ -223,7 +224,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs index fbdf2c18e..812a48151 100644 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs +++ b/Emby.Dlna/Profiles/SonyBlurayPlayer2014.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Dlna; namespace Emby.Dlna.Profiles @@ -223,7 +224,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs index ce32179a1..6bfff322e 100644 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs +++ b/Emby.Dlna/Profiles/SonyBlurayPlayer2015.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Dlna; namespace Emby.Dlna.Profiles @@ -211,7 +212,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = Array.Empty<ResponseProfile>(); } } } diff --git a/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs b/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs index aa1721d39..ec2529574 100644 --- a/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs +++ b/Emby.Dlna/Profiles/SonyBlurayPlayer2016.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Dlna; namespace Emby.Dlna.Profiles @@ -211,7 +212,7 @@ namespace Emby.Dlna.Profiles } }; - ResponseProfiles = new ResponseProfile[] { }; + ResponseProfiles = Array.Empty<ResponseProfile>(); } } } diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs index 1b736c77d..dcfdcbfed 100644 --- a/MediaBrowser.Api/FilterService.cs +++ b/MediaBrowser.Api/FilterService.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Api IncludeItemTypes = request.GetIncludeItemTypes(), DtoOptions = new Controller.Dto.DtoOptions { - Fields = new ItemFields[] { }, + Fields = Array.Empty<ItemFields>(), EnableImages = false, EnableUserData = false }, diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 25933bc90..90f62e153 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -613,7 +613,7 @@ namespace MediaBrowser.Controller.Entities { if (!IsFileProtocol) { - return new string[] { }; + return Array.Empty<string>(); } return new[] { Path }; diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 70c48b6f1..c131c5430 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -198,7 +198,7 @@ namespace MediaBrowser.Controller.Entities.Movies public Guid[] GetLibraryFolderIds() { - var expandedFolders = new List<Guid>() { }; + var expandedFolders = new List<Guid>(); return FlattenItems(this, expandedFolders) .SelectMany(i => LibraryManager.GetCollectionFolders(i)) diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index fc9b3f1c6..a3aa6019e 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Library }; } - return new DayOfWeek[] { }; + return Array.Empty<DayOfWeek>(); } return null; diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index e6359f4fb..ccfae2fa5 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo var outputStream = new BlurayDiscInfo { - MediaStreams = new MediaStream[] { } + MediaStreams = Array.Empty<MediaStream>() }; if (playlist == null) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 3f21c2bd4..c85d963ed 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1008,7 +1008,7 @@ namespace MediaBrowser.MediaEncoding.Probing var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); if (string.IsNullOrWhiteSpace(artist)) { - audio.Artists = new string[] { }; + audio.Artists = Array.Empty<string>(); } else { @@ -1031,7 +1031,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (string.IsNullOrWhiteSpace(albumArtist)) { - audio.AlbumArtists = new string[] { }; + audio.AlbumArtists = Array.Empty<string>(); } else { diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 398c5db8c..bdc5f8bb7 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -206,7 +206,7 @@ namespace MediaBrowser.Model.Dlna } } - return new MediaFormatProfile[] { }; + return Array.Empty<MediaFormatProfile>(); } private MediaFormatProfile ValueOf(string value) diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index b89e9ce90..8d7554e88 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -813,18 +813,18 @@ namespace MediaBrowser.Model.Dlna { var stream = TargetAudioStream; - string inputCodec = stream == null ? null : stream.Codec; + string inputCodec = stream?.Codec; if (IsDirectStream) { - return string.IsNullOrEmpty(inputCodec) ? new string[] { } : new[] { inputCodec }; + return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; } foreach (string codec in AudioCodecs) { if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - return string.IsNullOrEmpty(codec) ? new string[] { } : new[] { codec }; + return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; } } @@ -838,18 +838,18 @@ namespace MediaBrowser.Model.Dlna { var stream = TargetVideoStream; - string inputCodec = stream == null ? null : stream.Codec; + string inputCodec = stream?.Codec; if (IsDirectStream) { - return string.IsNullOrEmpty(inputCodec) ? new string[] { } : new[] { inputCodec }; + return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; } foreach (string codec in VideoCodecs) { if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - return string.IsNullOrEmpty(codec) ? new string[] { } : new[] { codec }; + return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; } } diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs index 12d537492..2ef6f7c60 100644 --- a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs +++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs @@ -1,6 +1,7 @@ #nullable disable #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Entities; namespace MediaBrowser.Model.Querying @@ -54,7 +55,7 @@ namespace MediaBrowser.Model.Querying public UpcomingEpisodesQuery() { - EnableImageTypes = new ImageType[] { }; + EnableImageTypes = Array.Empty<ImageType>(); } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index ecfa3d46d..3b0c7b56c 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -723,7 +723,7 @@ namespace MediaBrowser.Providers.Manager userDataList.AddRange(localItem.UserDataList); } - MergeData(localItem, temp, new MetadataField[] { }, !options.ReplaceAllMetadata, true); + MergeData(localItem, temp, Array.Empty<MetadataField>(), !options.ReplaceAllMetadata, true); refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport; // Only one local provider allowed per item @@ -849,7 +849,7 @@ namespace MediaBrowser.Providers.Manager { result.Provider = provider.Name; - MergeData(result, temp, new MetadataField[] { }, false, false); + MergeData(result, temp, Array.Empty<MetadataField>(), false, false); MergeNewData(temp.Item, id); refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload; -- cgit v1.2.3 From 29c4220227a5c31d0a34df4e2808dff88045db41 Mon Sep 17 00:00:00 2001 From: Sacha Korban <sachakorban@gmail.com> Date: Tue, 7 Jul 2020 19:50:12 +1000 Subject: Fix support for mixed-protocol external subtitles --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f1aa8ea5f..a971115c9 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -172,7 +172,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles inputFiles = new[] { mediaSource.Path }; } - var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); + var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, _mediaSourceManager.GetPathProtocol(subtitleStream.Path), subtitleStream, cancellationToken).ConfigureAwait(false); var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From 6e069f925b80bd134283dfa8f20399bad43865df Mon Sep 17 00:00:00 2001 From: Khinenw <deu07115@gmail.com> Date: Wed, 15 Apr 2020 17:30:23 +0000 Subject: Fix SAMI UTF-16 Encoding Bug --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f1aa8ea5f..fac9e0a81 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -426,7 +426,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles // 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 ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) && (encodingParam == "UTF-16BE" || encodingParam == "UTF-16LE")) + if ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) && + (encodingParam.Equals("UTF-16BE", StringComparison.OrdinalIgnoreCase) || + encodingParam.Equals("UTF-16LE", StringComparison.OrdinalIgnoreCase))) { encodingParam = ""; } -- cgit v1.2.3 From e98351b9128670abf12976af735cfb40d40be36d Mon Sep 17 00:00:00 2001 From: Bond_009 <Bond.009@outlook.com> Date: Mon, 20 Jul 2020 14:14:15 +0200 Subject: Replace \d with [0-9] in ffmpeg detection and scan code --- Emby.Naming/Common/NamingOptions.cs | 60 +++++++++++----------- .../Encoder/EncoderValidator.cs | 4 +- 2 files changed, 32 insertions(+), 32 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 1b343790e..d1e17f416 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -136,8 +136,8 @@ namespace Emby.Naming.Common CleanDateTimes = new[] { - @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19\d{2}|20\d{2})([ _\,\.\(\)\[\]\-][^0-9]|).*(19\d{2}|20\d{2})*", - @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19\d{2}|20\d{2})([ _\,\.\(\)\[\]\-][^0-9]|).*(19\d{2}|20\d{2})*" + @"(.+[^_\,\.\(\)\[\]\-])[_\.\(\)\[\]\-](19[0-9]{2}|20[0-9]{2})([ _\,\.\(\)\[\]\-][^0-9]|).*(19[0-9]{2}|20[0-9]{2})*", + @"(.+[^_\,\.\(\)\[\]\-])[ _\.\(\)\[\]\-]+(19[0-9]{2}|20[0-9]{2})([ _\,\.\(\)\[\]\-][^0-9]|).*(19[0-9]{2}|20[0-9]{2})*" }; CleanStrings = new[] @@ -277,7 +277,7 @@ namespace Emby.Naming.Common // This isn't a Kodi naming rule, but the expression below causes false positives, // so we make sure this one gets tested first. // "Foo Bar 889" - new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/x]*$") + new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/x]*$") { IsNamed = true }, @@ -300,32 +300,32 @@ namespace Emby.Naming.Common // *** End Kodi Standard Naming // [bar] Foo - 1 [baz] - new EpisodeExpression(@".*?(\[.*?\])+.*?(?<seriesname>[\w\s]+?)[-\s_]+(?<epnumber>\d+).*$") + new EpisodeExpression(@".*?(\[.*?\])+.*?(?<seriesname>[\w\s]+?)[-\s_]+(?<epnumber>[0-9]+).*$") { IsNamed = true }, - new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>\d+)[xX](?<epnumber>\d+)[^\\\/]*$") + new EpisodeExpression(@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]+)[xX](?<epnumber>[0-9]+)[^\\\/]*$") { IsNamed = true }, - new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>\d+)[x,X]?[eE](?<epnumber>\d+)[^\\\/]*$") + new EpisodeExpression(@".*(\\|\/)[sS](?<seasonnumber>[0-9]+)[x,X]?[eE](?<epnumber>[0-9]+)[^\\\/]*$") { IsNamed = true }, - new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d+))[^\\\/]*$") + new EpisodeExpression(@".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]+))[^\\\/]*$") { IsNamed = true }, - new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d+)[^\\\/]*$") + new EpisodeExpression(@".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]+)[^\\\/]*$") { IsNamed = true }, // "01.avi" - new EpisodeExpression(@".*[\\\/](?<epnumber>\d+)(-(?<endingepnumber>\d+))*\.\w+$") + new EpisodeExpression(@".*[\\\/](?<epnumber>[0-9]+)(-(?<endingepnumber>[0-9]+))*\.\w+$") { IsOptimistic = true, IsNamed = true @@ -335,34 +335,34 @@ namespace Emby.Naming.Common new EpisodeExpression(@"([0-9]+)-([0-9]+)"), // "01 - blah.avi", "01-blah.avi" - new EpisodeExpression(@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$") + new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\s?-\s?[^\\\/]*$") { IsOptimistic = true, IsNamed = true }, // "01.blah.avi" - new EpisodeExpression(@".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.[^\\\/]+$") + new EpisodeExpression(@".*(\\|\/)(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*\.[^\\\/]+$") { IsOptimistic = true, IsNamed = true }, // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah" - new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$") + new EpisodeExpression(@".*[\\\/][^\\\/]* - (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/]*$") { IsOptimistic = true, IsNamed = true }, // "01 episode title.avi" - new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>\d{1,3})([^\\\/]*)$") + new EpisodeExpression(@"[Ss]eason[\._ ](?<seasonnumber>[0-9]+)[\\\/](?<epnumber>[0-9]{1,3})([^\\\/]*)$") { IsOptimistic = true, IsNamed = true }, // "Episode 16", "Episode 16 - Title" - new EpisodeExpression(@".*[\\\/][^\\\/]* (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$") + new EpisodeExpression(@".*[\\\/][^\\\/]* (?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/]*$") { IsOptimistic = true, IsNamed = true @@ -625,17 +625,17 @@ namespace Emby.Naming.Common AudioBookPartsExpressions = new[] { // Detect specified chapters, like CH 01 - @"ch(?:apter)?[\s_-]?(?<chapter>\d+)", + @"ch(?:apter)?[\s_-]?(?<chapter>[0-9]+)", // Detect specified parts, like Part 02 - @"p(?:ar)?t[\s_-]?(?<part>\d+)", + @"p(?:ar)?t[\s_-]?(?<part>[0-9]+)", // Chapter is often beginning of filename - @"^(?<chapter>\d+)", + "^(?<chapter>[0-9]+)", // Part if often ending of filename - @"(?<part>\d+)$", + "(?<part>[0-9]+)$", // Sometimes named as 0001_005 (chapter_part) - @"(?<chapter>\d+)_(?<part>\d+)", + "(?<chapter>[0-9]+)_(?<part>[0-9]+)", // Some audiobooks are ripped from cd's, and will be named by disk number. - @"dis(?:c|k)[\s_-]?(?<chapter>\d+)" + @"dis(?:c|k)[\s_-]?(?<chapter>[0-9]+)" }; var extensions = VideoFileExtensions.ToList(); @@ -675,16 +675,16 @@ namespace Emby.Naming.Common MultipleEpisodeExpressions = new string[] { - @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$", - @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$" + @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[xX][eE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})(-[xE]?[eE]?(?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3}))((-| - )[0-9]{1,4}[xXeE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3}))((-| - )[0-9]{1,4}[xX][eE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3}))((-| - )?[xXeE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>((?![sS]?[0-9]{1,4}[xX][0-9]{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3}))(-[xX]?[eE]?(?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})((-| - )?[xXeE](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$", + @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>[0-9]{1,4})[xX\.]?[eE](?<epnumber>[0-9]{1,3})(-[xX]?[eE]?(?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$" }.Select(i => new EpisodeExpression(i) { IsNamed = true diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 0fd0239b4..5c43fdcfa 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -198,7 +198,7 @@ namespace MediaBrowser.MediaEncoding.Encoder internal static Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output - var match = Regex.Match(output, @"^ffmpeg version n?((?:\d+\.?)+)"); + var match = Regex.Match(output, @"^ffmpeg version n?((?:[0-9]+\.?)+)"); if (match.Success) { @@ -225,7 +225,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var rc = new StringBuilder(144); foreach (Match m in Regex.Matches( output, - @"((?<name>lib\w+)\s+(?<major>\d+)\.\s*(?<minor>\d+))", + @"((?<name>lib\w+)\s+(?<major>[0-9]+)\.\s*(?<minor>[0-9]+))", RegexOptions.Multiline)) { rc.Append(m.Groups["name"]) -- cgit v1.2.3 From febb6bced6d2eb0941ed30205558ff8cf045720b Mon Sep 17 00:00:00 2001 From: Bond_009 <Bond.009@outlook.com> Date: Wed, 22 Jul 2020 13:34:51 +0200 Subject: Review usage of string.Substring (part 1) Reduced allocations by replacing string.Substring with ReadOnlySpan<char>.Slice --- Emby.Dlna/Didl/DidlBuilder.cs | 3 +- Emby.Dlna/DlnaManager.cs | 6 ++-- Emby.Drawing/ImageProcessor.cs | 14 ++++----- Emby.Naming/TV/SeasonPathParser.cs | 2 +- .../Library/LibraryManager.cs | 4 +-- .../Library/MediaSourceManager.cs | 3 +- .../LiveTv/Listings/SchedulesDirect.cs | 4 +-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 ++++-- .../LiveTv/TunerHosts/M3uParser.cs | 25 ++++++++------- .../Localization/LocalizationManager.cs | 8 ++--- .../Networking/NetworkManager.cs | 2 +- .../Services/ServiceExec.cs | 8 ++++- .../Services/ServiceHandler.cs | 17 +++++----- .../Services/ServicePath.cs | 2 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 16 +++++----- .../MediaEncoding/EncodingHelper.cs | 23 +++++++------- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 4 +-- .../Subtitles/ParserValues.cs | 5 ++- MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 11 ++++--- MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs | 4 +++ MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 36 +++++++++------------- .../Subtitles/SubtitleEncoder.cs | 4 ++- MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs | 9 ++++-- MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs | 2 +- 25 files changed, 124 insertions(+), 99 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 66baa9512..70e358019 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -364,7 +364,8 @@ namespace Emby.Dlna.Didl writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture)); } - var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, + var mediaProfile = _profile.GetVideoMediaProfile( + streamInfo.Container, streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetAudioBitrate, diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 5911a73ef..1e20ff92b 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -387,7 +387,7 @@ namespace Emby.Dlna foreach (var name in _assembly.GetManifestResourceNames()) { - if (!name.StartsWith(namespaceName)) + if (!name.StartsWith(namespaceName, StringComparison.Ordinal)) { continue; } @@ -406,7 +406,7 @@ namespace Emby.Dlna using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { - await stream.CopyToAsync(fileStream); + await stream.CopyToAsync(fileStream).ConfigureAwait(false); } } } @@ -509,7 +509,7 @@ namespace Emby.Dlna return _jsonSerializer.DeserializeFromString<DeviceProfile>(json); } - class InternalProfileInfo + private class InternalProfileInfo { internal DeviceProfileInfo Info { get; set; } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 8696cb280..f585b90ca 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -448,21 +448,21 @@ namespace Emby.Drawing /// or /// filename. /// </exception> - public string GetCachePath(string path, string filename) + public string GetCachePath(ReadOnlySpan<char> path, ReadOnlySpan<char> filename) { - if (string.IsNullOrEmpty(path)) + if (path.IsEmpty) { - throw new ArgumentNullException(nameof(path)); + throw new ArgumentException("Path can't be empty.", nameof(path)); } - if (string.IsNullOrEmpty(filename)) + if (path.IsEmpty) { - throw new ArgumentNullException(nameof(filename)); + throw new ArgumentException("Filename can't be empty.", nameof(filename)); } - var prefix = filename.Substring(0, 1); + var prefix = filename.Slice(0, 1); - return Path.Combine(path, prefix, filename); + return Path.Join(path, prefix, filename); } /// <inheritdoc /> diff --git a/Emby.Naming/TV/SeasonPathParser.cs b/Emby.Naming/TV/SeasonPathParser.cs index 2fa6b4353..d2e324dda 100644 --- a/Emby.Naming/TV/SeasonPathParser.cs +++ b/Emby.Naming/TV/SeasonPathParser.cs @@ -77,7 +77,7 @@ namespace Emby.Naming.TV if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase)) { - var testFilename = filename.Substring(1); + var testFilename = filename.AsSpan().Slice(1); if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index c27b73c74..302d2a092 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -511,8 +511,8 @@ namespace Emby.Server.Implementations.Library { // Try to normalize paths located underneath program-data in an attempt to make them more portable key = key.Substring(_configurationManager.ApplicationPaths.ProgramDataPath.Length) - .TrimStart(new[] { '/', '\\' }) - .Replace("/", "\\"); + .TrimStart('/', '\\') + .Replace('/', '\\'); } if (forceCaseInsensitive || !_configurationManager.Configuration.EnableCaseSensitiveItemIds) diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index ceb36b389..e5df20622 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -869,7 +869,7 @@ namespace Emby.Server.Implementations.Library var provider = _providers.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture), keys[0], StringComparison.OrdinalIgnoreCase)); - var splitIndex = key.IndexOf(LiveStreamIdDelimeter); + var splitIndex = key.IndexOf(LiveStreamIdDelimeter, StringComparison.Ordinal); var keyId = key.Substring(splitIndex + 1); return new Tuple<IMediaSourceProvider, string>(provider, keyId); @@ -881,6 +881,7 @@ namespace Emby.Server.Implementations.Library public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } private readonly object _disposeLock = new object(); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 3709f8fe4..77a7069eb 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -461,7 +461,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private async Task<List<ScheduleDirect.ShowImages>> GetImageForPrograms( ListingsProviderInfo info, List<string> programIds, - CancellationToken cancellationToken) + CancellationToken cancellationToken) { if (programIds.Count == 0) { @@ -474,7 +474,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var imageId = i.Substring(0, 10); - if (!imageIdString.Contains(imageId)) + if (!imageIdString.Contains(imageId, StringComparison.Ordinal)) { imageIdString += "\"" + imageId + "\","; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2e2488e6e..00420bd2a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -195,7 +195,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun while (!sr.EndOfStream) { string line = StripXML(sr.ReadLine()); - if (line.Contains("Channel")) + if (line.Contains("Channel", StringComparison.Ordinal)) { LiveTvTunerStatus status; var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); @@ -226,6 +226,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private static string StripXML(string source) { + if (string.IsNullOrEmpty(source)) + { + return string.Empty; + } + char[] buffer = new char[source.Length]; int bufferIndex = 0; bool inside = false; @@ -270,7 +275,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun for (int i = 0; i < model.TunerCount; ++i) { - var name = string.Format("Tuner {0}", i + 1); + var name = string.Format(CultureInfo.InvariantCulture, "Tuner {0}", i + 1); var currentChannel = "none"; // @todo Get current channel and map back to Station Id var isAvailable = await manager.CheckTunerAvailability(ipInfo, i, cancellationToken).ConfigureAwait(false); var status = isAvailable ? LiveTvTunerStatus.Available : LiveTvTunerStatus.LiveTv; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index c798c0a85..875977219 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -158,15 +158,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts private string GetChannelNumber(string extInf, Dictionary<string, string> attributes, string mediaUrl) { var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - var nameInExtInf = nameParts.Length > 1 ? nameParts[nameParts.Length - 1].Trim() : null; + var nameInExtInf = nameParts.Length > 1 ? nameParts[^1].AsSpan().Trim() : ReadOnlySpan<char>.Empty; string numberString = null; string attributeValue; - double doubleValue; if (attributes.TryGetValue("tvg-chno", out attributeValue)) { - if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { numberString = attributeValue; } @@ -176,36 +175,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { if (attributes.TryGetValue("tvg-id", out attributeValue)) { - if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { numberString = attributeValue; } else if (attributes.TryGetValue("channel-id", out attributeValue)) { - if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { numberString = attributeValue; } } } - if (String.IsNullOrWhiteSpace(numberString)) + if (string.IsNullOrWhiteSpace(numberString)) { // Using this as a fallback now as this leads to Problems with channels like "5 USA" // where 5 isnt ment to be the channel number // Check for channel number with the format from SatIp // #EXTINF:0,84. VOX Schweiz // #EXTINF:0,84.0 - VOX Schweiz - if (!string.IsNullOrWhiteSpace(nameInExtInf)) + if (!nameInExtInf.IsEmpty && !nameInExtInf.IsWhiteSpace()) { var numberIndex = nameInExtInf.IndexOf(' '); if (numberIndex > 0) { - var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' }); + var numberPart = nameInExtInf.Slice(0, numberIndex).Trim(new[] { ' ', '.' }); - if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) + if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { - numberString = numberPart; + numberString = numberPart.ToString(); } } } @@ -231,7 +230,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last()); + numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/')[^1]); if (!IsValidChannelNumber(numberString)) { @@ -258,7 +257,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return false; } - if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) + if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { return false; } @@ -281,7 +280,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' }); - if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) + if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out _)) { // channel.Number = number.ToString(); nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' }); diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 62a23118f..90e2766b8 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -247,7 +247,7 @@ namespace Emby.Server.Implementations.Localization } // Try splitting by : to handle "Germany: FSK 18" - var index = rating.IndexOf(':'); + var index = rating.IndexOf(':', StringComparison.Ordinal); if (index != -1) { rating = rating.Substring(index).TrimStart(':').Trim(); @@ -312,12 +312,12 @@ namespace Emby.Server.Implementations.Localization throw new ArgumentNullException(nameof(culture)); } - const string prefix = "Core"; - var key = prefix + culture; + const string Prefix = "Core"; + var key = Prefix + culture; return _dictionaries.GetOrAdd( key, - f => GetDictionary(prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); + f => GetDictionary(Prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); } private async Task<Dictionary<string, string>> GetDictionary(string prefix, string culture, string baseFilename) diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 50cb44b28..ff95302ee 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -390,7 +390,7 @@ namespace Emby.Server.Implementations.Networking var host = uri.DnsSafeHost; _logger.LogDebug("Resolving host {0}", host); - address = GetIpAddresses(host).Result.FirstOrDefault(); + address = GetIpAddresses(host).GetAwaiter().GetResult().FirstOrDefault(); if (address != null) { diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs index cbc4b754d..947a5cbf8 100644 --- a/Emby.Server.Implementations/Services/ServiceExec.cs +++ b/Emby.Server.Implementations/Services/ServiceExec.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -105,7 +106,12 @@ namespace Emby.Server.Implementations.Services } var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLowerInvariant(); - throw new NotImplementedException(string.Format("Could not find method named {1}({0}) or Any({0}) on Service {2}", requestDto.GetType().GetMethodName(), expectedMethodName, serviceType.GetMethodName())); + throw new NotImplementedException( + string.Format( + CultureInfo.InvariantCulture, + "Could not find method named {1}({0}) or Any({0}) on Service {2}", + requestDto.GetType().GetMethodName(), + expectedMethodName, serviceType.GetMethodName())); } private static async Task<object> GetTaskResult(Task task) diff --git a/Emby.Server.Implementations/Services/ServiceHandler.cs b/Emby.Server.Implementations/Services/ServiceHandler.cs index a42f88ea0..e63a80cee 100644 --- a/Emby.Server.Implementations/Services/ServiceHandler.cs +++ b/Emby.Server.Implementations/Services/ServiceHandler.cs @@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.Services var pos = pathInfo.LastIndexOf('.'); if (pos != -1) { - var format = pathInfo.Substring(pos + 1); + var format = pathInfo.AsSpan().Slice(pos + 1); contentType = GetFormatContentType(format); if (contentType != null) { @@ -55,15 +55,18 @@ namespace Emby.Server.Implementations.Services return pathInfo; } - private static string GetFormatContentType(string format) + private static string GetFormatContentType(ReadOnlySpan<char> format) { - // built-in formats - switch (format) + if (format.Equals("json", StringComparison.Ordinal)) { - case "json": return "application/json"; - case "xml": return "application/xml"; - default: return null; + return "application/json"; } + else if (format.Equals("xml", StringComparison.Ordinal)) + { + return "application/xml"; + } + + return null; } public async Task ProcessRequestAsync(HttpListenerHost httpHost, IRequest httpReq, HttpResponse httpRes, ILogger logger, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 89538ae72..69c6844f8 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -156,7 +156,7 @@ namespace Emby.Server.Implementations.Services { var component = components[i]; - if (component.StartsWith(VariablePrefix)) + if (component.StartsWith(VariablePrefix, StringComparison.Ordinal)) { var variableName = component.Substring(1, component.Length - 2); if (variableName[variableName.Length - 1] == WildCardChar) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index fe5f980b1..6ff96ac56 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -369,7 +369,7 @@ namespace MediaBrowser.Api.Playback.Hls var playlistFilename = Path.GetFileNameWithoutExtension(playlist); - var indexString = Path.GetFileNameWithoutExtension(file.Name).Substring(playlistFilename.Length); + var indexString = Path.GetFileNameWithoutExtension(file.Name).AsSpan().Slice(playlistFilename.Length); return int.Parse(indexString, NumberStyles.Integer, CultureInfo.InvariantCulture); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 90f62e153..f34309c40 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -675,11 +675,11 @@ namespace MediaBrowser.Controller.Entities return System.IO.Path.Combine(basePath, "channels", ChannelId.ToString("N", CultureInfo.InvariantCulture), Id.ToString("N", CultureInfo.InvariantCulture)); } - var idString = Id.ToString("N", CultureInfo.InvariantCulture); + ReadOnlySpan<char> idString = Id.ToString("N", CultureInfo.InvariantCulture); basePath = System.IO.Path.Combine(basePath, "library"); - return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString); + return System.IO.Path.Join(basePath, idString.Slice(0, 2), idString); } /// <summary> @@ -702,26 +702,27 @@ namespace MediaBrowser.Controller.Entities foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters) { - sortable = sortable.Replace(removeChar, string.Empty); + sortable = sortable.Replace(removeChar, string.Empty, StringComparison.Ordinal); } foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters) { - sortable = sortable.Replace(replaceChar, " "); + sortable = sortable.Replace(replaceChar, " ", StringComparison.Ordinal); } foreach (var search in ConfigurationManager.Configuration.SortRemoveWords) { // Remove from beginning if a space follows - if (sortable.StartsWith(search + " ")) + if (sortable.StartsWith(search + " ", StringComparison.Ordinal)) { sortable = sortable.Remove(0, search.Length + 1); } + // Remove from middle if surrounded by spaces - sortable = sortable.Replace(" " + search + " ", " "); + sortable = sortable.Replace(" " + search + " ", " ", StringComparison.Ordinal); // Remove from end if followed by a space - if (sortable.EndsWith(" " + search)) + if (sortable.EndsWith(" " + search, StringComparison.Ordinal)) { sortable = sortable.Remove(sortable.Length - (search.Length + 1)); } @@ -751,6 +752,7 @@ namespace MediaBrowser.Controller.Entities builder.Append(chunkBuilder); } + // logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); return builder.ToString().RemoveDiacritics(); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ffbda42c3..18fd53ad6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1588,7 +1588,7 @@ namespace MediaBrowser.Controller.MediaEncoding { outputVideoCodec ??= string.Empty; - var outputSizeParam = string.Empty; + var outputSizeParam = ReadOnlySpan<char>.Empty; var request = state.BaseRequest; // Add resolution params, if specified @@ -1602,28 +1602,28 @@ namespace MediaBrowser.Controller.MediaEncoding var index = outputSizeParam.IndexOf("hwdownload", StringComparison.OrdinalIgnoreCase); if (index != -1) { - outputSizeParam = outputSizeParam.Substring(index); + outputSizeParam = outputSizeParam.Slice(index); } else { index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase); if (index != -1) { - outputSizeParam = outputSizeParam.Substring(index); + outputSizeParam = outputSizeParam.Slice(index); } else { index = outputSizeParam.IndexOf("yadif", StringComparison.OrdinalIgnoreCase); if (index != -1) { - outputSizeParam = outputSizeParam.Substring(index); + outputSizeParam = outputSizeParam.Slice(index); } else { index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase); if (index != -1) { - outputSizeParam = outputSizeParam.Substring(index); + outputSizeParam = outputSizeParam.Slice(index); } } } @@ -1669,9 +1669,9 @@ namespace MediaBrowser.Controller.MediaEncoding // Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference) // Always put the scaler before the overlay for better performance - var retStr = !string.IsNullOrEmpty(outputSizeParam) ? - " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" : - " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\""; + var retStr = !outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\""; // When the input may or may not be hardware VAAPI decodable if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) @@ -1705,7 +1705,7 @@ namespace MediaBrowser.Controller.MediaEncoding */ if (isLinux) { - retStr = !string.IsNullOrEmpty(outputSizeParam) ? + retStr = !outputSizeParam.IsEmpty ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv\""; } @@ -1717,7 +1717,7 @@ namespace MediaBrowser.Controller.MediaEncoding mapPrefix, subtitleStreamIndex, state.VideoStream.Index, - outputSizeParam, + outputSizeParam.ToString(), videoSizeParam); } @@ -2090,7 +2090,7 @@ namespace MediaBrowser.Controller.MediaEncoding // Add software deinterlace filter before scaling filter if (state.DeInterlace("h264", true) || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true)) { - var deintParam = string.Empty; + string deintParam; var inputFramerate = videoStream?.RealFrameRate; // If it is already 60fps then it will create an output framerate that is much too high for roku and others to handle @@ -2159,7 +2159,6 @@ namespace MediaBrowser.Controller.MediaEncoding return output; } - /// <summary> /// Gets the number of threads. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 0e2d70017..43a45291c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles continue; } - if (line.StartsWith("[")) + if (line[0] == '[') { break; } @@ -62,7 +62,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return trackInfo; } - long GetTicks(string time) + private long GetTicks(ReadOnlySpan<char> time) { return TimeSpan.TryParseExact(time, @"h\:mm\:ss\.ff", _usCulture, out var span) ? span.Ticks : 0; diff --git a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs index bf8808eb8..dca5c1e8a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs @@ -1,6 +1,9 @@ +#nullable enable +#pragma warning disable CS1591 + namespace MediaBrowser.MediaEncoding.Subtitles { - public class ParserValues + public static class ParserValues { public const string NewLine = "\r\n"; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 728efa788..cc35efb3f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; @@ -20,6 +22,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger = logger; } + /// <inheritdoc /> public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var trackInfo = new SubtitleTrackInfo(); @@ -55,11 +58,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles } subEvent.StartPositionTicks = GetTicks(time[0]); - var endTime = time[1]; - var idx = endTime.IndexOf(" ", StringComparison.Ordinal); + var endTime = time[1].AsSpan(); + var idx = endTime.IndexOf(' '); if (idx > 0) { - endTime = endTime.Substring(0, idx); + endTime = endTime.Slice(0, idx); } subEvent.EndPositionTicks = GetTicks(endTime); @@ -88,7 +91,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return trackInfo; } - long GetTicks(string time) + private long GetTicks(ReadOnlySpan<char> time) { return TimeSpan.TryParseExact(time, @"hh\:mm\:ss\.fff", _usCulture, out var span) ? span.Ticks diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs index 45b317b2e..143c010b7 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs @@ -8,8 +8,12 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { + /// <summary> + /// SRT subtitle writer. + /// </summary> public class SrtWriter : ISubtitleWriter { + /// <inheritdoc /> public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken) { using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 77033c6b4..bd330f568 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -12,6 +12,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> public class SsaParser : ISubtitleParser { + /// <inheritdoc /> public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var trackInfo = new SubtitleTrackInfo(); @@ -45,7 +46,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles header.AppendLine(line); } - if (line.Trim().ToLowerInvariant() == "[events]") + if (string.Equals(line.Trim(), "[events]", StringComparison.OrdinalIgnoreCase)) { eventsStarted = true; } @@ -63,27 +64,27 @@ namespace MediaBrowser.MediaEncoding.Subtitles format = line.ToLowerInvariant().Substring(8).Split(','); for (int i = 0; i < format.Length; i++) { - if (format[i].Trim().ToLowerInvariant() == "layer") + if (string.Equals(format[i].Trim(), "layer", StringComparison.OrdinalIgnoreCase)) { indexLayer = i; } - else if (format[i].Trim().ToLowerInvariant() == "start") + else if (string.Equals(format[i].Trim(), "start", StringComparison.OrdinalIgnoreCase)) { indexStart = i; } - else if (format[i].Trim().ToLowerInvariant() == "end") + else if (string.Equals(format[i].Trim(), "end", StringComparison.OrdinalIgnoreCase)) { indexEnd = i; } - else if (format[i].Trim().ToLowerInvariant() == "text") + else if (string.Equals(format[i].Trim(), "text", StringComparison.OrdinalIgnoreCase)) { indexText = i; } - else if (format[i].Trim().ToLowerInvariant() == "effect") + else if (string.Equals(format[i].Trim(), "effect", StringComparison.OrdinalIgnoreCase)) { indexEffect = i; } - else if (format[i].Trim().ToLowerInvariant() == "style") + else if (string.Equals(format[i].Trim(), "style", StringComparison.OrdinalIgnoreCase)) { indexStyle = i; } @@ -184,12 +185,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles int.Parse(timeCode[3]) * 10).Ticks; } - public static string GetFormattedText(string text) + private static string GetFormattedText(string text) { text = text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - bool italic = false; - for (int i = 0; i < 10; i++) // just look ten times... { if (text.Contains(@"{\fn")) @@ -200,7 +199,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string fontName = text.Substring(start + 4, end - (start + 4)); string extraTags = string.Empty; - CheckAndAddSubTags(ref fontName, ref extraTags, out italic); + CheckAndAddSubTags(ref fontName, ref extraTags, out bool italic); text = text.Remove(start, end - start + 1); if (italic) { @@ -231,7 +230,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string fontSize = text.Substring(start + 4, end - (start + 4)); string extraTags = string.Empty; - CheckAndAddSubTags(ref fontSize, ref extraTags, out italic); + CheckAndAddSubTags(ref fontSize, ref extraTags, out bool italic); if (IsInteger(fontSize)) { text = text.Remove(start, end - start + 1); @@ -265,7 +264,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string color = text.Substring(start + 4, end - (start + 4)); string extraTags = string.Empty; - CheckAndAddSubTags(ref color, ref extraTags, out italic); + CheckAndAddSubTags(ref color, ref extraTags, out bool italic); color = color.Replace("&", string.Empty).TrimStart('H'); color = color.PadLeft(6, '0'); @@ -303,7 +302,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string color = text.Substring(start + 5, end - (start + 5)); string extraTags = string.Empty; - CheckAndAddSubTags(ref color, ref extraTags, out italic); + CheckAndAddSubTags(ref color, ref extraTags, out bool italic); color = color.Replace("&", string.Empty).TrimStart('H'); color = color.PadLeft(6, '0'); @@ -354,14 +353,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } private static bool IsInteger(string s) - { - if (int.TryParse(s, out var i)) - { - return true; - } - - return false; - } + => int.TryParse(s, out _); private static int CountTagInText(string text, string tag) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f1aa8ea5f..969ad1b33 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Concurrent; using System.Diagnostics; @@ -365,7 +367,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <returns>System.Object.</returns> private SemaphoreSlim GetLock(string filename) { - return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1)); + return _semaphoreLocks.GetOrAdd(filename, _ => new SemaphoreSlim(1, 1)); } /// <summary> diff --git a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs index 7d3e18578..e5c785bc5 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs @@ -6,8 +6,12 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { + /// <summary> + /// TTML subtitle writer. + /// </summary> public class TtmlWriter : ISubtitleWriter { + /// <inheritdoc /> public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken) { // Example: https://github.com/zmalltalker/ttml2vtt/blob/master/data/sample.xml @@ -36,9 +40,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = Regex.Replace(text, @"\\n", "<br/>", RegexOptions.IgnoreCase); - writer.WriteLine("<p begin=\"{0}\" dur=\"{1}\">{2}</p>", + writer.WriteLine( + "<p begin=\"{0}\" dur=\"{1}\">{2}</p>", trackEvent.StartPositionTicks, - (trackEvent.EndPositionTicks - trackEvent.StartPositionTicks), + trackEvent.EndPositionTicks - trackEvent.StartPositionTicks, text); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs index de35acbba..ad32cb794 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = Regex.Replace(text, @"\\n", " ", RegexOptions.IgnoreCase); writer.WriteLine(text); - writer.WriteLine(string.Empty); + writer.WriteLine(); } } } -- cgit v1.2.3 From 7b862bba5aad345f0bc8d76bfb950590471ae232 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sat, 25 Jul 2020 00:57:34 +0800 Subject: add Tonemapping relaying on nvdec and ocl --- .../MediaEncoding/EncodingHelper.cs | 109 +++++++++++++++++++-- .../Probing/MediaStreamInfo.cs | 14 +++ .../Probing/ProbeResultNormalizer.cs | 10 ++ .../Configuration/EncodingOptions.cs | 29 +++++- MediaBrowser.Model/Entities/MediaStream.cs | 18 ++-- 5 files changed, 166 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 0242338b7..4a33f22e6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -454,6 +454,7 @@ namespace MediaBrowser.Controller.MediaEncoding var isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; + var isNvencHevcDecoder = videoDecoder.IndexOf("hevc_cuvid", StringComparison.OrdinalIgnoreCase) != -1; var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); @@ -511,6 +512,25 @@ namespace MediaBrowser.Controller.MediaEncoding } } } + + if (state.IsVideoRequest + && string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) + { + var codec = state.VideoStream.Codec.ToLowerInvariant(); + var isColorDepth10 = IsColorDepth10(state); + + if (isNvencHevcDecoder && isColorDepth10 + && _mediaEncoder.SupportsHwaccel("opencl") + && encodingOptions.EnableTonemapping + && !string.IsNullOrEmpty(state.VideoStream.VideoRange) + && state.VideoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase)) + { + arg.Append("-init_hw_device opencl=ocl:") + .Append(encodingOptions.OpenclDevice) + .Append(' ') + .Append("-filter_hw_device ocl "); + } + } } arg.Append("-i ") @@ -994,11 +1014,33 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) + && !string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } + if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + { + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty; + var videoStream = state.VideoStream; + var isColorDepth10 = IsColorDepth10(state); + + if (videoDecoder.IndexOf("hevc_cuvid", StringComparison.OrdinalIgnoreCase) != -1 + && isColorDepth10 + && _mediaEncoder.SupportsHwaccel("opencl") + && encodingOptions.EnableTonemapping + && !string.IsNullOrEmpty(videoStream.VideoRange) + && videoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase)) + { + param = "-pix_fmt nv12 " + param; + } + else + { + param = "-pix_fmt yuv420p " + param; + } + } + if (string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt nv21 " + param; @@ -1599,46 +1641,54 @@ namespace MediaBrowser.Controller.MediaEncoding { outputSizeParam = GetOutputSizeParam(state, options, outputVideoCodec).TrimEnd('"'); - var index = outputSizeParam.IndexOf("hwdownload", StringComparison.OrdinalIgnoreCase); + var index = outputSizeParam.IndexOf("hwupload,tonemap_opencl", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } else { - index = outputSizeParam.IndexOf("hwupload=extra_hw_frames", StringComparison.OrdinalIgnoreCase); + index = outputSizeParam.IndexOf("hwdownload", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } else { - index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase); + index = outputSizeParam.IndexOf("hwupload=extra_hw_frames", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } else { - index = outputSizeParam.IndexOf("yadif", StringComparison.OrdinalIgnoreCase); + index = outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } else { - index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase); + index = outputSizeParam.IndexOf("yadif", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } else { - index = outputSizeParam.IndexOf("vpp", StringComparison.OrdinalIgnoreCase); + index = outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase); if (index != -1) { outputSizeParam = outputSizeParam.Substring(index); } + else + { + index = outputSizeParam.IndexOf("vpp", StringComparison.OrdinalIgnoreCase); + if (index != -1) + { + outputSizeParam = outputSizeParam.Substring(index); + } + } } } } @@ -2058,12 +2108,58 @@ namespace MediaBrowser.Controller.MediaEncoding var isVaapiH264Encoder = outputVideoCodec.IndexOf("h264_vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isQsvH264Encoder = outputVideoCodec.IndexOf("h264_qsv", StringComparison.OrdinalIgnoreCase) != -1; var isNvdecH264Decoder = videoDecoder.IndexOf("h264_cuvid", StringComparison.OrdinalIgnoreCase) != -1; + var isNvdecHevcDecoder = videoDecoder.IndexOf("hevc_cuvid", StringComparison.OrdinalIgnoreCase) != -1; var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1; var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + var isColorDepth10 = IsColorDepth10(state); var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; + // Currently only with the use of NVENC decoder can we get a decent performance. + // Currently only the HEVC/H265 format is supported. + // NVIDIA Pascal and Turing or higher are recommended. + if (isNvdecHevcDecoder && isColorDepth10 + && _mediaEncoder.SupportsHwaccel("opencl") + && options.EnableTonemapping + && !string.IsNullOrEmpty(videoStream.VideoRange) + && videoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase)) + { + var parameters = "tonemap_opencl=format=nv12:primaries=bt709:transfer=bt709:matrix=bt709:tonemap={0}:desat={1}:threshold={2}:peak={3}"; + + if (options.TonemappingParam != 0) + { + parameters += ":param={4}"; + } + + if (!string.Equals(options.TonemappingRange, "auto", StringComparison.OrdinalIgnoreCase)) + { + parameters += ":range={5}"; + } + + // Upload the HDR10 or HLG data to the OpenCL device, + // use tonemap_opencl filter for tone mapping, + // and then download the SDR data to memory. + filters.Add("hwupload"); + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + parameters, + options.TonemappingAlgorithm, + options.TonemappingDesat, + options.TonemappingThreshold, + options.TonemappingPeak, + options.TonemappingParam, + options.TonemappingRange)); + filters.Add("hwdownload"); + + if (hasGraphicalSubs || state.DeInterlace("h265", true) || state.DeInterlace("hevc", true) + || string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) + { + filters.Add("format=nv12"); + } + } + // When the input may or may not be hardware VAAPI decodable if (isVaapiH264Encoder) { @@ -2081,7 +2177,6 @@ namespace MediaBrowser.Controller.MediaEncoding else if (IsVaapiSupported(state) && isVaapiDecoder && isLibX264Encoder) { var codec = videoStream.Codec.ToLowerInvariant(); - var isColorDepth10 = IsColorDepth10(state); // Assert 10-bit hardware VAAPI decodable if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index a2ea0766a..d9658cba2 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -279,6 +279,20 @@ namespace MediaBrowser.MediaEncoding.Probing [JsonPropertyName("disposition")] public IReadOnlyDictionary<string, int> Disposition { get; set; } + /// <summary> + /// Gets or sets the color range. + /// </summary> + /// <value>The color range.</value> + [JsonPropertyName("color_range")] + public string ColorRange { get; set; } + + /// <summary> + /// Gets or sets the color space. + /// </summary> + /// <value>The color space.</value> + [JsonPropertyName("color_space")] + public string ColorSpace { get; set; } + /// <summary> /// Gets or sets the color transfer. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c85d963ed..3815e00d4 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -703,6 +703,16 @@ namespace MediaBrowser.MediaEncoding.Probing stream.RefFrames = streamInfo.Refs; } + if (!string.IsNullOrEmpty(streamInfo.ColorRange)) + { + stream.ColorRange = streamInfo.ColorRange; + } + + if (!string.IsNullOrEmpty(streamInfo.ColorSpace)) + { + stream.ColorSpace = streamInfo.ColorSpace; + } + if (!string.IsNullOrEmpty(streamInfo.ColorTransfer)) { stream.ColorTransfer = streamInfo.ColorTransfer; diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 9a30f7e9f..843ff3ff9 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -29,6 +29,22 @@ namespace MediaBrowser.Model.Configuration public string VaapiDevice { get; set; } + public string OpenclDevice { get; set; } + + public bool EnableTonemapping { get; set; } + + public string TonemappingAlgorithm { get; set; } + + public string TonemappingRange { get; set; } + + public double TonemappingDesat { get; set; } + + public double TonemappingThreshold { get; set; } + + public double TonemappingPeak { get; set; } + + public double TonemappingParam { get; set; } + public int H264Crf { get; set; } public int H265Crf { get; set; } @@ -53,8 +69,19 @@ namespace MediaBrowser.Model.Configuration EnableThrottling = false; ThrottleDelaySeconds = 180; EncodingThreadCount = -1; - // This is a DRM device that is almost guaranteed to be there on every intel platform, plus it's the default one in ffmpeg if you don't specify anything + // This is a DRM device that is almost guaranteed to be there on every intel platform, + // plus it's the default one in ffmpeg if you don't specify anything VaapiDevice = "/dev/dri/renderD128"; + // This is the OpenCL device that is used for tonemapping. + // The left side of the dot is the platform number, and the right side is the device number on the platform. + OpenclDevice = "0.0"; + EnableTonemapping = false; + TonemappingAlgorithm = "reinhard"; + TonemappingRange = "auto"; + TonemappingDesat = 0; + TonemappingThreshold = 0.8; + TonemappingPeak = 0; + TonemappingParam = 0; H264Crf = 23; H265Crf = 28; DeinterlaceMethod = "yadif"; diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 1b37cfc93..19eb79acc 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -35,6 +35,18 @@ namespace MediaBrowser.Model.Entities /// <value>The language.</value> public string Language { get; set; } + /// <summary> + /// Gets or sets the color range. + /// </summary> + /// <value>The color range.</value> + public string ColorRange { get; set; } + + /// <summary> + /// Gets or sets the color space. + /// </summary> + /// <value>The color space.</value> + public string ColorSpace { get; set; } + /// <summary> /// Gets or sets the color transfer. /// </summary> @@ -47,12 +59,6 @@ namespace MediaBrowser.Model.Entities /// <value>The color primaries.</value> public string ColorPrimaries { get; set; } - /// <summary> - /// Gets or sets the color space. - /// </summary> - /// <value>The color space.</value> - public string ColorSpace { get; set; } - /// <summary> /// Gets or sets the comment. /// </summary> -- cgit v1.2.3 From 27709c9bb335df00b0660715a7478c2f21e49055 Mon Sep 17 00:00:00 2001 From: Odd Stråbø <oddstr13@openshell.no> Date: Sat, 25 Jul 2020 12:44:31 +0200 Subject: Fix embedded subtitles --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 8e6543d80..2f311293c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -174,7 +174,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles inputFiles = new[] { mediaSource.Path }; } - var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, _mediaSourceManager.GetPathProtocol(subtitleStream.Path), subtitleStream, cancellationToken).ConfigureAwait(false); + var protocol = mediaSource.Protocol; + if (subtitleStream.IsExternal) { + protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path); + } + var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, protocol, subtitleStream, cancellationToken).ConfigureAwait(false); var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From 591fcf7ff26d338975deec3d36f7d2297af9cec2 Mon Sep 17 00:00:00 2001 From: Odd Stråbø <oddstr13@openshell.no> Date: Sat, 25 Jul 2020 13:41:04 +0200 Subject: Fix formating --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 2f311293c..f850f5c2e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -175,9 +175,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles } var protocol = mediaSource.Protocol; - if (subtitleStream.IsExternal) { + if (subtitleStream.IsExternal) + { protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path); } + var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, protocol, subtitleStream, cancellationToken).ConfigureAwait(false); var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); -- cgit v1.2.3 From d4092846e4c1c6c545c37e2e31ecdaa892711789 Mon Sep 17 00:00:00 2001 From: Bond_009 <Bond.009@outlook.com> Date: Wed, 29 Jul 2020 13:17:01 +0200 Subject: Optimize Substring and StringBuilder usage --- Emby.Dlna/DlnaManager.cs | 18 +++++++++--------- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 3 ++- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 14 +++++++++----- MediaBrowser.Api/Subtitles/SubtitleService.cs | 15 +++++++++------ .../Probing/ProbeResultNormalizer.cs | 11 ++++++++--- .../Subtitles/SubtitleEncoder.cs | 12 ++++++------ .../MediaInfo/AudioImageProvider.cs | 6 +++--- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 4 ++-- .../Plugins/TheTvdb/TvdbEpisodeProvider.cs | 4 ++-- .../Plugins/Tmdb/People/TmdbPersonProvider.cs | 4 ++-- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 22 ++++++++++++++++------ 12 files changed, 69 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 1e20ff92b..269f7ee43 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -122,15 +122,15 @@ namespace Emby.Dlna var builder = new StringBuilder(); builder.AppendLine("No matching device profile found. The default will need to be used."); - builder.AppendLine(string.Format("DeviceDescription:{0}", profile.DeviceDescription ?? string.Empty)); - builder.AppendLine(string.Format("FriendlyName:{0}", profile.FriendlyName ?? string.Empty)); - builder.AppendLine(string.Format("Manufacturer:{0}", profile.Manufacturer ?? string.Empty)); - builder.AppendLine(string.Format("ManufacturerUrl:{0}", profile.ManufacturerUrl ?? string.Empty)); - builder.AppendLine(string.Format("ModelDescription:{0}", profile.ModelDescription ?? string.Empty)); - builder.AppendLine(string.Format("ModelName:{0}", profile.ModelName ?? string.Empty)); - builder.AppendLine(string.Format("ModelNumber:{0}", profile.ModelNumber ?? string.Empty)); - builder.AppendLine(string.Format("ModelUrl:{0}", profile.ModelUrl ?? string.Empty)); - builder.AppendLine(string.Format("SerialNumber:{0}", profile.SerialNumber ?? string.Empty)); + builder.AppendFormat(CultureInfo.InvariantCulture, "DeviceDescription:{0}", profile.DeviceDescription ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "FriendlyName:{0}", profile.FriendlyName ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "Manufacturer:{0}", profile.Manufacturer ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "ManufacturerUrl:{0}", profile.ManufacturerUrl ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "ModelDescription:{0}", profile.ModelDescription ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "ModelName:{0}", profile.ModelName ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "ModelNumber:{0}", profile.ModelNumber ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "ModelUrl:{0}", profile.ModelUrl ?? string.Empty).AppendLine(); + builder.AppendFormat(CultureInfo.InvariantCulture, "SerialNumber:{0}", profile.SerialNumber ?? string.Empty).AppendLine(); _logger.LogInformation(builder.ToString()); } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 418cd92b3..c80e8e64f 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -194,7 +194,8 @@ namespace MediaBrowser.Api.Playback.Hls var paddedBitrate = Convert.ToInt32(bitrate * 1.15); // Main stream - builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(CultureInfo.InvariantCulture)); + builder.Append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=") + .AppendLine(paddedBitrate.ToString(CultureInfo.InvariantCulture)); var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8"); builder.AppendLine(playlistUrl); diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 6ff96ac56..661c1ba5f 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -968,7 +968,8 @@ namespace MediaBrowser.Api.Playback.Hls builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); builder.AppendLine("#EXT-X-VERSION:3"); - builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture)); + builder.Append("#EXT-X-TARGETDURATION:") + .AppendLine(Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture)); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); var queryStringIndex = Request.RawUrl.IndexOf('?'); @@ -983,14 +984,17 @@ namespace MediaBrowser.Api.Playback.Hls foreach (var length in segmentLengths) { - builder.AppendLine("#EXTINF:" + length.ToString("0.0000", CultureInfo.InvariantCulture) + ", nodesc"); - - builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}", + builder.Append("#EXTINF:") + .Append(length.ToString("0.0000", CultureInfo.InvariantCulture)) + .AppendLine(", nodesc"); + builder.AppendFormat( + CultureInfo.InvariantCulture, + "hls1/{0}/{1}{2}{3}", name, index.ToString(CultureInfo.InvariantCulture), GetSegmentFileExtension(request), - queryString)); + queryString).AppendLine(); index++; } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index a70da8e56..6a6196d8a 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -175,11 +175,12 @@ namespace MediaBrowser.Api.Subtitles throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)"); } - builder.AppendLine("#EXTM3U"); - builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture)); - builder.AppendLine("#EXT-X-VERSION:3"); - builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); - builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); + builder.AppendLine("#EXTM3U") + .Append("#EXT-X-TARGETDURATION:") + .AppendLine(request.SegmentLength.ToString(CultureInfo.InvariantCulture)) + .AppendLine("#EXT-X-VERSION:3") + .AppendLine("#EXT-X-MEDIA-SEQUENCE:0") + .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); long positionTicks = 0; @@ -190,7 +191,9 @@ namespace MediaBrowser.Api.Subtitles var remaining = runtime - positionTicks; var lengthTicks = Math.Min(remaining, segmentLengthTicks); - builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture) + ","); + builder.Append("#EXTINF:") + .Append(TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture)) + .AppendLine(","); var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks); diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c85d963ed..0b447e3e6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1367,7 +1367,9 @@ namespace MediaBrowser.MediaEncoding.Probing // OR -> COMMENT. SUBTITLE: DESCRIPTION // e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S] // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S] - if (string.IsNullOrWhiteSpace(subTitle) && !string.IsNullOrWhiteSpace(description) && description.Substring(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).Contains(":")) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename + if (string.IsNullOrWhiteSpace(subTitle) + && !string.IsNullOrWhiteSpace(description) + && description.AsSpan().Slice(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename { string[] parts = description.Split(':'); if (parts.Length > 0) @@ -1375,7 +1377,7 @@ namespace MediaBrowser.MediaEncoding.Probing string subtitle = parts[0]; try { - if (subtitle.Contains("/")) // 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(' '); video.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]); @@ -1390,8 +1392,11 @@ namespace MediaBrowser.MediaEncoding.Probing } catch // Default parsing { - if (subtitle.Contains(".")) // skip the comment, keep the subtitle + if (subtitle.Contains('.', StringComparison.Ordinal)) + { + // skip the comment, keep the subtitle description = string.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + } else { description = subtitle.Trim(); // Clean up whitespaces and save it diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f850f5c2e..2afa89cda 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -731,19 +731,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); - var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension; + ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension; - var prefix = filename.Substring(0, 1); + var prefix = filename.Slice(0, 1); - return Path.Combine(SubtitleCachePath, prefix, filename); + return Path.Join(SubtitleCachePath, prefix, filename); } else { - var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension; + ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension; - var prefix = filename.Substring(0, 1); + var prefix = filename.Slice(0, 1); - return Path.Combine(SubtitleCachePath, prefix, filename); + return Path.Join(SubtitleCachePath, prefix, filename); } } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 80acb2c05..f69ec9744 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo private string GetAudioImagePath(Audio item) { - string filename = null; + string filename; if (item.GetType() == typeof(Audio)) { @@ -116,9 +116,9 @@ namespace MediaBrowser.Providers.MediaInfo filename = item.Id.ToString("N", CultureInfo.InvariantCulture) + ".jpg"; } - var prefix = filename.Substring(0, 1); + var prefix = filename.AsSpan().Slice(0, 1); - return Path.Combine(AudioImagesPath, prefix, filename); + return Path.Join(AudioImagesPath, prefix, filename); } public string AudioImagesPath => Path.Combine(_config.ApplicationPaths.CachePath, "extracted-audio-images"); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 944ba26af..12aecba84 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb item.SetProviderId(MetadataProvider.Imdb, result.imdbID); if (result.Year.Length > 0 - && int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) + && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) { item.ProductionYear = parsedYear; } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 9700f3b18..13098d140 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) && year >= 0) { item.ProductionYear = year; @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) && year >= 0) { item.ProductionYear = year; diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs index ced287d54..52fc53872 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs @@ -188,7 +188,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb for (var i = 0; i < episode.GuestStars.Length; ++i) { var currentActor = episode.GuestStars[i]; - var roleStartIndex = currentActor.IndexOf('('); + var roleStartIndex = currentActor.IndexOf('(', StringComparison.Ordinal); if (roleStartIndex == -1) { @@ -207,7 +207,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb for (var j = i + 1; j < episode.GuestStars.Length; ++j) { var currentRole = episode.GuestStars[j]; - var roleEndIndex = currentRole.IndexOf(')'); + var roleEndIndex = currentRole.IndexOf(')', StringComparison.Ordinal); if (roleEndIndex == -1) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index 76d3f8224..58cbf9eef 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -251,9 +251,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People private static string GetPersonDataPath(IApplicationPaths appPaths, string tmdbId) { - var letter = tmdbId.GetMD5().ToString().Substring(0, 1); + var letter = tmdbId.GetMD5().ToString().AsSpan().Slice(0, 1); - return Path.Combine(GetPersonsDataPath(appPaths), letter, tmdbId); + return Path.Join(GetPersonsDataPath(appPaths), letter, tmdbId); } internal static string GetPersonDataFilePath(IApplicationPaths appPaths, string tmdbId) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index b2d99c1a1..b06464409 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -222,8 +222,16 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (index != -1) { - var tmdbId = xml.Substring(index + srch.Length).TrimEnd('/').Split('-')[0]; - if (!string.IsNullOrWhiteSpace(tmdbId) && int.TryParse(tmdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + var tmdbId = xml.AsSpan().Slice(index + srch.Length).TrimEnd('/'); + index = tmdbId.IndexOf('-'); + if (index != -1) + { + tmdbId = tmdbId.Slice(0, index); + } + + if (!tmdbId.IsEmpty + && !tmdbId.IsWhiteSpace() + && int.TryParse(tmdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { item.SetProviderId(MetadataProvider.Tmdb, value.ToString(UsCulture)); } @@ -237,8 +245,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (index != -1) { - var tvdbId = xml.Substring(index + srch.Length).TrimEnd('/'); - if (!string.IsNullOrWhiteSpace(tvdbId) && int.TryParse(tvdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + var tvdbId = xml.AsSpan().Slice(index + srch.Length).TrimEnd('/'); + if (!tvdbId.IsEmpty + && !tvdbId.IsWhiteSpace() + && int.TryParse(tvdbId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) { item.SetProviderId(MetadataProvider.Tvdb, value.ToString(UsCulture)); } @@ -442,8 +452,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers { var val = reader.ReadElementContentAsString(); - var hasAspectRatio = item as IHasAspectRatio; - if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null) + if (!string.IsNullOrWhiteSpace(val) + && item is IHasAspectRatio hasAspectRatio) { hasAspectRatio.AspectRatio = val; } -- cgit v1.2.3 From 18efa25a6fdcfab2326cb35bb5781138a83e9d56 Mon Sep 17 00:00:00 2001 From: Bond-009 <bond.009@outlook.com> Date: Tue, 4 Aug 2020 16:20:52 +0200 Subject: Enable TreatWarningsAsErrors for MediaBrowser.MediaEncoding --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 ++ MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs | 4 ++++ .../Configuration/EncodingConfigurationFactory.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 ++ MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 1 + MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 3 +++ MediaBrowser.MediaEncoding/Probing/MediaChapter.cs | 2 ++ MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 4 ++++ MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 ++ MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 3 +++ MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs | 2 ++ MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 6 +++--- 14 files changed, 34 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index f02999370..a8ebe6bc5 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Concurrent; using System.Diagnostics; diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index ccfae2fa5..9108d9649 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -15,6 +15,10 @@ namespace MediaBrowser.MediaEncoding.BdInfo { private readonly IFileSystem _fileSystem; + /// <summary> + /// Initializes a new instance of the <see cref="BdInfoExaminer" /> class. + /// </summary> + /// <param name="fileSystem">The filesystem.</param> public BdInfoExaminer(IFileSystem fileSystem) { _fileSystem = fileSystem; diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index 75534b5bd..fea7ee6fe 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 5c43fdcfa..1ac56f845 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index d4aede572..7c2d9f1fd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.MediaInfo; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62fdbc618..0f0ae877f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index aeb4dbe73..dab5f866c 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -9,6 +9,7 @@ <TargetFramework>netstandard2.1</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <ItemGroup> diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 3aa296f7f..b2d4db894 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; namespace MediaBrowser.MediaEncoding.Probing { + /// <summary> + /// Class containing helper methods for working with FFprobe output. + /// </summary> public static class FFProbeHelpers { /// <summary> diff --git a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs index 6a45ccf49..de062d06b 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index a2ea0766a..93ef6f93e 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -269,6 +269,10 @@ namespace MediaBrowser.MediaEncoding.Probing [JsonPropertyName("loro_surmixlev")] public string LoroSurmixlev { get; set; } + /// <summary> + /// Gets or sets the field_order. + /// </summary> + /// <value>The loro_surmixlev.</value> [JsonPropertyName("field_order")] public string FieldOrder { get; set; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 0b447e3e6..8aaaf4a09 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 43a45291c..e6e21756a 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; @@ -13,6 +15,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + /// <inheritdoc /> public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var trackInfo = new SubtitleTrackInfo(); diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs index f0d107196..c0023ebf2 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.IO; using System.Threading; using MediaBrowser.Model.MediaInfo; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 2afa89cda..7c0697279 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -380,6 +380,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Converts the text subtitle to SRT. /// </summary> /// <param name="inputPath">The input path.</param> + /// <param name="language">The language.</param> /// <param name="inputProtocol">The input protocol.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> @@ -407,14 +408,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Converts the text subtitle to SRT internal. /// </summary> /// <param name="inputPath">The input path.</param> + /// <param name="language">The language.</param> /// <param name="inputProtocol">The input protocol.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException"> - /// inputPath - /// or - /// outputPath + /// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c> /// </exception> private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { -- cgit v1.2.3 From 53f99d5d4bdf3f2f5b65d53f9d84f1ea220e58e7 Mon Sep 17 00:00:00 2001 From: Bond-009 <bond.009@outlook.com> Date: Tue, 4 Aug 2020 17:08:09 +0200 Subject: Add some analyzers to MediaBrowser.MediaEncoding --- .../BdInfo/BdInfoDirectoryInfo.cs | 19 ++++-- .../BdInfo/BdInfoFileInfo.cs | 19 +++--- .../Configuration/EncodingConfigurationFactory.cs | 32 ---------- .../Configuration/EncodingConfigurationStore.cs | 38 +++++++++++ .../Encoder/EncoderValidator.cs | 30 ++++----- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 74 +++++++++++++--------- .../MediaBrowser.MediaEncoding.csproj | 12 ++++ .../Probing/ProbeResultNormalizer.cs | 65 +++++++++---------- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 18 +++--- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 14 ++-- .../Subtitles/SubtitleEncoder.cs | 58 ++++++++--------- 11 files changed, 210 insertions(+), 169 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index e040286ab..4a54b677d 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Linq; using BDInfo.IO; @@ -5,7 +7,7 @@ using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { - class BdInfoDirectoryInfo : IDirectoryInfo + public class BdInfoDirectoryInfo : IDirectoryInfo { private readonly IFileSystem _fileSystem = null; @@ -43,25 +45,32 @@ namespace MediaBrowser.MediaEncoding.BdInfo public IDirectoryInfo[] GetDirectories() { - return Array.ConvertAll(_fileSystem.GetDirectories(_impl.FullName).ToArray(), + return Array.ConvertAll( + _fileSystem.GetDirectories(_impl.FullName).ToArray(), x => new BdInfoDirectoryInfo(_fileSystem, x)); } public IFileInfo[] GetFiles() { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName).ToArray(), + return Array.ConvertAll( + _fileSystem.GetFiles(_impl.FullName).ToArray(), x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern) { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), + return Array.ConvertAll( + _fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption) { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, + return Array.ConvertAll( + _fileSystem.GetFiles( + _impl.FullName, + new[] { searchPattern }, + false, searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), x => new BdInfoFileInfo(x)); } diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs index a6ff4f767..0a8af8e9c 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -1,11 +1,18 @@ +#pragma warning disable CS1591 + using System.IO; using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { - class BdInfoFileInfo : BDInfo.IO.IFileInfo + public class BdInfoFileInfo : BDInfo.IO.IFileInfo { - FileSystemMetadata _impl = null; + private FileSystemMetadata _impl = null; + + public BdInfoFileInfo(FileSystemMetadata impl) + { + _impl = impl; + } public string Name => _impl.Name; @@ -17,14 +24,10 @@ namespace MediaBrowser.MediaEncoding.BdInfo public bool IsDir => _impl.IsDirectory; - public BdInfoFileInfo(FileSystemMetadata impl) - { - _impl = impl; - } - public System.IO.Stream OpenRead() { - return new FileStream(FullName, + return new FileStream( + FullName, FileMode.Open, FileAccess.Read, FileShare.Read); diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index fea7ee6fe..f81a337db 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -1,11 +1,7 @@ #pragma warning disable CS1591 -using System; using System.Collections.Generic; -using System.Globalization; -using System.IO; using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; namespace MediaBrowser.MediaEncoding.Configuration { @@ -19,32 +15,4 @@ namespace MediaBrowser.MediaEncoding.Configuration }; } } - - public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration - { - public EncodingConfigurationStore() - { - ConfigurationType = typeof(EncodingOptions); - Key = "encoding"; - } - - public void Validate(object oldConfig, object newConfig) - { - var newPath = ((EncodingOptions)newConfig).TranscodingTempPath; - - if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal)) - { - // Validate - if (!Directory.Exists(newPath)) - { - throw new DirectoryNotFoundException( - string.Format( - CultureInfo.InvariantCulture, - "{0} does not exist.", - newPath)); - } - } - } - } } diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs new file mode 100644 index 000000000..2f158157e --- /dev/null +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs @@ -0,0 +1,38 @@ +#pragma warning disable CS1591 + +using System; +using System.Globalization; +using System.IO; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; + +namespace MediaBrowser.MediaEncoding.Configuration +{ + public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration + { + public EncodingConfigurationStore() + { + ConfigurationType = typeof(EncodingOptions); + Key = "encoding"; + } + + public void Validate(object oldConfig, object newConfig) + { + var newPath = ((EncodingOptions)newConfig).TranscodingTempPath; + + if (!string.IsNullOrWhiteSpace(newPath) + && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal)) + { + // Validate + if (!Directory.Exists(newPath)) + { + throw new DirectoryNotFoundException( + string.Format( + CultureInfo.InvariantCulture, + "{0} does not exist.", + newPath)); + } + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 1ac56f845..75123a843 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { private const string DefaultEncoderPath = "ffmpeg"; - private static readonly string[] requiredDecoders = new[] + private static readonly string[] _requiredDecoders = new[] { "h264", "hevc", @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "vc1_opencl" }; - private static readonly string[] requiredEncoders = new[] + private static readonly string[] _requiredEncoders = new[] { "libx264", "libx265", @@ -112,6 +112,12 @@ namespace MediaBrowser.MediaEncoding.Encoder _encoderPath = encoderPath; } + private enum Codec + { + Encoder, + Decoder + } + public static Version MinVersion { get; } = new Version(4, 0); public static Version MaxVersion { get; } = null; @@ -195,8 +201,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// If that fails then we use one of the main libraries to determine if it's new/older than the latest /// we have stored. /// </summary> - /// <param name="output"></param> - /// <returns></returns> + /// <param name="output">The output from "ffmpeg -version".</param> + /// <returns>The FFmpeg version.</returns> internal static Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output @@ -218,10 +224,10 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output - /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc." + /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc.". /// </summary> - /// <param name="output"></param> - /// <returns></returns> + /// <param name="output">The 'ffmpeg -version' output.</param> + /// <returns>The library names and major.minor version numbers.</returns> private static string GetLibrariesVersionString(string output) { var rc = new StringBuilder(144); @@ -241,12 +247,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return rc.Length == 0 ? null : rc.ToString(); } - private enum Codec - { - Encoder, - Decoder - } - private IEnumerable<string> GetHwaccelTypes() { string output = null; @@ -264,7 +264,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty<string>(); } - var found = output.Split(new char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries).Skip(1).Distinct().ToList(); + var found = output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).Distinct().ToList(); _logger.LogInformation("Available hwaccel types: {Types}", found); return found; @@ -288,7 +288,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty<string>(); } - var required = codec == Codec.Encoder ? requiredEncoders : requiredDecoders; + var required = codec == Codec.Encoder ? _requiredEncoders : _requiredDecoders; var found = Regex .Matches(output, @"^\s\S{6}\s(?<codec>[\w|-]+)\s+.+$", RegexOptions.Multiline) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 0f0ae877f..62e6e8e3c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -21,9 +22,8 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; -using Microsoft.Extensions.Logging; -using System.Diagnostics; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { @@ -37,6 +37,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// </summary> internal const int DefaultImageExtractionTimeout = 5000; + /// <summary> + /// The us culture. + /// </summary> + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly ILogger<MediaEncoder> _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; @@ -49,6 +54,10 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); + private List<string> _encoders = new List<string>(); + private List<string> _decoders = new List<string>(); + private List<string> _hwaccels = new List<string>(); + private string _ffmpegPath = string.Empty; private string _ffprobePath; @@ -79,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. - /// Precedence is: Config > CLI > $PATH + /// Precedence is: Config > CLI > $PATH. /// </summary> public void SetFFmpegPath() { @@ -124,8 +133,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Triggered from the Settings > Transcoding UI page when users submits Custom FFmpeg path to use. /// Only write the new path to xml if it exists. Do not perform validation checks on ffmpeg here. /// </summary> - /// <param name="path"></param> - /// <param name="pathType"></param> + /// <param name="path">The path.</param> + /// <param name="pathType">The path type.</param> public void UpdateEncoderPath(string path, string pathType) { string newPath; @@ -170,8 +179,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. /// </summary> /// <param name="path">FQPN to test.</param> - /// <param name="location">Location (External, Custom, System) of tool</param> - /// <returns></returns> + /// <param name="location">Location (External, Custom, System) of tool.</param> + /// <returns><c>true</c> if the version validation succeeded; otherwise, <c>false</c>.</returns> private bool ValidatePath(string path, FFmpegLocation location) { bool rc = false; @@ -223,8 +232,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Search the system $PATH environment variable looking for given filename. /// </summary> - /// <param name="fileName"></param> - /// <returns></returns> + /// <param name="fileName">The filename.</param> + /// <returns>The full path to the file.</returns> private string ExistsOnSystemPath(string fileName) { var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true); @@ -248,25 +257,19 @@ namespace MediaBrowser.MediaEncoding.Encoder return null; } - private List<string> _encoders = new List<string>(); public void SetAvailableEncoders(IEnumerable<string> list) { _encoders = list.ToList(); - // _logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } - private List<string> _decoders = new List<string>(); public void SetAvailableDecoders(IEnumerable<string> list) { _decoders = list.ToList(); - // _logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } - private List<string> _hwaccels = new List<string>(); public void SetAvailableHwaccels(IEnumerable<string> list) { _hwaccels = list.ToList(); - //_logger.Info("Supported hwaccels: {0}", string.Join(",", list.ToArray())); } public bool SupportsEncoder(string encoder) @@ -334,8 +337,16 @@ namespace MediaBrowser.MediaEncoding.Encoder var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; - return GetMediaInfoInternal(GetInputArgument(inputFiles, request.MediaSource.Protocol), request.MediaSource.Path, request.MediaSource.Protocol, extractChapters, - probeSize, request.MediaType == DlnaProfileType.Audio, request.MediaSource.VideoType, forceEnableLogging, cancellationToken); + return GetMediaInfoInternal( + GetInputArgument(inputFiles, request.MediaSource.Protocol), + request.MediaSource.Path, + request.MediaSource.Protocol, + extractChapters, + probeSize, + request.MediaType == DlnaProfileType.Audio, + request.MediaSource.VideoType, + forceEnableLogging, + cancellationToken); } /// <summary> @@ -344,7 +355,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <param name="inputFiles">The input files.</param> /// <param name="protocol">The protocol.</param> /// <returns>System.String.</returns> - /// <exception cref="ArgumentException">Unrecognized InputType</exception> + /// <exception cref="ArgumentException">Unrecognized InputType.</exception> public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol) => EncodingUtils.GetInputArgument(inputFiles, protocol); @@ -352,7 +363,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets the media info internal. /// </summary> /// <returns>Task{MediaInfoResult}.</returns> - private async Task<MediaInfo> GetMediaInfoInternal(string inputPath, + private async Task<MediaInfo> GetMediaInfoInternal( + string inputPath, string primaryPath, MediaProtocol protocol, bool extractChapters, @@ -380,7 +392,6 @@ namespace MediaBrowser.MediaEncoding.Encoder FileName = _ffprobePath, Arguments = args, - WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, }, @@ -441,11 +452,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - /// <summary> - /// The us culture. - /// </summary> - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) { return ExtractImage(new[] { path }, null, null, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken); @@ -461,8 +467,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, protocol, false, null, null, cancellationToken); } - private async Task<string> ExtractImage(string[] inputFiles, string container, MediaStream videoStream, int? imageStreamIndex, MediaProtocol protocol, bool isAudio, - Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) + private async Task<string> ExtractImage( + string[] inputFiles, + string container, + MediaStream videoStream, + int? imageStreamIndex, + MediaProtocol protocol, + bool isAudio, + Video3DFormat? threedFormat, + TimeSpan? offset, + CancellationToken cancellationToken) { var inputArgument = GetInputArgument(inputFiles, protocol); @@ -647,7 +661,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetTimeParameter(TimeSpan time) { - return time.ToString(@"hh\:mm\:ss\.fff", UsCulture); + return time.ToString(@"hh\:mm\:ss\.fff", _usCulture); } public async Task ExtractVideoImagesOnInterval( @@ -664,11 +678,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { var inputArgument = GetInputArgument(inputFiles, protocol); - var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture); + var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); if (maxWidth.HasValue) { - var maxWidthParam = maxWidth.Value.ToString(UsCulture); + var maxWidthParam = maxWidth.Value.ToString(_usCulture); vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index dab5f866c..017f917e2 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -28,4 +28,16 @@ <PackageReference Include="UTF.Unknown" Version="2.3.0" /> </ItemGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <!-- 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> + </Project> diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 8aaaf4a09..19e3bd8e6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -18,10 +18,19 @@ namespace MediaBrowser.MediaEncoding.Probing { public class ProbeResultNormalizer { + // When extracting subtitles, the maximum length to consider (to avoid invalid filenames) + private const int MaxSubtitleDescriptionExtractionLength = 100; + + private const string ArtistReplaceValue = " | "; + + private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; + private List<string> _splitWhiteList = null; + public ProbeResultNormalizer(ILogger logger, ILocalizationManager localization) { _logger = logger; @@ -370,7 +379,6 @@ namespace MediaBrowser.MediaEncoding.Probing private List<NameValuePair> ReadValueArray(XmlReader reader) { - var pairs = new List<NameValuePair>(); reader.MoveToContent(); @@ -951,50 +959,46 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags) { + var peoples = new List<BaseItemPerson>(); var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); if (!string.IsNullOrWhiteSpace(composer)) { - var peoples = new List<BaseItemPerson>(); foreach (var person in Split(composer, false)) { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer }); } - - audio.People = peoples.ToArray(); } - // var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); - // if (!string.IsNullOrWhiteSpace(conductor)) - //{ - // foreach (var person in Split(conductor, false)) - // { - // audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); - // } - //} + var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); + if (!string.IsNullOrWhiteSpace(conductor)) + { + foreach (var person in Split(conductor, false)) + { + peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); + } + } - // var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); - // if (!string.IsNullOrWhiteSpace(lyricist)) - //{ - // foreach (var person in Split(lyricist, false)) - // { - // audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); - // } - //} + var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); + if (!string.IsNullOrWhiteSpace(lyricist)) + { + foreach (var person in Split(lyricist, false)) + { + peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); + } + } // Check for writer some music is tagged that way as alternative to composer/lyricist var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); if (!string.IsNullOrWhiteSpace(writer)) { - var peoples = new List<BaseItemPerson>(); foreach (var person in Split(writer, false)) { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer }); } - - audio.People = peoples.ToArray(); } + audio.People = peoples.ToArray(); audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); @@ -1119,8 +1123,6 @@ namespace MediaBrowser.MediaEncoding.Probing .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } - private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; - /// <summary> /// Splits the specified val. /// </summary> @@ -1140,8 +1142,6 @@ namespace MediaBrowser.MediaEncoding.Probing .Select(i => i.Trim()); } - private const string ArtistReplaceValue = " | "; - private IEnumerable<string> SplitArtists(string val, char[] delimiters, bool splitFeaturing) { if (splitFeaturing) @@ -1171,9 +1171,6 @@ namespace MediaBrowser.MediaEncoding.Probing return artistsFound; } - - private List<string> _splitWhiteList = null; - private IEnumerable<string> GetSplitWhitelist() { if (_splitWhiteList == null) @@ -1250,7 +1247,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// <summary> - /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3' + /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'. /// </summary> /// <param name="tags">The tags.</param> /// <param name="tagName">Name of the tag.</param> @@ -1296,8 +1293,6 @@ namespace MediaBrowser.MediaEncoding.Probing return info; } - private const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames) - private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) { if (data.Format == null || data.Format.Tags == null) @@ -1382,8 +1377,8 @@ namespace MediaBrowser.MediaEncoding.Probing if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number { string[] numbers = subtitle.Split(' '); - video.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]); - int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", "").Split('/')[1]); + 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]); description = string.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it } diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index e6e21756a..308b62886 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -25,7 +25,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string line; while (reader.ReadLine() != "[Events]") - { } + { + } var headers = ParseFieldHeaders(reader.ReadLine()); @@ -75,17 +76,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles { var fields = line.Substring(8).Split(',').Select(x => x.Trim()).ToList(); - var result = new Dictionary<string, int> { - {"Start", fields.IndexOf("Start")}, - {"End", fields.IndexOf("End")}, - {"Text", fields.IndexOf("Text")} - }; - return result; + return new Dictionary<string, int> + { + { "Start", fields.IndexOf("Start") }, + { "End", fields.IndexOf("End") }, + { "Text", fields.IndexOf("Text") } + }; } - /// <summary> - /// Credit: https://github.com/SubtitleEdit/subtitleedit/blob/master/src/Logic/SubtitleFormats/AdvancedSubStationAlpha.cs - /// </summary> private void RemoteNativeFormatting(SubtitleTrackEvent p) { int indexOfBegin = p.Text.IndexOf('{'); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index bd330f568..6b7a81e6e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { /// <summary> - /// Credit to https://github.com/SubtitleEdit/subtitleedit/blob/a299dc4407a31796364cc6ad83f0d3786194ba22/src/Logic/SubtitleFormats/SubStationAlpha.cs + /// <see href="https://github.com/SubtitleEdit/subtitleedit/blob/a299dc4407a31796364cc6ad83f0d3786194ba22/src/Logic/SubtitleFormats/SubStationAlpha.cs">Credit</see>. /// </summary> public class SsaParser : ISubtitleParser { @@ -179,10 +179,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { // h:mm:ss.cc string[] timeCode = time.Split(':', '.'); - return new TimeSpan(0, int.Parse(timeCode[0]), - int.Parse(timeCode[1]), - int.Parse(timeCode[2]), - int.Parse(timeCode[3]) * 10).Ticks; + return new TimeSpan( + 0, + int.Parse(timeCode[0]), + int.Parse(timeCode[1]), + int.Parse(timeCode[2]), + int.Parse(timeCode[3]) * 10).Ticks; } private static string GetFormattedText(string text) @@ -282,6 +284,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); } + int indexOfEndTag = text.IndexOf("{\\c}", start); if (indexOfEndTag > 0) { @@ -320,6 +323,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); } + text += "</font>"; } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 7c0697279..374e35b96 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -34,6 +34,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; + /// <summary> + /// The _semaphoreLocks. + /// </summary> + private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks = + new ConcurrentDictionary<string, SemaphoreSlim>(); + public SubtitleEncoder( ILibraryManager libraryManager, ILogger<SubtitleEncoder> logger, @@ -269,25 +275,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new SubtitleInfo(subtitleStream.Path, protocol, currentFormat, true); } - private struct SubtitleInfo - { - public SubtitleInfo(string path, MediaProtocol protocol, string format, bool isExternal) - { - Path = path; - Protocol = protocol; - Format = format; - IsExternal = isExternal; - } - - public string Path { get; set; } - - public MediaProtocol Protocol { get; set; } - - public string Format { get; set; } - - public bool IsExternal { get; set; } - } - private ISubtitleParser GetReader(string format, bool throwIfMissing) { if (string.IsNullOrEmpty(format)) @@ -360,12 +347,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentException("Unsupported format: " + format); } - /// <summary> - /// The _semaphoreLocks. - /// </summary> - private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks = - new ConcurrentDictionary<string, SemaphoreSlim>(); - /// <summary> /// Gets the lock. /// </summary> @@ -414,7 +395,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException"> - /// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c> + /// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c>. /// </exception> private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { @@ -438,7 +419,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles (encodingParam.Equals("UTF-16BE", StringComparison.OrdinalIgnoreCase) || encodingParam.Equals("UTF-16LE", StringComparison.OrdinalIgnoreCase))) { - encodingParam = ""; + encodingParam = string.Empty; } else if (!string.IsNullOrEmpty(encodingParam)) { @@ -540,7 +521,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - /// <exception cref="ArgumentException">Must use inputPath list overload</exception> + /// <exception cref="ArgumentException">Must use inputPath list overload.</exception> private async Task ExtractTextSubtitle( string[] inputFiles, MediaProtocol protocol, @@ -759,7 +740,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase) || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase))) { - charset = ""; + charset = string.Empty; } _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); @@ -790,5 +771,24 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentOutOfRangeException(nameof(protocol)); } } + + private struct SubtitleInfo + { + public SubtitleInfo(string path, MediaProtocol protocol, string format, bool isExternal) + { + Path = path; + Protocol = protocol; + Format = format; + IsExternal = isExternal; + } + + public string Path { get; set; } + + public MediaProtocol Protocol { get; set; } + + public string Format { get; set; } + + public bool IsExternal { get; set; } + } } } -- cgit v1.2.3 From d9f6953416ace083e7356cdc20ab4a1bd91f09cd Mon Sep 17 00:00:00 2001 From: Bond-009 <bond.009@outlook.com> Date: Tue, 4 Aug 2020 17:14:07 +0200 Subject: Minor fixes --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62e6e8e3c..778c0b18c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -875,6 +875,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (dispose) { StopProcesses(); + _thumbnailResourcePool.Dispose(); } } diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 93ef6f93e..8996d3b09 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -272,7 +272,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// <summary> /// Gets or sets the field_order. /// </summary> - /// <value>The loro_surmixlev.</value> + /// <value>The field_order.</value> [JsonPropertyName("field_order")] public string FieldOrder { get; set; } -- cgit v1.2.3 From 2b400c99ef946ef1e52e3f01cb18bc008a369c59 Mon Sep 17 00:00:00 2001 From: Bond_009 <Bond.009@outlook.com> Date: Fri, 7 Aug 2020 19:26:28 +0200 Subject: Fix warnings --- Emby.Dlna/DlnaManager.cs | 12 +-- Emby.Dlna/PlayTo/Device.cs | 36 ++++--- Emby.Dlna/PlayTo/TransportCommands.cs | 17 ++-- .../Data/SqliteItemRepository.cs | 4 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 5 +- .../LiveTv/LiveTvManager.cs | 106 +++++++++++---------- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 16 ++-- Jellyfin.Api/Controllers/ImageController.cs | 2 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 4 +- MediaBrowser.Controller/Entities/TV/Series.cs | 2 +- MediaBrowser.Controller/Entities/Trailer.cs | 3 +- MediaBrowser.Controller/Library/Profiler.cs | 17 +++- MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 2 +- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 8 +- .../Providers/IProviderManager.cs | 2 +- .../Encoder/EncodingUtils.cs | 9 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 14 +-- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 2 +- MediaBrowser.Model/Dlna/DlnaMaps.cs | 8 +- .../Dlna/MediaFormatProfileResolver.cs | 21 ++-- MediaBrowser.Model/Dlna/StreamInfo.cs | 12 +-- MediaBrowser.Providers/Manager/ImageSaver.cs | 4 +- .../Manager/ItemImageProvider.cs | 57 +++++------ MediaBrowser.Providers/Manager/MetadataService.cs | 73 +++++++------- MediaBrowser.Providers/Manager/ProviderManager.cs | 37 +++++-- .../MediaInfo/FFProbeAudioInfo.cs | 15 +-- .../MediaInfo/FFProbeProvider.cs | 21 +--- MediaBrowser.Providers/Music/Extensions.cs | 4 +- .../Plugins/MusicBrainz/AlbumProvider.cs | 2 +- .../Plugins/MusicBrainz/ArtistProvider.cs | 4 +- .../Plugins/Omdb/OmdbImageProvider.cs | 3 +- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 25 +++-- .../Plugins/TheTvdb/TvdbClientManager.cs | 31 ++---- .../Plugins/TheTvdb/TvdbEpisodeImageProvider.cs | 7 +- .../Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 4 +- .../Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs | 2 +- .../Plugins/Tmdb/Movies/TmdbSearch.cs | 54 +++++++++-- .../Plugins/Tmdb/TV/TmdbEpisodeProvider.cs | 2 +- .../Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 4 +- .../Plugins/Tmdb/TV/TmdbSeriesProvider.cs | 2 +- .../Studios/StudiosImageProvider.cs | 3 +- 46 files changed, 366 insertions(+), 302 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 269f7ee43..ce4be7b51 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -54,11 +54,15 @@ namespace Emby.Dlna _appHost = appHost; } + private string UserProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user"); + + private string SystemProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system"); + public async Task InitProfilesAsync() { try { - await ExtractSystemProfilesAsync(); + await ExtractSystemProfilesAsync().ConfigureAwait(false); LoadProfiles(); } catch (Exception ex) @@ -240,7 +244,7 @@ namespace Emby.Dlna } else { - var headerString = string.Join(", ", headers.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray()); + var headerString = string.Join(", ", headers.Select(i => string.Format(CultureInfo.InvariantCulture, "{0}={1}", i.Key, i.Value))); _logger.LogDebug("No matching device profile found. {0}", headerString); } @@ -280,10 +284,6 @@ namespace Emby.Dlna return false; } - private string UserProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "user"); - - private string SystemProfilesPath => Path.Combine(_appPaths.ConfigurationDirectoryPath, "dlna", "system"); - private IEnumerable<DeviceProfile> GetProfiles(string path, DeviceProfileType type) { try diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 72834c69d..86dd52a1b 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -19,6 +19,8 @@ namespace Emby.Dlna.PlayTo { public class Device : IDisposable { + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + private Timer _timer; public DeviceInfo Properties { get; set; } @@ -55,16 +57,13 @@ namespace Emby.Dlna.PlayTo private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - public Action OnDeviceUnavailable { get; set; } - public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger, IServerConfigurationManager config) + public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger) { Properties = deviceProperties; _httpClient = httpClient; _logger = logger; - _config = config; } public void Start() @@ -275,7 +274,7 @@ namespace Emby.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) + await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) .ConfigureAwait(false); RestartTimer(true); @@ -285,7 +284,7 @@ namespace Emby.Dlna.PlayTo { var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false); - url = url.Replace("&", "&"); + url = url.Replace("&", "&", StringComparison.Ordinal); _logger.LogDebug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", Properties.Name, url, header); @@ -297,8 +296,8 @@ namespace Emby.Dlna.PlayTo var dictionary = new Dictionary<string, string> { - {"CurrentURI", url}, - {"CurrentURIMetaData", CreateDidlMeta(metaData)} + { "CurrentURI", url }, + { "CurrentURIMetaData", CreateDidlMeta(metaData) } }; var service = GetAvTransportService(); @@ -732,10 +731,10 @@ namespace Emby.Dlna.PlayTo } var trackUriElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null); - var trackUri = trackUriElem == null ? null : trackUriElem.Value; + var trackUri = trackUriElem?.Value; var durationElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null); - var duration = durationElem == null ? null : durationElem.Value; + var duration = durationElem?.Value; if (!string.IsNullOrWhiteSpace(duration) && !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) @@ -748,7 +747,7 @@ namespace Emby.Dlna.PlayTo } var positionElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null); - var position = positionElem == null ? null : positionElem.Value; + var position = positionElem?.Value; if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { @@ -819,7 +818,7 @@ namespace Emby.Dlna.PlayTo // some devices send back invalid xml try { - return XElement.Parse(xml.Replace("&", "&")); + return XElement.Parse(xml.Replace("&", "&", StringComparison.Ordinal)); } catch (XmlException) { @@ -848,7 +847,7 @@ namespace Emby.Dlna.PlayTo ParentId = container.GetAttributeValue(uPnpNamespaces.ParentId), Title = container.GetValue(uPnpNamespaces.title), IconUrl = container.GetValue(uPnpNamespaces.Artwork), - SecondText = "", + SecondText = string.Empty, Url = url, ProtocolInfo = GetProtocolInfo(container), MetaData = container.ToString() @@ -941,12 +940,12 @@ namespace Emby.Dlna.PlayTo return url; } - if (!url.Contains("/")) + if (!url.Contains('/', StringComparison.Ordinal)) { url = "/dmr/" + url; } - if (!url.StartsWith("/")) + if (!url.StartsWith("/", StringComparison.Ordinal)) { url = "/" + url; } @@ -981,7 +980,7 @@ namespace Emby.Dlna.PlayTo var deviceProperties = new DeviceInfo() { Name = string.Join(" ", friendlyNames), - BaseUrl = string.Format("http://{0}:{1}", url.Host, url.Port) + BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port) }; var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault(); @@ -1068,10 +1067,9 @@ namespace Emby.Dlna.PlayTo } } - return new Device(deviceProperties, httpClient, logger, config); + return new Device(deviceProperties, httpClient, logger); } - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static DeviceIcon CreateIcon(XElement element) { if (element == null) @@ -1222,7 +1220,7 @@ namespace Emby.Dlna.PlayTo public override string ToString() { - return string.Format("{0} - {1}", Properties.Name, Properties.BaseUrl); + return string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Properties.Name, Properties.BaseUrl); } } } diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index c0ce3ab6e..dc797a691 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Xml.Linq; using Emby.Dlna.Common; @@ -11,14 +12,16 @@ namespace Emby.Dlna.PlayTo { public class TransportCommands { + private const string CommandBase = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "<SOAP-ENV:Body>" + "<m:{0} xmlns:m=\"{1}\">" + "{2}" + "</m:{0}>" + "</SOAP-ENV:Body></SOAP-ENV:Envelope>"; private List<StateVariable> _stateVariables = new List<StateVariable>(); + private List<ServiceAction> _serviceActions = new List<ServiceAction>(); + public List<StateVariable> StateVariables { get => _stateVariables; set => _stateVariables = value; } - private List<ServiceAction> _serviceActions = new List<ServiceAction>(); public List<ServiceAction> ServiceActions { get => _serviceActions; @@ -123,7 +126,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamespace, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamespace, stateString); } public string BuildPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "") @@ -147,7 +150,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); } public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary<string, string> dictionary) @@ -170,7 +173,7 @@ namespace Emby.Dlna.PlayTo } } - return string.Format(CommandBase, action.Name, xmlNamesapce, stateString); + return string.Format(CultureInfo.InvariantCulture, CommandBase, action.Name, xmlNamesapce, stateString); } private string BuildArgumentXml(Argument argument, string value, string commandParameter = "") @@ -183,12 +186,10 @@ namespace Emby.Dlna.PlayTo state.AllowedValues.FirstOrDefault() ?? value; - return string.Format("<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue); + return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue); } - return string.Format("<{0}>{1}</{0}>", argument.Name, value); + return string.Format(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", argument.Name, value); } - - private const string CommandBase = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + "<SOAP-ENV:Body>" + "<m:{0} xmlns:m=\"{1}\">" + "{2}" + "</m:{0}>" + "</SOAP-ENV:Body></SOAP-ENV:Envelope>"; } } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d11e5e62e..331ffc134 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4560,13 +4560,13 @@ namespace Emby.Server.Implementations.Data if (query.AncestorIds.Length > 1) { var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); + whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) { var inClause = "select guid from TypedBaseItems where PresentationUniqueKey=@AncestorWithPresentationUniqueKey"; - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); + whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); if (statement != null) { statement.TryBind("@AncestorWithPresentationUniqueKey", query.AncestorWithPresentationUniqueKey); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index d8ec107ec..612dc5238 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -230,7 +230,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (filters.Count > 0) { - output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); + output += string.Format(CultureInfo.InvariantCulture, " -vf \"{0}\"", string.Join(",", filters.ToArray())); } return output; diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 0a93c4674..f33d07174 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings && !programInfo.IsRepeat && (programInfo.EpisodeNumber ?? 0) == 0) { - programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); + programInfo.ShowId += programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture); } } else @@ -246,7 +246,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings } // Construct an id from the channel and start date - programInfo.Id = string.Format("{0}_{1:O}", program.ChannelId, program.StartDate); + programInfo.Id = string.Format(CultureInfo.InvariantCulture, "{0}_{1:O}", program.ChannelId, program.StartDate); if (programInfo.IsMovie) { @@ -296,7 +296,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings Name = c.DisplayName, ImageUrl = c.Icon != null && !string.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null, Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number - }).ToList(); } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1b075d86a..90cbd85a5 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -41,6 +41,7 @@ namespace Emby.Server.Implementations.LiveTv /// </summary> public class LiveTvManager : ILiveTvManager, IDisposable { + private const int MaxGuideDays = 14; private const string ExternalServiceTag = "ExternalServiceId"; private const string EtagKey = "ProgramEtag"; @@ -560,7 +561,7 @@ namespace Emby.Server.Implementations.LiveTv item.Audio = info.Audio; item.ChannelId = channel.Id; - item.CommunityRating = item.CommunityRating ?? info.CommunityRating; + item.CommunityRating ??= info.CommunityRating; if ((item.CommunityRating ?? 0).Equals(0)) { item.CommunityRating = null; @@ -645,8 +646,8 @@ namespace Emby.Server.Implementations.LiveTv item.IsSeries = isSeries; item.Name = info.Name; - item.OfficialRating = item.OfficialRating ?? info.OfficialRating; - item.Overview = item.Overview ?? info.Overview; + item.OfficialRating ??= info.OfficialRating; + item.Overview ??= info.Overview; item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; item.ProviderIds = info.ProviderIds; @@ -683,19 +684,23 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.ImagePath)) { - item.SetImage(new ItemImageInfo - { - Path = info.ImagePath, - Type = ImageType.Primary - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ImagePath, + Type = ImageType.Primary + }, + 0); } else if (!string.IsNullOrWhiteSpace(info.ImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.ImageUrl, - Type = ImageType.Primary - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ImageUrl, + Type = ImageType.Primary + }, + 0); } } @@ -703,11 +708,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.ThumbImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.ThumbImageUrl, - Type = ImageType.Thumb - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.ThumbImageUrl, + Type = ImageType.Thumb + }, + 0); } } @@ -715,11 +722,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.LogoImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.LogoImageUrl, - Type = ImageType.Logo - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.LogoImageUrl, + Type = ImageType.Logo + }, + 0); } } @@ -727,11 +736,13 @@ namespace Emby.Server.Implementations.LiveTv { if (!string.IsNullOrWhiteSpace(info.BackdropImageUrl)) { - item.SetImage(new ItemImageInfo - { - Path = info.BackdropImageUrl, - Type = ImageType.Backdrop - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = info.BackdropImageUrl, + Type = ImageType.Backdrop + }, + 0); } } @@ -786,7 +797,6 @@ namespace Emby.Server.Implementations.LiveTv if (query.OrderBy.Count == 0) { - // Unless something else was specified, order by start date to take advantage of a specialized index query.OrderBy = new[] { @@ -824,7 +834,7 @@ namespace Emby.Server.Implementations.LiveTv if (!string.IsNullOrWhiteSpace(query.SeriesTimerId)) { - var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery { }, cancellationToken).ConfigureAwait(false); + var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false); var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.Id).ToString("N", CultureInfo.InvariantCulture), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase)); if (seriesTimer != null) { @@ -847,13 +857,11 @@ namespace Emby.Server.Implementations.LiveTv var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user); - var result = new QueryResult<BaseItemDto> + return new QueryResult<BaseItemDto> { Items = returnArray, TotalRecordCount = queryResult.TotalRecordCount }; - - return result; } public QueryResult<BaseItem> GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken) @@ -1173,7 +1181,6 @@ namespace Emby.Server.Implementations.LiveTv var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery { - IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, ChannelIds = new Guid[] { currentChannel.Id }, DtoOptions = new DtoOptions(true) @@ -1298,8 +1305,6 @@ namespace Emby.Server.Implementations.LiveTv } } - private const int MaxGuideDays = 14; - private double GetGuideDays() { var config = GetConfiguration(); @@ -1712,7 +1717,7 @@ namespace Emby.Server.Implementations.LiveTv if (timer == null) { - throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); + throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "Timer with Id {0} not found", id)); } var service = GetService(timer.ServiceName); @@ -1731,7 +1736,7 @@ namespace Emby.Server.Implementations.LiveTv if (timer == null) { - throw new ResourceNotFoundException(string.Format("SeriesTimer with Id {0} not found", id)); + throw new ResourceNotFoundException(string.Format(CultureInfo.InvariantCulture, "SeriesTimer with Id {0} not found", id)); } var service = GetService(timer.ServiceName); @@ -1743,10 +1748,12 @@ namespace Emby.Server.Implementations.LiveTv public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken) { - var results = await GetTimers(new TimerQuery - { - Id = id - }, cancellationToken).ConfigureAwait(false); + var results = await GetTimers( + new TimerQuery + { + Id = id + }, + cancellationToken).ConfigureAwait(false); return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); } @@ -1794,10 +1801,7 @@ namespace Emby.Server.Implementations.LiveTv } var returnArray = timers - .Select(i => - { - return i.Item1; - }) + .Select(i => i.Item1) .ToArray(); return new QueryResult<SeriesTimerInfo> @@ -1968,7 +1972,7 @@ namespace Emby.Server.Implementations.LiveTv if (service == null) { - service = _services.First(); + service = _services[0]; } var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); @@ -1994,9 +1998,7 @@ namespace Emby.Server.Implementations.LiveTv { var info = await GetNewTimerDefaultsInternal(cancellationToken).ConfigureAwait(false); - var obj = _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null); - - return obj; + return _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null); } public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken) @@ -2125,6 +2127,7 @@ namespace Emby.Server.Implementations.LiveTv public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } private bool _disposed = false; @@ -2447,8 +2450,7 @@ namespace Emby.Server.Implementations.LiveTv .SelectMany(i => i.Locations) .Distinct(StringComparer.OrdinalIgnoreCase) .Select(i => _libraryManager.FindByPath(i, true)) - .Where(i => i != null) - .Where(i => i.IsVisibleStandalone(user)) + .Where(i => i != null && i.IsVisibleStandalone(user)) .SelectMany(i => _libraryManager.GetCollectionFolders(i)) .GroupBy(x => x.Id) .Select(x => x.First()) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c61189c0a..f1e120a64 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -182,12 +182,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - using (var response = await _httpClient.SendAsync(new HttpRequestOptions() - { - Url = string.Format("{0}/tuners.html", GetApiUrl(info)), - CancellationToken = cancellationToken, - BufferContent = false - }, HttpMethod.Get).ConfigureAwait(false)) + using (var response = await _httpClient.SendAsync( + new HttpRequestOptions() + { + Url = string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), + CancellationToken = cancellationToken, + BufferContent = false + }, + HttpMethod.Get).ConfigureAwait(false)) using (var stream = response.Content) using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) { @@ -730,7 +732,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Need a way to set the Receive timeout on the socket otherwise this might never timeout? try { - await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken); + await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken).ConfigureAwait(false); var receiveBuffer = new byte[8192]; while (!cancellationToken.IsCancellationRequested) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 8f5c6beb3..75734f0af 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Controllers user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); await _providerManager - .SaveImage(user, memoryStream, mimeType, user.ProfileImage.Path) + .SaveImage(memoryStream, mimeType, user.ProfileImage.Path) .ConfigureAwait(false); await _userManager.UpdateUserAsync(user).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 53badac4d..5ae396e68 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -1,5 +1,7 @@ + using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.Json.Serialization; using System.Threading; @@ -179,7 +181,7 @@ namespace MediaBrowser.Controller.Entities.Movies list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 45daa8a53..23d960092 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -496,7 +496,7 @@ namespace MediaBrowser.Controller.Entities.TV list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/shows/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/shows/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 6b544afc6..83e9ce1e7 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Providers; @@ -86,7 +87,7 @@ namespace MediaBrowser.Controller.Entities list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } diff --git a/MediaBrowser.Controller/Library/Profiler.cs b/MediaBrowser.Controller/Library/Profiler.cs index 399378a09..5efdc6a48 100644 --- a/MediaBrowser.Controller/Library/Profiler.cs +++ b/MediaBrowser.Controller/Library/Profiler.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Library @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Library /// The name. /// </summary> readonly string _name; + /// <summary> /// The stopwatch. /// </summary> @@ -44,6 +46,7 @@ namespace MediaBrowser.Controller.Library public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// <summary> @@ -58,13 +61,19 @@ namespace MediaBrowser.Controller.Library string message; if (_stopwatch.ElapsedMilliseconds > 300000) { - message = string.Format("{0} took {1} minutes.", - _name, ((float)_stopwatch.ElapsedMilliseconds / 60000).ToString("F")); + message = string.Format( + CultureInfo.InvariantCulture, + "{0} took {1} minutes.", + _name, + ((float)_stopwatch.ElapsedMilliseconds / 60000).ToString("F", CultureInfo.InvariantCulture)); } else { - message = string.Format("{0} took {1} seconds.", - _name, ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000")); + message = string.Format( + CultureInfo.InvariantCulture, + "{0} took {1} seconds.", + _name, + ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000", CultureInfo.InvariantCulture)); } _logger.LogInformation(message); diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 10af98121..aa7c12dd1 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Controller.LiveTv if (double.TryParse(Number, NumberStyles.Any, CultureInfo.InvariantCulture, out number)) { - return string.Format("{0:00000.0}", number) + "-" + (Name ?? string.Empty); + return string.Format(CultureInfo.InvariantCulture, "{0:00000.0}", number) + "-" + (Name ?? string.Empty); } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 472b061e6..e1de01ff0 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -261,7 +261,7 @@ namespace MediaBrowser.Controller.LiveTv list.Add(new ExternalUrl { Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://trakt.tv/movies/{0}", imdbId) }); } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 2dd21be3c..7b09f489e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -675,7 +675,7 @@ namespace MediaBrowser.Controller.MediaEncoding // } // } - // fallbackFontParam = string.Format(":force_style='FontName=Droid Sans Fallback':fontsdir='{0}'", _mediaEncoder.EscapeSubtitleFilterPath(_fileSystem.GetDirectoryName(fallbackFontPath))); + // fallbackFontParam = string.Format(CultureInfo.InvariantCulture, ":force_style='FontName=Droid Sans Fallback':fontsdir='{0}'", _mediaEncoder.EscapeSubtitleFilterPath(_fileSystem.GetDirectoryName(fallbackFontPath))); if (state.SubtitleStream.IsExternal) { @@ -880,7 +880,7 @@ namespace MediaBrowser.Controller.MediaEncoding profileScore = Math.Min(profileScore, 2); // http://www.webmproject.org/docs/encoder-parameters/ - param += string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", + param += string.Format(CultureInfo.InvariantCulture, "-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", profileScore.ToString(_usCulture), crf, qmin, @@ -904,7 +904,7 @@ namespace MediaBrowser.Controller.MediaEncoding var framerate = GetFramerateParam(state); if (framerate.HasValue) { - param += string.Format(" -r {0}", framerate.Value.ToString(_usCulture)); + param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(_usCulture)); } var targetVideoCodec = state.ActualOutputVideoCodec; @@ -1484,7 +1484,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (time > 0) { - return string.Format("-ss {0}", _mediaEncoder.GetTimeParameter(time)); + return string.Format(CultureInfo.InvariantCulture, "-ss {0}", _mediaEncoder.GetTimeParameter(time)); } return string.Empty; diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 8ba01d773..c77349d01 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Controller.Providers /// <returns>Task.</returns> Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken); - Task SaveImage(User user, Stream source, string mimeType, string path); + Task SaveImage(Stream source, string mimeType, string path); /// <summary> /// Adds the metadata providers. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 7c2d9f1fd..082ae2888 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.Collections.Generic; +using System.Globalization; using System.Linq; using MediaBrowser.Model.MediaInfo; @@ -14,7 +15,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var url = inputFiles[0]; - return string.Format("\"{0}\"", url); + return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", url); } return GetConcatInputArgument(inputFiles); @@ -33,7 +34,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var files = string.Join("|", inputFiles.Select(NormalizePath)); - return string.Format("concat:\"{0}\"", files); + return string.Format(CultureInfo.InvariantCulture, "concat:\"{0}\"", files); } // Determine the input path for video files @@ -49,13 +50,13 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (path.IndexOf("://") != -1) { - return string.Format("\"{0}\"", path); + return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path); } // Quotes are valid path characters in linux and they need to be escaped here with a leading \ path = NormalizePath(path); - return string.Format("file:\"{0}\"", path); + return string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", path); } /// <summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 778c0b18c..b9a6432ad 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -552,8 +552,8 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; - var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : - string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); + var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : + string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -570,7 +570,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (offset.HasValue) { - args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args; + args = string.Format(CultureInfo.InvariantCulture, "-ss {0} ", GetTimeParameter(offset.Value)) + args; } if (videoStream != null) @@ -641,7 +641,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (exitCode == -1 || !file.Exists || file.Length == 0) { - var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath); + var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputPath); _logger.LogError(msg); @@ -684,13 +684,13 @@ namespace MediaBrowser.MediaEncoding.Encoder { var maxWidthParam = maxWidth.Value.ToString(_usCulture); - vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); + vf += string.Format(CultureInfo.InvariantCulture, ",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -790,7 +790,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (exitCode == -1) { - var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument); + var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputArgument); _logger.LogError(msg); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 374e35b96..fbe8bd69f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -435,7 +435,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + Arguments = string.Format(CultureInfo.InvariantCulture, "{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false }, diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index a579f8464..93e60753a 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Model.Dlna // flagValue = flagValue | DlnaFlags.TimeBasedSeek; //} - string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}", + string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", DlnaMaps.FlagsToString(flagValue)); ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(container, diff --git a/MediaBrowser.Model/Dlna/DlnaMaps.cs b/MediaBrowser.Model/Dlna/DlnaMaps.cs index 052b4b78b..95cd0ac27 100644 --- a/MediaBrowser.Model/Dlna/DlnaMaps.cs +++ b/MediaBrowser.Model/Dlna/DlnaMaps.cs @@ -1,18 +1,20 @@ #pragma warning disable CS1591 +using System.Globalization; + namespace MediaBrowser.Model.Dlna { public static class DlnaMaps { private static readonly string DefaultStreaming = - FlagsToString(DlnaFlags.StreamingTransferMode | + FlagsToString(DlnaFlags.StreamingTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.ConnectionStall | DlnaFlags.ByteBasedSeek | DlnaFlags.DlnaV15); private static readonly string DefaultInteractive = - FlagsToString(DlnaFlags.InteractiveTransferMode | + FlagsToString(DlnaFlags.InteractiveTransferMode | DlnaFlags.BackgroundTransferMode | DlnaFlags.ConnectionStall | DlnaFlags.ByteBasedSeek | @@ -20,7 +22,7 @@ namespace MediaBrowser.Model.Dlna public static string FlagsToString(DlnaFlags flags) { - return string.Format("{0:X8}{1:D24}", (ulong)flags, 0); + return string.Format(CultureInfo.InvariantCulture, "{0:X8}{1:D24}", (ulong)flags, 0); } public static string GetOrgOpValue(bool hasKnownRuntime, bool isDirectStream, TranscodeSeekInfo profileTranscodeSeekInfo) diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index bdc5f8bb7..3c955989a 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using MediaBrowser.Model.MediaInfo; @@ -142,26 +143,26 @@ namespace MediaBrowser.Model.Dlna { if (timestampType == TransportStreamTimestamp.None) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_HP_{0}D_MPEG1_L2_ISO", resolution)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_HP_{0}D_MPEG1_L2_ISO", resolution)) }; } - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_HP_{0}D_MPEG1_L2_T", resolution)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_HP_{0}D_MPEG1_L2_T", resolution)) }; } if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_AAC_MULT5{1}", resolution, suffix)) }; } if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_MPEG1_L3{1}", resolution, suffix)) }; } if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "AVC_TS_MP_{0}D_AC3{1}", resolution, suffix)) }; } } else if (string.Equals(videoCodec, "vc1", StringComparison.OrdinalIgnoreCase)) @@ -180,29 +181,29 @@ namespace MediaBrowser.Model.Dlna { suffix = string.Equals(suffix, "_ISO", StringComparison.OrdinalIgnoreCase) ? suffix : "_T"; - return new MediaFormatProfile[] { ValueOf(string.Format("VC1_TS_HD_DTS{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "VC1_TS_HD_DTS{0}", suffix)) }; } } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; } if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; } if (string.Equals(audioCodec, "mp2", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; } if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) { - return new MediaFormatProfile[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; + return new MediaFormatProfile[] { ValueOf(string.Format(CultureInfo.InvariantCulture, "MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 204340c46..94d53ab70 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -191,7 +191,7 @@ namespace MediaBrowser.Model.Dlna var encodedValue = pair.Value.Replace(" ", "%20"); - list.Add(string.Format("{0}={1}", pair.Name, encodedValue)); + list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } string queryString = string.Join("&", list.ToArray()); @@ -214,18 +214,18 @@ namespace MediaBrowser.Model.Dlna { if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return string.Format("{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } private static List<NameValuePair> BuildParams(StreamInfo item, string accessToken) @@ -457,7 +457,7 @@ namespace MediaBrowser.Model.Dlna { if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) { - info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", + info.Url = string.Format(CultureInfo.InvariantCulture, "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", baseUrl, ItemId, MediaSourceId, diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 26b50784b..413d297cb 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.Manager } } - public async Task SaveImage(User user, Stream source, string path) + public async Task SaveImage(Stream source, string path) { await SaveImageToLocation(source, path, path, CancellationToken.None).ConfigureAwait(false); } @@ -355,7 +355,7 @@ namespace MediaBrowser.Providers.Manager if (string.IsNullOrWhiteSpace(extension)) { - throw new ArgumentException(string.Format("Unable to determine image file extension from mime type {0}", mimeType)); + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unable to determine image file extension from mime type {0}", mimeType)); } if (type == ImageType.Thumb && saveLocally) diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index a5eb095c4..9227b6d93 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -54,7 +54,12 @@ namespace MediaBrowser.Providers.Manager return hasChanges; } - public async Task<RefreshResult> RefreshImages(BaseItem item, LibraryOptions libraryOptions, List<IImageProvider> providers, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken) + public async Task<RefreshResult> RefreshImages( + BaseItem item, + LibraryOptions libraryOptions, + List<IImageProvider> providers, + ImageRefreshOptions refreshOptions, + CancellationToken cancellationToken) { if (refreshOptions.IsReplacingImage(ImageType.Backdrop)) { @@ -78,19 +83,15 @@ namespace MediaBrowser.Providers.Manager foreach (var provider in providers) { - var remoteProvider = provider as IRemoteImageProvider; - - if (remoteProvider != null) + if (provider is IRemoteImageProvider remoteProvider) { await RefreshFromProvider(item, libraryOptions, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); continue; } - var dynamicImageProvider = provider as IDynamicImageProvider; - - if (dynamicImageProvider != null) + if (provider is IDynamicImageProvider dynamicImageProvider) { - await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, libraryOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false); } } @@ -100,11 +101,11 @@ namespace MediaBrowser.Providers.Manager /// <summary> /// Refreshes from provider. /// </summary> - private async Task RefreshFromProvider(BaseItem item, + private async Task RefreshFromProvider( + BaseItem item, IDynamicImageProvider provider, ImageRefreshOptions refreshOptions, TypeOptions savedOptions, - LibraryOptions libraryOptions, ICollection<ImageType> downloadedImages, RefreshResult result, CancellationToken cancellationToken) @@ -115,7 +116,7 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in images) { - if (!IsEnabled(savedOptions, imageType, item)) + if (!IsEnabled(savedOptions, imageType)) { continue; } @@ -133,12 +134,13 @@ namespace MediaBrowser.Providers.Manager if (response.Protocol == MediaProtocol.Http) { _logger.LogDebug("Setting image url into item {0}", item.Id); - item.SetImage(new ItemImageInfo - { - Path = response.Path, - Type = imageType - - }, 0); + item.SetImage( + new ItemImageInfo + { + Path = response.Path, + Type = imageType + }, + 0); } else { @@ -157,7 +159,7 @@ namespace MediaBrowser.Providers.Manager } downloadedImages.Add(imageType); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; } } } @@ -279,7 +281,7 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in _singularImages) { - if (!IsEnabled(savedOptions, imageType, item)) + if (!IsEnabled(savedOptions, imageType)) { continue; } @@ -299,8 +301,7 @@ namespace MediaBrowser.Providers.Manager minWidth = savedOptions.GetMinWidth(ImageType.Backdrop); await DownloadBackdrops(item, libraryOptions, ImageType.Backdrop, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false); - var hasScreenshots = item as IHasScreenshots; - if (hasScreenshots != null) + if (item is IHasScreenshots hasScreenshots) { minWidth = savedOptions.GetMinWidth(ImageType.Screenshot); await DownloadBackdrops(item, libraryOptions, ImageType.Screenshot, screenshotLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false); @@ -317,7 +318,7 @@ namespace MediaBrowser.Providers.Manager } } - private bool IsEnabled(TypeOptions options, ImageType type, BaseItem item) + private bool IsEnabled(TypeOptions options, ImageType type) { return options.IsEnabled(type); } @@ -452,10 +453,10 @@ namespace MediaBrowser.Providers.Manager .Where(i => i.Type == type && !(i.Width.HasValue && i.Width.Value < minWidth)) .ToList(); - if (EnableImageStub(item, type, libraryOptions) && eligibleImages.Count > 0) + if (EnableImageStub(item, libraryOptions) && eligibleImages.Count > 0) { SaveImageStub(item, type, eligibleImages.Select(i => i.Url)); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; return true; } @@ -476,7 +477,7 @@ namespace MediaBrowser.Providers.Manager null, cancellationToken).ConfigureAwait(false); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; return true; } catch (HttpException ex) @@ -495,7 +496,7 @@ namespace MediaBrowser.Providers.Manager return false; } - private bool EnableImageStub(BaseItem item, ImageType type, LibraryOptions libraryOptions) + private bool EnableImageStub(BaseItem item, LibraryOptions libraryOptions) { if (item is LiveTvProgram) { @@ -563,10 +564,10 @@ namespace MediaBrowser.Providers.Manager var url = image.Url; - if (EnableImageStub(item, imageType, libraryOptions)) + if (EnableImageStub(item, libraryOptions)) { SaveImageStub(item, imageType, new[] { url }); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + result.UpdateType |= ItemUpdateType.ImageUpdate; continue; } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 3b0c7b56c..dcae300fc 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -52,7 +52,6 @@ namespace MediaBrowser.Providers.Manager public async Task<ItemUpdateType> RefreshMetadata(BaseItem item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { var itemOfType = (TItemType)item; - var config = ProviderManager.GetMetadataOptions(item); var updateType = ItemUpdateType.None; var requiresRefresh = false; @@ -86,7 +85,7 @@ namespace MediaBrowser.Providers.Manager // Always validate images and check for new locally stored ones. if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>(), refreshOptions.DirectoryService)) { - updateType = updateType | ItemUpdateType.ImageUpdate; + updateType |= ItemUpdateType.ImageUpdate; } } catch (Exception ex) @@ -102,7 +101,7 @@ namespace MediaBrowser.Providers.Manager bool hasRefreshedMetadata = true; bool hasRefreshedImages = true; - var isFirstRefresh = item.DateLastRefreshed == default(DateTime); + var isFirstRefresh = item.DateLastRefreshed == default; // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) @@ -114,7 +113,7 @@ namespace MediaBrowser.Providers.Manager { if (item.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata)) { - updateType = updateType | ItemUpdateType.MetadataImport; + updateType |= ItemUpdateType.MetadataImport; } } @@ -132,7 +131,7 @@ namespace MediaBrowser.Providers.Manager var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); - updateType = updateType | result.UpdateType; + updateType |= result.UpdateType; if (result.Failures > 0) { hasRefreshedMetadata = false; @@ -147,9 +146,9 @@ namespace MediaBrowser.Providers.Manager if (providers.Count > 0) { - var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false); + var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, cancellationToken).ConfigureAwait(false); - updateType = updateType | result.UpdateType; + updateType |= result.UpdateType; if (result.Failures > 0) { hasRefreshedImages = false; @@ -158,7 +157,7 @@ namespace MediaBrowser.Providers.Manager } var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType); - updateType = updateType | beforeSaveResult; + updateType |= beforeSaveResult; // Save if changes were made, or it's never been saved before if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh) @@ -175,7 +174,7 @@ namespace MediaBrowser.Providers.Manager // If any of these properties are set then make sure the updateType is not None, just to force everything to save if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata) { - updateType = updateType | ItemUpdateType.MetadataDownload; + updateType |= ItemUpdateType.MetadataDownload; } if (hasRefreshedMetadata && hasRefreshedImages) @@ -184,11 +183,11 @@ namespace MediaBrowser.Providers.Manager } else { - item.DateLastRefreshed = default(DateTime); + item.DateLastRefreshed = default; } // Save to database - SaveItem(metadataResult, libraryOptions, updateType, cancellationToken); + await SaveItemAsync(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false); } await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); @@ -203,26 +202,26 @@ namespace MediaBrowser.Providers.Manager lookupInfo.Year = result.ProductionYear; } - protected void SaveItem(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken) + protected async Task SaveItemAsync(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken) { if (result.Item.SupportsPeople && result.People != null) { var baseItem = result.Item; LibraryManager.UpdatePeople(baseItem, result.People); - SavePeopleMetadata(result.People, libraryOptions, cancellationToken); + await SavePeopleMetadataAsync(result.People, libraryOptions, cancellationToken).ConfigureAwait(false); } result.Item.UpdateToRepository(reason, cancellationToken); } - private void SavePeopleMetadata(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken) + private async Task SavePeopleMetadataAsync(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken) { foreach (var person in people) { cancellationToken.ThrowIfCancellationRequested(); - if (person.ProviderIds.Any() || !string.IsNullOrWhiteSpace(person.ImageUrl)) + if (person.ProviderIds.Count > 0 || !string.IsNullOrWhiteSpace(person.ImageUrl)) { var updateType = ItemUpdateType.MetadataDownload; @@ -239,10 +238,10 @@ namespace MediaBrowser.Providers.Manager if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) { - AddPersonImage(personEntity, libraryOptions, person.ImageUrl, cancellationToken); + await AddPersonImageAsync(personEntity, libraryOptions, person.ImageUrl, cancellationToken).ConfigureAwait(false); saveEntity = true; - updateType = updateType | ItemUpdateType.ImageUpdate; + updateType |= ItemUpdateType.ImageUpdate; } if (saveEntity) @@ -253,26 +252,28 @@ namespace MediaBrowser.Providers.Manager } } - private void AddPersonImage(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken) + private async Task AddPersonImageAsync(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken) { - // if (libraryOptions.DownloadImagesInAdvance) - //{ - // try - // { - // await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); - // return; - // } - // catch (Exception ex) - // { - // Logger.LogError(ex, "Error in AddPersonImage"); - // } - //} - - personEntity.SetImage(new ItemImageInfo - { - Path = imageUrl, - Type = ImageType.Primary - }, 0); + if (libraryOptions.DownloadImagesInAdvance) + { + try + { + await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + return; + } + catch (Exception ex) + { + Logger.LogError(ex, "Error in AddPersonImage"); + } + } + + personEntity.SetImage( + new ItemImageInfo + { + Path = imageUrl, + Type = ImageType.Primary + }, + 0); } protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index e67d1b8c3..d9a84be5c 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -210,10 +210,10 @@ namespace MediaBrowser.Providers.Manager } /// <inheritdoc/> - public Task SaveImage(User user, Stream source, string mimeType, string path) + public Task SaveImage(Stream source, string mimeType, string path) { return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger) - .SaveImage(user, source, path); + .SaveImage(source, path); } /// <inheritdoc/> @@ -563,7 +563,7 @@ namespace MediaBrowser.Providers.Manager var pluginList = summary.Plugins.ToList(); AddMetadataPlugins(pluginList, dummy, libraryOptions, options); - AddImagePlugins(pluginList, dummy, imageProviders); + AddImagePlugins(pluginList, imageProviders); var subtitleProviders = _subtitleManager.GetSupportedProviders(dummy); @@ -594,14 +594,14 @@ namespace MediaBrowser.Providers.Manager var providers = GetMetadataProvidersInternal<T>(item, libraryOptions, options, true, true).ToList(); // Locals - list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin + list.AddRange(providers.Where(i => i is ILocalMetadataProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.LocalMetadataProvider })); // Fetchers - list.AddRange(providers.Where(i => (i is IRemoteMetadataProvider)).Select(i => new MetadataPlugin + list.AddRange(providers.Where(i => i is IRemoteMetadataProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.MetadataFetcher @@ -615,11 +615,10 @@ namespace MediaBrowser.Providers.Manager })); } - private void AddImagePlugins<T>(List<MetadataPlugin> list, T item, List<IImageProvider> imageProviders) - where T : BaseItem + private void AddImagePlugins(List<MetadataPlugin> list, List<IImageProvider> imageProviders) { // Locals - list.AddRange(imageProviders.Where(i => (i is ILocalImageProvider)).Select(i => new MetadataPlugin + list.AddRange(imageProviders.Where(i => i is ILocalImageProvider).Select(i => new MetadataPlugin { Name = i.Name, Type = MetadataPluginType.LocalImageProvider @@ -1166,12 +1165,32 @@ namespace MediaBrowser.Providers.Manager /// <inheritdoc/> public void Dispose() { - _disposed = true; + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <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 (_disposed) + { + return; + } if (!_disposeCancellationTokenSource.IsCancellationRequested) { _disposeCancellationTokenSource.Cancel(); } + + if (disposing) + { + _disposeCancellationTokenSource.Dispose(); + } + + _disposed = true; } } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 69c6fd722..77f03580a 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -2,11 +2,9 @@ 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.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -17,7 +15,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.MediaInfo { @@ -25,19 +22,17 @@ namespace MediaBrowser.Providers.MediaInfo { private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public FFProbeAudioInfo(IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IApplicationPaths appPaths, IJsonSerializer json, ILibraryManager libraryManager) + public FFProbeAudioInfo( + IMediaSourceManager mediaSourceManager, + IMediaEncoder mediaEncoder, + IItemRepository itemRepo, + ILibraryManager libraryManager) { _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; - _appPaths = appPaths; - _json = json; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 4fabe709b..9926275ae 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -40,19 +40,15 @@ namespace MediaBrowser.Providers.MediaInfo IHasItemChangeMonitor { private readonly ILogger<FFProbeProvider> _logger; - private readonly IIsoManager _isoManager; private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; private readonly IBlurayExaminer _blurayExaminer; private readonly ILocalizationManager _localization; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; private readonly IEncodingManager _encodingManager; private readonly IServerConfigurationManager _config; private readonly ISubtitleManager _subtitleManager; private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; - private readonly IChannelManager _channelManager; private readonly IMediaSourceManager _mediaSourceManager; public string Name => "ffprobe"; @@ -126,14 +122,10 @@ namespace MediaBrowser.Providers.MediaInfo public FFProbeProvider( ILogger<FFProbeProvider> logger, IMediaSourceManager mediaSourceManager, - IChannelManager channelManager, - IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, - IApplicationPaths appPaths, - IJsonSerializer json, IEncodingManager encodingManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, @@ -141,19 +133,15 @@ namespace MediaBrowser.Providers.MediaInfo ILibraryManager libraryManager) { _logger = logger; - _isoManager = isoManager; _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; _blurayExaminer = blurayExaminer; _localization = localization; - _appPaths = appPaths; - _json = json; _encodingManager = encodingManager; _config = config; _subtitleManager = subtitleManager; _chapterManager = chapterManager; _libraryManager = libraryManager; - _channelManager = channelManager; _mediaSourceManager = mediaSourceManager; _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager); @@ -211,9 +199,9 @@ namespace MediaBrowser.Providers.MediaInfo private string NormalizeStrmLine(string line) { - return line.Replace("\t", string.Empty) - .Replace("\r", string.Empty) - .Replace("\n", string.Empty) + return line.Replace("\t", string.Empty, StringComparison.Ordinal) + .Replace("\r", string.Empty, StringComparison.Ordinal) + .Replace("\n", string.Empty, StringComparison.Ordinal) .Trim(); } @@ -242,10 +230,11 @@ namespace MediaBrowser.Providers.MediaInfo FetchShortcutInfo(item); } - var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _appPaths, _json, _libraryManager); + var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _libraryManager); return prober.Probe(item, options, cancellationToken); } + // Run last public int Order => 100; } diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/Extensions.cs index b57d35256..dddfd02e4 100644 --- a/MediaBrowser.Providers/Music/Extensions.cs +++ b/MediaBrowser.Providers/Music/Extensions.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Providers.Music { - public static class Extensions + public static class AlbumInfoExtensions { public static string GetAlbumArtist(this AlbumInfo info) { @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music return id; } - return info.AlbumArtists.FirstOrDefault(); + return info.AlbumArtists.Count > 0 ? info.AlbumArtists[0] : default; } public static string GetReleaseGroupId(this AlbumInfo info) diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 23acb7fd6..3550614dd 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -276,7 +276,7 @@ namespace MediaBrowser.Providers.Music private async Task<ReleaseResult> GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken) { - var url = string.Format("/ws/2/release/?query=\"{0}\" AND arid:{1}", + var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/release/?query=\"{0}\" AND arid:{1}", WebUtility.UrlEncode(albumName), artistId); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index b829ed378..781b71640 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Music // They seem to throw bad request failures on any term with a slash var nameToSearch = searchInfo.Name.Replace('/', ' '); - var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch)); + var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch)); using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false)) await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Music if (HasDiacritics(searchInfo.Name)) { // Try again using the search with accent characters url - url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs index 41e664aac..c18725e0a 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net.Http; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -70,7 +71,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb list.Add(new RemoteImageInfo { ProviderName = Name, - Url = string.Format("https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId) + Url = string.Format(CultureInfo.InvariantCulture, "https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId) }); } } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index d2823a08c..102ad82e1 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = OmdbProvider.GetOmdbUrl(urlQuery, _appHost, cancellationToken); + var url = OmdbProvider.GetOmdbUrl(urlQuery); using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 6ad5298de..c45149c3a 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -256,16 +256,16 @@ namespace MediaBrowser.Providers.Plugins.Omdb return false; } - public static string GetOmdbUrl(string query, IApplicationHost appHost, CancellationToken cancellationToken) + public static string GetOmdbUrl(string query) { - const string url = "https://www.omdbapi.com?apikey=2c9d9507"; + const string Url = "https://www.omdbapi.com?apikey=2c9d9507"; if (string.IsNullOrWhiteSpace(query)) { - return url; + return Url; } - return url + "&" + query; + return Url + "&" + query; } private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken) @@ -290,7 +290,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), _appHost, cancellationToken); + var url = GetOmdbUrl( + string.Format( + CultureInfo.InvariantCulture, + "i={0}&plot=short&tomatoes=true&r=json", + imdbParam)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -323,7 +327,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb } } - var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), _appHost, cancellationToken); + var url = GetOmdbUrl( + string.Format( + CultureInfo.InvariantCulture, + "i={0}&season={1}&detail=full", + imdbParam, + seasonId)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -348,7 +357,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb"); - var filename = string.Format("{0}.json", imdbId); + var filename = string.Format(CultureInfo.InvariantCulture, "{0}.json", imdbId); return Path.Combine(dataPath, filename); } @@ -362,7 +371,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb"); - var filename = string.Format("{0}_season_{1}.json", imdbId, seasonId); + var filename = string.Format(CultureInfo.InvariantCulture, "{0}_season_{1}.json", imdbId, seasonId); return Path.Combine(dataPath, filename); } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs index cd2f96f14..f22d484ab 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbClientManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -19,7 +20,6 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb { private const string DefaultLanguage = "en"; - private readonly SemaphoreSlim _cacheWriteLock = new SemaphoreSlim(1, 1); private readonly IMemoryCache _cache; private readonly TvDbClient _tvDbClient; private DateTime _tokenCreatedAt; @@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb string language, CancellationToken cancellationToken) { - searchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), + searchInfo.SeriesProviderIds.TryGetValue(nameof(MetadataProvider.Tvdb), out var seriesTvdbId); var episodeQuery = new EpisodeQuery(); @@ -203,10 +203,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb else if (searchInfo.PremiereDate.HasValue) { // tvdb expects yyyy-mm-dd format - episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd"); + episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); } - return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken); + return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), episodeQuery, language, cancellationToken); } public async Task<string> GetEpisodeTvdbId( @@ -218,7 +218,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var episodePage = await GetEpisodesPageAsync(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken) .ConfigureAwait(false); - return episodePage.Data.FirstOrDefault()?.Id.ToString(); + return episodePage.Data.FirstOrDefault()?.Id.ToString(CultureInfo.InvariantCulture); } public Task<TvDbResponse<EpisodeRecord[]>> GetEpisodesPageAsync( @@ -276,23 +276,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb return cachedValue; } - await _cacheWriteLock.WaitAsync().ConfigureAwait(false); - try - { - if (_cache.TryGetValue(key, out cachedValue)) - { - return cachedValue; - } - - _tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage; - var result = await resultFactory.Invoke().ConfigureAwait(false); - _cache.Set(key, result, TimeSpan.FromHours(1)); - return result; - } - finally - { - _cacheWriteLock.Release(); - } + _tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage; + var result = await resultFactory.Invoke().ConfigureAwait(false); + _cache.Set(key, result, TimeSpan.FromHours(1)); + return result; } private static string GenerateKey(params object[] objects) diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs index 4d38d38dc..4e7c0e5a6 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Net.Http; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; @@ -76,7 +77,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb var episodeResult = await _tvdbClientManager - .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId), language, cancellationToken) + .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId, CultureInfo.InvariantCulture), language, cancellationToken) .ConfigureAwait(false); var image = GetImageInfo(episodeResult.Data); @@ -103,8 +104,8 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb return new RemoteImageInfo { - Width = Convert.ToInt32(episode.ThumbWidth), - Height = Convert.ToInt32(episode.ThumbHeight), + Width = Convert.ToInt32(episode.ThumbWidth, CultureInfo.InvariantCulture), + Height = Convert.ToInt32(episode.ThumbHeight, CultureInfo.InvariantCulture), ProviderName = Name, Url = TvdbUtils.BannerUrl + episode.Filename, Type = ImageType.Primary diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs index 4f86a0293..4da2c042f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); // Get images in english and with no language url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language); @@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets { var path = GetDataPath(appPaths, tmdbId); - var filename = string.Format("all-{0}.json", preferredLanguage ?? string.Empty); + var filename = string.Format(CultureInfo.InvariantCulture, "all-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs index 27ca3759e..01a887eed 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs @@ -300,7 +300,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { movie.RemoteTrailers = movieData.Trailers.Youtube.Select(i => new MediaUrl { - Url = string.Format("https://www.youtube.com/watch?v={0}", i.Source), + Url = string.Format(CultureInfo.InvariantCulture, "https://www.youtube.com/watch?v={0}", i.Source), Name = i.Name }).ToArray(); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs index 48f2a68a6..b7c4a5643 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs @@ -37,7 +37,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies ).* # Match rest of string", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase); - private const string _searchURL = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}"; + private const string SearchUrl = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}"; + private const string SearchUrlWithYear = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}&first_air_date_year={4}"; private readonly ILogger _logger; private readonly IJsonSerializer _json; @@ -124,7 +125,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies name2 = name2.Trim(); // Search again if the new name is different - if (!string.Equals(name2, name) && !string.IsNullOrWhiteSpace(name2)) + if (!string.Equals(name2, name, StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(name2)) { _logger.LogInformation("TmdbSearch: Finding id for item: {0} ({1})", name2, year); results = await GetSearchResults(name2, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); @@ -164,10 +165,30 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { if (string.IsNullOrWhiteSpace(name)) { - throw new ArgumentException("name"); + throw new ArgumentException("String can't be null or empty.", nameof(name)); } - var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, type); + string url3; + if (year != null && string.Equals(type, "movie", StringComparison.OrdinalIgnoreCase)) + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + type) + "&primary_release_year=" + year; + } + else + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + type); + } var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3); foreach (var header in TmdbUtils.AcceptHeaders) @@ -207,10 +228,31 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { if (string.IsNullOrWhiteSpace(name)) { - throw new ArgumentException("name"); + throw new ArgumentException("String can't be null or empty.", nameof(name)); } - var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv"); + string url3; + if (year == null) + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrl, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + "tv"); + } + else + { + url3 = string.Format( + CultureInfo.InvariantCulture, + SearchUrlWithYear, + WebUtility.UrlEncode(name), + TmdbUtils.ApiKey, + language, + "tv", + year); + } var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3); foreach (var header in TmdbUtils.AcceptHeaders) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index b4aef4542..90e3cea93 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV { if (video.Site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase)) { - var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.Key); + var videoUrl = string.Format(CultureInfo.InvariantCulture, "http://www.youtube.com/watch?v={0}", video.Key); item.AddTrailerUrl(videoUrl); } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs index 154664321..5705885b4 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("season-{0}-episode-{1}-{2}.json", + var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-episode-{1}-{2}.json", seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber.ToString(CultureInfo.InvariantCulture), preferredLanguage); @@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", language); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", language); } var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index 2b9077f55..e59504cc6 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("season-{0}-{1}.json", + var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-{1}.json", seasonNumber.ToString(CultureInfo.InvariantCulture), preferredLanguage); @@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV if (!string.IsNullOrEmpty(language)) { - url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); + url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language)); } var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index ac577b125..0eded3233 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -496,7 +496,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var path = GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId); - var filename = string.Format("series-{0}.json", preferredLanguage ?? string.Empty); + var filename = string.Format(CultureInfo.InvariantCulture, "series-{0}.json", preferredLanguage ?? string.Empty); return Path.Combine(path, filename); } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index dad155c81..321153c6b 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -100,7 +101,7 @@ namespace MediaBrowser.Providers.Studios private string GetUrl(string image, string filename) { - return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename); + return string.Format(CultureInfo.InvariantCulture, "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename); } private Task<string> EnsureThumbsList(string file, CancellationToken cancellationToken) -- cgit v1.2.3 From ab2147751f9079bc104da068909a485fc9402a64 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Thu, 20 Aug 2020 12:16:24 +0200 Subject: Make MediaBrowser.MediaEncoding warnings free --- Emby.Dlna/Main/DlnaEntryPoint.cs | 4 +- Emby.Dlna/PlayTo/uBaseObject.cs | 2 +- Emby.Dlna/PlayTo/uPnpNamespaces.cs | 2 +- .../Data/SqliteItemRepository.cs | 7 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 27 +--- .../IO/LibraryMonitorStartup.cs | 35 +++++ .../Library/LibraryManager.cs | 2 +- .../LiveTv/EmbyTV/EntryPoint.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 148 +++++++++++---------- .../ScheduledTasks/TaskManager.cs | 1 + .../ScheduledTasks/Tasks/DeleteLogFileTask.cs | 64 ++++----- .../Services/ServicePath.cs | 8 +- .../Entities/UserViewBuilder.cs | 1 - .../Attachments/AttachmentExtractor.cs | 4 +- .../Encoder/EncodingUtils.cs | 5 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- .../Probing/ProbeResultNormalizer.cs | 9 +- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 8 +- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 95 ++++++------- .../Subtitles/SubtitleEncoder.cs | 17 +-- 22 files changed, 236 insertions(+), 213 deletions(-) create mode 100644 Emby.Server.Implementations/IO/LibraryMonitorStartup.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index a21d4cc11..191763de4 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -30,7 +30,7 @@ using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Dlna.Main { - public class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup + public sealed class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup { private readonly IServerConfigurationManager _config; private readonly ILogger<DlnaEntryPoint> _logger; @@ -60,7 +60,7 @@ namespace Emby.Dlna.Main public IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; } - public static DlnaEntryPoint Current; + public static DlnaEntryPoint Current { get; private set; }; public DlnaEntryPoint( IServerConfigurationManager config, diff --git a/Emby.Dlna/PlayTo/uBaseObject.cs b/Emby.Dlna/PlayTo/uBaseObject.cs index 05c19299f..f2dc31f6d 100644 --- a/Emby.Dlna/PlayTo/uBaseObject.cs +++ b/Emby.Dlna/PlayTo/uBaseObject.cs @@ -31,7 +31,7 @@ namespace Emby.Dlna.PlayTo throw new ArgumentNullException(nameof(obj)); } - return string.Equals(Id, obj.Id); + return string.Equals(Id, obj.Id, StringComparison.Ordinal); } public string MediaType diff --git a/Emby.Dlna/PlayTo/uPnpNamespaces.cs b/Emby.Dlna/PlayTo/uPnpNamespaces.cs index dc65cdf43..6ea7dc9cf 100644 --- a/Emby.Dlna/PlayTo/uPnpNamespaces.cs +++ b/Emby.Dlna/PlayTo/uPnpNamespaces.cs @@ -4,7 +4,7 @@ using System.Xml.Linq; 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 ns = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 331ffc134..5bf740cfc 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4308,7 +4308,7 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("ProductionYear=@Years"); 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) @@ -5170,7 +5170,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type 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())) diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index a32b03aaa..9290dfcd0 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -6,12 +6,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; +using Emby.Server.Implementations.Library; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.IO; -using Emby.Server.Implementations.Library; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.IO @@ -38,6 +37,8 @@ namespace Emby.Server.Implementations.IO /// </summary> private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + private bool _disposed = false; + /// <summary> /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope. /// </summary> @@ -492,8 +493,6 @@ namespace Emby.Server.Implementations.IO } } - private bool _disposed = false; - /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> @@ -522,24 +521,4 @@ namespace Emby.Server.Implementations.IO _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() - { - } - } } diff --git a/Emby.Server.Implementations/IO/LibraryMonitorStartup.cs b/Emby.Server.Implementations/IO/LibraryMonitorStartup.cs new file mode 100644 index 000000000..c51cf0545 --- /dev/null +++ b/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() + { + } + } +} diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7b770d940..7ed8f0bbf 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -729,7 +729,7 @@ namespace Emby.Server.Implementations.Library Directory.CreateDirectory(rootFolderPath); var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? - ((Folder) ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath))) + ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath))) .DeepCopy<Folder, AggregateFolder>(); // In case program data folder was moved diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs index 69a9cb78a..a2ec2df37 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs @@ -5,7 +5,7 @@ using MediaBrowser.Controller.Plugins; namespace Emby.Server.Implementations.LiveTv.EmbyTV { - public class EntryPoint : IServerEntryPoint + public sealed class EntryPoint : IServerEntryPoint { /// <inheritdoc /> public Task RunAsync() diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 77a7069eb..c4d5cc58a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -929,7 +929,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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 diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 8a900f42c..1ef083d04 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -10,7 +10,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Events; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -22,37 +21,53 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </summary> 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> /// Gets or sets the json serializer. /// </summary> /// <value>The json serializer.</value> - private IJsonSerializer JsonSerializer { get; set; } + private readonly IJsonSerializer _jsonSerializer; /// <summary> /// Gets or sets the application paths. /// </summary> /// <value>The application paths.</value> - private IApplicationPaths ApplicationPaths { get; set; } + private readonly IApplicationPaths _applicationPaths; /// <summary> - /// Gets the logger. + /// Gets or sets the logger. /// </summary> /// <value>The logger.</value> - private ILogger Logger { get; set; } + private readonly ILogger _logger; /// <summary> - /// Gets the task manager. + /// Gets or sets the task manager. /// </summary> /// <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> /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class. @@ -71,7 +86,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// or /// jsonSerializer /// or - /// logger + /// logger. /// </exception> public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger) { @@ -101,23 +116,22 @@ namespace Emby.Server.Implementations.ScheduledTasks } ScheduledTask = scheduledTask; - ApplicationPaths = applicationPaths; - TaskManager = taskManager; - JsonSerializer = jsonSerializer; - Logger = logger; + _applicationPaths = applicationPaths; + _taskManager = taskManager; + _jsonSerializer = jsonSerializer; + _logger = logger; InitTriggerEvents(); } - private bool _readFromFile = false; - /// <summary> - /// The _last execution result. - /// </summary> - private TaskResult _lastExecutionResult; + public event EventHandler<GenericEventArgs<double>> TaskProgress; + /// <summary> - /// The _last execution result sync lock. + /// Gets the scheduled task. /// </summary> - private readonly object _lastExecutionResultSyncLock = new object(); + /// <value>The scheduled task.</value> + public IScheduledTask ScheduledTask { get; private set; } + /// <summary> /// Gets the last execution result. /// </summary> @@ -136,11 +150,11 @@ namespace Emby.Server.Implementations.ScheduledTasks { try { - _lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path); + _lastExecutionResult = _jsonSerializer.DeserializeFromFile<TaskResult>(path); } 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) { - JsonSerializer.SerializeToFile(value, path); + _jsonSerializer.SerializeToFile(value, path); } } } @@ -184,7 +198,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public string Category => ScheduledTask.Category; /// <summary> - /// Gets the current cancellation token. + /// Gets or sets the current cancellation token. /// </summary> /// <value>The current cancellation token source.</value> private CancellationTokenSource CurrentCancellationTokenSource { get; set; } @@ -221,12 +235,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public double? CurrentProgress { get; private set; } /// <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> /// <value>The triggers.</value> private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers @@ -255,7 +264,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// Gets the triggers that define when the task will run. /// </summary> /// <value>The triggers.</value> - /// <exception cref="ArgumentNullException">value</exception> + /// <exception cref="ArgumentNullException"><c>value</c> is <c>null</c>.</exception> public TaskTriggerInfo[] Triggers { get @@ -280,11 +289,6 @@ namespace Emby.Server.Implementations.ScheduledTasks } } - /// <summary> - /// The _id. - /// </summary> - private string _id; - /// <summary> /// Gets the unique id. /// </summary> @@ -325,9 +329,9 @@ namespace Emby.Server.Implementations.ScheduledTasks 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> /// <param name="sender">The source of the event.</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; @@ -347,19 +351,17 @@ namespace Emby.Server.Implementations.ScheduledTasks 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(); - TaskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions); + _taskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions); await Task.Delay(1000).ConfigureAwait(false); - trigger.Start(LastExecutionResult, Logger, Name, false); + trigger.Start(LastExecutionResult, _logger, Name, false); } - private Task _currentTask; - /// <summary> /// Executes the task. /// </summary> @@ -395,9 +397,9 @@ namespace Emby.Server.Implementations.ScheduledTasks CurrentCancellationTokenSource = new CancellationTokenSource(); - Logger.LogInformation("Executing {0}", Name); + _logger.LogInformation("Executing {0}", Name); - ((TaskManager)TaskManager).OnTaskExecuting(this); + ((TaskManager)_taskManager).OnTaskExecuting(this); progress.ProgressChanged += OnProgressChanged; @@ -423,7 +425,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } catch (Exception ex) { - Logger.LogError(ex, "Error"); + _logger.LogError(ex, "Error"); failureException = ex; @@ -476,7 +478,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { if (State == TaskState.Running) { - Logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name); + _logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name); CurrentCancellationTokenSource.Cancel(); } } @@ -487,7 +489,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <returns>System.String.</returns> private string GetScheduledTasksConfigurationDirectory() { - return Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks"); + return Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks"); } /// <summary> @@ -496,7 +498,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <returns>System.String.</returns> private string GetScheduledTasksDataDirectory() { - return Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks"); + return Path.Combine(_applicationPaths.DataPath, "ScheduledTasks"); } /// <summary> @@ -535,7 +537,7 @@ namespace Emby.Server.Implementations.ScheduledTasks TaskTriggerInfo[] list = null; if (File.Exists(path)) { - list = JsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path); + list = _jsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path); } // Return defaults if file doesn't exist. @@ -571,7 +573,7 @@ namespace Emby.Server.Implementations.ScheduledTasks Directory.CreateDirectory(Path.GetDirectoryName(path)); - JsonSerializer.SerializeToFile(triggers, path); + _jsonSerializer.SerializeToFile(triggers, path); } /// <summary> @@ -585,7 +587,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { 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 { @@ -606,7 +608,7 @@ namespace Emby.Server.Implementations.ScheduledTasks LastExecutionResult = result; - ((TaskManager)TaskManager).OnTaskCompleted(this, result); + ((TaskManager)_taskManager).OnTaskCompleted(this, result); } /// <summary> @@ -615,6 +617,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// <summary> @@ -635,12 +638,12 @@ namespace Emby.Server.Implementations.ScheduledTasks { try { - Logger.LogInformation(Name + ": Cancelling"); + _logger.LogInformation(Name + ": Cancelling"); token.Cancel(); } 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 { - Logger.LogInformation(Name + ": Waiting on Task"); + _logger.LogInformation(Name + ": Waiting on Task"); var exited = Task.WaitAll(new[] { task }, 2000); if (exited) { - Logger.LogInformation(Name + ": Task exited"); + _logger.LogInformation(Name + ": Task exited"); } else { - Logger.LogInformation(Name + ": Timed out waiting for task to stop"); + _logger.LogInformation(Name + ": Timed out waiting for task to stop"); } } 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 { - Logger.LogDebug(Name + ": Disposing CancellationToken"); + _logger.LogDebug(Name + ": Disposing CancellationToken"); token.Dispose(); } 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> /// <param name="info">The info.</param> /// <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) { var options = new TaskOptions @@ -765,7 +767,7 @@ namespace Emby.Server.Implementations.ScheduledTasks foreach (var triggerInfo in InternalTriggers) { var trigger = triggerInfo.Item2; - trigger.Triggered -= trigger_Triggered; + trigger.Triggered -= OnTriggerTriggered; trigger.Stop(); } } diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 81096026b..6d2b4ffc8 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -207,6 +207,7 @@ namespace Emby.Server.Implementations.ScheduledTasks public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// <summary> diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs index 402b39a26..54e18eaea 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -1,12 +1,13 @@ 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.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Globalization; namespace Emby.Server.Implementations.ScheduledTasks.Tasks { @@ -15,12 +16,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// </summary> 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 ILocalizationManager _localization; @@ -32,18 +28,43 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// <param name="localization">The localization manager.</param> public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization) { - ConfigurationManager = configurationManager; + _configurationManager = configurationManager; _fileSystem = fileSystem; _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> /// Creates the triggers that define when the task will run. /// </summary> /// <returns>IEnumerable{BaseTaskTrigger}.</returns> public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() { - return new[] { + return new[] + { 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) { // 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 - 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) .ToList(); @@ -83,26 +104,5 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks 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; } } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 442b2ab1c..0d4728b43 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -80,8 +80,8 @@ namespace Emby.Server.Implementations.Services 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) @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Services { list.Add(hashPrefix + part); - if (part.IndexOf(ComponentSeperator) == -1) + if (part.IndexOf(ComponentSeperator, StringComparison.Ordinal) == -1) { continue; } @@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.Services } if (component.IndexOf(VariablePrefix, StringComparison.OrdinalIgnoreCase) != -1 - && component.IndexOf(ComponentSeperator) != -1) + && component.IndexOf(ComponentSeperator, StringComparison.Ordinal) != -1) { hasSeparators.Add(true); componentsList.AddRange(component.Split(ComponentSeperator)); diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index e3f4025bb..b384b27d1 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -10,7 +10,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index a8ebe6bc5..21b5d0c5b 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -240,11 +240,11 @@ namespace MediaBrowser.MediaEncoding.Attachments if (protocol == MediaProtocol.File) { 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 { - 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); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 082ae2888..63310fdf6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -48,7 +49,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <returns>System.String.</returns> private static string GetFileInputArgument(string path) { - if (path.IndexOf("://") != -1) + if (path.IndexOf("://", StringComparison.Ordinal) != -1) { return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path); } @@ -67,7 +68,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private static string NormalizePath(string path) { // 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); } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index b9a6432ad..7449e4a62 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -377,7 +377,7 @@ namespace MediaBrowser.MediaEncoding.Encoder 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_format"; - args = string.Format(args, probeSizeArgument, inputPath).Trim(); + args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath).Trim(); var process = new Process { @@ -856,7 +856,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping // We need to double escape - return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''"); + return path.Replace('\\', '/').Replace(":", "\\:", StringComparison.Ordinal).Replace("'", "'\\\\\\''", StringComparison.Ordinal); } /// <inheritdoc /> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 017f917e2..814edd732 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -34,7 +34,7 @@ <!-- Code Analyzers--> <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="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 19e3bd8e6..40a3b43e1 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -42,7 +42,8 @@ namespace MediaBrowser.MediaEncoding.Probing var info = new MediaInfo { Path = path, - Protocol = protocol + Protocol = protocol, + VideoType = videoType }; 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. // 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 : new[] { ',' }; @@ -1377,8 +1378,8 @@ namespace MediaBrowser.MediaEncoding.Probing if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number { 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 } diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 308b62886..86b87fddd 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -86,9 +86,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles private void RemoteNativeFormatting(SubtitleTrackEvent p) { - int indexOfBegin = p.Text.IndexOf('{'); + int indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal); 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); if (s.StartsWith("{\\an1}", StringComparison.Ordinal) || @@ -116,10 +116,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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); - indexOfBegin = p.Text.IndexOf('{'); + indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal); } p.Text = pre + p.Text; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 6b7a81e6e..a5d641747 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Threading; @@ -50,14 +51,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles { eventsStarted = true; } - else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";")) + else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";", StringComparison.Ordinal)) { // skip comment lines } else if (eventsStarted && line.Trim().Length > 0) { string s = line.Trim().ToLowerInvariant(); - if (s.StartsWith("format:")) + if (s.StartsWith("format:", StringComparison.Ordinal)) { if (line.Length > 10) { @@ -103,7 +104,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles string[] splittedLine; - if (s.StartsWith("dialogue:")) + if (s.StartsWith("dialogue:", StringComparison.Ordinal)) { splittedLine = line.Substring(10).Split(','); } @@ -181,10 +182,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles string[] timeCode = time.Split(':', '.'); return new TimeSpan( 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) @@ -193,11 +194,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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); - 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 extraTags = string.Empty; @@ -212,7 +213,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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) { 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); - 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 extraTags = string.Empty; @@ -245,7 +246,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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) { 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); - 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 extraTags = string.Empty; 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'); // switch to rrggbb from bbggrr @@ -285,7 +286,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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) { 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); - 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 extraTags = string.Empty; 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'); // 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>")) { 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>")) { 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>")) { text += "</b>"; @@ -362,7 +363,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private static int CountTagInText(string text, string tag) { int count = 0; - int index = text.IndexOf(tag); + int index = text.IndexOf(tag, StringComparison.Ordinal); while (index >= 0) { count++; @@ -371,7 +372,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return count; } - index = text.IndexOf(tag, index + 1); + index = text.IndexOf(tag, index + 1, StringComparison.Ordinal); } return count; @@ -380,7 +381,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out bool italic) { italic = false; - int indexOfSPlit = tagName.IndexOf(@"\"); + int indexOfSPlit = tagName.IndexOf('\\', StringComparison.Ordinal); if (indexOfSPlit > 0) { string rest = tagName.Substring(indexOfSPlit).TrimStart('\\'); @@ -388,9 +389,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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; if (indexOfSPlit > 0) { @@ -404,9 +405,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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; if (indexOfSPlit > 0) { @@ -420,9 +421,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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; if (indexOfSPlit > 0) { @@ -435,7 +436,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } 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'); // 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); @@ -443,9 +444,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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; if (indexOfSPlit > 0) { @@ -456,9 +457,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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('\\'); } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index fbe8bd69f..6ac5ac2ff 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -415,7 +415,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // 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 ((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-16LE", StringComparison.OrdinalIgnoreCase))) { @@ -506,7 +506,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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); } @@ -668,7 +668,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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. /// </summary> /// <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> - private async Task SetAssFont(string file) + private async Task SetAssFont(string file, CancellationToken cancellationToken = default) { _logger.LogInformation("Setting ass font within {File}", file); @@ -692,14 +693,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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 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; // 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-16be", StringComparison.OrdinalIgnoreCase))) { -- cgit v1.2.3 From cb5cb075a9803e296f6de594307994b88cb156d0 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Thu, 20 Aug 2020 17:16:09 +0200 Subject: Simplify FFmpeg detection code --- .../Encoder/EncoderValidator.cs | 58 +++------------------- .../EncoderValidatorTests.cs | 2 + .../EncoderValidatorTestsData.cs | 12 +++++ 3 files changed, 21 insertions(+), 51 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 0e9a5e502..1c389c237 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -100,20 +100,6 @@ namespace MediaBrowser.MediaEncoding.Encoder { "libpostproc", new Version(55, 1) } }; - // This lookup table is to be maintained with the following command line: - // $ ffmpeg -version | perl -ne ' print "$1=$2.$3," if /^(lib\w+)\s+(\d+)\.\s*(\d+)/' - private static readonly IReadOnlyDictionary<string, Version> _ffmpegVersionMap = new Dictionary<string, Version> - { - { "libavutil=56.51,libavcodec=58.91,libavformat=58.45,libavdevice=58.10,libavfilter=7.85,libswscale=5.7,libswresample=3.7,libpostproc=55.7,", new Version(4, 3) }, - { "libavutil=56.31,libavcodec=58.54,libavformat=58.29,libavdevice=58.8,libavfilter=7.57,libswscale=5.5,libswresample=3.5,libpostproc=55.5,", new Version(4, 2) }, - { "libavutil=56.22,libavcodec=58.35,libavformat=58.20,libavdevice=58.5,libavfilter=7.40,libswscale=5.3,libswresample=3.3,libpostproc=55.3,", new Version(4, 1) }, - { "libavutil=56.14,libavcodec=58.18,libavformat=58.12,libavdevice=58.3,libavfilter=7.16,libswscale=5.1,libswresample=3.1,libpostproc=55.1,", new Version(4, 0) }, - { "libavutil=55.78,libavcodec=57.107,libavformat=57.83,libavdevice=57.10,libavfilter=6.107,libswscale=4.8,libswresample=2.9,libpostproc=54.7,", new Version(3, 4) }, - { "libavutil=55.58,libavcodec=57.89,libavformat=57.71,libavdevice=57.6,libavfilter=6.82,libswscale=4.6,libswresample=2.7,libpostproc=54.5,", new Version(3, 3) }, - { "libavutil=55.34,libavcodec=57.64,libavformat=57.56,libavdevice=57.1,libavfilter=6.65,libswscale=4.2,libswresample=2.3,libpostproc=54.1,", new Version(3, 2) }, - { "libavutil=54.31,libavcodec=56.60,libavformat=56.40,libavdevice=56.4,libavfilter=5.40,libswscale=3.1,libswresample=1.2,libpostproc=53.3,", new Version(2, 8) } - }; - private readonly ILogger _logger; private readonly string _encoderPath; @@ -130,6 +116,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Decoder } + // When changing this, also change the minimum library versions in _ffmpegMinimumLibraryVersions public static Version MinVersion { get; } = new Version(4, 0); public static Version MaxVersion { get; } = null; @@ -227,28 +214,9 @@ namespace MediaBrowser.MediaEncoding.Encoder { return new Version(match.Groups[1].Value); } - else - { - if (!TryGetFFmpegLibraryVersions(output, out string versionString, out IReadOnlyDictionary<string, Version> versionMap)) - { - _logger.LogError("No ffmpeg library versions found"); - return null; - } - - // First try to lookup the full version string - if (_ffmpegVersionMap.TryGetValue(versionString, out Version version)) - { - return version; - } + var versionMap = GetFFmpegLibraryVersions(output); - // Then try to test for minimum library versions - return TestMinimumFFmpegLibraryVersions(versionMap); - } - } - - private Version TestMinimumFFmpegLibraryVersions(IReadOnlyDictionary<string, Version> versionMap) - { var allVersionsValidated = true; foreach (var minimumVersion in _ffmpegMinimumLibraryVersions) @@ -281,10 +249,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// </summary> /// <param name="output">The 'ffmpeg -version' output.</param> /// <returns>The library names and major.minor version numbers.</returns> - private static bool TryGetFFmpegLibraryVersions(string output, out string versionString, out IReadOnlyDictionary<string, Version> versionMap) + private static IReadOnlyDictionary<string, Version> GetFFmpegLibraryVersions(string output) { - var sb = new StringBuilder(144); - var map = new Dictionary<string, Version>(); foreach (Match match in Regex.Matches( @@ -292,24 +258,14 @@ namespace MediaBrowser.MediaEncoding.Encoder @"((?<name>lib\w+)\s+(?<major>[0-9]+)\.\s*(?<minor>[0-9]+))", RegexOptions.Multiline)) { - sb.Append(match.Groups["name"]) - .Append('=') - .Append(match.Groups["major"]) - .Append('.') - .Append(match.Groups["minor"]) - .Append(','); - - var str = $"{match.Groups["major"]}.{match.Groups["minor"]}"; - - var version = Version.Parse(str); + var version = new Version( + int.Parse(match.Groups["major"].Value), + int.Parse(match.Groups["minor"].Value)); map.Add(match.Groups["name"].Value, version); } - versionString = sb.ToString(); - versionMap = map; - - return sb.Length > 0; + return map; } private IEnumerable<string> GetHwaccelTypes() diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index c6b9cf67c..26db2dab0 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -18,6 +18,7 @@ namespace Jellyfin.MediaEncoding.Tests } [Theory] + [InlineData(EncoderValidatorTestsData.FFmpegV431Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV43Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV421Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] @@ -34,6 +35,7 @@ namespace Jellyfin.MediaEncoding.Tests { public IEnumerator<object?[]> GetEnumerator() { + yield return new object?[] { EncoderValidatorTestsData.FFmpegV431Output, new Version(4, 3, 1) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV43Output, new Version(4, 3) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV421Output, new Version(4, 2, 1) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs index f5ff3d723..f781471cc 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs @@ -2,6 +2,18 @@ namespace Jellyfin.MediaEncoding.Tests { internal static class EncoderValidatorTestsData { + public const string FFmpegV431Output = @"ffmpeg version n4.3.1 Copyright (c) 2000-2020 the FFmpeg developers +built with gcc 10.1.0 (GCC) +configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librav1e --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-omx --enable-shared --enable-version3 +libavutil 56. 51.100 / 56. 51.100 +libavcodec 58. 91.100 / 58. 91.100 +libavformat 58. 45.100 / 58. 45.100 +libavdevice 58. 10.100 / 58. 10.100 +libavfilter 7. 85.100 / 7. 85.100 +libswscale 5. 7.100 / 5. 7.100 +libswresample 3. 7.100 / 3. 7.100 +libpostproc 55. 7.100 / 55. 7.100"; + public const string FFmpegV43Output = @"ffmpeg version 4.3 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) configuration: --prefix=/usr/lib/jellyfin-ffmpeg --target-os=linux --disable-doc --disable-ffplay --disable-shared --disable-libxcb --disable-vdpau --disable-sdl2 --disable-xlib --enable-gpl --enable-version3 --enable-static --enable-libfontconfig --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libwebp --enable-libx264 --enable-libx265 --enable-libzvbi --arch=amd64 --enable-amf --enable-nvenc --enable-nvdec --enable-vaapi --enable-opencl -- cgit v1.2.3 From 301e029d42356d156a04d6269806d74916f80cc8 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Thu, 20 Aug 2020 17:45:40 +0200 Subject: Add unsupported ffmpeg version to tests --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 1 - .../Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs | 6 ++++-- .../EncoderValidatorTestsData.cs | 14 +++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 1c389c237..3c19109a7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index 26db2dab0..39fd8afda 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -24,7 +24,8 @@ namespace Jellyfin.MediaEncoding.Tests [InlineData(EncoderValidatorTestsData.FFmpegV42Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV414Output, true)] [InlineData(EncoderValidatorTestsData.FFmpegV404Output, true)] - [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, true)] + [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput2, true)] + [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)] public void ValidateVersionInternalTest(string versionOutput, bool valid) { var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>()); @@ -41,7 +42,8 @@ namespace Jellyfin.MediaEncoding.Tests yield return new object?[] { EncoderValidatorTestsData.FFmpegV42Output, new Version(4, 2) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV414Output, new Version(4, 1, 4) }; yield return new object?[] { EncoderValidatorTestsData.FFmpegV404Output, new Version(4, 0, 4) }; - yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, new Version(4, 0) }; + yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput2, new Version(4, 0) }; + yield return new object?[] { EncoderValidatorTestsData.FFmpegGitUnknownOutput, null }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs index f781471cc..9f5bef9a8 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTestsData.cs @@ -75,7 +75,7 @@ libswscale 5. 1.100 / 5. 1.100 libswresample 3. 1.100 / 3. 1.100 libpostproc 55. 1.100 / 55. 1.100"; - public const string FFmpegGitUnknownOutput = @"ffmpeg version N-94303-g7cb4f8c962 Copyright (c) 2000-2019 the FFmpeg developers + public const string FFmpegGitUnknownOutput2 = @"ffmpeg version N-94303-g7cb4f8c962 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.1.1 (GCC) 20190716 configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt libavutil 56. 30.100 / 56. 30.100 @@ -86,5 +86,17 @@ libavfilter 7. 56.101 / 7. 56.101 libswscale 5. 4.101 / 5. 4.101 libswresample 3. 4.100 / 3. 4.100 libpostproc 55. 4.100 / 55. 4.100"; + + public const string FFmpegGitUnknownOutput = @"ffmpeg version N-45325-gb173e0353-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2018 the FFmpeg developers +built with gcc 6.3.0 (Debian 6.3.0-18+deb9u1) 20170516 +configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gray --enable-libfribidi --enable-libass --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg +libavutil 56. 9.100 / 56. 9.100 +libavcodec 58. 14.100 / 58. 14.100 +libavformat 58. 10.100 / 58. 10.100 +libavdevice 58. 2.100 / 58. 2.100 +libavfilter 7. 13.100 / 7. 13.100 +libswscale 5. 0.102 / 5. 0.102 +libswresample 3. 0.101 / 3. 0.101 +libpostproc 55. 0.100 / 55. 0.100"; } } -- cgit v1.2.3 From 119f64f5e7b09aeb4ff8f59237093906c1e08f5f Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 21 Aug 2020 22:01:19 +0200 Subject: Make some methods async --- .../Channels/ChannelManager.cs | 21 ++++++--- .../Collections/CollectionManager.cs | 51 +++++++++------------- .../Library/LibraryManager.cs | 39 +++++++---------- .../LiveTv/LiveTvManager.cs | 16 ++++--- .../Playlists/PlaylistManager.cs | 16 +++---- Jellyfin.Api/Controllers/CollectionController.cs | 15 ++++--- Jellyfin.Api/Controllers/ImageController.cs | 14 +++--- Jellyfin.Api/Controllers/ItemUpdateController.cs | 7 +-- Jellyfin.Api/Controllers/PlaylistsController.cs | 12 ++--- Jellyfin.Api/Controllers/RemoteImageController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 14 +++--- .../Collections/ICollectionManager.cs | 12 ++--- MediaBrowser.Controller/Entities/BaseItem.cs | 20 ++++----- MediaBrowser.Controller/Entities/Folder.cs | 4 +- MediaBrowser.Controller/Entities/Video.cs | 7 +-- MediaBrowser.Controller/Library/ILibraryManager.cs | 41 +++++++++++++---- .../Playlists/IPlaylistManager.cs | 6 +-- .../Encoder/EncoderValidator.cs | 5 ++- MediaBrowser.Providers/Manager/MetadataService.cs | 4 +- MediaBrowser.Providers/TV/DummySeasonProvider.cs | 4 +- 20 files changed, 165 insertions(+), 145 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index d8ab1f1a1..26fc1bee4 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -746,12 +746,21 @@ namespace Emby.Server.Implementations.Channels // null if came from cache if (itemsResult != null) { - var internalItems = itemsResult.Items - .Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, parentItem, cancellationToken)) - .ToArray(); + var items = itemsResult.Items; + var itemsLen = items.Count; + var internalItems = new Guid[itemsLen]; + for (int i = 0; i < itemsLen; i++) + { + internalItems[i] = (await GetChannelItemEntityAsync( + items[i], + channelProvider, + channel.Id, + parentItem, + cancellationToken).ConfigureAwait(false)).Id; + } var existingIds = _libraryManager.GetItemIds(query); - var deadIds = existingIds.Except(internalItems.Select(i => i.Id)) + var deadIds = existingIds.Except(internalItems) .ToArray(); foreach (var deadId in deadIds) @@ -963,7 +972,7 @@ namespace Emby.Server.Implementations.Channels return item; } - private BaseItem GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken) + private async Task<BaseItem> GetChannelItemEntityAsync(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, BaseItem parentFolder, CancellationToken cancellationToken) { var parentFolderId = parentFolder.Id; @@ -1165,7 +1174,7 @@ namespace Emby.Server.Implementations.Channels } else if (forceUpdate) { - item.UpdateToRepository(ItemUpdateType.None, cancellationToken); + await item.UpdateToRepositoryAsync(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); } if ((isNew || forceUpdate) && info.Type == ChannelItemType.Media) diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index ac2edc1e2..3011a37e3 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -132,7 +132,7 @@ namespace Emby.Server.Implementations.Collections } /// <inheritdoc /> - public BoxSet CreateCollection(CollectionCreationOptions options) + public async Task<BoxSet> CreateCollectionAsync(CollectionCreationOptions options) { var name = options.Name; @@ -141,7 +141,7 @@ namespace Emby.Server.Implementations.Collections // This could cause it to get re-resolved as a plain folder var folderName = _fileSystem.GetValidFilename(name) + " [boxset]"; - var parentFolder = GetCollectionsFolder(true).GetAwaiter().GetResult(); + var parentFolder = await GetCollectionsFolder(true).ConfigureAwait(false); if (parentFolder == null) { @@ -169,12 +169,16 @@ namespace Emby.Server.Implementations.Collections if (options.ItemIdList.Length > 0) { - AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) - { - // The initial adding of items is going to create a local metadata file - // This will cause internet metadata to be skipped as a result - MetadataRefreshMode = MetadataRefreshMode.FullRefresh - }); + await AddToCollectionAsync( + collection.Id, + options.ItemIdList.Select(x => new Guid(x)), + false, + new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + { + // The initial adding of items is going to create a local metadata file + // This will cause internet metadata to be skipped as a result + MetadataRefreshMode = MetadataRefreshMode.FullRefresh + }).ConfigureAwait(false); } else { @@ -197,18 +201,10 @@ namespace Emby.Server.Implementations.Collections } /// <inheritdoc /> - public void AddToCollection(Guid collectionId, IEnumerable<string> ids) - { - AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - } + public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids) + => AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - /// <inheritdoc /> - public void AddToCollection(Guid collectionId, IEnumerable<Guid> ids) - { - AddToCollection(collectionId, ids.Select(i => i.ToString("N", CultureInfo.InvariantCulture)), true, new MetadataRefreshOptions(new DirectoryService(_fileSystem))); - } - - private void AddToCollection(Guid collectionId, IEnumerable<string> ids, bool fireEvent, MetadataRefreshOptions refreshOptions) + private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions) { var collection = _libraryManager.GetItemById(collectionId) as BoxSet; if (collection == null) @@ -224,15 +220,14 @@ namespace Emby.Server.Implementations.Collections foreach (var id in ids) { - var guidId = new Guid(id); - var item = _libraryManager.GetItemById(guidId); + var item = _libraryManager.GetItemById(id); if (item == null) { throw new ArgumentException("No item exists with the supplied Id"); } - if (!currentLinkedChildrenIds.Contains(guidId)) + if (!currentLinkedChildrenIds.Contains(id)) { itemList.Add(item); @@ -249,7 +244,7 @@ namespace Emby.Server.Implementations.Collections collection.UpdateRatingToItems(linkedChildrenList); - collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); refreshOptions.ForceSave = true; _providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High); @@ -266,13 +261,7 @@ namespace Emby.Server.Implementations.Collections } /// <inheritdoc /> - public void RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds) - { - RemoveFromCollection(collectionId, itemIds.Select(i => new Guid(i))); - } - - /// <inheritdoc /> - public void RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds) + public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds) { var collection = _libraryManager.GetItemById(collectionId) as BoxSet; @@ -309,7 +298,7 @@ namespace Emby.Server.Implementations.Collections collection.LinkedChildren = collection.LinkedChildren.Except(list).ToArray(); } - collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await collection.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); _providerManager.QueueRefresh( collection.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 7ed8f0bbf..375f09f5b 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -771,7 +771,7 @@ namespace Emby.Server.Implementations.Library if (folder.ParentId != rootFolder.Id) { folder.ParentId = rootFolder.Id; - folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult(); } rootFolder.AddVirtualChild(folder); @@ -1868,7 +1868,8 @@ namespace Emby.Server.Implementations.Library return image.Path != null && !image.IsLocalFile; } - public void UpdateImages(BaseItem item, bool forceUpdate = false) + /// <inheritdoc /> + public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false) { if (item == null) { @@ -1891,7 +1892,7 @@ namespace Emby.Server.Implementations.Library try { var index = item.GetImageIndex(img); - image = ConvertImageToLocal(item, img, index).ConfigureAwait(false).GetAwaiter().GetResult(); + image = await ConvertImageToLocal(item, img, index).ConfigureAwait(false); } catch (ArgumentException) { @@ -1913,7 +1914,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Cannnot get image dimensions for {0}", image.Path); + _logger.LogError(ex, "Cannot get image dimensions for {0}", image.Path); image.Width = 0; image.Height = 0; continue; @@ -1943,10 +1944,8 @@ namespace Emby.Server.Implementations.Library RegisterItem(item); } - /// <summary> - /// Updates the item. - /// </summary> - public void UpdateItems(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) + /// <inheritdoc /> + public async Task UpdateItemsAsync(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) { foreach (var item in items) { @@ -1957,7 +1956,7 @@ namespace Emby.Server.Implementations.Library item.DateLastSaved = DateTime.UtcNow; - UpdateImages(item, updateReason >= ItemUpdateType.ImageUpdate); + await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false); } _itemRepository.SaveItems(items, cancellationToken); @@ -1991,17 +1990,9 @@ namespace Emby.Server.Implementations.Library } } - /// <summary> - /// Updates the item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="parent">The parent item.</param> - /// <param name="updateReason">The update reason.</param> - /// <param name="cancellationToken">The cancellation token.</param> - public void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) - { - UpdateItems(new[] { item }, parent, updateReason, cancellationToken); - } + /// <inheritdoc /> + public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) + => UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken); /// <summary> /// Reports the item removed. @@ -2233,7 +2224,7 @@ namespace Emby.Server.Implementations.Library if (refresh) { - item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); + item.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult(); ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal); } @@ -2420,7 +2411,7 @@ namespace Emby.Server.Implementations.Library if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) { item.ViewType = viewType; - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult(); } var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; @@ -2902,7 +2893,7 @@ namespace Emby.Server.Implementations.Library await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return item.GetImageInfo(image.Type, imageIndex); } @@ -2920,7 +2911,7 @@ namespace Emby.Server.Implementations.Library // Remove this image to prevent it from retrying over and over item.RemoveImage(image); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); throw new InvalidOperationException(); } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 90cbd85a5..5ed6baeb9 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv } } - private LiveTvChannel GetChannel(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken) + private async Task<LiveTvChannel> GetChannelAsync(ChannelInfo channelInfo, string serviceName, BaseItem parentFolder, CancellationToken cancellationToken) { var parentFolderId = parentFolder.Id; var isNew = false; @@ -512,7 +512,7 @@ namespace Emby.Server.Implementations.LiveTv } else if (forceUpdate) { - _libraryManager.UpdateItem(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken); + await _libraryManager.UpdateItemAsync(item, parentFolder, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } return item; @@ -1129,7 +1129,7 @@ namespace Emby.Server.Implementations.LiveTv try { - var item = GetChannel(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken); + var item = await GetChannelAsync(channelInfo.Item2, channelInfo.Item1, parentFolder, cancellationToken).ConfigureAwait(false); list.Add(item); } @@ -1146,7 +1146,7 @@ namespace Emby.Server.Implementations.LiveTv double percent = numComplete; percent /= allChannelsList.Count; - progress.Report(5 * percent + 10); + progress.Report((5 * percent) + 10); } progress.Report(15); @@ -1221,7 +1221,11 @@ namespace Emby.Server.Implementations.LiveTv if (updatedPrograms.Count > 0) { - _libraryManager.UpdateItems(updatedPrograms, currentChannel, ItemUpdateType.MetadataImport, cancellationToken); + await _libraryManager.UpdateItemsAsync( + updatedPrograms, + currentChannel, + ItemUpdateType.MetadataImport, + cancellationToken).ConfigureAwait(false); } currentChannel.IsMovie = isMovie; @@ -1234,7 +1238,7 @@ namespace Emby.Server.Implementations.LiveTv currentChannel.AddTag("Kids"); } - currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); + await currentChannel.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); await currentChannel.RefreshMetadata( new MetadataRefreshOptions(new DirectoryService(_fileSystem)) { diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 38ceadedb..d35223b0a 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -184,17 +184,17 @@ namespace Emby.Server.Implementations.Playlists return Playlist.GetPlaylistItems(playlistMediaType, items, user, options); } - public void AddToPlaylist(string playlistId, ICollection<Guid> itemIds, Guid userId) + public Task AddToPlaylistAsync(string playlistId, ICollection<Guid> itemIds, Guid userId) { var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId); - AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false) + return AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false) { EnableImages = true }); } - private void AddToPlaylistInternal(string playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options) + private async Task AddToPlaylistInternal(string playlistId, ICollection<Guid> newItemIds, User user, DtoOptions options) { // Retrieve the existing playlist var playlist = _libraryManager.GetItemById(playlistId) as Playlist @@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.Playlists // Update the playlist in the repository playlist.LinkedChildren = newLinkedChildren; - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); // Update the playlist on disk if (playlist.IsFile) @@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.Playlists RefreshPriority.High); } - public void RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds) + public async Task RemoveFromPlaylistAsync(string playlistId, IEnumerable<string> entryIds) { if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) { @@ -273,7 +273,7 @@ namespace Emby.Server.Implementations.Playlists .Select(i => i.Item1) .ToArray(); - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (playlist.IsFile) { @@ -289,7 +289,7 @@ namespace Emby.Server.Implementations.Playlists RefreshPriority.High); } - public void MoveItem(string playlistId, string entryId, int newIndex) + public async Task MoveItemAsync(string playlistId, string entryId, int newIndex) { if (!(_libraryManager.GetItemById(playlistId) is Playlist playlist)) { @@ -322,7 +322,7 @@ namespace Emby.Server.Implementations.Playlists playlist.LinkedChildren = newList.ToArray(); - playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await playlist.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (playlist.IsFile) { diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 53821a188..c5910d6e8 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -51,7 +52,7 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="CollectionCreationOptions"/> with information about the new collection.</returns> [HttpPost] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult<CollectionCreationResult> CreateCollection( + public async Task<ActionResult<CollectionCreationResult>> CreateCollection( [FromQuery] string? name, [FromQuery] string? ids, [FromQuery] Guid? parentId, @@ -59,14 +60,14 @@ namespace Jellyfin.Api.Controllers { var userId = _authContext.GetAuthorizationInfo(Request).UserId; - var item = _collectionManager.CreateCollection(new CollectionCreationOptions + var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions { IsLocked = isLocked, Name = name, ParentId = parentId, ItemIdList = RequestHelpers.Split(ids, ',', true), UserIds = new[] { userId } - }); + }).ConfigureAwait(false); var dtoOptions = new DtoOptions().AddClientFields(Request); @@ -87,9 +88,9 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="NoContentResult"/> indicating success.</returns> [HttpPost("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task<ActionResult> AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) { - _collectionManager.AddToCollection(collectionId, RequestHelpers.Split(itemIds, ',', true)); + await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true); return NoContent(); } @@ -102,9 +103,9 @@ namespace Jellyfin.Api.Controllers /// <returns>A <see cref="NoContentResult"/> indicating success.</returns> [HttpDelete("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task<ActionResult> RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) { - _collectionManager.RemoveFromCollection(collectionId, RequestHelpers.Split(itemIds, ',', true)); + await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false); return NoContent(); } } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 75734f0af..ca9c2fa46 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -174,7 +174,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteItemImage( + public async Task<ActionResult> DeleteItemImage( [FromRoute] Guid itemId, [FromRoute] ImageType imageType, [FromRoute] int? imageIndex = null) @@ -185,7 +185,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - item.DeleteImage(imageType, imageIndex ?? 0); + await item.DeleteImageAsync(imageType, imageIndex ?? 0).ConfigureAwait(false); return NoContent(); } @@ -218,7 +218,7 @@ namespace Jellyfin.Api.Controllers // Handle image/png; charset=utf-8 var mimeType = Request.ContentType.Split(';').FirstOrDefault(); await _providerManager.SaveImage(item, Request.Body, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -237,7 +237,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItemImageIndex( + public async Task<ActionResult> UpdateItemImageIndex( [FromRoute] Guid itemId, [FromRoute] ImageType imageType, [FromRoute] int imageIndex, @@ -249,7 +249,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - item.SwapImages(imageType, imageIndex, newIndex); + await item.SwapImagesAsync(imageType, imageIndex, newIndex).ConfigureAwait(false); return NoContent(); } @@ -264,7 +264,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult<IEnumerable<ImageInfo>> GetItemImageInfos([FromRoute] Guid itemId) + public async Task<ActionResult<IEnumerable<ImageInfo>>> GetItemImageInfos([FromRoute] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers return list; } - _libraryManager.UpdateImages(item); // this makes sure dimensions and hashes are correct + await _libraryManager.UpdateImagesAsync(item).ConfigureAwait(false); // this makes sure dimensions and hashes are correct foreach (var image in itemImages) { diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 4b40c6ada..ec52f4996 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -67,7 +68,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request) + public async Task<ActionResult> UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -101,7 +102,7 @@ namespace Jellyfin.Api.Controllers item.OnMetadataChanged(); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (isLockedChanged && item.IsFolder) { @@ -110,7 +111,7 @@ namespace Jellyfin.Api.Controllers foreach (var child in folder.GetRecursiveChildren()) { child.IsLocked = newLockData; - child.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await child.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } } diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index 12c87d7c3..d69228c33 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -83,12 +83,12 @@ namespace Jellyfin.Api.Controllers /// <returns>An <see cref="NoContentResult"/> on success.</returns> [HttpPost("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult AddToPlaylist( + public async Task<ActionResult> AddToPlaylist( [FromRoute] string? playlistId, [FromQuery] string? ids, [FromQuery] Guid? userId) { - _playlistManager.AddToPlaylist(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty); + await _playlistManager.AddToPlaylistAsync(playlistId, RequestHelpers.GetGuids(ids), userId ?? Guid.Empty).ConfigureAwait(false); return NoContent(); } @@ -102,12 +102,12 @@ namespace Jellyfin.Api.Controllers /// <returns>An <see cref="NoContentResult"/> on success.</returns> [HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult MoveItem( + public async Task<ActionResult> MoveItem( [FromRoute] string? playlistId, [FromRoute] string? itemId, [FromRoute] int newIndex) { - _playlistManager.MoveItem(playlistId, itemId, newIndex); + await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false); return NoContent(); } @@ -120,9 +120,9 @@ namespace Jellyfin.Api.Controllers /// <returns>An <see cref="NoContentResult"/> on success.</returns> [HttpDelete("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds) + public async Task<ActionResult> RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds) { - _playlistManager.RemoveFromPlaylist(playlistId, RequestHelpers.Split(entryIds, ',', true)); + await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index a203c50b9..30a4f73fc 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -221,7 +221,7 @@ namespace Jellyfin.Api.Controllers await _providerManager.SaveImage(item, imageUrl, type, null, CancellationToken.None) .ConfigureAwait(false); - item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 14d3f2460..f42810c94 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteAlternateSources([FromRoute] Guid itemId) + public async Task<ActionResult> DeleteAlternateSources([FromRoute] Guid itemId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -180,12 +180,12 @@ namespace Jellyfin.Api.Controllers link.SetPrimaryVersionId(null); link.LinkedAlternateVersions = Array.Empty<LinkedChild>(); - link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } video.LinkedAlternateVersions = Array.Empty<LinkedChild>(); video.SetPrimaryVersionId(null); - video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await video.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public ActionResult MergeVersions([FromQuery, Required] string? itemIds) + public async Task<ActionResult> MergeVersions([FromQuery, Required] string? itemIds) { var items = RequestHelpers.Split(itemIds, ',', true) .Select(i => _libraryManager.GetItemById(i)) @@ -239,7 +239,7 @@ namespace Jellyfin.Api.Controllers { item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture)); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); list.Add(new LinkedChild { @@ -258,12 +258,12 @@ namespace Jellyfin.Api.Controllers if (item.LinkedAlternateVersions.Length > 0) { item.LinkedAlternateVersions = Array.Empty<LinkedChild>(); - item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } } primaryVersion.LinkedAlternateVersions = list.ToArray(); - primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None); + await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); return NoContent(); } diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs index 701423c0f..3861ae634 100644 --- a/MediaBrowser.Controller/Collections/ICollectionManager.cs +++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -27,24 +28,23 @@ namespace MediaBrowser.Controller.Collections /// Creates the collection. /// </summary> /// <param name="options">The options.</param> - BoxSet CreateCollection(CollectionCreationOptions options); + Task<BoxSet> CreateCollectionAsync(CollectionCreationOptions options); /// <summary> /// Adds to collection. /// </summary> /// <param name="collectionId">The collection identifier.</param> /// <param name="itemIds">The item ids.</param> - void AddToCollection(Guid collectionId, IEnumerable<string> itemIds); + /// <returns><see cref="Task"/> representing the asynchronous operation.</returns> + Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds); /// <summary> /// Removes from collection. /// </summary> /// <param name="collectionId">The collection identifier.</param> /// <param name="itemIds">The item ids.</param> - void RemoveFromCollection(Guid collectionId, IEnumerable<string> itemIds); - - void AddToCollection(Guid collectionId, IEnumerable<Guid> itemIds); - void RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds); + /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> + Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds); /// <summary> /// Collapses the items within box sets. diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f34309c40..9e595ddc3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1390,7 +1390,7 @@ namespace MediaBrowser.Controller.Entities new List<FileSystemMetadata>(); var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); - LibraryManager.UpdateImages(this); // ensure all image properties in DB are fresh + await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh if (ownedItemsChanged) { @@ -2279,7 +2279,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="type">The type.</param> /// <param name="index">The index.</param> - public void DeleteImage(ImageType type, int index) + public async Task DeleteImageAsync(ImageType type, int index) { var info = GetImageInfo(type, index); @@ -2297,7 +2297,7 @@ namespace MediaBrowser.Controller.Entities FileSystem.DeleteFile(info.Path); } - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + await UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); } public void RemoveImage(ItemImageInfo image) @@ -2310,10 +2310,8 @@ namespace MediaBrowser.Controller.Entities ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } - public virtual void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) - { - LibraryManager.UpdateItem(this, GetParent(), updateReason, cancellationToken); - } + public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) + => LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken); /// <summary> /// Validates that images within the item are still on the filesystem. @@ -2558,7 +2556,7 @@ namespace MediaBrowser.Controller.Entities return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; } - public void SwapImages(ImageType type, int index1, int index2) + public Task SwapImagesAsync(ImageType type, int index1, int index2) { if (!AllowsMultipleImages(type)) { @@ -2571,13 +2569,13 @@ namespace MediaBrowser.Controller.Entities if (info1 == null || info2 == null) { // Nothing to do - return; + return Task.CompletedTask; } if (!info1.IsLocalFile || !info2.IsLocalFile) { // TODO: Not supported yet - return; + return Task.CompletedTask; } var path1 = info1.Path; @@ -2594,7 +2592,7 @@ namespace MediaBrowser.Controller.Entities info2.Width = 0; info2.Height = 0; - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + return UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None); } public virtual bool IsPlayed(User user) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 6441340f9..11542c1ca 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -350,12 +350,12 @@ namespace MediaBrowser.Controller.Entities if (currentChild.UpdateFromResolvedItem(child) > ItemUpdateType.None) { - currentChild.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); + await currentChild.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } else { // metadata is up-to-date; make sure DB has correct images dimensions and hash - LibraryManager.UpdateImages(currentChild); + await LibraryManager.UpdateImagesAsync(currentChild).ConfigureAwait(false); } continue; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index b7d7e8e1a..eeff78e10 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -495,9 +495,10 @@ namespace MediaBrowser.Controller.Entities } } - public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + /// <inheritdoc /> + public override async Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) { - base.UpdateToRepository(updateReason, cancellationToken); + await base.UpdateToRepositoryAsync(updateReason, cancellationToken).ConfigureAwait(false); var localAlternates = GetLocalAlternateVersionIds() .Select(i => LibraryManager.GetItemById(i)) @@ -514,7 +515,7 @@ namespace MediaBrowser.Controller.Entities item.Genres = Genres; item.ProviderIds = ProviderIds; - item.UpdateToRepository(ItemUpdateType.MetadataDownload, cancellationToken); + await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9abcf2b62..d53b1fc8d 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Controller.Library /// <param name="name">The name.</param> /// <returns>Task{Artist}.</returns> MusicArtist GetArtist(string name); + MusicArtist GetArtist(string name, DtoOptions options); /// <summary> /// Gets a Studio. @@ -124,7 +125,7 @@ namespace MediaBrowser.Controller.Library /// </summary> void QueueLibraryScan(); - void UpdateImages(BaseItem item, bool forceUpdate = false); + Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false); /// <summary> /// Gets the default view. @@ -179,6 +180,7 @@ namespace MediaBrowser.Controller.Library /// <param name="sortOrder">The sort order.</param> /// <returns>IEnumerable{BaseItem}.</returns> IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder); + IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderBy); /// <summary> @@ -200,9 +202,16 @@ namespace MediaBrowser.Controller.Library /// <summary> /// Updates the item. /// </summary> - void UpdateItems(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); + Task UpdateItemsAsync(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); - void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); + /// <summary> + /// Updates the item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="parent">The parent item.</param> + /// <param name="updateReason">The update reason.</param> + /// <param name="cancellationToken">The cancellation token.</param> + Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); /// <summary> /// Retrieves the item. @@ -317,7 +326,8 @@ namespace MediaBrowser.Controller.Library /// <param name="name">The name.</param> /// <param name="viewType">Type of the view.</param> /// <param name="sortName">Name of the sort.</param> - UserView GetNamedView(string name, + UserView GetNamedView( + string name, string viewType, string sortName); @@ -329,7 +339,8 @@ namespace MediaBrowser.Controller.Library /// <param name="viewType">Type of the view.</param> /// <param name="sortName">Name of the sort.</param> /// <param name="uniqueId">The unique identifier.</param> - UserView GetNamedView(string name, + UserView GetNamedView( + string name, Guid parentId, string viewType, string sortName, @@ -341,7 +352,8 @@ namespace MediaBrowser.Controller.Library /// <param name="parent">The parent.</param> /// <param name="viewType">Type of the view.</param> /// <param name="sortName">Name of the sort.</param> - UserView GetShadowView(BaseItem parent, + UserView GetShadowView( + BaseItem parent, string viewType, string sortName); @@ -393,7 +405,9 @@ namespace MediaBrowser.Controller.Library /// <param name="fileSystemChildren">The file system children.</param> /// <param name="directoryService">The directory service.</param> /// <returns>IEnumerable<Trailer>.</returns> - IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, + IEnumerable<Video> FindTrailers( + BaseItem owner, + List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService); /// <summary> @@ -403,7 +417,9 @@ namespace MediaBrowser.Controller.Library /// <param name="fileSystemChildren">The file system children.</param> /// <param name="directoryService">The directory service.</param> /// <returns>IEnumerable<Video>.</returns> - IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, + IEnumerable<Video> FindExtras( + BaseItem owner, + List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService); /// <summary> @@ -522,16 +538,25 @@ namespace MediaBrowser.Controller.Library Guid GetMusicGenreId(string name); Task AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary); + Task RemoveVirtualFolder(string name, bool refreshLibrary); + void AddMediaPath(string virtualFolderName, MediaPathInfo path); + void UpdateMediaPath(string virtualFolderName, MediaPathInfo path); + void RemoveMediaPath(string virtualFolderName, string path); QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query); int GetCount(InternalItemsQuery query); diff --git a/MediaBrowser.Controller/Playlists/IPlaylistManager.cs b/MediaBrowser.Controller/Playlists/IPlaylistManager.cs index 544cd2643..e92abccd1 100644 --- a/MediaBrowser.Controller/Playlists/IPlaylistManager.cs +++ b/MediaBrowser.Controller/Playlists/IPlaylistManager.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Controller.Playlists /// <param name="itemIds">The item ids.</param> /// <param name="userId">The user identifier.</param> /// <returns>Task.</returns> - void AddToPlaylist(string playlistId, ICollection<Guid> itemIds, Guid userId); + Task AddToPlaylistAsync(string playlistId, ICollection<Guid> itemIds, Guid userId); /// <summary> /// Removes from playlist. @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.Playlists /// <param name="playlistId">The playlist identifier.</param> /// <param name="entryIds">The entry ids.</param> /// <returns>Task.</returns> - void RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds); + Task RemoveFromPlaylistAsync(string playlistId, IEnumerable<string> entryIds); /// <summary> /// Gets the playlists folder. @@ -53,6 +53,6 @@ namespace MediaBrowser.Controller.Playlists /// <param name="entryId">The entry identifier.</param> /// <param name="newIndex">The new index.</param> /// <returns>Task.</returns> - void MoveItem(string playlistId, string entryId, int newIndex); + Task MoveItemAsync(string playlistId, string entryId, int newIndex); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 3c19109a7..c8bf5557b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; @@ -258,8 +259,8 @@ namespace MediaBrowser.MediaEncoding.Encoder RegexOptions.Multiline)) { var version = new Version( - int.Parse(match.Groups["major"].Value), - int.Parse(match.Groups["minor"].Value)); + int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture), + int.Parse(match.Groups["minor"].Value, CultureInfo.InvariantCulture)); map.Add(match.Groups["name"].Value, version); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index dcae300fc..d0de58427 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -212,7 +212,7 @@ namespace MediaBrowser.Providers.Manager await SavePeopleMetadataAsync(result.People, libraryOptions, cancellationToken).ConfigureAwait(false); } - result.Item.UpdateToRepository(reason, cancellationToken); + await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false); } private async Task SavePeopleMetadataAsync(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken) @@ -246,7 +246,7 @@ namespace MediaBrowser.Providers.Manager if (saveEntity) { - personEntity.UpdateToRepository(updateType, cancellationToken); + await personEntity.UpdateToRepositoryAsync(updateType, cancellationToken).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index df09d13dd..0c09cdef6 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Providers.TV else if (existingSeason.IsVirtualItem) { existingSeason.IsVirtualItem = false; - existingSeason.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken); + await existingSeason.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); seasons = null; } } @@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV else if (existingSeason.IsVirtualItem) { existingSeason.IsVirtualItem = false; - existingSeason.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken); + await existingSeason.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); seasons = null; } } -- cgit v1.2.3 From 8b96881aa1667495c78b0955321254da0dc5a22f Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Wed, 26 Aug 2020 08:22:48 -0600 Subject: Clean up json Converters --- .../Extensions/ApiServiceCollectionExtensions.cs | 1 + .../Json/Converters/JsonDoubleConverter.cs | 56 --------------- .../Json/Converters/JsonInt32Converter.cs | 40 ----------- .../Json/Converters/JsonInt64Converter.cs | 56 --------------- .../JsonNonStringKeyDictionaryConverter.cs | 82 ---------------------- .../JsonNonStringKeyDictionaryConverterFactory.cs | 59 ---------------- .../Json/Converters/JsonNullableInt32Converter.cs | 60 ---------------- .../Json/Converters/JsonNullableInt64Converter.cs | 75 -------------------- MediaBrowser.Common/Json/JsonDefaults.cs | 9 +-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 ++ .../Probing/MediaStreamInfo.cs | 1 - .../FFprobeParserTests.cs | 3 +- 12 files changed, 11 insertions(+), 437 deletions(-) delete mode 100644 MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index ddbe0edb7..0fd599cfc 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -169,6 +169,7 @@ namespace Jellyfin.Server.Extensions options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition; + options.JsonSerializerOptions.NumberHandling = jsonOptions.NumberHandling; options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) diff --git a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs b/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs deleted file mode 100644 index 56c0ecbe9..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Double to String JSON converter. - /// Web client send quoted doubles. - /// </summary> - public class JsonDoubleConverter : JsonConverter<double> - { - /// <summary> - /// Read JSON string as double. - /// </summary> - /// <param name="reader"><see cref="Utf8JsonReader"/>.</param> - /// <param name="typeToConvert">Type.</param> - /// <param name="options">Options.</param> - /// <returns>Parsed value.</returns> - public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out double number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (double.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetDouble(); - } - - /// <summary> - /// Write double to JSON string. - /// </summary> - /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param> - /// <param name="value">Value to write.</param> - /// <param name="options">Options.</param> - public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs deleted file mode 100644 index 7ed9d6766..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a int32 object or value to/from JSON. - /// </summary> - public class JsonInt32Converter : JsonConverter<int> - { - /// <inheritdoc /> - public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - if (int.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - return reader.GetInt32(); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs deleted file mode 100644 index 427f1fa7e..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Parse JSON string as long. - /// Javascript does not support 64-bit integers. - /// </summary> - public class JsonInt64Converter : JsonConverter<long> - { - /// <summary> - /// Read JSON string as int64. - /// </summary> - /// <param name="reader"><see cref="Utf8JsonReader"/>.</param> - /// <param name="type">Type.</param> - /// <param name="options">Options.</param> - /// <returns>Parsed value.</returns> - public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (long.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetInt64(); - } - - /// <summary> - /// Write long to JSON long. - /// </summary> - /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param> - /// <param name="value">Value to write.</param> - /// <param name="options">Options.</param> - public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs deleted file mode 100644 index 8053461f0..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs +++ /dev/null @@ -1,82 +0,0 @@ -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converter for Dictionaries without string key. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// </summary> - /// <typeparam name="TKey">Type of key.</typeparam> - /// <typeparam name="TValue">Type of value.</typeparam> - internal sealed class JsonNonStringKeyDictionaryConverter<TKey, TValue> : JsonConverter<IDictionary<TKey, TValue>> - { - /// <summary> - /// Read JSON. - /// </summary> - /// <param name="reader">The Utf8JsonReader.</param> - /// <param name="typeToConvert">The type to convert.</param> - /// <param name="options">The json serializer options.</param> - /// <returns>Typed dictionary.</returns> - /// <exception cref="NotSupportedException">Dictionary key type not supported.</exception> - public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var convertedType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]); - var value = JsonSerializer.Deserialize(ref reader, convertedType, options); - var instance = (Dictionary<TKey, TValue>)Activator.CreateInstance( - typeToConvert, - BindingFlags.Instance | BindingFlags.Public, - null, - null, - CultureInfo.CurrentCulture); - var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null); - var parse = typeof(TKey).GetMethod( - "Parse", - 0, - BindingFlags.Public | BindingFlags.Static, - null, - CallingConventions.Any, - new[] { typeof(string) }, - null); - if (parse == null) - { - throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary<TKey, TValue> is not supported."); - } - - while (enumerator.MoveNext()) - { - var element = (KeyValuePair<string?, TValue>)enumerator.Current; - instance.Add((TKey)parse.Invoke(null, new[] { (object?)element.Key }), element.Value); - } - - return instance; - } - - /// <summary> - /// Write dictionary as Json. - /// </summary> - /// <param name="writer">The Utf8JsonWriter.</param> - /// <param name="value">The dictionary value.</param> - /// <param name="options">The Json serializer options.</param> - public override void Write(Utf8JsonWriter writer, IDictionary<TKey, TValue> value, JsonSerializerOptions options) - { - var convertedDictionary = new Dictionary<string?, TValue>(value.Count); - foreach (var (k, v) in value) - { - if (k != null) - { - convertedDictionary[k.ToString()] = v; - } - } - - JsonSerializer.Serialize(writer, convertedDictionary, options); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs deleted file mode 100644 index 52f360740..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs +++ /dev/null @@ -1,59 +0,0 @@ -#nullable enable - -using System; -using System.Collections; -using System.Globalization; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// https://github.com/dotnet/runtime/issues/30524#issuecomment-524619972. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// </summary> - internal sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory - { - /// <summary> - /// Only convert objects that implement IDictionary and do not have string keys. - /// </summary> - /// <param name="typeToConvert">Type convert.</param> - /// <returns>Conversion ability.</returns> - public override bool CanConvert(Type typeToConvert) - { - if (!typeToConvert.IsGenericType) - { - return false; - } - - // Let built in converter handle string keys - if (typeToConvert.GenericTypeArguments[0] == typeof(string)) - { - return false; - } - - // Only support objects that implement IDictionary - return typeToConvert.GetInterface(nameof(IDictionary)) != null; - } - - /// <summary> - /// Create converter for generic dictionary type. - /// </summary> - /// <param name="typeToConvert">Type to convert.</param> - /// <param name="options">Json serializer options.</param> - /// <returns>JsonConverter for given type.</returns> - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var converterType = typeof(JsonNonStringKeyDictionaryConverter<,>) - .MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]); - var converter = (JsonConverter)Activator.CreateInstance( - converterType, - BindingFlags.Instance | BindingFlags.Public, - null, - null, - CultureInfo.CurrentCulture); - return converter; - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs deleted file mode 100644 index 9db44d626..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a nullable int32 object or value to/from JSON. - /// </summary> - public class JsonNullableInt32Converter : JsonConverter<int?> - { - /// <inheritdoc /> - public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - if (reader.TokenType == JsonTokenType.String) - { - ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - var stringValue = reader.GetString().AsSpan(); - - // value is null or empty, just return null. - if (stringValue.IsEmpty) - { - return null; - } - - if (int.TryParse(stringValue, out number)) - { - return number; - } - } - - return reader.GetInt32(); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) - { - if (value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteNumberValue(value.Value); - } - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs deleted file mode 100644 index a9cdc23d7..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Parse JSON string as nullable long. - /// Javascript does not support 64-bit integers. - /// </summary> - public class JsonNullableInt64Converter : JsonConverter<long?> - { - /// <summary> - /// Read JSON string as int64. - /// </summary> - /// <param name="reader"><see cref="Utf8JsonReader"/>.</param> - /// <param name="type">Type.</param> - /// <param name="options">Options.</param> - /// <returns>Parsed value.</returns> - public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - var stringValue = reader.GetString().AsSpan(); - - // value is null or empty, just return null. - if (stringValue.IsEmpty) - { - return null; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (long.TryParse(stringValue, out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetInt64(); - } - - /// <summary> - /// Write long to JSON long. - /// </summary> - /// <param name="writer"><see cref="Utf8JsonWriter"/>.</param> - /// <param name="value">Value to write.</param> - /// <param name="options">Options.</param> - public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options) - { - if (value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteNumberValue(value.Value); - } - } - } -} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index b46ecffc7..9d30927db 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -25,17 +25,12 @@ namespace MediaBrowser.Common.Json { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString }; options.Converters.Add(new JsonGuidConverter()); - options.Converters.Add(new JsonInt32Converter()); - options.Converters.Add(new JsonNullableInt32Converter()); options.Converters.Add(new JsonStringEnumConverter()); - options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory()); - options.Converters.Add(new JsonInt64Converter()); - options.Converters.Add(new JsonNullableInt64Converter()); - options.Converters.Add(new JsonDoubleConverter()); return options; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9d01da40f..5a3a9185d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; @@ -54,6 +55,9 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); + // MediaEncoder is registered as a Singleton + private readonly JsonSerializerOptions _jsonSerializerOptions; + private List<string> _encoders = new List<string>(); private List<string> _decoders = new List<string>(); private List<string> _hwaccels = new List<string>(); @@ -75,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _localization = localization; _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; + _jsonSerializerOptions = JsonDefaults.GetOptions(); } private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; @@ -414,6 +419,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { result = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>( process.StandardOutput.BaseStream, + _jsonSerializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false); } catch diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 8996d3b09..b7b23deff 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -133,7 +133,6 @@ namespace MediaBrowser.MediaEncoding.Probing /// </summary> /// <value>The bits_per_raw_sample.</value> [JsonPropertyName("bits_per_raw_sample")] - [JsonConverter(typeof(JsonInt32Converter))] public int BitsPerRawSample { get; set; } /// <summary> diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 2032f6cec..c39ef0ce9 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -1,6 +1,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; +using MediaBrowser.Common.Json; using MediaBrowser.MediaEncoding.Probing; using Xunit; @@ -15,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests var path = Path.Join("Test Data", fileName); using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream).ConfigureAwait(false); + await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.GetOptions()).ConfigureAwait(false); } } } -- cgit v1.2.3 From 30ba35a33b1aa131bd5f3f3a82cf03b033f7f190 Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Mon, 31 Aug 2020 11:07:40 -0600 Subject: Use HttpClientFactory in SubtitleEncoder --- .../MediaBrowser.MediaEncoding.csproj | 1 + .../Subtitles/SubtitleEncoder.cs | 27 ++++++++++------------ 2 files changed, 13 insertions(+), 15 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 814edd732..6ead93e09 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,6 +24,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" /> <PackageReference Include="UTF.Unknown" Version="2.3.0" /> </ItemGroup> diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 6ac5ac2ff..0a9958b9e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -31,7 +32,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IMediaSourceManager _mediaSourceManager; /// <summary> @@ -46,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IMediaSourceManager mediaSourceManager) { _libraryManager = libraryManager; @@ -54,7 +55,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _appPaths = appPaths; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _mediaSourceManager = mediaSourceManager; } @@ -750,24 +751,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) + private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) { switch (protocol) { case MediaProtocol.Http: - var opts = new HttpRequestOptions() - { - Url = path, - CancellationToken = cancellationToken, - - // Needed for seeking - BufferContent = true - }; - - return _httpClient.Get(opts); + { + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(path, cancellationToken) + .ConfigureAwait(false); + return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + } case MediaProtocol.File: - return Task.FromResult<Stream>(File.OpenRead(path)); + return File.OpenRead(path); default: throw new ArgumentOutOfRangeException(nameof(protocol)); } -- cgit v1.2.3 From 5464eaed4ae0e1927883fce89d02ed2b6e60a745 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Sat, 19 Sep 2020 16:40:39 +0100 Subject: Update EncoderValidator.cs --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index c8bf5557b..3287f9814 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -212,7 +212,10 @@ namespace MediaBrowser.MediaEncoding.Encoder if (match.Success) { - return new Version(match.Groups[1].Value); + if (Version.TryParse(match.Groups[1].Value, out var result)) + { + return result; + } } var versionMap = GetFFmpegLibraryVersions(output); -- cgit v1.2.3 From 3ad62329731c1156566bd707f21cad60e74f9a5f Mon Sep 17 00:00:00 2001 From: Stanislav Ionascu <stanislav.ionascu@gmail.com> Date: Thu, 24 Sep 2020 08:41:42 +0200 Subject: Add probe / direct-stream / transcoding support for BluRays This commit (and ffmpeg built with libbluray support), adds support for playback of bluray images (bd-iso) and bluray folders. --- .../MediaEncoder/EncodingManager.cs | 20 +++++------ Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 4 +-- .../MediaEncoding/EncodingHelper.cs | 24 ++----------- .../MediaEncoding/IMediaEncoder.cs | 11 +++--- .../MediaEncoding/MediaEncoderHelpers.cs | 10 ++---- .../Attachments/AttachmentExtractor.cs | 16 ++++----- .../Encoder/EncodingUtils.cs | 14 ++++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 42 ++++++++++++++-------- .../Subtitles/SubtitleEncoder.cs | 36 +++++++++---------- .../MediaInfo/FFProbeProvider.cs | 5 --- .../MediaInfo/VideoImageProvider.cs | 21 ++++++++--- 11 files changed, 101 insertions(+), 102 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 438bbe24a..791d00963 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -81,12 +82,7 @@ namespace Emby.Server.Implementations.MediaEncoder return false; } - if (video.VideoType == VideoType.Iso) - { - return false; - } - - if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd) + if (video.VideoType == VideoType.Dvd) { return false; } @@ -140,15 +136,19 @@ namespace Emby.Server.Implementations.MediaEncoder // Add some time for the first chapter to make sure we don't end up with a black image var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - var protocol = MediaProtocol.File; - - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, null, Array.Empty<string>()); + var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, Array.Empty<string>()); Directory.CreateDirectory(Path.GetDirectoryName(path)); var container = video.Container; + var mediaSource = new MediaSourceInfo + { + VideoType = video.VideoType, + IsoType = video.IsoType, + Protocol = video.PathProtocol.Value, + }; - var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); + var tempFile = await _encoder.ExtractVideoImage(inputPath, container, mediaSource, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); File.Copy(tempFile, path, true); try diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 64d1227f7..465857b01 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -762,7 +762,7 @@ namespace Jellyfin.Api.Helpers private async Task AcquireResources(StreamState state, CancellationTokenSource cancellationTokenSource) { - if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && _isoManager.CanMount(state.MediaPath)) + if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && state.IsoType == IsoType.Dvd && _isoManager.CanMount(state.MediaPath)) { state.IsoMount = await _isoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index c5529ad5b..7481cc7b9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -379,25 +379,9 @@ namespace MediaBrowser.Controller.MediaEncoding public string GetInputPathArgument(EncodingJobInfo state) { - var protocol = state.InputProtocol; var mediaPath = state.MediaPath ?? string.Empty; - string[] inputPath; - if (state.IsInputVideo - && !(state.VideoType == VideoType.Iso && state.IsoMount == null)) - { - inputPath = MediaEncoderHelpers.GetInputArgument( - _fileSystem, - mediaPath, - state.IsoMount, - state.PlayableStreamFileNames); - } - else - { - inputPath = new[] { mediaPath }; - } - - return _mediaEncoder.GetInputArgument(inputPath, protocol); + return _mediaEncoder.GetInputArgument(mediaPath, state.MediaSource); } /// <summary> @@ -2546,14 +2530,10 @@ namespace MediaBrowser.Controller.MediaEncoding { state.VideoType = mediaSource.VideoType.Value; - if (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd) + if (mediaSource.VideoType.Value == VideoType.Dvd) { state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, mediaSource.VideoType.Value).Select(Path.GetFileName).ToArray(); } - else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.BluRay) - { - state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.BluRay).Select(Path.GetFileName).ToArray(); - } else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.Dvd) { state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.Dvd).Select(Path.GetFileName).ToArray(); diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 17d6dc5d2..5c070122d 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -61,9 +62,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Extracts the video image. /// </summary> - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); /// <summary> /// Extracts the video images on interval. @@ -71,7 +72,7 @@ namespace MediaBrowser.Controller.MediaEncoding Task ExtractVideoImagesOnInterval(string[] inputFiles, string container, MediaStream videoStream, - MediaProtocol protocol, + MediaSourceInfo mediaSource, Video3DFormat? threedFormat, TimeSpan interval, string targetDirectory, @@ -91,9 +92,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// Gets the input argument. /// </summary> /// <param name="inputFiles">The input files.</param> - /// <param name="protocol">The protocol.</param> + /// <param name="mediaSource">The mediaSource.</param> /// <returns>System.String.</returns> - string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol); + string GetInputArgument(IReadOnlyList<string> inputFiles, MediaSourceInfo mediaSource); /// <summary> /// Gets the time parameter. diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index ce53c23ad..df2d2fa57 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -18,19 +18,13 @@ namespace MediaBrowser.Controller.MediaEncoding /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="videoPath">The video path.</param> - /// <param name="isoMount">The iso mount.</param> /// <param name="playableStreamFileNames">The playable stream file names.</param> /// <returns>string[].</returns> - public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IIsoMount isoMount, IReadOnlyCollection<string> playableStreamFileNames) + public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IReadOnlyCollection<string> playableStreamFileNames) { if (playableStreamFileNames.Count > 0) { - if (isoMount == null) - { - return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames); - } - - return GetPlayableStreamFiles(fileSystem, isoMount.MountedPath, playableStreamFileNames); + return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames); } return new[] { videoPath }; diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 21b5d0c5b..466fd75e1 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -87,19 +87,19 @@ namespace MediaBrowser.MediaEncoding.Attachments MediaAttachment mediaAttachment, CancellationToken cancellationToken) { - var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); + var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource, mediaAttachment, cancellationToken).ConfigureAwait(false); return File.OpenRead(attachmentPath); } private async Task<string> GetReadableFile( string mediaPath, string inputFile, - MediaProtocol protocol, + MediaSourceInfo mediaSource, MediaAttachment mediaAttachment, CancellationToken cancellationToken) { - var outputPath = GetAttachmentCachePath(mediaPath, protocol, mediaAttachment.Index); - await ExtractAttachment(inputFile, protocol, mediaAttachment.Index, outputPath, cancellationToken) + var outputPath = GetAttachmentCachePath(mediaPath, mediaSource, mediaAttachment.Index); + await ExtractAttachment(inputFile, mediaSource, mediaAttachment.Index, outputPath, cancellationToken) .ConfigureAwait(false); return outputPath; @@ -107,7 +107,7 @@ namespace MediaBrowser.MediaEncoding.Attachments private async Task ExtractAttachment( string inputFile, - MediaProtocol protocol, + MediaSourceInfo mediaSource, int attachmentStreamIndex, string outputPath, CancellationToken cancellationToken) @@ -121,7 +121,7 @@ namespace MediaBrowser.MediaEncoding.Attachments if (!File.Exists(outputPath)) { await ExtractAttachmentInternal( - _mediaEncoder.GetInputArgument(new[] { inputFile }, protocol), + _mediaEncoder.GetInputArgument(new[] { inputFile }, mediaSource), attachmentStreamIndex, outputPath, cancellationToken).ConfigureAwait(false); @@ -234,10 +234,10 @@ namespace MediaBrowser.MediaEncoding.Attachments } } - private string GetAttachmentCachePath(string mediaPath, MediaProtocol protocol, int attachmentStreamIndex) + private string GetAttachmentCachePath(string mediaPath, MediaSourceInfo mediaSource, int attachmentStreamIndex) { string filename; - if (protocol == MediaProtocol.File) + if (mediaSource.Protocol == MediaProtocol.File) { var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D", CultureInfo.InvariantCulture); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 63310fdf6..b1fcba2d1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { public static class EncodingUtils { - public static string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol) + public static string GetInputArgument(string inputPrefix, IReadOnlyList<string> inputFiles, MediaProtocol protocol) { if (protocol != MediaProtocol.File) { @@ -19,15 +19,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", url); } - return GetConcatInputArgument(inputFiles); + return GetConcatInputArgument(inputFiles, inputPrefix); } /// <summary> /// Gets the concat input argument. /// </summary> /// <param name="inputFiles">The input files.</param> + /// <param name="inputPrefix">The input prefix.</param> /// <returns>System.String.</returns> - private static string GetConcatInputArgument(IReadOnlyList<string> inputFiles) + private static string GetConcatInputArgument(IReadOnlyList<string> inputFiles, string inputPrefix) { // Get all streams // If there's more than one we'll need to use the concat command @@ -39,15 +40,16 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Determine the input path for video files - return GetFileInputArgument(inputFiles[0]); + return GetFileInputArgument(inputFiles[0], inputPrefix); } /// <summary> /// Gets the file input argument. /// </summary> /// <param name="path">The path.</param> + /// <param name="inputPrefix">The path prefix.</param> /// <returns>System.String.</returns> - private static string GetFileInputArgument(string path) + private static string GetFileInputArgument(string path, string inputPrefix) { if (path.IndexOf("://", StringComparison.Ordinal) != -1) { @@ -57,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Quotes are valid path characters in linux and they need to be escaped here with a leading \ path = NormalizePath(path); - return string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", path); + return string.Format(CultureInfo.InvariantCulture, "{1}:\"{0}\"", path, inputPrefix); } /// <summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 5a3a9185d..edf83c816 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -18,6 +18,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; @@ -319,7 +320,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters; - var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); + var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.PlayableStreamFileNames); var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length); string analyzeDuration; @@ -340,7 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; return GetMediaInfoInternal( - GetInputArgument(inputFiles, request.MediaSource.Protocol), + GetInputArgument(inputFiles, request.MediaSource), request.MediaSource.Path, request.MediaSource.Protocol, extractChapters, @@ -355,11 +356,19 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets the input argument. /// </summary> /// <param name="inputFiles">The input files.</param> - /// <param name="protocol">The protocol.</param> + /// <param name="mediaSource">The mediaSource.</param> /// <returns>System.String.</returns> /// <exception cref="ArgumentException">Unrecognized InputType.</exception> - public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaProtocol protocol) - => EncodingUtils.GetInputArgument(inputFiles, protocol); + public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaSourceInfo mediaSource) + { + var prefix = "file"; + if (mediaSource.VideoType == VideoType.BluRay || mediaSource.VideoType == VideoType.Iso) + { + prefix = "bluray"; + } + + return EncodingUtils.GetInputArgument(prefix, inputFiles, mediaSource.Protocol); + } /// <summary> /// Gets the media info internal. @@ -457,17 +466,22 @@ namespace MediaBrowser.MediaEncoding.Encoder public Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) { - return ExtractImage(new[] { path }, null, null, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken); + var mediaSource = new MediaSourceInfo + { + Protocol = MediaProtocol.File + }; + + return ExtractImage(new[] { path }, null, null, imageStreamIndex, mediaSource, true, null, null, cancellationToken); } - public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) + public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { - return ExtractImage(inputFiles, container, videoStream, null, protocol, false, threedFormat, offset, cancellationToken); + return ExtractImage(inputFiles, container, videoStream, null, mediaSource, false, threedFormat, offset, cancellationToken); } - public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken) + public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken) { - return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, protocol, false, null, null, cancellationToken); + return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, mediaSource, false, null, null, cancellationToken); } private async Task<string> ExtractImage( @@ -475,13 +489,13 @@ namespace MediaBrowser.MediaEncoding.Encoder string container, MediaStream videoStream, int? imageStreamIndex, - MediaProtocol protocol, + MediaSourceInfo mediaSource, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { - var inputArgument = GetInputArgument(inputFiles, protocol); + var inputArgument = GetInputArgument(inputFiles, mediaSource); if (isAudio) { @@ -671,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string[] inputFiles, string container, MediaStream videoStream, - MediaProtocol protocol, + MediaSourceInfo mediaSource, Video3DFormat? threedFormat, TimeSpan interval, string targetDirectory, @@ -679,7 +693,7 @@ namespace MediaBrowser.MediaEncoding.Encoder int? maxWidth, CancellationToken cancellationToken) { - var inputArgument = GetInputArgument(inputFiles, protocol); + var inputArgument = GetInputArgument(inputFiles, mediaSource); var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 0a9958b9e..4fa145d96 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path); } - var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, protocol, subtitleStream, cancellationToken).ConfigureAwait(false); + var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false); var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); @@ -221,7 +221,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private async Task<SubtitleInfo> GetReadableFile( string mediaPath, string[] inputFiles, - MediaProtocol protocol, + MediaSourceInfo mediaSource, MediaStream subtitleStream, CancellationToken cancellationToken) { @@ -252,9 +252,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles } // Extract - var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, "." + outputFormat); + var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, "." + outputFormat); - await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken) + await ExtractTextSubtitle(inputFiles, mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken) .ConfigureAwait(false); return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false); @@ -266,14 +266,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (GetReader(currentFormat, false) == null) { // Convert - var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, ".srt"); + var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, ".srt"); - await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, protocol, outputPath, cancellationToken).ConfigureAwait(false); + await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false); return new SubtitleInfo(outputPath, MediaProtocol.File, "srt", true); } - return new SubtitleInfo(subtitleStream.Path, protocol, currentFormat, true); + return new SubtitleInfo(subtitleStream.Path, mediaSource.Protocol, currentFormat, true); } private ISubtitleParser GetReader(string format, bool throwIfMissing) @@ -363,11 +363,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="language">The language.</param> - /// <param name="inputProtocol">The input protocol.</param> + /// <param name="mediaSource">The input mediaSource.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - private async Task ConvertTextSubtitleToSrt(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) + private async Task ConvertTextSubtitleToSrt(string inputPath, string language, MediaSourceInfo mediaSource, string outputPath, CancellationToken cancellationToken) { var semaphore = GetLock(outputPath); @@ -377,7 +377,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ConvertTextSubtitleToSrtInternal(inputPath, language, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false); + await ConvertTextSubtitleToSrtInternal(inputPath, language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false); } } finally @@ -391,14 +391,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="language">The language.</param> - /// <param name="inputProtocol">The input protocol.</param> + /// <param name="mediaSource">The input mediaSource.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException"> /// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c>. /// </exception> - private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) + private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaSourceInfo mediaSource, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { @@ -412,7 +412,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); + var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, mediaSource.Protocol, cancellationToken).ConfigureAwait(false); // 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" @@ -516,7 +516,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Extracts the text subtitle. /// </summary> /// <param name="inputFiles">The input files.</param> - /// <param name="protocol">The protocol.</param> + /// <param name="mediaSource">The mediaSource.</param> /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> /// <param name="outputCodec">The output codec.</param> /// <param name="outputPath">The output path.</param> @@ -525,7 +525,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <exception cref="ArgumentException">Must use inputPath list overload.</exception> private async Task ExtractTextSubtitle( string[] inputFiles, - MediaProtocol protocol, + MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputCodec, string outputPath, @@ -540,7 +540,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!File.Exists(outputPath)) { await ExtractTextSubtitleInternal( - _mediaEncoder.GetInputArgument(inputFiles, protocol), + _mediaEncoder.GetInputArgument(inputFiles, mediaSource), subtitleStreamIndex, outputCodec, outputPath, @@ -706,9 +706,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private string GetSubtitleCachePath(string mediaPath, MediaProtocol protocol, int subtitleStreamIndex, string outputSubtitleExtension) + private string GetSubtitleCachePath(string mediaPath, MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputSubtitleExtension) { - if (protocol == MediaProtocol.File) + if (mediaSource.Protocol == MediaProtocol.File) { var ticksParam = string.Empty; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index c61187fdf..648329757 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -150,11 +150,6 @@ namespace MediaBrowser.Providers.MediaInfo public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) where T : Video { - if (item.VideoType == VideoType.Iso) - { - return _cachedTask; - } - if (item.IsPlaceHolder) { return _cachedTask; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index fc38d3832..9ef393ec2 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -50,7 +51,7 @@ namespace MediaBrowser.Providers.MediaInfo } // No support for this - if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.Dvd || video.VideoType == VideoType.BluRay) + if (video.VideoType == VideoType.Dvd) { return Task.FromResult(new DynamicImageResponse { HasImage = false }); } @@ -72,7 +73,6 @@ namespace MediaBrowser.Providers.MediaInfo var inputPath = MediaEncoderHelpers.GetInputArgument( _fileSystem, item.Path, - null, item.GetPlayableStreamFileNames()); var mediaStreams = @@ -107,7 +107,14 @@ namespace MediaBrowser.Providers.MediaInfo } } - extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, imageStream, videoIndex, cancellationToken).ConfigureAwait(false); + MediaSourceInfo mediaSource = new MediaSourceInfo + { + VideoType = item.VideoType, + IsoType = item.IsoType, + Protocol = item.PathProtocol.Value, + }; + + extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, imageStream, videoIndex, cancellationToken).ConfigureAwait(false); } else { @@ -119,8 +126,14 @@ namespace MediaBrowser.Providers.MediaInfo : TimeSpan.FromSeconds(10); var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); + var mediaSource = new MediaSourceInfo + { + VideoType = item.VideoType, + IsoType = item.IsoType, + Protocol = item.PathProtocol.Value, + }; - extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, protocol, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); + extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); } return new DynamicImageResponse -- cgit v1.2.3 From cd4641dca02bae552cc7ea1942b0efbd4b791bcb Mon Sep 17 00:00:00 2001 From: Stanislav Ionascu <stanislav.ionascu@gmail.com> Date: Thu, 1 Oct 2020 22:20:28 +0200 Subject: Remove PlayableStreamFileNames as unused Since ffmpeg can play and transcode ISO files and BDMV folders directly, there's no use of that property. --- .../MediaEncoder/EncodingManager.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 5 --- MediaBrowser.Controller/Entities/Video.cs | 45 ------------------- .../MediaEncoding/EncodingHelper.cs | 34 +-------------- .../MediaEncoding/EncodingJobInfo.cs | 5 --- .../MediaEncoding/IMediaEncoder.cs | 10 ++--- .../MediaEncoding/MediaEncoderHelpers.cs | 27 ------------ .../MediaEncoding/MediaInfoRequest.cs | 11 ----- .../Attachments/AttachmentExtractor.cs | 2 +- .../Encoder/EncodingUtils.cs | 23 +++------- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 51 +++++++++------------- .../Subtitles/SubtitleEncoder.cs | 25 +++-------- .../MediaInfo/FFProbeVideoInfo.cs | 4 +- .../MediaInfo/VideoImageProvider.cs | 5 +-- 14 files changed, 44 insertions(+), 205 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 791d00963..f27305cbe 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.MediaEncoder // Add some time for the first chapter to make sure we don't end up with a black image var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, Array.Empty<string>()); + var inputPath = video.Path; Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 465857b01..cc9dcd10e 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -762,11 +762,6 @@ namespace Jellyfin.Api.Helpers private async Task AcquireResources(StreamState state, CancellationTokenSource cancellationTokenSource) { - if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && state.IsoType == IsoType.Dvd && _isoManager.CanMount(state.MediaPath)) - { - state.IsoMount = await _isoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false); - } - if (state.MediaSource.RequiresOpening && string.IsNullOrWhiteSpace(state.Request.LiveStreamId)) { var liveStreamResponse = await _mediaSourceManager.OpenLiveStream( diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 07f381881..6320b01b8 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -143,26 +143,6 @@ namespace MediaBrowser.Controller.Entities /// <value>The video3 D format.</value> public Video3DFormat? Video3DFormat { get; set; } - public string[] GetPlayableStreamFileNames() - { - var videoType = VideoType; - - if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.BluRay) - { - videoType = VideoType.BluRay; - } - else if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.Dvd) - { - videoType = VideoType.Dvd; - } - else - { - return Array.Empty<string>(); - } - - throw new NotImplementedException(); - } - /// <summary> /// Gets or sets the aspect ratio. /// </summary> @@ -415,31 +395,6 @@ namespace MediaBrowser.Controller.Entities return updateType; } - public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType) - { - if (videoType == VideoType.Dvd) - { - return FileSystem.GetFiles(rootPath, new[] { ".vob" }, false, true) - .OrderByDescending(i => i.Length) - .ThenBy(i => i.FullName) - .Take(1) - .Select(i => i.FullName) - .ToArray(); - } - - if (videoType == VideoType.BluRay) - { - return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true) - .OrderByDescending(i => i.Length) - .ThenBy(i => i.FullName) - .Take(1) - .Select(i => i.FullName) - .ToArray(); - } - - return Array.Empty<string>(); - } - /// <summary> /// Gets a value indicating whether [is3 D]. /// </summary> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 7481cc7b9..cf9bf0b5e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2323,18 +2323,10 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public string GetProbeSizeArgument(int numInputFiles) - => numInputFiles > 1 ? "-probesize " + _configuration.GetFFmpegProbeSize() : string.Empty; - - public string GetAnalyzeDurationArgument(int numInputFiles) - => numInputFiles > 1 ? "-analyzeduration " + _configuration.GetFFmpegAnalyzeDuration() : string.Empty; - public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions) { var inputModifier = string.Empty; - - var numInputFiles = state.PlayableStreamFileNames.Length > 0 ? state.PlayableStreamFileNames.Length : 1; - var probeSizeArgument = GetProbeSizeArgument(numInputFiles); + var probeSizeArgument = string.Empty; string analyzeDurationArgument; if (state.MediaSource.AnalyzeDurationMs.HasValue) @@ -2343,7 +2335,7 @@ namespace MediaBrowser.Controller.MediaEncoding } else { - analyzeDurationArgument = GetAnalyzeDurationArgument(numInputFiles); + analyzeDurationArgument = string.Empty; } if (!string.IsNullOrEmpty(probeSizeArgument)) @@ -2526,28 +2518,6 @@ namespace MediaBrowser.Controller.MediaEncoding state.IsoType = mediaSource.IsoType; - if (mediaSource.VideoType.HasValue) - { - state.VideoType = mediaSource.VideoType.Value; - - if (mediaSource.VideoType.Value == VideoType.Dvd) - { - state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, mediaSource.VideoType.Value).Select(Path.GetFileName).ToArray(); - } - else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.Dvd) - { - state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.Dvd).Select(Path.GetFileName).ToArray(); - } - else - { - state.PlayableStreamFileNames = Array.Empty<string>(); - } - } - else - { - state.PlayableStreamFileNames = Array.Empty<string>(); - } - if (mediaSource.Timestamp.HasValue) { state.InputTimestamp = mediaSource.Timestamp.Value; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index c7ec878d2..c93822f0b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -33,10 +33,6 @@ namespace MediaBrowser.Controller.MediaEncoding public bool IsInputVideo { get; set; } - public IIsoMount IsoMount { get; set; } - - public string[] PlayableStreamFileNames { get; set; } - public string OutputAudioCodec { get; set; } public int? OutputVideoBitrate { get; set; } @@ -308,7 +304,6 @@ namespace MediaBrowser.Controller.MediaEncoding { TranscodingType = jobType; RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - PlayableStreamFileNames = Array.Empty<string>(); SupportedAudioCodecs = Array.Empty<string>(); SupportedVideoCodecs = Array.Empty<string>(); SupportedSubtitleCodecs = Array.Empty<string>(); diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 5c070122d..2560d0e31 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -62,14 +62,14 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Extracts the video image. /// </summary> - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); /// <summary> /// Extracts the video images on interval. /// </summary> - Task ExtractVideoImagesOnInterval(string[] inputFiles, + Task ExtractVideoImagesOnInterval(string inputFile, string container, MediaStream videoStream, MediaSourceInfo mediaSource, @@ -91,10 +91,10 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Gets the input argument. /// </summary> - /// <param name="inputFiles">The input files.</param> + /// <param name="inputFile">The input file.</param> /// <param name="mediaSource">The mediaSource.</param> /// <returns>System.String.</returns> - string GetInputArgument(IReadOnlyList<string> inputFiles, MediaSourceInfo mediaSource); + string GetInputArgument(string inputFile, MediaSourceInfo mediaSource); /// <summary> /// Gets the time parameter. diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index df2d2fa57..281d50372 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -13,32 +13,5 @@ namespace MediaBrowser.Controller.MediaEncoding /// </summary> public static class MediaEncoderHelpers { - /// <summary> - /// Gets the input argument. - /// </summary> - /// <param name="fileSystem">The file system.</param> - /// <param name="videoPath">The video path.</param> - /// <param name="playableStreamFileNames">The playable stream file names.</param> - /// <returns>string[].</returns> - public static string[] GetInputArgument(IFileSystem fileSystem, string videoPath, IReadOnlyCollection<string> playableStreamFileNames) - { - if (playableStreamFileNames.Count > 0) - { - return GetPlayableStreamFiles(fileSystem, videoPath, playableStreamFileNames); - } - - return new[] { videoPath }; - } - - private static string[] GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable<string> filenames) - { - var allFiles = fileSystem - .GetFilePaths(rootPath, true) - .ToArray(); - - return filenames.Select(name => allFiles.FirstOrDefault(f => string.Equals(Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase))) - .Where(f => !string.IsNullOrEmpty(f)) - .ToArray(); - } } } diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs index 59729de49..2cb04bdc4 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs @@ -1,9 +1,7 @@ #pragma warning disable CS1591 -using System; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.MediaEncoding { @@ -14,14 +12,5 @@ namespace MediaBrowser.Controller.MediaEncoding public bool ExtractChapters { get; set; } public DlnaProfileType MediaType { get; set; } - - public IIsoMount MountedIso { get; set; } - - public string[] PlayableStreamFileNames { get; set; } - - public MediaInfoRequest() - { - PlayableStreamFileNames = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 466fd75e1..c4a2d7779 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.MediaEncoding.Attachments if (!File.Exists(outputPath)) { await ExtractAttachmentInternal( - _mediaEncoder.GetInputArgument(new[] { inputFile }, mediaSource), + _mediaEncoder.GetInputArgument(inputFile, mediaSource), attachmentStreamIndex, outputPath, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index b1fcba2d1..d0ea0429b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,46 +1,35 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Encoder { public static class EncodingUtils { - public static string GetInputArgument(string inputPrefix, IReadOnlyList<string> inputFiles, MediaProtocol protocol) + public static string GetInputArgument(string inputPrefix, string inputFile, MediaProtocol protocol) { if (protocol != MediaProtocol.File) { - var url = inputFiles[0]; - - return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", url); + return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", inputFile); } - return GetConcatInputArgument(inputFiles, inputPrefix); + return GetConcatInputArgument(inputFile, inputPrefix); } /// <summary> /// Gets the concat input argument. /// </summary> - /// <param name="inputFiles">The input files.</param> + /// <param name="inputFile">The input file.</param> /// <param name="inputPrefix">The input prefix.</param> /// <returns>System.String.</returns> - private static string GetConcatInputArgument(IReadOnlyList<string> inputFiles, string inputPrefix) + private static string GetConcatInputArgument(string inputFile, string inputPrefix) { // Get all streams // If there's more than one we'll need to use the concat command - if (inputFiles.Count > 1) - { - var files = string.Join("|", inputFiles.Select(NormalizePath)); - - return string.Format(CultureInfo.InvariantCulture, "concat:\"{0}\"", files); - } - // Determine the input path for video files - return GetFileInputArgument(inputFiles[0], inputPrefix); + return GetFileInputArgument(inputFile, inputPrefix); } /// <summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index edf83c816..3657f7e31 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -83,8 +83,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _jsonSerializerOptions = JsonDefaults.GetOptions(); } - private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; - /// <inheritdoc /> public string EncoderPath => _ffmpegPath; @@ -319,33 +317,24 @@ namespace MediaBrowser.MediaEncoding.Encoder public Task<MediaInfo> GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken) { var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters; + var inputFile = request.MediaSource.Path; - var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.PlayableStreamFileNames); - - var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length); - string analyzeDuration; + string analyzeDuration = string.Empty; if (request.MediaSource.AnalyzeDurationMs > 0) { analyzeDuration = "-analyzeduration " + (request.MediaSource.AnalyzeDurationMs * 1000).ToString(); } - else - { - analyzeDuration = EncodingHelper.GetAnalyzeDurationArgument(inputFiles.Length); - } - - probeSize = probeSize + " " + analyzeDuration; - probeSize = probeSize.Trim(); var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; return GetMediaInfoInternal( - GetInputArgument(inputFiles, request.MediaSource), + GetInputArgument(inputFile, request.MediaSource), request.MediaSource.Path, request.MediaSource.Protocol, extractChapters, - probeSize, + analyzeDuration, request.MediaType == DlnaProfileType.Audio, request.MediaSource.VideoType, forceEnableLogging, @@ -355,11 +344,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Gets the input argument. /// </summary> - /// <param name="inputFiles">The input files.</param> + /// <param name="inputFile">The input file.</param> /// <param name="mediaSource">The mediaSource.</param> /// <returns>System.String.</returns> /// <exception cref="ArgumentException">Unrecognized InputType.</exception> - public string GetInputArgument(IReadOnlyList<string> inputFiles, MediaSourceInfo mediaSource) + public string GetInputArgument(string inputFile, MediaSourceInfo mediaSource) { var prefix = "file"; if (mediaSource.VideoType == VideoType.BluRay || mediaSource.VideoType == VideoType.Iso) @@ -367,7 +356,7 @@ namespace MediaBrowser.MediaEncoding.Encoder prefix = "bluray"; } - return EncodingUtils.GetInputArgument(prefix, inputFiles, mediaSource.Protocol); + return EncodingUtils.GetInputArgument(prefix, inputFile, mediaSource.Protocol); } /// <summary> @@ -471,21 +460,21 @@ namespace MediaBrowser.MediaEncoding.Encoder Protocol = MediaProtocol.File }; - return ExtractImage(new[] { path }, null, null, imageStreamIndex, mediaSource, true, null, null, cancellationToken); + return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, cancellationToken); } - public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) + public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { - return ExtractImage(inputFiles, container, videoStream, null, mediaSource, false, threedFormat, offset, cancellationToken); + return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, cancellationToken); } - public Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken) + public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken) { - return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, mediaSource, false, null, null, cancellationToken); + return ExtractImage(inputFile, container, imageStream, imageStreamIndex, mediaSource, false, null, null, cancellationToken); } private async Task<string> ExtractImage( - string[] inputFiles, + string inputFile, string container, MediaStream videoStream, int? imageStreamIndex, @@ -495,7 +484,7 @@ namespace MediaBrowser.MediaEncoding.Encoder TimeSpan? offset, CancellationToken cancellationToken) { - var inputArgument = GetInputArgument(inputFiles, mediaSource); + var inputArgument = GetInputArgument(inputFile, mediaSource); if (isAudio) { @@ -572,8 +561,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); - var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); - var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); + var probeSizeArgument = string.Empty; + var analyzeDurationArgument = string.Empty; if (!string.IsNullOrWhiteSpace(probeSizeArgument)) { @@ -682,7 +671,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } public async Task ExtractVideoImagesOnInterval( - string[] inputFiles, + string inputFile, string container, MediaStream videoStream, MediaSourceInfo mediaSource, @@ -693,7 +682,7 @@ namespace MediaBrowser.MediaEncoding.Encoder int? maxWidth, CancellationToken cancellationToken) { - var inputArgument = GetInputArgument(inputFiles, mediaSource); + var inputArgument = GetInputArgument(inputFile, mediaSource); var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); @@ -709,8 +698,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); - var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); - var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); + var probeSizeArgument = string.Empty; + var analyzeDurationArgument = string.Empty; if (!string.IsNullOrWhiteSpace(probeSizeArgument)) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 4fa145d96..ed6c568c5 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -168,18 +168,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles MediaStream subtitleStream, CancellationToken cancellationToken) { - string[] inputFiles; - - if (mediaSource.VideoType.HasValue - && (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd)) - { - var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSource.Id)); - inputFiles = mediaSourceItem.GetPlayableStreamFileNames(); - } - else - { - inputFiles = new[] { mediaSource.Path }; - } + var inputFile = mediaSource.Path; var protocol = mediaSource.Protocol; if (subtitleStream.IsExternal) @@ -187,7 +176,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path); } - var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false); + var fileInfo = await GetReadableFile(mediaSource.Path, inputFile, mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false); var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); @@ -220,7 +209,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private async Task<SubtitleInfo> GetReadableFile( string mediaPath, - string[] inputFiles, + string inputFile, MediaSourceInfo mediaSource, MediaStream subtitleStream, CancellationToken cancellationToken) @@ -254,7 +243,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // Extract var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, "." + outputFormat); - await ExtractTextSubtitle(inputFiles, mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken) + await ExtractTextSubtitle(inputFile, mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken) .ConfigureAwait(false); return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false); @@ -515,7 +504,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <summary> /// Extracts the text subtitle. /// </summary> - /// <param name="inputFiles">The input files.</param> + /// <param name="inputFile">The input file.</param> /// <param name="mediaSource">The mediaSource.</param> /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> /// <param name="outputCodec">The output codec.</param> @@ -524,7 +513,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <returns>Task.</returns> /// <exception cref="ArgumentException">Must use inputPath list overload.</exception> private async Task ExtractTextSubtitle( - string[] inputFiles, + string inputFile, MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputCodec, @@ -540,7 +529,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!File.Exists(outputPath)) { await ExtractTextSubtitleInternal( - _mediaEncoder.GetInputArgument(inputFiles, mediaSource), + _mediaEncoder.GetInputArgument(inputFile, mediaSource), subtitleStreamIndex, outputCodec, outputPath, diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 776dee780..6d39c091e 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.MediaInfo streamFileNames = Array.Empty<string>(); } - mediaInfoResult = await GetMediaInfo(item, streamFileNames, cancellationToken).ConfigureAwait(false); + mediaInfoResult = await GetMediaInfo(item, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); } @@ -128,7 +128,6 @@ namespace MediaBrowser.Providers.MediaInfo private Task<Model.MediaInfo.MediaInfo> GetMediaInfo( Video item, - string[] streamFileNames, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -145,7 +144,6 @@ namespace MediaBrowser.Providers.MediaInfo return _mediaEncoder.GetMediaInfo( new MediaInfoRequest { - PlayableStreamFileNames = streamFileNames, ExtractChapters = true, MediaType = DlnaProfileType.Video, MediaSource = new MediaSourceInfo diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 9ef393ec2..c36c3af6a 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -70,10 +70,7 @@ namespace MediaBrowser.Providers.MediaInfo { var protocol = item.PathProtocol ?? MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument( - _fileSystem, - item.Path, - item.GetPlayableStreamFileNames()); + var inputPath = item.Path; var mediaStreams = item.GetMediaStreams(); -- cgit v1.2.3 From 28ee4f0a7f7b7be954ac2dccc374bf72b1eb4f40 Mon Sep 17 00:00:00 2001 From: Stéphane Senart <stephane.senart@gmail.com> Date: Thu, 22 Oct 2020 11:09:59 +0200 Subject: [AudioTranscoding] Add FLAC as supported target audio format and be able to define the corresponding target sample rate --- .../MediaEncoding/EncodingJobInfo.cs | 5 ++++- .../Encoder/EncoderValidator.cs | 2 ++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 26 ++++++++++++++++++++++ MediaBrowser.Model/Dlna/StreamInfo.cs | 9 ++++++-- 4 files changed, 39 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 6cd0c70d2..e99c48a70 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -404,7 +404,10 @@ namespace MediaBrowser.Controller.MediaEncoding { // Don't exceed what the encoder supports // Seeing issues of attempting to encode to 88200 - return Math.Min(44100, BaseRequest.AudioSampleRate.Value); + // return Math.Min(44100, BaseRequest.AudioSampleRate.Value); + + // I don't see any reason why limiting the sample rate to a maximum of 44100 ! + return BaseRequest.AudioSampleRate.Value; } return null; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 3287f9814..92f16ab95 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -25,6 +25,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "ac3", "aac", "mp3", + "flac", "h264_qsv", "hevc_qsv", "mpeg2_qsv", @@ -71,6 +72,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "libmp3lame", "libopus", "libvorbis", + "flac", "srt", "h264_amf", "hevc_amf", diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 4959a9b92..cf392ffce 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1438,6 +1438,32 @@ namespace MediaBrowser.Model.Dlna break; } + case ProfileConditionValue.AudioSampleRate: + { + if (!enableNonQualifiedConditions) + { + continue; + } + + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var num)) + { + if (condition.Condition == ProfileConditionType.Equals) + { + item.AudioSampleRate = num; + } + else if (condition.Condition == ProfileConditionType.LessThanEqual) + { + item.AudioSampleRate = Math.Min(num, item.AudioSampleRate ?? num); + } + else if (condition.Condition == ProfileConditionType.GreaterThanEqual) + { + item.AudioSampleRate = Math.Max(num, item.AudioSampleRate ?? num); + } + } + + break; + } + case ProfileConditionValue.AudioChannels: { if (string.IsNullOrEmpty(qualifier)) diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 9399d21f1..20ca54773 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -110,6 +110,8 @@ namespace MediaBrowser.Model.Dlna public int? AudioBitrate { get; set; } + public int? AudioSampleRate { get; set; } + public int? VideoBitrate { get; set; } public int? MaxWidth { get; set; } @@ -184,7 +186,7 @@ namespace MediaBrowser.Model.Dlna } if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase)) + string.Equals(pair.Value, "true", StringComparison.OrdinalIgnoreCase)) { continue; } @@ -250,6 +252,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); @@ -521,7 +524,9 @@ namespace MediaBrowser.Model.Dlna get { var stream = TargetAudioStream; - return stream == null ? null : stream.SampleRate; + return AudioSampleRate.HasValue && !IsDirectStream + ? AudioSampleRate + : stream == null ? null : stream.SampleRate; } } -- cgit v1.2.3 From 84fd5a09532bd1e854ec3745609f845aa7098da2 Mon Sep 17 00:00:00 2001 From: Orry Verducci <orry@orryverducci.co.uk> Date: Sun, 25 Oct 2020 16:35:03 +0000 Subject: Fix frame rate probing for interlaced MKV files --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 22537a4d9..cdeefbbbd 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -666,6 +666,16 @@ namespace MediaBrowser.MediaEncoding.Probing stream.AverageFrameRate = GetFrameRate(streamInfo.AverageFrameRate); stream.RealFrameRate = GetFrameRate(streamInfo.RFrameRate); + // Interlaced video streams in Matroska containers return the field rate instead of the frame rate + // as both the average and real frame rate, so we half the returned frame rates to get the correct values + // + // https://gitlab.com/mbunkus/mkvtoolnix/-/wikis/Wrong-frame-rate-displayed + if (stream.IsInterlaced && formatInfo.FormatName.Contains("matroska", StringComparison.OrdinalIgnoreCase)) + { + stream.AverageFrameRate /= 2; + stream.RealFrameRate /= 2; + } + if (isAudio || string.Equals(stream.Codec, "gif", StringComparison.OrdinalIgnoreCase) || string.Equals(stream.Codec, "png", StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From 83629ab6f24ee1a8991dae2b8a55d24c93832ad5 Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Tue, 10 Nov 2020 09:52:34 -0700 Subject: Update packages to net5 --- DvdLib/DvdLib.csproj | 2 +- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Drawing/Emby.Drawing.csproj | 2 +- Emby.Naming/Emby.Naming.csproj | 2 +- Emby.Notifications/Emby.Notifications.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 12 ++++++------ Jellyfin.Api/Jellyfin.Api.csproj | 6 +++--- Jellyfin.Data/Jellyfin.Data.csproj | 6 +++--- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 10 +++++----- MediaBrowser.Common/MediaBrowser.Common.csproj | 6 +++--- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj | 2 +- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/Extensions/StringHelper.cs | 6 ------ MediaBrowser.Model/MediaBrowser.Model.csproj | 8 ++++---- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 8 ++++---- MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 2 +- RSSDP/RSSDP.csproj | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 6 +++--- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 2 +- .../Jellyfin.Controller.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 2 +- 27 files changed, 55 insertions(+), 61 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index 64d041cb0..7bbd9acf8 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -10,7 +10,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 6ed49944c..bd30cc1e1 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -17,7 +17,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 092f8580a..7d479a5c6 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 6857f9952..80800840e 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 1d430a5e5..16ee918c4 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index dbe01257f..62e33e6c4 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -19,7 +19,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index c762aa0b8..bcddea281 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,13 +32,13 @@ <PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" /> <PackageReference Include="Mono.Nat" Version="3.0.0" /> <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.0" /> - <PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" /> + <PackageReference Include="ServiceStack.Text.Core" Version="5.10.0" /> <PackageReference Include="sharpcompress" Version="0.26.0" /> <PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" /> <PackageReference Include="DotNet.Glob" Version="3.1.0" /> @@ -49,7 +49,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index da0852ceb..2836f7b0a 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> @@ -14,9 +14,9 @@ <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.9" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.6.3" /> </ItemGroup> diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 5038988f9..9ae129d07 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> @@ -41,8 +41,8 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.9" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.9" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0" /> </ItemGroup> <ItemGroup> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index c11ac5fb3..466a12e67 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index c52be3b8a..e663798da 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> @@ -24,12 +24,12 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="System.Linq.Async" Version="4.1.1" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9"> + <PackageReference Include="System.Linq.Async" Version="5.0.0" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 3558f144c..03d06fdff 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -8,7 +8,7 @@ <PropertyGroup> <AssemblyName>jellyfin</AssemblyName> <OutputType>Exe</OutputType> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> @@ -38,10 +38,10 @@ <ItemGroup> <PackageReference Include="CommandLineParser" Version="2.8.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="5.0.0" /> <PackageReference Include="prometheus-net" Version="4.0.0" /> <PackageReference Include="prometheus-net.AspNetCore" Version="4.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" /> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index e716a6610..b67a54983 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -18,8 +18,8 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> <PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" /> </ItemGroup> @@ -29,7 +29,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4374317d6..9acc98dce 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -14,8 +14,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> </ItemGroup> @@ -29,7 +29,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors> diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 529e7065c..3ce9ff4cc 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -11,7 +11,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 6ead93e09..7bb2a7d03 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> @@ -25,7 +25,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" /> - <PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" /> + <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="UTF.Unknown" Version="2.3.0" /> </ItemGroup> diff --git a/MediaBrowser.Model/Extensions/StringHelper.cs b/MediaBrowser.Model/Extensions/StringHelper.cs index 8ffa3c4ba..2d9a6c4db 100644 --- a/MediaBrowser.Model/Extensions/StringHelper.cs +++ b/MediaBrowser.Model/Extensions/StringHelper.cs @@ -22,11 +22,6 @@ namespace MediaBrowser.Model.Extensions return str; } -#if NETSTANDARD2_0 - char[] a = str.ToCharArray(); - a[0] = char.ToUpperInvariant(a[0]); - return new string(a); -#else return string.Create( str.Length, str, @@ -38,7 +33,6 @@ namespace MediaBrowser.Model.Extensions chars[i] = buf[i]; } }); -#endif } } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 253ee7e79..b86187f9b 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,7 +14,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors> @@ -32,11 +32,11 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> + <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" /> <PackageReference Include="System.Globalization" Version="4.3.0" /> - <PackageReference Include="System.Text.Json" Version="5.0.0-preview.8.20407.11" /> + <PackageReference Include="System.Text.Json" Version="5.0.0" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9465fe42c..fd3f9f4c7 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.9" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" /> <PackageReference Include="PlaylistsNET" Version="1.1.2" /> <PackageReference Include="TMDbLib" Version="1.7.3-alpha" /> @@ -26,7 +26,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 45fd9add9..87d1e9464 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,7 +15,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 664663bd7..d0962e82c 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -10,7 +10,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>netstandard2.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index ce61f5684..5bf322f07 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> @@ -16,8 +16,8 @@ <PackageReference Include="AutoFixture" Version="4.14.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.14.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 67dc8286a..e8eca6760 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 30e84842a..6e3fac43d 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 4fd0d5342..e88de3811 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 0d240fd65..567cf34ef 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index db1f2956e..b960fda72 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>netcoreapp3.1</TargetFramework> + <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> -- cgit v1.2.3 From 57e5b59b93272bbbafeb1b57bdacc862c48f0996 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Wed, 11 Nov 2020 17:08:50 +0800 Subject: adjust bitrate limit for HLS audio codecs --- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 2 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 49 ++++++--- .../MediaEncoding/EncodingHelper.cs | 50 +++++---- .../Probing/ProbeResultNormalizer.cs | 112 ++++++++++++++++++++- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 8 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 72 +++++++++++-- MediaBrowser.Model/Dlna/StreamInfo.cs | 2 +- 7 files changed, 246 insertions(+), 49 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index d6fa6e98d..d2710bf40 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -222,7 +222,7 @@ namespace Jellyfin.Api.Helpers EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); var sdrOutputVideoBitrate = encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0; - var sdrOutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.VideoRequest.AudioBitRate, state.AudioStream) ?? 0; + var sdrOutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate; AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index f4ec29bde..5bd347846 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Helpers state.OutputContainer = (containerInternal ?? string.Empty).TrimStart('.'); - state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(streamingRequest.AudioBitRate, state.AudioStream); + state.OutputAudioBitrate = encodingHelper.GetAudioBitrateParam(streamingRequest.AudioBitRate, streamingRequest.AudioCodec, state.AudioStream); state.OutputAudioCodec = streamingRequest.AudioCodec; @@ -196,20 +196,41 @@ namespace Jellyfin.Api.Helpers encodingHelper.TryStreamCopy(state); - if (state.OutputVideoBitrate.HasValue && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) + if (!EncodingHelper.IsCopyCodec(state.OutputVideoCodec) && state.OutputVideoBitrate.HasValue) { - var resolution = ResolutionNormalizer.Normalize( - state.VideoStream?.BitRate, - state.VideoStream?.Width, - state.VideoStream?.Height, - state.OutputVideoBitrate.Value, - state.VideoStream?.Codec, - state.OutputVideoCodec, - state.VideoRequest.MaxWidth, - state.VideoRequest.MaxHeight); - - state.VideoRequest.MaxWidth = resolution.MaxWidth; - state.VideoRequest.MaxHeight = resolution.MaxHeight; + var isVideoResolutionNotRequested = !state.VideoRequest.Width.HasValue + && !state.VideoRequest.Height.HasValue + && !state.VideoRequest.MaxWidth.HasValue + && !state.VideoRequest.MaxHeight.HasValue; + + if (isVideoResolutionNotRequested + && state.VideoRequest.VideoBitRate.HasValue + && state.VideoStream.BitRate.HasValue + && state.VideoRequest.VideoBitRate.Value >= state.VideoStream.BitRate.Value) + { + // Don't downscale the resolution if the width/height/MaxWidth/MaxHeight is not requested, + // and the requested video bitrate is higher than source video bitrate. + if (state.VideoStream.Width.HasValue || state.VideoStream.Height.HasValue) + { + state.VideoRequest.MaxWidth = state.VideoStream?.Width; + state.VideoRequest.MaxHeight = state.VideoStream?.Height; + } + } + else + { + var resolution = ResolutionNormalizer.Normalize( + state.VideoStream?.BitRate, + state.VideoStream?.Width, + state.VideoStream?.Height, + state.OutputVideoBitrate.Value, + state.VideoStream?.Codec, + state.OutputVideoCodec, + state.VideoRequest.MaxWidth, + state.VideoRequest.MaxHeight); + + state.VideoRequest.MaxWidth = resolution.MaxWidth; + state.VideoRequest.MaxHeight = resolution.MaxHeight; + } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 6255e1b61..e8b4869ee 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1390,7 +1390,7 @@ namespace MediaBrowser.Controller.MediaEncoding || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) { - return .5; + return .6; } return 1; @@ -1424,36 +1424,48 @@ namespace MediaBrowser.Controller.MediaEncoding public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream) { - if (audioStream == null) - { - return null; - } - - if (request.AudioBitRate.HasValue) - { - // Don't encode any higher than this - return Math.Min(384000, request.AudioBitRate.Value); - } - - // Empty bitrate area is not allow on iOS - // Default audio bitrate to 128K if it is not being requested - // https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options - return 128000; + return GetAudioBitrateParam(request.AudioBitRate, request.AudioCodec, audioStream); } - public int? GetAudioBitrateParam(int? audioBitRate, MediaStream audioStream) + public int? GetAudioBitrateParam(int? audioBitRate, string audioCodec, MediaStream audioStream) { if (audioStream == null) { return null; } - if (audioBitRate.HasValue) + if (audioBitRate.HasValue && string.IsNullOrEmpty(audioCodec)) { - // Don't encode any higher than this return Math.Min(384000, audioBitRate.Value); } + if (audioBitRate.HasValue && !string.IsNullOrEmpty(audioCodec)) + { + if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "eac3", StringComparison.OrdinalIgnoreCase)) + { + if ((audioStream.Channels ?? 0) >= 6) + { + return Math.Min(640000, audioBitRate.Value); + } + + return Math.Min(384000, audioBitRate.Value); + } + + if (string.Equals(audioCodec, "flac", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "alac", StringComparison.OrdinalIgnoreCase)) + { + if ((audioStream.Channels ?? 0) >= 6) + { + return Math.Min(3584000, audioBitRate.Value); + } + + return Math.Min(1536000, audioBitRate.Value); + } + } + // Empty bitrate area is not allow on iOS // Default audio bitrate to 128K if it is not being requested // https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index cdeefbbbd..1b0d4d1af 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -234,8 +234,8 @@ namespace MediaBrowser.MediaEncoding.Probing var channelsValue = channels.Value; - if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) || - string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) { if (channelsValue <= 2) { @@ -248,6 +248,34 @@ namespace MediaBrowser.MediaEncoding.Probing } } + if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) + { + if (channelsValue <= 2) + { + return 192000; + } + + if (channelsValue >= 5) + { + return 640000; + } + } + + if (string.Equals(codec, "flac", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "alac", StringComparison.OrdinalIgnoreCase)) + { + if (channelsValue <= 2) + { + return 960000; + } + + if (channelsValue >= 5) + { + return 2880000; + } + } + return null; } @@ -774,6 +802,35 @@ namespace MediaBrowser.MediaEncoding.Probing stream.BitRate = bitrate; } + // Extract bitrate info from tag "BPS" if possible. + if (!stream.BitRate.HasValue + && (string.Equals(streamInfo.CodecType, "audio", StringComparison.OrdinalIgnoreCase) + || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) + { + var bps = GetBPSFromTags(streamInfo); + if (bps != null && bps > 0) + { + stream.BitRate = bps; + } + } + + // Get average bitrate info from tag "NUMBER_OF_BYTES" and "DURATION" if possible. + if (!stream.BitRate.HasValue + && (string.Equals(streamInfo.CodecType, "audio", StringComparison.OrdinalIgnoreCase) + || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) + { + var durationInSeconds = GetRuntimeSecondsFromTags(streamInfo); + var bytes = GetNumberOfBytesFromTags(streamInfo); + if (durationInSeconds != null && bytes != null) + { + var bps = Convert.ToInt32(bytes * 8 / durationInSeconds); + if (bps > 0) + { + stream.BitRate = bps; + } + } + } + var disposition = streamInfo.Disposition; if (disposition != null) { @@ -963,6 +1020,57 @@ namespace MediaBrowser.MediaEncoding.Probing } } + private int? GetBPSFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); + if (!string.IsNullOrEmpty(bps)) + { + if (int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) + { + return parsedBps; + } + } + } + + return null; + } + + private double? GetRuntimeSecondsFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); + if (!string.IsNullOrEmpty(duration)) + { + if (TimeSpan.TryParse(duration, out var parsedDuration)) + { + return parsedDuration.TotalSeconds; + } + } + } + + return null; + } + + private long? GetNumberOfBytesFromTags(MediaStreamInfo streamInfo) + { + if (streamInfo != null && streamInfo.Tags != null) + { + var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); + if (!string.IsNullOrEmpty(numberOfBytes)) + { + if (long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) + { + return parsedBytes; + } + } + } + + return null; + } + private void SetSize(InternalMediaInfoResult data, MediaInfo info) { if (data.Format != null) diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index 102db3b44..39439f1fa 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -79,11 +79,11 @@ namespace MediaBrowser.Model.Dlna private static double GetVideoBitrateScaleFactor(string codec) { - if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || - string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) || - string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) + || string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase)) { - return .5; + return .6; } return 1; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 4959a9b92..2e99fe5bf 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -872,11 +872,34 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - private static int GetDefaultAudioBitrateIfUnknown(MediaStream audioStream) + private static int GetDefaultAudioBitrate(string audioCodec, int? audioChannels) { - if ((audioStream.Channels ?? 0) >= 6) + if (!string.IsNullOrEmpty(audioCodec)) { - return 384000; + // Default to a higher bitrate for stream copy + if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "eac3", StringComparison.OrdinalIgnoreCase)) + { + if ((audioChannels ?? 0) < 2) + { + return 128000; + } + + return (audioChannels ?? 0) >= 6 ? 640000 : 384000; + } + + if (string.Equals(audioCodec, "flac", StringComparison.OrdinalIgnoreCase) + || string.Equals(audioCodec, "alac", StringComparison.OrdinalIgnoreCase)) + { + if ((audioChannels ?? 0) < 2) + { + return 768000; + } + + return (audioChannels ?? 0) >= 6 ? 3584000 : 1536000; + } } return 192000; @@ -897,14 +920,27 @@ namespace MediaBrowser.Model.Dlna } else { - if (targetAudioChannels.HasValue && audioStream.Channels.HasValue && targetAudioChannels.Value < audioStream.Channels.Value) + if (targetAudioChannels.HasValue + && audioStream.Channels.HasValue + && audioStream.Channels.Value > targetAudioChannels.Value) { - // Reduce the bitrate if we're downmixing - defaultBitrate = targetAudioChannels.Value < 2 ? 128000 : 192000; + // Reduce the bitrate if we're downmixing. + defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, targetAudioChannels); + } + else if (targetAudioChannels.HasValue + && audioStream.Channels.HasValue + && audioStream.Channels.Value <= targetAudioChannels.Value + && !string.IsNullOrEmpty(audioStream.Codec) + && targetAudioCodecs != null + && targetAudioCodecs.Length > 0 + && !Array.Exists(targetAudioCodecs, elem => string.Equals(audioStream.Codec, elem, StringComparison.OrdinalIgnoreCase))) + { + // Shift the bitrate if we're transcoding to a different audio codec. + defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, audioStream.Channels.Value); } else { - defaultBitrate = audioStream.BitRate ?? GetDefaultAudioBitrateIfUnknown(audioStream); + defaultBitrate = audioStream.BitRate ?? GetDefaultAudioBitrate(targetAudioCodec, targetAudioChannels); } // Seeing webm encoding failures when source has 1 audio channel and 22k bitrate. @@ -938,8 +974,28 @@ namespace MediaBrowser.Model.Dlna { return 448000; } + else if (totalBitrate <= 4000000) + { + return 640000; + } + else if (totalBitrate <= 5000000) + { + return 768000; + } + else if (totalBitrate <= 10000000) + { + return 1536000; + } + else if (totalBitrate <= 15000000) + { + return 2304000; + } + else if (totalBitrate <= 20000000) + { + return 3584000; + } - return 640000; + return 7168000; } private (PlayMethod?, List<TranscodeReason>) GetVideoDirectPlayProfile( diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 9399d21f1..7b72a1303 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -787,7 +787,7 @@ namespace MediaBrowser.Model.Dlna public int? GetTargetAudioChannels(string codec) { - var defaultValue = GlobalMaxAudioChannels; + var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels; var value = GetOption(codec, "audiochannels"); if (string.IsNullOrEmpty(value)) -- cgit v1.2.3 From 6987cb83570a6a822260691f009f4b3762d98942 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Wed, 11 Nov 2020 17:25:14 +0800 Subject: fix ci --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 1b0d4d1af..d6b87477c 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -823,7 +823,7 @@ namespace MediaBrowser.MediaEncoding.Probing var bytes = GetNumberOfBytesFromTags(streamInfo); if (durationInSeconds != null && bytes != null) { - var bps = Convert.ToInt32(bytes * 8 / durationInSeconds); + var bps = Convert.ToInt32(bytes * 8 / durationInSeconds, CultureInfo.InvariantCulture); if (bps > 0) { stream.BitRate = bps; -- cgit v1.2.3 From e82829c444a235d56aeafb60ad4424ee0d92b8b8 Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Fri, 13 Nov 2020 09:01:55 -0700 Subject: Fix nullability errors in MediaBrowser.MediaEncoding --- MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 21b5d0c5b..bc940d0b8 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -178,7 +178,7 @@ namespace MediaBrowser.MediaEncoding.Attachments process.Start(); - var ranToCompletion = await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + var ranToCompletion = await ProcessExtensions.WaitForExitAsync(process, cancellationToken).ConfigureAwait(false); if (!ranToCompletion) { -- cgit v1.2.3 From 01355e049855a21b69e7e258599c3fa35965375a Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Fri, 13 Nov 2020 09:04:31 -0700 Subject: Fix nullability errors in Jellyfin.Api (part 1) --- Jellyfin.Api/Controllers/DynamicHlsController.cs | 12 +++++++++- Jellyfin.Api/Controllers/EnvironmentController.cs | 5 ++++ Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 5 ++++ Jellyfin.Api/Controllers/ImageByNameController.cs | 2 +- Jellyfin.Api/Controllers/ImageController.cs | 3 ++- Jellyfin.Api/Controllers/ItemLookupController.cs | 21 ++++++++++++++-- Jellyfin.Api/Controllers/LibraryController.cs | 6 ++--- Jellyfin.Api/Controllers/LiveTvController.cs | 2 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 4 ++-- Jellyfin.Api/Controllers/PackageController.cs | 5 ++++ Jellyfin.Api/Controllers/RemoteImageController.cs | 28 ++++++++++++++++++---- Jellyfin.Api/Controllers/SearchController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 8 ++++++- Jellyfin.Api/Helpers/AudioHelper.cs | 8 ++++++- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 11 ++++++--- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 4 ++-- Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs | 6 ++--- Jellyfin.Api/Helpers/HlsHelpers.cs | 4 ++++ Jellyfin.Api/Helpers/ProgressiveFileCopier.cs | 5 ++++ Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 ++++ Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 26 +++++++++++++------- .../Models/PlaybackDtos/TranscodingJobDto.cs | 4 ++-- .../Models/PlaybackDtos/TranscodingThrottler.cs | 2 +- .../ActivityLogWebSocketListener.cs | 2 +- .../ScheduledTasksWebSocketListener.cs | 6 ++--- .../SessionInfoWebSocketListener.cs | 14 +++++------ .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/Net/MimeTypes.cs | 6 ++--- 29 files changed, 155 insertions(+), 54 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index e07690e11..b0d5a7cd8 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1347,7 +1347,13 @@ namespace Jellyfin.Api.Controllers var mapArgs = state.IsOutputVideo ? _encodingHelper.GetMapArgs(state) : string.Empty; - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); var segmentFormat = GetSegmentFileExtension(state.Request.SegmentContainer).TrimStart('.'); if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) @@ -1566,6 +1572,10 @@ namespace Jellyfin.Api.Controllers private string GetSegmentPath(StreamState state, string playlist, int index) { var folder = Path.GetDirectoryName(playlist); + if (folder == null) + { + throw new NullReferenceException(nameof(folder)); + } var filename = Path.GetFileNameWithoutExtension(playlist); diff --git a/Jellyfin.Api/Controllers/EnvironmentController.cs b/Jellyfin.Api/Controllers/EnvironmentController.cs index ce88b0b99..8de217bbf 100644 --- a/Jellyfin.Api/Controllers/EnvironmentController.cs +++ b/Jellyfin.Api/Controllers/EnvironmentController.cs @@ -103,6 +103,11 @@ namespace Jellyfin.Api.Controllers if (validatePathDto.ValidateWritable) { + if (validatePathDto.Path == null) + { + throw new NullReferenceException(nameof(validatePathDto.Path)); + } + var file = Path.Combine(validatePathDto.Path, Guid.NewGuid().ToString()); try { diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index f6e0772ec..9c009d784 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -177,7 +177,7 @@ namespace Jellyfin.Api.Controllers return _dtoService.GetBaseItemDto(item, dtoOptions); } - private T GetItemFromSlugName<T>(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) + private T? GetItemFromSlugName<T>(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) where T : BaseItem, new() { var result = libraryManager.GetItemList(new InternalItemsQuery diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 054e586ce..2cee0e9ef 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -136,6 +136,11 @@ namespace Jellyfin.Api.Controllers string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); + if (playlistPath == null) + { + throw new NullReferenceException(nameof(playlistPath)); + } + return GetFileResult(file, playlistPath); } diff --git a/Jellyfin.Api/Controllers/ImageByNameController.cs b/Jellyfin.Api/Controllers/ImageByNameController.cs index 980c3273d..198dbc51f 100644 --- a/Jellyfin.Api/Controllers/ImageByNameController.cs +++ b/Jellyfin.Api/Controllers/ImageByNameController.cs @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers /// <param name="theme">Theme to search.</param> /// <param name="name">File name to search for.</param> /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns> - private ActionResult GetImageFile(string basePath, string? theme, string? name) + private ActionResult GetImageFile(string basePath, string theme, string? name) { var themeFolder = Path.Combine(basePath, theme); if (Directory.Exists(themeFolder)) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 4a67c1aed..76e53b9a5 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; @@ -1268,7 +1269,7 @@ namespace Jellyfin.Api.Controllers Response.Headers.Add(key, value); } - Response.ContentType = imageContentType; + Response.ContentType = imageContentType ?? MediaTypeNames.Text.Plain; Response.Headers.Add(HeaderNames.Age, Convert.ToInt64((DateTime.UtcNow - dateImageModified).TotalSeconds).ToString(CultureInfo.InvariantCulture)); Response.Headers.Add(HeaderNames.Vary, HeaderNames.Accept); diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index ab73aa428..b6cb79716 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -334,10 +334,21 @@ namespace Jellyfin.Api.Controllers private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath) { using var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false); + if (result.Content.Headers.ContentType?.MediaType == null) + { + throw new NullReferenceException(nameof(result.Content.Headers.ContentType)); + } + var ext = result.Content.Headers.ContentType.MediaType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + var directory = Path.GetDirectoryName(fullCachePath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + Directory.CreateDirectory(directory); using (var stream = result.Content) { await using var fileStream = new FileStream( @@ -351,7 +362,13 @@ namespace Jellyfin.Api.Controllers await stream.CopyToAsync(fileStream).ConfigureAwait(false); } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); + if (pointerCacheDirectory == null) + { + throw new NullReferenceException(nameof(pointerCacheDirectory)); + } + + Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath).ConfigureAwait(false); } diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 8a872ae13..60bbc5022 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -455,7 +455,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions().AddClientFields(Request); - BaseItem parent = item.GetParent(); + BaseItem? parent = item.GetParent(); while (parent != null) { @@ -466,7 +466,7 @@ namespace Jellyfin.Api.Controllers baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user)); - parent = parent.GetParent(); + parent = parent?.GetParent(); } return baseItemDtos; @@ -854,7 +854,7 @@ namespace Jellyfin.Api.Controllers return _libraryManager.GetItemsResult(query).TotalRecordCount; } - private BaseItem TranslateParentItem(BaseItem item, User user) + private BaseItem? TranslateParentItem(BaseItem item, User user) { return item.GetParent() is AggregateFolder ? _libraryManager.GetUserRootFolder().GetChildren(user, true) diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 31253cbbc..384a48705 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1078,7 +1078,7 @@ namespace Jellyfin.Api.Controllers var client = _httpClientFactory.CreateClient(NamedClient.Default); // https://json.schedulesdirect.org/20141201/available/countries // Can't dispose the response as it's required up the call chain. - var response = await client.GetAsync("https://json.schedulesdirect.org/20141201/available/countries") + var response = await client.GetAsync(new Uri("https://json.schedulesdirect.org/20141201/available/countries")) .ConfigureAwait(false); return File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), MediaTypeNames.Application.Json); diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index e434f190a..989c383fd 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers { var dtoOptions = new DtoOptions().AddClientFields(Request); - MusicGenre item; + MusicGenre? item; if (genreName.IndexOf(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase) != -1) { @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers return _dtoService.GetBaseItemDto(item, dtoOptions); } - private T GetItemFromSlugName<T>(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) + private T? GetItemFromSlugName<T>(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) where T : BaseItem, new() { var result = libraryManager.GetItemList(new InternalItemsQuery diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 1d9de14d2..a104af4e6 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -54,6 +54,11 @@ namespace Jellyfin.Api.Controllers string.IsNullOrEmpty(assemblyGuid) ? default : Guid.Parse(assemblyGuid)) .FirstOrDefault(); + if (result == null) + { + return NotFound(); + } + return result; } diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 5f095443b..ad76b3984 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -157,9 +157,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesImageFile] - public async Task<ActionResult> GetRemoteImage([FromQuery, Required] string imageUrl) + public async Task<ActionResult> GetRemoteImage([FromQuery, Required] Uri imageUrl) { - var urlHash = imageUrl.GetMD5(); + var urlHash = imageUrl.ToString().GetMD5(); var pointerCachePath = GetFullCachePath(urlHash.ToString()); string? contentPath = null; @@ -245,17 +245,35 @@ namespace Jellyfin.Api.Controllers /// <param name="urlHash">The URL hash.</param> /// <param name="pointerCachePath">The pointer cache path.</param> /// <returns>Task.</returns> - private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath) + private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath) { var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); using var response = await httpClient.GetAsync(url).ConfigureAwait(false); + if (response.Content.Headers.ContentType?.MediaType == null) + { + throw new NullReferenceException(nameof(response.Content.Headers.ContentType)); + } + var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + var fullCacheDirectory = Path.GetDirectoryName(fullCachePath); + if (fullCacheDirectory == null) + { + throw new NullReferenceException(nameof(fullCacheDirectory)); + } + + Directory.CreateDirectory(fullCacheDirectory); await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); + if (pointerCacheDirectory == null) + { + throw new NullReferenceException(nameof(pointerCacheDirectory)); + } + + Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) .ConfigureAwait(false); } diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 62c870cb1..e75f0d06b 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers } } - private T GetParentWithImage<T>(BaseItem item, ImageType type) + private T? GetParentWithImage<T>(BaseItem item, ImageType type) where T : BaseItem { return item.GetParents().OfType<T>().FirstOrDefault(i => i.HasImage(type)); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index d7bcf79c1..517239966 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -361,7 +361,13 @@ namespace Jellyfin.Api.Controllers var threads = _encodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions); var format = !string.IsNullOrWhiteSpace(state.Request.SegmentContainer) ? "." + state.Request.SegmentContainer : ".ts"; - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; var segmentFormat = format.TrimStart('.'); if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index a3f2d88ce..c6d577b19 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -1,4 +1,5 @@ -using System.Net.Http; +using System; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; @@ -98,6 +99,11 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest) { + if (_httpContextAccessor.HttpContext == null) + { + throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + } + bool isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == System.Net.WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index ea012f837..20bca731f 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Helpers StreamingRequestDto streamingRequest, bool enableAdaptiveBitrateStreaming) { - var isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == WebRequestMethods.Http.Head; + var isHeadRequest = _httpContextAccessor.HttpContext?.Request.Method == WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); return await GetMasterPlaylistInternal( streamingRequest, @@ -130,6 +130,11 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, CancellationTokenSource cancellationTokenSource) { + if (_httpContextAccessor.HttpContext == null) + { + throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + } + using var state = await StreamingHelpers.GetStreamingState( streamingRequest, _httpContextAccessor.HttpContext.Request, @@ -487,14 +492,14 @@ namespace Jellyfin.Api.Helpers if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) { - string profile = state.GetRequestedProfiles("h264").FirstOrDefault(); + string? profile = state.GetRequestedProfiles("h264").FirstOrDefault(); return HlsCodecStringHelpers.GetH264String(profile, level); } if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) { - string profile = state.GetRequestedProfiles("h265").FirstOrDefault(); + string? profile = state.GetRequestedProfiles("h265").FirstOrDefault(); return HlsCodecStringHelpers.GetH265String(profile, level); } diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index 366301d3e..20c94cdda 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -37,8 +37,8 @@ namespace Jellyfin.Api.Helpers } // Can't dispose the response as it's required up the call chain. - var response = await httpClient.GetAsync(state.MediaPath).ConfigureAwait(false); - var contentType = response.Content.Headers.ContentType.ToString(); + var response = await httpClient.GetAsync(new Uri(state.MediaPath)).ConfigureAwait(false); + var contentType = response.Content.Headers.ContentType?.ToString(); httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; diff --git a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs index 95f1906ef..1bd3d67ff 100644 --- a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Api.Helpers /// </summary> /// <param name="profile">AAC profile.</param> /// <returns>AAC codec string.</returns> - public static string GetAACString(string profile) + public static string GetAACString(string? profile) { StringBuilder result = new StringBuilder("mp4a", 9); @@ -46,7 +46,7 @@ namespace Jellyfin.Api.Helpers /// <param name="profile">H.264 profile.</param> /// <param name="level">H.264 level.</param> /// <returns>H.264 string.</returns> - public static string GetH264String(string profile, int level) + public static string GetH264String(string? profile, int level) { StringBuilder result = new StringBuilder("avc1", 11); @@ -80,7 +80,7 @@ namespace Jellyfin.Api.Helpers /// <param name="profile">H.265 profile.</param> /// <param name="level">H.265 level.</param> /// <returns>H.265 string.</returns> - public static string GetH265String(string profile, int level) + public static string GetH265String(string? profile, int level) { // The h265 syntax is a bit of a mystery at the time this comment was written. // This is what I've found through various sources: diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 242496697..16fbac7ae 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -45,6 +45,10 @@ namespace Jellyfin.Api.Helpers while (!reader.EndOfStream) { var line = await reader.ReadLineAsync().ConfigureAwait(false); + if (line == null) + { + throw new NullReferenceException(nameof(line)); + } if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) { diff --git a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs index e00ed3304..65c03c710 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs @@ -90,6 +90,11 @@ namespace Jellyfin.Api.Helpers allowAsyncFileRead = true; } + if (_path == null) + { + throw new NullReferenceException(nameof(_path)); + } + await using var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); var eofCount = 0; diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index f4ec29bde..1d102071c 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -83,6 +83,10 @@ namespace Jellyfin.Api.Helpers } streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query); + if (httpRequest.Path.Value == null) + { + throw new NullReferenceException(nameof(httpRequest.Path)); + } var url = httpRequest.Path.Value.Split('.').Last(); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 0db1fabff..b72e33af3 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -102,7 +102,7 @@ namespace Jellyfin.Api.Helpers /// </summary> /// <param name="playSessionId">Playback session id.</param> /// <returns>The transcoding job.</returns> - public TranscodingJobDto GetTranscodingJob(string playSessionId) + public TranscodingJobDto? GetTranscodingJob(string playSessionId) { lock (_activeTranscodingJobs) { @@ -116,7 +116,7 @@ namespace Jellyfin.Api.Helpers /// <param name="path">Path to the transcoding file.</param> /// <param name="type">The <see cref="TranscodingJobType"/>.</param> /// <returns>The transcoding job.</returns> - public TranscodingJobDto GetTranscodingJob(string path, TranscodingJobType type) + public TranscodingJobDto? GetTranscodingJob(string path, TranscodingJobType type) { lock (_activeTranscodingJobs) { @@ -193,9 +193,13 @@ namespace Jellyfin.Api.Helpers /// Called when [transcode kill timer stopped]. /// </summary> /// <param name="state">The state.</param> - private async void OnTranscodeKillTimerStopped(object state) + private async void OnTranscodeKillTimerStopped(object? state) { - var job = (TranscodingJobDto)state; + var job = (TranscodingJobDto?)state; + if (job == null) + { + throw new NullReferenceException(nameof(job)); + } if (!job.HasExited && job.Type != TranscodingJobType.Progressive) { @@ -489,7 +493,13 @@ namespace Jellyfin.Api.Helpers CancellationTokenSource cancellationTokenSource, string? workingDirectory = null) { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + Directory.CreateDirectory(directory); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); @@ -523,7 +533,7 @@ namespace Jellyfin.Api.Helpers RedirectStandardInput = true, FileName = _mediaEncoder.EncoderPath, Arguments = commandLineArguments, - WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? null : workingDirectory, + WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? string.Empty : workingDirectory, ErrorDialog = false }, EnableRaisingEvents = true @@ -827,7 +837,7 @@ namespace Jellyfin.Api.Helpers { lock (_transcodingLocks) { - if (!_transcodingLocks.TryGetValue(outputPath, out SemaphoreSlim result)) + if (!_transcodingLocks.TryGetValue(outputPath, out SemaphoreSlim? result)) { result = new SemaphoreSlim(1, 1); _transcodingLocks[outputPath] = result; @@ -837,7 +847,7 @@ namespace Jellyfin.Api.Helpers } } - private void OnPlaybackProgress(object sender, PlaybackProgressEventArgs e) + private void OnPlaybackProgress(object? sender, PlaybackProgressEventArgs e) { if (!string.IsNullOrWhiteSpace(e.PlaySessionId)) { diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs index b9507a4e5..9edc19bb6 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// Start kill timer. /// </summary> /// <param name="callback">Callback action.</param> - public void StartKillTimer(Action<object> callback) + public void StartKillTimer(Action<object?> callback) { StartKillTimer(callback, PingTimeout); } @@ -206,7 +206,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// </summary> /// <param name="callback">Callback action.</param> /// <param name="intervalMs">Callback interval.</param> - public void StartKillTimer(Action<object> callback, int intervalMs) + public void StartKillTimer(Action<object?> callback, int intervalMs) { if (HasExited) { diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index b5e42ea29..872a46824 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -101,7 +101,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos return _config.GetConfiguration<EncodingOptions>("encoding"); } - private async void TimerCallback(object state) + private async void TimerCallback(object? state) { if (_job.HasExited) { diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 77d55828d..ce5465116 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -56,7 +56,7 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private void OnEntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e) + private void OnEntryCreated(object? sender, GenericEventArgs<ActivityLogEntry> e) { SendData(true); } diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index 80314b923..94df23e56 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -64,19 +64,19 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private void OnTaskCompleted(object sender, TaskCompletionEventArgs e) + private void OnTaskCompleted(object? sender, TaskCompletionEventArgs e) { SendData(true); e.Task.TaskProgress -= OnTaskProgress; } - private void OnTaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e) + private void OnTaskExecuting(object? sender, GenericEventArgs<IScheduledTaskWorker> e) { SendData(true); e.Argument.TaskProgress += OnTaskProgress; } - private void OnTaskProgress(object sender, GenericEventArgs<double> e) + private void OnTaskProgress(object? sender, GenericEventArgs<double> e) { SendData(false); } diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs index 1cf43a005..d996ac69f 100644 --- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs @@ -66,37 +66,37 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private async void OnSessionManagerSessionActivity(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionActivity(object? sender, SessionEventArgs e) { await SendData(false).ConfigureAwait(false); } - private async void OnSessionManagerCapabilitiesChanged(object sender, SessionEventArgs e) + private async void OnSessionManagerCapabilitiesChanged(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackProgress(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackProgress(object? sender, PlaybackProgressEventArgs e) { await SendData(!e.IsAutomated).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackStopped(object sender, PlaybackStopEventArgs e) + private async void OnSessionManagerPlaybackStopped(object? sender, PlaybackStopEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackStart(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackStart(object? sender, PlaybackProgressEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionEnded(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerSessionStarted(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionStarted(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 0a9958b9e..8b3c6b2e6 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -758,7 +758,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles case MediaProtocol.Http: { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(path, cancellationToken) + .GetAsync(new Uri(path), cancellationToken) .ConfigureAwait(false); return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index afe7351d3..55c0e6c9a 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -210,9 +210,9 @@ namespace MediaBrowser.Model.Net return enableStreamDefault ? "application/octet-stream" : null; } - public static string? ToExtension(string mimeType) + public static string? ToExtension(string? mimeType) { - if (mimeType.Length == 0) + if (string.IsNullOrEmpty(mimeType)) { throw new ArgumentException("String can't be empty.", nameof(mimeType)); } @@ -220,7 +220,7 @@ namespace MediaBrowser.Model.Net // handle text/html; charset=UTF-8 mimeType = mimeType.Split(';')[0]; - if (_extensionLookup.TryGetValue(mimeType, out string result)) + if (_extensionLookup.TryGetValue(mimeType, out string? result)) { return result; } -- cgit v1.2.3 From ff49a3bb6156a6b50a43d398796a8b4f3b4c2bda Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 14 Nov 2020 16:28:49 +0100 Subject: Missed some stuff --- DvdLib/Ifo/Dvd.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- .../Library/Resolvers/Audio/AudioResolver.cs | 2 +- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- Jellyfin.Api/Controllers/FilterController.cs | 6 +++--- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 4 ++-- MediaBrowser.Model/Dlna/ContainerProfile.cs | 2 +- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 2 +- MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs | 2 +- RSSDP/HttpParserBase.cs | 8 ++++---- 12 files changed, 18 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index 361319625..b4a11ed5d 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -31,7 +31,7 @@ namespace DvdLib.Ifo continue; } - var nums = ifo.Name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); + var nums = ifo.Name.Split('_', StringSplitOptions.RemoveEmptyEntries); if (nums.Length >= 2 && ushort.TryParse(nums[1], out var ifoNumber)) { ReadVTS(ifoNumber, ifo.FullName); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index f16eda1ec..7074382b6 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2705,7 +2705,7 @@ namespace Emby.Server.Implementations.Library var videos = videoListResolver.Resolve(fileSystemChildren); - var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase)); + var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files[0].Path, StringComparison.OrdinalIgnoreCase)); if (currentVideo != null) { diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index 70be52411..2c4497c69 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -201,7 +201,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio continue; } - var firstMedia = resolvedItem.Files.First(); + var firstMedia = resolvedItem.Files[0]; var libraryItem = new T { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 8439f8a99..171e44258 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -106,7 +106,7 @@ namespace Emby.Server.Implementations.ScheduledTasks try { previouslyFailedImages = File.ReadAllText(failHistoryPath) - .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) + .Split('|', StringSplitOptions.RemoveEmptyEntries) .ToList(); } catch (IOException) diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 2a567c846..008bb58d1 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -78,8 +78,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery { User = user, - MediaTypes = (mediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), - IncludeItemTypes = (includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), + MediaTypes = (mediaTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries), + IncludeItemTypes = (includeItemTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries), Recursive = true, EnableTotalRecordCount = false, DtoOptions = new DtoOptions @@ -168,7 +168,7 @@ namespace Jellyfin.Api.Controllers var genreQuery = new InternalItemsQuery(user) { IncludeItemTypes = - (includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), + (includeItemTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries), DtoOptions = new DtoOptions { Fields = Array.Empty<ItemFields>(), diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index cdeefbbbd..15a70e2e7 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -149,7 +149,7 @@ namespace MediaBrowser.MediaEncoding.Probing var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC"); if (!string.IsNullOrWhiteSpace(iTunEXTC)) { - var parts = iTunEXTC.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + var parts = iTunEXTC.Split('|', StringSplitOptions.RemoveEmptyEntries); // Example // mpaa|G|100|For crude humor if (parts.Length > 1) @@ -1139,7 +1139,7 @@ namespace MediaBrowser.MediaEncoding.Probing return null; } - return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) + return value.Split('/', StringSplitOptions.RemoveEmptyEntries) .Select(i => i.Trim()) .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index f77d9b267..09afa64bb 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Dlna return Array.Empty<string>(); } - return value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + return value.Split(',', StringSplitOptions.RemoveEmptyEntries); } public bool ContainsContainer(string container) diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 8b73ecbd4..50e3374f7 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -186,7 +186,7 @@ namespace MediaBrowser.Model.Dlna if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn)) { - orgPnValues.AddRange(mediaProfile.OrgPn.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)); + orgPnValues.AddRange(mediaProfile.OrgPn.Split(',', StringSplitOptions.RemoveEmptyEntries)); } else { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 4959a9b92..13234c381 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1647,7 +1647,7 @@ namespace MediaBrowser.Model.Dlna // strip spaces to avoid having to encode var values = value - .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + .Split('|', StringSplitOptions.RemoveEmptyEntries); if (condition.Condition == ProfileConditionType.Equals || condition.Condition == ProfileConditionType.EqualsAny) { diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 32dab60a6..9eed6172d 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -391,7 +391,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb item.Genres = Array.Empty<string>(); foreach (var genre in result.Genre - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(i => i.Trim()) .Where(i => !string.IsNullOrWhiteSpace(i))) { diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs index b34e52235..e5a3e9a6a 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb _logger.LogError(e, "Failed to retrieve series with remote id {RemoteId}", id); } - return result?.Data.First().Id.ToString(); + return result?.Data[0].Id.ToString(CultureInfo.InvariantCulture); } /// <summary> diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index a40612bc2..11202940e 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -119,7 +119,7 @@ namespace Rssdp.Infrastructure } else { - headersToAddTo.TryAddWithoutValidation(headerName, values.First()); + headersToAddTo.TryAddWithoutValidation(headerName, values[0]); } } @@ -151,7 +151,7 @@ namespace Rssdp.Infrastructure return lineIndex; } - private IList<string> ParseValues(string headerValue) + private List<string> ParseValues(string headerValue) { // This really should be better and match the HTTP 1.1 spec, // but this should actually be good enough for SSDP implementations @@ -160,7 +160,7 @@ namespace Rssdp.Infrastructure if (headerValue == "\"\"") { - values.Add(String.Empty); + values.Add(string.Empty); return values; } @@ -172,7 +172,7 @@ namespace Rssdp.Infrastructure else { var segments = headerValue.Split(SeparatorCharacters); - if (headerValue.Contains("\"")) + if (headerValue.Contains('"')) { for (int segmentIndex = 0; segmentIndex < segments.Length; segmentIndex++) { -- cgit v1.2.3 From a6ad36b57a78984d4a76fac2f760524a7692511b Mon Sep 17 00:00:00 2001 From: Fernando Fernández <ferferga.fer@gmail.com> Date: Tue, 17 Nov 2020 14:20:18 +0100 Subject: Don't scale images extracted by ffmpeg --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 5a3a9185d..d804e6443 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -520,29 +520,29 @@ namespace MediaBrowser.MediaEncoding.Encoder var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); - // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. + // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar - var vf = "scale=600:trunc(600/dar/2)*2"; + var vf = String.Empty; if (threedFormat.HasValue) { switch (threedFormat.Value) { case Video3DFormat.HalfSideBySide: - vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. + vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. break; case Video3DFormat.FullSideBySide: - vf = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - // fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to 600. + vf = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + // fsbs crop width in half,set the display aspect,crop out any black bars we may have made break; case Video3DFormat.HalfTopAndBottom: - vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to 600 + vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made break; case Video3DFormat.FullTopAndBottom: - vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made the scale width to 600 + vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made break; default: break; -- cgit v1.2.3 From 94cae4f1455995a0a35df8d1b7c64760387e5b64 Mon Sep 17 00:00:00 2001 From: Fernando Fernández <ferferga.fer@gmail.com> Date: Tue, 17 Nov 2020 14:46:23 +0100 Subject: Specify threads to ffmpeg properly --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 12 +++++++++--- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 14 ++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3e5457dbd..4726211d2 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dto; @@ -25,6 +26,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IServerApplicationPaths _appPaths; private readonly IJsonSerializer _json; private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(); + private readonly IServerConfigurationManager _serverConfigurationManager; private bool _hasExited; private Stream _logFileStream; @@ -35,12 +37,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV ILogger logger, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, - IJsonSerializer json) + IJsonSerializer json, + IServerConfigurationManager serverConfigurationManager) { _logger = logger; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; + _serverConfigurationManager = serverConfigurationManager; } private static bool CopySubtitles => false; @@ -179,15 +183,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var outputParam = string.Empty; + var threads = EncodingHelper.GetNumberOfThreads(null, _serverConfigurationManager.GetEncodingOptions(), null); var commandLineArgs = string.Format( CultureInfo.InvariantCulture, - "-i \"{0}\" {2} -map_metadata -1 -threads 0 {3}{4}{5} -y \"{1}\"", + "-i \"{0}\" {2} -map_metadata -1 -threads {6} {3}{4}{5} -y \"{1}\"", inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), subtitleArgs, - outputParam); + outputParam, + threads); return inputModifier + " " + commandLineArgs; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d804e6443..2b4712b2d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -64,6 +64,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private string _ffmpegPath = string.Empty; private string _ffprobePath; + private int threads; public MediaEncoder( ILogger<MediaEncoder> logger, @@ -129,6 +130,7 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); SetAvailableHwaccels(validator.GetHwaccels()); + threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); } _logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty); @@ -377,9 +379,9 @@ namespace MediaBrowser.MediaEncoding.Encoder CancellationToken cancellationToken) { 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_format"; - args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath).Trim(); + ? "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_chapters -show_format" + : "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_format"; + args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, threads).Trim(); var process = new Process { @@ -555,8 +557,8 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; - var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : - string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); + var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {5} -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail, threads) : + string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -693,7 +695,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); -- cgit v1.2.3 From 4b1c9dc9eaa120a30a7820257a83dd5aa3ecd9f4 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 17 Nov 2020 19:43:00 +0100 Subject: Pass cancellation where possible --- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 4 ++-- Emby.Server.Implementations/ApplicationHost.cs | 2 +- Emby.Server.Implementations/Data/SqliteExtensions.cs | 14 -------------- .../LiveTv/EmbyTV/DirectRecorder.cs | 7 ++++--- .../LiveTv/Listings/SchedulesDirect.cs | 18 +++++++++--------- .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 6 +++--- .../LiveTv/TunerHosts/M3uParser.cs | 2 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- .../Updates/InstallationManager.cs | 7 ++++--- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 6 ++++-- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Providers/Manager/ItemImageProvider.cs | 4 ++-- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../Plugins/AudioDb/AlbumProvider.cs | 2 +- .../Plugins/AudioDb/ArtistProvider.cs | 2 +- .../Plugins/MusicBrainz/ArtistProvider.cs | 6 +++--- .../Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs | 10 +++++----- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 4 ++-- 20 files changed, 47 insertions(+), 57 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index c8c36fc97..f4d793790 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -45,7 +45,7 @@ namespace Emby.Dlna.PlayTo header, cancellationToken) .ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var reader = new StreamReader(stream, Encoding.UTF8); return XDocument.Parse( await reader.ReadToEndAsync().ConfigureAwait(false), @@ -94,7 +94,7 @@ namespace Emby.Dlna.PlayTo options.Headers.UserAgent.ParseAdd(USERAGENT); options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var reader = new StreamReader(stream, Encoding.UTF8); return XDocument.Parse( await reader.ReadToEndAsync().ConfigureAwait(false), diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ad3c19618..17b99c858 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1378,7 +1378,7 @@ namespace Emby.Server.Implementations using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var result = await System.Text.Json.JsonSerializer.DeserializeAsync<string>(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false); var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index 70a6df977..1af301ceb 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -107,20 +107,6 @@ namespace Emby.Server.Implementations.Data return null; } - public static void Attach(SQLiteDatabaseConnection db, string path, string alias) - { - var commandText = string.Format( - CultureInfo.InvariantCulture, - "attach @path as {0};", - alias); - - using (var statement = db.PrepareStatement(commandText)) - { - statement.TryBind("@path", path); - statement.MoveNext(); - } - } - public static bool IsDBNull(this IReadOnlyList<IResultSetValue> result, int index) { return result[index].SQLiteType == SQLiteType.Null; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 44560d1e2..341194f23 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -77,11 +77,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logger.LogInformation("Copying recording stream to file {0}", targetFile); // The media source if infinite so we need to handle stopping ourselves - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + using var durationToken = new CancellationTokenSource(duration); + using var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token); + cancellationToken = linkedCancellationToken.Token; await _streamHelper.CopyUntilCancelled( - await response.Content.ReadAsStreamAsync().ConfigureAwait(false), + await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false), output, IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 43128c60d..91f7c7931 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json); options.Headers.TryAddWithoutValidation("token", token); using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(responseStream).ConfigureAwait(false); _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); @@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); - await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponseStream).ConfigureAwait(false); var programDict = programDetails.ToDictionary(p => p.programID, y => y); @@ -480,9 +480,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false); - await using var response = await innerResponse2.Content.ReadAsStreamAsync().ConfigureAwait(false); - return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>( - response).ConfigureAwait(false); + await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>(response).ConfigureAwait(false); } catch (Exception ex) { @@ -509,7 +508,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false); - await using var response = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var root = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Headends>>(response).ConfigureAwait(false); @@ -542,6 +541,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>(); private DateTime _lastErrorResponse; + private async Task<string> GetToken(ListingsProviderInfo info, CancellationToken cancellationToken) { var username = info.Username; @@ -651,7 +651,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + hashedPassword + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json); using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(stream).ConfigureAwait(false); if (root.message == "OK") { @@ -705,7 +705,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); - await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var response = httpResponse.Content; var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(stream).ConfigureAwait(false); @@ -780,7 +780,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings var list = new List<ChannelInfo>(); using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(stream).ConfigureAwait(false); _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count); _logger.LogInformation("Mapping Stations to Channel"); diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 2d6f453bd..76c875737 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew)) { await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 9fdbad63c..c0a4d1228 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List<Channels>(); @@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false); @@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); var tuners = new List<LiveTvTunerInfo>(); while (!sr.EndOfStream) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 7c13d45e9..6ea1e1dd7 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts .SendAsync(requestMessage, cancellationToken) .ConfigureAwait(false); response.EnsureSuccessStatusCode(); - return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); } return File.OpenRead(info.Url); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 2e1b89509..2de447ad9 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -135,7 +135,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using var message = response; - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); await StreamHelper.CopyToAsync( stream, diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 6b6b8c4fe..851e7bd68 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.Updates { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(manifest, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); try { @@ -241,7 +241,8 @@ namespace Emby.Server.Implementations.Updates _currentInstallations.Add(tuple); } - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token; + using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token); + var linkedToken = linkedTokenSource.Token; await _eventManager.PublishAsync(new PluginInstallingEventArgs(package)).ConfigureAwait(false); @@ -333,7 +334,7 @@ namespace Emby.Server.Implementations.Updates using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(package.SourceUrl, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); // CA5351: Do Not Use Broken Cryptographic Algorithms #pragma warning disable CA5351 diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index 20c94cdda..cfa2c1229 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -24,12 +24,14 @@ namespace Jellyfin.Api.Helpers /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param> /// <param name="httpClient">The <see cref="HttpClient"/> making the remote request.</param> /// <param name="httpContext">The current http context.</param> + /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param> /// <returns>A <see cref="Task{ActionResult}"/> containing the API response.</returns> public static async Task<ActionResult> GetStaticRemoteStreamResult( StreamState state, bool isHeadRequest, HttpClient httpClient, - HttpContext httpContext) + HttpContext httpContext, + CancellationToken cancellationToken = default) { if (state.RemoteHttpHeaders.TryGetValue(HeaderNames.UserAgent, out var useragent)) { @@ -47,7 +49,7 @@ namespace Jellyfin.Api.Helpers return new FileContentResult(Array.Empty<byte>(), contentType); } - return new FileStreamResult(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), contentType); + return new FileStreamResult(await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false), contentType); } /// <summary> diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 8b3c6b2e6..b61b8a0e0 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -760,7 +760,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(new Uri(path), cancellationToken) .ConfigureAwait(false); - return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); } case MediaProtocol.File: diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 39748171a..ffc6889fa 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -469,7 +469,7 @@ namespace MediaBrowser.Providers.Manager try { using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await _providerManager.SaveImage( item, @@ -586,7 +586,7 @@ namespace MediaBrowser.Providers.Manager } } - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await _providerManager.SaveImage( item, stream, diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 7a1b7bb2c..58ca88a5b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -181,7 +181,7 @@ namespace MediaBrowser.Providers.Manager throw new HttpRequestException("Invalid image received.", null, HttpStatusCode.NotFound); } - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await SaveImage( item, stream, diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index e6d89e688..6536b303f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 72dad8a25..85c92fa7b 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index f27da7ce6..dc755b600 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.Music var url = "/ws/2/artist/?query=arid:{0}" + musicBrainzId.ToString(CultureInfo.InvariantCulture); using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); return GetResultsFromResponse(stream); } else @@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Music var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch)); using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false)) - await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + await using (var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false)) { var results = GetResultsFromResponse(stream).ToList(); @@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.Music url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); return GetResultsFromResponse(stream); } } diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs index 31f0123dc..93178d64a 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrWhiteSpace(url)) { using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); return GetResultsFromResponse(stream); } @@ -284,7 +284,7 @@ namespace MediaBrowser.Providers.Music artistId); using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var oReader = new StreamReader(stream, Encoding.UTF8); var settings = new XmlReaderSettings { @@ -307,7 +307,7 @@ namespace MediaBrowser.Providers.Music WebUtility.UrlEncode(artistName)); using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var oReader = new StreamReader(stream, Encoding.UTF8); var settings = new XmlReaderSettings() { @@ -622,7 +622,7 @@ namespace MediaBrowser.Providers.Music var url = "/ws/2/release?release-group=" + releaseGroupId.ToString(CultureInfo.InvariantCulture); using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var oReader = new StreamReader(stream, Encoding.UTF8); var settings = new XmlReaderSettings { @@ -649,7 +649,7 @@ namespace MediaBrowser.Providers.Music var url = "/ws/2/release-group/?query=reid:" + releaseEntryId.ToString(CultureInfo.InvariantCulture); using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); using var oReader = new StreamReader(stream, Encoding.UTF8); var settings = new XmlReaderSettings { diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 705359d2c..43d8af75f 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var url = OmdbProvider.GetOmdbUrl(urlQuery); using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var resultList = new List<SearchResult>(); if (isSearch) diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 9eed6172d..6af52b591 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -298,7 +298,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb imdbParam)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(rootObject, path); @@ -336,7 +336,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb seasonId)); using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(rootObject, path); -- cgit v1.2.3 From 38c3b6fcd37d71d09c6afe26ad26c762850f9971 Mon Sep 17 00:00:00 2001 From: Fernando Fernández <ferferga.fer@gmail.com> Date: Wed, 18 Nov 2020 10:01:03 +0100 Subject: Fix build and thread detection logic --- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 1 + Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 13 ++++++++----- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 16 ++++++++-------- 6 files changed, 20 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index fcc2d1eeb..0dc045ee6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1635,7 +1635,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (mediaSource.RequiresLooping || !(mediaSource.Container ?? string.Empty).EndsWith("ts", StringComparison.OrdinalIgnoreCase) || (mediaSource.Protocol != MediaProtocol.File && mediaSource.Protocol != MediaProtocol.Http)) { - return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer); + return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _config); } return new DirectRecorder(_logger, _httpClientFactory, _streamHelper); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 4726211d2..e6ee9819e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -8,6 +8,7 @@ using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 6e59da798..bba5e972e 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1329,7 +1329,7 @@ namespace Jellyfin.Api.Controllers { var videoCodec = _encodingHelper.GetVideoEncoder(state, encodingOptions); - var threads = _encodingHelper.GetNumberOfThreads(state, encodingOptions, videoCodec); + var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, videoCodec); // GetNumberOfThreads is static if (state.BaseRequest.BreakOnNonKeyFrames) { diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 389dc8a08..065fa786e 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -359,7 +359,7 @@ namespace Jellyfin.Api.Controllers private string GetCommandLineArguments(string outputPath, StreamState state) { var videoCodec = _encodingHelper.GetVideoEncoder(state, _encodingOptions); - var threads = _encodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); + var threads = EncodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); // GetNumberOfThreads is static var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions); var format = !string.IsNullOrWhiteSpace(state.Request.SegmentContainer) ? "." + state.Request.SegmentContainer : ".ts"; var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 3a9f57c55..60c44cfcf 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2329,20 +2329,23 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Gets the number of threads. /// </summary> - public int GetNumberOfThreads(EncodingJobInfo state, EncodingOptions encodingOptions, string outputVideoCodec) + public static int GetNumberOfThreads(EncodingJobInfo state, EncodingOptions encodingOptions, string outputVideoCodec) { - if (string.Equals(outputVideoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + if (outputVideoCodec != null && string.Equals(outputVideoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { // per docs: // -threads number of threads to use for encoding, can't be 0 [auto] with VP8 // (recommended value : number of real cores - 1) return Math.Max(Environment.ProcessorCount - 1, 1); } - - var threads = state.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount; + var threads = state?.BaseRequest.CpuCoreLimit ?? encodingOptions.EncodingThreadCount; // Automatic - if (threads <= 0 || threads >= Environment.ProcessorCount) + if (threads <= 0) + { + return 0; + } + else if (threads >= Environment.ProcessorCount) { return Environment.ProcessorCount; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 2b4712b2d..5f60c09ae 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -524,26 +524,26 @@ namespace MediaBrowser.MediaEncoding.Encoder // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar - var vf = String.Empty; + var vf = string.Empty; if (threedFormat.HasValue) { switch (threedFormat.Value) { case Video3DFormat.HalfSideBySide: - vf = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + vf = "-vf crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. break; case Video3DFormat.FullSideBySide: - vf = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + vf = "-vf crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; // fsbs crop width in half,set the display aspect,crop out any black bars we may have made break; case Video3DFormat.HalfTopAndBottom: - vf = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + vf = "-vf crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made break; case Video3DFormat.FullTopAndBottom: - vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; + vf = "-vf crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made break; default: @@ -557,8 +557,8 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; - var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {5} -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail, threads) : - string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); + var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {5} -v quiet -vframes 1 {2}{4} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail, threads) : + string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); @@ -695,7 +695,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); -- cgit v1.2.3 From 9a323f6df08927b5db06ba634f430523a236265f Mon Sep 17 00:00:00 2001 From: Greenback <jimcartlidge@yahoo.co.uk> Date: Wed, 18 Nov 2020 13:46:14 +0000 Subject: More spelling corrections. --- Jellyfin.Data/Entities/Libraries/CollectionItem.cs | 4 ++-- Jellyfin.Data/Entities/Libraries/ItemMetadata.cs | 2 +- .../Users/DefaultAuthenticationProvider.cs | 2 +- MediaBrowser.Common/Net/INetworkManager.cs | 4 ++-- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 6 +++--- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 2 +- MediaBrowser.Providers/Manager/ProviderUtils.cs | 4 ++-- MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 10 +++++----- MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs | 10 +++++----- RSSDP/DisposableManagedObjectBase.cs | 6 +++--- RSSDP/HttpParserBase.cs | 2 +- RSSDP/ISsdpDeviceLocator.cs | 4 ++-- RSSDP/SsdpDevicePublisher.cs | 4 ++-- RSSDP/SsdpRootDevice.cs | 4 ++-- 18 files changed, 36 insertions(+), 36 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs index 4467c9bbd..f9539964d 100644 --- a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs +++ b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs @@ -73,7 +73,7 @@ namespace Jellyfin.Data.Entities.Libraries /// Gets or sets the next item in the collection. /// </summary> /// <remarks> - /// TODO check if this properly updated dependant and has the proper principal relationship. + /// TODO check if this properly updated Dependant and has the proper principal relationship. /// </remarks> public virtual CollectionItem Next { get; set; } @@ -81,7 +81,7 @@ namespace Jellyfin.Data.Entities.Libraries /// Gets or sets the previous item in the collection. /// </summary> /// <remarks> - /// TODO check if this properly updated dependant and has the proper principal relationship. + /// TODO check if this properly updated Dependant and has the proper principal relationship. /// </remarks> public virtual CollectionItem Previous { get; set; } diff --git a/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs b/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs index 1d2dc0f66..d74330c05 100644 --- a/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs @@ -141,7 +141,7 @@ namespace Jellyfin.Data.Entities.Libraries public virtual ICollection<PersonRole> PersonRoles { get; protected set; } /// <summary> - /// Gets or sets a collection containing the generes for this item. + /// Gets or sets a collection containing the genres for this item. /// </summary> public virtual ICollection<Genre> Genres { get; protected set; } diff --git a/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs index f79e433a6..662b4bf65 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Server.Implementations.Users bool success = false; - // As long as jellyfin supports passwordless users, we need this little block here to accommodate + // As long as jellyfin supports password-less users, we need this little block here to accommodate if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password)) { return Task.FromResult(new ProviderAuthenticationResult diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index a0330afef..12966a474 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Net /// <summary> /// Investigates an caches a list of interface addresses, excluding local link and LAN excluded addresses. /// </summary> - /// <returns>The list of ipaddresses.</returns> + /// <returns>The list of ip addresses.</returns> IPAddress[] GetLocalIpAddresses(); /// <summary> @@ -73,7 +73,7 @@ namespace MediaBrowser.Common.Net /// Returns true if address is in the LAN list in the config file. /// </summary> /// <param name="address">The address to check.</param> - /// <param name="excludeInterfaces">If true, check against addresses in the LAN settings which have [] arroud and return true if it matches the address give in address.</param> + /// <param name="excludeInterfaces">If true, check against addresses in the LAN settings which have [] around and return true if it matches the address give in address.</param> /// <param name="excludeRFC">If true, returns false if address is in the 127.x.x.x or 169.128.x.x range.</param> /// <returns><c>false</c>if the address isn't in the LAN list, <c>true</c> if the address has been defined as a LAN address.</returns> bool IsAddressInSubnets(IPAddress address, bool excludeInterfaces, bool excludeRFC); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1d44a5511..8d7773004 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2611,7 +2611,7 @@ namespace MediaBrowser.Controller.Entities { if (!AllowsMultipleImages(type)) { - throw new ArgumentException("The change index operation is only applicable to backdrops and screenshots"); + throw new ArgumentException("The change index operation is only applicable to backdrops and screen shots"); } var info1 = GetImageInfo(type, index1); diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index a76c8a376..1e3825c6e 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -212,7 +212,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Loads our children. Validation will occur externally. - /// We want this sychronous. + /// We want this synchronous. /// </summary> protected virtual List<BaseItem> LoadChildren() { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5846a603a..a4a5cecdc 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Controller.MediaEncoding { // Only use alternative encoders for video files. // When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully - // Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this. + // Since transcoding of folder rips is experimental anyway, it's not worth adding additional variables such as this. if (state.VideoType == VideoType.VideoFile) { var hwType = encodingOptions.HardwareAccelerationType; @@ -247,7 +247,7 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } - // Seeing reported failures here, not sure yet if this is related to specfying input format + // Seeing reported failures here, not sure yet if this is related to specifying input format if (string.Equals(container, "m4v", StringComparison.OrdinalIgnoreCase)) { return null; @@ -2752,7 +2752,7 @@ namespace MediaBrowser.Controller.MediaEncoding var videoType = state.MediaSource.VideoType ?? VideoType.VideoFile; // Only use alternative encoders for video files. // When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully - // Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this. + // Since transcoding of folder rips is experimental anyway, it's not worth adding additional variables such as this. if (videoType != VideoType.VideoFile) { return null; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 5a3a9185d..e060253ee 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -542,7 +542,7 @@ namespace MediaBrowser.MediaEncoding.Encoder break; case Video3DFormat.FullTopAndBottom: vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; - // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made the scale width to 600 + // ftab crop height in half, set the display aspect,crop out any black bars we may have made the scale width to 600 break; default: break; diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index a4305c810..2f8614386 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Model.Dlna int? maxWidth, int? maxHeight) { - // If the bitrate isn't changing, then don't downlscale the resolution + // If the bitrate isn't changing, then don't downscale the resolution if (inputBitrate.HasValue && outputBitrate >= inputBitrate.Value) { if (maxWidth.HasValue || maxHeight.HasValue) diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 70a5a6ac1..5621d2b86 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.Manager { if (replaceData || string.IsNullOrEmpty(target.Name)) { - // Safeguard against incoming data having an emtpy name + // Safeguard against incoming data having an empty name if (!string.IsNullOrWhiteSpace(source.Name)) { target.Name = source.Name; @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Manager if (replaceData || string.IsNullOrEmpty(target.OriginalTitle)) { - // Safeguard against incoming data having an emtpy name + // Safeguard against incoming data having an empty name if (!string.IsNullOrWhiteSpace(source.OriginalTitle)) { target.OriginalTitle = source.OriginalTitle; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 6af52b591..332479ff8 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var result = await GetRootObject(imdbId, cancellationToken).ConfigureAwait(false); - // Only take the name and rating if the user's language is set to english, since Omdb has no localization + // Only take the name and rating if the user's language is set to English, since Omdb has no localization if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport) { item.Name = result.Title; @@ -151,7 +151,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb return false; } - // Only take the name and rating if the user's language is set to english, since Omdb has no localization + // Only take the name and rating if the user's language is set to English, since Omdb has no localization if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) || _configurationManager.Configuration.EnableNewOmdbSupport) { item.Name = result.Title; @@ -385,7 +385,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var isConfiguredForEnglish = IsConfiguredForEnglish(item) || _configurationManager.Configuration.EnableNewOmdbSupport; // Grab series genres because IMDb data is better than TVDB. Leave movies alone - // But only do it if english is the preferred language because this data will not be localized + // But only do it if English is the preferred language because this data will not be localized if (isConfiguredForEnglish && !string.IsNullOrWhiteSpace(result.Genre)) { item.Genres = Array.Empty<string>(); @@ -401,7 +401,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (isConfiguredForEnglish) { - // Omdb is currently english only, so for other languages skip this and let secondary providers fill it in + // Omdb is currently English only, so for other languages skip this and let secondary providers fill it in item.Overview = result.Plot; } @@ -455,7 +455,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb { var lang = item.GetPreferredMetadataLanguage(); - // The data isn't localized and so can only be used for english users + // The data isn't localized and so can only be used for English users return string.Equals(lang, "en", StringComparison.OrdinalIgnoreCase); } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs index b754a0795..0e8a5baab 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs @@ -98,7 +98,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb if (preferredLanguage.Length == 5) // like en-US { - // Currenty, TMDB supports 2-letter language codes only + // Currently, TMDB supports 2-letter language codes only // They are planning to change this in the future, thus we're // supplying both codes if we're having a 5-letter code. languages.Add(preferredLanguage.Substring(0, 2)); diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index 9cc0344c1..bce4cf009 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -134,7 +134,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - // int.TryParse is local aware, so it can be probamatic, force us culture + // int.TryParse is local aware, so it can be problematic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; @@ -150,7 +150,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - // int.TryParse is local aware, so it can be probamatic, force us culture + // int.TryParse is local aware, so it can be problematic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) { item.AirsAfterSeasonNumber = rval; @@ -166,7 +166,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - // int.TryParse is local aware, so it can be probamatic, force us culture + // int.TryParse is local aware, so it can be problematic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; @@ -182,7 +182,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - // int.TryParse is local aware, so it can be probamatic, force us culture + // int.TryParse is local aware, so it can be problematic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; @@ -198,7 +198,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - // int.TryParse is local aware, so it can be probamatic, force us culture + // int.TryParse is local aware, so it can be problematic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 745ec359c..7d6a471f9 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -5,7 +5,7 @@ using System.Text; namespace Rssdp.Infrastructure { /// <summary> - /// Correclty implements the <see cref="IDisposable"/> interface and pattern for an object containing only managed resources, and adds a few common niceities not on the interface such as an <see cref="IsDisposed"/> property. + /// Correctly implements the <see cref="IDisposable"/> interface and pattern for an object containing only managed resources, and adds a few common niceties not on the interface such as an <see cref="IsDisposed"/> property. /// </summary> public abstract class DisposableManagedObjectBase : IDisposable { @@ -61,10 +61,10 @@ namespace Rssdp.Infrastructure /// Disposes this object instance and all internally managed resources. /// </summary> /// <remarks> - /// <para>Sets the <see cref="IsDisposed"/> property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behaviour of derived classes.</para> + /// <para>Sets the <see cref="IsDisposed"/> property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behavior of derived classes.</para> /// </remarks> /// <seealso cref="IsDisposed"/> - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "We do exactly as asked, but CA doesn't seem to like us also setting the IsDisposed property. Too bad, it's a good idea and shouldn't cause an exception or anything likely to interfer with the dispose process.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "We do exactly as asked, but CA doesn't seem to like us also setting the IsDisposed property. Too bad, it's a good idea and shouldn't cause an exception or anything likely to interfere with the dispose process.")] public void Dispose() { IsDisposed = true; diff --git a/RSSDP/HttpParserBase.cs b/RSSDP/HttpParserBase.cs index 11202940e..c56249523 100644 --- a/RSSDP/HttpParserBase.cs +++ b/RSSDP/HttpParserBase.cs @@ -105,7 +105,7 @@ namespace Rssdp.Infrastructure var headerName = line.Substring(0, headerKeySeparatorIndex).Trim(); var headerValue = line.Substring(headerKeySeparatorIndex + 1).Trim(); - // Not sure how to determine where request headers and and content headers begin, + // Not sure how to determine where request headers and content headers begin, // at least not without a known set of headers (general headers first the content headers) // which seems like a bad way of doing it. So we'll assume if it's a known content header put it there // else use request headers. diff --git a/RSSDP/ISsdpDeviceLocator.cs b/RSSDP/ISsdpDeviceLocator.cs index 413055643..4df166cd2 100644 --- a/RSSDP/ISsdpDeviceLocator.cs +++ b/RSSDP/ISsdpDeviceLocator.cs @@ -52,7 +52,7 @@ namespace Rssdp.Infrastructure } /// <summary> - /// Aynchronously performs a search for all devices using the default search timeout, and returns an awaitable task that can be used to retrieve the results. + /// Asynchronously performs a search for all devices using the default search timeout, and returns an awaitable task that can be used to retrieve the results. /// </summary> /// <returns>A task whose result is an <see cref="System.Collections.Generic.IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<DiscoveredSsdpDevice>> SearchAsync(); @@ -83,7 +83,7 @@ namespace Rssdp.Infrastructure /// </param> /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 is recommended by the UPnP 1.1 specification. Specify TimeSpan.Zero to return only devices already in the cache.</param> /// <remarks> - /// <para>By design RSSDP does not support 'publishing services' as it is intended for use with non-standard UPnP devices that don't publish UPnP style services. However, it is still possible to use RSSDP to search for devices implemetning these services if you know the service type.</para> + /// <para>By design RSSDP does not support 'publishing services' as it is intended for use with non-standard UPnP devices that don't publish UPnP style services. However, it is still possible to use RSSDP to search for devices implementing these services if you know the service type.</para> /// </remarks> /// <returns>A task whose result is an <see cref="System.Collections.Generic.IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns> System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget, TimeSpan searchWaitTime); diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index 1a8577d8d..90925b9e0 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -102,7 +102,7 @@ namespace Rssdp.Infrastructure /// <param name="device">The <see cref="SsdpDevice"/> instance to add.</param> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> argument is null.</exception> /// <exception cref="InvalidOperationException">Thrown if the <paramref name="device"/> contains property values that are not acceptable to the UPnP 1.0 specification.</exception> - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "t", Justification = "Capture task to local variable supresses compiler warning, but task is not really needed.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "t", Justification = "Capture task to local variable suppresses compiler warning, but task is not really needed.")] public void AddDevice(SsdpRootDevice device) { if (device == null) @@ -180,7 +180,7 @@ namespace Rssdp.Infrastructure /// </summary> /// <remarks> /// <para>Enabling this option will cause devices to show up in Microsoft Windows Explorer's network screens (if discovery is enabled etc.). Windows Explorer appears to search only for pnp:rootdeivce and not upnp:rootdevice.</para> - /// <para>If false, the system will only use upnp:rootdevice for notifiation broadcasts and and search responses, which is correct according to the UPnP/SSDP spec.</para> + /// <para>If false, the system will only use upnp:rootdevice for notification broadcasts and and search responses, which is correct according to the UPnP/SSDP spec.</para> /// </remarks> public bool SupportPnpRootDevice { diff --git a/RSSDP/SsdpRootDevice.cs b/RSSDP/SsdpRootDevice.cs index 8937ec331..4084b31ca 100644 --- a/RSSDP/SsdpRootDevice.cs +++ b/RSSDP/SsdpRootDevice.cs @@ -25,7 +25,7 @@ namespace Rssdp /// Specifies how long clients can cache this device's details for. Optional but defaults to <see cref="TimeSpan.Zero"/> which means no-caching. Recommended value is half an hour. /// </summary> /// <remarks> - /// <para>Specifiy <see cref="TimeSpan.Zero"/> to indicate no caching allowed.</para> + /// <para>Specify <see cref="TimeSpan.Zero"/> to indicate no caching allowed.</para> /// <para>Also used to specify how often to rebroadcast alive notifications.</para> /// <para>The UPnP/SSDP specifications indicate this should not be less than 1800 seconds (half an hour), but this is not enforced by this library.</para> /// </remarks> @@ -50,7 +50,7 @@ namespace Rssdp public IPAddress SubnetMask { get; set; } /// <summary> - /// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional. + /// The base URL to use for all relative url's provided in other properties (and those of child devices). Optional. /// </summary> /// <remarks> /// <para>Defines the base URL. Used to construct fully-qualified URLs. All relative URLs that appear elsewhere in the description are combined with this base URL. If URLBase is empty or not given, the base URL is the URL from which the device description was retrieved (which is the preferred implementation; use of URLBase is no longer recommended). Specified by UPnP vendor. Single URL.</para> -- cgit v1.2.3 From 5ff08338d5a475d2975ecc6d4fe5222456368bd2 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Thu, 19 Nov 2020 15:02:36 +0000 Subject: Apply suggestions from code review Co-authored-by: Claus Vium <cvium@users.noreply.github.com> --- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 6 +++--- .../Probing/ProbeResultNormalizer.cs | 23 ++++++++-------------- MediaBrowser.Model/Dlna/StreamBuilder.cs | 12 +++++------ 4 files changed, 18 insertions(+), 25 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index bb8026543..b151f85e2 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -578,7 +578,7 @@ namespace Jellyfin.Api.Controllers args += _encodingHelper.GetOutputSizeParam(state, _encodingOptions, codec); } - if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)) + if (state.SubtitleStream == null || !state.SubtitleStream.IsExternal || state.SubtitleStream.IsTextSubtitleStream) { args += " -start_at_zero"; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index a2e3318f3..6e36adc16 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1194,7 +1194,7 @@ namespace MediaBrowser.Controller.MediaEncoding } } else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) - || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) + || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) { param += " -level " + level; } @@ -1205,7 +1205,7 @@ namespace MediaBrowser.Controller.MediaEncoding // NVENC cannot adjust the given level, just throw an error. } else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) - || !string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) + || !string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param += " -level " + level; } @@ -1931,7 +1931,7 @@ namespace MediaBrowser.Controller.MediaEncoding retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\""; } else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) - || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) + || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) { /* QSV in FFMpeg can now setup hardware overlay for transcodes. diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 387594ce6..3d3d1eb48 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1025,12 +1025,10 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); - if (!string.IsNullOrEmpty(bps)) + if (!string.IsNullOrEmpty(bps) + && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) { - if (int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) - { - return parsedBps; - } + return parsedBps; } } @@ -1042,12 +1040,9 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); - if (!string.IsNullOrEmpty(duration)) + if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) { - if (TimeSpan.TryParse(duration, out var parsedDuration)) - { - return parsedDuration.TotalSeconds; - } + return parsedDuration.TotalSeconds; } } @@ -1059,12 +1054,10 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo != null && streamInfo.Tags != null) { var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); - if (!string.IsNullOrEmpty(numberOfBytes)) + if (!string.IsNullOrEmpty(numberOfBytes) + && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) { - if (long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) - { - return parsedBytes; - } + return parsedBytes; } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 76b137c49..2e5137005 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -928,12 +928,12 @@ namespace MediaBrowser.Model.Dlna defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, targetAudioChannels); } else if (targetAudioChannels.HasValue - && audioStream.Channels.HasValue - && audioStream.Channels.Value <= targetAudioChannels.Value - && !string.IsNullOrEmpty(audioStream.Codec) - && targetAudioCodecs != null - && targetAudioCodecs.Length > 0 - && !Array.Exists(targetAudioCodecs, elem => string.Equals(audioStream.Codec, elem, StringComparison.OrdinalIgnoreCase))) + && audioStream.Channels.HasValue + && audioStream.Channels.Value <= targetAudioChannels.Value + && !string.IsNullOrEmpty(audioStream.Codec) + && targetAudioCodecs != null + && targetAudioCodecs.Length > 0 + && !Array.Exists(targetAudioCodecs, elem => string.Equals(audioStream.Codec, elem, StringComparison.OrdinalIgnoreCase))) { // Shift the bitrate if we're transcoding to a different audio codec. defaultBitrate = GetDefaultAudioBitrate(targetAudioCodec, audioStream.Channels.Value); -- cgit v1.2.3 From 812300ad333a8ee844ba1c5e7facbe35c98f983c Mon Sep 17 00:00:00 2001 From: Orry Verducci <orry@orryverducci.co.uk> Date: Sun, 22 Nov 2020 16:54:41 +0000 Subject: Revert "Fix frame rate probing for interlaced MKV files" This reverts commit 84fd5a09532bd1e854ec3745609f845aa7098da2. --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index cdeefbbbd..22537a4d9 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -666,16 +666,6 @@ namespace MediaBrowser.MediaEncoding.Probing stream.AverageFrameRate = GetFrameRate(streamInfo.AverageFrameRate); stream.RealFrameRate = GetFrameRate(streamInfo.RFrameRate); - // Interlaced video streams in Matroska containers return the field rate instead of the frame rate - // as both the average and real frame rate, so we half the returned frame rates to get the correct values - // - // https://gitlab.com/mbunkus/mkvtoolnix/-/wikis/Wrong-frame-rate-displayed - if (stream.IsInterlaced && formatInfo.FormatName.Contains("matroska", StringComparison.OrdinalIgnoreCase)) - { - stream.AverageFrameRate /= 2; - stream.RealFrameRate /= 2; - } - if (isAudio || string.Equals(stream.Codec, "gif", StringComparison.OrdinalIgnoreCase) || string.Equals(stream.Codec, "png", StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From d19edefbcd020e58031c8bf1101bf20328257303 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sat, 28 Nov 2020 20:55:09 +0800 Subject: fix image extraction --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 5f60c09ae..2a979e857 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -553,12 +553,18 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; - var enableThumbnail = !new List<string> { "wtv" }.Contains(container ?? string.Empty, StringComparer.OrdinalIgnoreCase); // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; + var enableThumbnail = useIFrame && !new List<string> { "wtv" }.Contains(container ?? string.Empty, StringComparer.OrdinalIgnoreCase); + if (string.IsNullOrEmpty(vf)) + { + vf = enableThumbnail ? "-vf thumbnail=24" : string.Empty; + } + else + { + vf += enableThumbnail ? ",thumbnail=24" : string.Empty; + } - var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {5} -v quiet -vframes 1 {2}{4} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail, threads) : - string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); -- cgit v1.2.3 From 53c91c2c145535f40f391f1b8d986078f10e3428 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Sat, 28 Nov 2020 21:14:55 +0800 Subject: Apply suggestions from code review Co-authored-by: BaronGreenback <jimcartlidge@yahoo.co.uk> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 2a979e857..f8a704efd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -554,7 +554,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var enableThumbnail = useIFrame && !new List<string> { "wtv" }.Contains(container ?? string.Empty, StringComparer.OrdinalIgnoreCase); + var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(vf)) { vf = enableThumbnail ? "-vf thumbnail=24" : string.Empty; -- cgit v1.2.3 From d72f3498bf2c53be0dfb900feba58d84efbffde0 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Sat, 28 Nov 2020 21:27:55 +0800 Subject: fix ci --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f8a704efd..cb162f0d4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -554,7 +554,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparer.OrdinalIgnoreCase); + var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); if (string.IsNullOrEmpty(vf)) { vf = enableThumbnail ? "-vf thumbnail=24" : string.Empty; -- cgit v1.2.3 From 0c6efe6317d1682ba71b751686360124eda41de9 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Sat, 28 Nov 2020 22:32:54 +0800 Subject: Apply suggestions from code review Co-authored-by: Claus Vium <cvium@users.noreply.github.com> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index cb162f0d4..8d83096fb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -555,13 +555,16 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); - if (string.IsNullOrEmpty(vf)) + if (enableThumbnail) { - vf = enableThumbnail ? "-vf thumbnail=24" : string.Empty; - } - else - { - vf += enableThumbnail ? ",thumbnail=24" : string.Empty; + if (string.IsNullOrEmpty(vf)) + { + vf = "-vf thumbnail=24"; + } + else + { + vf += ",thumbnail=24"; + } } var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); -- cgit v1.2.3 From bb16174936dca01812d3dc92e6728847bf994b20 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sun, 29 Nov 2020 13:12:41 +0800 Subject: increase the default image extraction timeout --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 8d83096fb..753da46a6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// The default image extraction timeout in milliseconds. /// </summary> - internal const int DefaultImageExtractionTimeout = 5000; + internal const int DefaultImageExtractionTimeout = 10000; /// <summary> /// The us culture. -- cgit v1.2.3 From c2c06ae15b9d35ad587920a2a4994cf6f3381d5a Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sun, 29 Nov 2020 13:20:55 +0800 Subject: fix image extraction --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 5f60c09ae..753da46a6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// The default image extraction timeout in milliseconds. /// </summary> - internal const int DefaultImageExtractionTimeout = 5000; + internal const int DefaultImageExtractionTimeout = 10000; /// <summary> /// The us culture. @@ -553,12 +553,21 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; - var enableThumbnail = !new List<string> { "wtv" }.Contains(container ?? string.Empty, StringComparer.OrdinalIgnoreCase); // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var thumbnail = enableThumbnail ? ",thumbnail=24" : string.Empty; + var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); + if (enableThumbnail) + { + if (string.IsNullOrEmpty(vf)) + { + vf = "-vf thumbnail=24"; + } + else + { + vf += ",thumbnail=24"; + } + } - var args = useIFrame ? string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {5} -v quiet -vframes 1 {2}{4} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail, threads) : - string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); var probeSizeArgument = EncodingHelper.GetProbeSizeArgument(1); var analyzeDurationArgument = EncodingHelper.GetAnalyzeDurationArgument(1); -- cgit v1.2.3 From 3e9cf98c30277e09f7b8a6c8ecb603e9ea10774a Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sun, 29 Nov 2020 13:22:42 +0800 Subject: add hdr tone mapping to image extraction --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 58 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 753da46a6..be63a18e4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -34,9 +34,14 @@ namespace MediaBrowser.MediaEncoding.Encoder public class MediaEncoder : IMediaEncoder, IDisposable { /// <summary> - /// The default image extraction timeout in milliseconds. + /// The default SDR image extraction timeout in milliseconds. /// </summary> - internal const int DefaultImageExtractionTimeout = 10000; + internal const int DefaultSdrImageExtractionTimeout = 10000; + + /// <summary> + /// The default HDR image extraction timeout in milliseconds. + /// </summary> + internal const int DefaultHdrImageExtractionTimeout = 20000; /// <summary> /// The us culture. @@ -495,9 +500,36 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { + // The failure of HDR extraction usually occurs when using custom ffmpeg that does not contain the zscale filter. + try + { + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, true, cancellationToken).ConfigureAwait(false); + } + catch (ArgumentException) + { + throw; + } + catch (Exception ex) + { + _logger.LogError(ex, "I-frame or HDR image extraction failed, will attempt with I-frame extraction disabled. Input: {Arguments}", inputArgument); + } + + try + { + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, true, cancellationToken).ConfigureAwait(false); + } + catch (ArgumentException) + { + throw; + } + catch (Exception ex) + { + _logger.LogError(ex, "HDR image extraction failed, will fallback to SDR image extraction. Input: {Arguments}", inputArgument); + } + try { - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, false, cancellationToken).ConfigureAwait(false); } catch (ArgumentException) { @@ -509,10 +541,10 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, false, cancellationToken).ConfigureAwait(false); } - private async Task<string> ExtractImageInternal(string inputPath, string container, MediaStream videoStream, int? imageStreamIndex, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, CancellationToken cancellationToken) + private async Task<string> ExtractImageInternal(string inputPath, string container, MediaStream videoStream, int? imageStreamIndex, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, bool allowTonemap, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { @@ -553,6 +585,20 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; + var enableHdrExtraction = allowTonemap && videoStream != null && !string.IsNullOrEmpty(videoStream.VideoRange) && string.Equals(videoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); + if (enableHdrExtraction) + { + string tonemapFilters = "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709,format=yuv420p"; + if (string.IsNullOrEmpty(vf)) + { + vf = "-vf " + tonemapFilters; + } + else + { + vf += "," + tonemapFilters; + } + } + // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); if (enableThumbnail) @@ -635,7 +681,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var timeoutMs = _configurationManager.Configuration.ImageExtractionTimeoutMs; if (timeoutMs <= 0) { - timeoutMs = DefaultImageExtractionTimeout; + timeoutMs = enableHdrExtraction ? DefaultHdrImageExtractionTimeout : DefaultSdrImageExtractionTimeout; } ranToCompletion = await process.WaitForExitAsync(TimeSpan.FromMilliseconds(timeoutMs)).ConfigureAwait(false); -- cgit v1.2.3 From 92118c2129ec8175665e65dcd78c1400fbe60c80 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sun, 29 Nov 2020 22:46:26 +0800 Subject: allow to extract music bitrate info from formatInfo --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 97d61441c..27bd693e3 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -778,7 +778,11 @@ namespace MediaBrowser.MediaEncoding.Probing } } - if (bitrate == 0 && formatInfo != null && !string.IsNullOrEmpty(formatInfo.BitRate) && stream.Type == MediaStreamType.Video) + // The bitrate info of FLAC musics and some videos is included in formatInfo. + if (bitrate == 0 + && formatInfo != null + && !string.IsNullOrEmpty(formatInfo.BitRate) + && (stream.Type == MediaStreamType.Video || stream.Type == MediaStreamType.Audio)) { // If the stream info doesn't have a bitrate get the value from the media format info if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) -- cgit v1.2.3 From 6536c81226d5348f587119aa46635b32cc7a807e Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Tue, 1 Dec 2020 10:53:56 +0800 Subject: do not extract audio stream bitrate info for videos from formatInfo --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 27bd693e3..bd026bce1 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -782,7 +782,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (bitrate == 0 && formatInfo != null && !string.IsNullOrEmpty(formatInfo.BitRate) - && (stream.Type == MediaStreamType.Video || stream.Type == MediaStreamType.Audio)) + && (stream.Type == MediaStreamType.Video || (isAudio && stream.Type == MediaStreamType.Audio))) { // If the stream info doesn't have a bitrate get the value from the media format info if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) -- cgit v1.2.3 From 7b5285feacb278ce1d23b08c6a55b7df78126d40 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Wed, 2 Dec 2020 08:22:07 +0800 Subject: Apply suggestions from code review Co-authored-by: BaronGreenback <jimcartlidge@yahoo.co.uk> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index be63a18e4..bfc09cc97 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -585,7 +585,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; - var enableHdrExtraction = allowTonemap && videoStream != null && !string.IsNullOrEmpty(videoStream.VideoRange) && string.Equals(videoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); + var enableHdrExtraction = allowTonemap && string.Equals(videoStream?.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); if (enableHdrExtraction) { string tonemapFilters = "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709,format=yuv420p"; -- cgit v1.2.3 From e4fd61411f102abdd4aa5b6df67c9b18c103cb28 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Wed, 2 Dec 2020 15:38:52 +0100 Subject: Minor improvements --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 1 - .../ServiceActionListBuilder.cs | 1 - Emby.Dlna/PlayTo/Device.cs | 6 +-- Emby.Dlna/PlayTo/PlayToController.cs | 47 +++++++++------------- Emby.Dlna/PlayTo/PlayToManager.cs | 7 ++-- Emby.Dlna/PlayTo/PlaylistItemFactory.cs | 4 +- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 3 +- Emby.Dlna/PlayTo/TransportCommands.cs | 16 ++++---- Emby.Server.Implementations/ApplicationHost.cs | 10 +---- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 +- .../LiveTv/TunerHosts/M3uParser.cs | 2 +- Jellyfin.Networking/Manager/NetworkManager.cs | 3 +- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 16 ++++---- MediaBrowser.Model/Dlna/ContainerProfile.cs | 2 +- .../MediaInfo/FFProbeProvider.cs | 2 +- 15 files changed, 48 insertions(+), 75 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index b93651746..27f1fdaba 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -1681,7 +1681,6 @@ namespace Emby.Dlna.ContentDirectory private ServerItem GetItemFromObjectId(string id) { return DidlBuilder.IsIdRoot(id) - ? new ServerItem(_libraryManager.GetUserRootFolder()) : ParseItemId(id); } diff --git a/Emby.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs b/Emby.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs index 1dc9c79c1..56788ae22 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/ServiceActionListBuilder.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Emby.Dlna.Common; -using MediaBrowser.Model.Dlna; namespace Emby.Dlna.MediaReceiverRegistrar { diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index f8ff03076..938ce5fbf 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -12,8 +12,6 @@ using System.Xml; using System.Xml.Linq; using Emby.Dlna.Common; using Emby.Dlna.Ssdp; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; using Microsoft.Extensions.Logging; namespace Emby.Dlna.PlayTo @@ -345,7 +343,7 @@ namespace Emby.Dlna.PlayTo RestartTimer(true); } - private string CreateDidlMeta(string value) + private static string CreateDidlMeta(string value) { if (string.IsNullOrEmpty(value)) { @@ -962,7 +960,7 @@ namespace Emby.Dlna.PlayTo url = "/dmr/" + url; } - if (!url.StartsWith("/", StringComparison.Ordinal)) + if (!url.StartsWith('/')) { url = "/" + url; } diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 3907b2a39..b7cd91a5c 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Emby.Dlna.Didl; using Jellyfin.Data.Entities; using Jellyfin.Data.Events; -using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; @@ -41,7 +40,6 @@ namespace Emby.Dlna.PlayTo private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IConfigurationManager _config; private readonly IMediaEncoder _mediaEncoder; private readonly IDeviceDiscovery _deviceDiscovery; @@ -68,7 +66,6 @@ namespace Emby.Dlna.PlayTo IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, - IConfigurationManager config, IMediaEncoder mediaEncoder) { _session = session; @@ -84,7 +81,6 @@ namespace Emby.Dlna.PlayTo _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; - _config = config; _mediaEncoder = mediaEncoder; } @@ -337,25 +333,17 @@ namespace Emby.Dlna.PlayTo } var startIndex = command.StartIndex ?? 0; + int len = items.Count - startIndex; if (startIndex > 0) { - items = items.GetRange(startIndex, items.Count - startIndex); + items = items.GetRange(startIndex, len); } - var playlist = new List<PlaylistItem>(); - var isFirst = true; - - foreach (var item in items) + var playlist = new PlaylistItem[len]; + playlist[0] = CreatePlaylistItem(items[0], user, command.StartPositionTicks.Value, command.MediaSourceId, command.AudioStreamIndex, command.SubtitleStreamIndex); + for (int i = 1; i < len; i++) { - if (isFirst && command.StartPositionTicks.HasValue) - { - playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value, command.MediaSourceId, command.AudioStreamIndex, command.SubtitleStreamIndex)); - isFirst = false; - } - else - { - playlist.Add(CreatePlaylistItem(item, user, 0, null, null, null)); - } + playlist[i] = CreatePlaylistItem(items[i], user, 0, null, null, null); } _logger.LogDebug("{0} - Playlist created", _session.DeviceName); @@ -468,8 +456,8 @@ namespace Emby.Dlna.PlayTo _dlnaManager.GetDefaultProfile(); var mediaSources = item is IHasMediaSources - ? _mediaSourceManager.GetStaticMediaSources(item, true, user) - : new List<MediaSourceInfo>(); + ? _mediaSourceManager.GetStaticMediaSources(item, true, user).ToArray() + : Array.Empty<MediaSourceInfo>(); var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex); playlistItem.StreamInfo.StartPositionTicks = startPostionTicks; @@ -548,7 +536,7 @@ namespace Emby.Dlna.PlayTo return null; } - private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaSourceInfo> mediaSources, DeviceProfile profile, string deviceId, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) + private PlaylistItem GetPlaylistItem(BaseItem item, MediaSourceInfo[] mediaSources, DeviceProfile profile, string deviceId, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) { if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) { @@ -557,7 +545,7 @@ namespace Emby.Dlna.PlayTo StreamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildVideoItem(new VideoOptions { ItemId = item.Id, - MediaSources = mediaSources.ToArray(), + MediaSources = mediaSources, Profile = profile, DeviceId = deviceId, MaxBitrate = profile.MaxStreamingBitrate, @@ -577,7 +565,7 @@ namespace Emby.Dlna.PlayTo StreamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildAudioItem(new AudioOptions { ItemId = item.Id, - MediaSources = mediaSources.ToArray(), + MediaSources = mediaSources, Profile = profile, DeviceId = deviceId, MaxBitrate = profile.MaxStreamingBitrate, @@ -590,7 +578,7 @@ namespace Emby.Dlna.PlayTo if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase)) { - return new PlaylistItemFactory().Create((Photo)item, profile); + return PlaylistItemFactory.Create((Photo)item, profile); } throw new ArgumentException("Unrecognized item type."); @@ -774,13 +762,14 @@ namespace Emby.Dlna.PlayTo private async Task SeekAfterTransportChange(long positionTicks, CancellationToken cancellationToken) { - const int maxWait = 15000000; - const int interval = 500; + const int MaxWait = 15000000; + const int Interval = 500; + var currentWait = 0; - while (_device.TransportState != TransportState.Playing && currentWait < maxWait) + while (_device.TransportState != TransportState.Playing && currentWait < MaxWait) { - await Task.Delay(interval).ConfigureAwait(false); - currentWait += interval; + await Task.Delay(Interval).ConfigureAwait(false); + currentWait += Interval; } await _device.Seek(TimeSpan.FromTicks(positionTicks), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index cb183ce71..f34332d62 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -90,10 +90,10 @@ namespace Emby.Dlna.PlayTo string location = info.Location.ToString(); // It has to report that it's a media renderer - if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1) + if (!usn.Contains("MediaRenderer:", StringComparison.OrdinalIgnoreCase) + && !nt.Contains("MediaRenderer:", StringComparison.OrdinalIgnoreCase)) { - // _logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location); + _logger.LogDebug("Upnp device {0} does not contain a MediaRenderer device (0).", location); return; } @@ -203,7 +203,6 @@ namespace Emby.Dlna.PlayTo _userDataManager, _localization, _mediaSourceManager, - _config, _mediaEncoder); sessionInfo.AddController(controller); diff --git a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs index bedc8b9ad..e28840a89 100644 --- a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs +++ b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs @@ -8,9 +8,9 @@ using MediaBrowser.Model.Session; namespace Emby.Dlna.PlayTo { - public class PlaylistItemFactory + public static class PlaylistItemFactory { - public PlaylistItem Create(Photo item, DeviceProfile profile) + public static PlaylistItem Create(Photo item, DeviceProfile profile) { var playlistItem = new PlaylistItem { diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index f4d793790..557bc69a7 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -4,7 +4,6 @@ using System; using System.Globalization; using System.IO; using System.Net.Http; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading; @@ -60,7 +59,7 @@ namespace Emby.Dlna.PlayTo return serviceUrl; } - if (!serviceUrl.StartsWith("/", StringComparison.Ordinal)) + if (!serviceUrl.StartsWith('/')) { serviceUrl = "/" + serviceUrl; } diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index fda17a8b4..0865968ad 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -78,7 +78,7 @@ namespace Emby.Dlna.PlayTo private static StateVariable FromXml(XElement container) { - var allowedValues = new List<string>(); + var allowedValues = Array.Empty<string>(); var element = container.Descendants(UPnpNamespaces.Svc + "allowedValueList") .FirstOrDefault(); @@ -86,14 +86,14 @@ namespace Emby.Dlna.PlayTo { var values = element.Descendants(UPnpNamespaces.Svc + "allowedValue"); - allowedValues.AddRange(values.Select(child => child.Value)); + allowedValues = values.Select(child => child.Value).ToArray(); } return new StateVariable { Name = container.GetValue(UPnpNamespaces.Svc + "name"), DataType = container.GetValue(UPnpNamespaces.Svc + "dataType"), - AllowedValues = allowedValues.ToArray() + AllowedValues = allowedValues }; } @@ -103,12 +103,12 @@ namespace Emby.Dlna.PlayTo foreach (var arg in action.ArgumentList) { - if (arg.Direction == "out") + if (string.Equals(arg.Direction, "out", StringComparison.Ordinal)) { continue; } - if (arg.Name == "InstanceID") + if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal)) { stateString += BuildArgumentXml(arg, "0"); } @@ -127,12 +127,12 @@ namespace Emby.Dlna.PlayTo foreach (var arg in action.ArgumentList) { - if (arg.Direction == "out") + if (string.Equals(arg.Direction, "out", StringComparison.Ordinal)) { continue; } - if (arg.Name == "InstanceID") + if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal)) { stateString += BuildArgumentXml(arg, "0"); } @@ -151,7 +151,7 @@ namespace Emby.Dlna.PlayTo foreach (var arg in action.ArgumentList) { - if (arg.Name == "InstanceID") + if (string.Equals(arg.Name, "InstanceID", StringComparison.Ordinal)) { stateString += BuildArgumentXml(arg, "0"); } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 30ccaf8de..5498f5a10 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1,21 +1,18 @@ #pragma warning disable CS1591 using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Sockets; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml.Serialization; using Emby.Dlna; using Emby.Dlna.Main; using Emby.Dlna.Ssdp; @@ -52,7 +49,6 @@ using Jellyfin.Networking.Manager; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -85,7 +81,6 @@ using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.TV; using MediaBrowser.LocalMetadata.Savers; using MediaBrowser.MediaEncoding.BdInfo; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Globalization; @@ -100,7 +95,6 @@ using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Plugins.Tmdb; using MediaBrowser.Providers.Subtitles; using MediaBrowser.XbmcMetadata.Providers; -using Microsoft.AspNetCore.DataProtection.Repositories; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; @@ -128,7 +122,6 @@ namespace Emby.Server.Implementations private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; - private IHttpClientFactory _httpClientFactory; private string[] _urlPrefixes; /// <summary> @@ -661,7 +654,6 @@ namespace Emby.Server.Implementations _mediaEncoder = Resolve<IMediaEncoder>(); _sessionManager = Resolve<ISessionManager>(); - _httpClientFactory = Resolve<IHttpClientFactory>(); ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize(); @@ -1049,7 +1041,7 @@ namespace Emby.Server.Implementations metafile = dir.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)[^1]; int versionIndex = dir.LastIndexOf('_'); - if (versionIndex != -1 && Version.TryParse(dir.Substring(versionIndex + 1), out Version parsedVersion)) + if (versionIndex != -1 && Version.TryParse(dir.AsSpan()[(versionIndex + 1)..], out Version parsedVersion)) { // Versioned folder. versions.Add(new LocalPlugin(Guid.Empty, metafile, parsedVersion, dir)); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c0a4d1228..b6444b172 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -237,8 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (!inside) { - buffer[bufferIndex] = let; - bufferIndex++; + buffer[bufferIndex++] = let; } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 1d6c26c13..c82b67b41 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts extInf = line.Substring(ExtInfPrefix.Length).Trim(); _logger.LogInformation("Found m3u channel: {0}", extInf); } - else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase)) + else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith('#')) { var channel = GetChannelnfo(extInf, tunerHostId, line); if (string.IsNullOrWhiteSpace(channel.Id)) diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 1a5614b7b..85da927fb 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -256,7 +256,7 @@ namespace Jellyfin.Networking.Manager } catch (ArgumentException e) { - _logger.LogWarning(e, "Ignoring LAN value {value}.", v); + _logger.LogWarning(e, "Ignoring LAN value {Value}.", v); } } @@ -668,7 +668,6 @@ namespace Jellyfin.Networking.Manager if (address.AddressFamily == AddressFamily.InterNetworkV6) { int i = str.IndexOf("%", StringComparison.OrdinalIgnoreCase); - if (i != -1) { str = str.Substring(0, i); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index a5d641747..db6b47583 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -51,7 +51,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { eventsStarted = true; } - else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";", StringComparison.Ordinal)) + else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(';')) { // skip comment lines } @@ -151,13 +151,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - var p = new SubtitleTrackEvent(); - - p.StartPositionTicks = GetTimeCodeFromString(start); - p.EndPositionTicks = GetTimeCodeFromString(end); - p.Text = GetFormattedText(text); - - trackEvents.Add(p); + trackEvents.Add( + new SubtitleTrackEvent + { + StartPositionTicks = GetTimeCodeFromString(start), + EndPositionTicks = GetTimeCodeFromString(end), + Text = GetFormattedText(text) + }); } catch { diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 09afa64bb..56c89d854 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Model.Dlna public static bool ContainsContainer(string profileContainers, string inputContainer) { var isNegativeList = false; - if (profileContainers != null && profileContainers.StartsWith("-", StringComparison.Ordinal)) + if (profileContainers != null && profileContainers.StartsWith('-')) { isNegativeList = true; profileContainers = profileContainers.Substring(1); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 648329757..4fff57273 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.MediaInfo { item.ShortcutPath = File.ReadAllLines(item.Path) .Select(NormalizeStrmLine) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith("#", StringComparison.OrdinalIgnoreCase)); + .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith('#')); } public Task<ItemUpdateType> FetchAudioInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) -- cgit v1.2.3 From ca5c20c9889f2c279f0b9d80ce776ddc8ee31ad1 Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Thu, 3 Dec 2020 07:34:15 -0700 Subject: Remove IIsoMounter and IsoMounter --- Emby.Server.Implementations/ApplicationHost.cs | 4 -- Emby.Server.Implementations/IO/IsoManager.cs | 67 ---------------------- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 5 -- .../MediaEncoding/IMediaEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +- MediaBrowser.Model/IO/IIsoManager.cs | 35 ----------- MediaBrowser.Model/IO/IIsoMount.cs | 22 ------- MediaBrowser.Model/IO/IIsoMounter.cs | 35 ----------- .../MediaInfo/FFProbeVideoInfo.cs | 2 +- 9 files changed, 4 insertions(+), 174 deletions(-) delete mode 100644 Emby.Server.Implementations/IO/IsoManager.cs delete mode 100644 MediaBrowser.Model/IO/IIsoManager.cs delete mode 100644 MediaBrowser.Model/IO/IIsoMount.cs delete mode 100644 MediaBrowser.Model/IO/IIsoMounter.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 30ccaf8de..29c93faa6 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -538,8 +538,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(NetManager); - ServiceCollection.AddSingleton<IIsoManager, IsoManager>(); - ServiceCollection.AddSingleton<ITaskManager, TaskManager>(); ServiceCollection.AddSingleton(_xmlSerializer); @@ -820,8 +818,6 @@ namespace Emby.Server.Implementations Resolve<IMediaSourceManager>().AddParts(GetExports<IMediaSourceProvider>()); Resolve<INotificationManager>().AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>()); - - Resolve<IIsoManager>().AddParts(GetExports<IIsoMounter>()); } /// <summary> diff --git a/Emby.Server.Implementations/IO/IsoManager.cs b/Emby.Server.Implementations/IO/IsoManager.cs deleted file mode 100644 index 94e92c2a6..000000000 --- a/Emby.Server.Implementations/IO/IsoManager.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; - -namespace Emby.Server.Implementations.IO -{ - /// <summary> - /// Class IsoManager. - /// </summary> - public class IsoManager : IIsoManager - { - /// <summary> - /// The _mounters. - /// </summary> - private readonly List<IIsoMounter> _mounters = new List<IIsoMounter>(); - - /// <summary> - /// Mounts the specified iso path. - /// </summary> - /// <param name="isoPath">The iso path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns><see creaf="IsoMount" />.</returns> - public Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken) - { - if (string.IsNullOrEmpty(isoPath)) - { - throw new ArgumentNullException(nameof(isoPath)); - } - - var mounter = _mounters.FirstOrDefault(i => i.CanMount(isoPath)); - - if (mounter == null) - { - throw new ArgumentException( - string.Format( - CultureInfo.InvariantCulture, - "No mounters are able to mount {0}", - isoPath)); - } - - return mounter.Mount(isoPath, cancellationToken); - } - - /// <summary> - /// Determines whether this instance can mount the specified path. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if this instance can mount the specified path; otherwise, <c>false</c>.</returns> - public bool CanMount(string path) - { - return _mounters.Any(i => i.CanMount(path)); - } - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="mounters">The mounters.</param> - public void AddParts(IEnumerable<IIsoMounter> mounters) - { - _mounters.AddRange(mounters); - } - } -} diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index bb2265dba..240d132b1 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -12,7 +12,6 @@ using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; @@ -46,7 +45,6 @@ namespace Jellyfin.Api.Helpers private readonly IAuthorizationContext _authorizationContext; private readonly EncodingHelper _encodingHelper; private readonly IFileSystem _fileSystem; - private readonly IIsoManager _isoManager; private readonly ILogger<TranscodingJobHelper> _logger; private readonly IMediaEncoder _mediaEncoder; private readonly IMediaSourceManager _mediaSourceManager; @@ -64,7 +62,6 @@ namespace Jellyfin.Api.Helpers /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> - /// <param name="isoManager">Instance of the <see cref="IIsoManager"/> interface.</param> /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> @@ -76,7 +73,6 @@ namespace Jellyfin.Api.Helpers IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, - IIsoManager isoManager, ISubtitleEncoder subtitleEncoder, IConfiguration configuration, ILoggerFactory loggerFactory) @@ -88,7 +84,6 @@ namespace Jellyfin.Api.Helpers _serverConfigurationManager = serverConfigurationManager; _sessionManager = sessionManager; _authorizationContext = authorizationContext; - _isoManager = isoManager; _loggerFactory = loggerFactory; _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index e7f042d2f..34fe895cc 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -117,6 +117,6 @@ namespace MediaBrowser.Controller.MediaEncoding void UpdateEncoderPath(string path, string pathType); - IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber); + IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 380894278..b1da9c712 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -949,16 +949,14 @@ namespace MediaBrowser.MediaEncoding.Encoder } /// <inheritdoc /> - public IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber) + public IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, uint? titleNumber) { // min size 300 mb const long MinPlayableSize = 314572800; - var root = isoMount != null ? isoMount.MountedPath : path; - // Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size // Once we reach a file that is at least the minimum, return all subsequent ones - var allVobs = _fileSystem.GetFiles(root, true) + var allVobs = _fileSystem.GetFiles(path, true) .Where(file => string.Equals(file.Extension, ".vob", StringComparison.OrdinalIgnoreCase)) .OrderBy(i => i.FullName) .ToList(); diff --git a/MediaBrowser.Model/IO/IIsoManager.cs b/MediaBrowser.Model/IO/IIsoManager.cs deleted file mode 100644 index 299bb0a21..000000000 --- a/MediaBrowser.Model/IO/IIsoManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Model.IO -{ - public interface IIsoManager - { - /// <summary> - /// Mounts the specified iso path. - /// </summary> - /// <param name="isoPath">The iso path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>IsoMount.</returns> - /// <exception cref="IOException">Unable to create mount.</exception> - Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken); - - /// <summary> - /// Determines whether this instance can mount the specified path. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if this instance can mount the specified path; otherwise, <c>false</c>.</returns> - bool CanMount(string path); - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="mounters">The mounters.</param> - void AddParts(IEnumerable<IIsoMounter> mounters); - } -} diff --git a/MediaBrowser.Model/IO/IIsoMount.cs b/MediaBrowser.Model/IO/IIsoMount.cs deleted file mode 100644 index ea65d976a..000000000 --- a/MediaBrowser.Model/IO/IIsoMount.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace MediaBrowser.Model.IO -{ - /// <summary> - /// Interface IIsoMount. - /// </summary> - public interface IIsoMount : IDisposable - { - /// <summary> - /// Gets the iso path. - /// </summary> - /// <value>The iso path.</value> - string IsoPath { get; } - - /// <summary> - /// Gets the mounted path. - /// </summary> - /// <value>The mounted path.</value> - string MountedPath { get; } - } -} diff --git a/MediaBrowser.Model/IO/IIsoMounter.cs b/MediaBrowser.Model/IO/IIsoMounter.cs deleted file mode 100644 index 0d257395a..000000000 --- a/MediaBrowser.Model/IO/IIsoMounter.cs +++ /dev/null @@ -1,35 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Model.IO -{ - public interface IIsoMounter - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - string Name { get; } - - /// <summary> - /// Mounts the specified iso path. - /// </summary> - /// <param name="isoPath">The iso path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>IsoMount.</returns> - /// <exception cref="ArgumentNullException">isoPath</exception> - /// <exception cref="IOException">Unable to create mount.</exception> - Task<IIsoMount> Mount(string isoPath, CancellationToken cancellationToken); - - /// <summary> - /// Determines whether this instance can mount the specified path. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if this instance can mount the specified path; otherwise, <c>false</c>.</returns> - bool CanMount(string path); - } -} diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 6d39c091e..74849a522 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -619,7 +619,7 @@ namespace MediaBrowser.Providers.MediaInfo item.RunTimeTicks = GetRuntime(primaryTitle); } - return _mediaEncoder.GetPrimaryPlaylistVobFiles(item.Path, null, titleNumber) + return _mediaEncoder.GetPrimaryPlaylistVobFiles(item.Path, titleNumber) .Select(Path.GetFileName) .ToArray(); } -- cgit v1.2.3 From ebd9ab3ccc2a152b2f950d8948f018fadf5e8916 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Wed, 9 Dec 2020 14:39:11 +0800 Subject: use larger batch size on mpegts to avoid corrupted thumbnails --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index b1da9c712..4c804371e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -603,16 +603,19 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. + // mpegts need larger batch size otherwise the corrupted thumbnail will be created. Larger batch size will lower the processing speed. var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); + var useLargerBatchSize = string.Equals("mpegts", container, StringComparison.OrdinalIgnoreCase); if (enableThumbnail) { + var batchSize = useLargerBatchSize ? "50" : "24"; if (string.IsNullOrEmpty(vf)) { - vf = "-vf thumbnail=24"; + vf = "-vf thumbnail=" + batchSize; } else { - vf += ",thumbnail=24"; + vf += ",thumbnail=" + batchSize; } } -- cgit v1.2.3 From 060f6c194f186eccd4eede7426a65e3496fdcf45 Mon Sep 17 00:00:00 2001 From: Nyanmisaka <nst799610810@gmail.com> Date: Wed, 9 Dec 2020 16:37:15 +0800 Subject: Apply suggestions from code review Co-authored-by: Claus Vium <cvium@users.noreply.github.com> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4c804371e..fbd08a97c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -605,9 +605,9 @@ namespace MediaBrowser.MediaEncoding.Encoder // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. // mpegts need larger batch size otherwise the corrupted thumbnail will be created. Larger batch size will lower the processing speed. var enableThumbnail = useIFrame && !string.Equals("wtv", container, StringComparison.OrdinalIgnoreCase); - var useLargerBatchSize = string.Equals("mpegts", container, StringComparison.OrdinalIgnoreCase); if (enableThumbnail) { + var useLargerBatchSize = string.Equals("mpegts", container, StringComparison.OrdinalIgnoreCase); var batchSize = useLargerBatchSize ? "50" : "24"; if (string.IsNullOrEmpty(vf)) { -- cgit v1.2.3 From 1dac2226c4d12c5ccb9bed83c8b6cceab8dbff09 Mon Sep 17 00:00:00 2001 From: crobibero <cody@robibe.ro> Date: Tue, 22 Dec 2020 08:57:51 -0700 Subject: Remove unused deps --- Emby.Dlna/Emby.Dlna.csproj | 4 +--- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 8 -------- Jellyfin.Api/Jellyfin.Api.csproj | 2 -- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 - MediaBrowser.Providers/MediaBrowser.Providers.csproj | 1 - 7 files changed, 3 insertions(+), 17 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index bd30cc1e1..8b057a095 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -78,9 +78,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" /> - <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> </ItemGroup> </Project> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 9e9452f32..7c9a5fbe1 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -23,14 +23,6 @@ <ItemGroup> <PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" /> - <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" /> - <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" /> - <PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> - <PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index b4f2817f7..f01f50cea 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -15,9 +15,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.1" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.6.3" /> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index be5e7f5b4..320e60dc6 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -14,6 +14,7 @@ </PropertyGroup> <ItemGroup> + <FrameworkReference Include="Microsoft.AspNetCore.App"/> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> </ItemGroup> @@ -21,7 +22,6 @@ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 7bb2a7d03..f8af499e4 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,7 +24,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="UTF.Unknown" Version="2.3.0" /> </ItemGroup> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b86187f9b..334fe8209 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -33,7 +33,6 @@ <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" /> <PackageReference Include="System.Globalization" Version="4.3.0" /> <PackageReference Include="System.Text.Json" Version="5.0.0" /> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index accdea36e..fc8eb8c4e 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -22,7 +22,6 @@ <PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" /> <PackageReference Include="PlaylistsNET" Version="1.1.3" /> <PackageReference Include="TMDbLib" Version="1.7.3-alpha" /> - <PackageReference Include="TvDbSharper" Version="3.2.2" /> </ItemGroup> <PropertyGroup> -- cgit v1.2.3 From d0382db37df977d284a440f408ae78798e9fba02 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Mon, 28 Dec 2020 15:33:15 +0100 Subject: Minor improvements to ass parser --- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 86b87fddd..e0b7914fb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles using (var reader = new StreamReader(stream)) { string line; - while (reader.ReadLine() != "[Events]") + while (!string.Equals(reader.ReadLine(), "[Events]", StringComparison.Ordinal)) { } @@ -46,12 +46,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) }; eventIndex++; - var sections = line.Substring(10).Split(','); + const string Dialogue = "Dialogue: "; + var sections = line.Substring(Dialogue.Length).Split(','); subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]); subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]); - subEvent.Text = string.Join(",", sections.Skip(headers["Text"])); + subEvent.Text = string.Join(',', sections[headers["Text"]..]); RemoteNativeFormatting(subEvent); subEvent.Text = subEvent.Text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); @@ -62,7 +63,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - trackInfo.TrackEvents = trackEvents.ToArray(); + trackInfo.TrackEvents = trackEvents; return trackInfo; } @@ -72,9 +73,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles ? span.Ticks : 0; } - private Dictionary<string, int> ParseFieldHeaders(string line) + internal static Dictionary<string, int> ParseFieldHeaders(string line) { - var fields = line.Substring(8).Split(',').Select(x => x.Trim()).ToList(); + const string Format = "Format: "; + var fields = line.Substring(Format.Length).Split(',').Select(x => x.Trim()).ToList(); return new Dictionary<string, int> { -- cgit v1.2.3 From 5ac36a8b5859d5416005ab411774aa9464a533d2 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Mon, 28 Dec 2020 15:43:55 +0100 Subject: Add tests for srt parser --- MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 4 +-- .../Subtitles/SrtParserTests.cs | 35 ++++++++++++++++++++++ .../Test Data/example.srt | 8 +++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index cc35efb3f..4a87f87dc 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var multiline = new List<string>(); while ((line = reader.ReadLine()) != null) { - if (string.IsNullOrEmpty(line)) + if (line.Length == 0) { break; } @@ -87,7 +87,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - trackInfo.TrackEvents = trackEvents.ToArray(); + trackInfo.TrackEvents = trackEvents; return trackInfo; } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs new file mode 100644 index 000000000..3e2d2de10 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Jellyfin.MediaEncoding.Subtitles.Tests +{ + public class SrtParserTests + { + [Fact] + public void Parse_Valid_Success() + { + using (var stream = File.OpenRead("Test Data/example.srt")) + { + var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None); + Assert.Equal(2, parsed.TrackEvents.Count); + + var trackEvent1 = parsed.TrackEvents[0]; + Assert.Equal("1", trackEvent1.Id); + Assert.Equal(TimeSpan.Parse("00:02:17.440", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:20.375", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); + Assert.Equal("Senator, we're making\r\nour final approach into Coruscant.", trackEvent1.Text); + + var trackEvent2 = parsed.TrackEvents[1]; + Assert.Equal("2", trackEvent2.Id); + Assert.Equal(TimeSpan.Parse("00:02:20.476", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:22.501", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); + Assert.Equal("Very good, Lieutenant.", trackEvent2.Text); + } + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt new file mode 100644 index 000000000..78d74014e --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt @@ -0,0 +1,8 @@ +1 +00:02:17,440 --> 00:02:20,375 +Senator, we're making +our final approach into Coruscant. + +2 +00:02:20,476 --> 00:02:22,501 +Very good, Lieutenant. -- cgit v1.2.3 From 0282a1ed09e40464d944977411cf3ae302aa32a4 Mon Sep 17 00:00:00 2001 From: obradovichv <53901450+obradovichv@users.noreply.github.com> Date: Sun, 3 Jan 2021 20:13:21 +0200 Subject: Fix string culture specificity Fix bug in SsaParser.cs primary color {\1c} formatting that would leave behind the {\1c} closing token and instead append </font> token unconditionally to the dialogue text. Add tests. Change AlphanumComparatorTests.cs complementary test data generation from an array shuffle to an array reversal. Although it was previously using a seeded Random, the shuffle itself could result in no rearrangement of elements if the seed or test data changed over time. The reversal guarantees reordering of elements and has the added benefit of simplifying the test code since no special handling is needed for arrays of 2 elements. Change DailyTrigger.cs logging of TriggerDate format to "yyyy-MM-dd HH:mm:ss.fff zzz" for consistency with configured log timestamp format and change DueTime format to culture-invariant "c" format. --- .../ScheduledTasks/Triggers/DailyTrigger.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 10 ++- .../AlphanumComparatorTests.cs | 16 +--- .../Jellyfin.MediaEncoding.Tests/SsaParserTests.cs | 96 ++++++++++++++++++++++ 4 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index 8b67d37d7..3b40320ab 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.ScheduledTasks var dueTime = triggerDate - now; - logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:g}, which is {DueTime:g} from now.", taskName, triggerDate, dueTime); + logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:yyyy-MM-dd HH:mm:ss.fff zzz}, which is {DueTime:c} from now.", taskName, triggerDate, dueTime); Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1)); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index db6b47583..bc84c5074 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -325,7 +325,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); } - text += "</font>"; + int indexOfEndTag = text.IndexOf("{\\1c}", start, StringComparison.Ordinal); + if (indexOfEndTag > 0) + { + text = text.Remove(indexOfEndTag, "{\\1c}".Length).Insert(indexOfEndTag, "</font>"); + } + else + { + text += "</font>"; + } } } } diff --git a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs b/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs index 929bb92aa..0adf098c3 100644 --- a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs +++ b/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Sorting; using Xunit; @@ -8,8 +7,6 @@ namespace Jellyfin.Controller.Tests { public class AlphanumComparatorTests { - private readonly Random _rng = new Random(42); - // InlineData is pre-sorted [Theory] [InlineData(null, "", "1", "9", "10", "a", "z")] @@ -25,18 +22,7 @@ namespace Jellyfin.Controller.Tests [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")] public void AlphanumComparatorTest(params string?[] strings) { - var copy = (string?[])strings.Clone(); - if (strings.Length == 2) - { - var tmp = copy[0]; - copy[0] = copy[1]; - copy[1] = tmp; - } - else - { - copy.Shuffle(_rng); - } - + var copy = strings.Reverse().ToArray(); Array.Sort(copy, new AlphanumComparator()); Assert.True(strings.SequenceEqual(copy)); } diff --git a/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs new file mode 100644 index 000000000..d11cb242c --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using MediaBrowser.Model.MediaInfo; +using Xunit; + +namespace Jellyfin.MediaEncoding.Tests +{ + public class SsaParserTests + { + // commonly shared invariant value between tests, assumes default format order + private const string InvariantDialoguePrefix = "[Events]\nDialogue: ,0:00:00.00,0:00:00.01,,,,,,,"; + + private SsaParser parser = new SsaParser(); + + [Theory] + [InlineData("[EvEnTs]\nDialogue: ,0:00:00.00,0:00:00.01,,,,,,,text", "text")] // label casing insensitivity + [InlineData("[Events]\n,0:00:00.00,0:00:00.01,,,,,,,labelless dialogue", "labelless dialogue")] // no "Dialogue:" label, it is optional + [InlineData("[Events]\nFormat: Text, Start, End, Layer, Effect, Style\nDialogue: reordered text,0:00:00.00,0:00:00.01", "reordered text")] // reordered formats + [InlineData(InvariantDialoguePrefix + "Cased TEXT", "Cased TEXT")] // preserve text casing + [InlineData(InvariantDialoguePrefix + " text ", " text ")] // do not trim text + [InlineData(InvariantDialoguePrefix + "text, more text", "text, more text")] // append excess dialogue values (> 10) to text + [InlineData(InvariantDialoguePrefix + "start {\\fnFont Name}text{\\fn} end", "start <font face=\"Font Name\">text</font> end")] // font name + [InlineData(InvariantDialoguePrefix + "start {\\fs10}text{\\fs} end", "start <font size=\"10\">text</font> end")] // font size + [InlineData(InvariantDialoguePrefix + "start {\\c&H112233}text{\\c} end", "start <font color=\"#332211\">text</font> end")] // color + [InlineData(InvariantDialoguePrefix + "start {\\1c&H112233}text{\\1c} end", "start <font color=\"#332211\">text</font> end")] // primay color + [InlineData(InvariantDialoguePrefix + "start {\\fnFont Name}text1 {\\fs10}text2{\\fs}{\\fn} {\\1c&H112233}text3{\\1c} end", "start <font face=\"Font Name\">text1 <font size=\"10\">text2</font></font> <font color=\"#332211\">text3</font> end")] // nested formatting + public void Parse(string ssa, string expectedText) + { + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa))) + { + SubtitleTrackInfo subtitleTrackInfo = parser.Parse(stream, CancellationToken.None); + SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[0]; + Assert.Equal(expectedText, actual.Text); + } + } + + [Theory] + [MemberData(nameof(Parse_MultipleDialogues_TestData))] + public void Parse_MultipleDialogues(string ssa, IReadOnlyList<SubtitleTrackEvent> expectedSubtitleTrackEvents) + { + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa))) + { + SubtitleTrackInfo subtitleTrackInfo = parser.Parse(stream, CancellationToken.None); + + Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count); + + for (int i = 0; i < expectedSubtitleTrackEvents.Count; ++i) + { + SubtitleTrackEvent expected = expectedSubtitleTrackEvents[i]; + SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[i]; + + Assert.Equal(expected.StartPositionTicks, actual.StartPositionTicks); + Assert.Equal(expected.EndPositionTicks, actual.EndPositionTicks); + Assert.Equal(expected.Text, actual.Text); + } + } + } + + public static IEnumerable<object[]> Parse_MultipleDialogues_TestData() + { + yield return new object[] + { + @"[Events] + Format: Layer, Start, End, Text + Dialogue: ,0:00:01.18,0:00:01.85,dialogue1 + Dialogue: ,0:00:02.18,0:00:02.85,dialogue2 + Dialogue: ,0:00:03.18,0:00:03.85,dialogue3 + ", + new List<SubtitleTrackEvent> + { + new SubtitleTrackEvent + { + StartPositionTicks = 11800000, + EndPositionTicks = 18500000, + Text = "dialogue1" + }, + new SubtitleTrackEvent + { + StartPositionTicks = 21800000, + EndPositionTicks = 28500000, + Text = "dialogue2" + }, + new SubtitleTrackEvent + { + StartPositionTicks = 31800000, + EndPositionTicks = 38500000, + Text = "dialogue3" + } + } + }; + } + } +} -- cgit v1.2.3 From df402df908e3c0aae6ac276dbcef6438a00d148c Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Thu, 21 Jan 2021 12:43:54 +0000 Subject: fix return --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fbd08a97c..92483ae9a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -209,6 +209,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _ffmpegPath = path; EncoderLocation = location; + return true; } else { -- cgit v1.2.3 From 8c640a1492ad3722778636222a6c29d0cce8cdc9 Mon Sep 17 00:00:00 2001 From: Troy <47042611+M0ssTee@users.noreply.github.com> Date: Mon, 1 Feb 2021 02:46:30 +0000 Subject: Replaced /d with [0-9], see issue #2923 --- Emby.Dlna/Profiles/SonyBravia2010Profile.cs | 4 ++-- Emby.Dlna/Profiles/SonyBravia2011Profile.cs | 4 ++-- Emby.Dlna/Profiles/SonyBravia2012Profile.cs | 4 ++-- Emby.Dlna/Profiles/SonyBravia2013Profile.cs | 4 ++-- Emby.Dlna/Profiles/SonyBravia2014Profile.cs | 4 ++-- Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml | 4 ++-- Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml | 4 ++-- Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml | 4 ++-- Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml | 4 ++-- Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml | 4 ++-- Emby.Naming/Common/NamingOptions.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Profiles/SonyBravia2010Profile.cs b/Emby.Dlna/Profiles/SonyBravia2010Profile.cs index 8ab4acd1b..9f0d82b8f 100644 --- a/Emby.Dlna/Profiles/SonyBravia2010Profile.cs +++ b/Emby.Dlna/Profiles/SonyBravia2010Profile.cs @@ -13,7 +13,7 @@ namespace Emby.Dlna.Profiles Identification = new DeviceIdentification { - FriendlyName = @"KDL-\d{2}[EHLNPB]X\d[01]\d.*", + FriendlyName = @"KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*", Manufacturer = "Sony", Headers = new[] @@ -21,7 +21,7 @@ namespace Emby.Dlna.Profiles new HttpHeaderInfo { Name = "X-AV-Client-Info", - Value = @".*KDL-\d{2}[EHLNPB]X\d[01]\d.*", + Value = @".*KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*", Match = HeaderMatchType.Regex } } diff --git a/Emby.Dlna/Profiles/SonyBravia2011Profile.cs b/Emby.Dlna/Profiles/SonyBravia2011Profile.cs index 42d253394..dfb91817a 100644 --- a/Emby.Dlna/Profiles/SonyBravia2011Profile.cs +++ b/Emby.Dlna/Profiles/SonyBravia2011Profile.cs @@ -13,7 +13,7 @@ namespace Emby.Dlna.Profiles Identification = new DeviceIdentification { - FriendlyName = @"KDL-\d{2}([A-Z]X\d2\d|CX400).*", + FriendlyName = @"KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*", Manufacturer = "Sony", Headers = new[] @@ -21,7 +21,7 @@ namespace Emby.Dlna.Profiles new HttpHeaderInfo { Name = "X-AV-Client-Info", - Value = @".*KDL-\d{2}([A-Z]X\d2\d|CX400).*", + Value = @".*KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*", Match = HeaderMatchType.Regex } } diff --git a/Emby.Dlna/Profiles/SonyBravia2012Profile.cs b/Emby.Dlna/Profiles/SonyBravia2012Profile.cs index 0598e8342..d59ee38d7 100644 --- a/Emby.Dlna/Profiles/SonyBravia2012Profile.cs +++ b/Emby.Dlna/Profiles/SonyBravia2012Profile.cs @@ -13,7 +13,7 @@ namespace Emby.Dlna.Profiles Identification = new DeviceIdentification { - FriendlyName = @"KDL-\d{2}[A-Z]X\d5(\d|G).*", + FriendlyName = @"KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*", Manufacturer = "Sony", Headers = new[] @@ -21,7 +21,7 @@ namespace Emby.Dlna.Profiles new HttpHeaderInfo { Name = "X-AV-Client-Info", - Value = @".*KDL-\d{2}[A-Z]X\d5(\d|G).*", + Value = @".*KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*", Match = HeaderMatchType.Regex } } diff --git a/Emby.Dlna/Profiles/SonyBravia2013Profile.cs b/Emby.Dlna/Profiles/SonyBravia2013Profile.cs index 3d90a1e72..73b0fd67e 100644 --- a/Emby.Dlna/Profiles/SonyBravia2013Profile.cs +++ b/Emby.Dlna/Profiles/SonyBravia2013Profile.cs @@ -13,7 +13,7 @@ namespace Emby.Dlna.Profiles Identification = new DeviceIdentification { - FriendlyName = @"KDL-\d{2}[WR][5689]\d{2}A.*", + FriendlyName = @"KDL-[0-9]{2}[WR][5689][0-9]{2}A.*", Manufacturer = "Sony", Headers = new[] @@ -21,7 +21,7 @@ namespace Emby.Dlna.Profiles new HttpHeaderInfo { Name = "X-AV-Client-Info", - Value = @".*KDL-\d{2}[WR][5689]\d{2}A.*", + Value = @".*KDL-[0-9]{2}[WR][5689][0-9]{2}A.*", Match = HeaderMatchType.Regex } } diff --git a/Emby.Dlna/Profiles/SonyBravia2014Profile.cs b/Emby.Dlna/Profiles/SonyBravia2014Profile.cs index 9188f73ef..db8ee5750 100644 --- a/Emby.Dlna/Profiles/SonyBravia2014Profile.cs +++ b/Emby.Dlna/Profiles/SonyBravia2014Profile.cs @@ -13,7 +13,7 @@ namespace Emby.Dlna.Profiles Identification = new DeviceIdentification { - FriendlyName = @"(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*", + FriendlyName = @"(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*", Manufacturer = "Sony", Headers = new[] @@ -21,7 +21,7 @@ namespace Emby.Dlna.Profiles new HttpHeaderInfo { Name = "X-AV-Client-Info", - Value = @".*(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*", + Value = @".*(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*", Match = HeaderMatchType.Regex } } diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml index f20e9fcb6..1461db311 100644 --- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -3,10 +3,10 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Sony Bravia (2010)</Name> <Identification> - <FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName> + <FriendlyName>KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*</FriendlyName> <Manufacturer>Sony</Manufacturer> <Headers> - <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[EHLNPB]X\d[01]\d.*" match="Regex" /> + <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-[0-9]{2}[EHLNPB]X[0-9][01][0-9].*" match="Regex" /> </Headers> </Identification> <Manufacturer>Microsoft Corporation</Manufacturer> diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml index e516ff512..7c5f2b181 100644 --- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -3,10 +3,10 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Sony Bravia (2011)</Name> <Identification> - <FriendlyName>KDL-\d{2}([A-Z]X\d2\d|CX400).*</FriendlyName> + <FriendlyName>KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*</FriendlyName> <Manufacturer>Sony</Manufacturer> <Headers> - <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}([A-Z]X\d2\d|CX400).*" match="Regex" /> + <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-[0-9]{2}([A-Z]X[0-9]2[0-9]|CX400).*" match="Regex" /> </Headers> </Identification> <Manufacturer>Microsoft Corporation</Manufacturer> diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml index 88bd1c2f5..842a8fba3 100644 --- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml +++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml @@ -3,10 +3,10 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Sony Bravia (2012)</Name> <Identification> - <FriendlyName>KDL-\d{2}[A-Z]X\d5(\d|G).*</FriendlyName> + <FriendlyName>KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*</FriendlyName> <Manufacturer>Sony</Manufacturer> <Headers> - <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[A-Z]X\d5(\d|G).*" match="Regex" /> + <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-[0-9]{2}[A-Z]X[0-9]5([0-9]|G).*" match="Regex" /> </Headers> </Identification> <Manufacturer>Microsoft Corporation</Manufacturer> diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml index 3ca9893cd..f1135c3fe 100644 --- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml +++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml @@ -3,10 +3,10 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Sony Bravia (2013)</Name> <Identification> - <FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName> + <FriendlyName>KDL-[0-9]{2}[WR][5689][0-9]{2}A.*</FriendlyName> <Manufacturer>Sony</Manufacturer> <Headers> - <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-\d{2}[WR][5689]\d{2}A.*" match="Regex" /> + <HttpHeaderInfo name="X-AV-Client-Info" value=".*KDL-[0-9]{2}[WR][5689][0-9]{2}A.*" match="Regex" /> </Headers> </Identification> <Manufacturer>Microsoft Corporation</Manufacturer> diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml index 8804a75df..85c7868c6 100644 --- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml +++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml @@ -3,10 +3,10 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Name>Sony Bravia (2014)</Name> <Identification> - <FriendlyName>(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*</FriendlyName> + <FriendlyName>(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*</FriendlyName> <Manufacturer>Sony</Manufacturer> <Headers> - <HttpHeaderInfo name="X-AV-Client-Info" value=".*(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*" match="Regex" /> + <HttpHeaderInfo name="X-AV-Client-Info" value=".*(KDL-[0-9]{2}W[5-9][0-9]{2}B|KDL-[0-9]{2}R480|XBR-[0-9]{2}X[89][0-9]{2}B|KD-[0-9]{2}[SX][89][0-9]{3}B).*" match="Regex" /> </Headers> </Identification> <Manufacturer>Microsoft Corporation</Manufacturer> diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 035d1b228..365f1a926 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -587,7 +587,7 @@ namespace Emby.Naming.Common AudioBookNamesExpressions = new[] { // Detect year usually in brackets after name Batman (2020) - @"^(?<name>.+?)\s*\(\s*(?<year>\d{4})\s*\)\s*$", + @"^(?<name>.+?)\s*\(\s*(?<year>[0-9]{4})\s*\)\s*$", @"^\s*(?<name>[^ ].*?)\s*$" }; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index cdc8c6870..615eff2c4 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -26,7 +26,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public LegacyHdHomerunChannelCommands(string url) { // parse url for channel and program - var regExp = new Regex(@"\/ch(\d+)-?(\d*)"); + var regExp = new Regex(@"\/ch([0-9]+)-?([[0-9]*)"); var match = regExp.Match(url); if (match.Success) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index e0b7914fb..3b46fdaf7 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subEvent.Text = subEvent.Text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w[0-9]]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); trackEvents.Add(subEvent); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 4a87f87dc..ccef7eeea 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subEvent.Text = string.Join(ParserValues.NewLine, multiline); subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, @"\{(?:\\\d?[\w.-]+(?:\([^\)]*\)|&H?[0-9A-Fa-f]+&|))+\}", string.Empty, RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, @"\{(?:\\[0-9]?[\w.-]+(?:\([^\)]*\)|&H?[0-9A-Fa-f]+&|))+\}", string.Empty, RegexOptions.IgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, "<", "<", RegexOptions.IgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, ">", ">", RegexOptions.IgnoreCase); subEvent.Text = Regex.Replace(subEvent.Text, "<(\\/?(font|b|u|i|s))((\\s+(\\w|\\w[\\w\\-]*\\w)(\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)(\\/?)>", "<$1$3$7>", RegexOptions.IgnoreCase); -- cgit v1.2.3 From f854a1ce1ff98224c231e5ad95101ad84128f65b Mon Sep 17 00:00:00 2001 From: David <daullmer@gmail.com> Date: Wed, 3 Feb 2021 11:34:21 +0100 Subject: Remove unused files --- .drone.yml | 30 ------------------- .../MediaBrowser.MediaEncoding.nuget.targets | 6 ---- MediaBrowser.sln.GhostDoc.xml | 35 ---------------------- hooks/pre_build | 6 ---- 4 files changed, 77 deletions(-) delete mode 100644 .drone.yml delete mode 100644 MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.nuget.targets delete mode 100644 MediaBrowser.sln.GhostDoc.xml delete mode 100644 hooks/pre_build (limited to 'MediaBrowser.MediaEncoding') diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 87c8e414e..000000000 --- a/.drone.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -kind: pipeline -name: build-debug - -steps: -- name: submodules - image: docker:git - commands: - - git submodule update --init --recursive - -- name: build - image: microsoft/dotnet:2-sdk - commands: - - dotnet publish "Jellyfin.Server" --configuration Debug --output "../ci/ci-debug" - ---- -kind: pipeline -name: build-release - -steps: -- name: submodules - image: docker:git - commands: - - git submodule update --init --recursive - -- name: build - image: microsoft/dotnet:2-sdk - commands: - - dotnet publish "Jellyfin.Server" --configuration Release --output "../ci/ci-release" - diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.nuget.targets b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.nuget.targets deleted file mode 100644 index f793e09bc..000000000 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.nuget.targets +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="no"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Target Name="EmitMSBuildWarning" BeforeTargets="Build"> - <Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." /> - </Target> -</Project> \ No newline at end of file diff --git a/MediaBrowser.sln.GhostDoc.xml b/MediaBrowser.sln.GhostDoc.xml deleted file mode 100644 index eafee0bf5..000000000 --- a/MediaBrowser.sln.GhostDoc.xml +++ /dev/null @@ -1,35 +0,0 @@ -<GhostDoc> - <SpellChecker> - <IncludeExtensions> - </IncludeExtensions> - <IgnoreExtensions> - </IgnoreExtensions> - <IgnoreFiles> - </IgnoreFiles> - </SpellChecker> - <HelpConfigurations selected="HelpFile"> - <HelpConfiguration name="HelpFile"> - <OutputPath>D:\Development\MediaBrowser\Help</OutputPath> - <ImageFolderPath /> - <HtmlFormats> - <HtmlHelp>true</HtmlHelp> - <MSHelpViewer>false</MSHelpViewer> - <MSHelp2>false</MSHelp2> - <Website>false</Website> - </HtmlFormats> - <IncludeScopes> - <Public>true</Public> - <Internal>false</Internal> - <Protected>false</Protected> - <Private>false</Private> - <Inherited>true</Inherited> - <EnableTags>false</EnableTags> - <TagList /> - </IncludeScopes> - <ResolveCrefLinks>true</ResolveCrefLinks> - <HeaderText /> - <FooterText /> - <SelectedProjects /> - </HelpConfiguration> - </HelpConfigurations> -</GhostDoc> diff --git a/hooks/pre_build b/hooks/pre_build deleted file mode 100644 index 2fd6136c5..000000000 --- a/hooks/pre_build +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -git submodule update --init --recursive - -# Register qemu-*-static for all supported processors except the -# current one, but also remove all registered binfmt_misc before -docker run --rm --privileged multiarch/qemu-user-static:register --reset -- cgit v1.2.3 From 256bb3ee989082ed10bfb0cb3f02481bf3292a43 Mon Sep 17 00:00:00 2001 From: M0ssTee <47042611+M0ssTee@users.noreply.github.com> Date: Thu, 4 Feb 2021 16:14:57 -0500 Subject: Update MediaBrowser.MediaEncoding/Subtitles/AssParser.cs Co-authored-by: Cody Robibero <cody@robibe.ro> --- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 3b46fdaf7..bb48bed27 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subEvent.Text = subEvent.Text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w[0-9]]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w0-9]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); trackEvents.Add(subEvent); } -- cgit v1.2.3 From b0e0e19468eeadcff0c3a16b47607ce2620227af Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Wed, 27 Jan 2021 03:20:53 +0800 Subject: add cuda format converter --- .../MediaEncoding/EncodingHelper.cs | 129 +++++++++++++-------- .../MediaEncoding/IMediaEncoder.cs | 8 ++ .../Encoder/EncoderValidator.cs | 32 +++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 11 ++ 4 files changed, 132 insertions(+), 48 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1ba02e276..1f60f3bcc 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -112,9 +112,11 @@ namespace MediaBrowser.Controller.MediaEncoding return _mediaEncoder.SupportsHwaccel("vaapi"); } - private bool IsCudaSupported(EncodingJobInfo state) + private bool IsCudaSupported() { - return _mediaEncoder.SupportsHwaccel("cuda"); + return _mediaEncoder.SupportsHwaccel("cuda") + && _mediaEncoder.SupportsFilter("scale_cuda", null) + && _mediaEncoder.SupportsFilter("yadif_cuda", null); } private bool IsTonemappingSupported(EncodingJobInfo state, EncodingOptions options) @@ -123,8 +125,7 @@ namespace MediaBrowser.Controller.MediaEncoding return IsColorDepth10(state) && _mediaEncoder.SupportsHwaccel("opencl") && options.EnableTonemapping - && !string.IsNullOrEmpty(videoStream.VideoRange) - && videoStream.VideoRange.Contains("HDR", StringComparison.OrdinalIgnoreCase); + && string.Equals(videoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); } private bool IsVppTonemappingSupported(EncodingJobInfo state, EncodingOptions options) @@ -138,8 +139,7 @@ namespace MediaBrowser.Controller.MediaEncoding && string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) && _mediaEncoder.SupportsHwaccel("vaapi") && options.EnableVppTonemapping - && !string.IsNullOrEmpty(videoStream.ColorTransfer) - && videoStream.ColorTransfer.Equals("smpte2084", StringComparison.OrdinalIgnoreCase); + && string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase); } // Vpp tonemapping may come to QSV in the future. @@ -482,8 +482,8 @@ namespace MediaBrowser.Controller.MediaEncoding var isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; var isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; - var isNvdecDecoder = videoDecoder.IndexOf("cuda", StringComparison.OrdinalIgnoreCase) != -1; - var isCuvidHevcDecoder = videoDecoder.IndexOf("hevc_cuvid", StringComparison.OrdinalIgnoreCase) != -1; + var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase); + var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); @@ -560,17 +560,17 @@ namespace MediaBrowser.Controller.MediaEncoding } if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) + && string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) + && isNvdecDecoder) { - if (isNvdecDecoder) - { - arg.Append("-hwaccel_output_format cuda "); - } + arg.Append("-hwaccel_output_format cuda "); } if (state.IsVideoRequest - && (string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder)) - || (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && (isD3d11vaDecoder || isSwDecoder))) + && ((string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) + && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder)) + || (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) + && (isD3d11vaDecoder || isSwDecoder)))) { if (isTonemappingSupported) { @@ -2051,8 +2051,8 @@ namespace MediaBrowser.Controller.MediaEncoding else if (isNvdecDecoder && isNvencEncoder) { retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay,format=yuv420p|nv12,hwupload_cuda\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay,format=yuv420p|nv12,hwupload_cuda\""; + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay,format=nv12|yuv420p,hwupload_cuda\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay,format=nv12|yuv420p,hwupload_cuda\""; } return string.Format( @@ -2152,16 +2152,9 @@ namespace MediaBrowser.Controller.MediaEncoding var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder); var outputPixFmt = "format=nv12"; - if (isTonemappingSupportedOnVaapi) + if (isTonemappingSupportedOnVaapi && (isTonemappingSupported || isVppTonemappingSupported)) { - if (isVppTonemappingSupported) - { - outputPixFmt = "format=p010"; - } - else if (isTonemappingSupported) - { - outputPixFmt = "format=p010:out_range=limited"; - } + outputPixFmt = "format=p010"; } if (!videoWidth.HasValue @@ -2181,7 +2174,9 @@ namespace MediaBrowser.Controller.MediaEncoding ":" + outputPixFmt, (qsv_or_vaapi && isDeintEnabled) ? ":deinterlace=1" : string.Empty)); } - else + + // Assert 10-bit is P010 so as we can avoid the extra scaler to get a bit more fps on high res HDR videos. + else if (!(isTonemappingSupportedOnVaapi && (isTonemappingSupported || isVppTonemappingSupported))) { filters.Add( string.Format( @@ -2199,6 +2194,20 @@ namespace MediaBrowser.Controller.MediaEncoding var outputWidth = width.Value; var outputHeight = height.Value; + var isTonemappingSupported = IsTonemappingSupported(state, options); + var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase); + var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilter("scale_cuda", "Output format (default \"same\")"); + + var outputPixFmt = string.Empty; + if (isCudaFormatConversionSupported) + { + outputPixFmt = "format=nv12"; + if (isTonemappingSupported && isTonemappingSupportedOnNvenc) + { + outputPixFmt = "format=p010"; + } + } + if (!videoWidth.HasValue || outputWidth != videoWidth.Value || !videoHeight.HasValue @@ -2207,9 +2216,18 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add( string.Format( CultureInfo.InvariantCulture, - "scale_cuda=w={0}:h={1}", + "scale_cuda=w={0}:h={1}{2}", outputWidth, - outputHeight)); + outputHeight, + isCudaFormatConversionSupported ? (":" + outputPixFmt) : string.Empty)); + } + else if (isCudaFormatConversionSupported) + { + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + "scale_cuda={0}", + outputPixFmt)); } } else if ((videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1 @@ -2594,9 +2612,7 @@ namespace MediaBrowser.Controller.MediaEncoding // When the input may or may not be hardware VAAPI decodable. if ((isVaapiH264Encoder || isVaapiHevcEncoder) - && !isTonemappingSupported - && !isVppTonemappingSupported - && !isTonemappingSupportedOnVaapi) + && !(isTonemappingSupportedOnVaapi && (isTonemappingSupported || isVppTonemappingSupported))) { filters.Add("format=nv12|vaapi"); filters.Add("hwupload"); @@ -2611,7 +2627,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If we're hardware VAAPI decoding and software encoding, download frames from the decoder first. else if ((IsVaapiSupported(state) && isVaapiDecoder) && (isLibX264Encoder || isLibX265Encoder)) { - var codec = videoStream.Codec.ToLowerInvariant(); + var codec = videoStream.Codec; // Assert 10-bit hardware VAAPI decodable if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) @@ -2712,21 +2728,38 @@ namespace MediaBrowser.Controller.MediaEncoding if (isNvdecDecoder && !isTonemappingSupported) { var codec = videoStream.Codec; + var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilter("scale_cuda", "Output format (default \"same\")"); // Assert 10-bit hardware decodable if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase))) { - // Download data from GPU to CPU as p010 format. - filters.Add("hwdownload"); - filters.Add("format=p010"); + if (isCudaFormatConversionSupported) + { + if (isLibX264Encoder || isLibX265Encoder || hasSubs) + { + if (isNvencEncoder) + { + isHwuploadCudaRequired = true; + } - // Cuda lacks of a pixel format converter. - if (isNvencEncoder) + filters.Add("hwdownload"); + filters.Add("format=nv12"); + } + } + else { - isHwuploadCudaRequired = true; - filters.Add("format=yuv420p"); + // Download data from GPU to CPU as p010 format. + filters.Add("hwdownload"); + filters.Add("format=p010"); + + // Cuda lacks of a pixel format converter. + if (isNvencEncoder) + { + isHwuploadCudaRequired = true; + filters.Add("format=yuv420p"); + } } } @@ -3285,32 +3318,32 @@ namespace MediaBrowser.Controller.MediaEncoding { case "avc": case "h264": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "h264", isColorDepth10) : GetHwDecoderName(encodingOptions, "h264_cuvid", "h264", isColorDepth10); case "hevc": case "h265": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "hevc", isColorDepth10) : GetHwDecoderName(encodingOptions, "hevc_cuvid", "hevc", isColorDepth10); case "mpeg2video": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "mpeg2video", isColorDepth10) : GetHwDecoderName(encodingOptions, "mpeg2_cuvid", "mpeg2video", isColorDepth10); case "vc1": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "vc1", isColorDepth10) : GetHwDecoderName(encodingOptions, "vc1_cuvid", "vc1", isColorDepth10); case "mpeg4": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "mpeg4", isColorDepth10) : GetHwDecoderName(encodingOptions, "mpeg4_cuvid", "mpeg4", isColorDepth10); case "vp8": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "vp8", isColorDepth10) : GetHwDecoderName(encodingOptions, "vp8_cuvid", "vp8", isColorDepth10); case "vp9": - return encodingOptions.EnableEnhancedNvdecDecoder + return encodingOptions.EnableEnhancedNvdecDecoder && IsCudaSupported() ? GetHwaccelType(state, encodingOptions, "vp9", isColorDepth10) : GetHwDecoderName(encodingOptions, "vp9_cuvid", "vp9", isColorDepth10); } @@ -3500,7 +3533,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - if (IsCudaSupported(state) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase)) + if (options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase)) { return "-hwaccel cuda"; } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 34fe895cc..0bfa7d3c2 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -50,6 +50,14 @@ namespace MediaBrowser.Controller.MediaEncoding /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> bool SupportsHwaccel(string hwaccel); + /// <summary> + /// Whether given filter is supported. + /// </summary> + /// <param name="filter">The filter.</param> + /// <param name="option">The option.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool SupportsFilter(string filter, string option); + /// <summary> /// Extracts the audio image. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 92f16ab95..9e2417603 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -296,6 +296,38 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } + public bool CheckFilter(string filter, string option) + { + if (string.IsNullOrEmpty(filter)) + { + return false; + } + + string output = null; + try + { + output = GetProcessOutput(_encoderPath, "-h filter=" + filter); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error detecting the given filter"); + } + + if (output.Contains("Filter " + filter, StringComparison.Ordinal)) + { + if (string.IsNullOrEmpty(option)) + { + return true; + } + + return output.Contains(option, StringComparison.Ordinal); + } + + _logger.LogWarning("Filter: {Name} with option {Option} is not available", filter, option); + + return false; + } + private IEnumerable<string> GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fbd08a97c..c0b6cf28b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -295,6 +295,17 @@ namespace MediaBrowser.MediaEncoding.Encoder return _hwaccels.Contains(hwaccel, StringComparer.OrdinalIgnoreCase); } + public bool SupportsFilter(string filter, string option) + { + if (_ffmpegPath != null) + { + var validator = new EncoderValidator(_logger, _ffmpegPath); + return validator.CheckFilter(filter, option); + } + + return false; + } + public bool CanEncodeToAudioCodec(string codec) { if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) -- cgit v1.2.3 From ed8fce2dced5aa1e3db5426e2bdd0aaf756d0e6b Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 8 Jan 2021 23:03:02 +0100 Subject: Use SubtitleEdit to parse subtitles --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- MediaBrowser.Common/Extensions/StreamExtensions.cs | 51 +++ .../MediaBrowser.MediaEncoding.csproj | 1 + MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 129 +----- MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 101 +---- MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 474 +-------------------- .../Subtitles/SubtitleEditParser.cs | 45 ++ .../Subtitles/SubtitleEncoder.cs | 5 +- MediaBrowser.Model/MediaInfo/SubtitleTrackEvent.cs | 7 +- MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs | 1 + .../Subtitles/AssParserTests.cs | 12 +- .../Subtitles/SrtParserTests.cs | 5 +- .../Subtitles/SsaParserTests.cs | 28 ++ .../Test Data/example.ssa | 20 + 14 files changed, 174 insertions(+), 707 deletions(-) create mode 100644 MediaBrowser.Common/Extensions/StreamExtensions.cs create mode 100644 MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ssa (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 1b9bb86bb..0a7c5c1fb 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -374,7 +374,7 @@ namespace Emby.Server.Implementations /// <summary> /// Creates an instance of type and resolves all constructor dependencies. /// </summary> - /// /// <typeparam name="T">The type.</typeparam> + /// <typeparam name="T">The type.</typeparam> /// <returns>T.</returns> public T CreateInstance<T>() => ActivatorUtilities.CreateInstance<T>(ServiceProvider); diff --git a/MediaBrowser.Common/Extensions/StreamExtensions.cs b/MediaBrowser.Common/Extensions/StreamExtensions.cs new file mode 100644 index 000000000..cd77be7b2 --- /dev/null +++ b/MediaBrowser.Common/Extensions/StreamExtensions.cs @@ -0,0 +1,51 @@ +#nullable enable + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace MediaBrowser.Common.Extensions +{ + /// <summary> + /// Class BaseExtensions. + /// </summary> + public static class StreamExtensions + { + /// <summary> + /// Reads all lines in the <see cref="Stream" />. + /// </summary> + /// <param name="stream">The <see cref="Stream" /> to read from.</param> + /// <returns>All lines in the stream.</returns> + public static string[] ReadAllLines(this Stream stream) + => ReadAllLines(stream, Encoding.UTF8); + + /// <summary> + /// Reads all lines in the <see cref="Stream" />. + /// </summary> + /// <param name="stream">The <see cref="Stream" /> to read from.</param> + /// <param name="encoding">The character encoding to use.</param> + /// <returns>All lines in the stream.</returns> + public static string[] ReadAllLines(this Stream stream, Encoding encoding) + { + using (StreamReader reader = new StreamReader(stream, encoding)) + { + return ReadAllLines(reader).ToArray(); + } + } + + /// <summary> + /// Reads all lines in the <see cref="StreamReader" />. + /// </summary> + /// <param name="reader">The <see cref="StreamReader" /> to read from.</param> + /// <returns>All lines in the stream.</returns> + public static IEnumerable<string> ReadAllLines(this StreamReader reader) + { + string? line; + while ((line = reader.ReadLine()) != null) + { + yield return line; + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index f8af499e4..61daf50b3 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,6 +24,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> + <PackageReference Include="libse" Version="3.5.8" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="UTF.Unknown" Version="2.3.0" /> diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index bb48bed27..cdfd87bad 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,130 +1,13 @@ -#pragma warning disable CS1591 +#nullable enable -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using MediaBrowser.Model.MediaInfo; +using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles { - public class AssParser : ISubtitleParser + /// <summary> + /// Advanced SubStation Alpha subtitle parser. + /// </summary> + public class AssParser : SubtitleEditParser<AdvancedSubStationAlpha> { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - /// <inheritdoc /> - public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) - { - var trackInfo = new SubtitleTrackInfo(); - var trackEvents = new List<SubtitleTrackEvent>(); - var eventIndex = 1; - using (var reader = new StreamReader(stream)) - { - string line; - while (!string.Equals(reader.ReadLine(), "[Events]", StringComparison.Ordinal)) - { - } - - var headers = ParseFieldHeaders(reader.ReadLine()); - - while ((line = reader.ReadLine()) != null) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - if (line[0] == '[') - { - break; - } - - var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) }; - eventIndex++; - const string Dialogue = "Dialogue: "; - var sections = line.Substring(Dialogue.Length).Split(','); - - subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]); - subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]); - - subEvent.Text = string.Join(',', sections[headers["Text"]..]); - RemoteNativeFormatting(subEvent); - - subEvent.Text = subEvent.Text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - - subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w0-9]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); - - trackEvents.Add(subEvent); - } - } - - trackInfo.TrackEvents = trackEvents; - return trackInfo; - } - - private long GetTicks(ReadOnlySpan<char> time) - { - return TimeSpan.TryParseExact(time, @"h\:mm\:ss\.ff", _usCulture, out var span) - ? span.Ticks : 0; - } - - internal static Dictionary<string, int> ParseFieldHeaders(string line) - { - const string Format = "Format: "; - var fields = line.Substring(Format.Length).Split(',').Select(x => x.Trim()).ToList(); - - return new Dictionary<string, int> - { - { "Start", fields.IndexOf("Start") }, - { "End", fields.IndexOf("End") }, - { "Text", fields.IndexOf("Text") } - }; - } - - private void RemoteNativeFormatting(SubtitleTrackEvent p) - { - int indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal); - string pre = string.Empty; - while (indexOfBegin >= 0 && p.Text.IndexOf('}', StringComparison.Ordinal) > indexOfBegin) - { - string s = p.Text.Substring(indexOfBegin); - if (s.StartsWith("{\\an1}", StringComparison.Ordinal) || - s.StartsWith("{\\an2}", StringComparison.Ordinal) || - s.StartsWith("{\\an3}", StringComparison.Ordinal) || - s.StartsWith("{\\an4}", StringComparison.Ordinal) || - s.StartsWith("{\\an5}", StringComparison.Ordinal) || - s.StartsWith("{\\an6}", StringComparison.Ordinal) || - s.StartsWith("{\\an7}", StringComparison.Ordinal) || - s.StartsWith("{\\an8}", StringComparison.Ordinal) || - s.StartsWith("{\\an9}", StringComparison.Ordinal)) - { - pre = s.Substring(0, 6); - } - else if (s.StartsWith("{\\an1\\", StringComparison.Ordinal) || - s.StartsWith("{\\an2\\", StringComparison.Ordinal) || - s.StartsWith("{\\an3\\", StringComparison.Ordinal) || - s.StartsWith("{\\an4\\", StringComparison.Ordinal) || - s.StartsWith("{\\an5\\", StringComparison.Ordinal) || - s.StartsWith("{\\an6\\", StringComparison.Ordinal) || - s.StartsWith("{\\an7\\", StringComparison.Ordinal) || - s.StartsWith("{\\an8\\", StringComparison.Ordinal) || - s.StartsWith("{\\an9\\", StringComparison.Ordinal)) - { - pre = s.Substring(0, 5) + "}"; - } - - int indexOfEnd = p.Text.IndexOf('}', StringComparison.Ordinal); - p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1); - - indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal); - } - - p.Text = pre + p.Text; - } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index ccef7eeea..7a7196f6c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -1,102 +1,13 @@ -#pragma warning disable CS1591 +#nullable enable -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text.RegularExpressions; -using System.Threading; -using MediaBrowser.Model.MediaInfo; -using Microsoft.Extensions.Logging; +using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles { - public class SrtParser : ISubtitleParser + /// <summary> + /// SubRip subtitle parser. + /// </summary> + public class SrtParser : SubtitleEditParser<SubRip> { - private readonly ILogger _logger; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public SrtParser(ILogger logger) - { - _logger = logger; - } - - /// <inheritdoc /> - public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) - { - var trackInfo = new SubtitleTrackInfo(); - var trackEvents = new List<SubtitleTrackEvent>(); - using (var reader = new StreamReader(stream)) - { - string line; - while ((line = reader.ReadLine()) != null) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var subEvent = new SubtitleTrackEvent { Id = line }; - line = reader.ReadLine(); - - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var time = Regex.Split(line, @"[\t ]*-->[\t ]*"); - - if (time.Length < 2) - { - // This occurs when subtitle text has an empty line as part of the text. - // Need to adjust the break statement below to resolve this. - _logger.LogWarning("Unrecognized line in srt: {0}", line); - continue; - } - - subEvent.StartPositionTicks = GetTicks(time[0]); - var endTime = time[1].AsSpan(); - var idx = endTime.IndexOf(' '); - if (idx > 0) - { - endTime = endTime.Slice(0, idx); - } - - subEvent.EndPositionTicks = GetTicks(endTime); - var multiline = new List<string>(); - while ((line = reader.ReadLine()) != null) - { - if (line.Length == 0) - { - break; - } - - multiline.Add(line); - } - - subEvent.Text = string.Join(ParserValues.NewLine, multiline); - subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, @"\{(?:\\[0-9]?[\w.-]+(?:\([^\)]*\)|&H?[0-9A-Fa-f]+&|))+\}", string.Empty, RegexOptions.IgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, "<", "<", RegexOptions.IgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, ">", ">", RegexOptions.IgnoreCase); - subEvent.Text = Regex.Replace(subEvent.Text, "<(\\/?(font|b|u|i|s))((\\s+(\\w|\\w[\\w\\-]*\\w)(\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)(\\/?)>", "<$1$3$7>", RegexOptions.IgnoreCase); - trackEvents.Add(subEvent); - } - } - - trackInfo.TrackEvents = trackEvents; - return trackInfo; - } - - private long GetTicks(ReadOnlySpan<char> time) - { - return TimeSpan.TryParseExact(time, @"hh\:mm\:ss\.fff", _usCulture, out var span) - ? span.Ticks - : (TimeSpan.TryParseExact(time, @"hh\:mm\:ss\,fff", _usCulture, out span) - ? span.Ticks : 0); - } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index bc84c5074..8cd06194d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,477 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading; -using MediaBrowser.Model.MediaInfo; +#nullable enable + +using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles { /// <summary> - /// <see href="https://github.com/SubtitleEdit/subtitleedit/blob/a299dc4407a31796364cc6ad83f0d3786194ba22/src/Logic/SubtitleFormats/SubStationAlpha.cs">Credit</see>. + /// SubStation Alpha subtitle parser. /// </summary> - public class SsaParser : ISubtitleParser + public class SsaParser : SubtitleEditParser<SubStationAlpha> { - /// <inheritdoc /> - public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) - { - var trackInfo = new SubtitleTrackInfo(); - var trackEvents = new List<SubtitleTrackEvent>(); - - using (var reader = new StreamReader(stream)) - { - bool eventsStarted = false; - - string[] format = "Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text".Split(','); - int indexLayer = 0; - int indexStart = 1; - int indexEnd = 2; - int indexStyle = 3; - int indexName = 4; - int indexEffect = 8; - int indexText = 9; - int lineNumber = 0; - - var header = new StringBuilder(); - - string line; - - while ((line = reader.ReadLine()) != null) - { - cancellationToken.ThrowIfCancellationRequested(); - - lineNumber++; - if (!eventsStarted) - { - header.AppendLine(line); - } - - if (string.Equals(line.Trim(), "[events]", StringComparison.OrdinalIgnoreCase)) - { - eventsStarted = true; - } - else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(';')) - { - // skip comment lines - } - else if (eventsStarted && line.Trim().Length > 0) - { - string s = line.Trim().ToLowerInvariant(); - if (s.StartsWith("format:", StringComparison.Ordinal)) - { - if (line.Length > 10) - { - format = line.ToLowerInvariant().Substring(8).Split(','); - for (int i = 0; i < format.Length; i++) - { - if (string.Equals(format[i].Trim(), "layer", StringComparison.OrdinalIgnoreCase)) - { - indexLayer = i; - } - else if (string.Equals(format[i].Trim(), "start", StringComparison.OrdinalIgnoreCase)) - { - indexStart = i; - } - else if (string.Equals(format[i].Trim(), "end", StringComparison.OrdinalIgnoreCase)) - { - indexEnd = i; - } - else if (string.Equals(format[i].Trim(), "text", StringComparison.OrdinalIgnoreCase)) - { - indexText = i; - } - else if (string.Equals(format[i].Trim(), "effect", StringComparison.OrdinalIgnoreCase)) - { - indexEffect = i; - } - else if (string.Equals(format[i].Trim(), "style", StringComparison.OrdinalIgnoreCase)) - { - indexStyle = i; - } - } - } - } - else if (!string.IsNullOrEmpty(s)) - { - string text = string.Empty; - string start = string.Empty; - string end = string.Empty; - string style = string.Empty; - string layer = string.Empty; - string effect = string.Empty; - string name = string.Empty; - - string[] splittedLine; - - if (s.StartsWith("dialogue:", StringComparison.Ordinal)) - { - splittedLine = line.Substring(10).Split(','); - } - else - { - splittedLine = line.Split(','); - } - - for (int i = 0; i < splittedLine.Length; i++) - { - if (i == indexStart) - { - start = splittedLine[i].Trim(); - } - else if (i == indexEnd) - { - end = splittedLine[i].Trim(); - } - else if (i == indexLayer) - { - layer = splittedLine[i]; - } - else if (i == indexEffect) - { - effect = splittedLine[i]; - } - else if (i == indexText) - { - text = splittedLine[i]; - } - else if (i == indexStyle) - { - style = splittedLine[i]; - } - else if (i == indexName) - { - name = splittedLine[i]; - } - else if (i > indexText) - { - text += "," + splittedLine[i]; - } - } - - try - { - trackEvents.Add( - new SubtitleTrackEvent - { - StartPositionTicks = GetTimeCodeFromString(start), - EndPositionTicks = GetTimeCodeFromString(end), - Text = GetFormattedText(text) - }); - } - catch - { - } - } - } - } - - // if (header.Length > 0) - // subtitle.Header = header.ToString(); - - // subtitle.Renumber(1); - } - - trackInfo.TrackEvents = trackEvents.ToArray(); - return trackInfo; - } - - private static long GetTimeCodeFromString(string time) - { - // h:mm:ss.cc - string[] timeCode = time.Split(':', '.'); - return new TimeSpan( - 0, - 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) - { - text = text.Replace("\\n", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase); - - for (int i = 0; i < 10; i++) // just look ten times... - { - if (text.Contains(@"{\fn", StringComparison.Ordinal)) - { - int start = text.IndexOf(@"{\fn", StringComparison.Ordinal); - int end = text.IndexOf('}', start); - if (end > 0 && !text.Substring(start).StartsWith("{\\fn}", StringComparison.Ordinal)) - { - string fontName = text.Substring(start + 4, end - (start + 4)); - string extraTags = string.Empty; - CheckAndAddSubTags(ref fontName, ref extraTags, out bool italic); - text = text.Remove(start, end - start + 1); - if (italic) - { - text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + "><i>"); - } - else - { - text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">"); - } - - int indexOfEndTag = text.IndexOf("{\\fn}", start, StringComparison.Ordinal); - if (indexOfEndTag > 0) - { - text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>"); - } - else - { - text += "</font>"; - } - } - } - - if (text.Contains(@"{\fs", StringComparison.Ordinal)) - { - int start = text.IndexOf(@"{\fs", StringComparison.Ordinal); - int end = text.IndexOf('}', start); - if (end > 0 && !text.Substring(start).StartsWith("{\\fs}", StringComparison.Ordinal)) - { - string fontSize = text.Substring(start + 4, end - (start + 4)); - string extraTags = string.Empty; - CheckAndAddSubTags(ref fontSize, ref extraTags, out bool italic); - if (IsInteger(fontSize)) - { - text = text.Remove(start, end - start + 1); - if (italic) - { - text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + "><i>"); - } - else - { - text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">"); - } - - int indexOfEndTag = text.IndexOf("{\\fs}", start, StringComparison.Ordinal); - if (indexOfEndTag > 0) - { - text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>"); - } - else - { - text += "</font>"; - } - } - } - } - - if (text.Contains(@"{\c", StringComparison.Ordinal)) - { - int start = text.IndexOf(@"{\c", StringComparison.Ordinal); - int end = text.IndexOf('}', start); - if (end > 0 && !text.Substring(start).StartsWith("{\\c}", StringComparison.Ordinal)) - { - string color = text.Substring(start + 4, end - (start + 4)); - string extraTags = string.Empty; - CheckAndAddSubTags(ref color, ref extraTags, out bool italic); - - color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H'); - color = color.PadLeft(6, '0'); - - // 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.ToLowerInvariant(); - - text = text.Remove(start, end - start + 1); - if (italic) - { - text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); - } - else - { - text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); - } - - int indexOfEndTag = text.IndexOf("{\\c}", start, StringComparison.Ordinal); - if (indexOfEndTag > 0) - { - text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>"); - } - else - { - text += "</font>"; - } - } - } - - if (text.Contains(@"{\1c", StringComparison.Ordinal)) // "1" specifices primary color - { - int start = text.IndexOf(@"{\1c", StringComparison.Ordinal); - int end = text.IndexOf('}', start); - if (end > 0 && !text.Substring(start).StartsWith("{\\1c}", StringComparison.Ordinal)) - { - string color = text.Substring(start + 5, end - (start + 5)); - string extraTags = string.Empty; - CheckAndAddSubTags(ref color, ref extraTags, out bool italic); - - color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H'); - color = color.PadLeft(6, '0'); - - // 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.ToLowerInvariant(); - - text = text.Remove(start, end - start + 1); - if (italic) - { - text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>"); - } - else - { - text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">"); - } - - int indexOfEndTag = text.IndexOf("{\\1c}", start, StringComparison.Ordinal); - if (indexOfEndTag > 0) - { - text = text.Remove(indexOfEndTag, "{\\1c}".Length).Insert(indexOfEndTag, "</font>"); - } - else - { - text += "</font>"; - } - } - } - } - - 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>")) - { - text += "</i>"; - } - - 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>")) - { - text += "</u>"; - } - - 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>")) - { - text += "</b>"; - } - - return text; - } - - private static bool IsInteger(string s) - => int.TryParse(s, out _); - - private static int CountTagInText(string text, string tag) - { - int count = 0; - int index = text.IndexOf(tag, StringComparison.Ordinal); - while (index >= 0) - { - count++; - if (index == text.Length) - { - return count; - } - - index = text.IndexOf(tag, index + 1, StringComparison.Ordinal); - } - - return count; - } - - private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out bool italic) - { - italic = false; - int indexOfSPlit = tagName.IndexOf('\\', StringComparison.Ordinal); - if (indexOfSPlit > 0) - { - string rest = tagName.Substring(indexOfSPlit).TrimStart('\\'); - tagName = tagName.Remove(indexOfSPlit); - - for (int i = 0; i < 10; i++) - { - if (rest.StartsWith("fs", StringComparison.Ordinal) && rest.Length > 2) - { - indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal); - string fontSize = rest; - if (indexOfSPlit > 0) - { - fontSize = rest.Substring(0, indexOfSPlit); - rest = rest.Substring(indexOfSPlit).TrimStart('\\'); - } - else - { - rest = string.Empty; - } - - extraTags += " size=\"" + fontSize.Substring(2) + "\""; - } - else if (rest.StartsWith("fn", StringComparison.Ordinal) && rest.Length > 2) - { - indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal); - string fontName = rest; - if (indexOfSPlit > 0) - { - fontName = rest.Substring(0, indexOfSPlit); - rest = rest.Substring(indexOfSPlit).TrimStart('\\'); - } - else - { - rest = string.Empty; - } - - extraTags += " face=\"" + fontName.Substring(2) + "\""; - } - else if (rest.StartsWith("c", StringComparison.Ordinal) && rest.Length > 2) - { - indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal); - string fontColor = rest; - if (indexOfSPlit > 0) - { - fontColor = rest.Substring(0, indexOfSPlit); - rest = rest.Substring(indexOfSPlit).TrimStart('\\'); - } - else - { - rest = string.Empty; - } - - string color = fontColor.Substring(2); - color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H'); - color = color.PadLeft(6, '0'); - // 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.ToLowerInvariant(); - - extraTags += " color=\"" + color + "\""; - } - else if (rest.StartsWith("i1", StringComparison.Ordinal) && rest.Length > 1) - { - indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal); - italic = true; - if (indexOfSPlit > 0) - { - rest = rest.Substring(indexOfSPlit).TrimStart('\\'); - } - else - { - rest = string.Empty; - } - } - else if (rest.Length > 0 && rest.Contains('\\', StringComparison.Ordinal)) - { - indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal); - rest = rest.Substring(indexOfSPlit).TrimStart('\\'); - } - } - } - } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs new file mode 100644 index 000000000..441b9ce33 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -0,0 +1,45 @@ +#nullable enable + +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Model.MediaInfo; +using Nikse.SubtitleEdit.Core; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + /// <summary> + /// SubStation Alpha subtitle parser. + /// </summary> + /// <typeparam name="T">The <see cref="Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat" />.</typeparam> + public abstract class SubtitleEditParser<T> : ISubtitleParser + where T : Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat, new() + { + /// <inheritdoc /> + public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) + { + var subtitle = new Subtitle(); + var subRip = new T(); + var lines = stream.ReadAllLines().ToList(); + subRip.LoadSubtitle(subtitle, lines, "untitled"); + + var trackInfo = new SubtitleTrackInfo(); + int len = subtitle.Paragraphs.Count; + var trackEvents = new SubtitleTrackEvent[len]; + for (int i = 0; i < len; i++) + { + var p = subtitle.Paragraphs[i]; + trackEvents[i] = new SubtitleTrackEvent(p.Number.ToString(CultureInfo.InvariantCulture), p.Text) + { + StartPositionTicks = p.StartTime.TimeSpan.Ticks, + EndPositionTicks = p.EndTime.TimeSpan.Ticks + }; + } + + trackInfo.TrackEvents = trackEvents; + return trackInfo; + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index b92c4ee06..62ac83c91 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -27,7 +27,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles { public class SubtitleEncoder : ISubtitleEncoder { - private readonly ILibraryManager _libraryManager; private readonly ILogger<SubtitleEncoder> _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; @@ -42,7 +41,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles new ConcurrentDictionary<string, SemaphoreSlim>(); public SubtitleEncoder( - ILibraryManager libraryManager, ILogger<SubtitleEncoder> logger, IApplicationPaths appPaths, IFileSystem fileSystem, @@ -50,7 +48,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles IHttpClientFactory httpClientFactory, IMediaSourceManager mediaSourceManager) { - _libraryManager = libraryManager; _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; @@ -274,7 +271,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { - return new SrtParser(_logger); + return new SrtParser(); } if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackEvent.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackEvent.cs index 72bb3d9c6..88b00c166 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackEvent.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackEvent.cs @@ -1,10 +1,15 @@ -#nullable disable #pragma warning disable CS1591 namespace MediaBrowser.Model.MediaInfo { public class SubtitleTrackEvent { + public SubtitleTrackEvent(string id, string text) + { + Id = id; + Text = text; + } + public string Id { get; set; } public string Text { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs index 37f5c55da..fb47dc9c2 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs @@ -1,3 +1,4 @@ +#nullable enable #pragma warning disable CS1591 using System; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index 14ad49839..457ef4544 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -21,18 +21,8 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests Assert.Equal("1", trackEvent.Id); Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); - Assert.Equal("Like an Angel with pity on nobody\r\nThe second line in subtitle", trackEvent.Text); + Assert.Equal("{\\pos(400,570)}Like an Angel with pity on nobody\nThe second line in subtitle", trackEvent.Text); } } - - [Fact] - public void ParseFieldHeaders_Valid_Success() - { - const string Line = "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; - var headers = AssParser.ParseFieldHeaders(Line); - Assert.Equal(1, headers["Start"]); - Assert.Equal(2, headers["End"]); - Assert.Equal(9, headers["Text"]); - } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 3e2d2de10..6bfc426cb 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; -using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Jellyfin.MediaEncoding.Subtitles.Tests @@ -15,14 +14,14 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { using (var stream = File.OpenRead("Test Data/example.srt")) { - var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None); + var parsed = new SrtParser().Parse(stream, CancellationToken.None); Assert.Equal(2, parsed.TrackEvents.Count); var trackEvent1 = parsed.TrackEvents[0]; Assert.Equal("1", trackEvent1.Id); Assert.Equal(TimeSpan.Parse("00:02:17.440", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); Assert.Equal(TimeSpan.Parse("00:02:20.375", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); - Assert.Equal("Senator, we're making\r\nour final approach into Coruscant.", trackEvent1.Text); + Assert.Equal("Senator, we're making\nour final approach into Coruscant.", trackEvent1.Text); var trackEvent2 = parsed.TrackEvents[1]; Assert.Equal("2", trackEvent2.Id); diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs new file mode 100644 index 000000000..660b7f1be --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using Xunit; + +namespace Jellyfin.MediaEncoding.Subtitles.Tests +{ + public class SsaParserTests + { + [Fact] + public void Parse_Valid_Success() + { + using (var stream = File.OpenRead("Test Data/example.ssa")) + { + var parsed = new SsaParser().Parse(stream, CancellationToken.None); + Assert.Single(parsed.TrackEvents); + var trackEvent = parsed.TrackEvents[0]; + + Assert.Equal("1", trackEvent.Id); + Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); + Assert.Equal("{\\pos(400,570)}Like an angel with pity on nobody", trackEvent.Text); + } + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ssa b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ssa new file mode 100644 index 000000000..dcbb972eb --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ssa @@ -0,0 +1,20 @@ +[Script Info] +; This is a Sub Station Alpha v4 script. +; For Sub Station Alpha info and downloads, +; go to http://www.eswat.demon.co.uk/ +Title: Neon Genesis Evangelion - Episode 26 (neutral Spanish) +Original Script: RoRo +Script Updated By: version 2.8.01 +ScriptType: v4.00 +Collisions: Normal +PlayResY: 600 +PlayDepth: 0 +Timer: 100,0000 + +[V4 Styles] +Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding +Style: DefaultVCD, Arial,28,11861244,11861244,11861244,-2147483640,-1,0,1,1,2,2,30,30,30,0,0 + +[Events] +Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text +Dialogue: Marked=0,0:00:01.18,0:00:06.85,DefaultVCD, NTP,0000,0000,0000,,{\pos(400,570)}Like an angel with pity on nobody -- cgit v1.2.3 From be965e35b680de9362a09eeee2879e8867911656 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 8 Jan 2021 23:21:50 +0100 Subject: Log subtitle errors --- MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 8 ++++++++ MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 8 ++++++++ MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 8 ++++++++ .../Subtitles/SubtitleEditParser.cs | 22 ++++++++++++++++++++-- .../Subtitles/SubtitleEncoder.cs | 6 +++--- .../Subtitles/AssParserTests.cs | 3 ++- .../Subtitles/SrtParserTests.cs | 3 ++- .../Subtitles/SsaParserTests.cs | 3 ++- 8 files changed, 53 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index cdfd87bad..8219aa7b4 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,5 +1,6 @@ #nullable enable +using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles @@ -9,5 +10,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> public class AssParser : SubtitleEditParser<AdvancedSubStationAlpha> { + /// <summary> + /// Initializes a new instance of the <see cref="AssParser"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + public AssParser(ILogger logger) : base(logger) + { + } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 7a7196f6c..19fb951dc 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -1,5 +1,6 @@ #nullable enable +using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles @@ -9,5 +10,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> public class SrtParser : SubtitleEditParser<SubRip> { + /// <summary> + /// Initializes a new instance of the <see cref="SrtParser"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + public SrtParser(ILogger logger) : base(logger) + { + } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 8cd06194d..36dc2e01f 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,5 +1,6 @@ #nullable enable +using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace MediaBrowser.MediaEncoding.Subtitles @@ -9,5 +10,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// </summary> public class SsaParser : SubtitleEditParser<SubStationAlpha> { + /// <summary> + /// Initializes a new instance of the <see cref="SsaParser"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + public SsaParser(ILogger logger) : base(logger) + { + } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 441b9ce33..82ec6ca21 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -6,17 +6,31 @@ using System.Linq; using System.Threading; using MediaBrowser.Common.Extensions; using MediaBrowser.Model.MediaInfo; +using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core; +using ILogger = Microsoft.Extensions.Logging.ILogger; +using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat; namespace MediaBrowser.MediaEncoding.Subtitles { /// <summary> /// SubStation Alpha subtitle parser. /// </summary> - /// <typeparam name="T">The <see cref="Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat" />.</typeparam> + /// <typeparam name="T">The <see cref="SubtitleFormat" />.</typeparam> public abstract class SubtitleEditParser<T> : ISubtitleParser - where T : Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat, new() + where T : SubtitleFormat, new() { + private readonly ILogger _logger; + + /// <summary> + /// Initializes a new instance of the <see cref="SubtitleEditParser{T}"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + protected SubtitleEditParser(ILogger logger) + { + _logger = logger; + } + /// <inheritdoc /> public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { @@ -24,6 +38,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles var subRip = new T(); var lines = stream.ReadAllLines().ToList(); subRip.LoadSubtitle(subtitle, lines, "untitled"); + if (subRip.ErrorCount > 0) + { + _logger.LogError("{ErrorCount} errors encountered while parsing subtitle."); + } var trackInfo = new SubtitleTrackInfo(); int len = subtitle.Paragraphs.Count; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 62ac83c91..a9d118ef5 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -271,17 +271,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { - return new SrtParser(); + return new SrtParser(_logger); } if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) { - return new SsaParser(); + return new SsaParser(_logger); } if (string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase)) { - return new AssParser(); + return new AssParser(_logger); } if (throwIfMissing) diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index 457ef4544..f38fc23d5 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Jellyfin.MediaEncoding.Subtitles.Tests @@ -14,7 +15,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { using (var stream = File.OpenRead("Test Data/example.ass")) { - var parsed = new AssParser().Parse(stream, CancellationToken.None); + var parsed = new AssParser(new NullLogger<AssParser>()).Parse(stream, CancellationToken.None); Assert.Single(parsed.TrackEvents); var trackEvent = parsed.TrackEvents[0]; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 6bfc426cb..25b8b4746 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Jellyfin.MediaEncoding.Subtitles.Tests @@ -14,7 +15,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { using (var stream = File.OpenRead("Test Data/example.srt")) { - var parsed = new SrtParser().Parse(stream, CancellationToken.None); + var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None); Assert.Equal(2, parsed.TrackEvents.Count); var trackEvent1 = parsed.TrackEvents[0]; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs index 660b7f1be..0ff7cb1ec 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace Jellyfin.MediaEncoding.Subtitles.Tests @@ -14,7 +15,7 @@ namespace Jellyfin.MediaEncoding.Subtitles.Tests { using (var stream = File.OpenRead("Test Data/example.ssa")) { - var parsed = new SsaParser().Parse(stream, CancellationToken.None); + var parsed = new SsaParser(new NullLogger<SsaParser>()).Parse(stream, CancellationToken.None); Assert.Single(parsed.TrackEvents); var trackEvent = parsed.TrackEvents[0]; -- cgit v1.2.3 From 65bab55ca09b09f5229d6e9d50f9cfccfeb8f3d0 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 13 Feb 2021 00:39:18 +0100 Subject: Minor improvements --- Emby.Dlna/PlayTo/Device.cs | 2 +- Emby.Naming/AudioBook/AudioBookListResolver.cs | 2 +- .../Data/SqliteExtensions.cs | 6 +- .../Data/SqliteItemRepository.cs | 84 +++++++++++----------- .../Data/SqliteUserDataRepository.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- .../LiveTv/TunerHosts/M3uParser.cs | 2 +- .../MediaEncoder/EncodingManager.cs | 2 +- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- .../Controllers/UniversalAudioController.cs | 4 +- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +- MediaBrowser.Controller/Entities/TV/Series.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 13 ++-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 4 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 14 ++-- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 2 +- 20 files changed, 78 insertions(+), 77 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 938ce5fbf..9961d15b0 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -990,7 +990,7 @@ namespace Emby.Dlna.PlayTo var deviceProperties = new DeviceInfo() { - Name = string.Join(" ", friendlyNames), + Name = string.Join(' ', friendlyNames), BaseUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", url.Host, url.Port) }; diff --git a/Emby.Naming/AudioBook/AudioBookListResolver.cs b/Emby.Naming/AudioBook/AudioBookListResolver.cs index e9ea9b7a5..ca5322890 100644 --- a/Emby.Naming/AudioBook/AudioBookListResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookListResolver.cs @@ -73,7 +73,7 @@ namespace Emby.Naming.AudioBook var haveChaptersOrPages = stackFiles.Any(x => x.ChapterNumber != null || x.PartNumber != null); var groupedBy = stackFiles.GroupBy(file => new { file.ChapterNumber, file.PartNumber }); - var nameWithReplacedDots = nameParserResult.Name.Replace(" ", "."); + var nameWithReplacedDots = nameParserResult.Name.Replace(' ', '.'); foreach (var group in groupedBy) { diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index 1af301ceb..a04d63088 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using SQLitePCL.pretty; @@ -59,7 +60,7 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction(conn => { - conn.ExecuteAll(string.Join(";", queries)); + conn.ExecuteAll(string.Join(';', queries)); }); } @@ -142,11 +143,10 @@ namespace Emby.Server.Implementations.Data return result[index].ReadGuidFromBlob(); } + [Conditional("DEBUG")] private static void CheckName(string name) { -#if DEBUG throw new ArgumentException("Invalid param name: " + name, nameof(name)); -#endif } public static void TryBind(this IStatement statement, string name, double value) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 6e1f2feae..dad8bec7b 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -687,7 +687,7 @@ namespace Emby.Server.Implementations.Data if (item.Genres.Length > 0) { - saveItemStatement.TryBind("@Genres", string.Join("|", item.Genres)); + saveItemStatement.TryBind("@Genres", string.Join('|', item.Genres)); } else { @@ -749,7 +749,7 @@ namespace Emby.Server.Implementations.Data if (item.LockedFields.Length > 0) { - saveItemStatement.TryBind("@LockedFields", string.Join("|", item.LockedFields)); + saveItemStatement.TryBind("@LockedFields", string.Join('|', item.LockedFields)); } else { @@ -758,7 +758,7 @@ namespace Emby.Server.Implementations.Data if (item.Studios.Length > 0) { - saveItemStatement.TryBind("@Studios", string.Join("|", item.Studios)); + saveItemStatement.TryBind("@Studios", string.Join('|', item.Studios)); } else { @@ -785,7 +785,7 @@ namespace Emby.Server.Implementations.Data if (item.Tags.Length > 0) { - saveItemStatement.TryBind("@Tags", string.Join("|", item.Tags)); + saveItemStatement.TryBind("@Tags", string.Join('|', item.Tags)); } else { @@ -807,7 +807,7 @@ namespace Emby.Server.Implementations.Data if (item is Trailer trailer && trailer.TrailerTypes.Length > 0) { - saveItemStatement.TryBind("@TrailerTypes", string.Join("|", trailer.TrailerTypes)); + saveItemStatement.TryBind("@TrailerTypes", string.Join('|', trailer.TrailerTypes)); } else { @@ -902,7 +902,7 @@ namespace Emby.Server.Implementations.Data if (item.ProductionLocations.Length > 0) { - saveItemStatement.TryBind("@ProductionLocations", string.Join("|", item.ProductionLocations)); + saveItemStatement.TryBind("@ProductionLocations", string.Join('|', item.ProductionLocations)); } else { @@ -911,7 +911,7 @@ namespace Emby.Server.Implementations.Data if (item.ExtraIds.Length > 0) { - saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds)); + saveItemStatement.TryBind("@ExtraIds", string.Join('|', item.ExtraIds)); } else { @@ -931,7 +931,7 @@ namespace Emby.Server.Implementations.Data string artists = null; if (item is IHasArtist hasArtists && hasArtists.Artists.Count > 0) { - artists = string.Join("|", hasArtists.Artists); + artists = string.Join('|', hasArtists.Artists); } saveItemStatement.TryBind("@Artists", artists); @@ -940,7 +940,7 @@ namespace Emby.Server.Implementations.Data if (item is IHasAlbumArtist hasAlbumArtists && hasAlbumArtists.AlbumArtists.Count > 0) { - albumArtists = string.Join("|", hasAlbumArtists.AlbumArtists); + albumArtists = string.Join('|', hasAlbumArtists.AlbumArtists); } saveItemStatement.TryBind("@AlbumArtists", albumArtists); @@ -2549,7 +2549,7 @@ namespace Emby.Server.Implementations.Data if (groups.Count > 0) { - return " Group by " + string.Join(",", groups); + return " Group by " + string.Join(',', groups); } return string.Empty; @@ -2578,7 +2578,7 @@ namespace Emby.Server.Implementations.Data } var commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count(distinct PresentationUniqueKey)" })) + GetFromText() + GetJoinUserDataText(query); @@ -2630,7 +2630,7 @@ namespace Emby.Server.Implementations.Data } var commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + string.Join(',', GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText() + GetJoinUserDataText(query); @@ -2880,7 +2880,7 @@ namespace Emby.Server.Implementations.Data } var commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + + string.Join(',', GetFinalColumnsToSelect(query, _retriveItemColumns)) + GetFromText() + GetJoinUserDataText(query); @@ -2923,15 +2923,15 @@ namespace Emby.Server.Implementations.Data if (EnableGroupByPresentationUniqueKey(query)) { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); } else if (query.GroupBySeriesPresentationUniqueKey) { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct SeriesPresentationUniqueKey)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct SeriesPresentationUniqueKey)" })) + GetFromText(); } else { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } commandText += GetJoinUserDataText(query) @@ -3039,7 +3039,7 @@ namespace Emby.Server.Implementations.Data return string.Empty; } - return " ORDER BY " + string.Join(",", orderBy.Select(i => + return " ORDER BY " + string.Join(',', orderBy.Select(i => { var columnMap = MapOrderByField(i.Item1, query); @@ -3137,7 +3137,7 @@ namespace Emby.Server.Implementations.Data var now = DateTime.UtcNow; var commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText() + GetJoinUserDataText(query); @@ -3203,7 +3203,7 @@ namespace Emby.Server.Implementations.Data var now = DateTime.UtcNow; - var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid", "path" })) + GetFromText(); + var commandText = "select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "guid", "path" })) + GetFromText(); var whereClauses = GetWhereClauses(query, null); if (whereClauses.Count != 0) @@ -3284,7 +3284,7 @@ namespace Emby.Server.Implementations.Data var now = DateTime.UtcNow; var commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "guid" })) + GetFromText() + GetJoinUserDataText(query); @@ -3327,15 +3327,15 @@ namespace Emby.Server.Implementations.Data if (EnableGroupByPresentationUniqueKey(query)) { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText(); } else if (query.GroupBySeriesPresentationUniqueKey) { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct SeriesPresentationUniqueKey)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct SeriesPresentationUniqueKey)" })) + GetFromText(); } else { - commandText += " select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); + commandText += " select " + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (guid)" })) + GetFromText(); } commandText += GetJoinUserDataText(query) @@ -3596,7 +3596,7 @@ namespace Emby.Server.Implementations.Data } else if (excludeTypes.Length > 1) { - var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'")); + var inClause = string.Join(',', excludeTypes.Select(i => "'" + i + "'")); whereClauses.Add($"type not in ({inClause})"); } } @@ -3607,7 +3607,7 @@ namespace Emby.Server.Implementations.Data } else if (includeTypes.Length > 1) { - var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'")); + var inClause = string.Join(',', includeTypes.Select(i => "'" + i + "'")); whereClauses.Add($"type in ({inClause})"); } @@ -3618,7 +3618,7 @@ namespace Emby.Server.Implementations.Data } else if (query.ChannelIds.Count > 1) { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); + var inClause = string.Join(',', query.ChannelIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); whereClauses.Add($"ChannelId in ({inClause})"); } @@ -4351,7 +4351,7 @@ namespace Emby.Server.Implementations.Data } else if (query.Years.Length > 1) { - var val = string.Join(",", query.Years); + var val = string.Join(',', query.Years); whereClauses.Add("ProductionYear in (" + val + ")"); } @@ -4401,7 +4401,7 @@ namespace Emby.Server.Implementations.Data } else if (queryMediaTypes.Length > 1) { - var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'")); + var val = string.Join(',', queryMediaTypes.Select(i => "'" + i + "'")); whereClauses.Add("MediaType in (" + val + ")"); } @@ -4498,7 +4498,7 @@ namespace Emby.Server.Implementations.Data var paramName = "@HasAnyProviderId" + index; // this is a search for the placeholder - hasProviderIds.Add("ProviderIds like " + paramName + ""); + hasProviderIds.Add("ProviderIds like " + paramName); // this replaces the placeholder with a value, here: %key=val% if (statement != null) @@ -4549,7 +4549,7 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); + var itemByNameTypeVal = string.Join(',', includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(TopParentId=@TopParentId or Type in (" + itemByNameTypeVal + "))"); } else @@ -4564,7 +4564,7 @@ namespace Emby.Server.Implementations.Data } else if (queryTopParentIds.Length > 1) { - var val = string.Join(",", queryTopParentIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); + var val = string.Join(',', queryTopParentIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); if (enableItemsByName && includedItemByNameTypes.Count == 1) { @@ -4576,7 +4576,7 @@ namespace Emby.Server.Implementations.Data } else if (enableItemsByName && includedItemByNameTypes.Count > 1) { - var itemByNameTypeVal = string.Join(",", includedItemByNameTypes.Select(i => "'" + i + "'")); + var itemByNameTypeVal = string.Join(',', includedItemByNameTypes.Select(i => "'" + i + "'")); whereClauses.Add("(Type in (" + itemByNameTypeVal + ") or TopParentId in (" + val + "))"); } else @@ -4597,7 +4597,7 @@ namespace Emby.Server.Implementations.Data if (query.AncestorIds.Length > 1) { - var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); + var inClause = string.Join(',', query.AncestorIds.Select(i => "'" + i.ToString("N", CultureInfo.InvariantCulture) + "'")); whereClauses.Add(string.Format(CultureInfo.InvariantCulture, "Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); } @@ -5148,7 +5148,7 @@ AND Type = @InternalPersonType)"); } else if (queryPersonTypes.Count > 1) { - var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'")); + var val = string.Join(',', queryPersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType in (" + val + ")"); } @@ -5162,7 +5162,7 @@ AND Type = @InternalPersonType)"); } else if (queryExcludePersonTypes.Count > 1) { - var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'")); + var val = string.Join(',', queryExcludePersonTypes.Select(i => "'" + i + "'")); whereClauses.Add("PersonType not in (" + val + ")"); } @@ -5308,19 +5308,19 @@ AND Type = @InternalPersonType)"); var typeClause = itemValueTypes.Length == 1 ? ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); + ("Type in (" + string.Join(',', itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); var commandText = "Select Value From ItemValues where " + typeClause; if (withItemTypes.Count > 0) { - var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'")); + var typeString = string.Join(',', withItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))"; } if (excludeItemTypes.Count > 0) { - var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'")); + var typeString = string.Join(',', excludeItemTypes.Select(i => "'" + i + "'")); commandText += " AND ItemId not In (select guid from typedbaseitems where type in (" + typeString + "))"; } @@ -5363,7 +5363,7 @@ AND Type = @InternalPersonType)"); var typeClause = itemValueTypes.Length == 1 ? ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); + ("Type in (" + string.Join(',', itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); InternalItemsQuery typeSubQuery = null; @@ -5427,7 +5427,7 @@ AND Type = @InternalPersonType)"); columns = GetFinalColumnsToSelect(query, columns); var commandText = "select " - + string.Join(",", columns) + + string.Join(',', columns) + GetFromText() + GetJoinUserDataText(query); @@ -5504,7 +5504,7 @@ AND Type = @InternalPersonType)"); if (query.EnableTotalRecordCount) { var countText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText() + GetJoinUserDataText(query) + whereText; @@ -5565,7 +5565,7 @@ AND Type = @InternalPersonType)"); if (query.EnableTotalRecordCount) { commandText = "select " - + string.Join(",", GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + + string.Join(',', GetFinalColumnsToSelect(query, new[] { "count (distinct PresentationUniqueKey)" })) + GetFromText() + GetJoinUserDataText(query) + whereText; diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 2c4e8e0fc..6574db607 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction( db => { - db.ExecuteAll(string.Join(";", new[] { + db.ExecuteAll(string.Join(';', new[] { "create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)", diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 7567ea312..d32b70e03 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -35,8 +35,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ICryptoProvider _cryptoProvider; private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>(); - private DateTime _lastErrorResponse; private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private DateTime _lastErrorResponse; public SchedulesDirect( ILogger<SchedulesDirect> logger, diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index c82b67b41..c4f173c7a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -155,7 +155,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (channelIdValues.Count > 0) { - channel.Id = string.Join("_", channelIdValues); + channel.Id = string.Join('_', channelIdValues); } return channel; diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index f27305cbe..c6e931448 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -166,7 +166,7 @@ namespace Emby.Server.Implementations.MediaEncoder } catch (Exception ex) { - _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(",", video.Path)); + _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(',', video.Path)); success = false; break; } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 171e44258..649305fd5 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -143,7 +143,7 @@ namespace Emby.Server.Implementations.ScheduledTasks Directory.CreateDirectory(parentPath); - string text = string.Join("|", previouslyFailedImages); + string text = string.Join('|', previouslyFailedImages); File.WriteAllText(failHistoryPath, text); } diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index bacd95bac..5aa033ccf 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers DeInterlace = true, RequireNonAnamorphic = true, EnableMpegtsM2TsMode = true, - TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), Context = EncodingContext.Static, StreamOptions = new Dictionary<string, string>(), EnableAdaptiveBitrateStreaming = true @@ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers CopyTimestamps = true, StartTimeTicks = startTimeTicks, SubtitleMethod = SubtitleDeliveryMethod.Embed, - TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), Context = EncodingContext.Static }; diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 92ff42b49..8a47f7461 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -222,7 +222,7 @@ namespace Jellyfin.Api.Helpers { // Force HEVC Main Profile and disable video stream copy. state.OutputVideoCodec = "hevc"; - var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(",", requestedVideoProfiles), "main"); + var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main"); sdrVideoUrl += "&AllowVideoStreamCopy=false"; EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7598b29e6..53d45261e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1243,7 +1243,7 @@ namespace MediaBrowser.Controller.Entities } } - return string.Join("/", terms.ToArray()); + return string.Join('/', terms.ToArray()); } /// <summary> @@ -2795,7 +2795,7 @@ namespace MediaBrowser.Controller.Entities { var list = GetEtagValues(user); - return string.Join("|", list).GetMD5().ToString("N", CultureInfo.InvariantCulture); + return string.Join('|', list).GetMD5().ToString("N", CultureInfo.InvariantCulture); } protected virtual List<string> GetEtagValues(User user) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 1a379074d..a410c1b66 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.Controller.Entities.TV return key; } - return key + "-" + string.Join("-", folders); + return key + "-" + string.Join('-', folders); } private static string GetUniqueSeriesKey(BaseItem series) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 07a9f5ba6..53a78a027 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -592,7 +592,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.IsVideoRequest && ((string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder)) - || (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) + || (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && (isD3d11vaDecoder || isSwDecoder)))) { if (isTonemappingSupported) @@ -1381,7 +1381,8 @@ namespace MediaBrowser.Controller.MediaEncoding var requestedProfile = requestedProfiles[0]; // strip spaces because they may be stripped out on the query string as well - if (!string.IsNullOrEmpty(videoStream.Profile) && !requestedProfiles.Contains(videoStream.Profile.Replace(" ", ""), StringComparer.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(videoStream.Profile) + && !requestedProfiles.Contains(videoStream.Profile.Replace(" ", "", StringComparison.Ordinal), StringComparer.OrdinalIgnoreCase)) { var currentScore = GetVideoProfileScore(videoStream.Profile); var requestedScore = GetVideoProfileScore(requestedProfile); @@ -1710,7 +1711,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (filters.Count > 0) { - return " -af \"" + string.Join(",", filters) + "\""; + return " -af \"" + string.Join(',', filters) + "\""; } return string.Empty; @@ -2888,7 +2889,7 @@ namespace MediaBrowser.Controller.MediaEncoding output += string.Format( CultureInfo.InvariantCulture, "{0}", - string.Join(",", filters)); + string.Join(',', filters)); } return output; @@ -2914,7 +2915,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (threads <= 0) { return 0; - } + } else if (threads >= Environment.ProcessorCount) { return Environment.ProcessorCount; @@ -3864,7 +3865,7 @@ namespace MediaBrowser.Controller.MediaEncoding GetInputArgument(state, encodingOptions), threads, " -vn", - string.Join(" ", audioTranscodeParams), + string.Join(' ', audioTranscodeParams), outputPath, string.Empty, string.Empty, diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 396206658..a337521c6 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -214,7 +214,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (item.LockedFields.Length > 0) { - writer.WriteElementString("LockedFields", string.Join("|", item.LockedFields)); + writer.WriteElementString("LockedFields", string.Join('|', item.LockedFields)); } if (item.CriticRating.HasValue) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index bd026bce1..b5291b560 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1496,7 +1496,7 @@ namespace MediaBrowser.MediaEncoding.Probing 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 } else { @@ -1508,7 +1508,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (subtitle.Contains('.', StringComparison.Ordinal)) { // skip the comment, keep the subtitle - description = string.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first } else { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 431cf0baf..a3983afe5 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1733,7 +1733,7 @@ namespace MediaBrowser.Model.Dlna if (condition.Condition == ProfileConditionType.Equals || condition.Condition == ProfileConditionType.EqualsAny) { - item.SetOption(qualifier, "profile", string.Join(",", values)); + item.SetOption(qualifier, "profile", string.Join(',', values)); } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 55b12ae81..4765052d5 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -193,12 +193,12 @@ namespace MediaBrowser.Model.Dlna continue; } - var encodedValue = pair.Value.Replace(" ", "%20"); + var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal); list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } - string queryString = string.Join("&", list.ToArray()); + string queryString = string.Join('&', list); return GetUrl(baseUrl, queryString); } @@ -238,11 +238,11 @@ namespace MediaBrowser.Model.Dlna string audioCodecs = item.AudioCodecs.Length == 0 ? string.Empty : - string.Join(",", item.AudioCodecs); + string.Join(',', item.AudioCodecs); string videoCodecs = item.VideoCodecs.Length == 0 ? string.Empty : - string.Join(",", item.VideoCodecs); + string.Join(',', item.VideoCodecs); list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); @@ -322,7 +322,7 @@ namespace MediaBrowser.Model.Dlna string subtitleCodecs = item.SubtitleCodecs.Length == 0 ? string.Empty : - string.Join(",", item.SubtitleCodecs); + string.Join(',', item.SubtitleCodecs); list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); @@ -351,12 +351,12 @@ namespace MediaBrowser.Model.Dlna } // strip spaces to avoid having to encode h264 profile names - list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", ""))); + list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal))); } if (!item.IsDirectStream) { - list.Add(new NameValuePair("TranscodeReasons", string.Join(",", item.TranscodeReasons.Distinct().Select(i => i.ToString())))); + list.Add(new NameValuePair("TranscodeReasons", string.Join(',', item.TranscodeReasons.Distinct().Select(i => i.ToString())))); } return list; diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index ca0b93c30..d85a8cde9 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -211,7 +211,7 @@ namespace MediaBrowser.Model.Entities return result.ToString(); } - return string.Join(" ", attributes); + return string.Join(' ', attributes); } case MediaStreamType.Subtitle: diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 9f22e618e..0edab3787 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -465,7 +465,7 @@ namespace MediaBrowser.XbmcMetadata.Savers if (item.LockedFields.Length > 0) { - writer.WriteElementString("lockedfields", string.Join("|", item.LockedFields)); + writer.WriteElementString("lockedfields", string.Join('|', item.LockedFields)); } writer.WriteElementString("dateadded", item.DateCreated.ToLocalTime().ToString(DateAddedFormat, CultureInfo.InvariantCulture)); -- cgit v1.2.3 From 141efafd3dbbef3dc64824a89fd3fdc77da0b25e Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 20 Feb 2021 23:13:04 +0100 Subject: Enable TreatWarningsAsErrors for MediaBrowser.Model --- Emby.Dlna/ContentDirectory/StubType.cs | 2 +- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/PlayTo/TransportState.cs | 2 +- .../Data/SqliteItemRepository.cs | 6 +- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 2 +- .../Probing/ProbeResultNormalizer.cs | 6 +- MediaBrowser.Model/Channels/ChannelFeatures.cs | 18 +- MediaBrowser.Model/Channels/ChannelQuery.cs | 6 +- .../Configuration/EncodingOptions.cs | 74 +- MediaBrowser.Model/Configuration/ImageOption.cs | 10 +- MediaBrowser.Model/Configuration/LibraryOptions.cs | 403 +------ MediaBrowser.Model/Configuration/MediaPathInfo.cs | 12 + .../Configuration/MetadataConfiguration.cs | 4 +- .../Configuration/MetadataOptions.cs | 20 +- .../Configuration/MetadataPluginSummary.cs | 12 +- MediaBrowser.Model/Configuration/TypeOptions.cs | 365 ++++++ .../Configuration/UserConfiguration.cs | 36 +- .../Configuration/XbmcMetadataOptions.cs | 16 +- MediaBrowser.Model/Dlna/AudioOptions.cs | 9 +- MediaBrowser.Model/Dlna/CodecProfile.cs | 12 +- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 2 +- MediaBrowser.Model/Dlna/ContainerProfile.cs | 10 +- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 36 +- MediaBrowser.Model/Dlna/IDeviceDiscovery.cs | 1 + .../Dlna/MediaFormatProfileResolver.cs | 4 +- MediaBrowser.Model/Dlna/ResolutionConfiguration.cs | 8 +- MediaBrowser.Model/Dlna/ResponseProfile.cs | 10 +- MediaBrowser.Model/Dlna/SearchCriteria.cs | 54 +- MediaBrowser.Model/Dlna/SortCriteria.cs | 4 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 14 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 1190 ++++++++++---------- MediaBrowser.Model/Dto/BaseItemDto.cs | 10 +- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 67 +- MediaBrowser.Model/Dto/MetadataEditorInfo.cs | 18 +- MediaBrowser.Model/Dto/NameGuidPair.cs | 14 + MediaBrowser.Model/Dto/NameIdPair.cs | 7 - MediaBrowser.Model/Dto/UserDto.cs | 18 +- MediaBrowser.Model/Entities/CollectionType.cs | 32 - MediaBrowser.Model/Entities/MediaStream.cs | 197 ++-- MediaBrowser.Model/Entities/PackageReviewInfo.cs | 40 - MediaBrowser.Model/Entities/SpecialFolder.cs | 36 + MediaBrowser.Model/Entities/VirtualFolderInfo.cs | 16 +- MediaBrowser.Model/Globalization/CultureDto.cs | 12 +- MediaBrowser.Model/IO/IFileSystem.cs | 7 +- MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs | 16 +- MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs | 58 + MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs | 26 +- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 97 +- MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs | 10 +- MediaBrowser.Model/LiveTv/RecordingQuery.cs | 16 +- MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs | 16 +- MediaBrowser.Model/LiveTv/TunerHostInfo.cs | 38 + MediaBrowser.Model/MediaBrowser.Model.csproj | 4 +- MediaBrowser.Model/MediaInfo/MediaInfo.cs | 22 +- .../MediaInfo/PlaybackInfoRequest.cs | 22 +- .../MediaInfo/PlaybackInfoResponse.cs | 16 +- MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs | 4 +- MediaBrowser.Model/Net/ISocket.cs | 6 + MediaBrowser.Model/Net/ISocketFactory.cs | 3 + MediaBrowser.Model/Net/MimeTypes.cs | 21 +- MediaBrowser.Model/Net/NetworkShare.cs | 33 - MediaBrowser.Model/Net/SocketReceiveResult.cs | 4 +- MediaBrowser.Model/Net/WebSocketMessage.cs | 2 +- .../Notifications/NotificationOptions.cs | 10 +- .../Notifications/NotificationRequest.cs | 14 +- MediaBrowser.Model/Providers/ExternalIdInfo.cs | 4 +- MediaBrowser.Model/Providers/RemoteImageInfo.cs | 2 +- MediaBrowser.Model/Providers/SubtitleOptions.cs | 16 +- MediaBrowser.Model/Querying/EpisodeQuery.cs | 10 +- MediaBrowser.Model/Querying/LatestItemsQuery.cs | 9 +- .../Querying/MovieRecommendationQuery.cs | 14 +- MediaBrowser.Model/Querying/NextUpQuery.cs | 20 +- MediaBrowser.Model/Querying/QueryFilters.cs | 25 +- MediaBrowser.Model/Querying/QueryFiltersLegacy.cs | 26 + MediaBrowser.Model/Querying/QueryResult.cs | 26 +- .../Querying/UpcomingEpisodesQuery.cs | 16 +- MediaBrowser.Model/Search/SearchQuery.cs | 32 +- MediaBrowser.Model/Session/BrowseRequest.cs | 1 + MediaBrowser.Model/Session/ClientCapabilities.cs | 14 +- MediaBrowser.Model/Session/GeneralCommand.cs | 13 +- MediaBrowser.Model/Session/PlaybackProgressInfo.cs | 14 - MediaBrowser.Model/Session/PlaystateCommand.cs | 6 +- MediaBrowser.Model/Session/QueueItem.cs | 14 + MediaBrowser.Model/Session/RepeatMode.cs | 11 + MediaBrowser.Model/Session/TranscodeReason.cs | 31 + MediaBrowser.Model/Session/TranscodingInfo.cs | 37 +- MediaBrowser.Model/Sync/SyncJob.cs | 10 +- MediaBrowser.Model/System/SystemInfo.cs | 18 +- MediaBrowser.Model/System/WakeOnLanInfo.cs | 2 +- MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs | 5 +- MediaBrowser.Model/Tasks/ITaskManager.cs | 20 +- MediaBrowser.Model/Tasks/ITaskTrigger.cs | 4 + MediaBrowser.Model/Tasks/TaskInfo.cs | 16 +- MediaBrowser.Model/Tasks/TaskTriggerInfo.cs | 12 +- MediaBrowser.Model/Users/UserPolicy.cs | 100 +- jellyfin.ruleset | 2 + tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs | 6 - 98 files changed, 1908 insertions(+), 1892 deletions(-) create mode 100644 MediaBrowser.Model/Configuration/MediaPathInfo.cs create mode 100644 MediaBrowser.Model/Configuration/TypeOptions.cs create mode 100644 MediaBrowser.Model/Dto/NameGuidPair.cs delete mode 100644 MediaBrowser.Model/Entities/PackageReviewInfo.cs create mode 100644 MediaBrowser.Model/Entities/SpecialFolder.cs create mode 100644 MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs create mode 100644 MediaBrowser.Model/LiveTv/TunerHostInfo.cs delete mode 100644 MediaBrowser.Model/Net/NetworkShare.cs create mode 100644 MediaBrowser.Model/Querying/QueryFiltersLegacy.cs create mode 100644 MediaBrowser.Model/Session/QueueItem.cs create mode 100644 MediaBrowser.Model/Session/RepeatMode.cs create mode 100644 MediaBrowser.Model/Session/TranscodeReason.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/ContentDirectory/StubType.cs b/Emby.Dlna/ContentDirectory/StubType.cs index 982ae5d68..a5116055d 100644 --- a/Emby.Dlna/ContentDirectory/StubType.cs +++ b/Emby.Dlna/ContentDirectory/StubType.cs @@ -1,5 +1,5 @@ #pragma warning disable CS1591 -#pragma warning disable SA1602 + namespace Emby.Dlna.ContentDirectory { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 21ba1c755..9ab324038 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -553,7 +553,7 @@ namespace Emby.Dlna private void DumpProfiles() { - DeviceProfile[] list = new [] + DeviceProfile[] list = new[] { new SamsungSmartTvProfile(), new XboxOneProfile(), diff --git a/Emby.Dlna/PlayTo/TransportState.cs b/Emby.Dlna/PlayTo/TransportState.cs index 7068a5d24..1ca71283a 100644 --- a/Emby.Dlna/PlayTo/TransportState.cs +++ b/Emby.Dlna/PlayTo/TransportState.cs @@ -1,5 +1,5 @@ #pragma warning disable CS1591 -#pragma warning disable SA1602 + namespace Emby.Dlna.PlayTo { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index dad8bec7b..d78b93bd7 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -6207,9 +6207,9 @@ AND Type = @InternalPersonType)"); if (item.Type == MediaStreamType.Subtitle) { - item.localizedUndefined = _localization.GetLocalizedString("Undefined"); - item.localizedDefault = _localization.GetLocalizedString("Default"); - item.localizedForced = _localization.GetLocalizedString("Forced"); + item.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); + item.LocalizedDefault = _localization.GetLocalizedString("Default"); + item.LocalizedForced = _localization.GetLocalizedString("Forced"); } return item; diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 0d8315dee..ce6740fc9 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -523,7 +523,7 @@ namespace Jellyfin.Api.Helpers /// <param name="type">Dlna profile type.</param> public void NormalizeMediaSourceContainer(MediaSourceInfo mediaSource, DeviceProfile profile, DlnaProfileType type) { - mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, mediaSource.Path, profile, type); + mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, profile, type); } private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string accessToken) diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 4957ee8b8..8df1f5c27 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Helpers if (string.IsNullOrEmpty(containerInternal)) { containerInternal = streamingRequest.Static ? - StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, state.MediaPath, null, DlnaProfileType.Audio) + StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, null, DlnaProfileType.Audio) : GetOutputFileExtension(state); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index b5291b560..b9cb49cf2 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -681,9 +681,9 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.Type = MediaStreamType.Subtitle; stream.Codec = NormalizeSubtitleCodec(stream.Codec); - stream.localizedUndefined = _localization.GetLocalizedString("Undefined"); - stream.localizedDefault = _localization.GetLocalizedString("Default"); - stream.localizedForced = _localization.GetLocalizedString("Forced"); + stream.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); + stream.LocalizedDefault = _localization.GetLocalizedString("Default"); + stream.LocalizedForced = _localization.GetLocalizedString("Forced"); } else if (string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Channels/ChannelFeatures.cs b/MediaBrowser.Model/Channels/ChannelFeatures.cs index a55754edd..d925b78b6 100644 --- a/MediaBrowser.Model/Channels/ChannelFeatures.cs +++ b/MediaBrowser.Model/Channels/ChannelFeatures.cs @@ -7,6 +7,13 @@ namespace MediaBrowser.Model.Channels { public class ChannelFeatures { + public ChannelFeatures() + { + MediaTypes = Array.Empty<ChannelMediaType>(); + ContentTypes = Array.Empty<ChannelMediaContentType>(); + DefaultSortFields = Array.Empty<ChannelItemSortField>(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -38,7 +45,7 @@ namespace MediaBrowser.Model.Channels public ChannelMediaContentType[] ContentTypes { get; set; } /// <summary> - /// Represents the maximum number of records the channel allows retrieving at a time. + /// Gets or sets the maximum number of records the channel allows retrieving at a time. /// </summary> public int? MaxPageSize { get; set; } @@ -55,7 +62,7 @@ namespace MediaBrowser.Model.Channels public ChannelItemSortField[] DefaultSortFields { get; set; } /// <summary> - /// Indicates if a sort ascending/descending toggle is supported or not. + /// Gets or sets a value indicating whether a sort ascending/descending toggle is supported. /// </summary> public bool SupportsSortOrderToggle { get; set; } @@ -76,12 +83,5 @@ namespace MediaBrowser.Model.Channels /// </summary> /// <value><c>true</c> if [supports content downloading]; otherwise, <c>false</c>.</value> public bool SupportsContentDownloading { get; set; } - - public ChannelFeatures() - { - MediaTypes = Array.Empty<ChannelMediaType>(); - ContentTypes = Array.Empty<ChannelMediaContentType>(); - DefaultSortFields = Array.Empty<ChannelItemSortField>(); - } } } diff --git a/MediaBrowser.Model/Channels/ChannelQuery.cs b/MediaBrowser.Model/Channels/ChannelQuery.cs index fd90e7f06..59966127f 100644 --- a/MediaBrowser.Model/Channels/ChannelQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelQuery.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Channels public class ChannelQuery { /// <summary> - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } @@ -28,13 +28,13 @@ namespace MediaBrowser.Model.Channels public Guid UserId { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index da467e133..a9b280301 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -5,6 +5,41 @@ namespace MediaBrowser.Model.Configuration { public class EncodingOptions { + public EncodingOptions() + { + EnableFallbackFont = false; + DownMixAudioBoost = 2; + MaxMuxingQueueSize = 2048; + EnableThrottling = false; + ThrottleDelaySeconds = 180; + EncodingThreadCount = -1; + // This is a DRM device that is almost guaranteed to be there on every intel platform, + // plus it's the default one in ffmpeg if you don't specify anything + VaapiDevice = "/dev/dri/renderD128"; + // This is the OpenCL device that is used for tonemapping. + // The left side of the dot is the platform number, and the right side is the device number on the platform. + OpenclDevice = "0.0"; + EnableTonemapping = false; + EnableVppTonemapping = false; + TonemappingAlgorithm = "hable"; + TonemappingRange = "auto"; + TonemappingDesat = 0; + TonemappingThreshold = 0.8; + TonemappingPeak = 100; + TonemappingParam = 0; + H264Crf = 23; + H265Crf = 28; + DeinterlaceDoubleRate = false; + DeinterlaceMethod = "yadif"; + EnableDecodingColorDepth10Hevc = true; + EnableDecodingColorDepth10Vp9 = true; + EnableEnhancedNvdecDecoder = true; + EnableHardwareEncoding = true; + AllowHevcEncoding = true; + EnableSubtitleExtraction = true; + HardwareDecodingCodecs = new string[] { "h264", "vc1" }; + } + public int EncodingThreadCount { get; set; } public string TranscodingTempPath { get; set; } @@ -24,12 +59,12 @@ namespace MediaBrowser.Model.Configuration public string HardwareAccelerationType { get; set; } /// <summary> - /// FFmpeg path as set by the user via the UI. + /// Gets or sets the FFmpeg path as set by the user via the UI. /// </summary> public string EncoderAppPath { get; set; } /// <summary> - /// The current FFmpeg path being used by the system and displayed on the transcode page. + /// Gets or sets the current FFmpeg path being used by the system and displayed on the transcode page. /// </summary> public string EncoderAppPathDisplay { get; set; } @@ -76,40 +111,5 @@ namespace MediaBrowser.Model.Configuration public bool EnableSubtitleExtraction { get; set; } public string[] HardwareDecodingCodecs { get; set; } - - public EncodingOptions() - { - EnableFallbackFont = false; - DownMixAudioBoost = 2; - MaxMuxingQueueSize = 2048; - EnableThrottling = false; - ThrottleDelaySeconds = 180; - EncodingThreadCount = -1; - // This is a DRM device that is almost guaranteed to be there on every intel platform, - // plus it's the default one in ffmpeg if you don't specify anything - VaapiDevice = "/dev/dri/renderD128"; - // This is the OpenCL device that is used for tonemapping. - // The left side of the dot is the platform number, and the right side is the device number on the platform. - OpenclDevice = "0.0"; - EnableTonemapping = false; - EnableVppTonemapping = false; - TonemappingAlgorithm = "hable"; - TonemappingRange = "auto"; - TonemappingDesat = 0; - TonemappingThreshold = 0.8; - TonemappingPeak = 100; - TonemappingParam = 0; - H264Crf = 23; - H265Crf = 28; - DeinterlaceDoubleRate = false; - DeinterlaceMethod = "yadif"; - EnableDecodingColorDepth10Hevc = true; - EnableDecodingColorDepth10Vp9 = true; - EnableEnhancedNvdecDecoder = true; - EnableHardwareEncoding = true; - AllowHevcEncoding = true; - EnableSubtitleExtraction = true; - HardwareDecodingCodecs = new string[] { "h264", "vc1" }; - } } } diff --git a/MediaBrowser.Model/Configuration/ImageOption.cs b/MediaBrowser.Model/Configuration/ImageOption.cs index 2b1268c74..0af7b7e14 100644 --- a/MediaBrowser.Model/Configuration/ImageOption.cs +++ b/MediaBrowser.Model/Configuration/ImageOption.cs @@ -6,6 +6,11 @@ namespace MediaBrowser.Model.Configuration { public class ImageOption { + public ImageOption() + { + Limit = 1; + } + /// <summary> /// Gets or sets the type. /// </summary> @@ -23,10 +28,5 @@ namespace MediaBrowser.Model.Configuration /// </summary> /// <value>The minimum width.</value> public int MinWidth { get; set; } - - public ImageOption() - { - Limit = 1; - } } } diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 77ac11d69..24698360e 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -2,13 +2,30 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Model.Configuration { public class LibraryOptions { + public LibraryOptions() + { + TypeOptions = Array.Empty<TypeOptions>(); + DisabledSubtitleFetchers = Array.Empty<string>(); + SubtitleFetcherOrder = Array.Empty<string>(); + DisabledLocalMetadataReaders = Array.Empty<string>(); + + SkipSubtitlesIfAudioTrackMatches = true; + RequirePerfectSubtitleMatch = true; + + EnablePhotos = true; + SaveSubtitlesWithMedia = true; + EnableRealtimeMonitor = true; + PathInfos = Array.Empty<MediaPathInfo>(); + EnableInternetProviders = true; + EnableAutomaticSeriesGrouping = true; + SeasonZeroDisplayName = "Specials"; + } + public bool EnablePhotos { get; set; } public bool EnableRealtimeMonitor { get; set; } @@ -79,387 +96,5 @@ namespace MediaBrowser.Model.Configuration return null; } - - public LibraryOptions() - { - TypeOptions = Array.Empty<TypeOptions>(); - DisabledSubtitleFetchers = Array.Empty<string>(); - SubtitleFetcherOrder = Array.Empty<string>(); - DisabledLocalMetadataReaders = Array.Empty<string>(); - - SkipSubtitlesIfAudioTrackMatches = true; - RequirePerfectSubtitleMatch = true; - - EnablePhotos = true; - SaveSubtitlesWithMedia = true; - EnableRealtimeMonitor = true; - PathInfos = Array.Empty<MediaPathInfo>(); - EnableInternetProviders = true; - EnableAutomaticSeriesGrouping = true; - SeasonZeroDisplayName = "Specials"; - } - } - - public class MediaPathInfo - { - public string Path { get; set; } - - public string NetworkPath { get; set; } - } - - public class TypeOptions - { - public string Type { get; set; } - - public string[] MetadataFetchers { get; set; } - - public string[] MetadataFetcherOrder { get; set; } - - public string[] ImageFetchers { get; set; } - - public string[] ImageFetcherOrder { get; set; } - - public ImageOption[] ImageOptions { get; set; } - - public ImageOption GetImageOptions(ImageType type) - { - foreach (var i in ImageOptions) - { - if (i.Type == type) - { - return i; - } - } - - if (DefaultImageOptions.TryGetValue(Type, out ImageOption[] options)) - { - foreach (var i in options) - { - if (i.Type == type) - { - return i; - } - } - } - - return DefaultInstance; - } - - public int GetLimit(ImageType type) - { - return GetImageOptions(type).Limit; - } - - public int GetMinWidth(ImageType type) - { - return GetImageOptions(type).MinWidth; - } - - public bool IsEnabled(ImageType type) - { - return GetLimit(type) > 0; - } - - public TypeOptions() - { - MetadataFetchers = Array.Empty<string>(); - MetadataFetcherOrder = Array.Empty<string>(); - ImageFetchers = Array.Empty<string>(); - ImageFetcherOrder = Array.Empty<string>(); - ImageOptions = Array.Empty<ImageOption>(); - } - - public static Dictionary<string, ImageOption[]> DefaultImageOptions = new Dictionary<string, ImageOption[]> - { - { - "Movie", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "MusicVideo", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "Series", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "MusicAlbum", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - } - } - }, - { - "MusicArtist", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - // Don't download this by default - // They do look great, but most artists won't have them, which means a banner view isn't really possible - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - // Don't download this by default - // Generally not used - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - } - } - }, - { - "BoxSet", new [] - { - new ImageOption - { - Limit = 1, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Thumb - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Logo - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Art - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Disc - }, - - // Don't download this by default as it's rarely used. - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - } - } - }, - { - "Season", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Banner - }, - - new ImageOption - { - Limit = 0, - Type = ImageType.Thumb - } - } - }, - { - "Episode", new [] - { - new ImageOption - { - Limit = 0, - MinWidth = 1280, - Type = ImageType.Backdrop - }, - - new ImageOption - { - Limit = 1, - Type = ImageType.Primary - } - } - } - }; - - public static ImageOption DefaultInstance = new ImageOption(); } } diff --git a/MediaBrowser.Model/Configuration/MediaPathInfo.cs b/MediaBrowser.Model/Configuration/MediaPathInfo.cs new file mode 100644 index 000000000..4f311c58f --- /dev/null +++ b/MediaBrowser.Model/Configuration/MediaPathInfo.cs @@ -0,0 +1,12 @@ +#nullable disable +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Configuration +{ + public class MediaPathInfo + { + public string Path { get; set; } + + public string NetworkPath { get; set; } + } +} diff --git a/MediaBrowser.Model/Configuration/MetadataConfiguration.cs b/MediaBrowser.Model/Configuration/MetadataConfiguration.cs index 706831bdd..be044243d 100644 --- a/MediaBrowser.Model/Configuration/MetadataConfiguration.cs +++ b/MediaBrowser.Model/Configuration/MetadataConfiguration.cs @@ -4,11 +4,11 @@ namespace MediaBrowser.Model.Configuration { public class MetadataConfiguration { - public bool UseFileCreationTimeForDateAdded { get; set; } - public MetadataConfiguration() { UseFileCreationTimeForDateAdded = true; } + + public bool UseFileCreationTimeForDateAdded { get; set; } } } diff --git a/MediaBrowser.Model/Configuration/MetadataOptions.cs b/MediaBrowser.Model/Configuration/MetadataOptions.cs index e7dc3da3c..76b72bd08 100644 --- a/MediaBrowser.Model/Configuration/MetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/MetadataOptions.cs @@ -10,6 +10,16 @@ namespace MediaBrowser.Model.Configuration /// </summary> public class MetadataOptions { + public MetadataOptions() + { + DisabledMetadataSavers = Array.Empty<string>(); + LocalMetadataReaderOrder = Array.Empty<string>(); + DisabledMetadataFetchers = Array.Empty<string>(); + MetadataFetcherOrder = Array.Empty<string>(); + DisabledImageFetchers = Array.Empty<string>(); + ImageFetcherOrder = Array.Empty<string>(); + } + public string ItemType { get; set; } public string[] DisabledMetadataSavers { get; set; } @@ -23,15 +33,5 @@ namespace MediaBrowser.Model.Configuration public string[] DisabledImageFetchers { get; set; } public string[] ImageFetcherOrder { get; set; } - - public MetadataOptions() - { - DisabledMetadataSavers = Array.Empty<string>(); - LocalMetadataReaderOrder = Array.Empty<string>(); - DisabledMetadataFetchers = Array.Empty<string>(); - MetadataFetcherOrder = Array.Empty<string>(); - DisabledImageFetchers = Array.Empty<string>(); - ImageFetcherOrder = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs index 0c197ee02..aa07d6623 100644 --- a/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs +++ b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs @@ -8,6 +8,12 @@ namespace MediaBrowser.Model.Configuration { public class MetadataPluginSummary { + public MetadataPluginSummary() + { + SupportedImageTypes = Array.Empty<ImageType>(); + Plugins = Array.Empty<MetadataPlugin>(); + } + /// <summary> /// Gets or sets the type of the item. /// </summary> @@ -25,11 +31,5 @@ namespace MediaBrowser.Model.Configuration /// </summary> /// <value>The supported image types.</value> public ImageType[] SupportedImageTypes { get; set; } - - public MetadataPluginSummary() - { - SupportedImageTypes = Array.Empty<ImageType>(); - Plugins = Array.Empty<MetadataPlugin>(); - } } } diff --git a/MediaBrowser.Model/Configuration/TypeOptions.cs b/MediaBrowser.Model/Configuration/TypeOptions.cs new file mode 100644 index 000000000..d0179e5aa --- /dev/null +++ b/MediaBrowser.Model/Configuration/TypeOptions.cs @@ -0,0 +1,365 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Model.Configuration +{ + public class TypeOptions + { + public static readonly ImageOption DefaultInstance = new ImageOption(); + + public static readonly Dictionary<string, ImageOption[]> DefaultImageOptions = new Dictionary<string, ImageOption[]> + { + { + "Movie", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "MusicVideo", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "Series", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "MusicAlbum", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + } + } + }, + { + "MusicArtist", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + // Don't download this by default + // They do look great, but most artists won't have them, which means a banner view isn't really possible + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + // Don't download this by default + // Generally not used + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + } + } + }, + { + "BoxSet", new[] + { + new ImageOption + { + Limit = 1, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Thumb + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Logo + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Art + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Disc + }, + + // Don't download this by default as it's rarely used. + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + } + } + }, + { + "Season", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Banner + }, + + new ImageOption + { + Limit = 0, + Type = ImageType.Thumb + } + } + }, + { + "Episode", new[] + { + new ImageOption + { + Limit = 0, + MinWidth = 1280, + Type = ImageType.Backdrop + }, + + new ImageOption + { + Limit = 1, + Type = ImageType.Primary + } + } + } + }; + + public TypeOptions() + { + MetadataFetchers = Array.Empty<string>(); + MetadataFetcherOrder = Array.Empty<string>(); + ImageFetchers = Array.Empty<string>(); + ImageFetcherOrder = Array.Empty<string>(); + ImageOptions = Array.Empty<ImageOption>(); + } + + public string Type { get; set; } + + public string[] MetadataFetchers { get; set; } + + public string[] MetadataFetcherOrder { get; set; } + + public string[] ImageFetchers { get; set; } + + public string[] ImageFetcherOrder { get; set; } + + public ImageOption[] ImageOptions { get; set; } + + public ImageOption GetImageOptions(ImageType type) + { + foreach (var i in ImageOptions) + { + if (i.Type == type) + { + return i; + } + } + + if (DefaultImageOptions.TryGetValue(Type, out ImageOption[] options)) + { + foreach (var i in options) + { + if (i.Type == type) + { + return i; + } + } + } + + return DefaultInstance; + } + + public int GetLimit(ImageType type) + { + return GetImageOptions(type).Limit; + } + + public int GetMinWidth(ImageType type) + { + return GetImageOptions(type).MinWidth; + } + + public bool IsEnabled(ImageType type) + { + return GetLimit(type) > 0; + } + } +} diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index cc0e0c468..935e6cbe1 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -11,6 +11,24 @@ namespace MediaBrowser.Model.Configuration /// </summary> public class UserConfiguration { + /// <summary> + /// Initializes a new instance of the <see cref="UserConfiguration" /> class. + /// </summary> + public UserConfiguration() + { + EnableNextEpisodeAutoPlay = true; + RememberAudioSelections = true; + RememberSubtitleSelections = true; + + HidePlayedInLatest = true; + PlayDefaultAudioTrack = true; + + LatestItemsExcludes = Array.Empty<string>(); + OrderedViews = Array.Empty<string>(); + MyMediaExcludes = Array.Empty<string>(); + GroupedFolders = Array.Empty<string>(); + } + /// <summary> /// Gets or sets the audio language preference. /// </summary> @@ -52,23 +70,5 @@ namespace MediaBrowser.Model.Configuration public bool RememberSubtitleSelections { get; set; } public bool EnableNextEpisodeAutoPlay { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="UserConfiguration" /> class. - /// </summary> - public UserConfiguration() - { - EnableNextEpisodeAutoPlay = true; - RememberAudioSelections = true; - RememberSubtitleSelections = true; - - HidePlayedInLatest = true; - PlayDefaultAudioTrack = true; - - LatestItemsExcludes = Array.Empty<string>(); - OrderedViews = Array.Empty<string>(); - MyMediaExcludes = Array.Empty<string>(); - GroupedFolders = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs index 4d5f996f8..8ad070dcb 100644 --- a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -5,6 +5,14 @@ namespace MediaBrowser.Model.Configuration { public class XbmcMetadataOptions { + public XbmcMetadataOptions() + { + ReleaseDateFormat = "yyyy-MM-dd"; + + SaveImagePathsInNfo = true; + EnablePathSubstitution = true; + } + public string UserId { get; set; } public string ReleaseDateFormat { get; set; } @@ -14,13 +22,5 @@ namespace MediaBrowser.Model.Configuration public bool EnablePathSubstitution { get; set; } public bool EnableExtraThumbsDuplication { get; set; } - - public XbmcMetadataOptions() - { - ReleaseDateFormat = "yyyy-MM-dd"; - - SaveImagePathsInNfo = true; - EnablePathSubstitution = true; - } } } diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index bbb8bf426..4d4d8d78c 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -34,20 +34,20 @@ namespace MediaBrowser.Model.Dlna public DeviceProfile Profile { get; set; } /// <summary> - /// Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested. + /// Gets or sets a media source id. Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested. /// </summary> public string MediaSourceId { get; set; } public string DeviceId { get; set; } /// <summary> - /// Allows an override of supported number of audio channels - /// Example: DeviceProfile supports five channel, but user only has stereo speakers + /// Gets or sets an override of supported number of audio channels + /// Example: DeviceProfile supports five channel, but user only has stereo speakers. /// </summary> public int? MaxAudioChannels { get; set; } /// <summary> - /// The application's configured quality setting. + /// Gets or sets the application's configured quality setting. /// </summary> public int? MaxBitrate { get; set; } @@ -66,6 +66,7 @@ namespace MediaBrowser.Model.Dlna /// <summary> /// Gets the maximum bitrate. /// </summary> + /// <param name="isAudio">Whether or not this is audio.</param> /// <returns>System.Nullable<System.Int32>.</returns> public int? GetMaxBitrate(bool isAudio) { diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index d4fd3e673..8343cf028 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -9,6 +9,12 @@ namespace MediaBrowser.Model.Dlna { public class CodecProfile { + public CodecProfile() + { + Conditions = Array.Empty<ProfileCondition>(); + ApplyConditions = Array.Empty<ProfileCondition>(); + } + [XmlAttribute("type")] public CodecType Type { get; set; } @@ -22,12 +28,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("container")] public string Container { get; set; } - public CodecProfile() - { - Conditions = Array.Empty<ProfileCondition>(); - ApplyConditions = Array.Empty<ProfileCondition>(); - } - public string[] GetCodecs() { return ContainerProfile.SplitValue(Codec); diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index faf1ee41b..55c4dd074 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -1,8 +1,8 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Globalization; +using System.Linq; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 56c89d854..d83c8f2f3 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -9,6 +9,11 @@ namespace MediaBrowser.Model.Dlna { public class ContainerProfile { + public ContainerProfile() + { + Conditions = Array.Empty<ProfileCondition>(); + } + [XmlAttribute("type")] public DlnaProfileType Type { get; set; } @@ -17,11 +22,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("container")] public string Container { get; set; } - public ContainerProfile() - { - Conditions = Array.Empty<ProfileCondition>(); - } - public string[] GetContainers() { return SplitValue(Container); diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 50e3374f7..ec106f105 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -81,13 +81,13 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.DlnaV15; // if (isDirectStream) - //{ - // flagValue = flagValue | DlnaFlags.ByteBasedSeek; - //} - // else if (runtimeTicks.HasValue) - //{ - // flagValue = flagValue | DlnaFlags.TimeBasedSeek; - //} + // { + // flagValue = flagValue | DlnaFlags.ByteBasedSeek; + // } + // else if (runtimeTicks.HasValue) + // { + // flagValue = flagValue | DlnaFlags.TimeBasedSeek; + // } string dlnaflags = string.Format( CultureInfo.InvariantCulture, @@ -150,16 +150,18 @@ namespace MediaBrowser.Model.Dlna DlnaFlags.DlnaV15; // if (isDirectStream) - //{ - // flagValue = flagValue | DlnaFlags.ByteBasedSeek; - //} - // else if (runtimeTicks.HasValue) - //{ - // flagValue = flagValue | DlnaFlags.TimeBasedSeek; - //} - - string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}", - DlnaMaps.FlagsToString(flagValue)); + // { + // flagValue = flagValue | DlnaFlags.ByteBasedSeek; + // } + // else if (runtimeTicks.HasValue) + // { + // flagValue = flagValue | DlnaFlags.TimeBasedSeek; + // } + + string dlnaflags = string.Format( + CultureInfo.InvariantCulture, + ";DLNA.ORG_FLAGS={0}", + DlnaMaps.FlagsToString(flagValue)); ResponseProfile mediaProfile = _profile.GetVideoMediaProfile( container, diff --git a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs index 05209e53d..086088dea 100644 --- a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs +++ b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Model.Dlna public interface IDeviceDiscovery { event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceDiscovered; + event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceLeft; } } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 3c955989a..f61b8d59e 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -57,7 +57,6 @@ namespace MediaBrowser.Model.Dlna string.Equals(container, "mpegts", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "m2ts", StringComparison.OrdinalIgnoreCase)) { - return ResolveVideoMPEG2TSFormat(videoCodec, audioCodec, width, height, timestampType); } @@ -323,7 +322,6 @@ namespace MediaBrowser.Model.Dlna if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase) && (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "wmapro", StringComparison.OrdinalIgnoreCase))) { - if (width.HasValue && height.HasValue) { if ((width.Value <= 720) && (height.Value <= 576)) @@ -479,7 +477,9 @@ namespace MediaBrowser.Model.Dlna { if (string.Equals(container, "jpeg", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "jpg", StringComparison.OrdinalIgnoreCase)) + { return ResolveImageJPGFormat(width, height); + } if (string.Equals(container, "png", StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs b/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs index 30c44fbe0..f8f76c69d 100644 --- a/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs +++ b/MediaBrowser.Model/Dlna/ResolutionConfiguration.cs @@ -4,14 +4,14 @@ namespace MediaBrowser.Model.Dlna { public class ResolutionConfiguration { - public int MaxWidth { get; set; } - - public int MaxBitrate { get; set; } - public ResolutionConfiguration(int maxWidth, int maxBitrate) { MaxWidth = maxWidth; MaxBitrate = maxBitrate; } + + public int MaxWidth { get; set; } + + public int MaxBitrate { get; set; } } } diff --git a/MediaBrowser.Model/Dlna/ResponseProfile.cs b/MediaBrowser.Model/Dlna/ResponseProfile.cs index 48f53f06c..bf9661f7f 100644 --- a/MediaBrowser.Model/Dlna/ResponseProfile.cs +++ b/MediaBrowser.Model/Dlna/ResponseProfile.cs @@ -8,6 +8,11 @@ namespace MediaBrowser.Model.Dlna { public class ResponseProfile { + public ResponseProfile() + { + Conditions = Array.Empty<ProfileCondition>(); + } + [XmlAttribute("container")] public string Container { get; set; } @@ -28,11 +33,6 @@ namespace MediaBrowser.Model.Dlna public ProfileCondition[] Conditions { get; set; } - public ResponseProfile() - { - Conditions = Array.Empty<ProfileCondition>(); - } - public string[] GetContainers() { return ContainerProfile.SplitValue(Container); diff --git a/MediaBrowser.Model/Dlna/SearchCriteria.cs b/MediaBrowser.Model/Dlna/SearchCriteria.cs index 94f5bd3db..b1fc48c08 100644 --- a/MediaBrowser.Model/Dlna/SearchCriteria.cs +++ b/MediaBrowser.Model/Dlna/SearchCriteria.cs @@ -7,31 +7,6 @@ namespace MediaBrowser.Model.Dlna { public class SearchCriteria { - public SearchType SearchType { get; set; } - - /// <summary> - /// Splits the specified string. - /// </summary> - /// <param name="str">The string.</param> - /// <param name="term">The term.</param> - /// <param name="limit">The limit.</param> - /// <returns>System.String[].</returns> - private static string[] RegexSplit(string str, string term, int limit) - { - return new Regex(term).Split(str, limit); - } - - /// <summary> - /// Splits the specified string. - /// </summary> - /// <param name="str">The string.</param> - /// <param name="term">The term.</param> - /// <returns>System.String[].</returns> - private static string[] RegexSplit(string str, string term) - { - return Regex.Split(str, term, RegexOptions.IgnoreCase); - } - public SearchCriteria(string search) { if (search.Length == 0) @@ -48,8 +23,8 @@ namespace MediaBrowser.Model.Dlna if (subFactors.Length == 3) { - if (string.Equals("upnp:class", subFactors[0], StringComparison.OrdinalIgnoreCase) && - (string.Equals("=", subFactors[1], StringComparison.Ordinal) || string.Equals("derivedfrom", subFactors[1], StringComparison.OrdinalIgnoreCase))) + if (string.Equals("upnp:class", subFactors[0], StringComparison.OrdinalIgnoreCase) + && (string.Equals("=", subFactors[1], StringComparison.Ordinal) || string.Equals("derivedfrom", subFactors[1], StringComparison.OrdinalIgnoreCase))) { if (string.Equals("\"object.item.imageItem\"", subFactors[2], StringComparison.Ordinal) || string.Equals("\"object.item.imageItem.photo\"", subFactors[2], StringComparison.OrdinalIgnoreCase)) { @@ -71,5 +46,30 @@ namespace MediaBrowser.Model.Dlna } } } + + public SearchType SearchType { get; set; } + + /// <summary> + /// Splits the specified string. + /// </summary> + /// <param name="str">The string.</param> + /// <param name="term">The term.</param> + /// <param name="limit">The limit.</param> + /// <returns>System.String[].</returns> + private static string[] RegexSplit(string str, string term, int limit) + { + return new Regex(term).Split(str, limit); + } + + /// <summary> + /// Splits the specified string. + /// </summary> + /// <param name="str">The string.</param> + /// <param name="term">The term.</param> + /// <returns>System.String[].</returns> + private static string[] RegexSplit(string str, string term) + { + return Regex.Split(str, term, RegexOptions.IgnoreCase); + } } } diff --git a/MediaBrowser.Model/Dlna/SortCriteria.cs b/MediaBrowser.Model/Dlna/SortCriteria.cs index 53e4540cb..7769d0bd3 100644 --- a/MediaBrowser.Model/Dlna/SortCriteria.cs +++ b/MediaBrowser.Model/Dlna/SortCriteria.cs @@ -6,10 +6,10 @@ namespace MediaBrowser.Model.Dlna { public class SortCriteria { - public SortOrder SortOrder => SortOrder.Ascending; - public SortCriteria(string value) { } + + public SortOrder SortOrder => SortOrder.Ascending; } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a3983afe5..bf33691c7 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -227,7 +227,7 @@ namespace MediaBrowser.Model.Dlna } } - public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, string _, DeviceProfile profile, DlnaProfileType type) + public static string NormalizeMediaSourceFormatIntoSingleContainer(string inputContainer, DeviceProfile profile, DlnaProfileType type) { if (string.IsNullOrEmpty(inputContainer)) { @@ -274,14 +274,14 @@ namespace MediaBrowser.Model.Dlna if (options.ForceDirectPlay) { playlistItem.PlayMethod = PlayMethod.DirectPlay; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } if (options.ForceDirectStream) { playlistItem.PlayMethod = PlayMethod.DirectStream; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -349,7 +349,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.PlayMethod = PlayMethod.DirectStream; } - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Audio); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Audio); return playlistItem; } @@ -698,7 +698,7 @@ namespace MediaBrowser.Model.Dlna if (directPlay != null) { playlistItem.PlayMethod = directPlay.Value; - playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, item.Path, options.Profile, DlnaProfileType.Video); + playlistItem.Container = NormalizeMediaSourceFormatIntoSingleContainer(item.Container, options.Profile, DlnaProfileType.Video); if (subtitleStream != null) { @@ -1404,7 +1404,9 @@ namespace MediaBrowser.Model.Dlna { _logger.LogInformation( "Bitrate exceeds {PlayBackMethod} limit: media bitrate: {MediaBitrate}, max bitrate: {MaxBitrate}", - playMethod, itemBitrate, requestedMaxBitrate); + playMethod, + itemBitrate, + requestedMaxBitrate); return false; } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 4765052d5..f7010dcd0 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -27,45 +27,6 @@ namespace MediaBrowser.Model.Dlna StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } - public void SetOption(string qualifier, string name, string value) - { - if (string.IsNullOrEmpty(qualifier)) - { - SetOption(name, value); - } - else - { - SetOption(qualifier + "-" + name, value); - } - } - - public void SetOption(string name, string value) - { - StreamOptions[name] = value; - } - - public string GetOption(string qualifier, string name) - { - var value = GetOption(qualifier + "-" + name); - - if (string.IsNullOrEmpty(value)) - { - value = GetOption(name); - } - - return value; - } - - public string GetOption(string name) - { - if (StreamOptions.TryGetValue(name, out var value)) - { - return value; - } - - return null; - } - public Guid ItemId { get; set; } public PlayMethod PlayMethod { get; set; } @@ -152,887 +113,928 @@ namespace MediaBrowser.Model.Dlna PlayMethod == PlayMethod.DirectStream || PlayMethod == PlayMethod.DirectPlay; - public string ToUrl(string baseUrl, string accessToken) + /// <summary> + /// Gets the audio stream that will be used. + /// </summary> + public MediaStream TargetAudioStream { - if (PlayMethod == PlayMethod.DirectPlay) + get { - return MediaSource.Path; + if (MediaSource != null) + { + return MediaSource.GetDefaultAudioStream(AudioStreamIndex); + } + + return null; } + } - if (string.IsNullOrEmpty(baseUrl)) + /// <summary> + /// Gets the video stream that will be used. + /// </summary> + public MediaStream TargetVideoStream + { + get { - throw new ArgumentNullException(nameof(baseUrl)); + if (MediaSource != null) + { + return MediaSource.VideoStream; + } + + return null; } + } - var list = new List<string>(); - foreach (NameValuePair pair in BuildParams(this, accessToken)) + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public int? TargetAudioSampleRate + { + get { - if (string.IsNullOrEmpty(pair.Value)) + var stream = TargetAudioStream; + return AudioSampleRate.HasValue && !IsDirectStream + ? AudioSampleRate + : stream == null ? null : stream.SampleRate; + } + } + + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public int? TargetAudioBitDepth + { + get + { + if (IsDirectStream) { - continue; + return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; } - // Try to keep the url clean by omitting defaults - if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) + var targetAudioCodecs = TargetAudioCodec; + var audioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; + if (!string.IsNullOrEmpty(audioCodec)) { - continue; + return GetTargetAudioBitDepth(audioCodec); } - if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) + return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + } + } + + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public int? TargetVideoBitDepth + { + get + { + if (IsDirectStream) { - continue; + return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; } - // Be careful, IsDirectStream==true by default (Static != false or not in query). - // See initialization of StreamingRequestDto in AudioController.GetAudioStream() method : Static = @static ?? true. - if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && - string.Equals(pair.Value, "true", StringComparison.OrdinalIgnoreCase)) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - continue; + return GetTargetVideoBitDepth(videoCodec); } - var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal); - - list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); + return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; } - - string queryString = string.Join('&', list); - - return GetUrl(baseUrl, queryString); } - private string GetUrl(string baseUrl, string queryString) + /// <summary> + /// Gets the target reference frames. + /// </summary> + /// <value>The target reference frames.</value> + public int? TargetRefFrames { - if (string.IsNullOrEmpty(baseUrl)) + get { - throw new ArgumentNullException(nameof(baseUrl)); - } - - string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; - - baseUrl = baseUrl.TrimEnd('/'); + if (IsDirectStream) + { + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + } - if (MediaType == DlnaProfileType.Audio) - { - if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + return GetTargetRefFrames(videoCodec); } - return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; } + } - if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public float? TargetFramerate + { + get { - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); + var stream = TargetVideoStream; + return MaxFramerate.HasValue && !IsDirectStream + ? MaxFramerate + : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate; } - - return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - private static List<NameValuePair> BuildParams(StreamInfo item, string accessToken) + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public double? TargetVideoLevel { - var list = new List<NameValuePair>(); - - string audioCodecs = item.AudioCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.AudioCodecs); - - string videoCodecs = item.VideoCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.VideoCodecs); - - list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); - list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); - list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); - list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - list.Add(new NameValuePair("VideoCodec", videoCodecs)); - list.Add(new NameValuePair("AudioCodec", audioCodecs)); - list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - long startPositionTicks = item.StartPositionTicks; + get + { + if (IsDirectStream) + { + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + } - var isHls = string.Equals(item.SubProtocol, "hls", StringComparison.OrdinalIgnoreCase); + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) + { + return GetTargetVideoLevel(videoCodec); + } - if (isHls) - { - list.Add(new NameValuePair("StartTimeTicks", string.Empty)); + return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; } - else + } + + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public int? TargetPacketLength + { + get { - list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture))); + var stream = TargetVideoStream; + return !IsDirectStream + ? null + : stream == null ? null : stream.PacketLength; } + } - list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); - list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); - - string liveStreamId = item.MediaSource?.LiveStreamId; - list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); - - list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); - - if (!item.IsDirectStream) + /// <summary> + /// Gets the audio sample rate that will be in the output stream. + /// </summary> + public string TargetVideoProfile + { + get { - if (item.RequireNonAnamorphic) + if (IsDirectStream) { - list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + return TargetVideoStream == null ? null : TargetVideoStream.Profile; } - list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); - - if (item.EnableSubtitlesInManifest) + var targetVideoCodecs = TargetVideoCodec; + var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; + if (!string.IsNullOrEmpty(videoCodec)) { - list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.EnableMpegtsM2TsMode) - { - list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.EstimateContentLength) - { - list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto) - { - list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant())); - } - - if (item.CopyTimestamps) - { - list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); - } - - list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); - - string subtitleCodecs = item.SubtitleCodecs.Length == 0 ? - string.Empty : - string.Join(',', item.SubtitleCodecs); - - list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); - - if (isHls) - { - list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); - - if (item.SegmentLength.HasValue) - { - list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCulture))); - } - - if (item.MinSegments.HasValue) - { - list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))); - } - - list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture))); - } - - foreach (var pair in item.StreamOptions) - { - if (string.IsNullOrEmpty(pair.Value)) - { - continue; + return GetOption(videoCodec, "profile"); } - // strip spaces to avoid having to encode h264 profile names - list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal))); + return TargetVideoStream == null ? null : TargetVideoStream.Profile; } + } - if (!item.IsDirectStream) + /// <summary> + /// Gets the target video codec tag. + /// </summary> + /// <value>The target video codec tag.</value> + public string TargetVideoCodecTag + { + get { - list.Add(new NameValuePair("TranscodeReasons", string.Join(',', item.TranscodeReasons.Distinct().Select(i => i.ToString())))); + var stream = TargetVideoStream; + return !IsDirectStream + ? null + : stream == null ? null : stream.CodecTag; } - - return list; } - public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) + /// <summary> + /// Gets the audio bitrate that will be in the output stream. + /// </summary> + public int? TargetAudioBitrate { - return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + get + { + var stream = TargetAudioStream; + return AudioBitrate.HasValue && !IsDirectStream + ? AudioBitrate + : stream == null ? null : stream.BitRate; + } } - public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + /// <summary> + /// Gets the audio channels that will be in the output stream. + /// </summary> + public int? TargetAudioChannels { - var list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); - var newList = new List<SubtitleStreamInfo>(); - - // First add the selected track - foreach (SubtitleStreamInfo stream in list) + get { - if (stream.DeliveryMethod == SubtitleDeliveryMethod.External) + if (IsDirectStream) { - newList.Add(stream); + return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; } - } - return newList; - } + var targetAudioCodecs = TargetAudioCodec; + var codec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; + if (!string.IsNullOrEmpty(codec)) + { + return GetTargetRefFrames(codec); + } - public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) - { - return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + } } - public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + /// <summary> + /// Gets the audio codec that will be in the output stream. + /// </summary> + public string[] TargetAudioCodec { - var list = new List<SubtitleStreamInfo>(); + get + { + var stream = TargetAudioStream; - // HLS will preserve timestamps so we can just grab the full subtitle stream - long startPositionTicks = string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase) - ? 0 - : (PlayMethod == PlayMethod.Transcode && !CopyTimestamps ? StartPositionTicks : 0); + string inputCodec = stream?.Codec; - // First add the selected track - if (SubtitleStreamIndex.HasValue) - { - foreach (var stream in MediaSource.MediaStreams) + if (IsDirectStream) { - if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) - { - AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); - } + return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; } - } - if (!includeSelectedTrackOnly) - { - foreach (var stream in MediaSource.MediaStreams) + foreach (string codec in AudioCodecs) { - if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) + if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; } } - } - - return list; - } - - private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) - { - if (enableAllProfiles) - { - foreach (var profile in DeviceProfile.SubtitleProfiles) - { - var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport); - - list.Add(info); - } - } - else - { - var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport); - list.Add(info); + return AudioCodecs; } } - private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport) + public string[] TargetVideoCodec { - var subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transcoderSupport, Container, SubProtocol); - var info = new SubtitleStreamInfo + get { - IsForced = stream.IsForced, - Language = stream.Language, - Name = stream.Language ?? "Unknown", - Format = subtitleProfile.Format, - Index = stream.Index, - DeliveryMethod = subtitleProfile.Method, - DisplayTitle = stream.DisplayTitle - }; + var stream = TargetVideoStream; - if (info.DeliveryMethod == SubtitleDeliveryMethod.External) - { - if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) + string inputCodec = stream?.Codec; + + if (IsDirectStream) { - info.Url = string.Format(CultureInfo.InvariantCulture, "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", - baseUrl, - ItemId, - MediaSourceId, - stream.Index.ToString(CultureInfo.InvariantCulture), - startPositionTicks.ToString(CultureInfo.InvariantCulture), - subtitleProfile.Format); + return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; + } - if (!string.IsNullOrEmpty(accessToken)) + foreach (string codec in VideoCodecs) + { + if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) { - info.Url += "?api_key=" + accessToken; + return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; } - - info.IsExternalUrl = false; } - else - { - info.Url = stream.Path; - info.IsExternalUrl = true; - } - } - return info; + return VideoCodecs; + } } /// <summary> - /// Returns the audio stream that will be used. + /// Gets the audio channels that will be in the output stream. /// </summary> - public MediaStream TargetAudioStream + public long? TargetSize { get { - if (MediaSource != null) + if (IsDirectStream) { - return MediaSource.GetDefaultAudioStream(AudioStreamIndex); + return MediaSource.Size; + } + + if (RunTimeTicks.HasValue) + { + int? totalBitrate = TargetTotalBitrate; + + double totalSeconds = RunTimeTicks.Value; + // Convert to ms + totalSeconds /= 10000; + // Convert to seconds + totalSeconds /= 1000; + + return totalBitrate.HasValue ? + Convert.ToInt64(totalBitrate.Value * totalSeconds) : + (long?)null; } return null; } } - /// <summary> - /// Returns the video stream that will be used. - /// </summary> - public MediaStream TargetVideoStream + public int? TargetVideoBitrate { get { - if (MediaSource != null) - { - return MediaSource.VideoStream; - } + var stream = TargetVideoStream; - return null; + return VideoBitrate.HasValue && !IsDirectStream + ? VideoBitrate + : stream == null ? null : stream.BitRate; } } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public int? TargetAudioSampleRate + public TransportStreamTimestamp TargetTimestamp { get { - var stream = TargetAudioStream; - return AudioSampleRate.HasValue && !IsDirectStream - ? AudioSampleRate - : stream == null ? null : stream.SampleRate; + var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase) + ? TransportStreamTimestamp.Valid + : TransportStreamTimestamp.None; + + return !IsDirectStream + ? defaultValue + : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None; } } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public int? TargetAudioBitDepth + public int? TargetTotalBitrate => (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0); + + public bool? IsTargetAnamorphic { get { if (IsDirectStream) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; - } - - var targetAudioCodecs = TargetAudioCodec; - var audioCodec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; - if (!string.IsNullOrEmpty(audioCodec)) - { - return GetTargetAudioBitDepth(audioCodec); + return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic; } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.BitDepth; + return false; } } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public int? TargetVideoBitDepth + public bool? IsTargetInterlaced { get { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } var targetVideoCodecs = TargetVideoCodec; var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; if (!string.IsNullOrEmpty(videoCodec)) { - return GetTargetVideoBitDepth(videoCodec); + if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + { + return false; + } } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.BitDepth; + return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } } - /// <summary> - /// Gets the target reference frames. - /// </summary> - /// <value>The target reference frames.</value> - public int? TargetRefFrames + public bool? IsTargetAVC { get { if (IsDirectStream) { - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; - } - - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) - { - return GetTargetRefFrames(videoCodec); + return TargetVideoStream == null ? null : TargetVideoStream.IsAVC; } - return TargetVideoStream == null ? (int?)null : TargetVideoStream.RefFrames; + return true; } } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public float? TargetFramerate + public int? TargetWidth { get { - var stream = TargetVideoStream; - return MaxFramerate.HasValue && !IsDirectStream - ? MaxFramerate - : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate; + var videoStream = TargetVideoStream; + + if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) + { + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + + return size.Width; + } + + return MaxWidth; } } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public double? TargetVideoLevel + public int? TargetHeight { get { - if (IsDirectStream) - { - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; - } + var videoStream = TargetVideoStream; - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) { - return GetTargetVideoLevel(videoCodec); + ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + + size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + + return size.Height; } - return TargetVideoStream == null ? (double?)null : TargetVideoStream.Level; + return MaxHeight; } } - public int? GetTargetVideoBitDepth(string codec) + public int? TargetVideoStreamCount { - var value = GetOption(codec, "videobitdepth"); - if (string.IsNullOrEmpty(value)) + get { - return null; - } + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); + } - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) - { - return result; + return GetMediaStreamCount(MediaStreamType.Video, 1); } - - return null; } - public int? GetTargetAudioBitDepth(string codec) + public int? TargetAudioStreamCount { - var value = GetOption(codec, "audiobitdepth"); - if (string.IsNullOrEmpty(value)) - { - return null; - } - - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + get { - return result; - } + if (IsDirectStream) + { + return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); + } - return null; + return GetMediaStreamCount(MediaStreamType.Audio, 1); + } } - public double? GetTargetVideoLevel(string codec) + public void SetOption(string qualifier, string name, string value) { - var value = GetOption(codec, "level"); - if (string.IsNullOrEmpty(value)) + if (string.IsNullOrEmpty(qualifier)) { - return null; + SetOption(name, value); } - - if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + else { - return result; + SetOption(qualifier + "-" + name, value); } + } - return null; + public void SetOption(string name, string value) + { + StreamOptions[name] = value; } - public int? GetTargetRefFrames(string codec) + public string GetOption(string qualifier, string name) { - var value = GetOption(codec, "maxrefframes"); + var value = GetOption(qualifier + "-" + name); + if (string.IsNullOrEmpty(value)) { - return null; + value = GetOption(name); } - if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + return value; + } + + public string GetOption(string name) + { + if (StreamOptions.TryGetValue(name, out var value)) { - return result; + return value; } return null; } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public int? TargetPacketLength + public string ToUrl(string baseUrl, string accessToken) { - get + if (PlayMethod == PlayMethod.DirectPlay) { - var stream = TargetVideoStream; - return !IsDirectStream - ? null - : stream == null ? null : stream.PacketLength; + return MediaSource.Path; } - } - /// <summary> - /// Predicts the audio sample rate that will be in the output stream. - /// </summary> - public string TargetVideoProfile - { - get + if (string.IsNullOrEmpty(baseUrl)) { - if (IsDirectStream) + throw new ArgumentNullException(nameof(baseUrl)); + } + + var list = new List<string>(); + foreach (NameValuePair pair in BuildParams(this, accessToken)) + { + if (string.IsNullOrEmpty(pair.Value)) { - return TargetVideoStream == null ? null : TargetVideoStream.Profile; + continue; } - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + // Try to keep the url clean by omitting defaults + if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase)) { - return GetOption(videoCodec, "profile"); + continue; } - return TargetVideoStream == null ? null : TargetVideoStream.Profile; - } - } + if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase)) + { + continue; + } - /// <summary> - /// Gets the target video codec tag. - /// </summary> - /// <value>The target video codec tag.</value> - public string TargetVideoCodecTag - { - get - { - var stream = TargetVideoStream; - return !IsDirectStream - ? null - : stream == null ? null : stream.CodecTag; + // Be careful, IsDirectStream==true by default (Static != false or not in query). + // See initialization of StreamingRequestDto in AudioController.GetAudioStream() method : Static = @static ?? true. + if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase) && + string.Equals(pair.Value, "true", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + var encodedValue = pair.Value.Replace(" ", "%20"); + + list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue)); } + + string queryString = string.Join("&", list.ToArray()); + + return GetUrl(baseUrl, queryString); } - /// <summary> - /// Predicts the audio bitrate that will be in the output stream. - /// </summary> - public int? TargetAudioBitrate + private string GetUrl(string baseUrl, string queryString) { - get + if (string.IsNullOrEmpty(baseUrl)) { - var stream = TargetAudioStream; - return AudioBitrate.HasValue && !IsDirectStream - ? AudioBitrate - : stream == null ? null : stream.BitRate; + throw new ArgumentNullException(nameof(baseUrl)); } - } - /// <summary> - /// Predicts the audio channels that will be in the output stream. - /// </summary> - public int? TargetAudioChannels - { - get + string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container; + + baseUrl = baseUrl.TrimEnd('/'); + + if (MediaType == DlnaProfileType.Audio) { - if (IsDirectStream) + if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } - var targetAudioCodecs = TargetAudioCodec; - var codec = targetAudioCodecs.Length == 0 ? null : targetAudioCodecs[0]; - if (!string.IsNullOrEmpty(codec)) - { - return GetTargetRefFrames(codec); - } + return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); + } - return TargetAudioStream == null ? (int?)null : TargetAudioStream.Channels; + if (string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) + { + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryString); } + + return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, queryString); } - public int? GetTargetAudioChannels(string codec) + private static List<NameValuePair> BuildParams(StreamInfo item, string accessToken) { - var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels; + var list = new List<NameValuePair>(); - var value = GetOption(codec, "audiochannels"); - if (string.IsNullOrEmpty(value)) + string audioCodecs = item.AudioCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.AudioCodecs); + + string videoCodecs = item.VideoCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.VideoCodecs); + + list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); + list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); + list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); + list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + list.Add(new NameValuePair("VideoCodec", videoCodecs)); + list.Add(new NameValuePair("AudioCodec", audioCodecs)); + list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + long startPositionTicks = item.StartPositionTicks; + + var isHls = string.Equals(item.SubProtocol, "hls", StringComparison.OrdinalIgnoreCase); + + if (isHls) { - return defaultValue; + list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } - - if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + else { - return Math.Min(result, defaultValue ?? result); + list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture))); } - return defaultValue; - } + list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); + list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); - /// <summary> - /// Predicts the audio codec that will be in the output stream. - /// </summary> - public string[] TargetAudioCodec - { - get - { - var stream = TargetAudioStream; + string liveStreamId = item.MediaSource?.LiveStreamId; + list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); - string inputCodec = stream?.Codec; + list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); - if (IsDirectStream) + if (!item.IsDirectStream) + { + if (item.RequireNonAnamorphic) { - return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; + list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - foreach (string codec in AudioCodecs) + list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.TranscodingMaxAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)); + + if (item.EnableSubtitlesInManifest) { - if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) - { - return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; - } + list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - return AudioCodecs; - } - } - - public string[] TargetVideoCodec - { - get - { - var stream = TargetVideoStream; + if (item.EnableMpegtsM2TsMode) + { + list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + } - string inputCodec = stream?.Codec; + if (item.EstimateContentLength) + { + list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); + } - if (IsDirectStream) + if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto) { - return string.IsNullOrEmpty(inputCodec) ? Array.Empty<string>() : new[] { inputCodec }; + list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant())); } - foreach (string codec in VideoCodecs) + if (item.CopyTimestamps) { - if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase)) - { - return string.IsNullOrEmpty(codec) ? Array.Empty<string>() : new[] { codec }; - } + list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - return VideoCodecs; + list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvariant())); } - } - /// <summary> - /// Predicts the audio channels that will be in the output stream. - /// </summary> - public long? TargetSize - { - get + list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); + + string subtitleCodecs = item.SubtitleCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.SubtitleCodecs); + + list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); + + if (isHls) { - if (IsDirectStream) + list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); + + if (item.SegmentLength.HasValue) { - return MediaSource.Size; + list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCulture))); } - if (RunTimeTicks.HasValue) + if (item.MinSegments.HasValue) { - int? totalBitrate = TargetTotalBitrate; - - double totalSeconds = RunTimeTicks.Value; - // Convert to ms - totalSeconds /= 10000; - // Convert to seconds - totalSeconds /= 1000; - - return totalBitrate.HasValue ? - Convert.ToInt64(totalBitrate.Value * totalSeconds) : - (long?)null; + list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))); } - return null; + list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCulture))); } - } - public int? TargetVideoBitrate - { - get + foreach (var pair in item.StreamOptions) { - var stream = TargetVideoStream; + if (string.IsNullOrEmpty(pair.Value)) + { + continue; + } - return VideoBitrate.HasValue && !IsDirectStream - ? VideoBitrate - : stream == null ? null : stream.BitRate; + // strip spaces to avoid having to encode h264 profile names + list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty))); } - } - public TransportStreamTimestamp TargetTimestamp - { - get + if (!item.IsDirectStream) { - var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase) - ? TransportStreamTimestamp.Valid - : TransportStreamTimestamp.None; - - return !IsDirectStream - ? defaultValue - : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None; + list.Add(new NameValuePair("TranscodeReasons", string.Join(',', item.TranscodeReasons.Distinct()))); } + + return list; } - public int? TargetTotalBitrate => (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0); + public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) + { + return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + } - public bool? IsTargetAnamorphic + public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) { - get + var list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken); + var newList = new List<SubtitleStreamInfo>(); + + // First add the selected track + foreach (SubtitleStreamInfo stream in list) { - if (IsDirectStream) + if (stream.DeliveryMethod == SubtitleDeliveryMethod.External) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic; + newList.Add(stream); } - - return false; } + + return newList; } - public bool? IsTargetInterlaced + public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken) { - get + return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken); + } + + public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken) + { + var list = new List<SubtitleStreamInfo>(); + + // HLS will preserve timestamps so we can just grab the full subtitle stream + long startPositionTicks = string.Equals(SubProtocol, "hls", StringComparison.OrdinalIgnoreCase) + ? 0 + : (PlayMethod == PlayMethod.Transcode && !CopyTimestamps ? StartPositionTicks : 0); + + // First add the selected track + if (SubtitleStreamIndex.HasValue) { - if (IsDirectStream) + foreach (var stream in MediaSource.MediaStreams) { - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; + if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) + { + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); + } } + } - var targetVideoCodecs = TargetVideoCodec; - var videoCodec = targetVideoCodecs.Length == 0 ? null : targetVideoCodecs[0]; - if (!string.IsNullOrEmpty(videoCodec)) + if (!includeSelectedTrackOnly) + { + foreach (var stream in MediaSource.MediaStreams) { - if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase)) + if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value)) { - return false; + AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks); } } - - return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced; } + + return list; } - public bool? IsTargetAVC + private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks) { - get + if (enableAllProfiles) { - if (IsDirectStream) + foreach (var profile in DeviceProfile.SubtitleProfiles) { - return TargetVideoStream == null ? null : TargetVideoStream.IsAVC; + var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport); + + list.Add(info); } + } + else + { + var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport); - return true; + list.Add(info); } } - public int? TargetWidth + private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport) { - get + var subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transcoderSupport, Container, SubProtocol); + var info = new SubtitleStreamInfo { - var videoStream = TargetVideoStream; + IsForced = stream.IsForced, + Language = stream.Language, + Name = stream.Language ?? "Unknown", + Format = subtitleProfile.Format, + Index = stream.Index, + DeliveryMethod = subtitleProfile.Method, + DisplayTitle = stream.DisplayTitle + }; - if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) + if (info.DeliveryMethod == SubtitleDeliveryMethod.External) + { + if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, StringComparison.OrdinalIgnoreCase) || !stream.IsExternal) { - ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + info.Url = string.Format( + CultureInfo.InvariantCulture, + "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}", + baseUrl, + ItemId, + MediaSourceId, + stream.Index.ToString(CultureInfo.InvariantCulture), + startPositionTicks.ToString(CultureInfo.InvariantCulture), + subtitleProfile.Format); - size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + if (!string.IsNullOrEmpty(accessToken)) + { + info.Url += "?api_key=" + accessToken; + } - return size.Width; + info.IsExternalUrl = false; + } + else + { + info.Url = stream.Path; + info.IsExternalUrl = true; } + } - return MaxWidth; + return info; + } + + public int? GetTargetVideoBitDepth(string codec) + { + var value = GetOption(codec, "videobitdepth"); + if (string.IsNullOrEmpty(value)) + { + return null; + } + + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetHeight + public int? GetTargetAudioBitDepth(string codec) { - get + var value = GetOption(codec, "audiobitdepth"); + if (string.IsNullOrEmpty(value)) { - var videoStream = TargetVideoStream; + return null; + } - if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue) - { - ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value); + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return result; + } - size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0); + return null; + } - return size.Height; - } + public double? GetTargetVideoLevel(string codec) + { + var value = GetOption(codec, "level"); + if (string.IsNullOrEmpty(value)) + { + return null; + } - return MaxHeight; + if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetVideoStreamCount + public int? GetTargetRefFrames(string codec) { - get + var value = GetOption(codec, "maxrefframes"); + if (string.IsNullOrEmpty(value)) { - if (IsDirectStream) - { - return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue); - } + return null; + } - return GetMediaStreamCount(MediaStreamType.Video, 1); + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; } + + return null; } - public int? TargetAudioStreamCount + public int? GetTargetAudioChannels(string codec) { - get + var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels; + + var value = GetOption(codec, "audiochannels"); + if (string.IsNullOrEmpty(value)) { - if (IsDirectStream) - { - return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue); - } + return defaultValue; + } - return GetMediaStreamCount(MediaStreamType.Audio, 1); + if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + return Math.Min(result, defaultValue ?? result); } + + return defaultValue; } private int? GetMediaStreamCount(MediaStreamType type, int limit) diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 2f9f9d3cd..a784025e3 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -294,13 +294,13 @@ namespace MediaBrowser.Model.Dto public NameGuidPair[] GenreItems { get; set; } /// <summary> - /// If the item does not have a logo, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has a logo, this will hold the Id of the Parent that has one. /// </summary> /// <value>The parent logo item id.</value> public string ParentLogoItemId { get; set; } /// <summary> - /// If the item does not have any backdrops, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has any backdrops, this will hold the Id of the Parent that has one. /// </summary> /// <value>The parent backdrop item id.</value> public string ParentBackdropItemId { get; set; } @@ -318,7 +318,7 @@ namespace MediaBrowser.Model.Dto public int? LocalTrailerCount { get; set; } /// <summary> - /// User data for this item based on the user it's being requested for. + /// Gets or sets the user data for this item based on the user it's being requested for. /// </summary> /// <value>The user data.</value> public UserItemDataDto UserData { get; set; } @@ -506,7 +506,7 @@ namespace MediaBrowser.Model.Dto public string ParentLogoImageTag { get; set; } /// <summary> - /// If the item does not have a art, this will hold the Id of the Parent that has one. + /// Gets or sets wether the item has fan art, this will hold the Id of the Parent that has one. /// </summary> /// <value>The parent art item id.</value> public string ParentArtItemId { get; set; } @@ -695,7 +695,7 @@ namespace MediaBrowser.Model.Dto public string ChannelPrimaryImageTag { get; set; } /// <summary> - /// The start date of the recording, in UTC. + /// Gets or sets the start date of the recording, in UTC. /// </summary> public DateTime? StartDate { get; set; } diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index be682be23..ec3b37efa 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -12,6 +12,18 @@ namespace MediaBrowser.Model.Dto { public class MediaSourceInfo { + public MediaSourceInfo() + { + Formats = Array.Empty<string>(); + MediaStreams = new List<MediaStream>(); + MediaAttachments = Array.Empty<MediaAttachment>(); + RequiredHttpHeaders = new Dictionary<string, string>(); + SupportsTranscoding = true; + SupportsDirectStream = true; + SupportsDirectPlay = true; + SupportsProbing = true; + } + public MediaProtocol Protocol { get; set; } public string Id { get; set; } @@ -31,6 +43,7 @@ namespace MediaBrowser.Model.Dto public string Name { get; set; } /// <summary> + /// Gets or sets a value indicating whether the media is remote. /// Differentiate internet url vs local network. /// </summary> public bool IsRemote { get; set; } @@ -95,16 +108,28 @@ namespace MediaBrowser.Model.Dto public int? AnalyzeDurationMs { get; set; } - public MediaSourceInfo() + [JsonIgnore] + public TranscodeReason[] TranscodeReasons { get; set; } + + public int? DefaultAudioStreamIndex { get; set; } + + public int? DefaultSubtitleStreamIndex { get; set; } + + [JsonIgnore] + public MediaStream VideoStream { - Formats = Array.Empty<string>(); - MediaStreams = new List<MediaStream>(); - MediaAttachments = Array.Empty<MediaAttachment>(); - RequiredHttpHeaders = new Dictionary<string, string>(); - SupportsTranscoding = true; - SupportsDirectStream = true; - SupportsDirectPlay = true; - SupportsProbing = true; + get + { + foreach (var i in MediaStreams) + { + if (i.Type == MediaStreamType.Video) + { + return i; + } + } + + return null; + } } public void InferTotalBitrate(bool force = false) @@ -134,13 +159,6 @@ namespace MediaBrowser.Model.Dto } } - [JsonIgnore] - public TranscodeReason[] TranscodeReasons { get; set; } - - public int? DefaultAudioStreamIndex { get; set; } - - public int? DefaultSubtitleStreamIndex { get; set; } - public MediaStream GetDefaultAudioStream(int? defaultIndex) { if (defaultIndex.HasValue) @@ -175,23 +193,6 @@ namespace MediaBrowser.Model.Dto return null; } - [JsonIgnore] - public MediaStream VideoStream - { - get - { - foreach (var i in MediaStreams) - { - if (i.Type == MediaStreamType.Video) - { - return i; - } - } - - return null; - } - } - public MediaStream GetMediaStream(MediaStreamType type, int index) { foreach (var i in MediaStreams) diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs index e4f38d6af..e0e889f7d 100644 --- a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs +++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs @@ -10,6 +10,15 @@ namespace MediaBrowser.Model.Dto { public class MetadataEditorInfo { + public MetadataEditorInfo() + { + ParentalRatingOptions = Array.Empty<ParentalRating>(); + Countries = Array.Empty<CountryInfo>(); + Cultures = Array.Empty<CultureDto>(); + ExternalIdInfos = Array.Empty<ExternalIdInfo>(); + ContentTypeOptions = Array.Empty<NameValuePair>(); + } + public ParentalRating[] ParentalRatingOptions { get; set; } public CountryInfo[] Countries { get; set; } @@ -21,14 +30,5 @@ namespace MediaBrowser.Model.Dto public string ContentType { get; set; } public NameValuePair[] ContentTypeOptions { get; set; } - - public MetadataEditorInfo() - { - ParentalRatingOptions = Array.Empty<ParentalRating>(); - Countries = Array.Empty<CountryInfo>(); - Cultures = Array.Empty<CultureDto>(); - ExternalIdInfos = Array.Empty<ExternalIdInfo>(); - ContentTypeOptions = Array.Empty<NameValuePair>(); - } } } diff --git a/MediaBrowser.Model/Dto/NameGuidPair.cs b/MediaBrowser.Model/Dto/NameGuidPair.cs new file mode 100644 index 000000000..71166df97 --- /dev/null +++ b/MediaBrowser.Model/Dto/NameGuidPair.cs @@ -0,0 +1,14 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Dto +{ + public class NameGuidPair + { + public string Name { get; set; } + + public Guid Id { get; set; } + } +} diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs index 45c2fb35d..7f18b4502 100644 --- a/MediaBrowser.Model/Dto/NameIdPair.cs +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -19,11 +19,4 @@ namespace MediaBrowser.Model.Dto /// <value>The identifier.</value> public string Id { get; set; } } - - public class NameGuidPair - { - public string Name { get; set; } - - public Guid Id { get; set; } - } } diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index 40222c9dc..256d7b10f 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -10,6 +10,15 @@ namespace MediaBrowser.Model.Dto /// </summary> public class UserDto : IItemDto, IHasServerId { + /// <summary> + /// Initializes a new instance of the <see cref="UserDto"/> class. + /// </summary> + public UserDto() + { + Configuration = new UserConfiguration(); + Policy = new UserPolicy(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -94,15 +103,6 @@ namespace MediaBrowser.Model.Dto /// <value>The primary image aspect ratio.</value> public double? PrimaryImageAspectRatio { get; set; } - /// <summary> - /// Initializes a new instance of the <see cref="UserDto"/> class. - /// </summary> - public UserDto() - { - Configuration = new UserConfiguration(); - Policy = new UserPolicy(); - } - /// <inheritdoc /> public override string ToString() { diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs index 354038712..60b69d4b0 100644 --- a/MediaBrowser.Model/Entities/CollectionType.cs +++ b/MediaBrowser.Model/Entities/CollectionType.cs @@ -24,36 +24,4 @@ namespace MediaBrowser.Model.Entities public const string Playlists = "playlists"; public const string Folders = "folders"; } - - public static class SpecialFolder - { - public const string TvShowSeries = "TvShowSeries"; - public const string TvGenres = "TvGenres"; - public const string TvGenre = "TvGenre"; - public const string TvLatest = "TvLatest"; - public const string TvNextUp = "TvNextUp"; - public const string TvResume = "TvResume"; - public const string TvFavoriteSeries = "TvFavoriteSeries"; - public const string TvFavoriteEpisodes = "TvFavoriteEpisodes"; - - public const string MovieLatest = "MovieLatest"; - public const string MovieResume = "MovieResume"; - public const string MovieMovies = "MovieMovies"; - public const string MovieCollections = "MovieCollections"; - public const string MovieFavorites = "MovieFavorites"; - public const string MovieGenres = "MovieGenres"; - public const string MovieGenre = "MovieGenre"; - - public const string MusicArtists = "MusicArtists"; - public const string MusicAlbumArtists = "MusicAlbumArtists"; - public const string MusicAlbums = "MusicAlbums"; - public const string MusicGenres = "MusicGenres"; - public const string MusicLatest = "MusicLatest"; - public const string MusicPlaylists = "MusicPlaylists"; - public const string MusicSongs = "MusicSongs"; - public const string MusicFavorites = "MusicFavorites"; - public const string MusicFavoriteArtists = "MusicFavoriteArtists"; - public const string MusicFavoriteAlbums = "MusicFavoriteAlbums"; - public const string MusicFavoriteSongs = "MusicFavoriteSongs"; - } } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index d85a8cde9..ade9d7e8d 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Model.Entities public string Title { get; set; } /// <summary> - /// Gets or sets the video range. + /// Gets the video range. /// </summary> /// <value>The video range.</value> public string VideoRange @@ -108,11 +108,11 @@ namespace MediaBrowser.Model.Entities } } - public string localizedUndefined { get; set; } + public string LocalizedUndefined { get; set; } - public string localizedDefault { get; set; } + public string LocalizedDefault { get; set; } - public string localizedForced { get; set; } + public string LocalizedForced { get; set; } public string DisplayTitle { @@ -154,7 +154,7 @@ namespace MediaBrowser.Model.Entities if (IsDefault) { - attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault); + attributes.Add(string.IsNullOrEmpty(LocalizedDefault) ? "Default" : LocalizedDefault); } if (!string.IsNullOrEmpty(Title)) @@ -229,17 +229,17 @@ namespace MediaBrowser.Model.Entities } else { - attributes.Add(string.IsNullOrEmpty(localizedUndefined) ? "Und" : localizedUndefined); + attributes.Add(string.IsNullOrEmpty(LocalizedUndefined) ? "Und" : LocalizedUndefined); } if (IsDefault) { - attributes.Add(string.IsNullOrEmpty(localizedDefault) ? "Default" : localizedDefault); + attributes.Add(string.IsNullOrEmpty(LocalizedDefault) ? "Default" : LocalizedDefault); } if (IsForced) { - attributes.Add(string.IsNullOrEmpty(localizedForced) ? "Forced" : localizedForced); + attributes.Add(string.IsNullOrEmpty(LocalizedForced) ? "Forced" : LocalizedForced); } if (!string.IsNullOrEmpty(Title)) @@ -266,67 +266,6 @@ namespace MediaBrowser.Model.Entities } } - private string GetResolutionText() - { - var i = this; - - if (i.Width.HasValue && i.Height.HasValue) - { - var width = i.Width.Value; - var height = i.Height.Value; - - if (width >= 3800 || height >= 2000) - { - return "4K"; - } - - if (width >= 2500) - { - if (i.IsInterlaced) - { - return "1440i"; - } - - return "1440p"; - } - - if (width >= 1900 || height >= 1000) - { - if (i.IsInterlaced) - { - return "1080i"; - } - - return "1080p"; - } - - if (width >= 1260 || height >= 700) - { - if (i.IsInterlaced) - { - return "720i"; - } - - return "720p"; - } - - if (width >= 700 || height >= 440) - { - - if (i.IsInterlaced) - { - return "480i"; - } - - return "480p"; - } - - return "SD"; - } - - return null; - } - public string NalLengthSize { get; set; } /// <summary> @@ -487,6 +426,96 @@ namespace MediaBrowser.Model.Entities } } + /// <summary> + /// Gets or sets a value indicating whether [supports external stream]. + /// </summary> + /// <value><c>true</c> if [supports external stream]; otherwise, <c>false</c>.</value> + public bool SupportsExternalStream { get; set; } + + /// <summary> + /// Gets or sets the filename. + /// </summary> + /// <value>The filename.</value> + public string Path { get; set; } + + /// <summary> + /// Gets or sets the pixel format. + /// </summary> + /// <value>The pixel format.</value> + public string PixelFormat { get; set; } + + /// <summary> + /// Gets or sets the level. + /// </summary> + /// <value>The level.</value> + public double? Level { get; set; } + + /// <summary> + /// Gets or sets whether this instance is anamorphic. + /// </summary> + /// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value> + public bool? IsAnamorphic { get; set; } + + private string GetResolutionText() + { + var i = this; + + if (i.Width.HasValue && i.Height.HasValue) + { + var width = i.Width.Value; + var height = i.Height.Value; + + if (width >= 3800 || height >= 2000) + { + return "4K"; + } + + if (width >= 2500) + { + if (i.IsInterlaced) + { + return "1440i"; + } + + return "1440p"; + } + + if (width >= 1900 || height >= 1000) + { + if (i.IsInterlaced) + { + return "1080i"; + } + + return "1080p"; + } + + if (width >= 1260 || height >= 700) + { + if (i.IsInterlaced) + { + return "720i"; + } + + return "720p"; + } + + if (width >= 700 || height >= 440) + { + if (i.IsInterlaced) + { + return "480i"; + } + + return "480p"; + } + + return "SD"; + } + + return null; + } + public static bool IsTextFormat(string format) { string codec = format ?? string.Empty; @@ -533,35 +562,5 @@ namespace MediaBrowser.Model.Entities return true; } - - /// <summary> - /// Gets or sets a value indicating whether [supports external stream]. - /// </summary> - /// <value><c>true</c> if [supports external stream]; otherwise, <c>false</c>.</value> - public bool SupportsExternalStream { get; set; } - - /// <summary> - /// Gets or sets the filename. - /// </summary> - /// <value>The filename.</value> - public string Path { get; set; } - - /// <summary> - /// Gets or sets the pixel format. - /// </summary> - /// <value>The pixel format.</value> - public string PixelFormat { get; set; } - - /// <summary> - /// Gets or sets the level. - /// </summary> - /// <value>The level.</value> - public double? Level { get; set; } - - /// <summary> - /// Gets a value indicating whether this instance is anamorphic. - /// </summary> - /// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value> - public bool? IsAnamorphic { get; set; } } } diff --git a/MediaBrowser.Model/Entities/PackageReviewInfo.cs b/MediaBrowser.Model/Entities/PackageReviewInfo.cs deleted file mode 100644 index 5b22b34ac..000000000 --- a/MediaBrowser.Model/Entities/PackageReviewInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -using System; - -namespace MediaBrowser.Model.Entities -{ - public class PackageReviewInfo - { - /// <summary> - /// Gets or sets the package id (database key) for this review. - /// </summary> - public int id { get; set; } - - /// <summary> - /// Gets or sets the rating value. - /// </summary> - public int rating { get; set; } - - /// <summary> - /// Gets or sets whether or not this review recommends this item. - /// </summary> - public bool recommend { get; set; } - - /// <summary> - /// Gets or sets a short description of the review. - /// </summary> - public string title { get; set; } - - /// <summary> - /// Gets or sets the full review. - /// </summary> - public string review { get; set; } - - /// <summary> - /// Gets or sets the time of review. - /// </summary> - public DateTime timestamp { get; set; } - } -} diff --git a/MediaBrowser.Model/Entities/SpecialFolder.cs b/MediaBrowser.Model/Entities/SpecialFolder.cs new file mode 100644 index 000000000..2250c5dff --- /dev/null +++ b/MediaBrowser.Model/Entities/SpecialFolder.cs @@ -0,0 +1,36 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Entities +{ + public static class SpecialFolder + { + public const string TvShowSeries = "TvShowSeries"; + public const string TvGenres = "TvGenres"; + public const string TvGenre = "TvGenre"; + public const string TvLatest = "TvLatest"; + public const string TvNextUp = "TvNextUp"; + public const string TvResume = "TvResume"; + public const string TvFavoriteSeries = "TvFavoriteSeries"; + public const string TvFavoriteEpisodes = "TvFavoriteEpisodes"; + + public const string MovieLatest = "MovieLatest"; + public const string MovieResume = "MovieResume"; + public const string MovieMovies = "MovieMovies"; + public const string MovieCollections = "MovieCollections"; + public const string MovieFavorites = "MovieFavorites"; + public const string MovieGenres = "MovieGenres"; + public const string MovieGenre = "MovieGenre"; + + public const string MusicArtists = "MusicArtists"; + public const string MusicAlbumArtists = "MusicAlbumArtists"; + public const string MusicAlbums = "MusicAlbums"; + public const string MusicGenres = "MusicGenres"; + public const string MusicLatest = "MusicLatest"; + public const string MusicPlaylists = "MusicPlaylists"; + public const string MusicSongs = "MusicSongs"; + public const string MusicFavorites = "MusicFavorites"; + public const string MusicFavoriteArtists = "MusicFavoriteArtists"; + public const string MusicFavoriteAlbums = "MusicFavoriteAlbums"; + public const string MusicFavoriteSongs = "MusicFavoriteSongs"; + } +} diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index f2bc6f25e..1b0e59240 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -11,6 +11,14 @@ namespace MediaBrowser.Model.Entities /// </summary> public class VirtualFolderInfo { + /// <summary> + /// Initializes a new instance of the <see cref="VirtualFolderInfo"/> class. + /// </summary> + public VirtualFolderInfo() + { + Locations = Array.Empty<string>(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -31,14 +39,6 @@ namespace MediaBrowser.Model.Entities public LibraryOptions LibraryOptions { get; set; } - /// <summary> - /// Initializes a new instance of the <see cref="VirtualFolderInfo"/> class. - /// </summary> - public VirtualFolderInfo() - { - Locations = Array.Empty<string>(); - } - /// <summary> /// Gets or sets the item identifier. /// </summary> diff --git a/MediaBrowser.Model/Globalization/CultureDto.cs b/MediaBrowser.Model/Globalization/CultureDto.cs index 6af4a872c..5246f87d9 100644 --- a/MediaBrowser.Model/Globalization/CultureDto.cs +++ b/MediaBrowser.Model/Globalization/CultureDto.cs @@ -10,6 +10,11 @@ namespace MediaBrowser.Model.Globalization /// </summary> public class CultureDto { + public CultureDto() + { + ThreeLetterISOLanguageNames = Array.Empty<string>(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -29,7 +34,7 @@ namespace MediaBrowser.Model.Globalization public string TwoLetterISOLanguageName { get; set; } /// <summary> - /// Gets or sets the name of the three letter ISO language. + /// Gets the name of the three letter ISO language. /// </summary> /// <value>The name of the three letter ISO language.</value> public string ThreeLetterISOLanguageName @@ -47,10 +52,5 @@ namespace MediaBrowser.Model.Globalization } public string[] ThreeLetterISOLanguageNames { get; set; } - - public CultureDto() - { - ThreeLetterISOLanguageNames = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index dc6549787..ef08ecec6 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -155,13 +155,16 @@ namespace MediaBrowser.Model.IO /// Gets the directories. /// </summary> /// <param name="path">The path.</param> - /// <param name="recursive">if set to <c>true</c> [recursive].</param> - /// <returns>IEnumerable<DirectoryInfo>.</returns> + /// <param name="recursive">If set to <c>true</c> also searches in subdirectiories.</param> + /// <returns>All found directories.</returns> IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false); /// <summary> /// Gets the files. /// </summary> + /// <param name="path">The path in which to search.</param> + /// <param name="recursive">If set to <c>true</c> also searches in subdirectiories.</param> + /// <returns>All found files.</returns> IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false); IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string> extensions, bool enableCaseSensitiveExtensions, bool recursive); diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs index 07e76d960..c6de4c1ab 100644 --- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.LiveTv public class BaseTimerInfoDto : IHasServerId { /// <summary> - /// Id of the recording. + /// Gets or sets the Id of the recording. /// </summary> public string Id { get; set; } @@ -28,7 +28,7 @@ namespace MediaBrowser.Model.LiveTv public string ExternalId { get; set; } /// <summary> - /// ChannelId of the recording. + /// Gets or sets the channel id of the recording. /// </summary> public Guid ChannelId { get; set; } @@ -39,7 +39,7 @@ namespace MediaBrowser.Model.LiveTv public string ExternalChannelId { get; set; } /// <summary> - /// ChannelName of the recording. + /// Gets or sets the channel name of the recording. /// </summary> public string ChannelName { get; set; } @@ -58,22 +58,22 @@ namespace MediaBrowser.Model.LiveTv public string ExternalProgramId { get; set; } /// <summary> - /// Name of the recording. + /// Gets or sets the name of the recording. /// </summary> public string Name { get; set; } /// <summary> - /// Description of the recording. + /// Gets or sets the description of the recording. /// </summary> public string Overview { get; set; } /// <summary> - /// The start date of the recording, in UTC. + /// Gets or sets the start date of the recording, in UTC. /// </summary> public DateTime StartDate { get; set; } /// <summary> - /// The end date of the recording, in UTC. + /// Gets or sets the end date of the recording, in UTC. /// </summary> public DateTime EndDate { get; set; } @@ -108,7 +108,7 @@ namespace MediaBrowser.Model.LiveTv public bool IsPrePaddingRequired { get; set; } /// <summary> - /// If the item does not have any backdrops, this will hold the Id of the Parent that has one. + /// Gets or sets the Id of the Parent that has a backdrop if the item does not have one. /// </summary> /// <value>The parent backdrop item id.</value> public string ParentBackdropItemId { get; set; } diff --git a/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs b/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs new file mode 100644 index 000000000..082daeb51 --- /dev/null +++ b/MediaBrowser.Model/LiveTv/ListingsProviderInfo.cs @@ -0,0 +1,58 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.LiveTv +{ + public class ListingsProviderInfo + { + public ListingsProviderInfo() + { + NewsCategories = new[] { "news", "journalism", "documentary", "current affairs" }; + SportsCategories = new[] { "sports", "basketball", "baseball", "football" }; + KidsCategories = new[] { "kids", "family", "children", "childrens", "disney" }; + MovieCategories = new[] { "movie" }; + EnabledTuners = Array.Empty<string>(); + EnableAllTuners = true; + ChannelMappings = Array.Empty<NameValuePair>(); + } + + public string Id { get; set; } + + public string Type { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + + public string ListingsId { get; set; } + + public string ZipCode { get; set; } + + public string Country { get; set; } + + public string Path { get; set; } + + public string[] EnabledTuners { get; set; } + + public bool EnableAllTuners { get; set; } + + public string[] NewsCategories { get; set; } + + public string[] SportsCategories { get; set; } + + public string[] KidsCategories { get; set; } + + public string[] MovieCategories { get; set; } + + public NameValuePair[] ChannelMappings { get; set; } + + public string MoviePrefix { get; set; } + + public string PreferredLanguage { get; set; } + + public string UserAgent { get; set; } + } +} diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs index bcba344cc..ca8defd8b 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs @@ -11,6 +11,12 @@ namespace MediaBrowser.Model.LiveTv /// </summary> public class LiveTvChannelQuery { + public LiveTvChannelQuery() + { + EnableUserData = true; + SortBy = Array.Empty<string>(); + } + /// <summary> /// Gets or sets the type of the channel. /// </summary> @@ -48,13 +54,13 @@ namespace MediaBrowser.Model.LiveTv public Guid UserId { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// gets or sets the start index. Used for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } @@ -68,15 +74,15 @@ namespace MediaBrowser.Model.LiveTv public bool EnableUserData { get; set; } /// <summary> - /// Used to specific whether to return news or not. + /// Gets or sets a value whether to return news or not. /// </summary> - /// <remarks>If set to null, all programs will be returned</remarks> + /// <remarks>If set to <c>null</c>, all programs will be returned.</remarks> public bool? IsNews { get; set; } /// <summary> - /// Used to specific whether to return movies or not. + /// Gets or sets a value whether to return movies or not. /// </summary> - /// <remarks>If set to null, all programs will be returned</remarks> + /// <remarks>If set to <c>null</c>, all programs will be returned.</remarks> public bool? IsMovie { get; set; } /// <summary> @@ -96,15 +102,9 @@ namespace MediaBrowser.Model.LiveTv public string[] SortBy { get; set; } /// <summary> - /// The sort order to return results with. + /// Gets or sets the sort order to return results with. /// </summary> /// <value>The sort order.</value> public SortOrder? SortOrder { get; set; } - - public LiveTvChannelQuery() - { - EnableUserData = true; - SortBy = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 789de3198..4cece941c 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -2,12 +2,19 @@ #pragma warning disable CS1591 using System; -using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.LiveTv { public class LiveTvOptions { + public LiveTvOptions() + { + TunerHosts = Array.Empty<TunerHostInfo>(); + ListingProviders = Array.Empty<ListingsProviderInfo>(); + MediaLocationsCreated = Array.Empty<string>(); + RecordingPostProcessorArguments = "\"{path}\""; + } + public int? GuideDays { get; set; } public string RecordingPath { get; set; } @@ -33,93 +40,5 @@ namespace MediaBrowser.Model.LiveTv public string RecordingPostProcessor { get; set; } public string RecordingPostProcessorArguments { get; set; } - - public LiveTvOptions() - { - TunerHosts = Array.Empty<TunerHostInfo>(); - ListingProviders = Array.Empty<ListingsProviderInfo>(); - MediaLocationsCreated = Array.Empty<string>(); - RecordingPostProcessorArguments = "\"{path}\""; - } - } - - public class TunerHostInfo - { - public string Id { get; set; } - - public string Url { get; set; } - - public string Type { get; set; } - - public string DeviceId { get; set; } - - public string FriendlyName { get; set; } - - public bool ImportFavoritesOnly { get; set; } - - public bool AllowHWTranscoding { get; set; } - - public bool EnableStreamLooping { get; set; } - - public string Source { get; set; } - - public int TunerCount { get; set; } - - public string UserAgent { get; set; } - - public TunerHostInfo() - { - AllowHWTranscoding = true; - } - } - - public class ListingsProviderInfo - { - public string Id { get; set; } - - public string Type { get; set; } - - public string Username { get; set; } - - public string Password { get; set; } - - public string ListingsId { get; set; } - - public string ZipCode { get; set; } - - public string Country { get; set; } - - public string Path { get; set; } - - public string[] EnabledTuners { get; set; } - - public bool EnableAllTuners { get; set; } - - public string[] NewsCategories { get; set; } - - public string[] SportsCategories { get; set; } - - public string[] KidsCategories { get; set; } - - public string[] MovieCategories { get; set; } - - public NameValuePair[] ChannelMappings { get; set; } - - public string MoviePrefix { get; set; } - - public string PreferredLanguage { get; set; } - - public string UserAgent { get; set; } - - public ListingsProviderInfo() - { - NewsCategories = new[] { "news", "journalism", "documentary", "current affairs" }; - SportsCategories = new[] { "sports", "basketball", "baseball", "football" }; - KidsCategories = new[] { "kids", "family", "children", "childrens", "disney" }; - MovieCategories = new[] { "movie" }; - EnabledTuners = Array.Empty<string>(); - EnableAllTuners = true; - ChannelMappings = Array.Empty<NameValuePair>(); - } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs index 856f638c5..ef5c5d2f3 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs @@ -10,6 +10,11 @@ namespace MediaBrowser.Model.LiveTv /// </summary> public class LiveTvServiceInfo { + public LiveTvServiceInfo() + { + Tuners = Array.Empty<string>(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -53,10 +58,5 @@ namespace MediaBrowser.Model.LiveTv public bool IsVisible { get; set; } public string[] Tuners { get; set; } - - public LiveTvServiceInfo() - { - Tuners = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 69e7db470..99bb1603c 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -12,6 +12,11 @@ namespace MediaBrowser.Model.LiveTv /// </summary> public class RecordingQuery { + public RecordingQuery() + { + EnableTotalRecordCount = true; + } + /// <summary> /// Gets or sets the channel identifier. /// </summary> @@ -31,13 +36,13 @@ namespace MediaBrowser.Model.LiveTv public string Id { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } @@ -61,7 +66,7 @@ namespace MediaBrowser.Model.LiveTv public string SeriesTimerId { get; set; } /// <summary> - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } @@ -85,10 +90,5 @@ namespace MediaBrowser.Model.LiveTv public ImageType[] EnableImageTypes { get; set; } public bool EnableTotalRecordCount { get; set; } - - public RecordingQuery() - { - EnableTotalRecordCount = true; - } } } diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs index 90422d19c..b26f5f45f 100644 --- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs @@ -7,6 +7,14 @@ using MediaBrowser.Model.Entities; namespace MediaBrowser.Model.LiveTv { + public enum KeepUntil + { + UntilDeleted, + UntilSpaceNeeded, + UntilWatched, + UntilDate + } + /// <summary> /// Class SeriesTimerInfoDto. /// </summary> @@ -83,12 +91,4 @@ namespace MediaBrowser.Model.LiveTv /// <value>The parent primary image tag.</value> public string ParentPrimaryImageTag { get; set; } } - - public enum KeepUntil - { - UntilDeleted, - UntilSpaceNeeded, - UntilWatched, - UntilDate - } } diff --git a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs new file mode 100644 index 000000000..7d4bbb2d0 --- /dev/null +++ b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs @@ -0,0 +1,38 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.LiveTv +{ + public class TunerHostInfo + { + public TunerHostInfo() + { + AllowHWTranscoding = true; + } + + public string Id { get; set; } + + public string Url { get; set; } + + public string Type { get; set; } + + public string DeviceId { get; set; } + + public string FriendlyName { get; set; } + + public bool ImportFavoritesOnly { get; set; } + + public bool AllowHWTranscoding { get; set; } + + public bool EnableStreamLooping { get; set; } + + public string Source { get; set; } + + public int TunerCount { get; set; } + + public string UserAgent { get; set; } + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c53428651..b6d916913 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -17,7 +17,7 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> <LangVersion>latest</LangVersion> <PublishRepositoryUrl>true</PublishRepositoryUrl> @@ -44,7 +44,7 @@ <!-- Code Analyzers--> <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="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index 472055c22..a268a4fa6 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -10,6 +10,17 @@ namespace MediaBrowser.Model.MediaInfo { public class MediaInfo : MediaSourceInfo, IHasProviderIds { + public MediaInfo() + { + Chapters = Array.Empty<ChapterInfo>(); + Artists = Array.Empty<string>(); + AlbumArtists = Array.Empty<string>(); + Studios = Array.Empty<string>(); + Genres = Array.Empty<string>(); + People = Array.Empty<BaseItemPerson>(); + ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + } + public ChapterInfo[] Chapters { get; set; } /// <summary> @@ -69,16 +80,5 @@ namespace MediaBrowser.Model.MediaInfo /// </summary> /// <value>The overview.</value> public string Overview { get; set; } - - public MediaInfo() - { - Chapters = Array.Empty<ChapterInfo>(); - Artists = Array.Empty<string>(); - AlbumArtists = Array.Empty<string>(); - Studios = Array.Empty<string>(); - Genres = Array.Empty<string>(); - People = Array.Empty<BaseItemPerson>(); - ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } } } diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs index 321685677..ecd9b8834 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs @@ -8,6 +8,17 @@ namespace MediaBrowser.Model.MediaInfo { public class PlaybackInfoRequest { + public PlaybackInfoRequest() + { + EnableDirectPlay = true; + EnableDirectStream = true; + EnableTranscoding = true; + AllowVideoStreamCopy = true; + AllowAudioStreamCopy = true; + IsPlayback = true; + DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; + } + public Guid Id { get; set; } public Guid UserId { get; set; } @@ -43,16 +54,5 @@ namespace MediaBrowser.Model.MediaInfo public bool AutoOpenLiveStream { get; set; } public MediaProtocol[] DirectPlayProtocols { get; set; } - - public PlaybackInfoRequest() - { - EnableDirectPlay = true; - EnableDirectStream = true; - EnableTranscoding = true; - AllowVideoStreamCopy = true; - AllowAudioStreamCopy = true; - IsPlayback = true; - DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http }; - } } } diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs index 273350182..32971b108 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoResponse.cs @@ -10,6 +10,14 @@ namespace MediaBrowser.Model.MediaInfo /// </summary> public class PlaybackInfoResponse { + /// <summary> + /// Initializes a new instance of the <see cref="PlaybackInfoResponse" /> class. + /// </summary> + public PlaybackInfoResponse() + { + MediaSources = Array.Empty<MediaSourceInfo>(); + } + /// <summary> /// Gets or sets the media sources. /// </summary> @@ -27,13 +35,5 @@ namespace MediaBrowser.Model.MediaInfo /// </summary> /// <value>The error code.</value> public PlaybackErrorCode? ErrorCode { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="PlaybackInfoResponse" /> class. - /// </summary> - public PlaybackInfoResponse() - { - MediaSources = Array.Empty<MediaSourceInfo>(); - } } } diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs index 37f5c55da..d5c3a6aec 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs @@ -7,11 +7,11 @@ namespace MediaBrowser.Model.MediaInfo { public class SubtitleTrackInfo { - public IReadOnlyList<SubtitleTrackEvent> TrackEvents { get; set; } - public SubtitleTrackInfo() { TrackEvents = Array.Empty<SubtitleTrackEvent>(); } + + public IReadOnlyList<SubtitleTrackEvent> TrackEvents { get; set; } } } diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs index 5b6ed92df..3de41d565 100644 --- a/MediaBrowser.Model/Net/ISocket.cs +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -23,6 +23,12 @@ namespace MediaBrowser.Model.Net /// <summary> /// Sends a UDP message to a particular end point (uni or multicast). /// </summary> + /// <param name="buffer">An array of type <see cref="byte" /> that contains the data to send.</param> + /// <param name="offset">The zero-based position in buffer at which to begin sending data.</param> + /// <param name="bytes">The number of bytes to send.</param> + /// <param name="endPoint">An <see cref="IPEndPoint" /> that represents the remote device.</param> + /// <param name="cancellationToken">The cancellation token to cancel operation.</param> + /// <returns>The task object representing the asynchronous operation.</returns> Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index 363abefc1..1527ef595 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -14,6 +14,9 @@ namespace MediaBrowser.Model.Net /// <summary> /// Creates a new unicast socket using the specified local port number. /// </summary> + /// <param name="localIp">The local IP address to bind to.</param> + /// <param name="localPort">The local port to bind to.</param> + /// <returns>A new unicast socket using the specified local port number.</returns> ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort); /// <summary> diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 902db1e9e..96f5ab51a 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -91,9 +91,9 @@ namespace MediaBrowser.Model.Net { ".webp", "image/webp" }, // Type font - { ".ttf" , "font/ttf" }, - { ".woff" , "font/woff" }, - { ".woff2" , "font/woff2" }, + { ".ttf", "font/ttf" }, + { ".woff", "font/woff" }, + { ".woff2", "font/woff2" }, // Type text { ".ass", "text/x-ssa" }, @@ -168,14 +168,17 @@ namespace MediaBrowser.Model.Net /// <summary> /// Gets the type of the MIME. /// </summary> - public static string? GetMimeType(string path, bool enableStreamDefault) + /// <param name="filename">The filename to find the MIME type of.</param> + /// <param name="enableStreamDefault">Whether of not to return a default value if no fitting MIME type is found.</param> + /// <returns>The worrect MIME type for the given filename, or `null` if it wasn't found and <paramref name="enableStreamDefault"/> is false.</returns> + public static string? GetMimeType(string filename, bool enableStreamDefault) { - if (path.Length == 0) + if (filename.Length == 0) { - throw new ArgumentException("String can't be empty.", nameof(path)); + throw new ArgumentException("String can't be empty.", nameof(filename)); } - var ext = Path.GetExtension(path); + var ext = Path.GetExtension(filename); if (_mimeTypeLookup.TryGetValue(ext, out string? result)) { @@ -210,9 +213,9 @@ namespace MediaBrowser.Model.Net return enableStreamDefault ? "application/octet-stream" : null; } - public static string? ToExtension(string? mimeType) + public static string? ToExtension(string mimeType) { - if (string.IsNullOrEmpty(mimeType)) + if (mimeType.Length == 0) { throw new ArgumentException("String can't be empty.", nameof(mimeType)); } diff --git a/MediaBrowser.Model/Net/NetworkShare.cs b/MediaBrowser.Model/Net/NetworkShare.cs deleted file mode 100644 index 6344cbe21..000000000 --- a/MediaBrowser.Model/Net/NetworkShare.cs +++ /dev/null @@ -1,33 +0,0 @@ -#nullable disable -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Net -{ - public class NetworkShare - { - /// <summary> - /// The name of the computer that this share belongs to. - /// </summary> - public string Server { get; set; } - - /// <summary> - /// Share name. - /// </summary> - public string Name { get; set; } - - /// <summary> - /// Local path. - /// </summary> - public string Path { get; set; } - - /// <summary> - /// Share type. - /// </summary> - public NetworkShareType ShareType { get; set; } - - /// <summary> - /// Comment. - /// </summary> - public string Remark { get; set; } - } -} diff --git a/MediaBrowser.Model/Net/SocketReceiveResult.cs b/MediaBrowser.Model/Net/SocketReceiveResult.cs index 54139fe9c..1524786ea 100644 --- a/MediaBrowser.Model/Net/SocketReceiveResult.cs +++ b/MediaBrowser.Model/Net/SocketReceiveResult.cs @@ -20,12 +20,12 @@ namespace MediaBrowser.Model.Net public int ReceivedBytes { get; set; } /// <summary> - /// The <see cref="IPEndPoint"/> the data was received from. + /// Gets or sets the <see cref="IPEndPoint"/> the data was received from. /// </summary> public IPEndPoint RemoteEndPoint { get; set; } /// <summary> - /// The local <see cref="IPAddress"/>. + /// Gets or sets the local <see cref="IPAddress"/>. /// </summary> public IPAddress LocalIPAddress { get; set; } } diff --git a/MediaBrowser.Model/Net/WebSocketMessage.cs b/MediaBrowser.Model/Net/WebSocketMessage.cs index bffbbe612..b00158cb3 100644 --- a/MediaBrowser.Model/Net/WebSocketMessage.cs +++ b/MediaBrowser.Model/Net/WebSocketMessage.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Net /// <summary> /// Class WebSocketMessage. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">The type of the data.</typeparam> public class WebSocketMessage<T> { /// <summary> diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs index 239a3777e..94bb5d6e3 100644 --- a/MediaBrowser.Model/Notifications/NotificationOptions.cs +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -2,18 +2,16 @@ #pragma warning disable CS1591 using System; -using Jellyfin.Data.Enums; -using MediaBrowser.Model.Extensions; using System.Linq; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; +using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Notifications { public class NotificationOptions { - public NotificationOption[] Options { get; set; } - public NotificationOptions() { Options = new[] @@ -71,6 +69,8 @@ namespace MediaBrowser.Model.Notifications }; } + public NotificationOption[] Options { get; set; } + public NotificationOption GetOptions(string type) { foreach (NotificationOption i in Options) @@ -104,7 +104,7 @@ namespace MediaBrowser.Model.Notifications NotificationOption opt = GetOptions(type); return opt != null && opt.Enabled && - !opt.DisabledMonitorUsers.Contains(userId.ToString(""), StringComparer.OrdinalIgnoreCase); + !opt.DisabledMonitorUsers.Contains(userId.ToString(string.Empty), StringComparer.OrdinalIgnoreCase); } public bool IsEnabledToSendToUser(string type, string userId, User user) diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs index febc2bc09..622c50cd8 100644 --- a/MediaBrowser.Model/Notifications/NotificationRequest.cs +++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs @@ -7,6 +7,12 @@ namespace MediaBrowser.Model.Notifications { public class NotificationRequest { + public NotificationRequest() + { + UserIds = Array.Empty<Guid>(); + Date = DateTime.UtcNow; + } + public string Name { get; set; } public string Description { get; set; } @@ -20,16 +26,10 @@ namespace MediaBrowser.Model.Notifications public DateTime Date { get; set; } /// <summary> - /// The corresponding type name used in configuration. Not for display. + /// Gets or sets the corresponding type name used in configuration. Not for display. /// </summary> public string NotificationType { get; set; } public SendToUserType? SendToUserMode { get; set; } - - public NotificationRequest() - { - UserIds = Array.Empty<Guid>(); - Date = DateTime.UtcNow; - } } } diff --git a/MediaBrowser.Model/Providers/ExternalIdInfo.cs b/MediaBrowser.Model/Providers/ExternalIdInfo.cs index afe95e6ee..0ea3e96ca 100644 --- a/MediaBrowser.Model/Providers/ExternalIdInfo.cs +++ b/MediaBrowser.Model/Providers/ExternalIdInfo.cs @@ -6,11 +6,11 @@ namespace MediaBrowser.Model.Providers public class ExternalIdInfo { /// <summary> - /// Represents the external id information for serialization to the client. + /// Initializes a new instance of the <see cref="ExternalIdInfo"/> class. /// </summary> /// <param name="name">Name of the external id provider (IE: IMDB, MusicBrainz, etc).</param> /// <param name="key">Key for this id. This key should be unique across all providers.</param> - /// <param name="type">Specific media type for this id</param> + /// <param name="type">Specific media type for this id.</param> /// <param name="urlFormatString">URL format string.</param> public ExternalIdInfo(string name, string key, ExternalIdMediaType? type, string urlFormatString) { diff --git a/MediaBrowser.Model/Providers/RemoteImageInfo.cs b/MediaBrowser.Model/Providers/RemoteImageInfo.cs index fb25999e0..48207d2d4 100644 --- a/MediaBrowser.Model/Providers/RemoteImageInfo.cs +++ b/MediaBrowser.Model/Providers/RemoteImageInfo.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Model.Providers public string Url { get; set; } /// <summary> - /// Gets a url used for previewing a smaller version. + /// Gets or sets a url used for previewing a smaller version. /// </summary> public string ThumbnailUrl { get; set; } diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index 5702c460b..6ea1e1486 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -7,6 +7,14 @@ namespace MediaBrowser.Model.Providers { public class SubtitleOptions { + public SubtitleOptions() + { + DownloadLanguages = Array.Empty<string>(); + + SkipIfAudioTrackMatches = true; + RequirePerfectMatch = true; + } + public bool SkipIfEmbeddedSubtitlesPresent { get; set; } public bool SkipIfAudioTrackMatches { get; set; } @@ -24,13 +32,5 @@ namespace MediaBrowser.Model.Providers public bool IsOpenSubtitleVipAccount { get; set; } public bool RequirePerfectMatch { get; set; } - - public SubtitleOptions() - { - DownloadLanguages = Array.Empty<string>(); - - SkipIfAudioTrackMatches = true; - RequirePerfectMatch = true; - } } } diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs index 13b1a0dcb..56a7f3320 100644 --- a/MediaBrowser.Model/Querying/EpisodeQuery.cs +++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Querying { public class EpisodeQuery { + public EpisodeQuery() + { + Fields = Array.Empty<ItemFields>(); + } + /// <summary> /// Gets or sets the user identifier. /// </summary> @@ -66,10 +71,5 @@ namespace MediaBrowser.Model.Querying /// </summary> /// <value>The start item identifier.</value> public string StartItemId { get; set; } - - public EpisodeQuery() - { - Fields = Array.Empty<ItemFields>(); - } } } diff --git a/MediaBrowser.Model/Querying/LatestItemsQuery.cs b/MediaBrowser.Model/Querying/LatestItemsQuery.cs index 7954ef4b4..f555ffb36 100644 --- a/MediaBrowser.Model/Querying/LatestItemsQuery.cs +++ b/MediaBrowser.Model/Querying/LatestItemsQuery.cs @@ -14,31 +14,32 @@ namespace MediaBrowser.Model.Querying } /// <summary> - /// The user to localize search results for. + /// Gets or sets the user to localize search results for. /// </summary> /// <value>The user id.</value> public Guid UserId { get; set; } /// <summary> + /// Gets or sets the parent id. /// Specify this to localize the search to a specific item or folder. Omit to use the root. /// </summary> /// <value>The parent id.</value> public Guid ParentId { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Used for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } /// <summary> - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } diff --git a/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs b/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs index 1c8875890..b800f5de5 100644 --- a/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs +++ b/MediaBrowser.Model/Querying/MovieRecommendationQuery.cs @@ -7,6 +7,13 @@ namespace MediaBrowser.Model.Querying { public class MovieRecommendationQuery { + public MovieRecommendationQuery() + { + ItemLimit = 10; + CategoryLimit = 6; + Fields = Array.Empty<ItemFields>(); + } + /// <summary> /// Gets or sets the user identifier. /// </summary> @@ -36,12 +43,5 @@ namespace MediaBrowser.Model.Querying /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } - - public MovieRecommendationQuery() - { - ItemLimit = 10; - CategoryLimit = 6; - Fields = Array.Empty<ItemFields>(); - } } } diff --git a/MediaBrowser.Model/Querying/NextUpQuery.cs b/MediaBrowser.Model/Querying/NextUpQuery.cs index 001d0623c..0555afc00 100644 --- a/MediaBrowser.Model/Querying/NextUpQuery.cs +++ b/MediaBrowser.Model/Querying/NextUpQuery.cs @@ -8,6 +8,13 @@ namespace MediaBrowser.Model.Querying { public class NextUpQuery { + public NextUpQuery() + { + EnableImageTypes = Array.Empty<ImageType>(); + EnableTotalRecordCount = true; + DisableFirstEpisode = false; + } + /// <summary> /// Gets or sets the user id. /// </summary> @@ -27,19 +34,19 @@ namespace MediaBrowser.Model.Querying public string SeriesId { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } /// <summary> - /// Fields to return within the items, in addition to basic information. + /// gets or sets the fields to return within the items, in addition to basic information. /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } @@ -68,12 +75,5 @@ namespace MediaBrowser.Model.Querying /// Gets or sets a value indicating whether do disable sending first episode as next up. /// </summary> public bool DisableFirstEpisode { get; set; } - - public NextUpQuery() - { - EnableImageTypes = Array.Empty<ImageType>(); - EnableTotalRecordCount = true; - DisableFirstEpisode = false; - } } } diff --git a/MediaBrowser.Model/Querying/QueryFilters.cs b/MediaBrowser.Model/Querying/QueryFilters.cs index 6e4d25181..73b27a7b0 100644 --- a/MediaBrowser.Model/Querying/QueryFilters.cs +++ b/MediaBrowser.Model/Querying/QueryFilters.cs @@ -6,35 +6,16 @@ using MediaBrowser.Model.Dto; namespace MediaBrowser.Model.Querying { - public class QueryFiltersLegacy + public class QueryFilters { - public string[] Genres { get; set; } - - public string[] Tags { get; set; } - - public string[] OfficialRatings { get; set; } - - public int[] Years { get; set; } - - public QueryFiltersLegacy() + public QueryFilters() { - Genres = Array.Empty<string>(); Tags = Array.Empty<string>(); - OfficialRatings = Array.Empty<string>(); - Years = Array.Empty<int>(); + Genres = Array.Empty<NameGuidPair>(); } - } - public class QueryFilters - { public NameGuidPair[] Genres { get; set; } public string[] Tags { get; set; } - - public QueryFilters() - { - Tags = Array.Empty<string>(); - Genres = Array.Empty<NameGuidPair>(); - } } } diff --git a/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs b/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs new file mode 100644 index 000000000..fcb450ed3 --- /dev/null +++ b/MediaBrowser.Model/Querying/QueryFiltersLegacy.cs @@ -0,0 +1,26 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Querying +{ + public class QueryFiltersLegacy + { + public QueryFiltersLegacy() + { + Genres = Array.Empty<string>(); + Tags = Array.Empty<string>(); + OfficialRatings = Array.Empty<string>(); + Years = Array.Empty<int>(); + } + + public string[] Genres { get; set; } + + public string[] Tags { get; set; } + + public string[] OfficialRatings { get; set; } + + public int[] Years { get; set; } + } +} diff --git a/MediaBrowser.Model/Querying/QueryResult.cs b/MediaBrowser.Model/Querying/QueryResult.cs index 490f48b84..8ce794800 100644 --- a/MediaBrowser.Model/Querying/QueryResult.cs +++ b/MediaBrowser.Model/Querying/QueryResult.cs @@ -8,6 +8,17 @@ namespace MediaBrowser.Model.Querying { public class QueryResult<T> { + public QueryResult() + { + Items = Array.Empty<T>(); + } + + public QueryResult(IReadOnlyList<T> items) + { + Items = items; + TotalRecordCount = items.Count; + } + /// <summary> /// Gets or sets the items. /// </summary> @@ -15,26 +26,15 @@ namespace MediaBrowser.Model.Querying public IReadOnlyList<T> Items { get; set; } /// <summary> - /// The total number of records available. + /// Gets or sets the total number of records available. /// </summary> /// <value>The total record count.</value> public int TotalRecordCount { get; set; } /// <summary> - /// The index of the first record in Items. + /// Gets or sets the index of the first record in Items. /// </summary> /// <value>First record index.</value> public int StartIndex { get; set; } - - public QueryResult() - { - Items = Array.Empty<T>(); - } - - public QueryResult(IReadOnlyList<T> items) - { - Items = items; - TotalRecordCount = items.Count; - } } } diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs index eb6239460..2cf0f0d5f 100644 --- a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs +++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs @@ -8,6 +8,11 @@ namespace MediaBrowser.Model.Querying { public class UpcomingEpisodesQuery { + public UpcomingEpisodesQuery() + { + EnableImageTypes = Array.Empty<ImageType>(); + } + /// <summary> /// Gets or sets the user id. /// </summary> @@ -21,19 +26,19 @@ namespace MediaBrowser.Model.Querying public string ParentId { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Use for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } /// <summary> - /// Fields to return within the items, in addition to basic information. + /// Gets or sets the fields to return within the items, in addition to basic information. /// </summary> /// <value>The fields.</value> public ItemFields[] Fields { get; set; } @@ -55,10 +60,5 @@ namespace MediaBrowser.Model.Querying /// </summary> /// <value>The enable image types.</value> public ImageType[] EnableImageTypes { get; set; } - - public UpcomingEpisodesQuery() - { - EnableImageTypes = Array.Empty<ImageType>(); - } } } diff --git a/MediaBrowser.Model/Search/SearchQuery.cs b/MediaBrowser.Model/Search/SearchQuery.cs index ce60062cd..aedfa4d36 100644 --- a/MediaBrowser.Model/Search/SearchQuery.cs +++ b/MediaBrowser.Model/Search/SearchQuery.cs @@ -7,8 +7,21 @@ namespace MediaBrowser.Model.Search { public class SearchQuery { + public SearchQuery() + { + IncludeArtists = true; + IncludeGenres = true; + IncludeMedia = true; + IncludePeople = true; + IncludeStudios = true; + + MediaTypes = Array.Empty<string>(); + IncludeItemTypes = Array.Empty<string>(); + ExcludeItemTypes = Array.Empty<string>(); + } + /// <summary> - /// The user to localize search results for. + /// Gets or sets the user to localize search results for. /// </summary> /// <value>The user id.</value> public Guid UserId { get; set; } @@ -20,13 +33,13 @@ namespace MediaBrowser.Model.Search public string SearchTerm { get; set; } /// <summary> - /// Skips over a given number of items within the results. Use for paging. + /// Gets or sets the start index. Used for paging. /// </summary> /// <value>The start index.</value> public int? StartIndex { get; set; } /// <summary> - /// The maximum number of items to return. + /// Gets or sets the maximum number of items to return. /// </summary> /// <value>The limit.</value> public int? Limit { get; set; } @@ -58,18 +71,5 @@ namespace MediaBrowser.Model.Search public bool? IsKids { get; set; } public bool? IsSports { get; set; } - - public SearchQuery() - { - IncludeArtists = true; - IncludeGenres = true; - IncludeMedia = true; - IncludePeople = true; - IncludeStudios = true; - - MediaTypes = Array.Empty<string>(); - IncludeItemTypes = Array.Empty<string>(); - ExcludeItemTypes = Array.Empty<string>(); - } } } diff --git a/MediaBrowser.Model/Session/BrowseRequest.cs b/MediaBrowser.Model/Session/BrowseRequest.cs index 1c997d584..65afe5cf3 100644 --- a/MediaBrowser.Model/Session/BrowseRequest.cs +++ b/MediaBrowser.Model/Session/BrowseRequest.cs @@ -7,6 +7,7 @@ namespace MediaBrowser.Model.Session public class BrowseRequest { /// <summary> + /// Gets or sets the item type. /// Artist, Genre, Studio, Person, or any kind of BaseItem. /// </summary> /// <value>The type of the item.</value> diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs index 5852f4e37..d692906c6 100644 --- a/MediaBrowser.Model/Session/ClientCapabilities.cs +++ b/MediaBrowser.Model/Session/ClientCapabilities.cs @@ -9,6 +9,13 @@ namespace MediaBrowser.Model.Session { public class ClientCapabilities { + public ClientCapabilities() + { + PlayableMediaTypes = Array.Empty<string>(); + SupportedCommands = Array.Empty<GeneralCommandType>(); + SupportsPersistentIdentifier = true; + } + public IReadOnlyList<string> PlayableMediaTypes { get; set; } public IReadOnlyList<GeneralCommandType> SupportedCommands { get; set; } @@ -28,12 +35,5 @@ namespace MediaBrowser.Model.Session public string AppStoreUrl { get; set; } public string IconUrl { get; set; } - - public ClientCapabilities() - { - PlayableMediaTypes = Array.Empty<string>(); - SupportedCommands = Array.Empty<GeneralCommandType>(); - SupportsPersistentIdentifier = true; - } } } diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs index 77bb6bcf7..29528c110 100644 --- a/MediaBrowser.Model/Session/GeneralCommand.cs +++ b/MediaBrowser.Model/Session/GeneralCommand.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -8,15 +7,15 @@ namespace MediaBrowser.Model.Session { public class GeneralCommand { - public GeneralCommandType Name { get; set; } - - public Guid ControllingUserId { get; set; } - - public Dictionary<string, string> Arguments { get; set; } - public GeneralCommand() { Arguments = new Dictionary<string, string>(); } + + public GeneralCommandType Name { get; set; } + + public Guid ControllingUserId { get; set; } + + public Dictionary<string, string> Arguments { get; } } } diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index 73dbe6a2d..a6e7efcb0 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -111,18 +111,4 @@ namespace MediaBrowser.Model.Session public string PlaylistItemId { get; set; } } - - public enum RepeatMode - { - RepeatNone = 0, - RepeatAll = 1, - RepeatOne = 2 - } - - public class QueueItem - { - public Guid Id { get; set; } - - public string PlaylistItemId { get; set; } - } } diff --git a/MediaBrowser.Model/Session/PlaystateCommand.cs b/MediaBrowser.Model/Session/PlaystateCommand.cs index 3aa091f79..df47f3b73 100644 --- a/MediaBrowser.Model/Session/PlaystateCommand.cs +++ b/MediaBrowser.Model/Session/PlaystateCommand.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - namespace MediaBrowser.Model.Session { /// <summary> @@ -46,6 +44,10 @@ namespace MediaBrowser.Model.Session /// The fast forward. /// </summary> FastForward, + + /// <summary> + /// The play pause. + /// </summary> PlayPause } } diff --git a/MediaBrowser.Model/Session/QueueItem.cs b/MediaBrowser.Model/Session/QueueItem.cs new file mode 100644 index 000000000..32b19101b --- /dev/null +++ b/MediaBrowser.Model/Session/QueueItem.cs @@ -0,0 +1,14 @@ +#nullable disable +#pragma warning disable CS1591 + +using System; + +namespace MediaBrowser.Model.Session +{ + public class QueueItem + { + public Guid Id { get; set; } + + public string PlaylistItemId { get; set; } + } +} diff --git a/MediaBrowser.Model/Session/RepeatMode.cs b/MediaBrowser.Model/Session/RepeatMode.cs new file mode 100644 index 000000000..c6e173d6b --- /dev/null +++ b/MediaBrowser.Model/Session/RepeatMode.cs @@ -0,0 +1,11 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Session +{ + public enum RepeatMode + { + RepeatNone = 0, + RepeatAll = 1, + RepeatOne = 2 + } +} diff --git a/MediaBrowser.Model/Session/TranscodeReason.cs b/MediaBrowser.Model/Session/TranscodeReason.cs new file mode 100644 index 000000000..e93b5d288 --- /dev/null +++ b/MediaBrowser.Model/Session/TranscodeReason.cs @@ -0,0 +1,31 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Session +{ + public enum TranscodeReason + { + ContainerNotSupported = 0, + VideoCodecNotSupported = 1, + AudioCodecNotSupported = 2, + ContainerBitrateExceedsLimit = 3, + AudioBitrateNotSupported = 4, + AudioChannelsNotSupported = 5, + VideoResolutionNotSupported = 6, + UnknownVideoStreamInfo = 7, + UnknownAudioStreamInfo = 8, + AudioProfileNotSupported = 9, + AudioSampleRateNotSupported = 10, + AnamorphicVideoNotSupported = 11, + InterlacedVideoNotSupported = 12, + SecondaryAudioNotSupported = 13, + RefFramesNotSupported = 14, + VideoBitDepthNotSupported = 15, + VideoBitrateNotSupported = 16, + VideoFramerateNotSupported = 17, + VideoLevelNotSupported = 18, + VideoProfileNotSupported = 19, + AudioBitDepthNotSupported = 20, + SubtitleCodecNotSupported = 21, + DirectPlayError = 22 + } +} diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs index e832c2f6f..064a087d5 100644 --- a/MediaBrowser.Model/Session/TranscodingInfo.cs +++ b/MediaBrowser.Model/Session/TranscodingInfo.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Session { public class TranscodingInfo { + public TranscodingInfo() + { + TranscodeReasons = Array.Empty<TranscodeReason>(); + } + public string AudioCodec { get; set; } public string VideoCodec { get; set; } @@ -30,37 +35,5 @@ namespace MediaBrowser.Model.Session public int? AudioChannels { get; set; } public TranscodeReason[] TranscodeReasons { get; set; } - - public TranscodingInfo() - { - TranscodeReasons = Array.Empty<TranscodeReason>(); - } - } - - public enum TranscodeReason - { - ContainerNotSupported = 0, - VideoCodecNotSupported = 1, - AudioCodecNotSupported = 2, - ContainerBitrateExceedsLimit = 3, - AudioBitrateNotSupported = 4, - AudioChannelsNotSupported = 5, - VideoResolutionNotSupported = 6, - UnknownVideoStreamInfo = 7, - UnknownAudioStreamInfo = 8, - AudioProfileNotSupported = 9, - AudioSampleRateNotSupported = 10, - AnamorphicVideoNotSupported = 11, - InterlacedVideoNotSupported = 12, - SecondaryAudioNotSupported = 13, - RefFramesNotSupported = 14, - VideoBitDepthNotSupported = 15, - VideoBitrateNotSupported = 16, - VideoFramerateNotSupported = 17, - VideoLevelNotSupported = 18, - VideoProfileNotSupported = 19, - AudioBitDepthNotSupported = 20, - SubtitleCodecNotSupported = 21, - DirectPlayError = 22 } } diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs index b9290b6e8..3e396e5d1 100644 --- a/MediaBrowser.Model/Sync/SyncJob.cs +++ b/MediaBrowser.Model/Sync/SyncJob.cs @@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Sync { public class SyncJob { + public SyncJob() + { + RequestedItemIds = Array.Empty<Guid>(); + } + /// <summary> /// Gets or sets the identifier. /// </summary> @@ -126,10 +131,5 @@ namespace MediaBrowser.Model.Sync public string PrimaryImageItemId { get; set; } public string PrimaryImageTag { get; set; } - - public SyncJob() - { - RequestedItemIds = Array.Empty<Guid>(); - } } } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 4b83fb7e6..d75ae91c0 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -30,6 +30,14 @@ namespace MediaBrowser.Model.System /// </summary> public class SystemInfo : PublicSystemInfo { + /// <summary> + /// Initializes a new instance of the <see cref="SystemInfo" /> class. + /// </summary> + public SystemInfo() + { + CompletedInstallations = Array.Empty<InstallationInfo>(); + } + /// <summary> /// Gets or sets the display name of the operating system. /// </summary> @@ -37,7 +45,7 @@ namespace MediaBrowser.Model.System public string OperatingSystemDisplayName { get; set; } /// <summary> - /// Get or sets the package name. + /// Gets or sets the package name. /// </summary> /// <value>The value of the '-package' command line argument.</value> public string PackageName { get; set; } @@ -127,13 +135,5 @@ namespace MediaBrowser.Model.System public FFmpegLocation EncoderLocation { get; set; } public Architecture SystemArchitecture { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="SystemInfo" /> class. - /// </summary> - public SystemInfo() - { - CompletedInstallations = Array.Empty<InstallationInfo>(); - } } } diff --git a/MediaBrowser.Model/System/WakeOnLanInfo.cs b/MediaBrowser.Model/System/WakeOnLanInfo.cs index b2cbe737d..aba19a6ba 100644 --- a/MediaBrowser.Model/System/WakeOnLanInfo.cs +++ b/MediaBrowser.Model/System/WakeOnLanInfo.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Model.System /// Gets the MAC address of the device. /// </summary> /// <value>The MAC address.</value> - public string? MacAddress { get; set; } + public string? MacAddress { get; } /// <summary> /// Gets or sets the wake-on-LAN port. diff --git a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs index 2f05e08c5..ca769e26b 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Tasks event EventHandler<GenericEventArgs<double>> TaskProgress; /// <summary> - /// Gets or sets the scheduled task. + /// Gets the scheduled task. /// </summary> /// <value>The scheduled task.</value> IScheduledTask ScheduledTask { get; } @@ -57,10 +57,9 @@ namespace MediaBrowser.Model.Tasks double? CurrentProgress { get; } /// <summary> - /// Gets the triggers that define when the task will run. + /// Gets or sets the triggers that define when the task will run. /// </summary> /// <value>The triggers.</value> - /// <exception cref="ArgumentNullException">value</exception> TaskTriggerInfo[] Triggers { get; set; } /// <summary> diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index 02b29074e..a86bf2a1c 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -9,6 +9,10 @@ namespace MediaBrowser.Model.Tasks { public interface ITaskManager : IDisposable { + event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting; + + event EventHandler<TaskCompletionEventArgs> TaskCompleted; + /// <summary> /// Gets the list of Scheduled Tasks. /// </summary> @@ -18,7 +22,7 @@ namespace MediaBrowser.Model.Tasks /// <summary> /// Cancels if running and queue. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">An implementatin of <see cref="IScheduledTask" />.</typeparam> /// <param name="options">Task options.</param> void CancelIfRunningAndQueue<T>(TaskOptions options) where T : IScheduledTask; @@ -26,21 +30,21 @@ namespace MediaBrowser.Model.Tasks /// <summary> /// Cancels if running and queue. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">An implementatin of <see cref="IScheduledTask" />.</typeparam> void CancelIfRunningAndQueue<T>() where T : IScheduledTask; /// <summary> /// Cancels if running. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">An implementatin of <see cref="IScheduledTask" />.</typeparam> void CancelIfRunning<T>() where T : IScheduledTask; /// <summary> /// Queues the scheduled task. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">An implementatin of <see cref="IScheduledTask" />.</typeparam> /// <param name="options">Task options.</param> void QueueScheduledTask<T>(TaskOptions options) where T : IScheduledTask; @@ -48,7 +52,7 @@ namespace MediaBrowser.Model.Tasks /// <summary> /// Queues the scheduled task. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">An implementatin of <see cref="IScheduledTask" />.</typeparam> void QueueScheduledTask<T>() where T : IScheduledTask; @@ -58,6 +62,8 @@ namespace MediaBrowser.Model.Tasks /// <summary> /// Queues the scheduled task. /// </summary> + /// <param name="task">The <see cref="IScheduledTask" /> to queue.</param> + /// <param name="options">The <see cref="TaskOptions" /> to use.</param> void QueueScheduledTask(IScheduledTask task, TaskOptions options); /// <summary> @@ -67,12 +73,10 @@ namespace MediaBrowser.Model.Tasks void AddTasks(IEnumerable<IScheduledTask> tasks); void Cancel(IScheduledTaskWorker task); + Task Execute(IScheduledTaskWorker task, TaskOptions options); void Execute<T>() where T : IScheduledTask; - - event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting; - event EventHandler<TaskCompletionEventArgs> TaskCompleted; } } diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs index 5c30d6c22..cbd60cca1 100644 --- a/MediaBrowser.Model/Tasks/ITaskTrigger.cs +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -21,6 +21,10 @@ namespace MediaBrowser.Model.Tasks /// <summary> /// Stars waiting for the trigger action. /// </summary> + /// <param name="lastResult">Result of the last run triggerd task.</param> + /// <param name="logger">The <see cref="ILogger"/>.</param> + /// <param name="taskName">The name of the task.</param> + /// <param name="isApplicationStartup">Wheter or not this is is fired during startup.</param> void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup); /// <summary> diff --git a/MediaBrowser.Model/Tasks/TaskInfo.cs b/MediaBrowser.Model/Tasks/TaskInfo.cs index 77100dfe7..16de0b121 100644 --- a/MediaBrowser.Model/Tasks/TaskInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskInfo.cs @@ -8,6 +8,14 @@ namespace MediaBrowser.Model.Tasks /// </summary> public class TaskInfo { + /// <summary> + /// Initializes a new instance of the <see cref="TaskInfo"/> class. + /// </summary> + public TaskInfo() + { + Triggers = Array.Empty<TaskTriggerInfo>(); + } + /// <summary> /// Gets or sets the name. /// </summary> @@ -67,13 +75,5 @@ namespace MediaBrowser.Model.Tasks /// </summary> /// <value>The key.</value> public string Key { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="TaskInfo"/> class. - /// </summary> - public TaskInfo() - { - Triggers = Array.Empty<TaskTriggerInfo>(); - } } } diff --git a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs index 5aeaffc2b..f8a8c727e 100644 --- a/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskTriggerInfo.cs @@ -10,6 +10,12 @@ namespace MediaBrowser.Model.Tasks /// </summary> public class TaskTriggerInfo { + public const string TriggerDaily = "DailyTrigger"; + public const string TriggerWeekly = "WeeklyTrigger"; + public const string TriggerInterval = "IntervalTrigger"; + public const string TriggerSystemEvent = "SystemEventTrigger"; + public const string TriggerStartup = "StartupTrigger"; + /// <summary> /// Gets or sets the type. /// </summary> @@ -39,11 +45,5 @@ namespace MediaBrowser.Model.Tasks /// </summary> /// <value>The maximum runtime ticks.</value> public long? MaxRuntimeTicks { get; set; } - - public const string TriggerDaily = "DailyTrigger"; - public const string TriggerWeekly = "WeeklyTrigger"; - public const string TriggerInterval = "IntervalTrigger"; - public const string TriggerSystemEvent = "SystemEventTrigger"; - public const string TriggerStartup = "StartupTrigger"; } } diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 37da04adf..111070d81 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -10,6 +10,56 @@ namespace MediaBrowser.Model.Users { public class UserPolicy { + public UserPolicy() + { + IsHidden = true; + + EnableContentDeletion = false; + EnableContentDeletionFromFolders = Array.Empty<string>(); + + EnableSyncTranscoding = true; + EnableMediaConversion = true; + + EnableMediaPlayback = true; + EnableAudioPlaybackTranscoding = true; + EnableVideoPlaybackTranscoding = true; + EnablePlaybackRemuxing = true; + ForceRemoteSourceTranscoding = false; + EnableLiveTvManagement = true; + EnableLiveTvAccess = true; + + // Without this on by default, admins won't be able to do this + // Improve in the future + EnableLiveTvManagement = true; + + EnableSharedDeviceControl = true; + + BlockedTags = Array.Empty<string>(); + BlockUnratedItems = Array.Empty<UnratedItem>(); + + EnableUserPreferenceAccess = true; + + AccessSchedules = Array.Empty<AccessSchedule>(); + + LoginAttemptsBeforeLockout = -1; + + MaxActiveSessions = 0; + + EnableAllChannels = true; + EnabledChannels = Array.Empty<Guid>(); + + EnableAllFolders = true; + EnabledFolders = Array.Empty<Guid>(); + + EnabledDevices = Array.Empty<string>(); + EnableAllDevices = true; + + EnableContentDownloading = true; + EnablePublicSharing = true; + EnableRemoteAccess = true; + SyncPlayAccess = SyncPlayUserAccessType.CreateAndJoinGroups; + } + /// <summary> /// Gets or sets a value indicating whether this instance is administrator. /// </summary> @@ -112,55 +162,5 @@ namespace MediaBrowser.Model.Users /// </summary> /// <value>Access level to SyncPlay features.</value> public SyncPlayUserAccessType SyncPlayAccess { get; set; } - - public UserPolicy() - { - IsHidden = true; - - EnableContentDeletion = false; - EnableContentDeletionFromFolders = Array.Empty<string>(); - - EnableSyncTranscoding = true; - EnableMediaConversion = true; - - EnableMediaPlayback = true; - EnableAudioPlaybackTranscoding = true; - EnableVideoPlaybackTranscoding = true; - EnablePlaybackRemuxing = true; - ForceRemoteSourceTranscoding = false; - EnableLiveTvManagement = true; - EnableLiveTvAccess = true; - - // Without this on by default, admins won't be able to do this - // Improve in the future - EnableLiveTvManagement = true; - - EnableSharedDeviceControl = true; - - BlockedTags = Array.Empty<string>(); - BlockUnratedItems = Array.Empty<UnratedItem>(); - - EnableUserPreferenceAccess = true; - - AccessSchedules = Array.Empty<AccessSchedule>(); - - LoginAttemptsBeforeLockout = -1; - - MaxActiveSessions = 0; - - EnableAllChannels = true; - EnabledChannels = Array.Empty<Guid>(); - - EnableAllFolders = true; - EnabledFolders = Array.Empty<Guid>(); - - EnabledDevices = Array.Empty<string>(); - EnableAllDevices = true; - - EnableContentDownloading = true; - EnablePublicSharing = true; - EnableRemoteAccess = true; - SyncPlayAccess = SyncPlayUserAccessType.CreateAndJoinGroups; - } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index fa09bfb66..81337390c 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -32,6 +32,8 @@ <Rule Id="SA1515" Action="None" /> <!-- disable warning SA1600: Elements should be documented --> <Rule Id="SA1600" Action="None" /> + <!-- disable warning SA1602: Enumeration items should be documented --> + <Rule Id="SA1602" Action="None" /> <!-- disable warning SA1633: The file header is missing or not located at the top of the file --> <Rule Id="SA1633" Action="None" /> </Rules> diff --git a/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs b/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs index 544a74637..92c534eae 100644 --- a/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs +++ b/tests/Jellyfin.Api.Tests/ModelBinders/TestType.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace Jellyfin.Api.Tests.ModelBinders { public enum TestType { -#pragma warning disable SA1602 // Enumeration items should be documented How, Much, Is, The, Fish -#pragma warning restore SA1602 // Enumeration items should be documented } } -- cgit v1.2.3 From b1fe28d0a6c1bbc67543fc1b5877a69f7958f8c5 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 21 Feb 2021 02:58:30 +0100 Subject: Use GetEncodingOptions where possible --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 5 ----- Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs | 2 +- Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +++--- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 5ef83f274..0760e8127 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -335,11 +335,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return new Uri(url).AbsoluteUri.TrimEnd('/'); } - protected EncodingOptions GetEncodingOptions() - { - return Config.GetConfiguration<EncodingOptions>("encoding"); - } - private static string GetHdHrIdFromChannelId(string channelId) { return channelId.Split('_')[1]; diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 872a46824..e33e552ed 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -98,7 +98,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private EncodingOptions GetOptions() { - return _config.GetConfiguration<EncodingOptions>("encoding"); + return _config.GetEncodingOptions(); } private async void TimerCallback(object? state) diff --git a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs index 0925a87b5..bf0225e98 100644 --- a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs +++ b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs @@ -32,7 +32,7 @@ namespace Jellyfin.Server.Migrations.Routines public void Perform() { // Set EnableThrottling to false since it wasn't used before and may introduce issues - var encoding = _configManager.GetConfiguration<EncodingOptions>("encoding"); + var encoding = _configManager.GetEncodingOptions(); if (encoding.EnableThrottling) { _logger.LogInformation("Disabling transcoding throttling during migration"); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index c0b6cf28b..45872b5c0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -103,7 +103,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetFFmpegPath() { // 1) Custom path stored in config/encoding xml file under tag <EncoderAppPath> takes precedence - if (!ValidatePath(_configurationManager.GetConfiguration<EncodingOptions>("encoding").EncoderAppPath, FFmpegLocation.Custom)) + if (!ValidatePath(_configurationManager.GetEncodingOptions().EncoderAppPath, FFmpegLocation.Custom)) { // 2) Check if the --ffmpeg CLI switch has been given if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument)) @@ -118,7 +118,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPathDisplay> so it appears in UI - var config = _configurationManager.GetConfiguration<EncodingOptions>("encoding"); + var config = _configurationManager.GetEncodingOptions(); config.EncoderAppPathDisplay = _ffmpegPath ?? string.Empty; _configurationManager.SaveConfiguration("encoding", config); @@ -177,7 +177,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Write the new ffmpeg path to the xml as <EncoderAppPath> // This ensures its not lost on next startup - var config = _configurationManager.GetConfiguration<EncodingOptions>("encoding"); + var config = _configurationManager.GetEncodingOptions(); config.EncoderAppPath = newPath; _configurationManager.SaveConfiguration("encoding", config); -- cgit v1.2.3 From 473a9956503d2b8b361c3b4ebe65a22303b31172 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Sun, 21 Feb 2021 15:53:20 +0000 Subject: Update SubtitleEncoder.cs --- .../Subtitles/SubtitleEncoder.cs | 47 +++++++++------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index b92c4ee06..c4c0e2a90 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -168,33 +168,25 @@ namespace MediaBrowser.MediaEncoding.Subtitles MediaStream subtitleStream, CancellationToken cancellationToken) { - var inputFile = mediaSource.Path; + var fileInfo = await GetReadableFile(mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false); - var protocol = mediaSource.Protocol; - if (subtitleStream.IsExternal) - { - protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path); - } - - var fileInfo = await GetReadableFile(mediaSource.Path, inputFile, mediaSource, subtitleStream, cancellationToken).ConfigureAwait(false); - - var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo, cancellationToken).ConfigureAwait(false); return (stream, fileInfo.Format); } - private async Task<Stream> GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) + private async Task<Stream> GetSubtitleStream(SubtitleInfo fileInfo, CancellationToken cancellationToken) { - if (requiresCharset) + if (fileInfo.IsExternal) { - using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) + using (var stream = await GetStream(fileInfo.Path, fileInfo.Protocol, cancellationToken).ConfigureAwait(false)) { var result = CharsetDetector.DetectFromStream(stream).Detected; stream.Position = 0; if (result != null) { - _logger.LogDebug("charset {CharSet} detected for {Path}", result.EncodingName, path); + _logger.LogDebug("charset {CharSet} detected for {Path}", result.EncodingName, fileInfo.Path); using var reader = new StreamReader(stream, result.Encoding); var text = await reader.ReadToEndAsync().ConfigureAwait(false); @@ -204,12 +196,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - return File.OpenRead(path); + return File.OpenRead(fileInfo.Path); } private async Task<SubtitleInfo> GetReadableFile( - string mediaPath, - string inputFile, MediaSourceInfo mediaSource, MediaStream subtitleStream, CancellationToken cancellationToken) @@ -241,9 +231,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles } // Extract - var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, "." + outputFormat); + var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + outputFormat); - await ExtractTextSubtitle(inputFile, mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken) + await ExtractTextSubtitle(mediaSource, subtitleStream.Index, outputCodec, outputPath, cancellationToken) .ConfigureAwait(false); return new SubtitleInfo(outputPath, MediaProtocol.File, outputFormat, false); @@ -255,13 +245,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (GetReader(currentFormat, false) == null) { // Convert - var outputPath = GetSubtitleCachePath(mediaPath, mediaSource, subtitleStream.Index, ".srt"); + var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, ".srt"); await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false); return new SubtitleInfo(outputPath, MediaProtocol.File, "srt", true); } + if (subtitleStream.IsExternal) + { + return new SubtitleInfo(subtitleStream.Path, _mediaSourceManager.GetPathProtocol(subtitleStream.Path), currentFormat, true); + } + return new SubtitleInfo(subtitleStream.Path, mediaSource.Protocol, currentFormat, true); } @@ -504,7 +499,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <summary> /// Extracts the text subtitle. /// </summary> - /// <param name="inputFile">The input file.</param> /// <param name="mediaSource">The mediaSource.</param> /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> /// <param name="outputCodec">The output codec.</param> @@ -513,7 +507,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// <returns>Task.</returns> /// <exception cref="ArgumentException">Must use inputPath list overload.</exception> private async Task ExtractTextSubtitle( - string inputFile, MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputCodec, @@ -529,7 +522,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!File.Exists(outputPath)) { await ExtractTextSubtitleInternal( - _mediaEncoder.GetInputArgument(inputFile, mediaSource), + _mediaEncoder.GetInputArgument(mediaSource.Path, mediaSource), subtitleStreamIndex, outputCodec, outputPath, @@ -695,15 +688,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private string GetSubtitleCachePath(string mediaPath, MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputSubtitleExtension) + private string GetSubtitleCachePath(MediaSourceInfo mediaSource, int subtitleStreamIndex, string outputSubtitleExtension) { if (mediaSource.Protocol == MediaProtocol.File) { var ticksParam = string.Empty; - var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); + var date = _fileSystem.GetLastWriteTimeUtc(mediaSource.Path); - ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension; + ReadOnlySpan<char> filename = (mediaSource.Path + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension; var prefix = filename.Slice(0, 1); @@ -711,7 +704,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } else { - ReadOnlySpan<char> filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension; + ReadOnlySpan<char> filename = (mediaSource.Path + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension; var prefix = filename.Slice(0, 1); -- cgit v1.2.3 From fef43c556d3987b008aab882f409e780c4b36b82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 12:00:38 +0000 Subject: Bump libse from 3.5.8 to 3.6.0 Bumps [libse](https://github.com/SubtitleEdit/subtitleedit) from 3.5.8 to 3.6.0. - [Release notes](https://github.com/SubtitleEdit/subtitleedit/releases) - [Changelog](https://github.com/SubtitleEdit/subtitleedit/blob/master/Changelog.txt) - [Commits](https://github.com/SubtitleEdit/subtitleedit/compare/3.5.8...3.6.0) Signed-off-by: dependabot[bot] <support@github.com> --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 61daf50b3..3d6b4f98a 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,7 +24,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> - <PackageReference Include="libse" Version="3.5.8" /> + <PackageReference Include="libse" Version="3.6.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="UTF.Unknown" Version="2.3.0" /> -- cgit v1.2.3 From 60ffa6f514656ed7256b555d483771c36164fce7 Mon Sep 17 00:00:00 2001 From: David <daullmer@gmail.com> Date: Sun, 7 Mar 2021 14:43:28 +0100 Subject: Use FileShare.None when creating files --- Emby.Dlna/DlnaManager.cs | 3 ++- Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 3 ++- Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs | 6 ++++-- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 6 ++++-- Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs | 3 ++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 3 ++- Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs | 3 ++- Jellyfin.Api/Controllers/ItemLookupController.cs | 3 ++- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 ++- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 3 ++- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 3 ++- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 3 ++- MediaBrowser.Providers/Manager/ImageSaver.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs | 3 ++- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 3 ++- 16 files changed, 36 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 9ab324038..d7b75f979 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -395,7 +395,8 @@ namespace Emby.Dlna { Directory.CreateDirectory(systemProfilesPath); - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 77819c764..3f7076383 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -53,7 +53,8 @@ namespace Emby.Server.Implementations.AppBase Directory.CreateDirectory(directory); // Save it after load in case we got new items - using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(newBytes, 0, newBytesLen); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 341194f23..7a6b1d8b6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -45,7 +45,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None)) { onStarted(); @@ -70,7 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 13b5a1c55..91a21db60 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1856,7 +1856,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { @@ -1920,7 +1921,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 78a82118e..40b934d32 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -91,7 +91,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index b16ccc561..08832bae1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -193,7 +193,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var resolved = false; - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) { while (true) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index eeb2426f4..233c3d83a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -136,7 +136,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.None); await StreamHelper.CopyToAsync( stream, fileStream, diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index dfc68ffce..dabd4deb7 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -344,11 +344,12 @@ namespace Jellyfin.Api.Controllers Directory.CreateDirectory(directory); using (var stream = result.Content) { + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . await using var fileStream = new FileStream( fullCachePath, FileMode.Create, FileAccess.Write, - FileShare.Read, + FileShare.None, IODefaults.FileStreamBufferSize, true); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 5284888d8..e226adc64 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -259,7 +259,8 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 240d132b1..7cd9024b0 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -553,7 +553,8 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index a337521c6..e59fcb965 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -133,7 +133,8 @@ namespace MediaBrowser.LocalMetadata.Savers // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.CopyTo(filestream); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d19538730..fbb1563bb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -677,7 +677,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) using (var writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 9dd87aef5..5bb85be7b 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -261,7 +261,8 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index f463a3566..0a79f5bb5 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -171,7 +171,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 7a15adb8e..4b1d91567 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -155,7 +155,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 47e9d5ee8..d4d79d27b 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -228,7 +228,8 @@ namespace MediaBrowser.Providers.Subtitles { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, FileStreamBufferSize, true)) + // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . + using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, true)) { await stream.CopyToAsync(fs).ConfigureAwait(false); } -- cgit v1.2.3 From 9ed7f429c01c3f54a154442250d3447fd66d1b02 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 9 Mar 2021 03:04:47 +0100 Subject: FxCop -> Net Analyzers (part 1) --- Emby.Dlna/Emby.Dlna.csproj | 1 - Emby.Drawing/Emby.Drawing.csproj | 1 - Emby.Naming/Emby.Naming.csproj | 1 - Emby.Notifications/Emby.Notifications.csproj | 1 - Emby.Photos/Emby.Photos.csproj | 1 - .../Emby.Server.Implementations.csproj | 1 - Jellyfin.Api/Jellyfin.Api.csproj | 1 - Jellyfin.Data/Jellyfin.Data.csproj | 1 - Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 1 - Jellyfin.Networking/Jellyfin.Networking.csproj | 1 - .../Jellyfin.Server.Implementations.csproj | 1 - Jellyfin.Server/Jellyfin.Server.csproj | 1 - Jellyfin.sln | 14 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 1 - .../MediaBrowser.Controller.csproj | 1 - .../MediaBrowser.LocalMetadata.csproj | 1 - .../BdInfo/BdInfoDirectoryInfo.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 92 +--- MediaBrowser.MediaEncoding/FfmpegException.cs | 39 ++ .../MediaBrowser.MediaEncoding.csproj | 8 +- .../Probing/ProbeResultNormalizer.cs | 18 +- .../Subtitles/SubtitleEncoder.cs | 6 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 9 +- .../MediaBrowser.Providers.csproj | 8 +- .../MediaBrowser.XbmcMetadata.csproj | 8 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 4 +- .../Providers/BaseVideoNfoProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs | 18 +- MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs | 13 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 16 +- .../Savers/EpisodeNfoSaver.cs | 31 +- MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs | 17 +- MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs | 11 +- MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs | 21 +- jellyfin.ruleset | 8 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 8 +- .../Jellyfin.Common.Tests.csproj | 8 +- .../Jellyfin.Controller.Tests.csproj | 8 +- .../Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 8 +- .../Jellyfin.MediaEncoding.Tests.csproj | 8 +- .../Jellyfin.Model.Tests.csproj | 8 +- .../AudioBook/AudioBookResolverTests.cs | 4 +- .../Jellyfin.Naming.Tests.csproj | 10 +- .../Video/VideoResolverTests.cs | 4 +- .../Jellyfin.Networking.Tests.csproj | 42 ++ .../Jellyfin.Networking.Tests/NetworkParseTests.cs | 518 ++++++++++++++++++++ .../Jellyfin.Networking.Tests.csproj | 39 -- .../NetworkTesting/NetworkParseTests.cs | 519 --------------------- .../Jellyfin.Server.Implementations.Tests.csproj | 8 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 8 +- 50 files changed, 750 insertions(+), 810 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/FfmpegException.cs create mode 100644 tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj create mode 100644 tests/Jellyfin.Networking.Tests/NetworkParseTests.cs delete mode 100644 tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj delete mode 100644 tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 8b057a095..480621dd7 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -25,7 +25,6 @@ <!-- 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" /> diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 7d479a5c6..5c5afe1c6 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -25,7 +25,6 @@ <!-- Code analysers--> <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" /> diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index b43203e9d..63116f368 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -44,7 +44,6 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <!-- TODO: <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" /> diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 16ee918c4..526a27229 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -25,7 +25,6 @@ <!-- 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" /> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 62e33e6c4..e64a658c5 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -28,7 +28,6 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f03f04e02..5a9792b51 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -49,7 +49,6 @@ <!-- 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" /> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 67d0a3b5a..d5372d752 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -28,7 +28,6 @@ <!-- 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" /> diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index a8ac45645..42731bb11 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -34,7 +34,6 @@ <!-- Code analysers--> <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" /> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 466a12e67..1a8415ae0 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -32,7 +32,6 @@ <!-- Code analysers--> <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" /> diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index cbda74361..f89a18426 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -13,7 +13,6 @@ <!-- 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" /> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 4f24da0ee..19c7ac567 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -14,7 +14,6 @@ <!-- Code analysers--> <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" /> diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index bf4f80669..6bfb5b878 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -26,7 +26,6 @@ <!-- 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" /> diff --git a/Jellyfin.sln b/Jellyfin.sln index d83013dab..02ac1c7e9 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -68,14 +68,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server.Implementat EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking", "Jellyfin.Networking\Jellyfin.Networking.csproj", "{0A3FCC4D-C714-4072-B90F-E374A15F9FF9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\NetworkTesting\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Dlna.Tests", "tests\Jellyfin.Dlna.Tests\Jellyfin.Dlna.Tests.csproj", "{B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.XbmcMetadata.Tests", "tests\Jellyfin.XbmcMetadata.Tests\Jellyfin.XbmcMetadata.Tests.csproj", "{30922383-D513-4F4D-B890-A940B57FA353}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Model.Tests", "tests\Jellyfin.Model.Tests\Jellyfin.Model.Tests.csproj", "{FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -190,10 +190,6 @@ Global {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0A3FCC4D-C714-4072-B90F-E374A15F9FF9}.Release|Any CPU.Build.0 = Release|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -206,6 +202,10 @@ Global {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}.Release|Any CPU.Build.0 = Release|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -217,10 +217,10 @@ Global {A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {462584F7-5023-4019-9EAC-B98CA458C0A0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} - {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {30922383-D513-4F4D-B890-A940B57FA353} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 8bb30c565..34e1934e2 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -46,7 +46,6 @@ <!-- 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" /> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6b1c096ac..d487a324f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -47,7 +47,6 @@ <!-- 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" /> diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 3ce9ff4cc..1792f1d9b 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -24,7 +24,6 @@ <!-- 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" /> diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index 4a54b677d..ef9943722 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo _impl.FullName, new[] { searchPattern }, false, - searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), + (searchOption & System.IO.SearchOption.AllDirectories) == System.IO.SearchOption.AllDirectories).ToArray(), x => new BdInfoFileInfo(x)); } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a52019384..8a25a64c7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -448,7 +448,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (result == null || (result.Streams == null && result.Format == null)) { - throw new Exception("ffprobe failed - streams and format are both null."); + throw new FfmpegException("ffprobe failed - streams and format are both null."); } if (result.Streams != null) @@ -571,32 +571,18 @@ namespace MediaBrowser.MediaEncoding.Encoder // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar - var vf = string.Empty; - - if (threedFormat.HasValue) + var vf = threedFormat switch { - switch (threedFormat.Value) - { - case Video3DFormat.HalfSideBySide: - vf = "-vf crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. - break; - case Video3DFormat.FullSideBySide: - vf = "-vf crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // fsbs crop width in half,set the display aspect,crop out any black bars we may have made - break; - case Video3DFormat.HalfTopAndBottom: - vf = "-vf crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made - break; - case Video3DFormat.FullTopAndBottom: - vf = "-vf crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1"; - // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made - break; - default: - break; - } - } + // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. + Video3DFormat.HalfSideBySide => "-vf crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // fsbs crop width in half,set the display aspect,crop out any black bars we may have made + Video3DFormat.FullSideBySide => "-vf crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made + Video3DFormat.HalfTopAndBottom => "-vf crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made + Video3DFormat.FullTopAndBottom => "-vf crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + _ => string.Empty + }; var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; @@ -604,7 +590,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (enableHdrExtraction) { string tonemapFilters = "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0:peak=100,zscale=t=bt709:m=bt709,format=yuv420p"; - if (string.IsNullOrEmpty(vf)) + if (vf.Length == 0) { vf = "-vf " + tonemapFilters; } @@ -633,35 +619,11 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); - var probeSizeArgument = string.Empty; - var analyzeDurationArgument = string.Empty; - - if (!string.IsNullOrWhiteSpace(probeSizeArgument)) - { - args = probeSizeArgument + " " + args; - } - - if (!string.IsNullOrWhiteSpace(analyzeDurationArgument)) - { - args = analyzeDurationArgument + " " + args; - } - if (offset.HasValue) { args = string.Format(CultureInfo.InvariantCulture, "-ss {0} ", GetTimeParameter(offset.Value)) + args; } - if (videoStream != null) - { - /* fix - var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions()); - if (!string.IsNullOrWhiteSpace(decoder)) - { - args = decoder + " " + args; - } - */ - } - if (!string.IsNullOrWhiteSpace(container)) { var inputFormat = EncodingHelper.GetInputFormat(container); @@ -723,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } return tempExtractPath; @@ -770,30 +732,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); - var probeSizeArgument = string.Empty; - var analyzeDurationArgument = string.Empty; - - if (!string.IsNullOrWhiteSpace(probeSizeArgument)) - { - args = probeSizeArgument + " " + args; - } - - if (!string.IsNullOrWhiteSpace(analyzeDurationArgument)) - { - args = analyzeDurationArgument + " " + args; - } - - if (videoStream != null) - { - /* fix - var decoder = encodinghelper.GetHardwareAcceleratedVideoDecoder(VideoType.VideoFile, videoStream, GetEncodingOptions()); - if (!string.IsNullOrWhiteSpace(decoder)) - { - args = decoder + " " + args; - } - */ - } - if (!string.IsNullOrWhiteSpace(container)) { var inputFormat = EncodingHelper.GetInputFormat(container); @@ -872,7 +810,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } } } diff --git a/MediaBrowser.MediaEncoding/FfmpegException.cs b/MediaBrowser.MediaEncoding/FfmpegException.cs new file mode 100644 index 000000000..1697fd33a --- /dev/null +++ b/MediaBrowser.MediaEncoding/FfmpegException.cs @@ -0,0 +1,39 @@ +using System; + +namespace MediaBrowser.MediaEncoding +{ + /// <summary> + /// Represents errors that occur during interaction with FFmpeg. + /// </summary> + public class FfmpegException : Exception + { + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class. + /// </summary> + public FfmpegException() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message. + /// </summary> + /// <param name="message">The message that describes the error.</param> + public FfmpegException(string message) : base(message) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message and a + /// reference to the inner exception that is the cause of this exception. + /// </summary> + /// <param name="message">The error message that explains the reason for the exception.</param> + /// <param name="innerException"> + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if + /// no inner exception is specified. + /// </param> + public FfmpegException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 3d6b4f98a..de00920ba 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -10,6 +10,9 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -30,13 +33,8 @@ <PackageReference Include="UTF.Unknown" Version="2.3.0" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <!-- 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" /> diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index b9cb49cf2..75067315f 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -640,7 +640,7 @@ namespace MediaBrowser.MediaEncoding.Probing } // Filter out junk - if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString) && streamInfo.CodecTagString.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + if (!string.IsNullOrWhiteSpace(streamInfo.CodecTagString) && !streamInfo.CodecTagString.Contains("[0]", StringComparison.OrdinalIgnoreCase)) { stream.CodecTag = streamInfo.CodecTagString; } @@ -1500,11 +1500,23 @@ namespace MediaBrowser.MediaEncoding.Probing } else { - throw new Exception(); // Switch to default parsing + // Switch to default parsing + if (subtitle.Contains('.', StringComparison.Ordinal)) + { + // skip the comment, keep the subtitle + description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + } + else + { + description = subtitle.Trim(); // Clean up whitespaces and save it + } } } - catch // Default parsing + catch (Exception ex) { + _logger.LogError(ex, "Error while parsing subtitle field"); + + // Default parsing if (subtitle.Contains('.', StringComparison.Ordinal)) { // skip the comment, keep the subtitle diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index fbb1563bb..39bec8da1 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -25,7 +25,7 @@ using UtfUnknown; namespace MediaBrowser.MediaEncoding.Subtitles { - public class SubtitleEncoder : ISubtitleEncoder + public sealed class SubtitleEncoder : ISubtitleEncoder { private readonly ILogger<SubtitleEncoder> _logger; private readonly IApplicationPaths _appPaths; @@ -484,7 +484,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.LogError("ffmpeg subtitle conversion failed for {Path}", inputPath); - throw new Exception( + throw new FfmpegException( string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath)); } @@ -637,7 +637,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.LogError(msg); - throw new Exception(msg); + throw new FfmpegException(msg); } else { diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b6d916913..30403219f 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -19,7 +19,9 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <LangVersion>latest</LangVersion> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode> --> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> @@ -44,7 +46,6 @@ <!-- 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" /> @@ -53,8 +54,4 @@ <ProjectReference Include="..\Jellyfin.Data\Jellyfin.Data.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 071a149db..5e7b8043f 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -30,20 +30,18 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode Condition=" '$(Configuration)' == 'Debug'">AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- 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> - <ItemGroup> <None Remove="Plugins\AudioDb\Configuration\config.html" /> <EmbeddedResource Include="Plugins\AudioDb\Configuration\config.html" /> diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 40f06c731..95327d3ae 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -20,18 +20,16 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- 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/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 6f164caf3..c4bbaf301 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1168,11 +1168,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// <returns>IEnumerable{System.String}.</returns> private IEnumerable<string> SplitNames(string value) { - value = value ?? string.Empty; - // Only split by comma if there is no pipe in the string // We have to be careful to not split names like Matthew, Jr. - var separator = value.IndexOf('|', StringComparison.Ordinal) == -1 && value.IndexOf(';', StringComparison.Ordinal) == -1 + var separator = !value.Contains('|', StringComparison.Ordinal) && !value.Contains(';', StringComparison.Ordinal) ? new[] { ',' } : new[] { '|', ';' }; diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs index af722748b..64cfc098f 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.XbmcMetadata.Providers private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; - public BaseVideoNfoProvider( + protected BaseVideoNfoProvider( ILogger<BaseVideoNfoProvider<T>> logger, IFileSystem fileSystem, IConfigurationManager config, diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs index c22f77dcd..2385e7048 100644 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs @@ -96,18 +96,16 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange( - new string[] - { - "track", - "artist", - "albumartist" - }); + foreach (var tag in base.GetTagsUsed(item)) + { + yield return tag; + } - return list; + yield return "track"; + yield return "artist"; + yield return "albumartist"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs index 6365cdecb..71b58cddb 100644 --- a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs @@ -88,16 +88,15 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "album", - "disbanded" - }); + yield return tag; + } - return list; + yield return "album"; + yield return "disbanded"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 0edab3787..3be35e2d9 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -166,19 +166,16 @@ namespace MediaBrowser.XbmcMetadata.Savers /// <inheritdoc /> public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType); - protected virtual List<string> GetTagsUsed(BaseItem item) + protected virtual IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = new List<string>(); foreach (var providerKey in item.ProviderIds.Keys) { var providerIdTagName = GetTagForProviderKey(providerKey); if (!_commonTags.Contains(providerIdTagName)) { - list.Add(providerIdTagName); + yield return providerIdTagName; } } - - return list; } /// <inheritdoc /> @@ -261,7 +258,7 @@ namespace MediaBrowser.XbmcMetadata.Savers AddMediaInfo(hasMediaSources, writer); } - var tagsUsed = GetTagsUsed(item); + var tagsUsed = GetTagsUsed(item).ToList(); try { @@ -351,10 +348,7 @@ namespace MediaBrowser.XbmcMetadata.Savers } var scanType = stream.IsInterlaced ? "interlaced" : "progressive"; - if (!string.IsNullOrEmpty(scanType)) - { - writer.WriteElementString("scantype", scanType); - } + writer.WriteElementString("scantype", scanType); if (stream.Channels.HasValue) { @@ -968,7 +962,7 @@ namespace MediaBrowser.XbmcMetadata.Savers => string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - private void AddCustomTags(string path, List<string> xmlTagsUsed, XmlWriter writer, ILogger<BaseNfoSaver> logger) + private void AddCustomTags(string path, IReadOnlyCollection<string> xmlTagsUsed, XmlWriter writer, ILogger<BaseNfoSaver> logger) { var settings = new XmlReaderSettings() { diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs index 5d3d17893..62f80e81b 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -111,24 +111,23 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "aired", - "season", - "episode", - "episodenumberend", - "airsafter_season", - "airsbefore_episode", - "airsbefore_season", - "displayseason", - "displayepisode", - "showtitle" - }); - - return list; + yield return tag; + } + + yield return "aired"; + yield return "season"; + yield return "episode"; + yield return "episodenumberend"; + yield return "airsafter_season"; + yield return "airsbefore_episode"; + yield return "airsbefore_season"; + yield return "displayseason"; + yield return "displayepisode"; + yield return "showtitle"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index 841121735..412e8031b 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -123,18 +123,17 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "album", - "artist", - "set", - "id" - }); + yield return tag; + } - return list; + yield return "album"; + yield return "artist"; + yield return "set"; + yield return "id"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs index 925a230bd..b9d73ba82 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs @@ -72,15 +72,14 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "seasonnumber" - }); + yield return tag; + } - return list; + yield return "seasonnumber"; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs index 42285db76..083f22e5d 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs @@ -90,20 +90,19 @@ namespace MediaBrowser.XbmcMetadata.Savers } /// <inheritdoc /> - protected override List<string> GetTagsUsed(BaseItem item) + protected override IEnumerable<string> GetTagsUsed(BaseItem item) { - var list = base.GetTagsUsed(item); - list.AddRange(new string[] + foreach (var tag in base.GetTagsUsed(item)) { - "id", - "episodeguide", - "season", - "episode", - "status", - "displayorder" - }); + yield return tag; + } - return list; + yield return "id"; + yield return "episodeguide"; + yield return "season"; + yield return "episode"; + yield return "status"; + yield return "displayorder"; } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 81337390c..b012d2b00 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -38,7 +38,7 @@ <Rule Id="SA1633" Action="None" /> </Rules> - <Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design"> + <Rules AnalyzerId="Microsoft.CodeAnalysis.NetAnalyzers" RuleNamespace="Microsoft.Design"> <!-- error on CA2016: Forward the CancellationToken parameter to methods that take one or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token --> <Rule Id="CA2016" Action="Error" /> @@ -53,6 +53,8 @@ <Rule Id="CA1716" Action="Info" /> <!-- disable warning CA1720: Identifiers should not contain type names --> <Rule Id="CA1720" Action="Info" /> + <!-- disable warning CA1805: Do not initialize unnecessarily --> + <Rule Id="CA1805" Action="Info" /> <!-- disable warning CA1812: internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static members, make it static --> @@ -61,7 +63,11 @@ <Rule Id="CA1822" Action="Info" /> <!-- disable warning CA2000: Dispose objects before losing scope --> <Rule Id="CA2000" Action="Info" /> + <!-- disable warning CA5394: Do not use insecure randomness --> + <Rule Id="CA5394" Action="Info" /> + <!-- disable warning CA1014: Mark assemblies with CLSCompliantAttribute --> + <Rule Id="CA1014" Action="Info" /> <!-- disable warning CA1054: Change the type of parameter url from string to System.Uri --> <Rule Id="CA1054" Action="None" /> <!-- disable warning CA1055: URI return values should not be strings --> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 873ff0ab4..0d8176bb2 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -10,6 +10,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -27,7 +30,6 @@ <!-- 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" /> @@ -37,10 +39,6 @@ <ProjectReference Include="..\..\Jellyfin.Server\Jellyfin.Server.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <EmbeddedResource Include="TestPage.html" /> </ItemGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 278f34109..78e3061f7 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -10,6 +10,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -21,7 +24,6 @@ <!-- 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" /> @@ -32,8 +34,4 @@ <ProjectReference Include="../../MediaBrowser.Providers/MediaBrowser.Providers.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index b02a68a3d..df1eb8617 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -10,6 +10,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -21,7 +24,6 @@ <!-- 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" /> @@ -31,8 +33,4 @@ <ProjectReference Include="../../MediaBrowser.Controller/MediaBrowser.Controller.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 850db1c75..d173d5c93 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -5,6 +5,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -16,7 +19,6 @@ <!-- 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" /> @@ -26,8 +28,4 @@ <ProjectReference Include="../../Emby.Dlna/Emby.Dlna.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e729dbb09..84306e0f7 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -10,6 +10,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -27,7 +30,6 @@ <!-- 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" /> @@ -37,8 +39,4 @@ <ProjectReference Include="../../MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index b6d2c63bd..b458c06ff 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -5,6 +5,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -16,7 +19,6 @@ <!-- 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" /> @@ -26,8 +28,4 @@ <ProjectReference Include="../../MediaBrowser.Model/MediaBrowser.Model.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs index b3257ace3..ad63adadc 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs @@ -10,7 +10,7 @@ namespace Jellyfin.Naming.Tests.AudioBook { private readonly NamingOptions _namingOptions = new NamingOptions(); - public static IEnumerable<object[]> GetResolveFileTestData() + public static IEnumerable<object[]> Resolve_ValidFileNameTestData() { yield return new object[] { @@ -36,7 +36,7 @@ namespace Jellyfin.Naming.Tests.AudioBook } [Theory] - [MemberData(nameof(GetResolveFileTestData))] + [MemberData(nameof(Resolve_ValidFileNameTestData))] public void Resolve_ValidFileName_Success(AudioBookFileInfo expectedResult) { var result = new AudioBookResolver(_namingOptions).Resolve(expectedResult.Path); diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 99185c975..0f8a0333a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -8,8 +8,11 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -25,14 +28,9 @@ <!-- 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-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs index ba5eaf1af..9bbbe2970 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoResolverTests.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Naming.Tests.Video { private readonly VideoResolver _videoResolver = new VideoResolver(new NamingOptions()); - public static IEnumerable<object[]> GetResolveFileTestData() + public static IEnumerable<object[]> ResolveFile_ValidFileNameTestData() { yield return new object[] { @@ -156,7 +156,7 @@ namespace Jellyfin.Naming.Tests.Video } [Theory] - [MemberData(nameof(GetResolveFileTestData))] + [MemberData(nameof(ResolveFile_ValidFileNameTestData))] public void ResolveFile_ValidFileName_Success(VideoFileInfo expectedResult) { var result = _videoResolver.ResolveFile(expectedResult.Path); diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj new file mode 100644 index 000000000..61eead0e9 --- /dev/null +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -0,0 +1,42 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> + <PropertyGroup> + <ProjectGuid>{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}</ProjectGuid> + </PropertyGroup> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" /> + <PackageReference Include="coverlet.collector" Version="3.0.3" /> + <PackageReference Include="Moq" Version="4.16.1" /> + </ItemGroup> + + <!-- Code Analyzers--> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <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> + + <ItemGroup> + <ProjectReference Include="../../Emby.Server.Implementations/Emby.Server.Implementations.csproj" /> + <ProjectReference Include="../../MediaBrowser.Common/MediaBrowser.Common.csproj" /> + </ItemGroup> + + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> + <DefineConstants>DEBUG</DefineConstants> + </PropertyGroup> + +</Project> diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs new file mode 100644 index 000000000..c3469035e --- /dev/null +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -0,0 +1,518 @@ +using System; +using System.Collections.ObjectModel; +using System.Net; +using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Manager; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Networking.Tests +{ + public class NetworkParseTests + { + private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) + { + var configManager = new Mock<IConfigurationManager> + { + CallBase = true + }; + configManager.Setup(x => x.GetConfiguration(It.IsAny<string>())).Returns(conf); + return (IConfigurationManager)configManager.Object; + } + + /// <summary> + /// Checks the ability to ignore virtual interfaces. + /// </summary> + /// <param name="interfaces">Mock network setup, in the format (IP address, interface index, interface name) | .... </param> + /// <param name="lan">LAN addresses.</param> + /// <param name="value">Bind addresses that are excluded.</param> + [Theory] + // All valid + [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.0/24", "[192.168.1.208/24,200.200.200.200/24]")] + // eth16 only + [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] + // All interfaces excluded. + [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] + // vEthernet1 and vEthernet212 should be excluded. + [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")] + public void IgnoreVirtualInterfaces(string interfaces, string lan, string value) + { + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) + }; + + NetworkManager.MockNetworkSettings = interfaces; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + NetworkManager.MockNetworkSettings = string.Empty; + + Assert.Equal(nm.GetInternalBindAddresses().AsString(), value); + } + + /// <summary> + /// Check that the value given is in the network provided. + /// </summary> + /// <param name="network">Network address.</param> + /// <param name="value">Value to check.</param> + [Theory] + [InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")] + public void IsInNetwork(string network, string value) + { + if (network == null) + { + throw new ArgumentNullException(nameof(network)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + LocalNetworkSubnets = network.Split(',') + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + + Assert.False(nm.IsInLocalNetwork(value)); + } + + /// <summary> + /// Checks IP address formats. + /// </summary> + /// <param name="address"></param> + [Theory] + [InlineData("127.0.0.1")] + [InlineData("127.0.0.1:123")] + [InlineData("localhost")] + [InlineData("localhost:1345")] + [InlineData("www.google.co.uk")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")] + [InlineData("fe80::7add:12ff:febb:c67b%16")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] + [InlineData("fe80::7add:12ff:febb:c67b%16:123")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]")] + [InlineData("192.168.1.2/255.255.255.0")] + [InlineData("192.168.1.2/24")] + public void ValidHostStrings(string address) + { + Assert.True(IPHost.TryParse(address, out _)); + } + + /// <summary> + /// Checks IP address formats. + /// </summary> + /// <param name="address"></param> + [Theory] + [InlineData("127.0.0.1")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] + [InlineData("fe80::7add:12ff:febb:c67b%16")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] + [InlineData("fe80::7add:12ff:febb:c67b%16:123")] + [InlineData("[fe80::7add:12ff:febb:c67b%16]")] + [InlineData("192.168.1.2/255.255.255.0")] + [InlineData("192.168.1.2/24")] + public void ValidIPStrings(string address) + { + Assert.True(IPNetAddress.TryParse(address, out _)); + } + + /// <summary> + /// All should be invalid address strings. + /// </summary> + /// <param name="address">Invalid address strings.</param> + [Theory] + [InlineData("256.128.0.0.0.1")] + [InlineData("127.0.0.1#")] + [InlineData("localhost!")] + [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] + [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] + public void InvalidAddressString(string address) + { + Assert.False(IPNetAddress.TryParse(address, out _)); + Assert.False(IPHost.TryParse(address, out _)); + } + + /// <summary> + /// Test collection parsing. + /// </summary> + /// <param name="settings">Collection to parse.</param> + /// <param name="result1">Included addresses from the collection.</param> + /// <param name="result2">Included IP4 addresses from the collection.</param> + /// <param name="result3">Excluded addresses from the collection.</param> + /// <param name="result4">Excluded IP4 addresses from the collection.</param> + /// <param name="result5">Network addresses of the collection.</param> + [Theory] + [InlineData( + "127.0.0.1#", + "[]", + "[]", + "[]", + "[]", + "[]")] + [InlineData( + "!127.0.0.1", + "[]", + "[]", + "[127.0.0.1/32]", + "[127.0.0.1/32]", + "[]")] + [InlineData( + "", + "[]", + "[]", + "[]", + "[]", + "[]")] + [InlineData( + "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", + "[192.158.1.2/16,[127.0.0.1/32,::1/128],fd23:184f:2029:0:3139:7386:67d7:d517/128]", + "[192.158.1.2/16,127.0.0.1/32]", + "[10.10.10.10/32]", + "[10.10.10.10/32]", + "[192.158.0.0/16,127.0.0.1/32,::1/128,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] + [InlineData( + "192.158.1.2/255.255.0.0,192.169.1.2/8", + "[192.158.1.2/16,192.169.1.2/8]", + "[192.158.1.2/16,192.169.1.2/8]", + "[]", + "[]", + "[192.158.0.0/16,192.0.0.0/8]")] + public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + + // Test included. + Collection<IPObject> nc = nm.CreateIPCollection(settings.Split(","), false); + Assert.Equal(nc.AsString(), result1); + + // Test excluded. + nc = nm.CreateIPCollection(settings.Split(","), true); + Assert.Equal(nc.AsString(), result3); + + conf.EnableIPV6 = false; + nm.UpdateSettings(conf); + + // Test IP4 included. + nc = nm.CreateIPCollection(settings.Split(","), false); + Assert.Equal(nc.AsString(), result2); + + // Test IP4 excluded. + nc = nm.CreateIPCollection(settings.Split(","), true); + Assert.Equal(nc.AsString(), result4); + + conf.EnableIPV6 = true; + nm.UpdateSettings(conf); + + // Test network addresses of collection. + nc = nm.CreateIPCollection(settings.Split(","), false); + nc = nc.AsNetworks(); + Assert.Equal(nc.AsString(), result5); + } + + /// <summary> + /// Union two collections. + /// </summary> + /// <param name="settings">Source.</param> + /// <param name="compare">Destination.</param> + /// <param name="result">Result.</param> + [Theory] + [InlineData("127.0.0.1", "fd23:184f:2029:0:3139:7386:67d7:d517/64,fd23:184f:2029:0:c0f0:8a8a:7605:fffa/128,fe80::3139:7386:67d7:d517%16/64,192.168.1.208/24,::1/128,127.0.0.1/8", "[127.0.0.1/32]")] + [InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")] + public void UnionCheck(string settings, string compare, string result) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + if (compare == null) + { + throw new ArgumentNullException(nameof(compare)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + + Collection<IPObject> nc1 = nm.CreateIPCollection(settings.Split(","), false); + Collection<IPObject> nc2 = nm.CreateIPCollection(compare.Split(","), false); + + Assert.Equal(nc1.Union(nc2).AsString(), result); + } + + [Theory] + [InlineData("192.168.5.85/24", "192.168.5.1")] + [InlineData("192.168.5.85/24", "192.168.5.254")] + [InlineData("10.128.240.50/30", "10.128.240.48")] + [InlineData("10.128.240.50/30", "10.128.240.49")] + [InlineData("10.128.240.50/30", "10.128.240.50")] + [InlineData("10.128.240.50/30", "10.128.240.51")] + [InlineData("127.0.0.1/8", "127.0.0.1")] + public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("192.168.5.85/24", "192.168.4.254")] + [InlineData("192.168.5.85/24", "191.168.5.254")] + [InlineData("10.128.240.50/30", "10.128.240.47")] + [InlineData("10.128.240.50/30", "10.128.240.52")] + [InlineData("10.128.240.50/30", "10.128.239.50")] + [InlineData("10.128.240.50/30", "10.127.240.51")] + public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")] + [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] + public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0000:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")] + [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")] + [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")] + public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) + { + var ipAddressObj = IPNetAddress.Parse(netMask); + Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); + } + + [Theory] + [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1/32")] + [InlineData("10.0.0.0/8", "10.10.10.1/32")] + [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1")] + + [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1/32")] + [InlineData("10.10.0.0/16", "10.10.10.1/32")] + [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1")] + + [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1/32")] + [InlineData("10.10.10.0/24", "10.10.10.1/32")] + [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1")] + + public void TestSubnetContains(string network, string ip) + { + Assert.True(IPNetAddress.TryParse(network, out var networkObj)); + Assert.True(IPNetAddress.TryParse(ip, out var ipObj)); + Assert.True(networkObj.Contains(ipObj)); + } + + [Theory] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24", "172.168.1.2/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24, 10.10.10.1", "172.168.1.2/24,10.10.10.1/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/255.255.255.0, 10.10.10.1", "192.168.1.2/24,10.10.10.1/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/24, 100.10.10.1", "192.168.1.2/24")] + [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "194.168.1.2/24, 100.10.10.1", "")] + + public void TestCollectionEquality(string source, string dest, string result) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (dest == null) + { + throw new ArgumentNullException(nameof(dest)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true + }; + + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + + // Test included, IP6. + Collection<IPObject> ncSource = nm.CreateIPCollection(source.Split(",")); + Collection<IPObject> ncDest = nm.CreateIPCollection(dest.Split(",")); + Collection<IPObject> ncResult = ncSource.Union(ncDest); + Collection<IPObject> resultCollection = nm.CreateIPCollection(result.Split(",")); + Assert.True(ncResult.Compare(resultCollection)); + } + + [Theory] + [InlineData("10.1.1.1/32", "10.1.1.1")] + [InlineData("192.168.1.254/32", "192.168.1.254/255.255.255.255")] + + public void TestEquals(string source, string dest) + { + Assert.True(IPNetAddress.Parse(source).Equals(IPNetAddress.Parse(dest))); + Assert.True(IPNetAddress.Parse(dest).Equals(IPNetAddress.Parse(source))); + } + + [Theory] + + // Testing bind interfaces. + // On my system eth16 is internal, eth11 external (Windows defines the indexes). + // + // This test is to replicate how DNLA requests work throughout the system. + + // User on internal network, we're bound internal and external - so result is internal. + [InlineData("192.168.1.1", "eth16,eth11", false, "eth16")] + // User on external network, we're bound internal and external - so result is external. + [InlineData("8.8.8.8", "eth16,eth11", false, "eth11")] + // User on internal network, we're bound internal only - so result is internal. + [InlineData("10.10.10.10", "eth16", false, "eth16")] + // User on internal network, no binding specified - so result is the 1st internal. + [InlineData("192.168.1.1", "", false, "eth16")] + // User on external network, internal binding only - so result is the 1st internal. + [InlineData("jellyfin.org", "eth16", false, "eth16")] + // User on external network, no binding - so result is the 1st external. + [InlineData("jellyfin.org", "", false, "eth11")] + // User assumed to be internal, no binding - so result is the 1st internal. + [InlineData("", "", false, "eth16")] + public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (bindAddresses == null) + { + throw new ArgumentNullException(nameof(bindAddresses)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + var conf = new NetworkConfiguration() + { + LocalNetworkAddresses = bindAddresses.Split(','), + EnableIPV6 = ipv6enabled, + EnableIPV4 = true + }; + + NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + NetworkManager.MockNetworkSettings = string.Empty; + + _ = nm.TryParseInterface(result, out Collection<IPObject>? resultObj); + + if (resultObj != null) + { + result = ((IPNetAddress)resultObj[0]).ToString(true); + var intf = nm.GetBindInterface(source, out int? _); + + Assert.Equal(intf, result); + } + } + + [Theory] + + // Testing bind interfaces. These are set for my system so won't work elsewhere. + // On my system eth16 is internal, eth11 external (Windows defines the indexes). + // + // This test is to replicate how subnet bound ServerPublisherUri work throughout the system. + + // User on internal network, we're bound internal and external - so result is internal override. + [InlineData("192.168.1.1", "192.168.1.0/24", "eth16,eth11", false, "192.168.1.0/24=internal.jellyfin", "internal.jellyfin")] + + // User on external network, we're bound internal and external - so result is override. + [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + + // User on internal network, we're bound internal only, but the address isn't in the LAN - so return the override. + [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] + + // User on internal network, no binding specified - so result is the 1st internal. + [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + + // User on external network, internal binding only - so assumption is a proxy forward, return external override. + [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] + + // User on external network, no binding - so result is the 1st external which is overriden. + [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] + + // User assumed to be internal, no binding - so result is the 1st internal. + [InlineData("", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] + + // User is internal, no binding - so result is the 1st internal, which is then overridden. + [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")] + public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result) + { + if (lan == null) + { + throw new ArgumentNullException(nameof(lan)); + } + + if (bindAddresses == null) + { + throw new ArgumentNullException(nameof(bindAddresses)); + } + + var conf = new NetworkConfiguration() + { + LocalNetworkSubnets = lan.Split(','), + LocalNetworkAddresses = bindAddresses.Split(','), + EnableIPV6 = ipv6enabled, + EnableIPV4 = true, + PublishedServerUriBySubnet = new string[] { publishedServers } + }; + + NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); + NetworkManager.MockNetworkSettings = string.Empty; + + if (nm.TryParseInterface(result, out Collection<IPObject>? resultObj) && resultObj != null) + { + // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). + result = ((IPNetAddress)resultObj[0]).ToString(true); + } + + var intf = nm.GetBindInterface(source, out int? _); + + Assert.Equal(intf, result); + } + } +} diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj deleted file mode 100644 index fd77397ba..000000000 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj +++ /dev/null @@ -1,39 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> - <PropertyGroup> - <ProjectGuid>{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}</ProjectGuid> - </PropertyGroup> - - <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> - <IsPackable>false</IsPackable> - <Nullable>enable</Nullable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - </PropertyGroup> - - <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" /> - <PackageReference Include="xunit" Version="2.4.1" /> - <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" /> - <PackageReference Include="coverlet.collector" Version="3.0.3" /> - <PackageReference Include="Moq" Version="4.16.1" /> - </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="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\..\..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" /> - <ProjectReference Include="..\..\..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> - </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> - <DefineConstants>DEBUG</DefineConstants> - </PropertyGroup> -</Project> diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs deleted file mode 100644 index 9f928ded1..000000000 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs +++ /dev/null @@ -1,519 +0,0 @@ -using System; -using System.Net; -using Jellyfin.Networking.Configuration; -using Jellyfin.Networking.Manager; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using Moq; -using Microsoft.Extensions.Logging.Abstractions; -using Xunit; -using System.Collections.ObjectModel; - -namespace Jellyfin.Networking.Tests -{ - public class NetworkParseTests - { - private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) - { - var configManager = new Mock<IConfigurationManager> - { - CallBase = true - }; - configManager.Setup(x => x.GetConfiguration(It.IsAny<string>())).Returns(conf); - return (IConfigurationManager)configManager.Object; - } - - /// <summary> - /// Checks the ability to ignore virtual interfaces. - /// </summary> - /// <param name="interfaces">Mock network setup, in the format (IP address, interface index, interface name) | .... </param> - /// <param name="lan">LAN addresses.</param> - /// <param name="value">Bind addresses that are excluded.</param> - [Theory] - // All valid - [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.0/24", "[192.168.1.208/24,200.200.200.200/24]")] - // eth16 only - [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] - // All interfaces excluded. - [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] - // vEthernet1 and vEthernet212 should be excluded. - [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")] - public void IgnoreVirtualInterfaces(string interfaces, string lan, string value) - { - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - LocalNetworkSubnets = lan?.Split(';') ?? throw new ArgumentNullException(nameof(lan)) - }; - - NetworkManager.MockNetworkSettings = interfaces; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - NetworkManager.MockNetworkSettings = string.Empty; - - Assert.Equal(nm.GetInternalBindAddresses().AsString(), value); - } - - /// <summary> - /// Check that the value given is in the network provided. - /// </summary> - /// <param name="network">Network address.</param> - /// <param name="value">Value to check.</param> - [Theory] - [InlineData("192.168.10.0/24, !192.168.10.60/32", "192.168.10.60")] - public void IsInNetwork(string network, string value) - { - if (network == null) - { - throw new ArgumentNullException(nameof(network)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - LocalNetworkSubnets = network.Split(',') - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - Assert.False(nm.IsInLocalNetwork(value)); - } - - /// <summary> - /// Checks IP address formats. - /// </summary> - /// <param name="address"></param> - [Theory] - [InlineData("127.0.0.1")] - [InlineData("127.0.0.1:123")] - [InlineData("localhost")] - [InlineData("localhost:1345")] - [InlineData("www.google.co.uk")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]:124")] - [InlineData("fe80::7add:12ff:febb:c67b%16")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] - [InlineData("fe80::7add:12ff:febb:c67b%16:123")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]")] - [InlineData("192.168.1.2/255.255.255.0")] - [InlineData("192.168.1.2/24")] - public void ValidHostStrings(string address) - { - Assert.True(IPHost.TryParse(address, out _)); - } - - /// <summary> - /// Checks IP address formats. - /// </summary> - /// <param name="address"></param> - [Theory] - [InlineData("127.0.0.1")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517/56")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517]")] - [InlineData("fe80::7add:12ff:febb:c67b%16")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]:123")] - [InlineData("fe80::7add:12ff:febb:c67b%16:123")] - [InlineData("[fe80::7add:12ff:febb:c67b%16]")] - [InlineData("192.168.1.2/255.255.255.0")] - [InlineData("192.168.1.2/24")] - public void ValidIPStrings(string address) - { - Assert.True(IPNetAddress.TryParse(address, out _)); - } - - - /// <summary> - /// All should be invalid address strings. - /// </summary> - /// <param name="address">Invalid address strings.</param> - [Theory] - [InlineData("256.128.0.0.0.1")] - [InlineData("127.0.0.1#")] - [InlineData("localhost!")] - [InlineData("fd23:184f:2029:0:3139:7386:67d7:d517:1231")] - [InlineData("[fd23:184f:2029:0:3139:7386:67d7:d517:1231]")] - public void InvalidAddressString(string address) - { - Assert.False(IPNetAddress.TryParse(address, out _)); - Assert.False(IPHost.TryParse(address, out _)); - } - - - /// <summary> - /// Test collection parsing. - /// </summary> - /// <param name="settings">Collection to parse.</param> - /// <param name="result1">Included addresses from the collection.</param> - /// <param name="result2">Included IP4 addresses from the collection.</param> - /// <param name="result3">Excluded addresses from the collection.</param> - /// <param name="result4">Excluded IP4 addresses from the collection.</param> - /// <param name="result5">Network addresses of the collection.</param> - [Theory] - [InlineData("127.0.0.1#", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData("!127.0.0.1", - "[]", - "[]", - "[127.0.0.1/32]", - "[127.0.0.1/32]", - "[]")] - [InlineData("", - "[]", - "[]", - "[]", - "[]", - "[]")] - [InlineData( - "192.158.1.2/16, localhost, fd23:184f:2029:0:3139:7386:67d7:d517, !10.10.10.10", - "[192.158.1.2/16,[127.0.0.1/32,::1/128],fd23:184f:2029:0:3139:7386:67d7:d517/128]", - "[192.158.1.2/16,127.0.0.1/32]", - "[10.10.10.10/32]", - "[10.10.10.10/32]", - "[192.158.0.0/16,127.0.0.1/32,::1/128,fd23:184f:2029:0:3139:7386:67d7:d517/128]")] - [InlineData("192.158.1.2/255.255.0.0,192.169.1.2/8", - "[192.158.1.2/16,192.169.1.2/8]", - "[192.158.1.2/16,192.169.1.2/8]", - "[]", - "[]", - "[192.158.0.0/16,192.0.0.0/8]")] - public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - // Test included. - Collection<IPObject> nc = nm.CreateIPCollection(settings.Split(","), false); - Assert.Equal(nc.AsString(), result1); - - // Test excluded. - nc = nm.CreateIPCollection(settings.Split(","), true); - Assert.Equal(nc.AsString(), result3); - - conf.EnableIPV6 = false; - nm.UpdateSettings(conf); - - // Test IP4 included. - nc = nm.CreateIPCollection(settings.Split(","), false); - Assert.Equal(nc.AsString(), result2); - - // Test IP4 excluded. - nc = nm.CreateIPCollection(settings.Split(","), true); - Assert.Equal(nc.AsString(), result4); - - conf.EnableIPV6 = true; - nm.UpdateSettings(conf); - - // Test network addresses of collection. - nc = nm.CreateIPCollection(settings.Split(","), false); - nc = nc.AsNetworks(); - Assert.Equal(nc.AsString(), result5); - } - - /// <summary> - /// Union two collections. - /// </summary> - /// <param name="settings">Source.</param> - /// <param name="compare">Destination.</param> - /// <param name="result">Result.</param> - [Theory] - [InlineData("127.0.0.1", "fd23:184f:2029:0:3139:7386:67d7:d517/64,fd23:184f:2029:0:c0f0:8a8a:7605:fffa/128,fe80::3139:7386:67d7:d517%16/64,192.168.1.208/24,::1/128,127.0.0.1/8", "[127.0.0.1/32]")] - [InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")] - public void UnionCheck(string settings, string compare, string result) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - if (compare == null) - { - throw new ArgumentNullException(nameof(compare)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - Collection<IPObject> nc1 = nm.CreateIPCollection(settings.Split(","), false); - Collection<IPObject> nc2 = nm.CreateIPCollection(compare.Split(","), false); - - Assert.Equal(nc1.Union(nc2).AsString(), result); - } - - [Theory] - [InlineData("192.168.5.85/24", "192.168.5.1")] - [InlineData("192.168.5.85/24", "192.168.5.254")] - [InlineData("10.128.240.50/30", "10.128.240.48")] - [InlineData("10.128.240.50/30", "10.128.240.49")] - [InlineData("10.128.240.50/30", "10.128.240.50")] - [InlineData("10.128.240.50/30", "10.128.240.51")] - [InlineData("127.0.0.1/8", "127.0.0.1")] - public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("192.168.5.85/24", "192.168.4.254")] - [InlineData("192.168.5.85/24", "191.168.5.254")] - [InlineData("10.128.240.50/30", "10.128.240.47")] - [InlineData("10.128.240.50/30", "10.128.240.52")] - [InlineData("10.128.240.50/30", "10.128.239.50")] - [InlineData("10.128.240.50/30", "10.127.240.51")] - public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")] - [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")] - public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.True(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0000:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")] - [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")] - [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")] - public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress) - { - var ipAddressObj = IPNetAddress.Parse(netMask); - Assert.False(ipAddressObj.Contains(IPAddress.Parse(ipAddress))); - } - - [Theory] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1/32")] - [InlineData("10.0.0.0/8", "10.10.10.1/32")] - [InlineData("10.0.0.0/255.0.0.0", "10.10.10.1")] - - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1/32")] - [InlineData("10.10.0.0/16", "10.10.10.1/32")] - [InlineData("10.10.0.0/255.255.0.0", "10.10.10.1")] - - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1/32")] - [InlineData("10.10.10.0/24", "10.10.10.1/32")] - [InlineData("10.10.10.0/255.255.255.0", "10.10.10.1")] - - public void TestSubnetContains(string network, string ip) - { - Assert.True(IPNetAddress.TryParse(network, out var networkObj)); - Assert.True(IPNetAddress.TryParse(ip, out var ipObj)); - Assert.True(networkObj.Contains(ipObj)); - } - - [Theory] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24", "172.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "172.168.1.2/24, 10.10.10.1", "172.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/255.255.255.0, 10.10.10.1", "192.168.1.2/24,10.10.10.1/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "192.168.1.2/24, 100.10.10.1", "192.168.1.2/24")] - [InlineData("192.168.1.2/24,10.10.10.1/24,172.168.1.2/24", "194.168.1.2/24, 100.10.10.1", "")] - - public void TestCollectionEquality(string source, string dest, string result) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true - }; - - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - - // Test included, IP6. - Collection<IPObject> ncSource = nm.CreateIPCollection(source.Split(",")); - Collection<IPObject> ncDest = nm.CreateIPCollection(dest.Split(",")); - Collection<IPObject> ncResult = ncSource.Union(ncDest); - Collection<IPObject> resultCollection = nm.CreateIPCollection(result.Split(",")); - Assert.True(ncResult.Compare(resultCollection)); - } - - - [Theory] - [InlineData("10.1.1.1/32", "10.1.1.1")] - [InlineData("192.168.1.254/32", "192.168.1.254/255.255.255.255")] - - public void TestEquals(string source, string dest) - { - Assert.True(IPNetAddress.Parse(source).Equals(IPNetAddress.Parse(dest))); - Assert.True(IPNetAddress.Parse(dest).Equals(IPNetAddress.Parse(source))); - } - - [Theory] - - // Testing bind interfaces. - // On my system eth16 is internal, eth11 external (Windows defines the indexes). - // - // This test is to replicate how DNLA requests work throughout the system. - - // User on internal network, we're bound internal and external - so result is internal. - [InlineData("192.168.1.1", "eth16,eth11", false, "eth16")] - // User on external network, we're bound internal and external - so result is external. - [InlineData("8.8.8.8", "eth16,eth11", false, "eth11")] - // User on internal network, we're bound internal only - so result is internal. - [InlineData("10.10.10.10", "eth16", false, "eth16")] - // User on internal network, no binding specified - so result is the 1st internal. - [InlineData("192.168.1.1", "", false, "eth16")] - // User on external network, internal binding only - so result is the 1st internal. - [InlineData("jellyfin.org", "eth16", false, "eth16")] - // User on external network, no binding - so result is the 1st external. - [InlineData("jellyfin.org", "", false, "eth11")] - // User assumed to be internal, no binding - so result is the 1st internal. - [InlineData("", "", false, "eth16")] - public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } - - var conf = new NetworkConfiguration() - { - LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true - }; - - NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - NetworkManager.MockNetworkSettings = string.Empty; - - _ = nm.TryParseInterface(result, out Collection<IPObject>? resultObj); - - if (resultObj != null) - { - result = ((IPNetAddress)resultObj[0]).ToString(true); - var intf = nm.GetBindInterface(source, out int? _); - - Assert.Equal(intf, result); - } - } - - [Theory] - - // Testing bind interfaces. These are set for my system so won't work elsewhere. - // On my system eth16 is internal, eth11 external (Windows defines the indexes). - // - // This test is to replicate how subnet bound ServerPublisherUri work throughout the system. - - // User on internal network, we're bound internal and external - so result is internal override. - [InlineData("192.168.1.1", "192.168.1.0/24", "eth16,eth11", false, "192.168.1.0/24=internal.jellyfin", "internal.jellyfin")] - - // User on external network, we're bound internal and external - so result is override. - [InlineData("8.8.8.8", "192.168.1.0/24", "eth16,eth11", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] - - // User on internal network, we're bound internal only, but the address isn't in the LAN - so return the override. - [InlineData("10.10.10.10", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://internalButNotDefinedAsLan.com", "http://internalButNotDefinedAsLan.com")] - - // User on internal network, no binding specified - so result is the 1st internal. - [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] - - // User on external network, internal binding only - so assumption is a proxy forward, return external override. - [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] - - // User on external network, no binding - so result is the 1st external which is overriden. - [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] - - // User assumed to be internal, no binding - so result is the 1st internal. - [InlineData("", "192.168.1.0/24", "", false, "0.0.0.0=http://helloworld.com", "eth16")] - - // User is internal, no binding - so result is the 1st internal, which is then overridden. - [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")] - - public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result) - { - if (lan == null) - { - throw new ArgumentNullException(nameof(lan)); - } - - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } - - var conf = new NetworkConfiguration() - { - LocalNetworkSubnets = lan.Split(','), - LocalNetworkAddresses = bindAddresses.Split(','), - EnableIPV6 = ipv6enabled, - EnableIPV4 = true, - PublishedServerUriBySubnet = new string[] { publishedServers } - }; - - NetworkManager.MockNetworkSettings = "192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11"; - using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>()); - NetworkManager.MockNetworkSettings = string.Empty; - - if (nm.TryParseInterface(result, out Collection<IPObject>? resultObj) && resultObj != null) - { - // Parse out IPAddresses so we can do a string comparison. (Ignore subnet masks). - result = ((IPNetAddress)resultObj[0]).ToString(true); - } - - var intf = nm.GetBindInterface(source, out int? _); - - Assert.Equal(intf, result); - } - } -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 1ad8171be..8debb08c5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -10,6 +10,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> <RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace> </PropertyGroup> @@ -31,7 +34,6 @@ <!-- 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" /> @@ -42,8 +44,4 @@ <ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index d6aab3f85..2bb94c81f 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -5,6 +5,9 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <EnableNETAnalyzers>true</EnableNETAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -23,7 +26,6 @@ <!-- 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" /> @@ -34,8 +36,4 @@ <ProjectReference Include="../../MediaBrowser.Providers/MediaBrowser.Providers.csproj" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> -- cgit v1.2.3 From d202df6e8a1f36a253e9780e7ec1521bc0c4b75e Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 9 Mar 2021 03:22:51 +0100 Subject: Remove useless line --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 1 - MediaBrowser.Model/MediaBrowser.Model.csproj | 1 - MediaBrowser.Providers/MediaBrowser.Providers.csproj | 1 - MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 1 - tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 1 - tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 1 - tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj | 1 - tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 1 - tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj | 1 - tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj | 1 - tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 1 - tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj | 1 - .../Jellyfin.Server.Implementations.Tests.csproj | 1 - tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj | 1 - 14 files changed, 14 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index de00920ba..39fb0b47c 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -10,7 +10,6 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 30403219f..f622a042a 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -19,7 +19,6 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode> --> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 5e7b8043f..152ea664a 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -30,7 +30,6 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode Condition=" '$(Configuration)' == 'Debug'">AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 95327d3ae..2904b40ec 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -20,7 +20,6 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 0d8176bb2..a336d2aee 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 78e3061f7..017a67e9f 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index df1eb8617..6dec25aa4 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index d173d5c93..5d52f94c0 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -5,7 +5,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 84306e0f7..4cc1d37ee 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index b458c06ff..0c7e262f5 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -5,7 +5,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 0f8a0333a..cc12a99a6 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 61eead0e9..a76c0e9a0 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 8debb08c5..c3c258b68 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -10,7 +10,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> <RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 2bb94c81f..9380fe2af 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -5,7 +5,6 @@ <IsPackable>false</IsPackable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <EnableNETAnalyzers>true</EnableNETAnalyzers> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> -- cgit v1.2.3 From a8ed753f6c890f74d3a70c2653ac5548d2399737 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 9 Mar 2021 05:57:38 +0100 Subject: FxCop -> Net Analyzers (part 2) --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 5 +- .../Channels/ChannelManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 2 +- .../Library/LiveStreamHelper.cs | 2 +- .../Library/MediaSourceManager.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- .../Localization/LocalizationManager.cs | 2 +- .../Plugins/PluginManager.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 2 +- .../Updates/InstallationManager.cs | 2 +- .../Controllers/ConfigurationController.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 2 +- Jellyfin.Data/DayOfWeekHelper.cs | 60 +++------------------- Jellyfin.Data/Entities/Libraries/Collection.cs | 1 + .../Entities/Libraries/MediaFileStream.cs | 2 + Jellyfin.Data/Entities/Permission.cs | 2 + Jellyfin.Data/Jellyfin.Data.csproj | 6 +-- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 11 ++-- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 13 ++--- Jellyfin.Networking/Jellyfin.Networking.csproj | 6 +-- .../Security/AuthenticationSucceededLogger.cs | 8 +-- .../Events/Consumers/System/TaskCompletedLogger.cs | 14 ++--- .../Consumers/Updates/PluginUninstalledLogger.cs | 4 +- .../Events/Consumers/Users/UserUpdatedNotifier.cs | 6 +-- .../Jellyfin.Server.Implementations.csproj | 2 + .../Users/DefaultPasswordResetProvider.cs | 2 +- .../Users/DisplayPreferencesManager.cs | 3 +- .../Extensions/ApiServiceCollectionExtensions.cs | 2 +- .../Formatters/CamelCaseJsonProfileFormatter.cs | 2 +- .../Formatters/PascalCaseJsonProfileFormatter.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++- Jellyfin.Server/Migrations/MigrationOptions.cs | 3 ++ .../Migrations/Routines/MigrateUserDb.cs | 2 +- Jellyfin.Server/Program.cs | 4 +- MediaBrowser.Common/IApplicationHost.cs | 4 +- MediaBrowser.Common/Json/JsonDefaults.cs | 6 +-- MediaBrowser.Common/MediaBrowser.Common.csproj | 6 +-- MediaBrowser.Common/Net/IPHost.cs | 2 +- MediaBrowser.Common/Net/IPNetAddress.cs | 6 +-- MediaBrowser.Common/Plugins/BasePlugin.cs | 2 +- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 36 ++++++------- MediaBrowser.Common/Plugins/LocalPlugin.cs | 6 +-- MediaBrowser.Common/Progress/ActionableProgress.cs | 1 + MediaBrowser.Common/Progress/SimpleProgress.cs | 1 + .../Entities/CollectionFolder.cs | 2 +- .../MediaBrowser.Controller.csproj | 6 +-- .../Providers/ILocalImageProvider.cs | 2 +- .../Images/CollectionFolderLocalImageProvider.cs | 2 +- .../Images/EpisodeLocalImageProvider.cs | 2 +- .../Images/InternalMetadataFolderImageProvider.cs | 7 +-- .../Images/LocalImageProvider.cs | 14 +++-- .../MediaBrowser.LocalMetadata.csproj | 6 +-- .../Parsers/BaseItemXmlParser.cs | 4 +- .../Parsers/BoxSetXmlParser.cs | 6 +-- .../Parsers/PlaylistXmlParser.cs | 6 +-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 17 ++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../Plugins/AudioDb/AlbumImageProvider.cs | 2 +- .../Plugins/AudioDb/AlbumProvider.cs | 2 +- .../Plugins/AudioDb/ArtistImageProvider.cs | 2 +- .../Plugins/AudioDb/ArtistProvider.cs | 2 +- .../Plugins/Omdb/OmdbItemProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 2 +- .../FFprobeParserTests.cs | 2 +- .../Controllers/DashboardControllerTests.cs | 2 +- 70 files changed, 151 insertions(+), 213 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index d7b75f979..552cd501b 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -36,7 +36,7 @@ namespace Emby.Dlna private readonly ILogger<DlnaManager> _logger; private readonly IServerApplicationHost _appHost; private static readonly Assembly _assembly = typeof(DlnaManager).Assembly; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private readonly Dictionary<string, Tuple<InternalProfileInfo, DeviceProfile>> _profiles = new Dictionary<string, Tuple<InternalProfileInfo, DeviceProfile>>(StringComparer.Ordinal); diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 835dc33b0..164e6d49d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -10,8 +10,6 @@ using System.Net; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Emby.Dlna; @@ -51,7 +49,6 @@ using Jellyfin.Networking.Manager; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -470,7 +467,7 @@ namespace Emby.Server.Implementations } /// <inheritdoc /> - public IReadOnlyCollection<T> GetExports<T>(CreationDelegate defaultFunc, bool manageLifetime = true) + public IReadOnlyCollection<T> GetExports<T>(CreationDelegateFactory defaultFunc, bool manageLifetime = true) { // Convert to list so this isn't executed for each iteration var parts = GetExportTypes<T>() diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 8c5fa09f6..87ebe960a 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.Channels private readonly IProviderManager _providerManager; private readonly IMemoryCache _memoryCache; private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// <summary> /// Initializes a new instance of the <see cref="ChannelManager"/> class. diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index d78b93bd7..2ae805447 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -88,7 +88,7 @@ namespace Emby.Server.Implementations.Data _imageProcessor = imageProcessor; _typeMapper = new TypeMapper(); - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 7e0c2c1da..06acb5606 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.HttpServer RemoteEndPoint = remoteEndPoint; QueryString = query; - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; LastActivityDate = DateTime.Now; } diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 2070df31e..c2951dd15 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Library private readonly IMediaEncoder _mediaEncoder; private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger, IApplicationPaths appPaths) { diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index c63eb7017..b2943020c 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.Library private readonly ConcurrentDictionary<string, ILiveStream> _openStreams = new ConcurrentDictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private IMediaSourceProvider[] _providers; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 78a82118e..44a8cdee4 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IServerApplicationPaths _appPaths; private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(); private readonly IServerConfigurationManager _serverConfigurationManager; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private bool _hasExited; private Stream _logFileStream; private string _targetPath; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 57424f043..c20b08088 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { private readonly string _dataPath; private readonly object _fileDataLock = new object(); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private T[] _items; public ItemDataProvider( diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 6d7c5ac6e..1926e738f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ICryptoProvider _cryptoProvider; private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>(); - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private DateTime _lastErrorResponse; public SchedulesDirect( diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 0760e8127..68173a0ef 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _networkManager = networkManager; _streamHelper = streamHelper; - _jsonOptions = JsonDefaults.GetOptions(); + _jsonOptions = JsonDefaults.Options; } public string Name => "HD Homerun"; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 3f9e22106..98de848bc 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Localization private List<CultureDto> _cultures; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// <summary> /// Initializes a new instance of the <see cref="LocalizationManager" /> class. diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index c579fc8cb..700396c4c 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.Plugins _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _pluginsPath = pluginsPath; _appVersion = appVersion ?? throw new ArgumentNullException(nameof(appVersion)); - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()) + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options) { WriteIndented = true }; @@ -678,7 +678,7 @@ namespace Emby.Server.Implementations.Plugins var entry = versions[x]; if (!string.Equals(lastName, entry.Name, StringComparison.OrdinalIgnoreCase)) { - entry.DllFiles.AddRange(Directory.EnumerateFiles(entry.Path, "*.dll", SearchOption.AllDirectories)); + entry.DllFiles = Directory.GetFiles(entry.Path, "*.dll", SearchOption.AllDirectories); if (entry.IsEnabledAndSupported) { lastName = entry.Name; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index b302303f8..a145a8423 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -69,7 +69,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <summary> /// The options for the json Serializer. /// </summary> - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; /// <summary> /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class. diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7af52ea65..fc34f93cd 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Updates _httpClientFactory = httpClientFactory; _config = config; _zipClient = zipClient; - _jsonSerializerOptions = JsonDefaults.GetOptions(); + _jsonSerializerOptions = JsonDefaults.Options; _pluginManager = pluginManager; } diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index e1c9f69f6..049a4bed7 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Api.Controllers private readonly IServerConfigurationManager _configurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly JsonSerializerOptions _serializerOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _serializerOptions = JsonDefaults.Options; /// <summary> /// Initializes a new instance of the <see cref="ConfigurationController"/> class. diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index a5aa9bfca..24285bfb9 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -45,7 +45,7 @@ namespace Jellyfin.Api.Controllers { _installationManager = installationManager; _pluginManager = pluginManager; - _serializerOptions = JsonDefaults.GetOptions(); + _serializerOptions = JsonDefaults.Options; _config = config; } diff --git a/Jellyfin.Data/DayOfWeekHelper.cs b/Jellyfin.Data/DayOfWeekHelper.cs index 4e75f4cfd..8d760a155 100644 --- a/Jellyfin.Data/DayOfWeekHelper.cs +++ b/Jellyfin.Data/DayOfWeekHelper.cs @@ -1,67 +1,21 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using Jellyfin.Data.Enums; namespace Jellyfin.Data { public static class DayOfWeekHelper { - public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day) + public static DayOfWeek[] GetDaysOfWeek(DynamicDayOfWeek day) { - var days = new List<DayOfWeek>(7); - - if (day == DynamicDayOfWeek.Sunday - || day == DynamicDayOfWeek.Weekend - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Sunday); - } - - if (day == DynamicDayOfWeek.Monday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Monday); - } - - if (day == DynamicDayOfWeek.Tuesday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Tuesday); - } - - if (day == DynamicDayOfWeek.Wednesday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) + return day switch { - days.Add(DayOfWeek.Wednesday); - } - - if (day == DynamicDayOfWeek.Thursday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Thursday); - } - - if (day == DynamicDayOfWeek.Friday - || day == DynamicDayOfWeek.Weekday - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Friday); - } - - if (day == DynamicDayOfWeek.Saturday - || day == DynamicDayOfWeek.Weekend - || day == DynamicDayOfWeek.Everyday) - { - days.Add(DayOfWeek.Saturday); - } - - return days; + DynamicDayOfWeek.Everyday => new[] { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday }, + DynamicDayOfWeek.Weekday => new[] { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday }, + DynamicDayOfWeek.Weekend => new[] { DayOfWeek.Saturday, DayOfWeek.Sunday }, + _ => new[] { (DayOfWeek)day } + }; } } } diff --git a/Jellyfin.Data/Entities/Libraries/Collection.cs b/Jellyfin.Data/Entities/Libraries/Collection.cs index 39eded752..854f17f80 100644 --- a/Jellyfin.Data/Entities/Libraries/Collection.cs +++ b/Jellyfin.Data/Entities/Libraries/Collection.cs @@ -1,3 +1,4 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix #pragma warning disable CA2227 using System.Collections.Generic; diff --git a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs index 5b03e260e..5e27156a4 100644 --- a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix + using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; diff --git a/Jellyfin.Data/Entities/Permission.cs b/Jellyfin.Data/Entities/Permission.cs index d92e5d9d2..0162e1acf 100644 --- a/Jellyfin.Data/Entities/Permission.cs +++ b/Jellyfin.Data/Entities/Permission.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1711 // Identifiers should not have incorrect suffix + using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 42731bb11..0340cda01 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -5,6 +5,8 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> @@ -24,10 +26,6 @@ <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 1a8415ae0..3fc44640b 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -11,6 +11,8 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -30,6 +32,11 @@ <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> </ItemGroup> + <ItemGroup> + <!-- Needed for https://github.com/dotnet/roslyn-analyzers/issues/4382 which is in the SDK yet --> + <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3" PrivateAssets="All" /> + </ItemGroup> + <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> @@ -37,8 +44,4 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index eab5777d5..fd7cb5ec5 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -274,8 +274,8 @@ namespace Jellyfin.Drawing.Skia if (requiresTransparencyHack || forceCleanBitmap) { - using var codec = SKCodec.Create(NormalizePath(path)); - if (codec == null) + using SKCodec codec = SKCodec.Create(NormalizePath(path), out SKCodecResult res); + if (res != SKCodecResult.Success) { origin = GetSKEncodedOrigin(orientation); return null; @@ -345,11 +345,6 @@ namespace Jellyfin.Drawing.Skia private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin) { - if (origin == SKEncodedOrigin.Default) - { - return bitmap; - } - var needsFlip = origin == SKEncodedOrigin.LeftBottom || origin == SKEncodedOrigin.LeftTop || origin == SKEncodedOrigin.RightBottom @@ -447,7 +442,7 @@ namespace Jellyfin.Drawing.Skia } /// <inheritdoc/> - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat) { if (inputPath.Length == 0) { @@ -459,7 +454,7 @@ namespace Jellyfin.Drawing.Skia throw new ArgumentException("String can't be empty.", nameof(outputPath)); } - var skiaOutputFormat = GetImageFormat(selectedOutputFormat); + var skiaOutputFormat = GetImageFormat(outputFormat); var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor); var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer); diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index f89a18426..63557e91f 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -5,6 +5,8 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -18,10 +20,6 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs index 2f9f44ed6..8b0bd84c6 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs @@ -29,20 +29,20 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security } /// <inheritdoc /> - public async Task OnEvent(GenericEventArgs<AuthenticationResult> e) + public async Task OnEvent(GenericEventArgs<AuthenticationResult> eventArgs) { await _activityManager.CreateAsync(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("AuthenticationSucceededWithUserName"), - e.Argument.User.Name), + eventArgs.Argument.User.Name), "AuthenticationSucceeded", - e.Argument.User.Id) + eventArgs.Argument.User.Id) { ShortOverview = string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("LabelIpAddressValue"), - e.Argument.SessionInfo.RemoteEndPoint), + eventArgs.Argument.SessionInfo.RemoteEndPoint), }).ConfigureAwait(false); } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs index 05201a346..cbc9f3017 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs @@ -33,10 +33,10 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.System } /// <inheritdoc /> - public async Task OnEvent(TaskCompletionEventArgs e) + public async Task OnEvent(TaskCompletionEventArgs eventArgs) { - var result = e.Result; - var task = e.Task; + var result = eventArgs.Result; + var task = eventArgs.Task; if (task.ScheduledTask is IConfigurableScheduledTask activityTask && !activityTask.IsLogged) @@ -54,14 +54,14 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.System { var vals = new List<string>(); - if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) + if (!string.IsNullOrEmpty(eventArgs.Result.ErrorMessage)) { - vals.Add(e.Result.ErrorMessage); + vals.Add(eventArgs.Result.ErrorMessage); } - if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) + if (!string.IsNullOrEmpty(eventArgs.Result.LongErrorMessage)) { - vals.Add(e.Result.LongErrorMessage); + vals.Add(eventArgs.Result.LongErrorMessage); } await _activityManager.CreateAsync(new ActivityLog( diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs index 91a30069e..eb7572ac6 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs @@ -30,13 +30,13 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates } /// <inheritdoc /> - public async Task OnEvent(PluginUninstalledEventArgs e) + public async Task OnEvent(PluginUninstalledEventArgs eventArgs) { await _activityManager.CreateAsync(new ActivityLog( string.Format( CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("PluginUninstalledWithName"), - e.Argument.Name), + eventArgs.Argument.Name), NotificationType.PluginUninstalled.ToString(), Guid.Empty)) .ConfigureAwait(false); diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs index a14911b94..9beb6f2f2 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs @@ -30,12 +30,12 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Users } /// <inheritdoc /> - public async Task OnEvent(UserUpdatedEventArgs e) + public async Task OnEvent(UserUpdatedEventArgs eventArgs) { await _sessionManager.SendMessageToUserSessions( - new List<Guid> { e.Argument.Id }, + new List<Guid> { eventArgs.Argument.Id }, SessionMessageType.UserUpdated, - _userManager.GetUserDto(e.Argument), + _userManager.GetUserDto(eventArgs.Argument), CancellationToken.None).ConfigureAwait(false); } } diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 19c7ac567..5a5992bd6 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -6,6 +6,8 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index 9cc1c3e5e..c99c5e4ef 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -66,7 +66,7 @@ namespace Jellyfin.Server.Implementations.Users else if (string.Equals( spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal), pin.Replace("-", string.Empty, StringComparison.Ordinal), - StringComparison.InvariantCultureIgnoreCase)) + StringComparison.OrdinalIgnoreCase)) { var resetUser = userManager.GetUserByName(spr.UserName) ?? throw new ResourceNotFoundException($"User with a username of {spr.UserName} not found"); diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index c8a589cab..a3e9516b9 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -1,4 +1,5 @@ #pragma warning disable CA1307 +#pragma warning disable CA1309 using System; using System.Collections.Generic; @@ -35,7 +36,7 @@ namespace Jellyfin.Server.Implementations.Users if (prefs == null) { - prefs = new DisplayPreferences(userId, itemId, client); + prefs = new DisplayPreferences(userId, itemId, client); _dbContext.DisplayPreferences.Add(prefs); } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 1828f1a7e..a3f49e6cb 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -225,7 +225,7 @@ namespace Jellyfin.Server.Extensions .AddJsonOptions(options => { // Update all properties that are set in JsonDefaults - var jsonOptions = JsonDefaults.GetPascalCaseOptions(); + var jsonOptions = JsonDefaults.PascalCaseOptions; // From JsonDefaults options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; diff --git a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs index 8043989b1..c349e3dca 100644 --- a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs @@ -12,7 +12,7 @@ namespace Jellyfin.Server.Formatters /// <summary> /// Initializes a new instance of the <see cref="CamelCaseJsonProfileFormatter"/> class. /// </summary> - public CamelCaseJsonProfileFormatter() : base(JsonDefaults.GetCamelCaseOptions()) + public CamelCaseJsonProfileFormatter() : base(JsonDefaults.CamelCaseOptions) { SupportedMediaTypes.Clear(); SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(JsonDefaults.CamelCaseMediaType)); diff --git a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs index d0110b125..0480f5e0e 100644 --- a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Formatters /// <summary> /// Initializes a new instance of the <see cref="PascalCaseJsonProfileFormatter"/> class. /// </summary> - public PascalCaseJsonProfileFormatter() : base(JsonDefaults.GetPascalCaseOptions()) + public PascalCaseJsonProfileFormatter() : base(JsonDefaults.PascalCaseOptions) { SupportedMediaTypes.Clear(); // Add application/json for default formatter diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 6bfb5b878..09799307b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -13,7 +13,9 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> - <DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> + <!-- <DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers> --> </PropertyGroup> <ItemGroup> @@ -31,10 +33,6 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <PackageReference Include="CommandLineParser" Version="2.8.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" /> diff --git a/Jellyfin.Server/Migrations/MigrationOptions.cs b/Jellyfin.Server/Migrations/MigrationOptions.cs index 816dd9ee7..c9710f1fd 100644 --- a/Jellyfin.Server/Migrations/MigrationOptions.cs +++ b/Jellyfin.Server/Migrations/MigrationOptions.cs @@ -16,9 +16,12 @@ namespace Jellyfin.Server.Migrations Applied = new List<(Guid Id, string Name)>(); } +// .Net xml serializer can't handle interfaces +#pragma warning disable CA1002 // Do not expose generic lists /// <summary> /// Gets the list of applied migration routine names. /// </summary> public List<(Guid Id, string Name)> Applied { get; } +#pragma warning restore CA1002 } } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 33f039c39..d61c04447 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var entry in queryResult) { - UserMockup? mockup = JsonSerializer.Deserialize<UserMockup>(entry[2].ToBlob(), JsonDefaults.GetOptions()); + UserMockup? mockup = JsonSerializer.Deserialize<UserMockup>(entry[2].ToBlob(), JsonDefaults.Options); if (mockup == null) { continue; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 6ae0542c0..4f203b7a9 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -222,7 +222,7 @@ namespace Jellyfin.Server } finally { - appHost?.Dispose(); + appHost.Dispose(); } if (_restartOnShutdown) @@ -623,7 +623,7 @@ namespace Jellyfin.Server string commandLineArgsString; if (options.RestartArgs != null) { - commandLineArgsString = options.RestartArgs ?? string.Empty; + commandLineArgsString = options.RestartArgs; } else { diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index ddcf2ac17..c3e4ed6db 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Common /// </summary> /// <param name="type">Type to create.</param> /// <returns>New instance of type <param>type</param>.</returns> - public delegate object CreationDelegate(Type type); + public delegate object CreationDelegateFactory(Type type); /// <summary> /// An interface to be implemented by the applications hosting a kernel. @@ -112,7 +112,7 @@ namespace MediaBrowser.Common /// <param name="defaultFunc">Delegate function that gets called to create the object.</param> /// <param name="manageLifetime">If set to <c>true</c> [manage lifetime].</param> /// <returns><see cref="IReadOnlyCollection{T}" />.</returns> - IReadOnlyCollection<T> GetExports<T>(CreationDelegate defaultFunc, bool manageLifetime = true); + IReadOnlyCollection<T> GetExports<T>(CreationDelegateFactory defaultFunc, bool manageLifetime = true); /// <summary> /// Gets the export types. diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 2ef24a884..177ad39fa 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// </remarks> /// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions GetOptions() + public static JsonSerializerOptions Options => _jsonSerializerOptions; /// <summary> @@ -72,7 +72,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// </remarks> /// <returns>The camelCase <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions GetCamelCaseOptions() + public static JsonSerializerOptions CamelCaseOptions => _camelCaseJsonSerializerOptions; /// <summary> @@ -83,7 +83,7 @@ namespace MediaBrowser.Common.Json /// If the defaults must be modified the author must use the copy constructor. /// </remarks> /// <returns>The PascalCase <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions GetPascalCaseOptions() + public static JsonSerializerOptions PascalCaseOptions => _pascalCaseJsonSerializerOptions; } } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 34e1934e2..0d9f78704 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -33,6 +33,8 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> @@ -51,10 +53,6 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> <_Parameter1>Jellyfin.Common.Tests</_Parameter1> diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index 4a7c70190..d67b6b8e1 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -406,7 +406,7 @@ namespace MediaBrowser.Common.Net } // If we haven't resolved before, or our timer has run out... - if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved?.AddMinutes(Timeout))) + if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) { _lastResolved = DateTime.UtcNow; ResolveHostInternal().GetAwaiter().GetResult(); diff --git a/MediaBrowser.Common/Net/IPNetAddress.cs b/MediaBrowser.Common/Net/IPNetAddress.cs index 5fab52eac..59e37a5c6 100644 --- a/MediaBrowser.Common/Net/IPNetAddress.cs +++ b/MediaBrowser.Common/Net/IPNetAddress.cs @@ -216,11 +216,11 @@ namespace MediaBrowser.Common.Net } /// <inheritdoc/> - public override bool Equals(IPAddress address) + public override bool Equals(IPAddress ip) { - if (address != null && !address.Equals(IPAddress.None) && !Address.Equals(IPAddress.None)) + if (ip != null && !ip.Equals(IPAddress.None) && !Address.Equals(IPAddress.None)) { - return address.Equals(Address); + return ip.Equals(Address); } return false; diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 7b162c0e1..ad5a7338d 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Common.Plugins /// Gets a value indicating whether the plugin can be uninstalled. /// </summary> public bool CanUninstall => !Path.GetDirectoryName(AssemblyFilePath) - .Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), StringComparison.InvariantCulture); + .Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), StringComparison.Ordinal); /// <summary> /// Gets the plugin info. diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index d5c780851..99c226f50 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -39,29 +39,27 @@ namespace MediaBrowser.Common.Plugins { ApplicationPaths = applicationPaths; XmlSerializer = xmlSerializer; - if (this is IPluginAssembly assemblyPlugin) - { - var assembly = GetType().Assembly; - var assemblyName = assembly.GetName(); - var assemblyFilePath = assembly.Location; - var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); - if (!Directory.Exists(dataFolderPath) && Version != null) - { - // Try again with the version number appended to the folder name. - dataFolderPath = dataFolderPath + "_" + Version.ToString(); - } + var assembly = GetType().Assembly; + var assemblyName = assembly.GetName(); + var assemblyFilePath = assembly.Location; - assemblyPlugin.SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); + var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); + if (!Directory.Exists(dataFolderPath) && Version != null) + { + // Try again with the version number appended to the folder name. + dataFolderPath = dataFolderPath + "_" + Version.ToString(); + } - var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true); - if (idAttributes.Length > 0) - { - var attribute = (GuidAttribute)idAttributes[0]; - var assemblyId = new Guid(attribute.Value); + SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); - assemblyPlugin.SetId(assemblyId); - } + var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true); + if (idAttributes.Length > 0) + { + var attribute = (GuidAttribute)idAttributes[0]; + var assemblyId = new Guid(attribute.Value); + + SetId(assemblyId); } } diff --git a/MediaBrowser.Common/Plugins/LocalPlugin.cs b/MediaBrowser.Common/Plugins/LocalPlugin.cs index 23b6cfa81..12a1ad1ec 100644 --- a/MediaBrowser.Common/Plugins/LocalPlugin.cs +++ b/MediaBrowser.Common/Plugins/LocalPlugin.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Common.Plugins public LocalPlugin(string path, bool isSupported, PluginManifest manifest) { Path = path; - DllFiles = new List<string>(); + DllFiles = Array.Empty<string>(); _supported = isSupported; Manifest = manifest; } @@ -59,9 +59,9 @@ namespace MediaBrowser.Common.Plugins public string Path { get; } /// <summary> - /// Gets the list of dll files for this plugin. + /// Gets or sets the list of dll files for this plugin. /// </summary> - public List<string> DllFiles { get; } + public IReadOnlyList<string> DllFiles { get; set; } /// <summary> /// Gets or sets the instance of this plugin. diff --git a/MediaBrowser.Common/Progress/ActionableProgress.cs b/MediaBrowser.Common/Progress/ActionableProgress.cs index d5bcd5be9..fe7cb1078 100644 --- a/MediaBrowser.Common/Progress/ActionableProgress.cs +++ b/MediaBrowser.Common/Progress/ActionableProgress.cs @@ -1,4 +1,5 @@ #pragma warning disable CS1591 +#pragma warning disable CA1003 using System; diff --git a/MediaBrowser.Common/Progress/SimpleProgress.cs b/MediaBrowser.Common/Progress/SimpleProgress.cs index d75675bf1..988d8ad34 100644 --- a/MediaBrowser.Common/Progress/SimpleProgress.cs +++ b/MediaBrowser.Common/Progress/SimpleProgress.cs @@ -1,4 +1,5 @@ #pragma warning disable CS1591 +#pragma warning disable CA1003 using System; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 65fd1654c..76b6d39a9 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public class CollectionFolder : Folder, ICollectionFolder { - private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public static IXmlSerializer XmlSerializer { get; set; } public static IServerApplicationHost ApplicationHost { get; set; } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d487a324f..8c68b47dd 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -34,6 +34,8 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors> + <AnalysisMode Condition=" '$(Configuration)' == 'Debug' ">AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> @@ -52,8 +54,4 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs index c129eddb3..f78bd6ddf 100644 --- a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs @@ -10,6 +10,6 @@ namespace MediaBrowser.Controller.Providers /// </summary> public interface ILocalImageProvider : IImageProvider { - List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService); + IEnumerable<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService); } } diff --git a/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs index 556bb6a0e..b6189bcdd 100644 --- a/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderLocalImageProvider.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// <inheritdoc /> - public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) { var collectionFolder = (CollectionFolder)item; diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index 393ad2efb..2d3b2d889 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// <inheritdoc /> - public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) { var parentPath = Path.GetDirectoryName(item.Path); diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index 509b5d700..10d691b3e 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -69,13 +70,13 @@ namespace MediaBrowser.LocalMetadata.Images } /// <inheritdoc /> - public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) { var path = item.GetInternalMetadataPath(); if (!Directory.Exists(path)) { - return new List<LocalImageInfo>(); + return Enumerable.Empty<LocalImageInfo>(); } try @@ -85,7 +86,7 @@ namespace MediaBrowser.LocalMetadata.Images catch (IOException ex) { _logger.LogError(ex, "Error while getting images for {Library}", item.Name); - return new List<LocalImageInfo>(); + return Enumerable.Empty<LocalImageInfo>(); } } } diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index 84c3ed8b0..7ad8c24e8 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -108,7 +108,7 @@ namespace MediaBrowser.LocalMetadata.Images { if (!item.IsFileProtocol) { - return new List<FileSystemMetadata>(); + return Enumerable.Empty<FileSystemMetadata>(); } var path = item.ContainingFolderPath; @@ -116,7 +116,7 @@ namespace MediaBrowser.LocalMetadata.Images // Exit if the cache dir does not exist, alternative solution is to create it, but that's a lot of empty dirs... if (!Directory.Exists(path)) { - return Array.Empty<FileSystemMetadata>(); + return Enumerable.Empty<FileSystemMetadata>(); } if (includeDirectories) @@ -133,7 +133,7 @@ namespace MediaBrowser.LocalMetadata.Images } /// <inheritdoc /> - public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService) { var files = GetFiles(item, true, directoryService).ToList(); @@ -151,7 +151,7 @@ namespace MediaBrowser.LocalMetadata.Images /// <param name="path">The images path.</param> /// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param> /// <returns>The local image info.</returns> - public List<LocalImageInfo> GetImages(BaseItem item, string path, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, string path, IDirectoryService directoryService) { return GetImages(item, new[] { path }, directoryService); } @@ -163,7 +163,7 @@ namespace MediaBrowser.LocalMetadata.Images /// <param name="paths">The image paths.</param> /// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param> /// <returns>The local image info.</returns> - public List<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, IDirectoryService directoryService) + public IEnumerable<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, IDirectoryService directoryService) { IEnumerable<FileSystemMetadata> files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false)); @@ -181,9 +181,7 @@ namespace MediaBrowser.LocalMetadata.Images { if (supportParentSeriesFiles) { - var season = item as Season; - - if (season != null) + if (item is Season season) { PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); } diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 1792f1d9b..eb2077a5f 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -16,6 +16,8 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> @@ -29,8 +31,4 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - </Project> diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index b0afb834b..5f620634f 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -1275,8 +1275,8 @@ namespace MediaBrowser.LocalMetadata.Parsers // Only split by comma if there is no pipe in the string // We have to be careful to not split names like Matthew, Jr. - var separator = value.IndexOf('|', StringComparison.Ordinal) == -1 - && value.IndexOf(';', StringComparison.Ordinal) == -1 ? new[] { ',' } : new[] { '|', ';' }; + var separator = !value.Contains('|', StringComparison.Ordinal) + && !value.Contains(';', StringComparison.Ordinal) ? new[] { ',' } : new[] { '|', ';' }; value = value.Trim().Trim(separator); diff --git a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs index ff846830b..7df800971 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } /// <inheritdoc /> - protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item) + protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> itemResult) { switch (reader.Name) { @@ -33,7 +33,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { using (var subReader = reader.ReadSubtree()) { - FetchFromCollectionItemsNode(subReader, item); + FetchFromCollectionItemsNode(subReader, itemResult); } } else @@ -44,7 +44,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; default: - base.FetchDataFromXmlNode(reader, item); + base.FetchDataFromXmlNode(reader, itemResult); break; } } diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs index 78c0fa8ad..b84307cb2 100644 --- a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs @@ -23,9 +23,9 @@ namespace MediaBrowser.LocalMetadata.Parsers } /// <inheritdoc /> - protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result) + protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> itemResult) { - var item = result.Item; + var item = itemResult.Item; switch (reader.Name) { @@ -53,7 +53,7 @@ namespace MediaBrowser.LocalMetadata.Parsers break; default: - base.FetchDataFromXmlNode(reader, result); + base.FetchDataFromXmlNode(reader, itemResult); break; } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index e59fcb965..dfbce5f49 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -37,7 +36,7 @@ namespace MediaBrowser.LocalMetadata.Savers /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{BaseXmlSaver}"/> interface.</param> - public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger) + protected BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger) { FileSystem = fileSystem; ConfigurationManager = configurationManager; @@ -421,20 +420,17 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - var boxset = item as BoxSet; - if (boxset != null) + if (item is BoxSet boxset) { AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem"); } - var playlist = item as Playlist; - if (playlist != null && !Playlist.IsPlaylistFile(playlist.Path)) + if (item is Playlist playlist && !Playlist.IsPlaylistFile(playlist.Path)) { AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem"); } - var hasShares = item as IHasShares; - if (hasShares != null) + if (item is IHasShares hasShares) { AddShares(hasShares, writer); } @@ -542,10 +538,5 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - - private bool IsPersonType(PersonInfo person, string type) - { - return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 8a25a64c7..47cf020b4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _localization = localization; _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; - _jsonSerializerOptions = JsonDefaults.GetOptions(); + _jsonSerializerOptions = JsonDefaults.Options; } /// <inheritdoc /> diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index cd9e47743..2adb11908 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb { private readonly IServerConfigurationManager _config; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbAlbumImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 0a79f5bb5..00feeec1f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public static AudioDbAlbumProvider Current; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index 36700d191..b8095ff04 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb { private readonly IServerConfigurationManager _config; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbArtistImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 4b1d91567..59ecbc017 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory) { diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 97fcbfb6f..428b0ded1 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb _configurationManager = configurationManager; _appHost = appHost; - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()); + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter()); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index e3301ff32..d35805a84 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb _configurationManager = configurationManager; _appHost = appHost; - _jsonOptions = new JsonSerializerOptions(JsonDefaults.GetOptions()); + _jsonOptions = new JsonSerializerOptions(JsonDefaults.Options); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableStringConverter()); _jsonOptions.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); } diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index c39ef0ce9..415682e85 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -16,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests var path = Path.Join("Test Data", fileName); using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.GetOptions()).ConfigureAwait(false); + await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false); } } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 86d6326d8..f5411dcb8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public sealed class DashboardControllerTests : IClassFixture<JellyfinApplicationFactory> { private readonly JellyfinApplicationFactory _factory; - private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.GetOptions(); + private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.Options; public DashboardControllerTests(JellyfinApplicationFactory factory) { -- cgit v1.2.3 From ef9eba8bc9f697ed6d8bf973d7f5c8d7865ecd18 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Thu, 25 Mar 2021 11:45:27 +0100 Subject: Ignore format for ISO files --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 6 ++++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 09080e7b2..92b9a8c7e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -313,6 +313,12 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } + // ISO files don't have an ffmpeg format + if (string.Equals(container, "iso", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + return container; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 47cf020b4..205933ae2 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -370,7 +370,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetInputArgument(string inputFile, MediaSourceInfo mediaSource) { var prefix = "file"; - if (mediaSource.VideoType == VideoType.BluRay || mediaSource.VideoType == VideoType.Iso) + if (mediaSource.VideoType == VideoType.BluRay) { prefix = "bluray"; } -- cgit v1.2.3 From e0f513232b0b03135fa09fe39862c10982cb469e Mon Sep 17 00:00:00 2001 From: Maxr1998 <max.rumpf1998@gmail.com> Date: Sun, 4 Apr 2021 14:58:20 +0200 Subject: Reduce nesting --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index b2d4db894..e65c16ee2 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -85,12 +85,14 @@ namespace MediaBrowser.MediaEncoding.Probing { var val = GetDictionaryValue(tags, key); - if (!string.IsNullOrEmpty(val)) + if (string.IsNullOrEmpty(val)) { - if (DateTime.TryParse(val, out var i)) - { - return i.ToUniversalTime(); - } + return null; + } + + if (DateTime.TryParse(val, out var i)) + { + return i.ToUniversalTime(); } return null; -- cgit v1.2.3 From 8d27e10cb696fb440ec7773aae69441d0651e64a Mon Sep 17 00:00:00 2001 From: Maxr1998 <max.rumpf1998@gmail.com> Date: Sun, 4 Apr 2021 15:04:01 +0200 Subject: Interpret ffprobe date as UTC Currently, dates are parsed according to the local time, which results in potentially wrong data being stored in the database after normalizing to UTC - e.g. 2021-04-04 would be stored as '2021-04-03 22:00:00Z' and displayed in the UI as 03.04.2021. --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index e65c16ee2..da37687e8 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace MediaBrowser.MediaEncoding.Probing { @@ -90,7 +91,7 @@ namespace MediaBrowser.MediaEncoding.Probing return null; } - if (DateTime.TryParse(val, out var i)) + if (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var i)) { return i.ToUniversalTime(); } -- cgit v1.2.3 From 873ad72c1893e87d1f8a0a744ebfe53b87781521 Mon Sep 17 00:00:00 2001 From: Maxr1998 <max.rumpf1998@gmail.com> Date: Sun, 4 Apr 2021 15:08:08 +0200 Subject: Support MKV DATE_RELEASED tag for PremiereDate https://www.matroska.org/technical/tagging.html#temporal-information --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 75067315f..a87104cd6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -131,6 +131,7 @@ namespace MediaBrowser.MediaEncoding.Probing info.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ?? + FFProbeHelpers.GetDictionaryDateTime(tags, "date_released") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "date"); if (isAudio) -- cgit v1.2.3 From 24ac8a12233936955e31a409c1a131473041846e Mon Sep 17 00:00:00 2001 From: Maxr1998 <max.rumpf1998@gmail.com> Date: Sun, 4 Apr 2021 23:34:29 +0200 Subject: Improve metadata probing to better support music videos --- .../Probing/ProbeResultNormalizer.cs | 95 +++++++++++++--------- MediaBrowser.Model/MediaInfo/MediaInfo.cs | 2 + .../MediaInfo/FFProbeAudioInfo.cs | 5 ++ .../MediaInfo/FFProbeVideoInfo.cs | 11 +++ 4 files changed, 74 insertions(+), 39 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index a87104cd6..22624dfd7 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -121,19 +121,67 @@ namespace MediaBrowser.MediaEncoding.Probing { info.Name = title; } + else + { + title = FFProbeHelpers.GetDictionaryValue(tags, "title-eng"); + if (!string.IsNullOrWhiteSpace(title)) + { + info.Name = title; + } + } + + var titleSort = FFProbeHelpers.GetDictionaryValue(tags, "titlesort"); + if (!string.IsNullOrWhiteSpace(titleSort)) + { + info.ForcedSortName = titleSort; + } info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); - // Several different forms of retaildate - info.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ?? + // Several different forms of retail/premiere date + info.PremiereDate = + FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "date_released") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "date"); + // Set common metadata for music (audio) and music videos (video) + info.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); + + var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); + + if (!string.IsNullOrWhiteSpace(artists)) + { + info.Artists = SplitArtists(artists, new[] { '/', ';' }, false) + .DistinctNames() + .ToArray(); + } + else + { + var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); + if (string.IsNullOrWhiteSpace(artist)) + { + info.Artists = Array.Empty<string>(); + } + else + { + info.Artists = SplitArtists(artist, _nameDelimiters, true) + .DistinctNames() + .ToArray(); + } + } + + // If we don't have a ProductionYear try and get it from PremiereDate + if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue) + { + info.ProductionYear = info.PremiereDate.Value.Year; + } + + // Set mediaType-specific metadata if (isAudio) { SetAudioRuntimeTicks(data, info); @@ -1076,13 +1124,13 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags) { - var peoples = new List<BaseItemPerson>(); + var people = new List<BaseItemPerson>(); var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); if (!string.IsNullOrWhiteSpace(composer)) { foreach (var person in Split(composer, false)) { - peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer }); + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer }); } } @@ -1091,7 +1139,7 @@ namespace MediaBrowser.MediaEncoding.Probing { foreach (var person in Split(conductor, false)) { - peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); } } @@ -1100,46 +1148,21 @@ namespace MediaBrowser.MediaEncoding.Probing { foreach (var person in Split(lyricist, false)) { - peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); } } // Check for writer some music is tagged that way as alternative to composer/lyricist var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); - if (!string.IsNullOrWhiteSpace(writer)) { foreach (var person in Split(writer, false)) { - peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer }); + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer }); } } - audio.People = peoples.ToArray(); - audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); - - var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); - - if (!string.IsNullOrWhiteSpace(artists)) - { - audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false) - .DistinctNames() - .ToArray(); - } - else - { - var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); - if (string.IsNullOrWhiteSpace(artist)) - { - audio.Artists = Array.Empty<string>(); - } - else - { - audio.Artists = SplitArtists(artist, _nameDelimiters, true) - .DistinctNames() - .ToArray(); - } - } + audio.People = people.ToArray(); var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist"); if (string.IsNullOrWhiteSpace(albumArtist)) @@ -1174,12 +1197,6 @@ namespace MediaBrowser.MediaEncoding.Probing // Disc number audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc"); - // If we don't have a ProductionYear try and get it from PremiereDate - if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue) - { - audio.ProductionYear = audio.PremiereDate.Value.ToLocalTime().Year; - } - // There's several values in tags may or may not be present FetchStudios(audio, tags, "organization"); FetchStudios(audio, tags, "ensemble"); diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index a268a4fa6..453aeb028 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -51,6 +51,8 @@ namespace MediaBrowser.Model.MediaInfo public string ShowName { get; set; } + public string ForcedSortName { get; set; } + public int? IndexNumber { get; set; } public int? ParentIndexNumber { get; set; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 945463666..cf271e7db 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -111,6 +111,11 @@ namespace MediaBrowser.Providers.MediaInfo audio.Name = data.Name; } + if (!string.IsNullOrEmpty(data.ForcedSortName)) + { + audio.ForcedSortName = data.ForcedSortName; + } + if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) { var people = new List<PersonInfo>(); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 74849a522..e7f9cf314 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -394,6 +394,12 @@ namespace MediaBrowser.Providers.MediaInfo } } + if (video is MusicVideo musicVideo) + { + musicVideo.Album = data.Album; + musicVideo.Artists = data.Artists; + } + if (data.ProductionYear.HasValue) { if (!video.ProductionYear.HasValue || isFullRefresh) @@ -436,6 +442,11 @@ namespace MediaBrowser.Providers.MediaInfo video.Name = data.Name; } } + + if (!string.IsNullOrWhiteSpace(data.ForcedSortName)) + { + video.ForcedSortName = data.ForcedSortName; + } } // If we don't have a ProductionYear try and get it from PremiereDate -- cgit v1.2.3 From bb6fddde9ac48905b876717806754a052bf0ad24 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Sat, 17 Apr 2021 11:19:09 +0100 Subject: Group Methods --- Emby.Server.Implementations/Playlists/PlaylistManager.cs | 2 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 ++-- Jellyfin.Networking/Manager/NetworkManager.cs | 2 +- Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 932f721ab..2d1a559f1 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -215,7 +215,7 @@ namespace Emby.Server.Implementations.Playlists // Create a list of the new linked children to add to the playlist var childrenToAdd = newItems - .Select(i => LinkedChild.Create(i)) + .Select(LinkedChild.Create) .ToList(); // Log duplicates that have been ignored, if any diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index e2306aa27..404cb3a46 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -121,14 +121,14 @@ namespace Jellyfin.Api.Helpers if (!string.IsNullOrWhiteSpace(streamingRequest.AudioCodec)) { state.SupportedAudioCodecs = streamingRequest.AudioCodec.Split(',', StringSplitOptions.RemoveEmptyEntries); - state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToAudioCodec(i)) + state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(mediaEncoder.CanEncodeToAudioCodec) ?? state.SupportedAudioCodecs.FirstOrDefault(); } if (!string.IsNullOrWhiteSpace(streamingRequest.SubtitleCodec)) { state.SupportedSubtitleCodecs = streamingRequest.SubtitleCodec.Split(',', StringSplitOptions.RemoveEmptyEntries); - state.Request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToSubtitleCodec(i)) + state.Request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(mediaEncoder.CanEncodeToSubtitleCodec) ?? state.SupportedSubtitleCodecs.FirstOrDefault(); } diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 73e8b2cd7..4078fd126 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -1067,7 +1067,7 @@ namespace Jellyfin.Networking.Manager } // Internal interfaces must be private, not excluded and part of the LocalNetworkSubnet. - _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsInLocalNetwork(i))); + _internalInterfaces = CreateCollection(_interfaceAddresses.Where(IsInLocalNetwork)); } _logger.LogInformation("Defined LAN addresses : {0}", _lanSubnets.AsString()); diff --git a/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs b/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs index 6821630db..ee4f8b0ba 100644 --- a/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs +++ b/Jellyfin.Server/Migrations/Routines/CreateUserLoggingConfigFile.cs @@ -75,7 +75,7 @@ namespace Jellyfin.Server.Migrations.Routines { var existingConfigJson = JToken.Parse(File.ReadAllText(oldConfigPath)); return _defaultConfigHistory - .Select(historicalConfigText => JToken.Parse(historicalConfigText)) + .Select(JToken.Parse) .Any(historicalConfigJson => JToken.DeepEquals(existingConfigJson, historicalConfigJson)); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 53d45261e..1b69c6646 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2324,7 +2324,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.IsLocalFile) .Select(i => System.IO.Path.GetDirectoryName(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) - .SelectMany(i => directoryService.GetFilePaths(i)) + .SelectMany(directoryService.GetFilePaths) .ToList(); var deletedImages = ImageInfos diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index a87104cd6..ee2e5fcde 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Probing .Where(i => i.Type != MediaStreamType.Subtitle || !string.IsNullOrWhiteSpace(i.Codec)) .ToList(); - info.MediaAttachments = internalStreams.Select(s => GetMediaAttachment(s)) + info.MediaAttachments = internalStreams.Select(GetMediaAttachment) .Where(i => i != null) .ToList(); diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 398d47d5f..f4c69fe8f 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -297,7 +297,7 @@ namespace MediaBrowser.Model.Dlna int? inputAudioSampleRate = audioStream?.SampleRate; int? inputAudioBitDepth = audioStream?.BitDepth; - if (directPlayMethods.Count() > 0) + if (directPlayMethods.Any()) { string audioCodec = audioStream?.Codec; -- cgit v1.2.3 From bc1cc2d04ae0e823becf59964e5bdc5a74ae7741 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Sat, 17 Apr 2021 11:37:55 +0100 Subject: Remove unused using directives --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 2 -- Emby.Dlna/Main/DlnaEntryPoint.cs | 1 - .../MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs | 1 - Emby.Dlna/PlayTo/SsdpHttpClient.cs | 1 - Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 1 - Emby.Server.Implementations/Channels/ChannelManager.cs | 1 - Emby.Server.Implementations/Collections/CollectionManager.cs | 3 --- Emby.Server.Implementations/ConfigurationOptions.cs | 1 - Emby.Server.Implementations/HttpServer/Security/AuthService.cs | 1 - Emby.Server.Implementations/IStartupOptions.cs | 1 - Emby.Server.Implementations/Images/ArtistImageProvider.cs | 8 -------- Emby.Server.Implementations/Images/DynamicImageProvider.cs | 1 - Emby.Server.Implementations/Library/PathExtensions.cs | 2 -- Emby.Server.Implementations/Library/SearchEngine.cs | 1 - Emby.Server.Implementations/Library/UserDataManager.cs | 2 +- Emby.Server.Implementations/Library/UserViewManager.cs | 1 - Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 1 - Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs | 2 -- Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs | 1 - .../LiveTv/Listings/XmlTvListingsProvider.cs | 1 - .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 --- Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs | 1 - Emby.Server.Implementations/Localization/LocalizationManager.cs | 1 - Emby.Server.Implementations/MediaEncoder/EncodingManager.cs | 1 - Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs | 1 - Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs | 1 - .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- .../ScheduledTasks/Tasks/PeopleValidationTask.cs | 2 +- .../ScheduledTasks/Tasks/PluginUpdateTask.cs | 1 - .../ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 1 - Jellyfin.Api/Extensions/DtoExtensions.cs | 1 - Jellyfin.Api/Helpers/AudioHelper.cs | 3 +-- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 1 - Jellyfin.Data/Entities/HomeSection.cs | 3 +-- Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs | 1 - Jellyfin.Networking/Configuration/NetworkConfiguration.cs | 1 - .../Configuration/NetworkConfigurationExtensions.cs | 1 - Jellyfin.Server/Filters/ParameterObsoleteFilter.cs | 1 - Jellyfin.Server/Formatters/CssOutputFormatter.cs | 3 +-- Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs | 2 -- Jellyfin.Server/Middleware/LanFilteringMiddleware.cs | 3 --- .../Migrations/Routines/DisableTranscodingThrottling.cs | 1 - Jellyfin.Server/Program.cs | 2 -- Jellyfin.Server/StartupOptions.cs | 3 --- MediaBrowser.Common/Cryptography/PasswordHash.cs | 1 - MediaBrowser.Common/Net/INetworkManager.cs | 1 - MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs | 1 - MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs | 1 - MediaBrowser.Controller/Drawing/ImageHelper.cs | 3 --- MediaBrowser.Controller/Entities/Folder.cs | 1 - .../Events/Updates/PluginUninstalledEventArgs.cs | 1 - MediaBrowser.Controller/IServerApplicationHost.cs | 3 --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 -- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 1 - MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs | 1 - MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 1 - MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs | 5 ----- MediaBrowser.Controller/Playlists/Playlist.cs | 1 - MediaBrowser.Controller/Providers/IRemoteImageProvider.cs | 1 - MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs | 1 - MediaBrowser.Controller/Subtitles/ISubtitleManager.cs | 1 - MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 1 - MediaBrowser.Model/Dto/NameIdPair.cs | 2 -- MediaBrowser.Model/LiveTv/TunerHostInfo.cs | 3 --- MediaBrowser.Model/Notifications/NotificationOptions.cs | 2 -- MediaBrowser.Providers/Manager/ProviderManager.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs | 1 - MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs | 1 - MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 2 -- MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 4 ++-- tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs | 1 - .../Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs | 1 - tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs | 1 - .../Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs | 1 - tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs | 1 - tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs | 1 - tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs | 1 - .../IO/ManagedFileSystemTests.cs | 1 - tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs | 2 -- tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs | 1 - tests/Jellyfin.Server.Tests/ParseNetworkTests.cs | 1 - .../Parsers/MusicArtistNfoParserTests.cs | 1 - 86 files changed, 9 insertions(+), 125 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 713f95099..90ba601b4 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -7,7 +6,6 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; -using Emby.Dlna.Configuration; using Emby.Dlna.Didl; using Emby.Dlna.Service; using Jellyfin.Data.Entities; diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index d3e9a41ec..bdfe430cf 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Linq; using System.Net.Http; using System.Net.Sockets; -using System.Threading; using System.Threading.Tasks; using Emby.Dlna.PlayTo; using Emby.Dlna.Ssdp; diff --git a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs index 37840cd09..f3789a791 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarXmlBuilder.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Emby.Dlna.Common; using Emby.Dlna.Service; -using MediaBrowser.Model.Dlna; namespace Emby.Dlna.MediaReceiverRegistrar { diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index e750f5bbc..d9f1ce490 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -2,7 +2,6 @@ using System; using System.Globalization; -using System.IO; using System.Net.Http; using System.Net.Mime; using System.Text; diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 3f7076383..29bac6634 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -3,7 +3,6 @@ using System; using System.IO; using System.Linq; -using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 87ebe960a..7324b0ee9 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index db532ce5b..e984afdba 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -8,11 +7,9 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index cd9dbb1bd..01dc728c1 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Emby.Server.Implementations.HttpServer; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Emby.Server.Implementations diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 4a0fc8239..9afabf527 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 -using System; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Net; diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index 0b823ff06..f719dc5f8 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 #nullable enable -using System; namespace Emby.Server.Implementations { diff --git a/Emby.Server.Implementations/Images/ArtistImageProvider.cs b/Emby.Server.Implementations/Images/ArtistImageProvider.cs index afa4ec7b1..e96b64595 100644 --- a/Emby.Server.Implementations/Images/ArtistImageProvider.cs +++ b/Emby.Server.Implementations/Images/ArtistImageProvider.cs @@ -2,20 +2,12 @@ using System; using System.Collections.Generic; -using System.Linq; -using Emby.Server.Implementations.Images; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 462eb03a8..50c531482 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Emby.Server.Implementations.Images; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 6eaecff0f..770cf6bb0 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -2,8 +2,6 @@ using System; using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Text.RegularExpressions; using MediaBrowser.Common.Providers; namespace Emby.Server.Implementations.Library diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 94602582b..bcdf854ca 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Search; -using Microsoft.Extensions.Logging; using Genre = MediaBrowser.Controller.Entities.Genre; using Person = MediaBrowser.Controller.Entities.Person; diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index d16275b19..e8caea196 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -13,8 +13,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using Book = MediaBrowser.Controller.Entities.Book; using AudioBook = MediaBrowser.Controller.Entities.AudioBook; +using Book = MediaBrowser.Controller.Entities.Book; namespace Emby.Server.Implementations.Library { diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index b6b7ea949..ac041bcf6 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using Jellyfin.Data.Entities; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 91a21db60..c9d9cc49a 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -17,7 +17,6 @@ using Jellyfin.Data.Enums; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index c20b08088..1cac9cb96 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; -using System.Threading.Tasks; using MediaBrowser.Common.Json; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs index da707fec6..b1259de23 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs @@ -2,7 +2,6 @@ using System; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 76c875737..6824aa442 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Threading; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 68173a0ef..1dcc78687 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -8,10 +8,8 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; @@ -19,7 +17,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 2af635492..cc30a516d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 98de848bc..2fdc2b4d9 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -11,7 +11,6 @@ using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Localization diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index a9dab9138..031b5d2e7 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -15,7 +15,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.MediaEncoder diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 7bed06de3..22739a008 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.Globalization; using System.Linq; using System.Security.Cryptography; -using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Authentication; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 3cc2cefb9..9c0e92705 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -4,7 +4,6 @@ using System; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 649305fd5..2312c85d9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -12,9 +12,9 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Globalization; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index c384cf4bb..57d294a40 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -5,8 +5,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index a69380cbb..11a5fb79f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -9,7 +9,6 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index e470adcf4..51b620404 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -6,8 +6,8 @@ using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Library; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; namespace Emby.Server.Implementations.ScheduledTasks { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 24285bfb9..adec86a10 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -12,7 +12,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Json; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; using Microsoft.AspNetCore.Authorization; diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index e0c744325..06173315a 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 21ec2d32f..9c35d1ec1 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -1,5 +1,4 @@ -using System; -using System.Net.Http; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 751b48682..1bb504ad1 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; -using System.Net.Mime; using System.Security.Claims; using System.Text; using System.Threading; diff --git a/Jellyfin.Data/Entities/HomeSection.cs b/Jellyfin.Data/Entities/HomeSection.cs index 5adc52491..d03d0f7a8 100644 --- a/Jellyfin.Data/Entities/HomeSection.cs +++ b/Jellyfin.Data/Entities/HomeSection.cs @@ -1,5 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; namespace Jellyfin.Data.Entities diff --git a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs index 730deccae..cc04d033a 100644 --- a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index 91bf0015f..faf814c06 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -1,7 +1,6 @@ #pragma warning disable CA1819 // Properties should not return arrays using System; -using MediaBrowser.Model.Configuration; namespace Jellyfin.Networking.Configuration { diff --git a/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs b/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs index e77b17ba9..8cbe398b0 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfigurationExtensions.cs @@ -1,4 +1,3 @@ -using Jellyfin.Networking.Configuration; using MediaBrowser.Common.Configuration; namespace Jellyfin.Networking.Configuration diff --git a/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs b/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs index e54044d0e..b9ce221f5 100644 --- a/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs +++ b/Jellyfin.Server/Filters/ParameterObsoleteFilter.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using Jellyfin.Api.Attributes; -using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; diff --git a/Jellyfin.Server/Formatters/CssOutputFormatter.cs b/Jellyfin.Server/Formatters/CssOutputFormatter.cs index e8dd48e4e..cfc9d1ad3 100644 --- a/Jellyfin.Server/Formatters/CssOutputFormatter.cs +++ b/Jellyfin.Server/Formatters/CssOutputFormatter.cs @@ -1,5 +1,4 @@ -using System; -using System.Text; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Formatters; diff --git a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs index 7d92bd7d3..0afcd61a0 100644 --- a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs +++ b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs @@ -1,9 +1,7 @@ using System.Net; using System.Threading.Tasks; -using Jellyfin.Networking.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; namespace Jellyfin.Server.Middleware diff --git a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs index 8065054a1..67bf24d2a 100644 --- a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs +++ b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs @@ -1,9 +1,6 @@ -using System; -using System.Linq; using System.Net; using System.Threading.Tasks; using Jellyfin.Networking.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs index bf0225e98..378e88e25 100644 --- a/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs +++ b/Jellyfin.Server/Migrations/Routines/DisableTranscodingThrottling.cs @@ -1,6 +1,5 @@ using System; using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Migrations.Routines diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 464e02419..c10b2ddb3 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -12,12 +12,10 @@ using System.Threading.Tasks; using CommandLine; using Emby.Server.Implementations; using Emby.Server.Implementations.IO; -using Jellyfin.Api.Controllers; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Extensions; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 6d8210527..a1cecc8c6 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -1,10 +1,7 @@ -using System; using System.Collections.Generic; using CommandLine; using Emby.Server.Implementations; -using Emby.Server.Implementations.EntryPoints; using Emby.Server.Implementations.Udp; -using Emby.Server.Implementations.Updates; using MediaBrowser.Controller.Extensions; namespace Jellyfin.Server diff --git a/MediaBrowser.Common/Cryptography/PasswordHash.cs b/MediaBrowser.Common/Cryptography/PasswordHash.cs index f2ecc4741..ec21d0580 100644 --- a/MediaBrowser.Common/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Common/Cryptography/PasswordHash.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Text; namespace MediaBrowser.Common.Cryptography diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 012824f65..185df5b77 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net; using System.Net.NetworkInformation; -using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Common.Net diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs index 31dd95402..a233c358e 100644 --- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Threading; -using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs index e1f5d05a6..8a8736427 100644 --- a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 181f8e905..596fcbc8c 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -1,10 +1,7 @@ #pragma warning disable CS1591 #nullable enable -using System; -using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Drawing { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index cac5026f7..bdca5c0ee 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Text.Json.Serialization; diff --git a/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs index a111e6d82..0f27be9bb 100644 --- a/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs +++ b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs @@ -1,5 +1,4 @@ using Jellyfin.Data.Events; -using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; namespace MediaBrowser.Controller.Events.Updates diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 20bfa697e..6a65a8e47 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -3,10 +3,7 @@ using System; using System.Collections.Generic; using System.Net; -using System.Threading; -using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Plugins; using MediaBrowser.Model.System; using Microsoft.AspNetCore.Http; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 92b9a8c7e..1379efacb 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -10,8 +10,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index dacd6dea6..d47a689f4 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -9,7 +9,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 5cbb57990..05dd1a69b 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index cc8820f39..227c5f258 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -3,7 +3,6 @@ using System; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 281d50372..89e01c08b 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -1,10 +1,5 @@ #pragma warning disable CS1591 -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.MediaEncoding { diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 977b14cb0..a5b7363fb 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Playlists diff --git a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs index ee8f5b860..de1631dcf 100644 --- a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; diff --git a/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs index 9592baa7c..e401ed211 100644 --- a/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs @@ -3,7 +3,6 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; namespace MediaBrowser.Controller.Providers { diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs index feb26bc10..6d63286ef 100644 --- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs +++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 205933ae2..36bf77c84 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -16,7 +16,6 @@ using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 8a7c032c5..7b7744163 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; namespace MediaBrowser.MediaEncoding.Probing { diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs index 7f18b4502..31516947f 100644 --- a/MediaBrowser.Model/Dto/NameIdPair.cs +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -1,8 +1,6 @@ #nullable disable #pragma warning disable CS1591 -using System; - namespace MediaBrowser.Model.Dto { public class NameIdPair diff --git a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs index 7d4bbb2d0..05576a0f8 100644 --- a/MediaBrowser.Model/LiveTv/TunerHostInfo.cs +++ b/MediaBrowser.Model/LiveTv/TunerHostInfo.cs @@ -1,9 +1,6 @@ #nullable disable #pragma warning disable CS1591 -using System; -using MediaBrowser.Model.Dto; - namespace MediaBrowser.Model.LiveTv { public class TunerHostInfo diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs index 94bb5d6e3..12e093b21 100644 --- a/MediaBrowser.Model/Notifications/NotificationOptions.cs +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -5,8 +5,6 @@ using System; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Notifications { diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index b4b0b826f..3bb2c6f0b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -25,7 +25,6 @@ using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using Microsoft.Extensions.Logging; using Priority_Queue; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index 2adb11908..85a28747f 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Plugins.AudioDb { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 00feeec1f..25bb3f9ce 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -19,7 +19,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; namespace MediaBrowser.Providers.Plugins.AudioDb diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index b8095ff04..db8536cc9 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Plugins.AudioDb { diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 59ecbc017..cbb61fa35 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -18,7 +18,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Music; namespace MediaBrowser.Providers.Plugins.AudioDb diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index d35805a84..46d303890 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -6,9 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; -using System.Text; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 833d1ae38..d22c1b50a 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -7,8 +7,6 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using TMDbLib.Objects.Find; -using TMDbLib.Objects.Search; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -16,6 +14,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; +using TMDbLib.Objects.Find; +using TMDbLib.Objects.Search; namespace MediaBrowser.Providers.Plugins.Tmdb.Movies { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs index 1e1cde957..dbfad3c2f 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Text.Json; using MediaBrowser.Common.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs index 22bc7afb9..cb3b66c4c 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Text.Json; using MediaBrowser.Common.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs index 51633e157..5864a0509 100644 --- a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs +++ b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs @@ -1,4 +1,3 @@ -using System; using MediaBrowser.Model.Extensions; using Xunit; diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs index e5768b620..d9e77dd2e 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookListResolverTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Emby.Naming.AudioBook; using Emby.Naming.Common; diff --git a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs index ad63adadc..53b35c2d6 100644 --- a/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/AudioBook/AudioBookResolverTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Emby.Naming.AudioBook; using Emby.Naming.Common; diff --git a/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs index f3abacb4f..2446660f3 100644 --- a/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs +++ b/tests/Jellyfin.Naming.Tests/Subtitles/SubtitleParserTests.cs @@ -1,4 +1,3 @@ -using System; using Emby.Naming.Common; using Emby.Naming.Subtitles; using Xunit; diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs index d34f65409..2f173b0ce 100644 --- a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs @@ -1,4 +1,3 @@ -using System; using Emby.Naming.Common; using Emby.Naming.Video; using MediaBrowser.Model.Entities; diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 5a535ac51..614a68975 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; diff --git a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 3cbd638f9..0ade345a1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -1,8 +1,6 @@ using System.IO; using System.Reflection; -using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Model.Branding; using Xunit; using Xunit.Abstractions; diff --git a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs index 4e5d0fcb6..0a463cfa3 100644 --- a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Reflection; using Emby.Server.Implementations; -using Jellyfin.Server; using MediaBrowser.Controller; using MediaBrowser.Model.IO; using Microsoft.Extensions.Configuration; diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 0b714e80a..146b16cf9 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; using System.Text; using Jellyfin.Networking.Configuration; diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs index 3d8e13e96..8ca3dd96e 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Threading; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities.Audio; -- cgit v1.2.3 From 499bac51854cf880beb4add835babf8abd8eb738 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 20 Apr 2021 23:03:36 +0200 Subject: EncodingHelper: Fix circular dependency --- Emby.Server.Implementations/ApplicationHost.cs | 3 +-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 24 ++++++------------- Jellyfin.Api/Controllers/VideoHlsController.cs | 24 +++++-------------- Jellyfin.Api/Controllers/VideosController.cs | 25 ++++++-------------- Jellyfin.Api/Helpers/AudioHelper.cs | 25 ++++++-------------- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 27 +++++++--------------- Jellyfin.Api/Helpers/StreamingHelpers.cs | 9 ++------ Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 8 +++---- .../MediaEncoding/EncodingHelper.cs | 8 +------ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 3 --- 10 files changed, 42 insertions(+), 114 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0512adf10..1ed74210d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -610,9 +610,8 @@ namespace Emby.Server.Implementations // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required ServiceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>)); - // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required - ServiceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>)); ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(); + ServiceCollection.AddSingleton<EncodingHelper>(); // TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required ServiceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>)); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index c4e75fe85..b4154b361 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -52,8 +52,6 @@ namespace Jellyfin.Api.Controllers private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly ILogger<DynamicHlsController> _logger; @@ -72,12 +70,11 @@ namespace Jellyfin.Api.Controllers /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param> /// <param name="logger">Instance of the <see cref="ILogger{DynamicHlsController}"/> interface.</param> /// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public DynamicHlsController( ILibraryManager libraryManager, IUserManager userManager, @@ -87,15 +84,12 @@ namespace Jellyfin.Api.Controllers IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, ILogger<DynamicHlsController> logger, - DynamicHlsHelper dynamicHlsHelper) + DynamicHlsHelper dynamicHlsHelper, + EncodingHelper encodingHelper) { - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); - _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; @@ -104,12 +98,12 @@ namespace Jellyfin.Api.Controllers _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _logger = logger; _dynamicHlsHelper = dynamicHlsHelper; + _encodingHelper = encodingHelper; + _encodingOptions = serverConfigurationManager.GetEncodingOptions(); } @@ -1126,9 +1120,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -1211,9 +1203,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index e95410d02..308334b23 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -48,9 +48,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly ILogger<VideoHlsController> _logger; @@ -60,9 +57,6 @@ namespace Jellyfin.Api.Controllers /// Initializes a new instance of the <see cref="VideoHlsController"/> class. /// </summary> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="userManger">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> @@ -72,11 +66,9 @@ namespace Jellyfin.Api.Controllers /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">The <see cref="TranscodingJobHelper"/> singleton.</param> /// <param name="logger">Instance of the <see cref="ILogger{VideoHlsController}"/>.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public VideoHlsController( IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDlnaManager dlnaManager, IUserManager userManger, IAuthorizationContext authorizationContext, @@ -85,10 +77,9 @@ namespace Jellyfin.Api.Controllers IServerConfigurationManager serverConfigurationManager, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, - ILogger<VideoHlsController> logger) + ILogger<VideoHlsController> logger, + EncodingHelper encodingHelper) { - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); - _dlnaManager = dlnaManager; _authContext = authorizationContext; _userManager = userManger; @@ -96,12 +87,11 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _logger = logger; + _encodingHelper = encodingHelper; + _encodingOptions = serverConfigurationManager.GetEncodingOptions(); } @@ -285,9 +275,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 699ca5327..8dbb6aaa5 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -49,12 +49,10 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; + private readonly EncodingHelper _encodingHelper; private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive; @@ -69,12 +67,10 @@ namespace Jellyfin.Api.Controllers /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param> /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public VideosController( ILibraryManager libraryManager, IUserManager userManager, @@ -84,12 +80,10 @@ namespace Jellyfin.Api.Controllers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, - IHttpClientFactory httpClientFactory) + IHttpClientFactory httpClientFactory, + EncodingHelper encodingHelper) { _libraryManager = libraryManager; _userManager = userManager; @@ -99,12 +93,10 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; + _encodingHelper = encodingHelper; } /// <summary> @@ -444,9 +436,7 @@ namespace Jellyfin.Api.Controllers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -515,8 +505,7 @@ namespace Jellyfin.Api.Controllers // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); - var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var ffmpegCommandLineArguments = encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); + var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 9c35d1ec1..cf35ee23a 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -32,13 +32,11 @@ namespace Jellyfin.Api.Helpers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly EncodingHelper _encodingHelper; /// <summary> /// Initializes a new instance of the <see cref="AudioHelper"/> class. @@ -50,13 +48,11 @@ namespace Jellyfin.Api.Helpers /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">Instance of <see cref="TranscodingJobHelper"/>.</param> /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param> /// <param name="httpContextAccessor">Instance of the <see cref="IHttpContextAccessor"/> interface.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public AudioHelper( IDlnaManager dlnaManager, IAuthorizationContext authContext, @@ -65,13 +61,11 @@ namespace Jellyfin.Api.Helpers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, IHttpClientFactory httpClientFactory, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + EncodingHelper encodingHelper) { _dlnaManager = dlnaManager; _authContext = authContext; @@ -80,13 +74,11 @@ namespace Jellyfin.Api.Helpers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; _httpContextAccessor = httpContextAccessor; + _encodingHelper = encodingHelper; } /// <summary> @@ -116,9 +108,7 @@ namespace Jellyfin.Api.Helpers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -187,8 +177,7 @@ namespace Jellyfin.Api.Helpers // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); - var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var ffmpegCommandLineArguments = encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath); + var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath); return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 1bb504ad1..fcada0e77 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -40,14 +40,12 @@ namespace Jellyfin.Api.Helpers private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly INetworkManager _networkManager; private readonly ILogger<DynamicHlsHelper> _logger; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly EncodingHelper _encodingHelper; /// <summary> /// Initializes a new instance of the <see cref="DynamicHlsHelper"/> class. @@ -59,14 +57,12 @@ namespace Jellyfin.Api.Helpers /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">Instance of <see cref="TranscodingJobHelper"/>.</param> /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{DynamicHlsHelper}"/> interface.</param> /// <param name="httpContextAccessor">Instance of the <see cref="IHttpContextAccessor"/> interface.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> public DynamicHlsHelper( ILibraryManager libraryManager, IUserManager userManager, @@ -75,14 +71,12 @@ namespace Jellyfin.Api.Helpers IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, INetworkManager networkManager, ILogger<DynamicHlsHelper> logger, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + EncodingHelper encodingHelper) { _libraryManager = libraryManager; _userManager = userManager; @@ -91,14 +85,12 @@ namespace Jellyfin.Api.Helpers _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _configuration = configuration; _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _networkManager = networkManager; _logger = logger; _httpContextAccessor = httpContextAccessor; + _encodingHelper = encodingHelper; } /// <summary> @@ -144,9 +136,7 @@ namespace Jellyfin.Api.Helpers _libraryManager, _serverConfigurationManager, _mediaEncoder, - _fileSystem, - _subtitleEncoder, - _configuration, + _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, @@ -227,9 +217,8 @@ namespace Jellyfin.Api.Helpers var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main"); sdrVideoUrl += "&AllowVideoStreamCopy=false"; - EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); - var sdrOutputVideoBitrate = encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0; - var sdrOutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; + var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0; + var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0; var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate; AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index e2306aa27..bab901c15 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -41,9 +41,7 @@ namespace Jellyfin.Api.Helpers /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="transcodingJobHelper">Initialized <see cref="TranscodingJobHelper"/>.</param> @@ -59,16 +57,13 @@ namespace Jellyfin.Api.Helpers ILibraryManager libraryManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, + EncodingHelper encodingHelper, IDlnaManager dlnaManager, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, TranscodingJobType transcodingJobType, CancellationToken cancellationToken) { - EncodingHelper encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); // Parse the DLNA time seek header if (!streamingRequest.StartTimeTicks.HasValue) { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 240d132b1..0879cbd18 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -62,8 +62,7 @@ namespace Jellyfin.Api.Helpers /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> - /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> - /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> + /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> public TranscodingJobHelper( ILogger<TranscodingJobHelper> logger, @@ -73,8 +72,7 @@ namespace Jellyfin.Api.Helpers IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration, + EncodingHelper encodingHelper, ILoggerFactory loggerFactory) { _logger = logger; @@ -84,8 +82,8 @@ namespace Jellyfin.Api.Helpers _serverConfigurationManager = serverConfigurationManager; _sessionManager = sessionManager; _authorizationContext = authorizationContext; + _encodingHelper = encodingHelper; _loggerFactory = loggerFactory; - _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration); DeleteEncodedMediaCache(); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1379efacb..2b5364775 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -25,9 +25,7 @@ namespace MediaBrowser.Controller.MediaEncoding private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IMediaEncoder _mediaEncoder; - private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfiguration _configuration; private static readonly string[] _videoProfiles = new[] { @@ -42,14 +40,10 @@ namespace MediaBrowser.Controller.MediaEncoding public EncodingHelper( IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - ISubtitleEncoder subtitleEncoder, - IConfiguration configuration) + ISubtitleEncoder subtitleEncoder) { _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; - _configuration = configuration; } public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 36bf77c84..62c0c0bb1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -52,7 +52,6 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; - private readonly Lazy<EncodingHelper> _encodingHelperFactory; private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); @@ -76,14 +75,12 @@ namespace MediaBrowser.MediaEncoding.Encoder IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, - Lazy<EncodingHelper> encodingHelperFactory, IConfiguration config) { _logger = logger; _configurationManager = configurationManager; _fileSystem = fileSystem; _localization = localization; - _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; _jsonSerializerOptions = JsonDefaults.Options; } -- cgit v1.2.3 From f2c10471bf00263adc6411b38db60ba931d0ec15 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Wed, 5 May 2021 12:37:36 +0100 Subject: Code Clean up: Use Pattern Matching (#5838) Co-authored-by: Cody Robibero <cody@robibe.ro> Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- .../Images/PlaylistImageProvider.cs | 4 +--- Emby.Server.Implementations/Library/MusicManager.cs | 3 +-- .../ScheduledTasks/ScheduledTaskWorker.cs | 4 +--- Emby.Server.Implementations/TV/TVSeriesManager.cs | 8 ++------ MediaBrowser.Controller/Entities/CollectionFolder.cs | 4 +--- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 3 +-- MediaBrowser.Controller/Entities/Photo.cs | 3 +-- MediaBrowser.Controller/Entities/TV/Series.cs | 11 ++--------- MediaBrowser.Controller/Providers/ItemInfo.cs | 3 +-- MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs | 3 +-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 6 ++---- MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs | 16 ++++------------ MediaBrowser.Providers/Manager/MetadataService.cs | 6 ++---- MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs | 4 +--- MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs | 4 +--- MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs | 4 +--- 16 files changed, 23 insertions(+), 63 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs index 0ce1b91e8..a4c106e87 100644 --- a/Emby.Server.Implementations/Images/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Images/PlaylistImageProvider.cs @@ -29,9 +29,7 @@ namespace Emby.Server.Implementations.Images { var subItem = i.Item2; - var episode = subItem as Episode; - - if (episode != null) + if (subItem is Episode episode) { var series = episode.Series; if (series != null && series.HasImage(ImageType.Primary)) diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs index 658c53f28..f8bae4fd1 100644 --- a/Emby.Server.Implementations/Library/MusicManager.cs +++ b/Emby.Server.Implementations/Library/MusicManager.cs @@ -100,8 +100,7 @@ namespace Emby.Server.Implementations.Library public List<BaseItem> GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions) { - var genre = item as MusicGenre; - if (genre != null) + if (item is MusicGenre genre) { return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions); } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 9c0e92705..61dccaa19 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -348,9 +348,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { var trigger = (ITaskTrigger)sender; - var configurableTask = ScheduledTask as IConfigurableScheduledTask; - - if (configurableTask != null && !configurableTask.IsEnabled) + if (ScheduledTask is IConfigurableScheduledTask configurableTask && !configurableTask.IsEnabled) { return; } diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index d3f6fa34d..829df64bf 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -43,9 +43,7 @@ namespace Emby.Server.Implementations.TV string presentationUniqueKey = null; if (!string.IsNullOrEmpty(request.SeriesId)) { - var series = _libraryManager.GetItemById(request.SeriesId) as Series; - - if (series != null) + if (_libraryManager.GetItemById(request.SeriesId) is Series series) { presentationUniqueKey = GetUniqueSeriesKey(series); } @@ -95,9 +93,7 @@ namespace Emby.Server.Implementations.TV int? limit = null; if (!string.IsNullOrEmpty(request.SeriesId)) { - var series = _libraryManager.GetItemById(request.SeriesId) as Series; - - if (series != null) + if (_libraryManager.GetItemById(request.SeriesId) is Series series) { presentationUniqueKey = GetUniqueSeriesKey(series); limit = 1; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 16a2c77e9..347d5b73c 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -354,9 +354,7 @@ namespace MediaBrowser.Controller.Entities if (result.Count == 0) { - var folder = LibraryManager.FindByPath(path, true) as Folder; - - if (folder != null) + if (LibraryManager.FindByPath(path, true) is Folder folder) { result.Add(folder); } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 05e4229ca..507f400f1 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -217,8 +217,7 @@ namespace MediaBrowser.Controller.Entities.Movies private IEnumerable<BaseItem> FlattenItems(BaseItem item, List<Guid> expandedFolders) { - var boxset = item as BoxSet; - if (boxset != null) + if (item is BoxSet boxset) { if (!expandedFolders.Contains(item.Id)) { diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index 2fc66176f..0f82f742f 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -24,8 +24,7 @@ namespace MediaBrowser.Controller.Entities var parents = GetParents(); foreach (var parent in parents) { - var photoAlbum = parent as PhotoAlbum; - if (photoAlbum != null) + if (parent is PhotoAlbum photoAlbum) { return photoAlbum; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 9f9a2ad50..06a405121 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -316,20 +316,13 @@ namespace MediaBrowser.Controller.Entities.TV cancellationToken.ThrowIfCancellationRequested(); - var skipItem = false; - - var episode = item as Episode; - - if (episode != null + bool skipItem = item is Episode episode && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh && !refreshOptions.ReplaceAllMetadata && episode.IsMissingEpisode && episode.LocationType == LocationType.Virtual && episode.PremiereDate.HasValue - && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) - { - skipItem = true; - } + && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30; if (!skipItem) { diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs index b50def043..3a97127ea 100644 --- a/MediaBrowser.Controller/Providers/ItemInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -14,8 +14,7 @@ namespace MediaBrowser.Controller.Providers ContainingFolderPath = item.ContainingFolderPath; IsInMixedFolder = item.IsInMixedFolder; - var video = item as Video; - if (video != null) + if (item is Video video) { VideoType = video.VideoType; IsPlaceHolder = video.IsPlaceHolder; diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 5f620634f..32e5ac761 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -468,8 +468,7 @@ namespace MediaBrowser.LocalMetadata.Parsers { var val = reader.ReadElementContentAsString(); - var hasDisplayOrder = item as IHasDisplayOrder; - if (hasDisplayOrder != null) + if (item is IHasDisplayOrder hasDisplayOrder) { if (!string.IsNullOrWhiteSpace(val)) { diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index dfbce5f49..98ed3dcf7 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -296,8 +296,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteEndElement(); } - var hasDisplayOrder = item as IHasDisplayOrder; - if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) + if (item is IHasDisplayOrder hasDisplayOrder && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) { writer.WriteElementString("DisplayOrder", hasDisplayOrder.DisplayOrder); } @@ -312,8 +311,7 @@ namespace MediaBrowser.LocalMetadata.Savers writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture)); } - var hasAspectRatio = item as IHasAspectRatio; - if (hasAspectRatio != null) + if (item is IHasAspectRatio hasAspectRatio) { if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio)) { diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index 9108d9649..6ebaa4fff 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -61,33 +61,25 @@ namespace MediaBrowser.MediaEncoding.BdInfo foreach (var stream in playlist.SortedStreams) { - var videoStream = stream as TSVideoStream; - - if (videoStream != null) + if (stream is TSVideoStream videoStream) { AddVideoStream(mediaStreams, videoStream); continue; } - var audioStream = stream as TSAudioStream; - - if (audioStream != null) + if (stream is TSAudioStream audioStream) { AddAudioStream(mediaStreams, audioStream); continue; } - var textStream = stream as TSTextStream; - - if (textStream != null) + if (stream is TSTextStream textStream) { AddSubtitleStream(mediaStreams, textStream); continue; } - var graphicsStream = stream as TSGraphicsStream; - - if (graphicsStream != null) + if (stream is TSGraphicsStream graphicsStream) { AddSubtitleStream(mediaStreams, graphicsStream); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 6b778a090..401c7e99f 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -281,8 +281,7 @@ namespace MediaBrowser.Providers.Manager return true; } - var folder = item as Folder; - if (folder != null) + if (item is Folder folder) { return folder.SupportsDateLastMediaAdded || folder.SupportsCumulativeRunTimeTicks; } @@ -336,8 +335,7 @@ namespace MediaBrowser.Providers.Manager private ItemUpdateType UpdateCumulativeRunTimeTicks(TItemType item, IList<BaseItem> children) { - var folder = item as Folder; - if (folder != null && folder.SupportsCumulativeRunTimeTicks) + if (item is Folder folder && folder.SupportsCumulativeRunTimeTicks) { long ticks = 0; diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 64ad1bddf..03e45fb86 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -137,9 +137,7 @@ namespace MediaBrowser.Providers.MediaInfo return false; } - var audio = item as Audio; - - return audio != null; + return item is Audio; } } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 912aedb0d..44ab5aa5b 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -172,9 +172,7 @@ namespace MediaBrowser.Providers.MediaInfo SubtitleFetcherOrder = subtitleFetcherOrder }; - var episode = video as Episode; - - if (episode != null) + if (video is Episode episode) { request.IndexNumberEnd = episode.IndexNumberEnd; request.SeriesName = episode.SeriesName; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index c36c3af6a..30af6710a 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -154,9 +154,7 @@ namespace MediaBrowser.Providers.MediaInfo return false; } - var video = item as Video; - - if (video != null && !video.IsPlaceHolder && video.IsCompleteMedia) + if (item is Video video && !video.IsPlaceHolder && video.IsCompleteMedia) { return true; } -- cgit v1.2.3 From 2e98de90628e9a4e42fb182f2d5a2a296acfd827 Mon Sep 17 00:00:00 2001 From: BaronGreenback <jimcartlidge@yahoo.co.uk> Date: Wed, 5 May 2021 12:51:14 +0100 Subject: Code Clean up: Convert to null-coalescing operator ?? (#5845) Co-authored-by: Cody Robibero <cody@robibe.ro> Co-authored-by: Patrick Barron <18354464+barronpm@users.noreply.github.com> --- Emby.Server.Implementations/ApplicationHost.cs | 10 +---- Emby.Server.Implementations/Dto/DtoService.cs | 15 ++------ .../Library/LibraryManager.cs | 5 +-- .../Library/Resolvers/TV/EpisodeResolver.cs | 14 ++----- .../LiveTv/EmbyTV/EmbyTV.cs | 10 ++--- .../LiveTv/Listings/SchedulesDirect.cs | 7 +--- .../LiveTv/LiveTvManager.cs | 15 ++------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 5 +-- .../Plugins/PluginManager.cs | 13 +------ .../ScheduledTasks/ScheduledTaskWorker.cs | 7 +--- .../Session/SessionManager.cs | 5 +-- Jellyfin.Api/Controllers/PluginsController.cs | 7 +--- Jellyfin.Api/Controllers/SearchController.cs | 5 +-- Jellyfin.Api/Helpers/StreamingHelpers.cs | 5 +-- MediaBrowser.Common/Net/IPHost.cs | 5 +-- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 5 +-- MediaBrowser.Controller/Entities/BaseItem.cs | 26 ++++--------- MediaBrowser.Controller/Entities/UserView.cs | 5 +-- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 5 +-- MediaBrowser.Controller/Playlists/Playlist.cs | 5 +-- .../Providers/MetadataRefreshOptions.cs | 5 +-- .../Providers/MetadataResult.cs | 16 +++----- .../Probing/ProbeResultNormalizer.cs | 45 ++++++---------------- .../Entities/ProviderIdsExtensions.cs | 5 +-- .../MediaInfo/FFProbeVideoInfo.cs | 5 +-- .../Subtitles/SubtitleManager.cs | 5 +-- RSSDP/SsdpCommunicationsServer.cs | 5 +-- 27 files changed, 60 insertions(+), 200 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 703f8d20d..75d8fc113 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -335,10 +335,7 @@ namespace Emby.Server.Implementations { get { - if (_deviceId == null) - { - _deviceId = new DeviceId(ApplicationPaths, LoggerFactory); - } + _deviceId ??= new DeviceId(ApplicationPaths, LoggerFactory); return _deviceId.Value; } @@ -370,10 +367,7 @@ namespace Emby.Server.Implementations /// <returns>System.Object.</returns> protected object CreateInstanceSafe(Type type) { - if (_creatingInstances == null) - { - _creatingInstances = new List<Type>(); - } + _creatingInstances ??= new List<Type>(); if (_creatingInstances.IndexOf(type) != -1) { diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 54b18a8c8..4ae35039a 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -665,10 +665,7 @@ namespace Emby.Server.Implementations.Dto var tag = GetImageCacheTag(item, image); if (!string.IsNullOrEmpty(image.BlurHash)) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>(); - } + dto.ImageBlurHashes ??= new Dictionary<ImageType, Dictionary<string, string>>(); if (!dto.ImageBlurHashes.ContainsKey(image.Type)) { @@ -702,10 +699,7 @@ namespace Emby.Server.Implementations.Dto if (hashes.Count > 0) { - if (dto.ImageBlurHashes == null) - { - dto.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>(); - } + dto.ImageBlurHashes ??= new Dictionary<ImageType, Dictionary<string, string>>(); dto.ImageBlurHashes[imageType] = hashes; } @@ -898,10 +892,7 @@ namespace Emby.Server.Implementations.Dto dto.Taglines = new string[] { item.Tagline }; } - if (dto.Taglines == null) - { - dto.Taglines = Array.Empty<string>(); - } + dto.Taglines ??= Array.Empty<string>(); } dto.Type = item.GetBaseItemKind(); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a44edad16..4d207471a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -176,10 +176,7 @@ namespace Emby.Server.Implementations.Library { lock (_rootFolderSyncLock) { - if (_rootFolder == null) - { - _rootFolder = CreateRootFolder(); - } + _rootFolder ??= CreateRootFolder(); } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 9b4cd7a3d..6f29bc649 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -35,14 +35,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - var season = parent as Season; - // Just in case the user decided to nest episodes. // Not officially supported but in some cases we can handle it. - if (season == null) - { - season = parent.GetParents().OfType<Season>().FirstOrDefault(); - } + + var season = parent as Season ?? parent.GetParents().OfType<Season>().FirstOrDefault(); // If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something // Also handle flat tv folders @@ -55,11 +51,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if (episode != null) { - var series = parent as Series; - if (series == null) - { - series = parent.GetParents().OfType<Series>().FirstOrDefault(); - } + var series = parent as Series ?? parent.GetParents().OfType<Series>().FirstOrDefault(); if (series != null) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 665fbfa0f..28a2095e1 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2237,14 +2237,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var enabledTimersForSeries = new List<TimerInfo>(); foreach (var timer in allTimers) { - var existingTimer = _timerProvider.GetTimer(timer.Id); - - if (existingTimer == null) - { - existingTimer = string.IsNullOrWhiteSpace(timer.ProgramId) + var existingTimer = _timerProvider.GetTimer(timer.Id) + ?? (string.IsNullOrWhiteSpace(timer.ProgramId) ? null - : _timerProvider.GetTimerByProgramId(timer.ProgramId); - } + : _timerProvider.GetTimerByProgramId(timer.ProgramId)); if (existingTimer == null) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1926e738f..9af65cabb 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -787,14 +787,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)); - if (station == null) - { - station = new ScheduleDirect.Station + var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) + ?? new ScheduleDirect.Station { stationID = channel.stationID }; - } var channelInfo = new ChannelInfo { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 63a3146aa..1145d8aa1 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -987,10 +987,7 @@ namespace Emby.Server.Implementations.LiveTv var externalProgramId = programTuple.Item2; string externalSeriesId = programTuple.Item3; - if (timerList == null) - { - timerList = (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + timerList ??= (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, externalProgramId, StringComparison.OrdinalIgnoreCase)); var foundSeriesTimer = false; @@ -1018,10 +1015,7 @@ namespace Emby.Server.Implementations.LiveTv continue; } - if (seriesTimerList == null) - { - seriesTimerList = (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; - } + seriesTimerList ??= (await GetSeriesTimersInternal(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false)).Items; var seriesTimer = seriesTimerList.FirstOrDefault(i => string.Equals(i.SeriesId, externalSeriesId, StringComparison.OrdinalIgnoreCase)); @@ -1974,10 +1968,7 @@ namespace Emby.Server.Implementations.LiveTv }; } - if (service == null) - { - service = _services[0]; - } + service ??= _services[0]; var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c32ca2fb6..4aa5832b1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -421,10 +421,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun string audioCodec = channelInfo.AudioCodec; - if (!videoBitrate.HasValue) - { - videoBitrate = isHd ? 15000000 : 2000000; - } + videoBitrate ??= isHd ? 15000000 : 2000000; int? audioBitrate = isHd ? 448000 : 192000; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index fd2ee6b7a..14df20936 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -44,12 +44,7 @@ namespace Emby.Server.Implementations.Plugins { get { - if (_httpClientFactory == null) - { - _httpClientFactory = _appHost.Resolve<IHttpClientFactory>(); - } - - return _httpClientFactory; + return _httpClientFactory ?? (_httpClientFactory = _appHost.Resolve<IHttpClientFactory>()); } } @@ -276,11 +271,7 @@ namespace Emby.Server.Implementations.Plugins // If no version is given, return the current instance. var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList(); - plugin = plugins.FirstOrDefault(p => p.Instance != null); - if (plugin == null) - { - plugin = plugins.OrderByDescending(p => p.Version).FirstOrDefault(); - } + plugin = plugins.FirstOrDefault(p => p.Instance != null) ?? plugins.OrderByDescending(p => p.Version).FirstOrDefault(); } else { diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 61dccaa19..101d9b537 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -301,12 +301,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { get { - if (_id == null) - { - _id = ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); - } - - return _id; + return _id ??= ScheduledTask.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture); } } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 6f21ec31e..6844152ea 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1475,10 +1475,7 @@ namespace Emby.Server.Implementations.Session user = _userManager.GetUserById(request.UserId); } - if (user == null) - { - user = _userManager.GetUserByName(request.Username); - } + user ??= _userManager.GetUserByName(request.Username); if (enforcePassword) { diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index adec86a10..7a6130719 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -207,12 +207,7 @@ namespace Jellyfin.Api.Controllers var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)); // Select the un-instanced one first. - var plugin = plugins.FirstOrDefault(p => p.Instance == null); - if (plugin == null) - { - // Then by the status. - plugin = plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); - } + var plugin = plugins.FirstOrDefault(p => p.Instance == null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault(); if (plugin != null) { diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 6c22050a7..73bdf9018 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -228,10 +228,7 @@ namespace Jellyfin.Api.Controllers itemWithImage = GetParentWithImage<Series>(item, ImageType.Thumb); } - if (itemWithImage == null) - { - itemWithImage = GetParentWithImage<BaseItem>(item, ImageType.Thumb); - } + itemWithImage ??= GetParentWithImage<BaseItem>(item, ImageType.Thumb); if (itemWithImage != null) { diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 583e613b4..8cffe9c4c 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -292,10 +292,7 @@ namespace Jellyfin.Api.Helpers } } - if (profile == null) - { - profile = dlnaManager.GetDefaultProfile(); - } + profile ??= dlnaManager.GetDefaultProfile(); var audioCodec = state.ActualOutputAudioCodec; diff --git a/MediaBrowser.Common/Net/IPHost.cs b/MediaBrowser.Common/Net/IPHost.cs index fb3ef9b12..7156ce618 100644 --- a/MediaBrowser.Common/Net/IPHost.cs +++ b/MediaBrowser.Common/Net/IPHost.cs @@ -400,10 +400,7 @@ namespace MediaBrowser.Common.Net private bool ResolveHost() { // When was the last time we resolved? - if (_lastResolved == null) - { - _lastResolved = DateTime.UtcNow; - } + _lastResolved ??= DateTime.UtcNow; // If we haven't resolved before, or our timer has run out... if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index 99c226f50..e074cc6a0 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -105,10 +105,7 @@ namespace MediaBrowser.Common.Plugins { lock (_configurationSyncLock) { - if (_configuration == null) - { - _configuration = LoadConfiguration(); - } + _configuration ??= LoadConfiguration(); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1b69c6646..32ae15498 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -106,15 +106,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeSongIds == null) - { - _themeSongIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) - .Select(song => song.Id) - .ToArray(); - } - - return _themeSongIds; + return _themeSongIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) + .Select(song => song.Id) + .ToArray(); } private set @@ -128,15 +123,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (_themeVideoIds == null) - { - _themeVideoIds = GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) - .Select(song => song.Id) - .ToArray(); - } - - return _themeVideoIds; + return _themeVideoIds ??= GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) + .Select(song => song.Id) + .ToArray(); } private set diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index b1da4d64c..fec83dd94 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -75,10 +75,7 @@ namespace MediaBrowser.Controller.Entities public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.EnableTotalRecordCount = false; var result = GetItemList(query); diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index f86f7df25..f9086066d 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -147,10 +147,7 @@ namespace MediaBrowser.Controller.Library throw new ArgumentException("The path was empty or null.", nameof(path)); } - if (AdditionalLocations == null) - { - AdditionalLocations = new List<string>(); - } + AdditionalLocations ??= new List<string>(); AdditionalLocations.Add(path); } diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index c9c168c4c..3c93cfc79 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -126,10 +126,7 @@ namespace MediaBrowser.Controller.Playlists private List<BaseItem> GetPlayableItems(User user, InternalItemsQuery query) { - if (query == null) - { - query = new InternalItemsQuery(user); - } + query ??= new InternalItemsQuery(user); query.IsFolder = false; diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index b92b83701..db0ef7072 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -45,10 +45,7 @@ namespace MediaBrowser.Controller.Providers if (copy.RefreshPaths != null && copy.RefreshPaths.Length > 0) { - if (RefreshPaths == null) - { - RefreshPaths = Array.Empty<string>(); - } + RefreshPaths ??= Array.Empty<string>(); RefreshPaths = copy.RefreshPaths.ToArray(); } diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 864cb3050..98c7eadfe 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -37,10 +37,7 @@ namespace MediaBrowser.Controller.Providers public void AddPerson(PersonInfo p) { - if (People == null) - { - People = new List<PersonInfo>(); - } + People ??= new List<PersonInfo>(); PeopleHelper.AddPerson(People, p); } @@ -54,16 +51,15 @@ namespace MediaBrowser.Controller.Providers { People = new List<PersonInfo>(); } - - People.Clear(); + else + { + People.Clear(); + } } public UserItemData GetOrAddUserData(string userId) { - if (UserDataList == null) - { - UserDataList = new List<UserItemData>(); - } + UserDataList ??= new List<UserItemData>(); UserItemData userData = null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ee2e5fcde..2e96f8cb0 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1187,43 +1187,28 @@ namespace MediaBrowser.MediaEncoding.Probing FetchStudios(audio, tags, "label"); // These support mulitple values, but for now we only store the first. - var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - } + var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")); - if (mb == null) - { - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - } + mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) + ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } @@ -1290,15 +1275,7 @@ namespace MediaBrowser.MediaEncoding.Probing private IEnumerable<string> GetSplitWhitelist() { - if (_splitWhiteList == null) - { - _splitWhiteList = new List<string> - { - "AC/DC" - }; - } - - return _splitWhiteList; + return _splitWhiteList ??= new List<string> { "AC/DC" }; } /// <summary> diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 09d14dc6a..ce4b0ec92 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -123,10 +123,7 @@ namespace MediaBrowser.Model.Entities else { // Ensure it exists - if (instance.ProviderIds == null) - { - instance.ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } + instance.ProviderIds ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); instance.ProviderIds[name] = value; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 74849a522..f049cc81f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -111,10 +111,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - if (streamFileNames == null) - { - streamFileNames = Array.Empty<string>(); - } + streamFileNames ??= Array.Empty<string>(); mediaInfoResult = await GetMediaInfo(item, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 1f3d9acff..8d62343cb 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -256,10 +256,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - if (exceptionToThrow == null) - { - exceptionToThrow = ex; - } + exceptionToThrow ??= ex; } finally { diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index 8f1f0fa61..f448ad38b 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -415,10 +415,7 @@ namespace Rssdp.Infrastructure { lock (_SendSocketSynchroniser) { - if (_sendSockets == null) - { - _sendSockets = CreateSocketAndListenForResponsesAsync(); - } + _sendSockets ??= CreateSocketAndListenForResponsesAsync(); } } } -- cgit v1.2.3 From e432796f6f0f500830b1c90c233c4e4c07287190 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Wed, 5 May 2021 14:39:50 +0200 Subject: Minor improvements --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 11 ++++------- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 12 ++++++------ 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 2e96f8cb0..884ec0a29 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly ILogger _logger; private readonly ILocalizationManager _localization; - private List<string> _splitWhiteList = null; + private string[] _splitWhiteList; public ProbeResultNormalizer(ILogger logger, ILocalizationManager localization) { @@ -37,6 +37,8 @@ namespace MediaBrowser.MediaEncoding.Probing _localization = localization; } + private IReadOnlyList<string> SplitWhitelist => _splitWhiteList ??= new string[] { "AC/DC" }; + public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) { var info = new MediaInfo @@ -1254,7 +1256,7 @@ namespace MediaBrowser.MediaEncoding.Probing var artistsFound = new List<string>(); - foreach (var whitelistArtist in GetSplitWhitelist()) + foreach (var whitelistArtist in SplitWhitelist) { var originalVal = val; val = val.Replace(whitelistArtist, "|", StringComparison.OrdinalIgnoreCase); @@ -1273,11 +1275,6 @@ namespace MediaBrowser.MediaEncoding.Probing return artistsFound; } - private IEnumerable<string> GetSplitWhitelist() - { - return _splitWhiteList ??= new List<string> { "AC/DC" }; - } - /// <summary> /// Gets the studios from the tags collection. /// </summary> diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 8d62343cb..bf0c853ae 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -207,7 +207,7 @@ namespace MediaBrowser.Providers.Subtitles { var mediaFolderPath = Path.GetFullPath(Path.Combine(video.ContainingFolderPath, saveFileName)); // TODO: Add some error handling to the API user: return BadRequest("Could not save subtitle, bad path."); - if (mediaFolderPath.StartsWith(video.ContainingFolderPath)) + if (mediaFolderPath.StartsWith(video.ContainingFolderPath, StringComparison.Ordinal)) { savePaths.Add(mediaFolderPath); } @@ -216,7 +216,7 @@ namespace MediaBrowser.Providers.Subtitles var internalPath = Path.GetFullPath(Path.Combine(video.GetInternalMetadataPath(), saveFileName)); // TODO: Add some error to the user: return BadRequest("Could not save subtitle, bad path."); - if (internalPath.StartsWith(video.GetInternalMetadataPath())) + if (internalPath.StartsWith(video.GetInternalMetadataPath(), StringComparison.Ordinal)) { savePaths.Add(internalPath); } @@ -234,7 +234,7 @@ namespace MediaBrowser.Providers.Subtitles private async Task TrySaveToFiles(Stream stream, List<string> savePaths) { - Exception exceptionToThrow = null; + List<Exception> exs = null; foreach (var savePath in savePaths) { @@ -256,7 +256,7 @@ namespace MediaBrowser.Providers.Subtitles } catch (Exception ex) { - exceptionToThrow ??= ex; + (exs ??= new List<Exception>()).Add(ex); } finally { @@ -266,9 +266,9 @@ namespace MediaBrowser.Providers.Subtitles stream.Position = 0; } - if (exceptionToThrow != null) + if (exs != null) { - throw exceptionToThrow; + throw new AggregateException(exs); } } -- cgit v1.2.3 From 26d7fc828075dbaa3068ac9c323ebef3370fd023 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Thu, 20 May 2021 22:10:19 +0200 Subject: Enable nullable reference types for MediaBrowser.MediaEncoding.Subtitles --- .../Attachments/AttachmentExtractor.cs | 1 + .../BdInfo/BdInfoDirectoryInfo.cs | 6 +- .../BdInfo/BdInfoFileInfo.cs | 2 +- .../Encoder/EncoderValidator.cs | 15 +++-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + .../MediaBrowser.MediaEncoding.csproj | 1 + .../Probing/FFProbeHelpers.cs | 2 + .../Probing/InternalMediaInfoResult.cs | 2 + MediaBrowser.MediaEncoding/Probing/MediaChapter.cs | 1 + .../Probing/MediaFormatInfo.cs | 2 + .../Probing/MediaStreamInfo.cs | 2 + .../Probing/ProbeResultNormalizer.cs | 1 + MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 2 - .../Subtitles/ParserValues.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs | 2 - MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs | 2 - .../Subtitles/SubtitleEditParser.cs | 2 - .../Subtitles/SubtitleEncoder.cs | 66 ++++++++++++---------- 18 files changed, 62 insertions(+), 49 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index e8aeabf9d..a0ec3bd90 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System; diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index ef9943722..e86e518be 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -9,9 +9,9 @@ namespace MediaBrowser.MediaEncoding.BdInfo { public class BdInfoDirectoryInfo : IDirectoryInfo { - private readonly IFileSystem _fileSystem = null; + private readonly IFileSystem _fileSystem; - private readonly FileSystemMetadata _impl = null; + private readonly FileSystemMetadata _impl; public BdInfoDirectoryInfo(IFileSystem fileSystem, string path) { @@ -29,7 +29,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo public string FullName => _impl.FullName; - public IDirectoryInfo Parent + public IDirectoryInfo? Parent { get { diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs index 0a8af8e9c..41143c259 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo { public class BdInfoFileInfo : BDInfo.IO.IFileInfo { - private FileSystemMetadata _impl = null; + private FileSystemMetadata _impl; public BdInfoFileInfo(FileSystemMetadata impl) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 9e2417603..f782e65bd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -121,11 +121,11 @@ namespace MediaBrowser.MediaEncoding.Encoder // When changing this, also change the minimum library versions in _ffmpegMinimumLibraryVersions public static Version MinVersion { get; } = new Version(4, 0); - public static Version MaxVersion { get; } = null; + public static Version? MaxVersion { get; } = null; public bool ValidateVersion() { - string output = null; + string output; try { output = GetProcessOutput(_encoderPath, "-version"); @@ -133,6 +133,7 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (Exception ex) { _logger.LogError(ex, "Error validating encoder"); + return false; } if (string.IsNullOrWhiteSpace(output)) @@ -207,7 +208,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// </summary> /// <param name="output">The output from "ffmpeg -version".</param> /// <returns>The FFmpeg version.</returns> - internal Version GetFFmpegVersion(string output) + internal Version? GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output var match = Regex.Match(output, @"^ffmpeg version n?((?:[0-9]+\.?)+)"); @@ -275,7 +276,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private IEnumerable<string> GetHwaccelTypes() { - string output = null; + string? output = null; try { output = GetProcessOutput(_encoderPath, "-hwaccels"); @@ -303,7 +304,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - string output = null; + string output; try { output = GetProcessOutput(_encoderPath, "-h filter=" + filter); @@ -311,6 +312,7 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (Exception ex) { _logger.LogError(ex, "Error detecting the given filter"); + return false; } if (output.Contains("Filter " + filter, StringComparison.Ordinal)) @@ -331,7 +333,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private IEnumerable<string> GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; - string output = null; + string output; try { output = GetProcessOutput(_encoderPath, "-" + codecstr); @@ -339,6 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder catch (Exception ex) { _logger.LogError(ex, "Error detecting available {Codec}", codecstr); + return Enumerable.Empty<string>(); } if (string.IsNullOrWhiteSpace(output)) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62c0c0bb1..cdb778bf2 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System; diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 39fb0b47c..7733e715f 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -10,6 +10,7 @@ <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index da37687e8..1fa90bb21 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs index 0e319c1a8..d4d153b08 100644 --- a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs +++ b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs @@ -1,3 +1,5 @@ +#nullable disable + using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs index de062d06b..a1cef7a9f 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System.Collections.Generic; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs index 8af122ef9..d50da37b8 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaFormatInfo.cs @@ -1,3 +1,5 @@ +#nullable disable + using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 7b7744163..c9c8c34c2 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -1,3 +1,5 @@ +#nullable disable + using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 884ec0a29..2ec9dc346 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1,3 +1,4 @@ +#nullable disable #pragma warning disable CS1591 using System; diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 8219aa7b4..08ee5c72e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,5 +1,3 @@ -#nullable enable - using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; diff --git a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs index dca5c1e8a..cec1aaf08 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs @@ -1,4 +1,3 @@ -#nullable enable #pragma warning disable CS1591 namespace MediaBrowser.MediaEncoding.Subtitles diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs index 19fb951dc..78d54ca51 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -1,5 +1,3 @@ -#nullable enable - using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index 36dc2e01f..17c2ae40e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -1,5 +1,3 @@ -#nullable enable - using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.SubtitleFormats; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 82ec6ca21..639a34d99 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -1,5 +1,3 @@ -#nullable enable - using System.Globalization; using System.IO; using System.Linq; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 39bec8da1..608ebf443 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -71,8 +72,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - var reader = GetReader(inputFormat, true); - + var reader = GetReader(inputFormat); var trackInfo = reader.Parse(stream, cancellationToken); FilterEvents(trackInfo, startTimeTicks, endTimeTicks, preserveOriginalTimestamps); @@ -139,10 +139,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles .ConfigureAwait(false); var inputFormat = subtitle.format; - var writer = TryGetWriter(outputFormat); // Return the original if we don't have any way of converting it - if (writer == null) + if (!TryGetWriter(outputFormat, out var writer)) { return subtitle.stream; } @@ -239,7 +238,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec) .TrimStart('.'); - if (GetReader(currentFormat, false) == null) + if (TryGetReader(currentFormat, out _)) { // Convert var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, ".srt"); @@ -257,37 +256,41 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new SubtitleInfo(subtitleStream.Path, mediaSource.Protocol, currentFormat, true); } - private ISubtitleParser GetReader(string format, bool throwIfMissing) + private bool TryGetReader(string format, [NotNullWhen(true)] out ISubtitleParser? value) { - if (string.IsNullOrEmpty(format)) - { - throw new ArgumentNullException(nameof(format)); - } - if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { - return new SrtParser(_logger); + value = new SrtParser(_logger); + return true; } if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase)) { - return new SsaParser(_logger); + value = new SsaParser(_logger); + return true; } if (string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase)) { - return new AssParser(_logger); + value = new AssParser(_logger); + return true; } - if (throwIfMissing) + value = null; + return false; + } + + private ISubtitleParser GetReader(string format) + { + if (TryGetReader(format, out var reader)) { - throw new ArgumentException("Unsupported format: " + format); + return reader; } - return null; + throw new ArgumentException("Unsupported format: " + format); } - private ISubtitleWriter TryGetWriter(string format) + private bool TryGetWriter(string format, [NotNullWhen(true)] out ISubtitleWriter? value) { if (string.IsNullOrEmpty(format)) { @@ -296,32 +299,35 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase)) { - return new JsonWriter(); + value = new JsonWriter(); + return true; } if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { - return new SrtWriter(); + value = new SrtWriter(); + return true; } if (string.Equals(format, SubtitleFormat.VTT, StringComparison.OrdinalIgnoreCase)) { - return new VttWriter(); + value = new VttWriter(); + return true; } if (string.Equals(format, SubtitleFormat.TTML, StringComparison.OrdinalIgnoreCase)) { - return new TtmlWriter(); + value = new TtmlWriter(); + return true; } - return null; + value = null; + return false; } private ISubtitleWriter GetWriter(string format) { - var writer = TryGetWriter(format); - - if (writer != null) + if (TryGetWriter(format, out var writer)) { return writer; } @@ -391,7 +397,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(outputPath)); } - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath))); var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, mediaSource.Protocol, cancellationToken).ConfigureAwait(false); @@ -549,7 +555,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException(nameof(outputPath)); } - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath))); var processArgs = string.Format( CultureInfo.InvariantCulture, @@ -715,7 +721,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) { - var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName; + var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName ?? string.Empty; // UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding if ((path.EndsWith(".ass", StringComparison.Ordinal) || path.EndsWith(".ssa", StringComparison.Ordinal) || path.EndsWith(".srt", StringComparison.Ordinal)) @@ -725,7 +731,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles charset = string.Empty; } - _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); + _logger.LogDebug("charset {0} detected for {Path}", charset, path); return charset; } -- cgit v1.2.3 From 0bc06014427e36a770adeda66392d08147658ea8 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 28 May 2021 14:33:54 +0200 Subject: Fix some warnings --- .../AppBase/BaseConfigurationManager.cs | 10 +-- .../AppBase/ConfigurationHelper.cs | 3 +- .../EntryPoints/UdpServerEntryPoint.cs | 4 +- .../EntryPoints/UserDataChangeNotifier.cs | 10 ++- .../LiveTv/EmbyTV/RecordingHelper.cs | 2 - .../LiveTv/LiveTvConfigurationFactory.cs | 10 +-- .../LiveTv/LiveTvManager.cs | 8 +-- .../LiveTv/RefreshChannelsScheduledTask.cs | 63 ------------------ .../LiveTv/RefreshGuideScheduledTask.cs | 75 ++++++++++++++++++++++ .../LiveTv/TunerHosts/BaseTunerHost.cs | 1 + .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 - .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 6 +- .../LiveTv/TunerHosts/M3UTunerHost.cs | 20 +++--- .../LiveTv/TunerHosts/M3uParser.cs | 8 +-- .../LiveTv/TunerHosts/SharedHttpStream.cs | 4 +- .../Plugins/PluginManager.cs | 3 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 21 ++---- .../ScheduledTasks/Triggers/DailyTrigger.cs | 41 ++++++------ .../ScheduledTasks/Triggers/IntervalTrigger.cs | 40 ++++++------ .../ScheduledTasks/Triggers/StartupTrigger.cs | 28 ++++---- .../ScheduledTasks/Triggers/WeeklyTrigger.cs | 54 +++++++--------- .../Session/WebSocketController.cs | 1 - Emby.Server.Implementations/Udp/UdpServer.cs | 67 ++++++++++--------- .../Events/EventManager.cs | 7 +- MediaBrowser.Common/IApplicationHost.cs | 8 +-- .../Subtitles/ParserValues.cs | 9 --- MediaBrowser.Model/Tasks/ITaskTrigger.cs | 4 +- jellyfin.ruleset | 3 + 28 files changed, 247 insertions(+), 265 deletions(-) delete mode 100644 Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs create mode 100644 Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs delete mode 100644 MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 8c919db43..4c442a473 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -25,6 +25,11 @@ namespace Emby.Server.Implementations.AppBase private readonly ConcurrentDictionary<string, object> _configurations = new ConcurrentDictionary<string, object>(); + /// <summary> + /// The _configuration sync lock. + /// </summary> + private readonly object _configurationSyncLock = new object(); + private ConfigurationStore[] _configurationStores = Array.Empty<ConfigurationStore>(); private IConfigurationFactory[] _configurationFactories = Array.Empty<IConfigurationFactory>(); @@ -33,11 +38,6 @@ namespace Emby.Server.Implementations.AppBase /// </summary> private bool _configurationLoaded; - /// <summary> - /// The _configuration sync lock. - /// </summary> - private readonly object _configurationSyncLock = new object(); - /// <summary> /// The _configuration. /// </summary> diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index de770f59e..0308a68e4 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -33,7 +33,8 @@ namespace Emby.Server.Implementations.AppBase } catch (Exception) { - configuration = Activator.CreateInstance(type) ?? throw new ArgumentException($"Provided path ({type}) is not valid.", nameof(type)); + // Note: CreateInstance returns null for Nullable<T>, e.g. CreateInstance(typeof(int?)) returns null. + configuration = Activator.CreateInstance(type)!; } using var stream = new MemoryStream(buffer?.Length ?? 0); diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 211941f44..2e72b18f5 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -54,8 +54,8 @@ namespace Emby.Server.Implementations.EntryPoints try { - _udpServer = new UdpServer(_logger, _appHost, _config); - _udpServer.Start(PortNumber, _cancellationTokenSource.Token); + _udpServer = new UdpServer(_logger, _appHost, _config, PortNumber); + _udpServer.Start(_cancellationTokenSource.Token); } catch (SocketException ex) { diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 332fb3385..d3bcd5e13 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -28,7 +26,7 @@ namespace Emby.Server.Implementations.EntryPoints private readonly Dictionary<Guid, List<BaseItem>> _changedItems = new Dictionary<Guid, List<BaseItem>>(); private readonly object _syncLock = new object(); - private Timer _updateTimer; + private Timer? _updateTimer; public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IUserManager userManager) { @@ -44,7 +42,7 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - void OnUserDataManagerUserDataSaved(object sender, UserDataSaveEventArgs e) + private void OnUserDataManagerUserDataSaved(object? sender, UserDataSaveEventArgs e) { if (e.SaveReason == UserDataSaveReason.PlaybackProgress) { @@ -66,7 +64,7 @@ namespace Emby.Server.Implementations.EntryPoints _updateTimer.Change(UpdateDuration, Timeout.Infinite); } - if (!_changedItems.TryGetValue(e.UserId, out List<BaseItem> keys)) + if (!_changedItems.TryGetValue(e.UserId, out List<BaseItem>? keys)) { keys = new List<BaseItem>(); _changedItems[e.UserId] = keys; @@ -89,7 +87,7 @@ namespace Emby.Server.Implementations.EntryPoints } } - private void UpdateTimerCallback(object state) + private void UpdateTimerCallback(object? state) { lock (_syncLock) { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 108863869..32245f899 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs index ba916af38..098f193fb 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs @@ -1,21 +1,23 @@ -#pragma warning disable CS1591 - using System.Collections.Generic; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.LiveTv; namespace Emby.Server.Implementations.LiveTv { + /// <summary> + /// <see cref="IConfigurationFactory" /> implementation for <see cref="LiveTvOptions" />. + /// </summary> public class LiveTvConfigurationFactory : IConfigurationFactory { + /// <inheritdoc /> public IEnumerable<ConfigurationStore> GetConfigurations() { return new ConfigurationStore[] { new ConfigurationStore { - ConfigurationType = typeof(LiveTvOptions), - Key = "livetv" + ConfigurationType = typeof(LiveTvOptions), + Key = "livetv" } }; } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1f1628900..d964769b5 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2266,7 +2266,7 @@ namespace Emby.Server.Implementations.LiveTv if (dataSourceChanged) { - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); + _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); } return info; @@ -2309,7 +2309,7 @@ namespace Emby.Server.Implementations.LiveTv _config.SaveConfiguration("livetv", config); - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); + _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); return info; } @@ -2321,7 +2321,7 @@ namespace Emby.Server.Implementations.LiveTv config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToArray(); _config.SaveConfiguration("livetv", config); - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); + _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); } public async Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelId, string providerChannelId) @@ -2355,7 +2355,7 @@ namespace Emby.Server.Implementations.LiveTv var tunerChannelMappings = tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList(); - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); + _taskManager.CancelIfRunningAndQueue<RefreshGuideScheduledTask>(); return tunerChannelMappings.First(i => string.Equals(i.Id, tunerChannelId, StringComparison.OrdinalIgnoreCase)); } diff --git a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs deleted file mode 100644 index 582b64923..000000000 --- a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ /dev/null @@ -1,63 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Tasks; - -namespace Emby.Server.Implementations.LiveTv -{ - public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask - { - private readonly ILiveTvManager _liveTvManager; - private readonly IConfigurationManager _config; - - public RefreshChannelsScheduledTask(ILiveTvManager liveTvManager, IConfigurationManager config) - { - _liveTvManager = liveTvManager; - _config = config; - } - - public string Name => "Refresh Guide"; - - public string Description => "Downloads channel information from live tv services."; - - public string Category => "Live TV"; - - public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress) - { - var manager = (LiveTvManager)_liveTvManager; - - return manager.RefreshChannels(progress, cancellationToken); - } - - /// <summary> - /// Creates the triggers that define when the task will run. - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() - { - return new[] - { - // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks } - }; - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - public bool IsHidden => _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Length == 0; - - public bool IsEnabled => true; - - public bool IsLogged => true; - - public string Key => "RefreshGuide"; - } -} diff --git a/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs new file mode 100644 index 000000000..15df0dcf1 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Tasks; + +namespace Emby.Server.Implementations.LiveTv +{ + /// <summary> + /// The "Refresh Guide" scheduled task. + /// </summary> + public class RefreshGuideScheduledTask : IScheduledTask, IConfigurableScheduledTask + { + private readonly ILiveTvManager _liveTvManager; + private readonly IConfigurationManager _config; + + /// <summary> + /// Initializes a new instance of the <see cref="RefreshGuideScheduledTask"/> class. + /// </summary> + /// <param name="liveTvManager">The live tv manager.</param> + /// <param name="config">The configuration manager.</param> + public RefreshGuideScheduledTask(ILiveTvManager liveTvManager, IConfigurationManager config) + { + _liveTvManager = liveTvManager; + _config = config; + } + + /// <inheritdoc /> + public string Name => "Refresh Guide"; + + /// <inheritdoc /> + public string Description => "Downloads channel information from live tv services."; + + /// <inheritdoc /> + public string Category => "Live TV"; + + /// <inheritdoc /> + public bool IsHidden => _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Length == 0; + + /// <inheritdoc /> + public bool IsEnabled => true; + + /// <inheritdoc /> + public bool IsLogged => true; + + /// <inheritdoc /> + public string Key => "RefreshGuide"; + + /// <inheritdoc /> + public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) + { + var manager = (LiveTvManager)_liveTvManager; + + return manager.RefreshChannels(progress, cancellationToken); + } + + /// <inheritdoc /> + public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() + { + return new[] + { + // Every so often + new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks } + }; + } + + private LiveTvOptions GetConfiguration() + { + return _config.GetConfiguration<LiveTvOptions>("livetv"); + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 00a37bb02..5941613cf 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -40,6 +40,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public virtual bool IsSupported => true; protected abstract Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken); + public abstract string Type { get; } public async Task<List<ChannelInfo>> GetChannels(TunerHostInfo tuner, bool enableCache, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c5700db71..54de841fe 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -583,7 +583,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Logger, Config, _appHost, - _networkManager, _streamHelper); } @@ -624,7 +623,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Logger, Config, _appHost, - _networkManager, _streamHelper); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 50a2d9abb..58e0c7448 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -12,7 +12,6 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; @@ -30,7 +29,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IServerApplicationHost _appHost; private readonly IHdHomerunChannelCommands _channelCommands; private readonly int _numTuners; - private readonly INetworkManager _networkManager; public HdHomerunUdpStream( MediaSourceInfo mediaSource, @@ -42,12 +40,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun ILogger logger, IConfigurationManager configurationManager, IServerApplicationHost appHost, - INetworkManager networkManager, IStreamHelper streamHelper) : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper) { _appHost = appHost; - _networkManager = networkManager; OriginalStreamId = originalStreamId; _channelCommands = channelCommands; _numTuners = numTuners; @@ -128,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using (udpClient) using (hdHomerunManager) { - if (!(ex is OperationCanceledException)) + if (ex is not OperationCanceledException) { Logger.LogError(ex, "Error opening live stream:"); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 69035dac9..8fa6f5ad6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -29,6 +29,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost { + private static readonly string[] _disallowedSharedStreamExtensions = + { + ".mkv", + ".mp4", + ".m3u8", + ".mpd" + }; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; private readonly INetworkManager _networkManager; @@ -67,7 +75,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var channelIdPrefix = GetFullChannelIdPrefix(info); - return await new M3uParser(Logger, _httpClientFactory, _appHost) + return await new M3uParser(Logger, _httpClientFactory) .Parse(info, channelIdPrefix, cancellationToken) .ConfigureAwait(false); } @@ -88,14 +96,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.FromResult(list); } - private static readonly string[] _disallowedSharedStreamExtensions = - { - ".mkv", - ".mp4", - ".m3u8", - ".mpd" - }; - protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, ChannelInfo channelInfo, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken) { var tunerCount = info.TunerCount; @@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task Validate(TunerHostInfo info) { - using (var stream = await new M3uParser(Logger, _httpClientFactory, _appHost).GetListingsStream(info, CancellationToken.None).ConfigureAwait(false)) + using (var stream = await new M3uParser(Logger, _httpClientFactory).GetListingsStream(info, CancellationToken.None).ConfigureAwait(false)) { } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 48a0c3cd3..40a162890 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -21,15 +21,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class M3uParser { + private const string ExtInfPrefix = "#EXTINF:"; + private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; - private readonly IServerApplicationHost _appHost; - public M3uParser(ILogger logger, IHttpClientFactory httpClientFactory, IServerApplicationHost appHost) + public M3uParser(ILogger logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; - _appHost = appHost; } public async Task<List<ChannelInfo>> Parse(TunerHostInfo info, string channelIdPrefix, CancellationToken cancellationToken) @@ -61,8 +61,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return File.OpenRead(info.Url); } - private const string ExtInfPrefix = "#EXTINF:"; - private async Task<List<ChannelInfo>> GetChannelsAsync(TextReader reader, string channelIdPrefix, string tunerHostId) { var channels = new List<ChannelInfo>(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 137ed27e2..f572151b8 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -91,8 +91,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var taskCompletionSource = new TaskCompletionSource<bool>(); - var now = DateTime.UtcNow; - _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); // OpenedMediaSource.Protocol = MediaProtocol.File; @@ -120,7 +118,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!taskCompletionSource.Task.Result) { Logger.LogWarning("Zero bytes copied from stream {0} to {1} but no exception raised", GetType().Name, TempFilePath); - throw new EndOfStreamException(String.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name)); + throw new EndOfStreamException(string.Format(CultureInfo.InvariantCulture, "Zero bytes copied from stream {0}", GetType().Name)); } } diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 48281b75f..16a2bd615 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -455,7 +455,8 @@ namespace Emby.Server.Implementations.Plugins try { _logger.LogDebug("Creating instance of {Type}", type); - var instance = (IPlugin)ActivatorUtilities.CreateInstance(_appHost.ServiceProvider, type); + // _appHost.ServiceProvider is already assigned when we create the plugins + var instance = (IPlugin)ActivatorUtilities.CreateInstance(_appHost.ServiceProvider!, type); if (plugin == null) { // Create a dummy record for the providers. diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index ccbd4289e..d7e320754 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -711,11 +711,7 @@ namespace Emby.Server.Implementations.ScheduledTasks throw new ArgumentException("Info did not contain a TimeOfDayTicks.", nameof(info)); } - return new DailyTrigger - { - TimeOfDay = TimeSpan.FromTicks(info.TimeOfDayTicks.Value), - TaskOptions = options - }; + return new DailyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), options); } if (info.Type.Equals(nameof(WeeklyTrigger), StringComparison.OrdinalIgnoreCase)) @@ -730,12 +726,7 @@ namespace Emby.Server.Implementations.ScheduledTasks throw new ArgumentException("Info did not contain a DayOfWeek.", nameof(info)); } - return new WeeklyTrigger - { - TimeOfDay = TimeSpan.FromTicks(info.TimeOfDayTicks.Value), - DayOfWeek = info.DayOfWeek.Value, - TaskOptions = options - }; + return new WeeklyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), info.DayOfWeek.Value, options); } if (info.Type.Equals(nameof(IntervalTrigger), StringComparison.OrdinalIgnoreCase)) @@ -745,16 +736,12 @@ namespace Emby.Server.Implementations.ScheduledTasks throw new ArgumentException("Info did not contain a IntervalTicks.", nameof(info)); } - return new IntervalTrigger - { - Interval = TimeSpan.FromTicks(info.IntervalTicks.Value), - TaskOptions = options - }; + return new IntervalTrigger(TimeSpan.FromTicks(info.IntervalTicks.Value), options); } if (info.Type.Equals(nameof(StartupTrigger), StringComparison.OrdinalIgnoreCase)) { - return new StartupTrigger(); + return new StartupTrigger(options); } throw new ArgumentException("Unrecognized trigger type: " + info.Type); diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index 3b63536a4..29ab6a73d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Threading; using MediaBrowser.Model.Tasks; @@ -10,29 +8,31 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <summary> /// Represents a task trigger that fires everyday. /// </summary> - public class DailyTrigger : ITaskTrigger + public sealed class DailyTrigger : ITaskTrigger { - /// <summary> - /// Occurs when [triggered]. - /// </summary> - public event EventHandler<EventArgs> Triggered; + private readonly TimeSpan _timeOfDay; + private Timer? _timer; /// <summary> - /// Gets or sets the time of day to trigger the task to run. + /// Initializes a new instance of the <see cref="DailyTrigger"/> class. /// </summary> - /// <value>The time of day.</value> - public TimeSpan TimeOfDay { get; set; } + /// <param name="timeofDay">The time of day to trigger the task to run.</param> + /// <param name="taskOptions">The options of this task.</param> + public DailyTrigger(TimeSpan timeofDay, TaskOptions taskOptions) + { + _timeOfDay = timeofDay; + TaskOptions = taskOptions; + } /// <summary> - /// Gets or sets the options of this task. + /// Occurs when [triggered]. /// </summary> - public TaskOptions TaskOptions { get; set; } + public event EventHandler<EventArgs>? Triggered; /// <summary> - /// Gets or sets the timer. + /// Gets the options of this task. /// </summary> - /// <value>The timer.</value> - private Timer Timer { get; set; } + public TaskOptions TaskOptions { get; } /// <summary> /// Stars waiting for the trigger action. @@ -47,14 +47,14 @@ namespace Emby.Server.Implementations.ScheduledTasks var now = DateTime.Now; - var triggerDate = now.TimeOfDay > TimeOfDay ? now.Date.AddDays(1) : now.Date; - triggerDate = triggerDate.Add(TimeOfDay); + var triggerDate = now.TimeOfDay > _timeOfDay ? now.Date.AddDays(1) : now.Date; + triggerDate = triggerDate.Add(_timeOfDay); var dueTime = triggerDate - now; logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:yyyy-MM-dd HH:mm:ss.fff zzz}, which is {DueTime:c} from now.", taskName, triggerDate, dueTime); - Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1)); + _timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1)); } /// <summary> @@ -70,10 +70,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </summary> private void DisposeTimer() { - if (Timer != null) - { - Timer.Dispose(); - } + _timer?.Dispose(); } /// <summary> diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs index e13782fe0..30568e809 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Linq; using System.Threading; @@ -11,31 +9,32 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <summary> /// Represents a task trigger that runs repeatedly on an interval. /// </summary> - public class IntervalTrigger : ITaskTrigger + public sealed class IntervalTrigger : ITaskTrigger { + private readonly TimeSpan _interval; private DateTime _lastStartDate; + private Timer? _timer; /// <summary> - /// Occurs when [triggered]. - /// </summary> - public event EventHandler<EventArgs> Triggered; - - /// <summary> - /// Gets or sets the interval. + /// Initializes a new instance of the <see cref="IntervalTrigger"/> class. /// </summary> - /// <value>The interval.</value> - public TimeSpan Interval { get; set; } + /// <param name="interval">The interval.</param> + /// <param name="taskOptions">The options of this task.</param> + public IntervalTrigger(TimeSpan interval, TaskOptions taskOptions) + { + _interval = interval; + TaskOptions = taskOptions; + } /// <summary> - /// Gets or sets the options of this task. + /// Occurs when [triggered]. /// </summary> - public TaskOptions TaskOptions { get; set; } + public event EventHandler<EventArgs>? Triggered; /// <summary> - /// Gets or sets the timer. + /// Gets the options of this task. /// </summary> - /// <value>The timer.</value> - private Timer Timer { get; set; } + public TaskOptions TaskOptions { get; } /// <summary> /// Stars waiting for the trigger action. @@ -57,7 +56,7 @@ namespace Emby.Server.Implementations.ScheduledTasks } else { - triggerDate = new[] { lastResult.EndTimeUtc, _lastStartDate }.Max().Add(Interval); + triggerDate = new[] { lastResult.EndTimeUtc, _lastStartDate }.Max().Add(_interval); } if (DateTime.UtcNow > triggerDate) @@ -73,7 +72,7 @@ namespace Emby.Server.Implementations.ScheduledTasks dueTime = maxDueTime; } - Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1)); + _timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1)); } /// <summary> @@ -89,10 +88,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </summary> private void DisposeTimer() { - if (Timer != null) - { - Timer.Dispose(); - } + _timer?.Dispose(); } /// <summary> diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs index ced14195b..18b9a8b75 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System; @@ -12,24 +10,28 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <summary> /// Class StartupTaskTrigger. /// </summary> - public class StartupTrigger : ITaskTrigger + public sealed class StartupTrigger : ITaskTrigger { + public const int DelayMs = 3000; + /// <summary> - /// Occurs when [triggered]. + /// Initializes a new instance of the <see cref="StartupTrigger"/> class. /// </summary> - public event EventHandler<EventArgs> Triggered; - - public int DelayMs { get; set; } + /// <param name="taskOptions">The options of this task.</param> + public StartupTrigger(TaskOptions taskOptions) + { + TaskOptions = taskOptions; + } /// <summary> - /// Gets or sets the options of this task. + /// Occurs when [triggered]. /// </summary> - public TaskOptions TaskOptions { get; set; } + public event EventHandler<EventArgs>? Triggered; - public StartupTrigger() - { - DelayMs = 3000; - } + /// <summary> + /// Gets the options of this task. + /// </summary> + public TaskOptions TaskOptions { get; } /// <summary> /// Stars waiting for the trigger action. diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs index a67f940b7..36ae190b0 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Threading; using MediaBrowser.Model.Tasks; @@ -10,35 +8,34 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <summary> /// Represents a task trigger that fires on a weekly basis. /// </summary> - public class WeeklyTrigger : ITaskTrigger + public sealed class WeeklyTrigger : ITaskTrigger { - /// <summary> - /// Occurs when [triggered]. - /// </summary> - public event EventHandler<EventArgs> Triggered; - - /// <summary> - /// Gets or sets the time of day to trigger the task to run. - /// </summary> - /// <value>The time of day.</value> - public TimeSpan TimeOfDay { get; set; } + private readonly TimeSpan _timeOfDay; + private readonly DayOfWeek _dayOfWeek; + private Timer? _timer; /// <summary> - /// Gets or sets the day of week. + /// Initializes a new instance of the <see cref="WeeklyTrigger"/> class. /// </summary> - /// <value>The day of week.</value> - public DayOfWeek DayOfWeek { get; set; } + /// <param name="timeofDay">The time of day to trigger the task to run.</param> + /// <param name="dayOfWeek">The day of week.</param> + /// <param name="taskOptions">The options of this task.</param> + public WeeklyTrigger(TimeSpan timeofDay, DayOfWeek dayOfWeek, TaskOptions taskOptions) + { + _timeOfDay = timeofDay; + _dayOfWeek = dayOfWeek; + TaskOptions = taskOptions; + } /// <summary> - /// Gets or sets the options of this task. + /// Occurs when [triggered]. /// </summary> - public TaskOptions TaskOptions { get; set; } + public event EventHandler<EventArgs>? Triggered; /// <summary> - /// Gets or sets the timer. + /// Gets the options of this task. /// </summary> - /// <value>The timer.</value> - private Timer Timer { get; set; } + public TaskOptions TaskOptions { get; } /// <summary> /// Stars waiting for the trigger action. @@ -53,7 +50,7 @@ namespace Emby.Server.Implementations.ScheduledTasks var triggerDate = GetNextTriggerDateTime(); - Timer = new Timer(state => OnTriggered(), null, triggerDate - DateTime.Now, TimeSpan.FromMilliseconds(-1)); + _timer = new Timer(state => OnTriggered(), null, triggerDate - DateTime.Now, TimeSpan.FromMilliseconds(-1)); } /// <summary> @@ -65,22 +62,22 @@ namespace Emby.Server.Implementations.ScheduledTasks var now = DateTime.Now; // If it's on the same day - if (now.DayOfWeek == DayOfWeek) + if (now.DayOfWeek == _dayOfWeek) { // It's either later today, or a week from now - return now.TimeOfDay < TimeOfDay ? now.Date.Add(TimeOfDay) : now.Date.AddDays(7).Add(TimeOfDay); + return now.TimeOfDay < _timeOfDay ? now.Date.Add(_timeOfDay) : now.Date.AddDays(7).Add(_timeOfDay); } var triggerDate = now.Date; // Walk the date forward until we get to the trigger day - while (triggerDate.DayOfWeek != DayOfWeek) + while (triggerDate.DayOfWeek != _dayOfWeek) { triggerDate = triggerDate.AddDays(1); } // Return the trigger date plus the time offset - return triggerDate.Add(TimeOfDay); + return triggerDate.Add(_timeOfDay); } /// <summary> @@ -96,10 +93,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// </summary> private void DisposeTimer() { - if (Timer != null) - { - Timer.Dispose(); - } + _timer?.Dispose(); } /// <summary> diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index ed1dfca59..9fa92a53a 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -1,5 +1,4 @@ #pragma warning disable CS1591 -#pragma warning disable SA1600 using System; using System.Collections.Generic; diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index 750f00168..8179e26c5 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Net; using System.Net.Sockets; @@ -19,6 +17,11 @@ namespace Emby.Server.Implementations.Udp /// </summary> public sealed class UdpServer : IDisposable { + /// <summary> + /// Address Override Configuration Key. + /// </summary> + public const string AddressOverrideConfigKey = "PublishedServerUrl"; + /// <summary> /// The _logger. /// </summary> @@ -26,11 +29,6 @@ namespace Emby.Server.Implementations.Udp private readonly IServerApplicationHost _appHost; private readonly IConfiguration _config; - /// <summary> - /// Address Override Configuration Key. - /// </summary> - public const string AddressOverrideConfigKey = "PublishedServerUrl"; - private Socket _udpSocket; private IPEndPoint _endpoint; private readonly byte[] _receiveBuffer = new byte[8192]; @@ -40,49 +38,58 @@ namespace Emby.Server.Implementations.Udp /// <summary> /// Initializes a new instance of the <see cref="UdpServer" /> class. /// </summary> - public UdpServer(ILogger logger, IServerApplicationHost appHost, IConfiguration configuration) + /// <param name="logger">The logger.</param> + /// <param name="appHost">The application host.</param> + /// <param name="configuration">The configuration manager.</param> + /// <param name="port">The port.</param> + public UdpServer( + ILogger logger, + IServerApplicationHost appHost, + IConfiguration configuration, + int port) { _logger = logger; _appHost = appHost; _config = configuration; + + _endpoint = new IPEndPoint(IPAddress.Any, port); + + _udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + _udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); } private async Task RespondToV2Message(string messageText, EndPoint endpoint, CancellationToken cancellationToken) { - string localUrl = !string.IsNullOrEmpty(_config[AddressOverrideConfigKey]) - ? _config[AddressOverrideConfigKey] - : _appHost.GetSmartApiUrl(((IPEndPoint)endpoint).Address); + string? localUrl = _config[AddressOverrideConfigKey]; + if (string.IsNullOrEmpty(localUrl)) + { + localUrl = _appHost.GetSmartApiUrl(((IPEndPoint)endpoint).Address); + } - if (!string.IsNullOrEmpty(localUrl)) + if (string.IsNullOrEmpty(localUrl)) { - var response = new ServerDiscoveryInfo(localUrl, _appHost.SystemId, _appHost.FriendlyName); + _logger.LogWarning("Unable to respond to udp request because the local ip address could not be determined."); + return; + } - try - { - await _udpSocket.SendToAsync(JsonSerializer.SerializeToUtf8Bytes(response), SocketFlags.None, endpoint).ConfigureAwait(false); - } - catch (SocketException ex) - { - _logger.LogError(ex, "Error sending response message"); - } + var response = new ServerDiscoveryInfo(localUrl, _appHost.SystemId, _appHost.FriendlyName); + + try + { + await _udpSocket.SendToAsync(JsonSerializer.SerializeToUtf8Bytes(response), SocketFlags.None, endpoint).ConfigureAwait(false); } - else + catch (SocketException ex) { - _logger.LogWarning("Unable to respond to udp request because the local ip address could not be determined."); + _logger.LogError(ex, "Error sending response message"); } } /// <summary> /// Starts the specified port. /// </summary> - /// <param name="port">The port.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param> - public void Start(int port, CancellationToken cancellationToken) + public void Start(CancellationToken cancellationToken) { - _endpoint = new IPEndPoint(IPAddress.Any, port); - - _udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - _udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); _udpSocket.Bind(_endpoint); _ = Task.Run(async () => await BeginReceiveAsync(cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); @@ -90,9 +97,9 @@ namespace Emby.Server.Implementations.Udp private async Task BeginReceiveAsync(CancellationToken cancellationToken) { + var infiniteTask = Task.Delay(-1, cancellationToken); while (!cancellationToken.IsCancellationRequested) { - var infiniteTask = Task.Delay(-1, cancellationToken); try { var task = _udpSocket.ReceiveFromAsync(_receiveBuffer, SocketFlags.None, _endpoint); diff --git a/Jellyfin.Server.Implementations/Events/EventManager.cs b/Jellyfin.Server.Implementations/Events/EventManager.cs index 707002442..c5e66112d 100644 --- a/Jellyfin.Server.Implementations/Events/EventManager.cs +++ b/Jellyfin.Server.Implementations/Events/EventManager.cs @@ -43,7 +43,12 @@ namespace Jellyfin.Server.Implementations.Events private async Task PublishInternal<T>(T eventArgs) where T : EventArgs { - using var scope = _appHost.ServiceProvider.CreateScope(); + using var scope = _appHost.ServiceProvider?.CreateScope(); + if (scope == null) + { + return; + } + foreach (var service in scope.ServiceProvider.GetServices<IEventConsumer<T>>()) { try diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 46d93e494..192a77611 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Reflection; @@ -12,7 +10,7 @@ namespace MediaBrowser.Common /// </summary> /// <param name="type">Type to create.</param> /// <returns>New instance of type <param>type</param>.</returns> - public delegate object CreationDelegateFactory(Type type); + public delegate object? CreationDelegateFactory(Type type); /// <summary> /// An interface to be implemented by the applications hosting a kernel. @@ -22,7 +20,7 @@ namespace MediaBrowser.Common /// <summary> /// Occurs when [has pending restart changed]. /// </summary> - event EventHandler HasPendingRestartChanged; + event EventHandler? HasPendingRestartChanged; /// <summary> /// Gets the name. @@ -63,7 +61,7 @@ namespace MediaBrowser.Common /// <summary> /// Gets or sets the service provider. /// </summary> - IServiceProvider ServiceProvider { get; set; } + IServiceProvider? ServiceProvider { get; set; } /// <summary> /// Gets the application version. diff --git a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs b/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs deleted file mode 100644 index cec1aaf08..000000000 --- a/MediaBrowser.MediaEncoding/Subtitles/ParserValues.cs +++ /dev/null @@ -1,9 +0,0 @@ -#pragma warning disable CS1591 - -namespace MediaBrowser.MediaEncoding.Subtitles -{ - public static class ParserValues - { - public const string NewLine = "\r\n"; - } -} diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs index db9fba696..999db9605 100644 --- a/MediaBrowser.Model/Tasks/ITaskTrigger.cs +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -14,9 +14,9 @@ namespace MediaBrowser.Model.Tasks event EventHandler<EventArgs>? Triggered; /// <summary> - /// Gets or sets the options of this task. + /// Gets the options of this task. /// </summary> - TaskOptions TaskOptions { get; set; } + TaskOptions TaskOptions { get; } /// <summary> /// Stars waiting for the trigger action. diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 1a9f2bf96..44bc34369 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -1,6 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <RuleSet Name="Rules for Jellyfin.Server" Description="Code analysis rules for Jellyfin.Server.csproj" ToolsVersion="14.0"> <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> + <!-- disable warning CA1040: Avoid empty interfaces --> + <Rule Id="CA1040" Action="Info" /> + <!-- disable warning SA1009: Closing parenthesis should be followed by a space. --> <Rule Id="SA1009" Action="None" /> <!-- disable warning SA1011: Closing square bracket should be followed by a space. --> -- cgit v1.2.3 From adf406b1821800bbf1b214c4ac673defa362e4f4 Mon Sep 17 00:00:00 2001 From: Stan <stanislav.ionascu@gmail.com> Date: Thu, 10 Jun 2021 21:07:28 +0300 Subject: Fix playback of complex BluRay ISOs (#6166) --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 3 ++- MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index cdb778bf2..3af618af8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -367,7 +367,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetInputArgument(string inputFile, MediaSourceInfo mediaSource) { var prefix = "file"; - if (mediaSource.VideoType == VideoType.BluRay) + if (mediaSource.VideoType == VideoType.BluRay + || mediaSource.IsoType == IsoType.BluRay) { prefix = "bluray"; } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 36b56f20f..12e1fbea5 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -147,7 +147,8 @@ namespace MediaBrowser.Providers.MediaInfo { Path = path, Protocol = protocol, - VideoType = item.VideoType + VideoType = item.VideoType, + IsoType = item.IsoType } }, cancellationToken); -- cgit v1.2.3 From 6f8ccab788e85e025eaa44b67a1487bf419afb53 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 19 Jun 2021 18:02:33 +0200 Subject: Move non-jellyfin extensions to separate project --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Naming/Audio/AudioFileParser.cs | 2 +- Emby.Naming/Video/VideoResolver.cs | 2 +- .../Channels/ChannelManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 3 +- .../HttpServer/Security/AuthorizationContext.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 2 +- .../IO/ManagedFileSystem.cs | 2 +- .../Library/LibraryManager.cs | 1 + .../Library/LiveStreamHelper.cs | 2 +- .../Library/MediaSourceManager.cs | 2 +- .../Library/Resolvers/Movies/MovieResolver.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 4 +- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 4 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 +- .../LiveTv/TunerHosts/M3uParser.cs | 1 + .../Localization/LocalizationManager.cs | 4 +- .../Plugins/PluginManager.cs | 4 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 2 +- .../Session/SessionManager.cs | 1 + .../Sorting/StudioComparer.cs | 3 +- .../Updates/InstallationManager.cs | 2 +- Jellyfin.Api/BaseJellyfinApiController.cs | 2 +- .../Controllers/ConfigurationController.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 2 +- Jellyfin.Api/Controllers/TvShowsController.cs | 2 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 2 +- Jellyfin.Api/Extensions/DtoExtensions.cs | 2 +- Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs | 2 +- .../Models/PlaylistDtos/CreatePlaylistDto.cs | 2 +- .../Models/SessionDtos/ClientCapabilitiesDto.cs | 4 +- .../Extensions/ApiServiceCollectionExtensions.cs | 2 +- .../Formatters/CamelCaseJsonProfileFormatter.cs | 2 +- .../Formatters/PascalCaseJsonProfileFormatter.cs | 2 +- .../Middleware/UrlDecodeQueryFeature.cs | 2 +- .../Migrations/Routines/MigrateUserDb.cs | 2 +- Jellyfin.sln | 16 +++ MediaBrowser.Common/Extensions/CopyToExtensions.cs | 26 ---- .../Extensions/EnumerableExtensions.cs | 51 -------- .../Extensions/ShuffleExtensions.cs | 41 ------ .../Extensions/SplitStringExtensions.cs | 95 -------------- MediaBrowser.Common/Extensions/StreamExtensions.cs | 63 --------- .../Extensions/StringBuilderExtensions.cs | 35 ----- .../Json/Converters/JsonBoolNumberConverter.cs | 30 ----- .../Converters/JsonCommaDelimitedArrayConverter.cs | 24 ---- .../JsonCommaDelimitedArrayConverterFactory.cs | 28 ---- .../Json/Converters/JsonDateTimeConverter.cs | 34 ----- .../Json/Converters/JsonDelimitedArrayConverter.cs | 81 ------------ .../Json/Converters/JsonGuidConverter.cs | 26 ---- .../Json/Converters/JsonNullableGuidConverter.cs | 33 ----- .../Json/Converters/JsonNullableStructConverter.cs | 45 ------- .../JsonNullableStructConverterFactory.cs | 27 ---- .../JsonOmdbNotAvailableInt32Converter.cs | 44 ------- .../JsonOmdbNotAvailableStringConverter.cs | 41 ------ .../Converters/JsonPipeDelimitedArrayConverter.cs | 24 ---- .../JsonPipeDelimitedArrayConverterFactory.cs | 28 ---- .../Json/Converters/JsonStringConverter.cs | 39 ------ .../Json/Converters/JsonVersionConverter.cs | 23 ---- MediaBrowser.Common/Json/JsonDefaults.cs | 90 ------------- .../BaseItemManager/BaseItemManager.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 1 + .../Entities/CollectionFolder.cs | 2 +- MediaBrowser.Controller/Entities/Extensions.cs | 2 +- .../Extensions/StringExtensions.cs | 21 --- .../Sorting/AlphanumComparator.cs | 137 -------------------- MediaBrowser.Controller/Sorting/SortExtensions.cs | 5 +- .../Images/EpisodeLocalImageProvider.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../Subtitles/SubtitleEditParser.cs | 2 +- .../Entities/JsonLowerCaseConverter.cs | 29 ----- MediaBrowser.Model/Entities/VirtualFolderInfo.cs | 1 + MediaBrowser.Model/MediaBrowser.Model.csproj | 3 +- .../Plugins/AudioDb/AlbumImageProvider.cs | 2 +- .../Plugins/AudioDb/AlbumProvider.cs | 2 +- .../Plugins/AudioDb/ArtistImageProvider.cs | 2 +- .../Plugins/AudioDb/ArtistProvider.cs | 2 +- .../Omdb/JsonOmdbNotAvailableInt32Converter.cs | 46 +++++++ .../Omdb/JsonOmdbNotAvailableStringConverter.cs | 43 ++++++ .../Plugins/Omdb/OmdbItemProvider.cs | 4 +- .../Plugins/Omdb/OmdbProvider.cs | 4 +- MediaBrowser.Providers/Properties/AssemblyInfo.cs | 2 +- .../Studios/StudiosImageProvider.cs | 2 +- src/Jellyfin.Extensions/AlphanumericComparator.cs | 144 +++++++++++++++++++++ src/Jellyfin.Extensions/CopyToExtensions.cs | 26 ++++ src/Jellyfin.Extensions/EnumerableExtensions.cs | 51 ++++++++ src/Jellyfin.Extensions/Jellyfin.Extensions.csproj | 30 +++++ .../Json/Converters/JsonBoolNumberConverter.cs | 30 +++++ .../Converters/JsonCommaDelimitedArrayConverter.cs | 24 ++++ .../JsonCommaDelimitedArrayConverterFactory.cs | 28 ++++ .../Json/Converters/JsonDateTimeConverter.cs | 34 +++++ .../Json/Converters/JsonDelimitedArrayConverter.cs | 81 ++++++++++++ .../Json/Converters/JsonGuidConverter.cs | 26 ++++ .../Json/Converters/JsonLowerCaseConverter.cs | 25 ++++ .../Json/Converters/JsonNullableGuidConverter.cs | 33 +++++ .../Json/Converters/JsonNullableStructConverter.cs | 45 +++++++ .../JsonNullableStructConverterFactory.cs | 27 ++++ .../Converters/JsonPipeDelimitedArrayConverter.cs | 24 ++++ .../JsonPipeDelimitedArrayConverterFactory.cs | 28 ++++ .../Json/Converters/JsonStringConverter.cs | 39 ++++++ .../Json/Converters/JsonVersionConverter.cs | 23 ++++ src/Jellyfin.Extensions/Json/JsonDefaults.cs | 90 +++++++++++++ src/Jellyfin.Extensions/ShuffleExtensions.cs | 41 ++++++ src/Jellyfin.Extensions/SplitStringExtensions.cs | 115 ++++++++++++++++ src/Jellyfin.Extensions/StreamExtensions.cs | 63 +++++++++ src/Jellyfin.Extensions/StringBuilderExtensions.cs | 35 +++++ src/Jellyfin.Extensions/StringExtensions.cs | 31 +++++ .../Extensions/CopyToExtensionsTests.cs | 40 ------ .../Extensions/ShuffleExtensionsTests.cs | 22 ---- .../Json/JsonBoolNumberTests.cs | 45 ------- .../Json/JsonCommaDelimitedArrayTests.cs | 142 -------------------- .../Json/JsonCommaDelimitedIReadOnlyListTests.cs | 92 ------------- .../Json/JsonGuidConverterTests.cs | 68 ---------- .../Json/JsonNullableGuidConverterTests.cs | 80 ------------ .../Json/JsonOmdbConverterTests.cs | 87 ------------- .../Json/JsonStringConverterTests.cs | 38 ------ .../Json/JsonVersionConverterTests.cs | 36 ------ .../Models/GenericBodyArrayModel.cs | 20 --- .../Models/GenericBodyIReadOnlyListModel.cs | 19 --- .../AlphanumComparatorTests.cs | 30 ----- .../Extensions/StringExtensionsTests.cs | 19 --- .../AlphanumericComparatorTests.cs | 29 +++++ .../CopyToExtensionsTests.cs | 39 ++++++ .../Jellyfin.Extensions.Tests.csproj | 38 ++++++ .../Json/Converters/JsonBoolNumberTests.cs | 45 +++++++ .../Converters/JsonCommaDelimitedArrayTests.cs | 142 ++++++++++++++++++++ .../JsonCommaDelimitedIReadOnlyListTests.cs | 92 +++++++++++++ .../Json/Converters/JsonGuidConverterTests.cs | 68 ++++++++++ .../Json/Converters/JsonLowerCaseConverterTests.cs | 71 ++++++++++ .../Converters/JsonNullableGuidConverterTests.cs | 80 ++++++++++++ .../Json/Converters/JsonStringConverterTests.cs | 38 ++++++ .../Json/Converters/JsonVersionConverterTests.cs | 36 ++++++ .../Json/Models/GenericBodyArrayModel.cs | 20 +++ .../Json/Models/GenericBodyIReadOnlyListModel.cs | 19 +++ .../ShuffleExtensionsTests.cs | 21 +++ .../StringExtensionsTests.cs | 18 +++ .../FFprobeParserTests.cs | 2 +- .../Probing/ProbeResultNormalizerTests.cs | 2 +- .../Entities/JsonLowerCaseConverterTests.cs | 70 ---------- .../Omdb/JsonOmdbConverterTests.cs | 86 ++++++++++++ .../AuthHelper.cs | 2 +- .../Controllers/DashboardControllerTests.cs | 2 +- .../Controllers/StartupControllerTests.cs | 2 +- .../Controllers/UserControllerTests.cs | 2 +- 144 files changed, 2113 insertions(+), 1988 deletions(-) delete mode 100644 MediaBrowser.Common/Extensions/CopyToExtensions.cs delete mode 100644 MediaBrowser.Common/Extensions/EnumerableExtensions.cs delete mode 100644 MediaBrowser.Common/Extensions/ShuffleExtensions.cs delete mode 100644 MediaBrowser.Common/Extensions/SplitStringExtensions.cs delete mode 100644 MediaBrowser.Common/Extensions/StreamExtensions.cs delete mode 100644 MediaBrowser.Common/Extensions/StringBuilderExtensions.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonStringConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs delete mode 100644 MediaBrowser.Common/Json/JsonDefaults.cs delete mode 100644 MediaBrowser.Controller/Sorting/AlphanumComparator.cs delete mode 100644 MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs create mode 100644 MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs create mode 100644 MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs create mode 100644 src/Jellyfin.Extensions/AlphanumericComparator.cs create mode 100644 src/Jellyfin.Extensions/CopyToExtensions.cs create mode 100644 src/Jellyfin.Extensions/EnumerableExtensions.cs create mode 100644 src/Jellyfin.Extensions/Jellyfin.Extensions.csproj create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs create mode 100644 src/Jellyfin.Extensions/Json/JsonDefaults.cs create mode 100644 src/Jellyfin.Extensions/ShuffleExtensions.cs create mode 100644 src/Jellyfin.Extensions/SplitStringExtensions.cs create mode 100644 src/Jellyfin.Extensions/StreamExtensions.cs create mode 100644 src/Jellyfin.Extensions/StringBuilderExtensions.cs create mode 100644 src/Jellyfin.Extensions/StringExtensions.cs delete mode 100644 tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs delete mode 100644 tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs delete mode 100644 tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs delete mode 100644 tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs delete mode 100644 tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs create mode 100644 tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs create mode 100644 tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs create mode 100644 tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs delete mode 100644 tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs create mode 100644 tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index a1b106704..b08f7590d 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -14,9 +14,9 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Emby.Dlna.Profiles; using Emby.Dlna.Server; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; diff --git a/Emby.Naming/Audio/AudioFileParser.cs b/Emby.Naming/Audio/AudioFileParser.cs index af4aa0059..2b610ec79 100644 --- a/Emby.Naming/Audio/AudioFileParser.cs +++ b/Emby.Naming/Audio/AudioFileParser.cs @@ -1,7 +1,7 @@ using System; using System.IO; using Emby.Naming.Common; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; namespace Emby.Naming.Audio { diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index c4ac5fdc6..3b1d906c6 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -2,7 +2,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; using Emby.Naming.Common; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; namespace Emby.Naming.Video { diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 448f12403..093607dd5 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -11,7 +11,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 9b147b5d7..35aa589a1 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -13,8 +13,9 @@ using System.Text.Json; using System.Threading; using Emby.Server.Implementations.Playlists; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs index c87f7dbbd..488614609 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Net; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Security; diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 8f7d60669..5d38ea0ca 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -7,7 +7,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 64d802457..ca028a3ca 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -6,8 +6,8 @@ using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 028673529..d80637332 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -21,6 +21,7 @@ using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.ScheduledTasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 4ef7923db..806269182 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -12,7 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index b812b6b61..91c9e61cf 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -15,7 +15,7 @@ using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 97f96f746..889e29a6b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Video; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 26e4ef1ed..93781cb7b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -11,9 +11,9 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index bdab8c3e4..4a031e475 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 00d02873c..b7639a51c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -15,7 +15,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Cryptography; @@ -789,7 +789,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) + var station = allStations.Find(item => string.Equals(item.stationID, channel.stationID, StringComparison.OrdinalIgnoreCase)) ?? new ScheduleDirect.Station { stationID = channel.stationID diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 54de841fe..011748d1d 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -12,8 +12,9 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 40a162890..c9657f605 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -10,6 +10,7 @@ using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index b1ff28c2c..a9e3bfdb0 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -8,8 +8,8 @@ using System.IO; using System.Reflection; using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 8fd61f2bc..fc0920edf 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading.Tasks; using MediaBrowser.Common; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index d7e320754..b34325041 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 62df354fd..c4b19f417 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Extensions; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 01445c525..6826aee3b 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -30,7 +31,7 @@ namespace Emby.Server.Implementations.Sorting throw new ArgumentNullException(nameof(y)); } - return AlphanumComparator.CompareValues(x.Studios.FirstOrDefault() ?? string.Empty, y.Studios.FirstOrDefault() ?? string.Empty); + return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault()); } /// <summary> diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index b0921cbd8..7b0afa4e2 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -11,7 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; diff --git a/Jellyfin.Api/BaseJellyfinApiController.cs b/Jellyfin.Api/BaseJellyfinApiController.cs index 1c1fc71d7..59d6b7513 100644 --- a/Jellyfin.Api/BaseJellyfinApiController.cs +++ b/Jellyfin.Api/BaseJellyfinApiController.cs @@ -1,5 +1,5 @@ using System.Net.Mime; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index b6309baab..60529e990 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.ConfigurationDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 7a6130719..0ae6109bc 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -8,8 +8,8 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.PluginDtos; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Net; diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index ffb726fab..51d40994e 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -6,7 +6,7 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 1d70406ac..a33a0826c 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -9,7 +9,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index 06173315a..5e338b67d 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using Jellyfin.Api.Helpers; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs index 8913180e4..411e4c550 100644 --- a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs +++ b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs b/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs index 65d4b644e..0761b2085 100644 --- a/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs +++ b/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; namespace Jellyfin.Api.Models.PlaylistDtos { diff --git a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs index e58095536..fa62472e1 100644 --- a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs +++ b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Session; @@ -85,4 +85,4 @@ namespace Jellyfin.Api.Models.SessionDtos }; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 924b250ce..15dc43856 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -21,11 +21,11 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; +using Jellyfin.Extensions.Json; using Jellyfin.Networking.Configuration; using Jellyfin.Server.Configuration; using Jellyfin.Server.Filters; using Jellyfin.Server.Formatters; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Authentication; diff --git a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs index c349e3dca..ea8c5ecdb 100644 --- a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; diff --git a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs index 0480f5e0e..03ca7dda7 100644 --- a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs @@ -1,5 +1,5 @@ using System.Net.Mime; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; diff --git a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs index 310a3d31a..c1f5b5dfa 100644 --- a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs +++ b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Web; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Primitives; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 96bd2ccc4..d9524645a 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -4,9 +4,9 @@ using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Serialization; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions.Json; using Jellyfin.Server.Implementations; using Jellyfin.Server.Implementations.Users; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; diff --git a/Jellyfin.sln b/Jellyfin.sln index 9fbd9d266..4626601c3 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -83,6 +83,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server.Integration EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Providers.Tests", "tests\Jellyfin.Providers.Tests\Jellyfin.Providers.Tests.csproj", "{A964008C-2136-4716-B6CB-B3426C22320A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions", "src\Jellyfin.Extensions\Jellyfin.Extensions.csproj", "{750B8757-BE3D-4F8C-941A-FBAD94904ADA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions.Tests", "tests\Jellyfin.Extensions.Tests\Jellyfin.Extensions.Tests.csproj", "{332A5C7A-F907-47CA-910E-BE6F7371B9E0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -229,6 +235,14 @@ Global {A964008C-2136-4716-B6CB-B3426C22320A}.Debug|Any CPU.Build.0 = Debug|Any CPU {A964008C-2136-4716-B6CB-B3426C22320A}.Release|Any CPU.ActiveCfg = Release|Any CPU {A964008C-2136-4716-B6CB-B3426C22320A}.Release|Any CPU.Build.0 = Release|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Release|Any CPU.Build.0 = Release|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -247,6 +261,8 @@ Global {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {68B0B823-A5AC-4E8B-82EA-965AAC7BF76E} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {A964008C-2136-4716-B6CB-B3426C22320A} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {750B8757-BE3D-4F8C-941A-FBAD94904ADA} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C} + {332A5C7A-F907-47CA-910E-BE6F7371B9E0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE} diff --git a/MediaBrowser.Common/Extensions/CopyToExtensions.cs b/MediaBrowser.Common/Extensions/CopyToExtensions.cs deleted file mode 100644 index 2ecbc6539..000000000 --- a/MediaBrowser.Common/Extensions/CopyToExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Provides <c>CopyTo</c> extensions methods for <see cref="IReadOnlyList{T}" />. - /// </summary> - public static class CopyToExtensions - { - /// <summary> - /// Copies all the elements of the current collection to the specified list - /// starting at the specified destination array index. The index is specified as a 32-bit integer. - /// </summary> - /// <param name="source">The current collection that is the source of the elements.</param> - /// <param name="destination">The list that is the destination of the elements copied from the current collection.</param> - /// <param name="index">A 32-bit integer that represents the index in <c>destination</c> at which copying begins.</param> - /// <typeparam name="T">The type of the array.</typeparam> - public static void CopyTo<T>(this IReadOnlyList<T> source, IList<T> destination, int index = 0) - { - for (int i = 0; i < source.Count; i++) - { - destination[index + i] = source[i]; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/EnumerableExtensions.cs b/MediaBrowser.Common/Extensions/EnumerableExtensions.cs deleted file mode 100644 index 2b8a6c395..000000000 --- a/MediaBrowser.Common/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Static extensions for the <see cref="IEnumerable{T}"/> interface. - /// </summary> - public static class EnumerableExtensions - { - /// <summary> - /// Determines whether the value is contained in the source collection. - /// </summary> - /// <param name="source">An instance of the <see cref="IEnumerable{String}"/> interface.</param> - /// <param name="value">The value to look for in the collection.</param> - /// <param name="stringComparison">The string comparison.</param> - /// <returns>A value indicating whether the value is contained in the collection.</returns> - /// <exception cref="ArgumentNullException">The source is null.</exception> - public static bool Contains(this IEnumerable<string> source, ReadOnlySpan<char> value, StringComparison stringComparison) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (source is IList<string> list) - { - int len = list.Count; - for (int i = 0; i < len; i++) - { - if (value.Equals(list[i], stringComparison)) - { - return true; - } - } - - return false; - } - - foreach (string element in source) - { - if (value.Equals(element, stringComparison)) - { - return true; - } - } - - return false; - } - } -} diff --git a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs b/MediaBrowser.Common/Extensions/ShuffleExtensions.cs deleted file mode 100644 index 2604abf85..000000000 --- a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Provides <c>Shuffle</c> extensions methods for <see cref="IList{T}" />. - /// </summary> - public static class ShuffleExtensions - { - private static readonly Random _rng = new Random(); - - /// <summary> - /// Shuffles the items in a list. - /// </summary> - /// <param name="list">The list that should get shuffled.</param> - /// <typeparam name="T">The type.</typeparam> - public static void Shuffle<T>(this IList<T> list) - { - list.Shuffle(_rng); - } - - /// <summary> - /// Shuffles the items in a list. - /// </summary> - /// <param name="list">The list that should get shuffled.</param> - /// <param name="rng">The random number generator to use.</param> - /// <typeparam name="T">The type.</typeparam> - public static void Shuffle<T>(this IList<T> list, Random rng) - { - int n = list.Count; - while (n > 1) - { - int k = rng.Next(n--); - T value = list[k]; - list[k] = list[n]; - list[n] = value; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/SplitStringExtensions.cs b/MediaBrowser.Common/Extensions/SplitStringExtensions.cs deleted file mode 100644 index 9c9108495..000000000 --- a/MediaBrowser.Common/Extensions/SplitStringExtensions.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* -MIT License - -Copyright (c) 2019 Gérald Barré - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ - -#pragma warning disable CS1591 -#pragma warning disable CA1034 -using System; -using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Extension class for splitting lines without unnecessary allocations. - /// </summary> - public static class SplitStringExtensions - { - /// <summary> - /// Creates a new string split enumerator. - /// </summary> - /// <param name="str">The string to split.</param> - /// <param name="separator">The separator to split on.</param> - /// <returns>The enumerator struct.</returns> - [Pure] - public static SplitEnumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); - - /// <summary> - /// Creates a new span split enumerator. - /// </summary> - /// <param name="str">The span to split.</param> - /// <param name="separator">The separator to split on.</param> - /// <returns>The enumerator struct.</returns> - [Pure] - public static SplitEnumerator Split(this ReadOnlySpan<char> str, char separator) => new (str, separator); - - [StructLayout(LayoutKind.Auto)] - public ref struct SplitEnumerator - { - private readonly char _separator; - private ReadOnlySpan<char> _str; - - public SplitEnumerator(ReadOnlySpan<char> str, char separator) - { - _str = str; - _separator = separator; - Current = default; - } - - public ReadOnlySpan<char> Current { get; private set; } - - public readonly SplitEnumerator GetEnumerator() => this; - - public bool MoveNext() - { - if (_str.Length == 0) - { - return false; - } - - var span = _str; - var index = span.IndexOf(_separator); - if (index == -1) - { - _str = ReadOnlySpan<char>.Empty; - Current = span; - return true; - } - - Current = span.Slice(0, index); - _str = span[(index + 1)..]; - return true; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/StreamExtensions.cs b/MediaBrowser.Common/Extensions/StreamExtensions.cs deleted file mode 100644 index 5cbf57d98..000000000 --- a/MediaBrowser.Common/Extensions/StreamExtensions.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Class BaseExtensions. - /// </summary> - public static class StreamExtensions - { - /// <summary> - /// Reads all lines in the <see cref="Stream" />. - /// </summary> - /// <param name="stream">The <see cref="Stream" /> to read from.</param> - /// <returns>All lines in the stream.</returns> - public static string[] ReadAllLines(this Stream stream) - => ReadAllLines(stream, Encoding.UTF8); - - /// <summary> - /// Reads all lines in the <see cref="Stream" />. - /// </summary> - /// <param name="stream">The <see cref="Stream" /> to read from.</param> - /// <param name="encoding">The character encoding to use.</param> - /// <returns>All lines in the stream.</returns> - public static string[] ReadAllLines(this Stream stream, Encoding encoding) - { - using (StreamReader reader = new StreamReader(stream, encoding)) - { - return ReadAllLines(reader).ToArray(); - } - } - - /// <summary> - /// Reads all lines in the <see cref="TextReader" />. - /// </summary> - /// <param name="reader">The <see cref="TextReader" /> to read from.</param> - /// <returns>All lines in the stream.</returns> - public static IEnumerable<string> ReadAllLines(this TextReader reader) - { - string? line; - while ((line = reader.ReadLine()) != null) - { - yield return line; - } - } - - /// <summary> - /// Reads all lines in the <see cref="TextReader" />. - /// </summary> - /// <param name="reader">The <see cref="TextReader" /> to read from.</param> - /// <returns>All lines in the stream.</returns> - public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader) - { - string? line; - while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null) - { - yield return line; - } - } - } -} diff --git a/MediaBrowser.Common/Extensions/StringBuilderExtensions.cs b/MediaBrowser.Common/Extensions/StringBuilderExtensions.cs deleted file mode 100644 index 75d654f23..000000000 --- a/MediaBrowser.Common/Extensions/StringBuilderExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace MediaBrowser.Common.Extensions -{ - /// <summary> - /// Extension methods for the <see cref="StringBuilder"/> class. - /// </summary> - public static class StringBuilderExtensions - { - /// <summary> - /// Concatenates and appends the members of a collection in single quotes using the specified delimiter. - /// </summary> - /// <param name="builder">The string builder.</param> - /// <param name="delimiter">The character delimiter.</param> - /// <param name="values">The collection of strings to concatenate.</param> - /// <returns>The updated string builder.</returns> - public static StringBuilder AppendJoinInSingleQuotes(this StringBuilder builder, char delimiter, IReadOnlyList<string> values) - { - var len = values.Count; - for (var i = 0; i < len; i++) - { - builder.Append('\'') - .Append(values[i]) - .Append('\'') - .Append(delimiter); - } - - // remove last , - builder.Length--; - - return builder; - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs b/MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs deleted file mode 100644 index b29e6a71a..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a number to a boolean. - /// This is needed for HDHomerun. - /// </summary> - public class JsonBoolNumberConverter : JsonConverter<bool> - { - /// <inheritdoc /> - public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Number) - { - return Convert.ToBoolean(reader.GetInt32()); - } - - return reader.GetBoolean(); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) - { - writer.WriteBooleanValue(value); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs deleted file mode 100644 index 127a41a06..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.ComponentModel; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Convert comma delimited string to array of type. - /// </summary> - /// <typeparam name="T">Type to convert to.</typeparam> - public sealed class JsonCommaDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> - { - /// <summary> - /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class. - /// </summary> - public JsonCommaDelimitedArrayConverter() : base() - { - } - - /// <inheritdoc /> - protected override char Delimiter => ','; - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs deleted file mode 100644 index de41348dd..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Json comma delimited array converter factory. - /// </summary> - /// <remarks> - /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. - /// </remarks> - public class JsonCommaDelimitedArrayConverterFactory : JsonConverterFactory - { - /// <inheritdoc /> - public override bool CanConvert(Type typeToConvert) - { - return true; - } - - /// <inheritdoc /> - public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; - return (JsonConverter?)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType)); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs b/MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs deleted file mode 100644 index 73e3a0493..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Legacy DateTime converter. - /// Milliseconds aren't output if zero by default. - /// </summary> - public class JsonDateTimeConverter : JsonConverter<DateTime> - { - /// <inheritdoc /> - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return reader.GetDateTime(); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - if (value.Millisecond == 0) - { - // Remaining ticks value will be 0, manually format. - writer.WriteStringValue(value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffZ", CultureInfo.InvariantCulture)); - } - else - { - writer.WriteStringValue(value); - } - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs deleted file mode 100644 index b691798c9..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.ComponentModel; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Convert delimited string to array of type. - /// </summary> - /// <typeparam name="T">Type to convert to.</typeparam> - public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]?> - { - private readonly TypeConverter _typeConverter; - - /// <summary> - /// Initializes a new instance of the <see cref="JsonDelimitedArrayConverter{T}"/> class. - /// </summary> - protected JsonDelimitedArrayConverter() - { - _typeConverter = TypeDescriptor.GetConverter(typeof(T)); - } - - /// <summary> - /// Gets the array delimiter. - /// </summary> - protected virtual char Delimiter { get; } - - /// <inheritdoc /> - public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - // GetString can't return null here because we already handled it above - var stringEntries = reader.GetString()?.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries); - if (stringEntries == null || stringEntries.Length == 0) - { - return Array.Empty<T>(); - } - - var parsedValues = new object[stringEntries.Length]; - var convertedCount = 0; - for (var i = 0; i < stringEntries.Length; i++) - { - try - { - parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()); - convertedCount++; - } - catch (FormatException) - { - // TODO log when upgraded to .Net6 - // https://github.com/dotnet/runtime/issues/42975 - // _logger.LogDebug(e, "Error converting value."); - } - } - - var typedValues = new T[convertedCount]; - var typedValueIndex = 0; - for (var i = 0; i < stringEntries.Length; i++) - { - if (parsedValues[i] != null) - { - typedValues.SetValue(parsedValues[i], typedValueIndex); - typedValueIndex++; - } - } - - return typedValues; - } - - return JsonSerializer.Deserialize<T[]>(ref reader, options); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, T[]? value, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs b/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs deleted file mode 100644 index bd9600110..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a GUID object or value to/from JSON. - /// </summary> - public class JsonGuidConverter : JsonConverter<Guid> - { - /// <inheritdoc /> - public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var guidStr = reader.GetString(); - return guidStr == null ? Guid.Empty : new Guid(guidStr); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString("N", CultureInfo.InvariantCulture)); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs deleted file mode 100644 index 6d96d5496..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a GUID object or value to/from JSON. - /// </summary> - public class JsonNullableGuidConverter : JsonConverter<Guid?> - { - /// <inheritdoc /> - public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var guidStr = reader.GetString(); - return guidStr == null ? null : new Guid(guidStr); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, Guid? value, JsonSerializerOptions options) - { - if (value == null || value == Guid.Empty) - { - writer.WriteNullValue(); - } - else - { - writer.WriteStringValue(value.Value.ToString("N", CultureInfo.InvariantCulture)); - } - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs deleted file mode 100644 index 0501f7b2a..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a nullable struct or value to/from JSON. - /// Required - some clients send an empty string. - /// </summary> - /// <typeparam name="TStruct">The struct type.</typeparam> - public class JsonNullableStructConverter<TStruct> : JsonConverter<TStruct?> - where TStruct : struct - { - /// <inheritdoc /> - public override TStruct? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - // Token is empty string. - if (reader.TokenType == JsonTokenType.String && ((reader.HasValueSequence && reader.ValueSequence.IsEmpty) || reader.ValueSpan.IsEmpty)) - { - return null; - } - - return JsonSerializer.Deserialize<TStruct>(ref reader, options); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, TStruct? value, JsonSerializerOptions options) - { - if (value.HasValue) - { - JsonSerializer.Serialize(writer, value.Value, options); - } - else - { - writer.WriteNullValue(); - } - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs deleted file mode 100644 index e2a3d798a..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Json nullable struct converter factory. - /// </summary> - public class JsonNullableStructConverterFactory : JsonConverterFactory - { - /// <inheritdoc /> - public override bool CanConvert(Type typeToConvert) - { - return typeToConvert.IsGenericType - && typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>) - && typeToConvert.GenericTypeArguments[0].IsValueType; - } - - /// <inheritdoc /> - public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var structType = typeToConvert.GenericTypeArguments[0]; - return (JsonConverter?)Activator.CreateInstance(typeof(JsonNullableStructConverter<>).MakeGenericType(structType)); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs deleted file mode 100644 index 3d97a9de5..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.ComponentModel; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a string <c>N/A</c> to <c>string.Empty</c>. - /// </summary> - public class JsonOmdbNotAvailableInt32Converter : JsonConverter<int?> - { - /// <inheritdoc /> - public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - var str = reader.GetString(); - if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) - { - return null; - } - - var converter = TypeDescriptor.GetConverter(typeToConvert); - return (int?)converter.ConvertFromString(str); - } - - return JsonSerializer.Deserialize<int>(ref reader, options); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) - { - if (value.HasValue) - { - writer.WriteNumberValue(value.Value); - } - else - { - writer.WriteNullValue(); - } - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs b/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs deleted file mode 100644 index 77cf46b70..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a string <c>N/A</c> to <c>string.Empty</c>. - /// </summary> - public class JsonOmdbNotAvailableStringConverter : JsonConverter<string?> - { - /// <inheritdoc /> - public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - if (reader.TokenType == JsonTokenType.String) - { - // GetString can't return null here because we already handled it above - var str = reader.GetString()!; - if (str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) - { - return null; - } - - return str; - } - - return JsonSerializer.Deserialize<string?>(ref reader, options); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) - { - writer.WriteStringValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs deleted file mode 100644 index a8f6cfbec..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.ComponentModel; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Convert Pipe delimited string to array of type. - /// </summary> - /// <typeparam name="T">Type to convert to.</typeparam> - public sealed class JsonPipeDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> - { - /// <summary> - /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class. - /// </summary> - public JsonPipeDelimitedArrayConverter() : base() - { - } - - /// <inheritdoc /> - protected override char Delimiter => '|'; - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs deleted file mode 100644 index 1bebc49ec..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Json Pipe delimited array converter factory. - /// </summary> - /// <remarks> - /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. - /// </remarks> - public class JsonPipeDelimitedArrayConverterFactory : JsonConverterFactory - { - /// <inheritdoc /> - public override bool CanConvert(Type typeToConvert) - { - return true; - } - - /// <inheritdoc /> - public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; - return (JsonConverter?)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType)); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonStringConverter.cs b/MediaBrowser.Common/Json/Converters/JsonStringConverter.cs deleted file mode 100644 index 6cd980e48..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonStringConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Buffers; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converter to allow the serializer to read strings. - /// </summary> - public class JsonStringConverter : JsonConverter<string?> - { - /// <inheritdoc /> - public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return reader.TokenType switch - { - JsonTokenType.Null => null, - JsonTokenType.String => reader.GetString(), - _ => GetRawValue(reader) - }; - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) - { - writer.WriteStringValue(value); - } - - private static string GetRawValue(Utf8JsonReader reader) - { - var utf8Bytes = reader.HasValueSequence - ? reader.ValueSequence.ToArray() - : reader.ValueSpan; - return Encoding.UTF8.GetString(utf8Bytes); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs b/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs deleted file mode 100644 index 81c093c54..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// <summary> - /// Converts a Version object or value to/from JSON. - /// </summary> - /// <remarks> - /// Required to send <see cref="Version"/> as a string instead of an object. - /// </remarks> - public class JsonVersionConverter : JsonConverter<Version> - { - /// <inheritdoc /> - public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => new Version(reader.GetString()!); // Will throw ArgumentNullException on null - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString()); - } -} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs deleted file mode 100644 index 405d6125f..000000000 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; - -namespace MediaBrowser.Common.Json -{ - /// <summary> - /// Helper class for having compatible JSON throughout the codebase. - /// </summary> - public static class JsonDefaults - { - /// <summary> - /// Pascal case json profile media type. - /// </summary> - public const string PascalCaseMediaType = "application/json; profile=\"PascalCase\""; - - /// <summary> - /// Camel case json profile media type. - /// </summary> - public const string CamelCaseMediaType = "application/json; profile=\"CamelCase\""; - - /// <summary> - /// When changing these options, update - /// Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs - /// -> AddJellyfinApi - /// -> AddJsonOptions. - /// </summary> - private static readonly JsonSerializerOptions _jsonSerializerOptions = new () - { - ReadCommentHandling = JsonCommentHandling.Disallow, - WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - NumberHandling = JsonNumberHandling.AllowReadingFromString, - Converters = - { - new JsonGuidConverter(), - new JsonNullableGuidConverter(), - new JsonVersionConverter(), - new JsonStringEnumConverter(), - new JsonNullableStructConverterFactory(), - new JsonBoolNumberConverter(), - new JsonDateTimeConverter(), - new JsonStringConverter() - } - }; - - private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new (_jsonSerializerOptions) - { - PropertyNamingPolicy = null - }; - - private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new (_jsonSerializerOptions) - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - /// <summary> - /// Gets the default <see cref="JsonSerializerOptions" /> options. - /// </summary> - /// <remarks> - /// The return value must not be modified. - /// If the defaults must be modified the author must use the copy constructor. - /// </remarks> - /// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions Options - => _jsonSerializerOptions; - - /// <summary> - /// Gets camelCase json options. - /// </summary> - /// <remarks> - /// The return value must not be modified. - /// If the defaults must be modified the author must use the copy constructor. - /// </remarks> - /// <returns>The camelCase <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions CamelCaseOptions - => _camelCaseJsonSerializerOptions; - - /// <summary> - /// Gets PascalCase json options. - /// </summary> - /// <remarks> - /// The return value must not be modified. - /// If the defaults must be modified the author must use the copy constructor. - /// </remarks> - /// <returns>The PascalCase <see cref="JsonSerializerOptions" /> options.</returns> - public static JsonSerializerOptions PascalCaseOptions - => _pascalCaseJsonSerializerOptions; - } -} diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs index ffc274c5d..97f40b537 100644 --- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs @@ -3,7 +3,7 @@ using System; using System.Linq; using System.Threading; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6137ddbf7..a6c22c93d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 4a721ca44..4f367fe2b 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -10,7 +10,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 244cc00be..d8bc0069c 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -2,7 +2,7 @@ using System; using System.Linq; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities diff --git a/MediaBrowser.Controller/Extensions/StringExtensions.cs b/MediaBrowser.Controller/Extensions/StringExtensions.cs index f1af01345..48bd9522a 100644 --- a/MediaBrowser.Controller/Extensions/StringExtensions.cs +++ b/MediaBrowser.Controller/Extensions/StringExtensions.cs @@ -21,27 +21,6 @@ namespace MediaBrowser.Controller.Extensions return Normalize(string.Concat(chars), NormalizationForm.FormC); } - /// <summary> - /// Counts the number of occurrences of [needle] in the string. - /// </summary> - /// <param name="value">The haystack to search in.</param> - /// <param name="needle">The character to search for.</param> - /// <returns>The number of occurrences of the [needle] character.</returns> - public static int Count(this ReadOnlySpan<char> value, char needle) - { - var count = 0; - var length = value.Length; - for (var i = 0; i < length; i++) - { - if (value[i] == needle) - { - count++; - } - } - - return count; - } - private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true) { if (stripStringOnFailure) diff --git a/MediaBrowser.Controller/Sorting/AlphanumComparator.cs b/MediaBrowser.Controller/Sorting/AlphanumComparator.cs deleted file mode 100644 index e00cadca2..000000000 --- a/MediaBrowser.Controller/Sorting/AlphanumComparator.cs +++ /dev/null @@ -1,137 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Sorting -{ - public class AlphanumComparator : IComparer<string?> - { - public static int CompareValues(string? s1, string? s2) - { - if (s1 == null && s2 == null) - { - return 0; - } - else if (s1 == null) - { - return -1; - } - else if (s2 == null) - { - return 1; - } - - int len1 = s1.Length; - int len2 = s2.Length; - - // Early return for empty strings - if (len1 == 0 && len2 == 0) - { - return 0; - } - else if (len1 == 0) - { - return -1; - } - else if (len2 == 0) - { - return 1; - } - - int pos1 = 0; - int pos2 = 0; - - do - { - int start1 = pos1; - int start2 = pos2; - - bool isNum1 = char.IsDigit(s1[pos1++]); - bool isNum2 = char.IsDigit(s2[pos2++]); - - while (pos1 < len1 && char.IsDigit(s1[pos1]) == isNum1) - { - pos1++; - } - - while (pos2 < len2 && char.IsDigit(s2[pos2]) == isNum2) - { - pos2++; - } - - var span1 = s1.AsSpan(start1, pos1 - start1); - var span2 = s2.AsSpan(start2, pos2 - start2); - - if (isNum1 && isNum2) - { - // Trim leading zeros so we can compare the length - // of the strings to find the largest number - span1 = span1.TrimStart('0'); - span2 = span2.TrimStart('0'); - var span1Len = span1.Length; - var span2Len = span2.Length; - if (span1Len < span2Len) - { - return -1; - } - else if (span1Len > span2Len) - { - return 1; - } - else if (span1Len >= 20) // Number is probably too big for a ulong - { - // Trim all the first digits that are the same - int i = 0; - while (i < span1Len && span1[i] == span2[i]) - { - i++; - } - - // If there are no more digits it's the same number - if (i == span1Len) - { - continue; - } - - // Only need to compare the most significant digit - span1 = span1.Slice(i, 1); - span2 = span2.Slice(i, 1); - } - - if (!ulong.TryParse(span1, out var num1) - || !ulong.TryParse(span2, out var num2)) - { - return 0; - } - else if (num1 < num2) - { - return -1; - } - else if (num1 > num2) - { - return 1; - } - } - else - { - int result = span1.CompareTo(span2, StringComparison.InvariantCulture); - if (result != 0) - { - return result; - } - } -#pragma warning disable SA1500 // TODO remove with StyleCop.Analyzers v1.2.0 https://github.com/DotNetAnalyzers/StyleCopAnalyzers/pull/3196 - } while (pos1 < len1 && pos2 < len2); -#pragma warning restore SA1500 - - return len1 - len2; - } - - /// <inheritdoc /> - public int Compare(string? x, string? y) - { - return CompareValues(x, y); - } - } -} diff --git a/MediaBrowser.Controller/Sorting/SortExtensions.cs b/MediaBrowser.Controller/Sorting/SortExtensions.cs index aa6ec513f..f9c0d39dd 100644 --- a/MediaBrowser.Controller/Sorting/SortExtensions.cs +++ b/MediaBrowser.Controller/Sorting/SortExtensions.cs @@ -1,16 +1,15 @@ -#nullable disable - #pragma warning disable CS1591 using System; using System.Collections.Generic; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Controller.Sorting { public static class SortExtensions { - private static readonly AlphanumComparator _comparer = new AlphanumComparator(); + private static readonly AlphanumericComparator _comparer = new AlphanumericComparator(); public static IEnumerable<T> OrderByString<T>(this IEnumerable<T> list, Func<T, string> getName) { diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index fdba64c4a..dc13bf4f6 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 3af618af8..412a95321 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -11,9 +11,9 @@ using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 639a34d99..24ceb1b57 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Threading; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core; diff --git a/MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs b/MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs deleted file mode 100644 index 7c627f0e3..000000000 --- a/MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs +++ /dev/null @@ -1,29 +0,0 @@ -#nullable disable -// THIS IS A HACK -// TODO: @bond Move to separate project - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Model.Entities -{ - /// <summary> - /// Converts an object to a lowercase string. - /// </summary> - /// <typeparam name="T">The object type.</typeparam> - public class JsonLowerCaseConverter<T> : JsonConverter<T> - { - /// <inheritdoc /> - public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return JsonSerializer.Deserialize<T>(ref reader, options); - } - - /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) - { - writer.WriteStringValue(value?.ToString().ToLowerInvariant()); - } - } -} diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index 8fed392b9..2b2bda12c 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -3,6 +3,7 @@ using System; using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Model.Entities diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 4db99f0b0..c475d905a 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -50,7 +50,8 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\Jellyfin.Data\Jellyfin.Data.csproj" /> + <ProjectReference Include="../Jellyfin.Data/Jellyfin.Data.csproj" /> + <ProjectReference Include="../src/Jellyfin.Extensions/Jellyfin.Extensions.csproj" /> </ItemGroup> </Project> diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index 85a28747f..36d8eeb40 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -6,7 +6,7 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 25bb3f9ce..9539c396d 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -11,7 +11,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index db8536cc9..aa61a56f6 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -6,7 +6,7 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index cbb61fa35..b2f05d76d 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs new file mode 100644 index 000000000..268538815 --- /dev/null +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs @@ -0,0 +1,46 @@ +#nullable enable + +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Providers.Plugins.Omdb +{ + /// <summary> + /// Converts a string <c>N/A</c> to <c>string.Empty</c>. + /// </summary> + public class JsonOmdbNotAvailableInt32Converter : JsonConverter<int?> + { + /// <inheritdoc /> + public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var str = reader.GetString(); + if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + var converter = TypeDescriptor.GetConverter(typeToConvert); + return (int?)converter.ConvertFromString(str); + } + + return JsonSerializer.Deserialize<int>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) + { + if (value.HasValue) + { + writer.WriteNumberValue(value.Value); + } + else + { + writer.WriteNullValue(); + } + } + } +} diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs new file mode 100644 index 000000000..c19589d45 --- /dev/null +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs @@ -0,0 +1,43 @@ +#nullable enable + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MediaBrowser.Providers.Plugins.Omdb +{ + /// <summary> + /// Converts a string <c>N/A</c> to <c>string.Empty</c>. + /// </summary> + public class JsonOmdbNotAvailableStringConverter : JsonConverter<string?> + { + /// <inheritdoc /> + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + + if (reader.TokenType == JsonTokenType.String) + { + // GetString can't return null here because we already handled it above + var str = reader.GetString()!; + if (str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + return str; + } + + return JsonSerializer.Deserialize<string?>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) + { + writer.WriteStringValue(value); + } + } +} diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 428b0ded1..78eea02e0 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 46d303890..5d9fd36d3 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Properties/AssemblyInfo.cs b/MediaBrowser.Providers/Properties/AssemblyInfo.cs index fe4749c79..bd301b5f0 100644 --- a/MediaBrowser.Providers/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Providers/Properties/AssemblyInfo.cs @@ -15,7 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] -[assembly: InternalsVisibleTo("Jellyfin.Common.Tests")] +[assembly: InternalsVisibleTo("Jellyfin.Providers.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index f6153dd53..63e78d15e 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/src/Jellyfin.Extensions/AlphanumericComparator.cs b/src/Jellyfin.Extensions/AlphanumericComparator.cs new file mode 100644 index 000000000..e3c81eba8 --- /dev/null +++ b/src/Jellyfin.Extensions/AlphanumericComparator.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Alphanumeric <see cref="IComparer{T}" />. + /// </summary> + public class AlphanumericComparator : IComparer<string?> + { + /// <summary> + /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. + /// </summary> + /// <param name="s1">The first object to compare.</param> + /// <param name="s2">The second object to compare.</param> + /// <returns>A signed integer that indicates the relative values of <c>x</c> and <c>y</c>.</returns> + public static int CompareValues(string? s1, string? s2) + { + if (s1 == null && s2 == null) + { + return 0; + } + else if (s1 == null) + { + return -1; + } + else if (s2 == null) + { + return 1; + } + + int len1 = s1.Length; + int len2 = s2.Length; + + // Early return for empty strings + if (len1 == 0 && len2 == 0) + { + return 0; + } + else if (len1 == 0) + { + return -1; + } + else if (len2 == 0) + { + return 1; + } + + int pos1 = 0; + int pos2 = 0; + + do + { + int start1 = pos1; + int start2 = pos2; + + bool isNum1 = char.IsDigit(s1[pos1++]); + bool isNum2 = char.IsDigit(s2[pos2++]); + + while (pos1 < len1 && char.IsDigit(s1[pos1]) == isNum1) + { + pos1++; + } + + while (pos2 < len2 && char.IsDigit(s2[pos2]) == isNum2) + { + pos2++; + } + + var span1 = s1.AsSpan(start1, pos1 - start1); + var span2 = s2.AsSpan(start2, pos2 - start2); + + if (isNum1 && isNum2) + { + // Trim leading zeros so we can compare the length + // of the strings to find the largest number + span1 = span1.TrimStart('0'); + span2 = span2.TrimStart('0'); + var span1Len = span1.Length; + var span2Len = span2.Length; + if (span1Len < span2Len) + { + return -1; + } + else if (span1Len > span2Len) + { + return 1; + } + else if (span1Len >= 20) // Number is probably too big for a ulong + { + // Trim all the first digits that are the same + int i = 0; + while (i < span1Len && span1[i] == span2[i]) + { + i++; + } + + // If there are no more digits it's the same number + if (i == span1Len) + { + continue; + } + + // Only need to compare the most significant digit + span1 = span1.Slice(i, 1); + span2 = span2.Slice(i, 1); + } + + if (!ulong.TryParse(span1, out var num1) + || !ulong.TryParse(span2, out var num2)) + { + return 0; + } + else if (num1 < num2) + { + return -1; + } + else if (num1 > num2) + { + return 1; + } + } + else + { + int result = span1.CompareTo(span2, StringComparison.InvariantCulture); + if (result != 0) + { + return result; + } + } +#pragma warning disable SA1500 // TODO remove with StyleCop.Analyzers v1.2.0 https://github.com/DotNetAnalyzers/StyleCopAnalyzers/pull/3196 + } while (pos1 < len1 && pos2 < len2); +#pragma warning restore SA1500 + + return len1 - len2; + } + + /// <inheritdoc /> + public int Compare(string? x, string? y) + { + return CompareValues(x, y); + } + } +} diff --git a/src/Jellyfin.Extensions/CopyToExtensions.cs b/src/Jellyfin.Extensions/CopyToExtensions.cs new file mode 100644 index 000000000..72d37b5b6 --- /dev/null +++ b/src/Jellyfin.Extensions/CopyToExtensions.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Provides <c>CopyTo</c> extensions methods for <see cref="IReadOnlyList{T}" />. + /// </summary> + public static class CopyToExtensions + { + /// <summary> + /// Copies all the elements of the current collection to the specified list + /// starting at the specified destination array index. The index is specified as a 32-bit integer. + /// </summary> + /// <param name="source">The current collection that is the source of the elements.</param> + /// <param name="destination">The list that is the destination of the elements copied from the current collection.</param> + /// <param name="index">A 32-bit integer that represents the index in <c>destination</c> at which copying begins.</param> + /// <typeparam name="T">The type of the array.</typeparam> + public static void CopyTo<T>(this IReadOnlyList<T> source, IList<T> destination, int index = 0) + { + for (int i = 0; i < source.Count; i++) + { + destination[index + i] = source[i]; + } + } + } +} diff --git a/src/Jellyfin.Extensions/EnumerableExtensions.cs b/src/Jellyfin.Extensions/EnumerableExtensions.cs new file mode 100644 index 000000000..b5fe93357 --- /dev/null +++ b/src/Jellyfin.Extensions/EnumerableExtensions.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Static extensions for the <see cref="IEnumerable{T}"/> interface. + /// </summary> + public static class EnumerableExtensions + { + /// <summary> + /// Determines whether the value is contained in the source collection. + /// </summary> + /// <param name="source">An instance of the <see cref="IEnumerable{String}"/> interface.</param> + /// <param name="value">The value to look for in the collection.</param> + /// <param name="stringComparison">The string comparison.</param> + /// <returns>A value indicating whether the value is contained in the collection.</returns> + /// <exception cref="ArgumentNullException">The source is null.</exception> + public static bool Contains(this IEnumerable<string> source, ReadOnlySpan<char> value, StringComparison stringComparison) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (source is IList<string> list) + { + int len = list.Count; + for (int i = 0; i < len; i++) + { + if (value.Equals(list[i], stringComparison)) + { + return true; + } + } + + return false; + } + + foreach (string element in source) + { + if (value.Equals(element, stringComparison)) + { + return true; + } + } + + return false; + } + } +} diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj new file mode 100644 index 000000000..c7b9a4ad0 --- /dev/null +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -0,0 +1,30 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <GenerateAssemblyInfo>false</GenerateAssemblyInfo> + <GenerateDocumentationFile>true</GenerateDocumentationFile> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../../jellyfin.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <PropertyGroup> + <Authors>Jellyfin Contributors</Authors> + <RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl> + <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression> + </PropertyGroup> + + <ItemGroup> + <Compile Include="../../SharedVersion.cs" /> + </ItemGroup> + + <!-- Code Analyzers--> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <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> + +</Project> diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs new file mode 100644 index 000000000..c2543cf7c --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts a number to a boolean. + /// This is needed for HDHomerun. + /// </summary> + public class JsonBoolNumberConverter : JsonConverter<bool> + { + /// <inheritdoc /> + public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + { + return Convert.ToBoolean(reader.GetInt32()); + } + + return reader.GetBoolean(); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) + { + writer.WriteBooleanValue(value); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs new file mode 100644 index 000000000..44980ec02 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Convert comma delimited string to array of type. + /// </summary> + /// <typeparam name="T">Type to convert to.</typeparam> + public sealed class JsonCommaDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> + { + /// <summary> + /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class. + /// </summary> + public JsonCommaDelimitedArrayConverter() : base() + { + } + + /// <inheritdoc /> + protected override char Delimiter => ','; + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs new file mode 100644 index 000000000..cc9311a24 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Json comma delimited array converter factory. + /// </summary> + /// <remarks> + /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + /// </remarks> + public class JsonCommaDelimitedArrayConverterFactory : JsonConverterFactory + { + /// <inheritdoc /> + public override bool CanConvert(Type typeToConvert) + { + return true; + } + + /// <inheritdoc /> + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; + return (JsonConverter?)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs new file mode 100644 index 000000000..8ae080b15 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Legacy DateTime converter. + /// Milliseconds aren't output if zero by default. + /// </summary> + public class JsonDateTimeConverter : JsonConverter<DateTime> + { + /// <inheritdoc /> + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetDateTime(); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + if (value.Millisecond == 0) + { + // Remaining ticks value will be 0, manually format. + writer.WriteStringValue(value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffZ", CultureInfo.InvariantCulture)); + } + else + { + writer.WriteStringValue(value); + } + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs new file mode 100644 index 000000000..c39805aa3 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs @@ -0,0 +1,81 @@ +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Convert delimited string to array of type. + /// </summary> + /// <typeparam name="T">Type to convert to.</typeparam> + public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]?> + { + private readonly TypeConverter _typeConverter; + + /// <summary> + /// Initializes a new instance of the <see cref="JsonDelimitedArrayConverter{T}"/> class. + /// </summary> + protected JsonDelimitedArrayConverter() + { + _typeConverter = TypeDescriptor.GetConverter(typeof(T)); + } + + /// <summary> + /// Gets the array delimiter. + /// </summary> + protected virtual char Delimiter { get; } + + /// <inheritdoc /> + public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + // GetString can't return null here because we already handled it above + var stringEntries = reader.GetString()?.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries); + if (stringEntries == null || stringEntries.Length == 0) + { + return Array.Empty<T>(); + } + + var parsedValues = new object[stringEntries.Length]; + var convertedCount = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + try + { + parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()); + convertedCount++; + } + catch (FormatException) + { + // TODO log when upgraded to .Net6 + // https://github.com/dotnet/runtime/issues/42975 + // _logger.LogDebug(e, "Error converting value."); + } + } + + var typedValues = new T[convertedCount]; + var typedValueIndex = 0; + for (var i = 0; i < stringEntries.Length; i++) + { + if (parsedValues[i] != null) + { + typedValues.SetValue(parsedValues[i], typedValueIndex); + typedValueIndex++; + } + } + + return typedValues; + } + + return JsonSerializer.Deserialize<T[]>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, T[]? value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs new file mode 100644 index 000000000..be94dd519 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts a GUID object or value to/from JSON. + /// </summary> + public class JsonGuidConverter : JsonConverter<Guid> + { + /// <inheritdoc /> + public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var guidStr = reader.GetString(); + return guidStr == null ? Guid.Empty : new Guid(guidStr); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("N", CultureInfo.InvariantCulture)); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs new file mode 100644 index 000000000..cd582ced6 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts an object to a lowercase string. + /// </summary> + /// <typeparam name="T">The object type.</typeparam> + public class JsonLowerCaseConverter<T> : JsonConverter<T> + { + /// <inheritdoc /> + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return JsonSerializer.Deserialize<T>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + writer.WriteStringValue(value?.ToString()?.ToLowerInvariant()); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs new file mode 100644 index 000000000..6192d1598 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts a GUID object or value to/from JSON. + /// </summary> + public class JsonNullableGuidConverter : JsonConverter<Guid?> + { + /// <inheritdoc /> + public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var guidStr = reader.GetString(); + return guidStr == null ? null : new Guid(guidStr); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, Guid? value, JsonSerializerOptions options) + { + if (value == null || value == Guid.Empty) + { + writer.WriteNullValue(); + } + else + { + writer.WriteStringValue(value.Value.ToString("N", CultureInfo.InvariantCulture)); + } + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs new file mode 100644 index 000000000..6de238b39 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs @@ -0,0 +1,45 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts a nullable struct or value to/from JSON. + /// Required - some clients send an empty string. + /// </summary> + /// <typeparam name="TStruct">The struct type.</typeparam> + public class JsonNullableStructConverter<TStruct> : JsonConverter<TStruct?> + where TStruct : struct + { + /// <inheritdoc /> + public override TStruct? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + + // Token is empty string. + if (reader.TokenType == JsonTokenType.String && ((reader.HasValueSequence && reader.ValueSequence.IsEmpty) || reader.ValueSpan.IsEmpty)) + { + return null; + } + + return JsonSerializer.Deserialize<TStruct>(ref reader, options); + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, TStruct? value, JsonSerializerOptions options) + { + if (value.HasValue) + { + JsonSerializer.Serialize(writer, value.Value, options); + } + else + { + writer.WriteNullValue(); + } + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs new file mode 100644 index 000000000..e7749589a --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs @@ -0,0 +1,27 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Json nullable struct converter factory. + /// </summary> + public class JsonNullableStructConverterFactory : JsonConverterFactory + { + /// <inheritdoc /> + public override bool CanConvert(Type typeToConvert) + { + return typeToConvert.IsGenericType + && typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>) + && typeToConvert.GenericTypeArguments[0].IsValueType; + } + + /// <inheritdoc /> + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var structType = typeToConvert.GenericTypeArguments[0]; + return (JsonConverter?)Activator.CreateInstance(typeof(JsonNullableStructConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs new file mode 100644 index 000000000..e3e492e24 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.ComponentModel; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Convert Pipe delimited string to array of type. + /// </summary> + /// <typeparam name="T">Type to convert to.</typeparam> + public sealed class JsonPipeDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> + { + /// <summary> + /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class. + /// </summary> + public JsonPipeDelimitedArrayConverter() : base() + { + } + + /// <inheritdoc /> + protected override char Delimiter => '|'; + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs new file mode 100644 index 000000000..579674f18 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Json Pipe delimited array converter factory. + /// </summary> + /// <remarks> + /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + /// </remarks> + public class JsonPipeDelimitedArrayConverterFactory : JsonConverterFactory + { + /// <inheritdoc /> + public override bool CanConvert(Type typeToConvert) + { + return true; + } + + /// <inheritdoc /> + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; + return (JsonConverter?)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType)); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs new file mode 100644 index 000000000..1a7a8c4f5 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Buffers; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converter to allow the serializer to read strings. + /// </summary> + public class JsonStringConverter : JsonConverter<string?> + { + /// <inheritdoc /> + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.Null => null, + JsonTokenType.String => reader.GetString(), + _ => GetRawValue(reader) + }; + } + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) + { + writer.WriteStringValue(value); + } + + private static string GetRawValue(Utf8JsonReader reader) + { + var utf8Bytes = reader.HasValueSequence + ? reader.ValueSequence.ToArray() + : reader.ValueSpan; + return Encoding.UTF8.GetString(utf8Bytes); + } + } +} diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs new file mode 100644 index 000000000..51ffec1cb --- /dev/null +++ b/src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs @@ -0,0 +1,23 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Jellyfin.Extensions.Json.Converters +{ + /// <summary> + /// Converts a Version object or value to/from JSON. + /// </summary> + /// <remarks> + /// Required to send <see cref="Version"/> as a string instead of an object. + /// </remarks> + public class JsonVersionConverter : JsonConverter<Version> + { + /// <inheritdoc /> + public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => new Version(reader.GetString()!); // Will throw ArgumentNullException on null + + /// <inheritdoc /> + public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString()); + } +} diff --git a/src/Jellyfin.Extensions/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs new file mode 100644 index 000000000..f4ec91123 --- /dev/null +++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs @@ -0,0 +1,90 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; + +namespace Jellyfin.Extensions.Json +{ + /// <summary> + /// Helper class for having compatible JSON throughout the codebase. + /// </summary> + public static class JsonDefaults + { + /// <summary> + /// Pascal case json profile media type. + /// </summary> + public const string PascalCaseMediaType = "application/json; profile=\"PascalCase\""; + + /// <summary> + /// Camel case json profile media type. + /// </summary> + public const string CamelCaseMediaType = "application/json; profile=\"CamelCase\""; + + /// <summary> + /// When changing these options, update + /// Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs + /// -> AddJellyfinApi + /// -> AddJsonOptions. + /// </summary> + private static readonly JsonSerializerOptions _jsonSerializerOptions = new () + { + ReadCommentHandling = JsonCommentHandling.Disallow, + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + Converters = + { + new JsonGuidConverter(), + new JsonNullableGuidConverter(), + new JsonVersionConverter(), + new JsonStringEnumConverter(), + new JsonNullableStructConverterFactory(), + new JsonBoolNumberConverter(), + new JsonDateTimeConverter(), + new JsonStringConverter() + } + }; + + private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new (_jsonSerializerOptions) + { + PropertyNamingPolicy = null + }; + + private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new (_jsonSerializerOptions) + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + /// <summary> + /// Gets the default <see cref="JsonSerializerOptions" /> options. + /// </summary> + /// <remarks> + /// The return value must not be modified. + /// If the defaults must be modified the author must use the copy constructor. + /// </remarks> + /// <returns>The default <see cref="JsonSerializerOptions" /> options.</returns> + public static JsonSerializerOptions Options + => _jsonSerializerOptions; + + /// <summary> + /// Gets camelCase json options. + /// </summary> + /// <remarks> + /// The return value must not be modified. + /// If the defaults must be modified the author must use the copy constructor. + /// </remarks> + /// <returns>The camelCase <see cref="JsonSerializerOptions" /> options.</returns> + public static JsonSerializerOptions CamelCaseOptions + => _camelCaseJsonSerializerOptions; + + /// <summary> + /// Gets PascalCase json options. + /// </summary> + /// <remarks> + /// The return value must not be modified. + /// If the defaults must be modified the author must use the copy constructor. + /// </remarks> + /// <returns>The PascalCase <see cref="JsonSerializerOptions" /> options.</returns> + public static JsonSerializerOptions PascalCaseOptions + => _pascalCaseJsonSerializerOptions; + } +} diff --git a/src/Jellyfin.Extensions/ShuffleExtensions.cs b/src/Jellyfin.Extensions/ShuffleExtensions.cs new file mode 100644 index 000000000..4e481983f --- /dev/null +++ b/src/Jellyfin.Extensions/ShuffleExtensions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Provides <c>Shuffle</c> extensions methods for <see cref="IList{T}" />. + /// </summary> + public static class ShuffleExtensions + { + private static readonly Random _rng = new Random(); + + /// <summary> + /// Shuffles the items in a list. + /// </summary> + /// <param name="list">The list that should get shuffled.</param> + /// <typeparam name="T">The type.</typeparam> + public static void Shuffle<T>(this IList<T> list) + { + list.Shuffle(_rng); + } + + /// <summary> + /// Shuffles the items in a list. + /// </summary> + /// <param name="list">The list that should get shuffled.</param> + /// <param name="rng">The random number generator to use.</param> + /// <typeparam name="T">The type.</typeparam> + public static void Shuffle<T>(this IList<T> list, Random rng) + { + int n = list.Count; + while (n > 1) + { + int k = rng.Next(n--); + T value = list[k]; + list[k] = list[n]; + list[n] = value; + } + } + } +} diff --git a/src/Jellyfin.Extensions/SplitStringExtensions.cs b/src/Jellyfin.Extensions/SplitStringExtensions.cs new file mode 100644 index 000000000..5fa5c0123 --- /dev/null +++ b/src/Jellyfin.Extensions/SplitStringExtensions.cs @@ -0,0 +1,115 @@ +/* +MIT License + +Copyright (c) 2019 Gérald Barré + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +// TODO: remove when analyzer is fixed: https://github.com/dotnet/roslyn-analyzers/issues/5158 +#pragma warning disable CA1034 // Nested types should not be visible + +using System; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Extension class for splitting lines without unnecessary allocations. + /// </summary> + public static class SplitStringExtensions + { + /// <summary> + /// Creates a new string split enumerator. + /// </summary> + /// <param name="str">The string to split.</param> + /// <param name="separator">The separator to split on.</param> + /// <returns>The enumerator struct.</returns> + [Pure] + public static Enumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); + + /// <summary> + /// Creates a new span split enumerator. + /// </summary> + /// <param name="str">The span to split.</param> + /// <param name="separator">The separator to split on.</param> + /// <returns>The enumerator struct.</returns> + [Pure] + public static Enumerator Split(this ReadOnlySpan<char> str, char separator) => new (str, separator); + + /// <summary> + /// Provides an enumerator for the substrings seperated by the separator. + /// </summary> + [StructLayout(LayoutKind.Auto)] + public ref struct Enumerator + { + private readonly char _separator; + private ReadOnlySpan<char> _str; + + /// <summary> + /// Initializes a new instance of the <see cref="Enumerator"/> struct. + /// </summary> + /// <param name="str">The span to split.</param> + /// <param name="separator">The separator to split on.</param> + public Enumerator(ReadOnlySpan<char> str, char separator) + { + _str = str; + _separator = separator; + Current = default; + } + + /// <summary> + /// Gets a reference to the item at the current position of the enumerator. + /// </summary> + public ReadOnlySpan<char> Current { get; private set; } + + /// <summary> + /// Returns <c>this</c>. + /// </summary> + /// <returns><c>this</c>.</returns> + public readonly Enumerator GetEnumerator() => this; + + /// <summary> + /// Advances the enumerator to the next item. + /// </summary> + /// <returns><c>true</c> if there is a next element; otherwise <c>false</c>.</returns> + public bool MoveNext() + { + if (_str.Length == 0) + { + return false; + } + + var span = _str; + var index = span.IndexOf(_separator); + if (index == -1) + { + _str = ReadOnlySpan<char>.Empty; + Current = span; + return true; + } + + Current = span.Slice(0, index); + _str = span[(index + 1)..]; + return true; + } + } + } +} diff --git a/src/Jellyfin.Extensions/StreamExtensions.cs b/src/Jellyfin.Extensions/StreamExtensions.cs new file mode 100644 index 000000000..9751d9d42 --- /dev/null +++ b/src/Jellyfin.Extensions/StreamExtensions.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Class BaseExtensions. + /// </summary> + public static class StreamExtensions + { + /// <summary> + /// Reads all lines in the <see cref="Stream" />. + /// </summary> + /// <param name="stream">The <see cref="Stream" /> to read from.</param> + /// <returns>All lines in the stream.</returns> + public static string[] ReadAllLines(this Stream stream) + => ReadAllLines(stream, Encoding.UTF8); + + /// <summary> + /// Reads all lines in the <see cref="Stream" />. + /// </summary> + /// <param name="stream">The <see cref="Stream" /> to read from.</param> + /// <param name="encoding">The character encoding to use.</param> + /// <returns>All lines in the stream.</returns> + public static string[] ReadAllLines(this Stream stream, Encoding encoding) + { + using (StreamReader reader = new StreamReader(stream, encoding)) + { + return ReadAllLines(reader).ToArray(); + } + } + + /// <summary> + /// Reads all lines in the <see cref="TextReader" />. + /// </summary> + /// <param name="reader">The <see cref="TextReader" /> to read from.</param> + /// <returns>All lines in the stream.</returns> + public static IEnumerable<string> ReadAllLines(this TextReader reader) + { + string? line; + while ((line = reader.ReadLine()) != null) + { + yield return line; + } + } + + /// <summary> + /// Reads all lines in the <see cref="TextReader" />. + /// </summary> + /// <param name="reader">The <see cref="TextReader" /> to read from.</param> + /// <returns>All lines in the stream.</returns> + public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader) + { + string? line; + while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null) + { + yield return line; + } + } + } +} diff --git a/src/Jellyfin.Extensions/StringBuilderExtensions.cs b/src/Jellyfin.Extensions/StringBuilderExtensions.cs new file mode 100644 index 000000000..02ff7cc1f --- /dev/null +++ b/src/Jellyfin.Extensions/StringBuilderExtensions.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Text; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Extension methods for the <see cref="StringBuilder"/> class. + /// </summary> + public static class StringBuilderExtensions + { + /// <summary> + /// Concatenates and appends the members of a collection in single quotes using the specified delimiter. + /// </summary> + /// <param name="builder">The string builder.</param> + /// <param name="delimiter">The character delimiter.</param> + /// <param name="values">The collection of strings to concatenate.</param> + /// <returns>The updated string builder.</returns> + public static StringBuilder AppendJoinInSingleQuotes(this StringBuilder builder, char delimiter, IReadOnlyList<string> values) + { + var len = values.Count; + for (var i = 0; i < len; i++) + { + builder.Append('\'') + .Append(values[i]) + .Append('\'') + .Append(delimiter); + } + + // remove last , + builder.Length--; + + return builder; + } + } +} diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs new file mode 100644 index 000000000..acc695ed2 --- /dev/null +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -0,0 +1,31 @@ +using System; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Provides extensions methods for <see cref="string" />. + /// </summary> + public static class StringExtensions + { + /// <summary> + /// Counts the number of occurrences of [needle] in the string. + /// </summary> + /// <param name="value">The haystack to search in.</param> + /// <param name="needle">The character to search for.</param> + /// <returns>The number of occurrences of the [needle] character.</returns> + public static int Count(this ReadOnlySpan<char> value, char needle) + { + var count = 0; + var length = value.Length; + for (var i = 0; i < length; i++) + { + if (value[i] == needle) + { + count++; + } + } + + return count; + } + } +} diff --git a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs b/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs deleted file mode 100644 index 9903409fa..000000000 --- a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Common.Extensions; -using Xunit; - -namespace Jellyfin.Common.Tests.Extensions -{ - public static class CopyToExtensionsTests - { - public static IEnumerable<object[]> CopyTo_Valid_Correct_TestData() - { - yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 } }; - yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } }; - } - - [Theory] - [MemberData(nameof(CopyTo_Valid_Correct_TestData))] - public static void CopyTo_Valid_Correct<T>(IReadOnlyList<T> source, IList<T> destination, int index, IList<T> expected) - { - source.CopyTo(destination, index); - Assert.Equal(expected, destination); - } - - public static IEnumerable<object[]> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData() - { - yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 }; - yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 }; - yield return new object[] { new[] { 0, 1, 2 }, Array.Empty<int>(), 0 }; - yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 }; - yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 }; - } - - [Theory] - [MemberData(nameof(CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData))] - public static void CopyTo_Invalid_ThrowsArgumentOutOfRangeException<T>(IReadOnlyList<T> source, IList<T> destination, int index) - { - Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, index)); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs b/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs deleted file mode 100644 index cbdbcf112..000000000 --- a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using MediaBrowser.Common.Extensions; -using Xunit; - -namespace Jellyfin.Common.Tests.Extensions -{ - public static class ShuffleExtensionsTests - { - private static readonly Random _rng = new Random(); - - [Fact] - public static void Shuffle_Valid_Correct() - { - byte[] original = new byte[1 << 6]; - _rng.NextBytes(original); - byte[] shuffled = (byte[])original.Clone(); - shuffled.Shuffle(); - - Assert.NotEqual(original, shuffled); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs deleted file mode 100644 index 7629d9912..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Globalization; -using System.Text.Json; -using FsCheck; -using FsCheck.Xunit; -using MediaBrowser.Common.Json.Converters; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonBoolNumberTests - { - private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() - { - Converters = - { - new JsonBoolNumberConverter() - } - }; - - [Theory] - [InlineData("1", true)] - [InlineData("0", false)] - [InlineData("2", true)] - [InlineData("true", true)] - [InlineData("false", false)] - public void Deserialize_Number_Valid_Success(string input, bool? output) - { - var value = JsonSerializer.Deserialize<bool>(input, _jsonOptions); - Assert.Equal(value, output); - } - - [Theory] - [InlineData(true, "true")] - [InlineData(false, "false")] - public void Serialize_Bool_Success(bool input, string output) - { - var value = JsonSerializer.Serialize(input, _jsonOptions); - Assert.Equal(value, output); - } - - [Property] - public Property Deserialize_NonZeroInt_True(NonZeroInt input) - => JsonSerializer.Deserialize<bool>(input.ToString(), _jsonOptions).ToProperty(); - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs deleted file mode 100644 index ca300401d..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Text.Json; -using System.Text.Json.Serialization; -using Jellyfin.Common.Tests.Models; -using MediaBrowser.Model.Session; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public static class JsonCommaDelimitedArrayTests - { - [Fact] - public static void Deserialize_String_Null_Success() - { - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": null }", options); - Assert.Null(value?.Value); - } - - [Fact] - public static void Deserialize_Empty_Success() - { - var desiredValue = new GenericBodyArrayModel<string> - { - Value = Array.Empty<string>() - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": """" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_String_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_String_Space_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_EmptyEntry_Success() - { - var desiredValue = new GenericBodyArrayModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Invalid_Success() - { - var desiredValue = new GenericBodyArrayModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Space_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_String_Array_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Array_Valid_Success() - { - var desiredValue = new GenericBodyArrayModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs deleted file mode 100644 index 34ad9bac7..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using Jellyfin.Common.Tests.Models; -using MediaBrowser.Model.Session; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public static class JsonCommaDelimitedIReadOnlyListTests - { - [Fact] - public static void Deserialize_String_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_String_Space_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Space_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_String_Array_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<string> - { - Value = new[] { "a", "b", "c" } - }; - - var options = new JsonSerializerOptions(); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - - [Fact] - public static void Deserialize_GenericCommandType_Array_Valid_Success() - { - var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> - { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); - var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); - Assert.Equal(desiredValue.Value, value?.Value); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs deleted file mode 100644 index dbfad3c2f..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Text.Json; -using MediaBrowser.Common.Json.Converters; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonGuidConverterTests - { - private readonly JsonSerializerOptions _options; - - public JsonGuidConverterTests() - { - _options = new JsonSerializerOptions(); - _options.Converters.Add(new JsonGuidConverter()); - } - - [Fact] - public void Deserialize_Valid_Success() - { - Guid value = JsonSerializer.Deserialize<Guid>(@"""a852a27afe324084ae66db579ee3ee18""", _options); - Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value); - } - - [Fact] - public void Deserialize_ValidDashed_Success() - { - Guid value = JsonSerializer.Deserialize<Guid>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options); - Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value); - } - - [Fact] - public void Roundtrip_Valid_Success() - { - Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18"); - string value = JsonSerializer.Serialize(guid, _options); - Assert.Equal(guid, JsonSerializer.Deserialize<Guid>(value, _options)); - } - - [Fact] - public void Deserialize_Null_EmptyGuid() - { - Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid>("null", _options)); - } - - [Fact] - public void Serialize_EmptyGuid_EmptyGuid() - { - Assert.Equal($"\"{Guid.Empty:N}\"", JsonSerializer.Serialize(Guid.Empty, _options)); - } - - [Fact] - public void Serialize_Valid_NoDash_Success() - { - var guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); - var str = JsonSerializer.Serialize(guid, _options); - Assert.Equal($"\"{guid:N}\"", str); - } - - [Fact] - public void Serialize_Nullable_Success() - { - Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); - var str = JsonSerializer.Serialize(guid, _options); - Assert.Equal($"\"{guid:N}\"", str); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs deleted file mode 100644 index cb3b66c4c..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Text.Json; -using MediaBrowser.Common.Json.Converters; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonNullableGuidConverterTests - { - private readonly JsonSerializerOptions _options; - - public JsonNullableGuidConverterTests() - { - _options = new JsonSerializerOptions(); - _options.Converters.Add(new JsonNullableGuidConverter()); - } - - [Fact] - public void Deserialize_Valid_Success() - { - Guid? value = JsonSerializer.Deserialize<Guid?>(@"""a852a27afe324084ae66db579ee3ee18""", _options); - Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value); - } - - [Fact] - public void Deserialize_ValidDashed_Success() - { - Guid? value = JsonSerializer.Deserialize<Guid?>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options); - Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value); - } - - [Fact] - public void Roundtrip_Valid_Success() - { - Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18"); - string value = JsonSerializer.Serialize(guid, _options); - Assert.Equal(guid, JsonSerializer.Deserialize<Guid?>(value, _options)); - } - - [Fact] - public void Deserialize_Null_Null() - { - Assert.Null(JsonSerializer.Deserialize<Guid?>("null", _options)); - } - - [Fact] - public void Deserialize_EmptyGuid_EmptyGuid() - { - Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", _options)); - } - - [Fact] - public void Serialize_EmptyGuid_Null() - { - Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, _options)); - } - - [Fact] - public void Serialize_Null_Null() - { - Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, _options)); - } - - [Fact] - public void Serialize_Valid_NoDash_Success() - { - var guid = (Guid?)new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); - var str = JsonSerializer.Serialize(guid, _options); - Assert.Equal($"\"{guid:N}\"", str); - } - - [Fact] - public void Serialize_Nullable_Success() - { - Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); - var str = JsonSerializer.Serialize(guid, _options); - Assert.Equal($"\"{guid:N}\"", str); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs deleted file mode 100644 index efe8063a0..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; -using MediaBrowser.Providers.Plugins.Omdb; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonOmdbConverterTests - { - private readonly JsonSerializerOptions _options; - - public JsonOmdbConverterTests() - { - _options = new JsonSerializerOptions(); - _options.Converters.Add(new JsonOmdbNotAvailableStringConverter()); - _options.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); - _options.NumberHandling = JsonNumberHandling.AllowReadingFromString; - } - - [Fact] - public void Deserialize_Omdb_Response_Not_Available_Success() - { - const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; - var seasonRootObject = JsonSerializer.Deserialize<OmdbProvider.RootObject>(Input, _options); - Assert.NotNull(seasonRootObject); - Assert.Null(seasonRootObject?.Awards); - Assert.Null(seasonRootObject?.Episode); - Assert.Null(seasonRootObject?.Metascore); - } - - [Theory] - [InlineData("\"N/A\"")] - [InlineData("null")] - public void Deserialization_To_Nullable_Int_Shoud_Be_Null(string input) - { - var result = JsonSerializer.Deserialize<int?>(input, _options); - Assert.Null(result); - } - - [Theory] - [InlineData("\"8\"", 8)] - [InlineData("8", 8)] - public void Deserialize_NullableInt_Success(string input, int? expected) - { - var result = JsonSerializer.Deserialize<int?>(input, _options); - Assert.Equal(result, expected); - } - - [Theory] - [InlineData("\"N/A\"")] - [InlineData("null")] - public void Deserialization_To_Nullable_String_Shoud_Be_Null(string input) - { - var result = JsonSerializer.Deserialize<string?>(input, _options); - Assert.Null(result); - } - - [Theory] - [InlineData("\"Jellyfin\"", "Jellyfin")] - public void Deserialize_Normal_String_Success(string input, string expected) - { - var result = JsonSerializer.Deserialize<string?>(input, _options); - Assert.Equal(expected, result); - } - - [Fact] - public void Roundtrip_Valid_Success() - { - const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; - var trip1 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(Input, _options); - Assert.NotNull(trip1); - Assert.NotNull(trip1?.Title); - Assert.Null(trip1?.Awards); - Assert.Null(trip1?.Episode); - Assert.Null(trip1?.Metascore); - - var serializedTrip1 = JsonSerializer.Serialize(trip1!, _options); - var trip2 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(serializedTrip1, _options); - Assert.NotNull(trip2); - Assert.NotNull(trip2?.Title); - Assert.Null(trip2?.Awards); - Assert.Null(trip2?.Episode); - Assert.Null(trip2?.Metascore); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs deleted file mode 100644 index 2b23c6705..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Text.Json; -using MediaBrowser.Common.Json.Converters; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonStringConverterTests - { - private readonly JsonSerializerOptions _jsonSerializerOptions = new () - { - Converters = - { - new JsonStringConverter() - } - }; - - [Theory] - [InlineData("\"test\"", "test")] - [InlineData("123", "123")] - [InlineData("123.45", "123.45")] - [InlineData("true", "true")] - [InlineData("false", "false")] - public void Deserialize_String_Valid_Success(string input, string output) - { - var deserialized = JsonSerializer.Deserialize<string>(input, _jsonSerializerOptions); - Assert.Equal(deserialized, output); - } - - [Fact] - public void Deserialize_Int32asInt32_Valid_Success() - { - const string? input = "123"; - const int output = 123; - var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions); - Assert.Equal(deserialized, output); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs deleted file mode 100644 index f2cefdbf8..000000000 --- a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Text.Json; -using MediaBrowser.Common.Json.Converters; -using Xunit; - -namespace Jellyfin.Common.Tests.Json -{ - public class JsonVersionConverterTests - { - private readonly JsonSerializerOptions _options; - - public JsonVersionConverterTests() - { - _options = new JsonSerializerOptions(); - _options.Converters.Add(new JsonVersionConverter()); - } - - [Fact] - public void Deserialize_Version_Success() - { - var input = "\"1.025.222\""; - var output = new Version(1, 25, 222); - var deserializedInput = JsonSerializer.Deserialize<Version>(input, _options); - Assert.Equal(output, deserializedInput); - } - - [Fact] - public void Serialize_Version_Success() - { - var input = new Version(1, 09, 59); - var output = "\"1.9.59\""; - var serializedInput = JsonSerializer.Serialize(input, _options); - Assert.Equal(output, serializedInput); - } - } -} diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs b/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs deleted file mode 100644 index 276e1bfbe..000000000 --- a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; - -namespace Jellyfin.Common.Tests.Models -{ - /// <summary> - /// The generic body model. - /// </summary> - /// <typeparam name="T">The value type.</typeparam> - public class GenericBodyArrayModel<T> - { - /// <summary> - /// Gets or sets the value. - /// </summary> - [SuppressMessage("Microsoft.Performance", "CA1819:Properties should not return arrays", MessageId = "Value", Justification = "Imported from ServiceStack")] - [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))] - public T[] Value { get; set; } = default!; - } -} diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs b/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs deleted file mode 100644 index 627454b25..000000000 --- a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; - -namespace Jellyfin.Common.Tests.Models -{ - /// <summary> - /// The generic body <c>IReadOnlyList</c> model. - /// </summary> - /// <typeparam name="T">The value type.</typeparam> - public class GenericBodyIReadOnlyListModel<T> - { - /// <summary> - /// Gets or sets the value. - /// </summary> - [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))] - public IReadOnlyList<T> Value { get; set; } = default!; - } -} diff --git a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs b/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs deleted file mode 100644 index 0adf098c3..000000000 --- a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Linq; -using MediaBrowser.Controller.Sorting; -using Xunit; - -namespace Jellyfin.Controller.Tests -{ - public class AlphanumComparatorTests - { - // InlineData is pre-sorted - [Theory] - [InlineData(null, "", "1", "9", "10", "a", "z")] - [InlineData("50F", "100F", "SR9", "SR100")] - [InlineData("image-1.jpg", "image-02.jpg", "image-4.jpg", "image-9.jpg", "image-10.jpg", "image-11.jpg", "image-22.jpg")] - [InlineData("Hard drive 2GB", "Hard drive 20GB")] - [InlineData("b", "e", "è", "ě", "f", "g", "k")] - [InlineData("123456789", "123456789a", "abc", "abcd")] - [InlineData("12345678912345678912345678913234567891", "123456789123456789123456789132345678912")] - [InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567891")] - [InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567892")] - [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891a")] - [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")] - public void AlphanumComparatorTest(params string?[] strings) - { - var copy = strings.Reverse().ToArray(); - Array.Sort(copy, new AlphanumComparator()); - Assert.True(strings.SequenceEqual(copy)); - } - } -} diff --git a/tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs b/tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs deleted file mode 100644 index 576c0a49b..000000000 --- a/tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using MediaBrowser.Controller.Extensions; -using Xunit; - -namespace Jellyfin.Controller.Extensions.Tests -{ - public class StringExtensionsTests - { - [Theory] - [InlineData("", '_', 0)] - [InlineData("___", '_', 3)] - [InlineData("test\x00", '\x00', 1)] - [InlineData("Imdb=tt0119567|Tmdb=330|TmdbCollection=328", '|', 2)] - public void ReadOnlySpan_Count_Success(string str, char needle, int count) - { - Assert.Equal(count, str.AsSpan().Count(needle)); - } - } -} diff --git a/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs new file mode 100644 index 000000000..7730841a1 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; +using Xunit; + +namespace Jellyfin.Extensions.Tests +{ + public class AlphanumericComparatorTests + { + // InlineData is pre-sorted + [Theory] + [InlineData(null, "", "1", "9", "10", "a", "z")] + [InlineData("50F", "100F", "SR9", "SR100")] + [InlineData("image-1.jpg", "image-02.jpg", "image-4.jpg", "image-9.jpg", "image-10.jpg", "image-11.jpg", "image-22.jpg")] + [InlineData("Hard drive 2GB", "Hard drive 20GB")] + [InlineData("b", "e", "è", "ě", "f", "g", "k")] + [InlineData("123456789", "123456789a", "abc", "abcd")] + [InlineData("12345678912345678912345678913234567891", "123456789123456789123456789132345678912")] + [InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567891")] + [InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567892")] + [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891a")] + [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")] + public void AlphanumericComparatorTest(params string?[] strings) + { + var copy = strings.Reverse().ToArray(); + Array.Sort(copy, new AlphanumericComparator()); + Assert.True(strings.SequenceEqual(copy)); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs new file mode 100644 index 000000000..6fdca4694 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace Jellyfin.Extensions.Tests +{ + public static class CopyToExtensionsTests + { + public static IEnumerable<object[]> CopyTo_Valid_Correct_TestData() + { + yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 0, new[] { 0, 1, 2, 3, 4, 5 } }; + yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 2, new[] { 5, 4, 0, 1, 2, 0 } }; + } + + [Theory] + [MemberData(nameof(CopyTo_Valid_Correct_TestData))] + public static void CopyTo_Valid_Correct<T>(IReadOnlyList<T> source, IList<T> destination, int index, IList<T> expected) + { + source.CopyTo(destination, index); + Assert.Equal(expected, destination); + } + + public static IEnumerable<object[]> CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData() + { + yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, -1 }; + yield return new object[] { new[] { 0, 1, 2 }, new[] { 5, 4, 3, 2, 1, 0 }, 6 }; + yield return new object[] { new[] { 0, 1, 2 }, Array.Empty<int>(), 0 }; + yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0 }, 0 }; + yield return new object[] { new[] { 0, 1, 2, 3, 4, 5 }, new[] { 0, 0, 0, 0, 0, 0 }, 1 }; + } + + [Theory] + [MemberData(nameof(CopyTo_Invalid_ThrowsArgumentOutOfRangeException_TestData))] + public static void CopyTo_Invalid_ThrowsArgumentOutOfRangeException<T>(IReadOnlyList<T> source, IList<T> destination, int index) + { + Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, index)); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj new file mode 100644 index 000000000..4b6dca377 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -0,0 +1,38 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + <PrivateAssets>all</PrivateAssets> + </PackageReference> + <PackageReference Include="coverlet.collector" Version="1.3.0"> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + <PrivateAssets>all</PrivateAssets> + </PackageReference> + <PackageReference Include="FsCheck.Xunit" Version="2.15.3" /> + </ItemGroup> + + <!-- Code Analyzers --> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <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> + + <ItemGroup> + <ProjectReference Include="../../MediaBrowser.Model/MediaBrowser.Model.csproj" /> + <ProjectReference Include="../../src/Jellyfin.Extensions/Jellyfin.Extensions.csproj" /> + </ItemGroup> + +</Project> diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs new file mode 100644 index 000000000..d0e3e9456 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs @@ -0,0 +1,45 @@ +using System.Globalization; +using System.Text.Json; +using FsCheck; +using FsCheck.Xunit; +using Jellyfin.Extensions.Json.Converters; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonBoolNumberTests + { + private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() + { + Converters = + { + new JsonBoolNumberConverter() + } + }; + + [Theory] + [InlineData("1", true)] + [InlineData("0", false)] + [InlineData("2", true)] + [InlineData("true", true)] + [InlineData("false", false)] + public void Deserialize_Number_Valid_Success(string input, bool? output) + { + var value = JsonSerializer.Deserialize<bool>(input, _jsonOptions); + Assert.Equal(value, output); + } + + [Theory] + [InlineData(true, "true")] + [InlineData(false, "false")] + public void Serialize_Bool_Success(bool input, string output) + { + var value = JsonSerializer.Serialize(input, _jsonOptions); + Assert.Equal(value, output); + } + + [Property] + public Property Deserialize_NonZeroInt_True(NonZeroInt input) + => JsonSerializer.Deserialize<bool>(input.ToString(), _jsonOptions).ToProperty(); + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs new file mode 100644 index 000000000..f2ca2ff08 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs @@ -0,0 +1,142 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Tests.Json.Models; +using MediaBrowser.Model.Session; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public static class JsonCommaDelimitedArrayTests + { + [Fact] + public static void Deserialize_String_Null_Success() + { + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": null }", options); + Assert.Null(value?.Value); + } + + [Fact] + public static void Deserialize_Empty_Success() + { + var desiredValue = new GenericBodyArrayModel<string> + { + Value = Array.Empty<string>() + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": """" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_String_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_String_Space_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_EmptyEntry_Success() + { + var desiredValue = new GenericBodyArrayModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Invalid_Success() + { + var desiredValue = new GenericBodyArrayModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Space_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_String_Array_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Array_Valid_Success() + { + var desiredValue = new GenericBodyArrayModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs new file mode 100644 index 000000000..92886dcd2 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs @@ -0,0 +1,92 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Tests.Json.Models; +using MediaBrowser.Model.Session; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public static class JsonCommaDelimitedIReadOnlyListTests + { + [Fact] + public static void Deserialize_String_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_String_Space_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Space_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_String_Array_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<string> + { + Value = new[] { "a", "b", "c" } + }; + + var options = new JsonSerializerOptions(); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + + [Fact] + public static void Deserialize_GenericCommandType_Array_Valid_Success() + { + var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType> + { + Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter()); + var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options); + Assert.Equal(desiredValue.Value, value?.Value); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs new file mode 100644 index 000000000..8465d465a --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs @@ -0,0 +1,68 @@ +using System; +using System.Text.Json; +using Jellyfin.Extensions.Json.Converters; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonGuidConverterTests + { + private readonly JsonSerializerOptions _options; + + public JsonGuidConverterTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new JsonGuidConverter()); + } + + [Fact] + public void Deserialize_Valid_Success() + { + Guid value = JsonSerializer.Deserialize<Guid>(@"""a852a27afe324084ae66db579ee3ee18""", _options); + Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value); + } + + [Fact] + public void Deserialize_ValidDashed_Success() + { + Guid value = JsonSerializer.Deserialize<Guid>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options); + Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value); + } + + [Fact] + public void Roundtrip_Valid_Success() + { + Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18"); + string value = JsonSerializer.Serialize(guid, _options); + Assert.Equal(guid, JsonSerializer.Deserialize<Guid>(value, _options)); + } + + [Fact] + public void Deserialize_Null_EmptyGuid() + { + Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid>("null", _options)); + } + + [Fact] + public void Serialize_EmptyGuid_EmptyGuid() + { + Assert.Equal($"\"{Guid.Empty:N}\"", JsonSerializer.Serialize(Guid.Empty, _options)); + } + + [Fact] + public void Serialize_Valid_NoDash_Success() + { + var guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); + var str = JsonSerializer.Serialize(guid, _options); + Assert.Equal($"\"{guid:N}\"", str); + } + + [Fact] + public void Serialize_Nullable_Success() + { + Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); + var str = JsonSerializer.Serialize(guid, _options); + Assert.Equal($"\"{guid:N}\"", str); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs new file mode 100644 index 000000000..af9227de2 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs @@ -0,0 +1,71 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; +using MediaBrowser.Model.Entities; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonLowerCaseConverterTests + { + private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() + { + Converters = + { + new JsonStringEnumConverter() + } + }; + + [Theory] + [InlineData(null, "{\"CollectionType\":null}")] + [InlineData(CollectionTypeOptions.Movies, "{\"CollectionType\":\"movies\"}")] + [InlineData(CollectionTypeOptions.MusicVideos, "{\"CollectionType\":\"musicvideos\"}")] + public void Serialize_CollectionTypeOptions_Correct(CollectionTypeOptions? collectionType, string expected) + { + Assert.Equal(expected, JsonSerializer.Serialize(new TestContainer(collectionType), _jsonOptions)); + } + + [Theory] + [InlineData("{\"CollectionType\":null}", null)] + [InlineData("{\"CollectionType\":\"movies\"}", CollectionTypeOptions.Movies)] + [InlineData("{\"CollectionType\":\"musicvideos\"}", CollectionTypeOptions.MusicVideos)] + public void Deserialize_CollectionTypeOptions_Correct(string json, CollectionTypeOptions? result) + { + var res = JsonSerializer.Deserialize<TestContainer>(json, _jsonOptions); + Assert.NotNull(res); + Assert.Equal(result, res!.CollectionType); + } + + [Theory] + [InlineData(null)] + [InlineData(CollectionTypeOptions.Movies)] + [InlineData(CollectionTypeOptions.MusicVideos)] + public void RoundTrip_CollectionTypeOptions_Correct(CollectionTypeOptions? value) + { + var res = JsonSerializer.Deserialize<TestContainer>(JsonSerializer.Serialize(new TestContainer(value), _jsonOptions), _jsonOptions); + Assert.NotNull(res); + Assert.Equal(value, res!.CollectionType); + } + + [Theory] + [InlineData("{\"CollectionType\":null}")] + [InlineData("{\"CollectionType\":\"movies\"}")] + [InlineData("{\"CollectionType\":\"musicvideos\"}")] + public void RoundTrip_String_Correct(string json) + { + var res = JsonSerializer.Serialize(JsonSerializer.Deserialize<TestContainer>(json, _jsonOptions), _jsonOptions); + Assert.Equal(json, res); + } + + private class TestContainer + { + public TestContainer(CollectionTypeOptions? collectionType) + { + CollectionType = collectionType; + } + + [JsonConverter(typeof(JsonLowerCaseConverter<CollectionTypeOptions?>))] + public CollectionTypeOptions? CollectionType { get; set; } + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs new file mode 100644 index 000000000..b0dbc09e4 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs @@ -0,0 +1,80 @@ +using System; +using System.Text.Json; +using Jellyfin.Extensions.Json.Converters; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonNullableGuidConverterTests + { + private readonly JsonSerializerOptions _options; + + public JsonNullableGuidConverterTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new JsonNullableGuidConverter()); + } + + [Fact] + public void Deserialize_Valid_Success() + { + Guid? value = JsonSerializer.Deserialize<Guid?>(@"""a852a27afe324084ae66db579ee3ee18""", _options); + Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value); + } + + [Fact] + public void Deserialize_ValidDashed_Success() + { + Guid? value = JsonSerializer.Deserialize<Guid?>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options); + Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value); + } + + [Fact] + public void Roundtrip_Valid_Success() + { + Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18"); + string value = JsonSerializer.Serialize(guid, _options); + Assert.Equal(guid, JsonSerializer.Deserialize<Guid?>(value, _options)); + } + + [Fact] + public void Deserialize_Null_Null() + { + Assert.Null(JsonSerializer.Deserialize<Guid?>("null", _options)); + } + + [Fact] + public void Deserialize_EmptyGuid_EmptyGuid() + { + Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", _options)); + } + + [Fact] + public void Serialize_EmptyGuid_Null() + { + Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, _options)); + } + + [Fact] + public void Serialize_Null_Null() + { + Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, _options)); + } + + [Fact] + public void Serialize_Valid_NoDash_Success() + { + var guid = (Guid?)new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); + var str = JsonSerializer.Serialize(guid, _options); + Assert.Equal($"\"{guid:N}\"", str); + } + + [Fact] + public void Serialize_Nullable_Success() + { + Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); + var str = JsonSerializer.Serialize(guid, _options); + Assert.Equal($"\"{guid:N}\"", str); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs new file mode 100644 index 000000000..655e07074 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using Jellyfin.Extensions.Json.Converters; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonStringConverterTests + { + private readonly JsonSerializerOptions _jsonSerializerOptions = new () + { + Converters = + { + new JsonStringConverter() + } + }; + + [Theory] + [InlineData("\"test\"", "test")] + [InlineData("123", "123")] + [InlineData("123.45", "123.45")] + [InlineData("true", "true")] + [InlineData("false", "false")] + public void Deserialize_String_Valid_Success(string input, string output) + { + var deserialized = JsonSerializer.Deserialize<string>(input, _jsonSerializerOptions); + Assert.Equal(deserialized, output); + } + + [Fact] + public void Deserialize_Int32asInt32_Valid_Success() + { + const string? input = "123"; + const int output = 123; + var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions); + Assert.Equal(deserialized, output); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs new file mode 100644 index 000000000..5fbac7eab --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs @@ -0,0 +1,36 @@ +using System; +using System.Text.Json; +using Jellyfin.Extensions.Json.Converters; +using Xunit; + +namespace Jellyfin.Extensions.Tests.Json.Converters +{ + public class JsonVersionConverterTests + { + private readonly JsonSerializerOptions _options; + + public JsonVersionConverterTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new JsonVersionConverter()); + } + + [Fact] + public void Deserialize_Version_Success() + { + var input = "\"1.025.222\""; + var output = new Version(1, 25, 222); + var deserializedInput = JsonSerializer.Deserialize<Version>(input, _options); + Assert.Equal(output, deserializedInput); + } + + [Fact] + public void Serialize_Version_Success() + { + var input = new Version(1, 09, 59); + var output = "\"1.9.59\""; + var serializedInput = JsonSerializer.Serialize(input, _options); + Assert.Equal(output, serializedInput); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs new file mode 100644 index 000000000..ef135278f --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs @@ -0,0 +1,20 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; + +namespace Jellyfin.Extensions.Tests.Json.Models +{ + /// <summary> + /// The generic body model. + /// </summary> + /// <typeparam name="T">The value type.</typeparam> + public class GenericBodyArrayModel<T> + { + /// <summary> + /// Gets or sets the value. + /// </summary> + [SuppressMessage("Microsoft.Performance", "CA1819:Properties should not return arrays", MessageId = "Value", Justification = "Imported from ServiceStack")] + [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))] + public T[] Value { get; set; } = default!; + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs new file mode 100644 index 000000000..8e7b5a35b --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; + +namespace Jellyfin.Extensions.Tests.Json.Models +{ + /// <summary> + /// The generic body <c>IReadOnlyList</c> model. + /// </summary> + /// <typeparam name="T">The value type.</typeparam> + public class GenericBodyIReadOnlyListModel<T> + { + /// <summary> + /// Gets or sets the value. + /// </summary> + [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))] + public IReadOnlyList<T> Value { get; set; } = default!; + } +} diff --git a/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs new file mode 100644 index 000000000..c72216d94 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs @@ -0,0 +1,21 @@ +using System; +using Xunit; + +namespace Jellyfin.Extensions.Tests +{ + public static class ShuffleExtensionsTests + { + private static readonly Random _rng = new Random(); + + [Fact] + public static void Shuffle_Valid_Correct() + { + byte[] original = new byte[1 << 6]; + _rng.NextBytes(original); + byte[] shuffled = (byte[])original.Clone(); + shuffled.Shuffle(); + + Assert.NotEqual(original, shuffled); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs new file mode 100644 index 000000000..d1aa2e476 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs @@ -0,0 +1,18 @@ +using System; +using Xunit; + +namespace Jellyfin.Extensions.Tests +{ + public class StringExtensionsTests + { + [Theory] + [InlineData("", '_', 0)] + [InlineData("___", '_', 3)] + [InlineData("test\x00", '\x00', 1)] + [InlineData("Imdb=tt0119567|Tmdb=330|TmdbCollection=328", '|', 2)] + public void ReadOnlySpan_Count_Success(string str, char needle, int count) + { + Assert.Equal(count, str.AsSpan().Count(needle)); + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 415682e85..45808375f 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -1,7 +1,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.MediaEncoding.Probing; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 98fbb00d5..d8089eea2 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -2,7 +2,7 @@ using System; using System.Globalization; using System.IO; using System.Text.Json; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; diff --git a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs b/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs deleted file mode 100644 index 955d296cc..000000000 --- a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using MediaBrowser.Model.Entities; -using Xunit; - -namespace Jellyfin.Model.Tests.Entities -{ - public class JsonLowerCaseConverterTests - { - private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions() - { - Converters = - { - new JsonStringEnumConverter() - } - }; - - [Theory] - [InlineData(null, "{\"CollectionType\":null}")] - [InlineData(CollectionTypeOptions.Movies, "{\"CollectionType\":\"movies\"}")] - [InlineData(CollectionTypeOptions.MusicVideos, "{\"CollectionType\":\"musicvideos\"}")] - public void Serialize_CollectionTypeOptions_Correct(CollectionTypeOptions? collectionType, string expected) - { - Assert.Equal(expected, JsonSerializer.Serialize(new TestContainer(collectionType), _jsonOptions)); - } - - [Theory] - [InlineData("{\"CollectionType\":null}", null)] - [InlineData("{\"CollectionType\":\"movies\"}", CollectionTypeOptions.Movies)] - [InlineData("{\"CollectionType\":\"musicvideos\"}", CollectionTypeOptions.MusicVideos)] - public void Deserialize_CollectionTypeOptions_Correct(string json, CollectionTypeOptions? result) - { - var res = JsonSerializer.Deserialize<TestContainer>(json, _jsonOptions); - Assert.NotNull(res); - Assert.Equal(result, res!.CollectionType); - } - - [Theory] - [InlineData(null)] - [InlineData(CollectionTypeOptions.Movies)] - [InlineData(CollectionTypeOptions.MusicVideos)] - public void RoundTrip_CollectionTypeOptions_Correct(CollectionTypeOptions? value) - { - var res = JsonSerializer.Deserialize<TestContainer>(JsonSerializer.Serialize(new TestContainer(value), _jsonOptions), _jsonOptions); - Assert.NotNull(res); - Assert.Equal(value, res!.CollectionType); - } - - [Theory] - [InlineData("{\"CollectionType\":null}")] - [InlineData("{\"CollectionType\":\"movies\"}")] - [InlineData("{\"CollectionType\":\"musicvideos\"}")] - public void RoundTrip_String_Correct(string json) - { - var res = JsonSerializer.Serialize(JsonSerializer.Deserialize<TestContainer>(json, _jsonOptions), _jsonOptions); - Assert.Equal(json, res); - } - - private class TestContainer - { - public TestContainer(CollectionTypeOptions? collectionType) - { - CollectionType = collectionType; - } - - [JsonConverter(typeof(JsonLowerCaseConverter<CollectionTypeOptions?>))] - public CollectionTypeOptions? CollectionType { get; set; } - } - } -} diff --git a/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs new file mode 100644 index 000000000..25900bc09 --- /dev/null +++ b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs @@ -0,0 +1,86 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using MediaBrowser.Providers.Plugins.Omdb; +using Xunit; + +namespace Jellyfin.Providers.Tests.Omdb +{ + public class JsonOmdbConverterTests + { + private readonly JsonSerializerOptions _options; + + public JsonOmdbConverterTests() + { + _options = new JsonSerializerOptions(); + _options.Converters.Add(new JsonOmdbNotAvailableStringConverter()); + _options.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); + _options.NumberHandling = JsonNumberHandling.AllowReadingFromString; + } + + [Fact] + public void Deserialize_Omdb_Response_Not_Available_Success() + { + const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; + var seasonRootObject = JsonSerializer.Deserialize<OmdbProvider.RootObject>(Input, _options); + Assert.NotNull(seasonRootObject); + Assert.Null(seasonRootObject?.Awards); + Assert.Null(seasonRootObject?.Episode); + Assert.Null(seasonRootObject?.Metascore); + } + + [Theory] + [InlineData("\"N/A\"")] + [InlineData("null")] + public void Deserialization_To_Nullable_Int_Shoud_Be_Null(string input) + { + var result = JsonSerializer.Deserialize<int?>(input, _options); + Assert.Null(result); + } + + [Theory] + [InlineData("\"8\"", 8)] + [InlineData("8", 8)] + public void Deserialize_NullableInt_Success(string input, int? expected) + { + var result = JsonSerializer.Deserialize<int?>(input, _options); + Assert.Equal(result, expected); + } + + [Theory] + [InlineData("\"N/A\"")] + [InlineData("null")] + public void Deserialization_To_Nullable_String_Shoud_Be_Null(string input) + { + var result = JsonSerializer.Deserialize<string?>(input, _options); + Assert.Null(result); + } + + [Theory] + [InlineData("\"Jellyfin\"", "Jellyfin")] + public void Deserialize_Normal_String_Success(string input, string expected) + { + var result = JsonSerializer.Deserialize<string?>(input, _options); + Assert.Equal(expected, result); + } + + [Fact] + public void Roundtrip_Valid_Success() + { + const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; + var trip1 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(Input, _options); + Assert.NotNull(trip1); + Assert.NotNull(trip1?.Title); + Assert.Null(trip1?.Awards); + Assert.Null(trip1?.Episode); + Assert.Null(trip1?.Metascore); + + var serializedTrip1 = JsonSerializer.Serialize(trip1!, _options); + var trip2 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(serializedTrip1, _options); + Assert.NotNull(trip2); + Assert.NotNull(trip2?.Title); + Assert.Null(trip2?.Awards); + Assert.Null(trip2?.Episode); + Assert.Null(trip2?.Metascore); + } + } +} diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index ea6838682..4ea05397d 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -7,7 +7,7 @@ using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; using Jellyfin.Api.Models.UserDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; namespace Jellyfin.Server.Integration.Tests diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index f5411dcb8..827365363 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; namespace Jellyfin.Server.Integration.Tests.Controllers diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index 169a5a6c5..9c0fc72f6 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -6,7 +6,7 @@ using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; using Xunit.Priority; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 6584490de..8866ab53c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -8,7 +8,7 @@ using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.UserDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Model.Dto; using Xunit; using Xunit.Priority; -- cgit v1.2.3 From 11a5551218cbfcd21c4dd1f33e8e8a6eea252f47 Mon Sep 17 00:00:00 2001 From: Maxr1998 <max.rumpf1998@gmail.com> Date: Fri, 9 Jul 2021 02:06:38 +0200 Subject: Refactor ProbeResultNormalizer Improve code structure and readability --- .../Probing/FFProbeHelpers.cs | 46 +- .../Probing/ProbeResultNormalizer.cs | 574 +++++++++------------ src/Jellyfin.Extensions/DictionaryExtensions.cs | 65 +++ 3 files changed, 317 insertions(+), 368 deletions(-) create mode 100644 src/Jellyfin.Extensions/DictionaryExtensions.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 1fa90bb21..d0a76c4ca 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Globalization; @@ -22,7 +20,7 @@ namespace MediaBrowser.MediaEncoding.Probing throw new ArgumentNullException(nameof(result)); } - if (result.Format != null && result.Format.Tags != null) + if (result.Format?.Tags != null) { result.Format.Tags = ConvertDictionaryToCaseInsensitive(result.Format.Tags); } @@ -40,39 +38,17 @@ namespace MediaBrowser.MediaEncoding.Probing } } - /// <summary> - /// Gets a string from an FFProbeResult tags dictionary. - /// </summary> - /// <param name="tags">The tags.</param> - /// <param name="key">The key.</param> - /// <returns>System.String.</returns> - public static string GetDictionaryValue(IReadOnlyDictionary<string, string> tags, string key) - { - if (tags == null) - { - return null; - } - - tags.TryGetValue(key, out var val); - return val; - } - /// <summary> /// Gets an int from an FFProbeResult tags dictionary. /// </summary> /// <param name="tags">The tags.</param> /// <param name="key">The key.</param> /// <returns>System.Nullable{System.Int32}.</returns> - public static int? GetDictionaryNumericValue(Dictionary<string, string> tags, string key) + public static int? GetDictionaryNumericValue(IReadOnlyDictionary<string, string> tags, string key) { - var val = GetDictionaryValue(tags, key); - - if (!string.IsNullOrEmpty(val)) + if (tags.TryGetValue(key, out var val) && int.TryParse(val, out var i)) { - if (int.TryParse(val, out var i)) - { - return i; - } + return i; } return null; @@ -84,18 +60,12 @@ namespace MediaBrowser.MediaEncoding.Probing /// <param name="tags">The tags.</param> /// <param name="key">The key.</param> /// <returns>System.Nullable{DateTime}.</returns> - public static DateTime? GetDictionaryDateTime(Dictionary<string, string> tags, string key) + public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary<string, string> tags, string key) { - var val = GetDictionaryValue(tags, key); - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - if (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var i)) + if (tags.TryGetValue(key, out var val) + && DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime)) { - return i.ToUniversalTime(); + return dateTime.ToUniversalTime(); } return null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index bbff5daca..c50a577be 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Text; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -80,68 +81,33 @@ namespace MediaBrowser.MediaEncoding.Probing var tags = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var tagStreamType = isAudio ? "audio" : "video"; - if (data.Streams != null) - { - var tagStream = data.Streams.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); + var tagStream = data.Streams?.FirstOrDefault(i => string.Equals(i.CodecType, tagStreamType, StringComparison.OrdinalIgnoreCase)); - if (tagStream != null && tagStream.Tags != null) + if (tagStream?.Tags != null) + { + foreach (var (key, value) in tagStream.Tags) { - foreach (var pair in tagStream.Tags) - { - tags[pair.Key] = pair.Value; - } + tags[key] = value; } } - if (data.Format != null && data.Format.Tags != null) + if (data.Format?.Tags != null) { - foreach (var pair in data.Format.Tags) + foreach (var (key, value) in data.Format.Tags) { - tags[pair.Key] = pair.Value; + tags[key] = value; } } FetchGenres(info, tags); - var overview = FFProbeHelpers.GetDictionaryValue(tags, "synopsis"); - - if (string.IsNullOrWhiteSpace(overview)) - { - overview = FFProbeHelpers.GetDictionaryValue(tags, "description"); - } - - if (string.IsNullOrWhiteSpace(overview)) - { - overview = FFProbeHelpers.GetDictionaryValue(tags, "desc"); - } - - if (!string.IsNullOrWhiteSpace(overview)) - { - info.Overview = overview; - } - var title = FFProbeHelpers.GetDictionaryValue(tags, "title"); - if (!string.IsNullOrWhiteSpace(title)) - { - info.Name = title; - } - else - { - title = FFProbeHelpers.GetDictionaryValue(tags, "title-eng"); - if (!string.IsNullOrWhiteSpace(title)) - { - info.Name = title; - } - } - - var titleSort = FFProbeHelpers.GetDictionaryValue(tags, "titlesort"); - if (!string.IsNullOrWhiteSpace(titleSort)) - { - info.ForcedSortName = titleSort; - } + info.Name = tags.GetFirstNotNullNorWhiteSpaceValue("title", "title-eng"); + info.ForcedSortName = tags.GetFirstNotNullNorWhiteSpaceValue("sort_name", "title-sort", "titlesort"); + info.Overview = tags.GetFirstNotNullNorWhiteSpaceValue("synopsis", "description", "desc"); info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); - info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); + info.ShowName = tags.GetValueOrDefault("show_name"); info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); // Several different forms of retail/premiere date @@ -153,32 +119,21 @@ namespace MediaBrowser.MediaEncoding.Probing FFProbeHelpers.GetDictionaryDateTime(tags, "date"); // Set common metadata for music (audio) and music videos (video) - info.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); - - var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); + info.Album = tags.GetValueOrDefault("album"); - if (!string.IsNullOrWhiteSpace(artists)) + if (tags.TryGetValue("artists", out var artists) && !string.IsNullOrWhiteSpace(artists)) { - info.Artists = SplitArtists(artists, new[] { '/', ';' }, false) - .DistinctNames() - .ToArray(); + info.Artists = SplitDistinctArtists(artists, new[] { '/', ';' }, false).ToArray(); } else { - var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist"); - if (string.IsNullOrWhiteSpace(artist)) - { - info.Artists = Array.Empty<string>(); - } - else - { - info.Artists = SplitArtists(artist, _nameDelimiters, true) - .DistinctNames() - .ToArray(); - } + var artist = tags.GetFirstNotNullNorWhiteSpaceValue("artist"); + info.Artists = artist == null + ? Array.Empty<string>() + : SplitDistinctArtists(artist, _nameDelimiters, true).ToArray(); } - // If we don't have a ProductionYear try and get it from PremiereDate + // Guess ProductionYear from PremiereDate if missing if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue) { info.ProductionYear = info.PremiereDate.Value.Year; @@ -198,10 +153,10 @@ namespace MediaBrowser.MediaEncoding.Probing { FetchStudios(info, tags, "copyright"); - var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC"); - if (!string.IsNullOrWhiteSpace(iTunEXTC)) + var iTunExtc = tags.GetFirstNotNullNorWhiteSpaceValue("iTunEXTC"); + if (iTunExtc != null) { - var parts = iTunEXTC.Split('|', StringSplitOptions.RemoveEmptyEntries); + var parts = iTunExtc.Split('|', StringSplitOptions.RemoveEmptyEntries); // Example // mpaa|G|100|For crude humor if (parts.Length > 1) @@ -215,10 +170,10 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var itunesXml = FFProbeHelpers.GetDictionaryValue(tags, "iTunMOVI"); - if (!string.IsNullOrWhiteSpace(itunesXml)) + var iTunXml = tags.GetFirstNotNullNorWhiteSpaceValue("iTunMOVI"); + if (iTunXml != null) { - FetchFromItunesInfo(itunesXml, info); + FetchFromItunesInfo(iTunXml, info); } if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) @@ -235,8 +190,7 @@ namespace MediaBrowser.MediaEncoding.Probing ExtractTimestamp(info); - var stereoMode = GetDictionaryValue(tags, "stereo_mode"); - if (string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) + if (tags.TryGetValue("stereo_mode", out var stereoMode) && string.Equals(stereoMode, "left_right", StringComparison.OrdinalIgnoreCase)) { info.Video3DFormat = Video3DFormat.FullSideBySide; } @@ -289,42 +243,36 @@ namespace MediaBrowser.MediaEncoding.Probing if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) - { - return 192000; - } - - if (channelsValue >= 5) + switch (channelsValue) { - return 320000; + case <= 2: + return 192000; + case >= 5: + return 320000; } } if (string.Equals(codec, "ac3", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) + switch (channelsValue) { - return 192000; - } - - if (channelsValue >= 5) - { - return 640000; + case <= 2: + return 192000; + case >= 5: + return 640000; } } if (string.Equals(codec, "flac", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "alac", StringComparison.OrdinalIgnoreCase)) { - if (channelsValue <= 2) - { - return 960000; - } - - if (channelsValue >= 5) + switch (channelsValue) { - return 2880000; + case <= 2: + return 960000; + case >= 5: + return 2880000; } } @@ -854,7 +802,7 @@ namespace MediaBrowser.MediaEncoding.Probing || string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase))) { var bps = GetBPSFromTags(streamInfo); - if (bps != null && bps > 0) + if (bps > 0) { stream.BitRate = bps; } @@ -923,6 +871,7 @@ namespace MediaBrowser.MediaEncoding.Probing } tags.TryGetValue(key, out var val); + return val; } @@ -930,7 +879,7 @@ namespace MediaBrowser.MediaEncoding.Probing { if (string.IsNullOrEmpty(input)) { - return input; + return null; } return input.Split('(').FirstOrDefault(); @@ -1018,64 +967,64 @@ namespace MediaBrowser.MediaEncoding.Probing /// <returns>System.Nullable{System.Single}.</returns> private float? GetFrameRate(string value) { - if (!string.IsNullOrEmpty(value)) + if (string.IsNullOrEmpty(value)) { - var parts = value.Split('/'); + return null; + } - float result; + var parts = value.Split('/'); - if (parts.Length == 2) - { - result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); - } - else - { - result = float.Parse(parts[0], _usCulture); - } + float result; - return float.IsNaN(result) ? (float?)null : result; + if (parts.Length == 2) + { + result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); + } + else + { + result = float.Parse(parts[0], _usCulture); } - return null; + return float.IsNaN(result) ? null : result; } private void SetAudioRuntimeTicks(InternalMediaInfoResult result, MediaInfo data) { - if (result.Streams != null) + // Get the first info stream + var stream = result.Streams?.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); + if (stream == null) { - // Get the first info stream - var stream = result.Streams.FirstOrDefault(s => string.Equals(s.CodecType, "audio", StringComparison.OrdinalIgnoreCase)); + return; + } - if (stream != null) - { - // Get duration from stream properties - var duration = stream.Duration; + // Get duration from stream properties + var duration = stream.Duration; - // If it's not there go into format properties - if (string.IsNullOrEmpty(duration)) - { - duration = result.Format.Duration; - } + // If it's not there go into format properties + if (string.IsNullOrEmpty(duration)) + { + duration = result.Format.Duration; + } - // If we got something, parse it - if (!string.IsNullOrEmpty(duration)) - { - data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; - } - } + // If we got something, parse it + if (!string.IsNullOrEmpty(duration)) + { + data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; } } private int? GetBPSFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); - if (!string.IsNullOrEmpty(bps) - && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) - { - return parsedBps; - } + return null; + } + + var bps = GetDictionaryValue(streamInfo.Tags, "BPS-eng") ?? GetDictionaryValue(streamInfo.Tags, "BPS"); + if (!string.IsNullOrEmpty(bps) + && int.TryParse(bps, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBps)) + { + return parsedBps; } return null; @@ -1083,13 +1032,15 @@ namespace MediaBrowser.MediaEncoding.Probing private double? GetRuntimeSecondsFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); - if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) - { - return parsedDuration.TotalSeconds; - } + return null; + } + + var duration = GetDictionaryValue(streamInfo.Tags, "DURATION-eng") ?? GetDictionaryValue(streamInfo.Tags, "DURATION"); + if (!string.IsNullOrEmpty(duration) && TimeSpan.TryParse(duration, out var parsedDuration)) + { + return parsedDuration.TotalSeconds; } return null; @@ -1097,14 +1048,17 @@ namespace MediaBrowser.MediaEncoding.Probing private long? GetNumberOfBytesFromTags(MediaStreamInfo streamInfo) { - if (streamInfo != null && streamInfo.Tags != null) + if (streamInfo?.Tags == null) { - var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); - if (!string.IsNullOrEmpty(numberOfBytes) - && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) - { - return parsedBytes; - } + return null; + } + + var numberOfBytes = GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES-eng") + ?? GetDictionaryValue(streamInfo.Tags, "NUMBER_OF_BYTES"); + if (!string.IsNullOrEmpty(numberOfBytes) + && long.TryParse(numberOfBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedBytes)) + { + return parsedBytes; } return null; @@ -1112,24 +1066,18 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetSize(InternalMediaInfoResult data, MediaInfo info) { - if (data.Format != null) + if (data.Format == null) { - if (!string.IsNullOrEmpty(data.Format.Size)) - { - info.Size = long.Parse(data.Format.Size, _usCulture); - } - else - { - info.Size = null; - } + return; } + + info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, _usCulture); } - private void SetAudioInfoFromTags(MediaInfo audio, Dictionary<string, string> tags) + private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary<string, string> tags) { var people = new List<BaseItemPerson>(); - var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); - if (!string.IsNullOrWhiteSpace(composer)) + if (tags.TryGetValue("composer", out var composer) && !string.IsNullOrWhiteSpace(composer)) { foreach (var person in Split(composer, false)) { @@ -1137,8 +1085,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); - if (!string.IsNullOrWhiteSpace(conductor)) + if (tags.TryGetValue("conductor", out var conductor) && !string.IsNullOrWhiteSpace(conductor)) { foreach (var person in Split(conductor, false)) { @@ -1146,8 +1093,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); - if (!string.IsNullOrWhiteSpace(lyricist)) + if (tags.TryGetValue("lyricist", out var lyricist) && !string.IsNullOrWhiteSpace(lyricist)) { foreach (var person in Split(lyricist, false)) { @@ -1156,8 +1102,7 @@ namespace MediaBrowser.MediaEncoding.Probing } // Check for writer some music is tagged that way as alternative to composer/lyricist - var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); - if (!string.IsNullOrWhiteSpace(writer)) + if (tags.TryGetValue("writer", out var writer) && !string.IsNullOrWhiteSpace(writer)) { foreach (var person in Split(writer, false)) { @@ -1167,38 +1112,23 @@ namespace MediaBrowser.MediaEncoding.Probing audio.People = people.ToArray(); - var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist"); - if (string.IsNullOrWhiteSpace(albumArtist)) - { - albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist"); - } - - if (string.IsNullOrWhiteSpace(albumArtist)) - { - albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist"); - } - - if (string.IsNullOrWhiteSpace(albumArtist)) - { - audio.AlbumArtists = Array.Empty<string>(); - } - else - { - audio.AlbumArtists = SplitArtists(albumArtist, _nameDelimiters, true) - .DistinctNames() - .ToArray(); - } + // Set album artist + var albumArtist = tags.GetFirstNotNullNorWhiteSpaceValue("albumartist", "album artist", "album_artist"); + audio.AlbumArtists = albumArtist != null + ? SplitDistinctArtists(albumArtist, _nameDelimiters, true).ToArray() + : Array.Empty<string>(); + // Set album artist to artist if empty if (audio.AlbumArtists.Length == 0) { audio.AlbumArtists = audio.Artists; } // Track number - audio.IndexNumber = GetDictionaryDiscValue(tags, "track"); + audio.IndexNumber = GetDictionaryTrackOrDiscNumber(tags, "track"); // Disc number - audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc"); + audio.ParentIndexNumber = GetDictionaryTrackOrDiscNumber(tags, "disc"); // There's several values in tags may or may not be present FetchStudios(audio, tags, "organization"); @@ -1206,30 +1136,25 @@ namespace MediaBrowser.MediaEncoding.Probing FetchStudios(audio, tags, "publisher"); FetchStudios(audio, tags, "label"); - // These support mulitple values, but for now we only store the first. - var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID")); - + // These support multiple values, but for now we only store the first. + var mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Artist Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Artist Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ARTISTID")); audio.SetProviderId(MetadataProvider.MusicBrainzArtist, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Album Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_ALBUMID")); audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Group Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASEGROUPID")); audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, mb); - mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")) - ?? GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID")); - + mb = GetMultipleMusicBrainzId(tags.GetValueOrDefault("MusicBrainz Release Track Id")) + ?? GetMultipleMusicBrainzId(tags.GetValueOrDefault("MUSICBRAINZ_RELEASETRACKID")); audio.SetProviderId(MetadataProvider.MusicBrainzTrack, mb); } @@ -1253,18 +1178,18 @@ namespace MediaBrowser.MediaEncoding.Probing /// <returns>System.String[][].</returns> private IEnumerable<string> Split(string val, bool allowCommaDelimiter) { - // Only use the comma as a delimeter if there are no slashes or pipes. + // Only use the comma as a delimiter if there are no slashes or pipes. // We want to be careful not to split names that have commas in them - var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? + var delimiter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ? _nameDelimiters : new[] { ',' }; - return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries) + return val.Split(delimiter, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) .Select(i => i.Trim()); } - private IEnumerable<string> SplitArtists(string val, char[] delimiters, bool splitFeaturing) + private IEnumerable<string> SplitDistinctArtists(string val, char[] delimiters, bool splitFeaturing) { if (splitFeaturing) { @@ -1290,7 +1215,7 @@ namespace MediaBrowser.MediaEncoding.Probing .Select(i => i.Trim()); artistsFound.AddRange(artists); - return artistsFound; + return artistsFound.DistinctNames(); } /// <summary> @@ -1299,36 +1224,38 @@ namespace MediaBrowser.MediaEncoding.Probing /// <param name="info">The info.</param> /// <param name="tags">The tags.</param> /// <param name="tagName">Name of the tag.</param> - private void FetchStudios(MediaInfo info, Dictionary<string, string> tags, string tagName) + private void FetchStudios(MediaInfo info, IReadOnlyDictionary<string, string> tags, string tagName) { - var val = FFProbeHelpers.GetDictionaryValue(tags, tagName); + var val = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(val)) + if (string.IsNullOrEmpty(val)) { - var studios = Split(val, true); - var studioList = new List<string>(); + return; + } - foreach (var studio in studios) - { - // Sometimes the artist name is listed here, account for that - if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase)) - { - continue; - } + var studios = Split(val, true); + var studioList = new List<string>(); - if (info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) - { - continue; - } + foreach (var studio in studios) + { + if (string.IsNullOrWhiteSpace(studio)) + { + continue; + } - studioList.Add(studio); + // Don't add artist/album artist name to studios, even if it's listed there + if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase) + || info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) + { + continue; } - info.Studios = studioList - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); + studioList.Add(studio); } + + info.Studios = studioList + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); } /// <summary> @@ -1336,58 +1263,55 @@ namespace MediaBrowser.MediaEncoding.Probing /// </summary> /// <param name="info">The information.</param> /// <param name="tags">The tags.</param> - private void FetchGenres(MediaInfo info, Dictionary<string, string> tags) + private void FetchGenres(MediaInfo info, IReadOnlyDictionary<string, string> tags) { - var val = FFProbeHelpers.GetDictionaryValue(tags, "genre"); + var genreVal = tags.GetValueOrDefault("genre"); + if (string.IsNullOrEmpty(genreVal)) + { + return; + } - if (!string.IsNullOrEmpty(val)) + var genres = new List<string>(info.Genres); + foreach (var genre in Split(genreVal, true)) { - var genres = new List<string>(info.Genres); - foreach (var genre in Split(val, true)) + if (string.IsNullOrWhiteSpace(genre)) { - genres.Add(genre); + continue; } - info.Genres = genres - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); + genres.Add(genre); } + + info.Genres = genres + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); } /// <summary> - /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'. + /// Gets the track or disc number, which can be in the form of '1', or '1/3'. /// </summary> /// <param name="tags">The tags.</param> /// <param name="tagName">Name of the tag.</param> - /// <returns>System.Nullable{System.Int32}.</returns> - private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName) + /// <returns>The track or disc number, or null, if missing or not parseable.</returns> + private static int? GetDictionaryTrackOrDiscNumber(IReadOnlyDictionary<string, string> tags, string tagName) { - var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName); + var disc = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(disc)) + if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.Split('/')[0], out var discNum)) { - disc = disc.Split('/')[0]; - - if (int.TryParse(disc, out var num)) - { - return num; - } + return discNum; } return null; } - private ChapterInfo GetChapterInfo(MediaChapter chapter) + private static ChapterInfo GetChapterInfo(MediaChapter chapter) { var info = new ChapterInfo(); - if (chapter.Tags != null) + if (chapter.Tags != null && chapter.Tags.TryGetValue("title", out string name)) { - if (chapter.Tags.TryGetValue("title", out string name)) - { - info.Name = name; - } + info.Name = name; } // Limit accuracy to milliseconds to match xml saving @@ -1404,14 +1328,14 @@ namespace MediaBrowser.MediaEncoding.Probing private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) { - if (data.Format == null || data.Format.Tags == null) + var tags = data.Format?.Tags; + + if (tags == null) { return; } - var genres = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/Genre"); - - if (!string.IsNullOrWhiteSpace(genres)) + if (tags.TryGetValue("WM/Genre", out var genres) && !string.IsNullOrWhiteSpace(genres)) { var genreList = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) @@ -1425,16 +1349,12 @@ namespace MediaBrowser.MediaEncoding.Probing } } - var officialRating = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/ParentalRating"); - - if (!string.IsNullOrWhiteSpace(officialRating)) + if (tags.TryGetValue("WM/ParentalRating", out var officialRating) && !string.IsNullOrWhiteSpace(officialRating)) { video.OfficialRating = officialRating; } - var people = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaCredits"); - - if (!string.IsNullOrEmpty(people)) + if (tags.TryGetValue("WM/MediaCredits", out var people) && !string.IsNullOrEmpty(people)) { video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) @@ -1442,29 +1362,21 @@ namespace MediaBrowser.MediaEncoding.Probing .ToArray(); } - var year = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/OriginalReleaseTime"); - if (!string.IsNullOrWhiteSpace(year)) + if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, _usCulture, out var parsedYear)) { - if (int.TryParse(year, NumberStyles.Integer, _usCulture, out var val)) - { - video.ProductionYear = val; - } + video.ProductionYear = parsedYear; } - var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/MediaOriginalBroadcastDateTime"); - if (!string.IsNullOrWhiteSpace(premiereDateString)) + // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ + // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) + if (tags.TryGetValue("WM/MediaOriginalBroadcastDateTime", out var premiereDateString) && DateTime.TryParse(year, null, DateTimeStyles.None, out var parsedDate)) { - // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ - // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) - if (DateTime.TryParse(year, null, DateTimeStyles.None, out var val)) - { - video.PremiereDate = val.ToUniversalTime(); - } + video.PremiereDate = parsedDate.ToUniversalTime(); } - var description = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitleDescription"); + var description = tags.GetValueOrDefault("WM/SubTitleDescription"); - var subTitle = FFProbeHelpers.GetDictionaryValue(data.Format.Tags, "WM/SubTitle"); + var subTitle = tags.GetValueOrDefault("WM/SubTitle"); // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ @@ -1475,49 +1387,48 @@ namespace MediaBrowser.MediaEncoding.Probing // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S] if (string.IsNullOrWhiteSpace(subTitle) && !string.IsNullOrWhiteSpace(description) - && description.AsSpan().Slice(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename + && description.AsSpan()[0..Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)].IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename { - string[] parts = description.Split(':'); - if (parts.Length > 0) + string[] descriptionParts = description.Split(':'); + if (descriptionParts.Length > 0) { - string subtitle = parts[0]; + string subtitle = descriptionParts[0]; try { - if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number + // Check if it contains a episode number and season number + if (subtitle.Contains('/', StringComparison.Ordinal)) { - string[] numbers = subtitle.Split(' '); - 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); + string[] subtitleParts = subtitle.Split(' '); + string[] numbers = subtitleParts[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/'); + video.IndexNumber = int.Parse(numbers[0], CultureInfo.InvariantCulture); + // int totalEpisodesInSeason = int.Parse(numbers[1], CultureInfo.InvariantCulture); - description = string.Join(' ', numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it + // Skip the numbers, concatenate the rest, trim and set as new description + description = string.Join(' ', subtitleParts, 1, subtitleParts.Length - 1).Trim(); + } + else if (subtitle.Contains('.', StringComparison.Ordinal)) + { + var subtitleParts = subtitle.Split('.'); + description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); } else { - // Switch to default parsing - if (subtitle.Contains('.', StringComparison.Ordinal)) - { - // skip the comment, keep the subtitle - description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first - } - else - { - description = subtitle.Trim(); // Clean up whitespaces and save it - } + description = subtitle.Trim(); } } catch (Exception ex) { _logger.LogError(ex, "Error while parsing subtitle field"); - // Default parsing + // Fallback to default parsing if (subtitle.Contains('.', StringComparison.Ordinal)) { - // skip the comment, keep the subtitle - description = string.Join('.', subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first + var subtitleParts = subtitle.Split('.'); + description = string.Join('.', subtitleParts, 1, subtitleParts.Length - 1).Trim(); } else { - description = subtitle.Trim(); // Clean up whitespaces and save it + description = subtitle.Trim(); } } } @@ -1531,24 +1442,27 @@ namespace MediaBrowser.MediaEncoding.Probing private void ExtractTimestamp(MediaInfo video) { - if (video.VideoType == VideoType.VideoFile) + if (video.VideoType != VideoType.VideoFile) { - if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) || - string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) || - string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) - { - try - { - video.Timestamp = GetMpegTimestamp(video.Path); + return; + } - _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); - video.Timestamp = null; - } - } + if (!string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) + && !string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) + && !string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + try + { + video.Timestamp = GetMpegTimestamp(video.Path); + _logger.LogDebug("Video has {Timestamp} timestamp", video.Timestamp); + } + catch (Exception ex) + { + video.Timestamp = null; + _logger.LogError(ex, "Error extracting timestamp info from {Path}", video.Path); } } @@ -1567,17 +1481,17 @@ namespace MediaBrowser.MediaEncoding.Probing return TransportStreamTimestamp.None; } - if ((packetBuffer[4] == 71) && (packetBuffer[196] == 71)) + if ((packetBuffer[4] != 71) || (packetBuffer[196] != 71)) { - if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) - { - return TransportStreamTimestamp.Zero; - } + return TransportStreamTimestamp.None; + } - return TransportStreamTimestamp.Valid; + if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) + { + return TransportStreamTimestamp.Zero; } - return TransportStreamTimestamp.None; + return TransportStreamTimestamp.Valid; } } } diff --git a/src/Jellyfin.Extensions/DictionaryExtensions.cs b/src/Jellyfin.Extensions/DictionaryExtensions.cs new file mode 100644 index 000000000..43ed41ab1 --- /dev/null +++ b/src/Jellyfin.Extensions/DictionaryExtensions.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; + +namespace Jellyfin.Extensions +{ + /// <summary> + /// Static extensions for the <see cref="IReadOnlyDictionary{TKey,TValue}"/> interface. + /// </summary> + public static class DictionaryExtensions + { + /// <summary> + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// </summary> + /// <param name="dictionary">The dictionary.</param> + /// <param name="key1">The first checked key.</param> + /// <returns>System.String.</returns> + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1) + { + return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, string.Empty, string.Empty); + } + + /// <summary> + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// </summary> + /// <param name="dictionary">The dictionary.</param> + /// <param name="key1">The first checked key.</param> + /// <param name="key2">The second checked key.</param> + /// <returns>System.String.</returns> + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1, string key2) + { + return dictionary.GetFirstNotNullNorWhiteSpaceValue(key1, key2, string.Empty); + } + + /// <summary> + /// Gets a string from a string dictionary, checking all keys sequentially, + /// stopping at the first key that returns a result that's neither null nor blank. + /// </summary> + /// <param name="dictionary">The dictionary.</param> + /// <param name="key1">The first checked key.</param> + /// <param name="key2">The second checked key.</param> + /// <param name="key3">The third checked key.</param> + /// <returns>System.String.</returns> + public static string? GetFirstNotNullNorWhiteSpaceValue(this IReadOnlyDictionary<string, string> dictionary, string key1, string key2, string key3) + { + if (dictionary.TryGetValue(key1, out var val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + if (!string.IsNullOrEmpty(key2) && dictionary.TryGetValue(key2, out val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + if (!string.IsNullOrEmpty(key3) && dictionary.TryGetValue(key3, out val) && !string.IsNullOrWhiteSpace(val)) + { + return val; + } + + return null; + } + } +} -- cgit v1.2.3 From 020c0fc4cba9657b3cddf6ea237bb00a59fdf118 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Sat, 10 Jul 2021 17:04:00 +0200 Subject: Add more artist names to the splitting whitelist --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c50a577be..feefd5348 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -39,7 +39,16 @@ namespace MediaBrowser.MediaEncoding.Probing _localization = localization; } - private IReadOnlyList<string> SplitWhitelist => _splitWhiteList ??= new string[] { "AC/DC" }; + private IReadOnlyList<string> SplitWhitelist => _splitWhiteList ??= new string[] + { + "AC/DC", + "Au/Ra", + "이달의 소녀 1/3", + "LOONA 1/3", + "LOONA / yyxy", + "LOONA / ODD EYE CIRCLE", + "KD/A" + }; public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) { -- cgit v1.2.3 From 6957bc9a12caefbf091b816f77f7b1f73c456e65 Mon Sep 17 00:00:00 2001 From: natedawg <git@natedawg.net> Date: Sat, 10 Jul 2021 16:26:42 -0700 Subject: Fix spelling of artist K/DA in splitting whitelist --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index feefd5348..c9ad3c41e 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Probing "LOONA 1/3", "LOONA / yyxy", "LOONA / ODD EYE CIRCLE", - "KD/A" + "K/DA" }; public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) -- cgit v1.2.3 From 3beda02d925c74c7a7083eaee733537f3396ec92 Mon Sep 17 00:00:00 2001 From: nyanmisaka <nst799610810@gmail.com> Date: Sun, 25 Jul 2021 00:52:16 +0800 Subject: add support for cuda tonemap and overlay --- .../MediaEncoding/EncodingHelper.cs | 385 ++++++++++++++++----- .../MediaEncoding/FilterOptionType.cs | 23 ++ .../MediaEncoding/IMediaEncoder.cs | 14 +- .../Encoder/EncoderValidator.cs | 102 +++++- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 39 ++- .../Probing/ProbeResultNormalizer.cs | 17 + 6 files changed, 477 insertions(+), 103 deletions(-) create mode 100644 MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 257cd5df6..b12cacb6f 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -40,6 +40,8 @@ namespace MediaBrowser.Controller.MediaEncoding "ConstrainedHigh" }; + private static readonly Version minVersionForCudaOverlay = new Version(4, 4); + public EncodingHelper( IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder) @@ -109,17 +111,41 @@ namespace MediaBrowser.Controller.MediaEncoding private bool IsCudaSupported() { return _mediaEncoder.SupportsHwaccel("cuda") - && _mediaEncoder.SupportsFilter("scale_cuda", null) - && _mediaEncoder.SupportsFilter("yadif_cuda", null); + && _mediaEncoder.SupportsFilter("scale_cuda") + && _mediaEncoder.SupportsFilter("yadif_cuda") + && _mediaEncoder.SupportsFilter("hwupload_cuda"); } - private bool IsTonemappingSupported(EncodingJobInfo state, EncodingOptions options) + private bool IsOpenclTonemappingSupported(EncodingJobInfo state, EncodingOptions options) { var videoStream = state.VideoStream; - return IsColorDepth10(state) + if (videoStream == null) + { + return false; + } + + return (string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.ColorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) + && IsColorDepth10(state) && _mediaEncoder.SupportsHwaccel("opencl") - && options.EnableTonemapping - && string.Equals(videoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); + && _mediaEncoder.SupportsFilter("tonemap_opencl") + && options.EnableTonemapping; + } + + private bool IsCudaTonemappingSupported(EncodingJobInfo state, EncodingOptions options) + { + var videoStream = state.VideoStream; + if (videoStream == null) + { + return false; + } + + return (string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) + || string.Equals(videoStream.ColorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) + && IsColorDepth10(state) + && _mediaEncoder.SupportsHwaccel("cuda") + && _mediaEncoder.SupportsFilterWithOption(FilterOptionType.TonemapCudaName) + && options.EnableTonemapping; } private bool IsVppTonemappingSupported(EncodingJobInfo state, EncodingOptions options) @@ -135,23 +161,25 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) { // Limited to HEVC for now since the filter doesn't accept master data from VP9. - return IsColorDepth10(state) + return string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) + && IsColorDepth10(state) && string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) && _mediaEncoder.SupportsHwaccel("vaapi") - && options.EnableVppTonemapping - && string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase); + && _mediaEncoder.SupportsFilter("tonemap_vaapi") + && options.EnableVppTonemapping; } // Hybrid VPP tonemapping for QSV with VAAPI if (OperatingSystem.IsLinux() && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { // Limited to HEVC for now since the filter doesn't accept master data from VP9. - return IsColorDepth10(state) + return string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) + && IsColorDepth10(state) && string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) && _mediaEncoder.SupportsHwaccel("vaapi") + && _mediaEncoder.SupportsFilter("tonemap_vaapi") && _mediaEncoder.SupportsHwaccel("qsv") - && options.EnableVppTonemapping - && string.Equals(videoStream.ColorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase); + && options.EnableVppTonemapping; } // Native VPP tonemapping may come to QSV in the future. @@ -489,11 +517,14 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Gets the input argument. /// </summary> - public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions) + public string GetInputArgument(EncodingJobInfo state, EncodingOptions options) { var arg = new StringBuilder(); - var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty; - var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty; + var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty; + var outputVideoCodec = GetVideoEncoder(state, options) ?? string.Empty; + var isWindows = OperatingSystem.IsWindows(); + var isLinux = OperatingSystem.IsLinux(); + var isMacOS = OperatingSystem.IsMacOS(); var isSwDecoder = string.IsNullOrEmpty(videoDecoder); var isD3d11vaDecoder = videoDecoder.IndexOf("d3d11va", StringComparison.OrdinalIgnoreCase) != -1; var isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1; @@ -502,26 +533,24 @@ namespace MediaBrowser.Controller.MediaEncoding var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase); var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); - var isWindows = OperatingSystem.IsWindows(); - var isLinux = OperatingSystem.IsLinux(); - var isMacOS = OperatingSystem.IsMacOS(); - var isTonemappingSupported = IsTonemappingSupported(state, encodingOptions); - var isVppTonemappingSupported = IsVppTonemappingSupported(state, encodingOptions); + var isCuvidVp9Decoder = videoDecoder.Contains("vp9_cuvid", StringComparison.OrdinalIgnoreCase); + var isOpenclTonemappingSupported = IsOpenclTonemappingSupported(state, options); + var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); + var isCudaTonemappingSupported = IsCudaTonemappingSupported(state, options); if (!IsCopyCodec(outputVideoCodec)) { if (state.IsVideoRequest && _mediaEncoder.SupportsHwaccel("vaapi") - && string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) + && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)) { if (isVaapiDecoder) { - if (isTonemappingSupported && !isVppTonemappingSupported) + if (isOpenclTonemappingSupported && !isVppTonemappingSupported) { arg.Append("-init_hw_device vaapi=va:") - .Append(encodingOptions.VaapiDevice) - .Append(' ') - .Append("-init_hw_device opencl=ocl@va ") + .Append(options.VaapiDevice) + .Append(" -init_hw_device opencl=ocl@va ") .Append("-hwaccel_device va ") .Append("-hwaccel_output_format vaapi ") .Append("-filter_hw_device ocl "); @@ -530,14 +559,14 @@ namespace MediaBrowser.Controller.MediaEncoding { arg.Append("-hwaccel_output_format vaapi ") .Append("-vaapi_device ") - .Append(encodingOptions.VaapiDevice) + .Append(options.VaapiDevice) .Append(' '); } } else if (!isVaapiDecoder && isVaapiEncoder) { arg.Append("-vaapi_device ") - .Append(encodingOptions.VaapiDevice) + .Append(options.VaapiDevice) .Append(' '); } @@ -545,7 +574,7 @@ namespace MediaBrowser.Controller.MediaEncoding } if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + && string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; @@ -581,9 +610,8 @@ namespace MediaBrowser.Controller.MediaEncoding else if (isVaapiDecoder && isVppTonemappingSupported) { arg.Append("-init_hw_device vaapi=va:") - .Append(encodingOptions.VaapiDevice) - .Append(' ') - .Append("-init_hw_device qsv@va ") + .Append(options.VaapiDevice) + .Append(" -init_hw_device qsv@va ") .Append("-hwaccel_output_format vaapi "); } @@ -592,7 +620,7 @@ namespace MediaBrowser.Controller.MediaEncoding } if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) + && string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && isNvdecDecoder) { // Fix for 'No decoder surfaces left' error. https://trac.ffmpeg.org/ticket/7562 @@ -600,22 +628,31 @@ namespace MediaBrowser.Controller.MediaEncoding } if (state.IsVideoRequest - && ((string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) - && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder)) - || (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) - && (isD3d11vaDecoder || isSwDecoder)))) + && ((string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) + && (isNvdecDecoder || isCuvidHevcDecoder || isCuvidVp9Decoder || isSwDecoder)))) + { + if (!isCudaTonemappingSupported && isOpenclTonemappingSupported) + { + arg.Append("-init_hw_device opencl=ocl:") + .Append(options.OpenclDevice) + .Append(" -filter_hw_device ocl "); + } + } + + if (state.IsVideoRequest + && string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) + && (isD3d11vaDecoder || isSwDecoder)) { - if (isTonemappingSupported) + if (isOpenclTonemappingSupported) { arg.Append("-init_hw_device opencl=ocl:") - .Append(encodingOptions.OpenclDevice) - .Append(' ') - .Append("-filter_hw_device ocl "); + .Append(options.OpenclDevice) + .Append(" -filter_hw_device ocl "); } } if (state.IsVideoRequest - && string.Equals(encodingOptions.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase)) + && string.Equals(options.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase)) { arg.Append("-hwaccel videotoolbox "); } @@ -1991,14 +2028,18 @@ namespace MediaBrowser.Controller.MediaEncoding var isQsvHevcEncoder = outputVideoCodec.Contains("hevc_qsv", StringComparison.OrdinalIgnoreCase); var isNvdecDecoder = videoDecoder.Contains("cuda", StringComparison.OrdinalIgnoreCase); var isNvencEncoder = outputVideoCodec.Contains("nvenc", StringComparison.OrdinalIgnoreCase); - var isTonemappingSupported = IsTonemappingSupported(state, options); - var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder); var isTonemappingSupportedOnQsv = string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isQsvH264Encoder || isQsvHevcEncoder); + var isOpenclTonemappingSupported = IsOpenclTonemappingSupported(state, options); + var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); + + var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; + var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.ScaleCudaFormat); // Tonemapping and burn-in graphical subtitles requires overlay_vaapi. // But it's still in ffmpeg mailing list. Disable it for now. - if (isTonemappingSupportedOnVaapi && isTonemappingSupported && !isVppTonemappingSupported) + if (isTonemappingSupportedOnVaapi && isOpenclTonemappingSupported && !isVppTonemappingSupported) { return GetOutputSizeParam(state, options, outputVideoCodec); } @@ -2024,13 +2065,22 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(videoSizeParam) && !(isTonemappingSupportedOnQsv && isVppTonemappingSupported)) { - // For QSV, feed it into hardware encoder now + // upload graphical subtitle to QSV if (isLinux && (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase))) { videoSizeParam += ",hwupload=extra_hw_frames=64"; } } + + if (!string.IsNullOrEmpty(videoSizeParam)) + { + // upload graphical subtitle to cuda + if (isNvdecDecoder && isNvencEncoder && isCudaOverlaySupported && isCudaFormatConversionSupported) + { + videoSizeParam += ",hwupload_cuda"; + } + } } var mapPrefix = state.SubtitleStream.IsExternal ? @@ -2043,9 +2093,9 @@ namespace MediaBrowser.Controller.MediaEncoding // Setup default filtergraph utilizing FFMpeg overlay() and FFMpeg scale() (see the return of this function for index reference) // Always put the scaler before the overlay for better performance - var retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\""; + var retStr = outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\""; // When the input may or may not be hardware VAAPI decodable if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) @@ -2056,9 +2106,9 @@ namespace MediaBrowser.Controller.MediaEncoding [sub]: SW scaling subtitle to FixedOutputSize [base][sub]: SW overlay */ - retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3},hwdownload[base];[base][sub]overlay,format=nv12,hwupload\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]hwdownload[base];[base][sub]overlay,format=nv12,hwupload\""; + retStr = outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]hwdownload[base];[base][sub]overlay,format=nv12,hwupload\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3},hwdownload[base];[base][sub]overlay,format=nv12,hwupload\""; } // If we're hardware VAAPI decoding and software encoding, download frames from the decoder first @@ -2071,9 +2121,9 @@ namespace MediaBrowser.Controller.MediaEncoding [sub]: SW scaling subtitle to FixedOutputSize [base][sub]: SW overlay */ - retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\""; + retStr = outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\""; } else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(outputVideoCodec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) @@ -2090,16 +2140,25 @@ namespace MediaBrowser.Controller.MediaEncoding } else if (isLinux) { - retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv\""; + retStr = outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_qsv\""; } } else if (isNvdecDecoder && isNvencEncoder) { - retStr = !outputSizeParam.IsEmpty - ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay,format=nv12|yuv420p,hwupload_cuda\"" - : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay,format=nv12|yuv420p,hwupload_cuda\""; + if (isCudaOverlaySupported && isCudaFormatConversionSupported) + { + retStr = outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]scale_cuda=format=yuv420p[base];[base][sub]overlay_cuda\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay_cuda\""; + } + else + { + retStr = !outputSizeParam.IsEmpty + ? " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay,format=nv12|yuv420p,hwupload_cuda\"" + : " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay,format=nv12|yuv420p,hwupload_cuda\""; + } } return string.Format( @@ -2196,11 +2255,11 @@ namespace MediaBrowser.Controller.MediaEncoding var isVaapiHevcEncoder = videoEncoder.Contains("hevc_vaapi", StringComparison.OrdinalIgnoreCase); var isQsvH264Encoder = videoEncoder.Contains("h264_qsv", StringComparison.OrdinalIgnoreCase); var isQsvHevcEncoder = videoEncoder.Contains("hevc_qsv", StringComparison.OrdinalIgnoreCase); - var isTonemappingSupported = IsTonemappingSupported(state, options); + var isOpenclTonemappingSupported = IsOpenclTonemappingSupported(state, options); var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder); var isTonemappingSupportedOnQsv = string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isQsvH264Encoder || isQsvHevcEncoder); - var isP010PixFmtRequired = (isTonemappingSupportedOnVaapi && (isTonemappingSupported || isVppTonemappingSupported)) + var isP010PixFmtRequired = (isTonemappingSupportedOnVaapi && (isOpenclTonemappingSupported || isVppTonemappingSupported)) || (isTonemappingSupportedOnQsv && isVppTonemappingSupported); var outputPixFmt = "format=nv12"; @@ -2251,15 +2310,23 @@ namespace MediaBrowser.Controller.MediaEncoding var outputWidth = width.Value; var outputHeight = height.Value; - var isTonemappingSupported = IsTonemappingSupported(state, options); + var isNvencEncoder = videoEncoder.Contains("nvenc", StringComparison.OrdinalIgnoreCase); + var isOpenclTonemappingSupported = IsOpenclTonemappingSupported(state, options); + var isCudaTonemappingSupported = IsCudaTonemappingSupported(state, options); var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase); - var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilter("scale_cuda", "Output format (default \"same\")"); + var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; + var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.ScaleCudaFormat); + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var outputPixFmt = string.Empty; if (isCudaFormatConversionSupported) { - outputPixFmt = "format=nv12"; - if (isTonemappingSupported && isTonemappingSupportedOnNvenc) + outputPixFmt = (hasGraphicalSubs && isCudaOverlaySupported && isNvencEncoder) + ? "format=yuv420p" + : "format=nv12"; + if ((isOpenclTonemappingSupported || isCudaTonemappingSupported) + && isTonemappingSupportedOnNvenc) { outputPixFmt = "format=p010"; } @@ -2525,16 +2592,21 @@ namespace MediaBrowser.Controller.MediaEncoding var isNvencEncoder = outputVideoCodec.Contains("nvenc", StringComparison.OrdinalIgnoreCase); var isCuvidH264Decoder = videoDecoder.Contains("h264_cuvid", StringComparison.OrdinalIgnoreCase); var isCuvidHevcDecoder = videoDecoder.Contains("hevc_cuvid", StringComparison.OrdinalIgnoreCase); + var isCuvidVp9Decoder = videoDecoder.Contains("vp9_cuvid", StringComparison.OrdinalIgnoreCase); var isLibX264Encoder = outputVideoCodec.IndexOf("libx264", StringComparison.OrdinalIgnoreCase) != -1; var isLibX265Encoder = outputVideoCodec.IndexOf("libx265", StringComparison.OrdinalIgnoreCase) != -1; var isLinux = OperatingSystem.IsLinux(); var isColorDepth10 = IsColorDepth10(state); - var isTonemappingSupported = IsTonemappingSupported(state, options); - var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); - var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder); + + var isTonemappingSupportedOnNvenc = string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase) && (isNvdecDecoder || isCuvidHevcDecoder || isCuvidVp9Decoder || isSwDecoder); var isTonemappingSupportedOnAmf = string.Equals(options.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase) && (isD3d11vaDecoder || isSwDecoder); var isTonemappingSupportedOnVaapi = string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isVaapiH264Encoder || isVaapiHevcEncoder); var isTonemappingSupportedOnQsv = string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && isVaapiDecoder && (isQsvH264Encoder || isQsvHevcEncoder); + var isOpenclTonemappingSupported = IsOpenclTonemappingSupported(state, options); + var isVppTonemappingSupported = IsVppTonemappingSupported(state, options); + var isCudaTonemappingSupported = IsCudaTonemappingSupported(state, options); + var mediaEncoderVersion = _mediaEncoder.GetMediaEncoderVersion(); + var isCudaOverlaySupported = _mediaEncoder.SupportsFilter("overlay_cuda") && mediaEncoderVersion != null && mediaEncoderVersion >= minVersionForCudaOverlay; var hasSubs = state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; @@ -2546,19 +2618,25 @@ namespace MediaBrowser.Controller.MediaEncoding var isScalingInAdvance = false; var isCudaDeintInAdvance = false; var isHwuploadCudaRequired = false; + var isNoTonemapFilterApplied = true; var isDeinterlaceH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true); var isDeinterlaceHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true); // Add OpenCL tonemapping filter for NVENC/AMF/VAAPI. - if (isTonemappingSupportedOnNvenc || isTonemappingSupportedOnAmf || (isTonemappingSupportedOnVaapi && !isVppTonemappingSupported)) + if ((isTonemappingSupportedOnNvenc && !isCudaTonemappingSupported) || isTonemappingSupportedOnAmf || (isTonemappingSupportedOnVaapi && !isVppTonemappingSupported)) { - // Currently only with the use of NVENC decoder can we get a decent performance. - // Currently only the HEVC/H265 format is supported with NVDEC decoder. // NVIDIA Pascal and Turing or higher are recommended. // AMD Polaris and Vega or higher are recommended. // Intel Kaby Lake or newer is required. - if (isTonemappingSupported) + if (isOpenclTonemappingSupported) { + isNoTonemapFilterApplied = false; + var inputHdrParams = GetInputHdrParams(videoStream.ColorTransfer); + if (!string.IsNullOrEmpty(inputHdrParams)) + { + filters.Add(inputHdrParams); + } + var parameters = "tonemap_opencl=format=nv12:primaries=bt709:transfer=bt709:matrix=bt709:tonemap={0}:desat={1}:threshold={2}:peak={3}"; if (options.TonemappingParam != 0) @@ -2630,7 +2708,11 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwdownload,format=p010"); } - if (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder || isD3d11vaDecoder) + if (isNvdecDecoder + || isCuvidHevcDecoder + || isCuvidVp9Decoder + || isSwDecoder + || isD3d11vaDecoder) { // Upload the HDR10 or HLG data to the OpenCL device, // use tonemap_opencl filter for tone mapping, @@ -2638,6 +2720,14 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload"); } + // Fallback to hable if bt2390 is chosen but not supported in tonemap_opencl. + var isBt2390SupportedInOpenclTonemap = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.TonemapOpenclBt2390); + if (string.Equals(options.TonemappingAlgorithm, "bt2390", StringComparison.OrdinalIgnoreCase) + && !isBt2390SupportedInOpenclTonemap) + { + options.TonemappingAlgorithm = "hable"; + } + filters.Add( string.Format( CultureInfo.InvariantCulture, @@ -2649,7 +2739,11 @@ namespace MediaBrowser.Controller.MediaEncoding options.TonemappingParam, options.TonemappingRange)); - if (isNvdecDecoder || isCuvidHevcDecoder || isSwDecoder || isD3d11vaDecoder) + if (isNvdecDecoder + || isCuvidHevcDecoder + || isCuvidVp9Decoder + || isSwDecoder + || isD3d11vaDecoder) { filters.Add("hwdownload"); filters.Add("format=nv12"); @@ -2665,12 +2759,18 @@ namespace MediaBrowser.Controller.MediaEncoding // Reverse the data route from opencl to vaapi. filters.Add("hwmap=derive_device=vaapi:reverse=1"); } + + var outputSdrParams = GetOutputSdrParams(options.TonemappingRange); + if (!string.IsNullOrEmpty(outputSdrParams)) + { + filters.Add(outputSdrParams); + } } } // When the input may or may not be hardware VAAPI decodable. if ((isVaapiH264Encoder || isVaapiHevcEncoder) - && !(isTonemappingSupportedOnVaapi && (isTonemappingSupported || isVppTonemappingSupported))) + && !(isTonemappingSupportedOnVaapi && (isOpenclTonemappingSupported || isVppTonemappingSupported))) { filters.Add("format=nv12|vaapi"); filters.Add("hwupload"); @@ -2778,6 +2878,61 @@ namespace MediaBrowser.Controller.MediaEncoding request.MaxHeight)); } + // Add Cuda tonemapping filter. + if (isNvdecDecoder && isCudaTonemappingSupported) + { + isNoTonemapFilterApplied = false; + var inputHdrParams = GetInputHdrParams(videoStream.ColorTransfer); + if (!string.IsNullOrEmpty(inputHdrParams)) + { + filters.Add(inputHdrParams); + } + + var parameters = (hasGraphicalSubs && isCudaOverlaySupported && isNvencEncoder) + ? "tonemap_cuda=format=yuv420p:primaries=bt709:transfer=bt709:matrix=bt709:tonemap={0}:peak={1}:desat={2}" + : "tonemap_cuda=format=nv12:primaries=bt709:transfer=bt709:matrix=bt709:tonemap={0}:peak={1}:desat={2}"; + + if (options.TonemappingParam != 0) + { + parameters += ":param={3}"; + } + + if (!string.Equals(options.TonemappingRange, "auto", StringComparison.OrdinalIgnoreCase)) + { + parameters += ":range={4}"; + } + + filters.Add( + string.Format( + CultureInfo.InvariantCulture, + parameters, + options.TonemappingAlgorithm, + options.TonemappingPeak, + options.TonemappingDesat, + options.TonemappingParam, + options.TonemappingRange)); + + if (isLibX264Encoder + || isLibX265Encoder + || hasTextSubs + || (hasGraphicalSubs && !isCudaOverlaySupported && isNvencEncoder)) + { + if (isNvencEncoder) + { + isHwuploadCudaRequired = true; + } + + filters.Add("hwdownload"); + filters.Add("format=nv12"); + } + + var outputSdrParams = GetOutputSdrParams(options.TonemappingRange); + if (!string.IsNullOrEmpty(outputSdrParams)) + { + filters.Add(outputSdrParams); + } + } + // Add VPP tonemapping filter for VAAPI. // Full hardware based video post processing, faster than OpenCL but lacks fine tuning options. if ((isTonemappingSupportedOnVaapi || isTonemappingSupportedOnQsv) @@ -2787,10 +2942,10 @@ namespace MediaBrowser.Controller.MediaEncoding } // Another case is when using Nvenc decoder. - if (isNvdecDecoder && !isTonemappingSupported) + if (isNvdecDecoder && !isOpenclTonemappingSupported && !isCudaTonemappingSupported) { var codec = videoStream.Codec; - var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilter("scale_cuda", "Output format (default \"same\")"); + var isCudaFormatConversionSupported = _mediaEncoder.SupportsFilterWithOption(FilterOptionType.ScaleCudaFormat); // Assert 10-bit hardware decodable if (isColorDepth10 && (string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase) @@ -2799,7 +2954,10 @@ namespace MediaBrowser.Controller.MediaEncoding { if (isCudaFormatConversionSupported) { - if (isLibX264Encoder || isLibX265Encoder || hasSubs) + if (isLibX264Encoder + || isLibX265Encoder + || hasTextSubs + || (hasGraphicalSubs && !isCudaOverlaySupported && isNvencEncoder)) { if (isNvencEncoder) { @@ -2826,7 +2984,11 @@ namespace MediaBrowser.Controller.MediaEncoding } // Assert 8-bit hardware decodable - else if (!isColorDepth10 && (isLibX264Encoder || isLibX265Encoder || hasSubs)) + else if (!isColorDepth10 + && (isLibX264Encoder + || isLibX265Encoder + || hasTextSubs + || (hasGraphicalSubs && !isCudaOverlaySupported && isNvencEncoder))) { if (isNvencEncoder) { @@ -2847,7 +3009,7 @@ namespace MediaBrowser.Controller.MediaEncoding { // Convert hw context from ocl to va. // For tonemapping and text subs burn-in. - if (isTonemappingSupportedOnVaapi && isTonemappingSupported && !isVppTonemappingSupported) + if (isTonemappingSupportedOnVaapi && isOpenclTonemappingSupported && !isVppTonemappingSupported) { filters.Add("scale_vaapi"); } @@ -2893,6 +3055,17 @@ namespace MediaBrowser.Controller.MediaEncoding filters.Add("hwupload_cuda"); } + // If no tonemap filter is applied, + // tag the video range as SDR to prevent the encoder from encoding HDR video. + if (isNoTonemapFilterApplied) + { + var outputSdrParams = GetOutputSdrParams(null); + if (!string.IsNullOrEmpty(outputSdrParams)) + { + filters.Add(outputSdrParams); + } + } + var output = string.Empty; if (filters.Count > 0) { @@ -2905,6 +3078,36 @@ namespace MediaBrowser.Controller.MediaEncoding return output; } + public static string GetInputHdrParams(string colorTransfer) + { + if (string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) + { + // HLG + return "setparams=color_primaries=bt2020:color_trc=arib-std-b67:colorspace=bt2020nc"; + } + else + { + // HDR10 + return "setparams=color_primaries=bt2020:color_trc=smpte2084:colorspace=bt2020nc"; + } + } + + public static string GetOutputSdrParams(string tonemappingRange) + { + // SDR + if (string.Equals(tonemappingRange, "tv", StringComparison.OrdinalIgnoreCase)) + { + return "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv"; + } + + if (string.Equals(tonemappingRange, "pc", StringComparison.OrdinalIgnoreCase)) + { + return "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=pc"; + } + + return "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709"; + } + /// <summary> /// Gets the number of threads. /// </summary> @@ -3371,8 +3574,13 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) && IsVppTonemappingSupported(state, encodingOptions)) { - // Since tonemap_vaapi only support HEVC for now, no need to check the codec again. - return GetHwaccelType(state, encodingOptions, "hevc", isColorDepth10); + var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty; + var isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1; + if (isQsvEncoder) + { + // Since tonemap_vaapi only support HEVC for now, no need to check the codec again. + return GetHwaccelType(state, encodingOptions, "hevc", isColorDepth10); + } } if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) @@ -3895,6 +4103,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (videoStream != null) { + if (videoStream.BitDepth.HasValue) + { + return videoStream.BitDepth.Value == 10; + } + if (!string.IsNullOrEmpty(videoStream.PixelFormat)) { result = videoStream.PixelFormat.Contains("p10", StringComparison.OrdinalIgnoreCase); @@ -3914,12 +4127,6 @@ namespace MediaBrowser.Controller.MediaEncoding return true; } } - - result = (videoStream.BitDepth ?? 8) == 10; - if (result) - { - return true; - } } return result; diff --git a/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs b/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs new file mode 100644 index 000000000..7ce707b19 --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs @@ -0,0 +1,23 @@ +namespace MediaBrowser.Controller.MediaEncoding +{ + /// <summary> + /// Enum FilterOptionType. + /// </summary> + public enum FilterOptionType + { + /// <summary> + /// The scale_cuda_format. + /// </summary> + ScaleCudaFormat = 0, + + /// <summary> + /// The tonemap_cuda_name. + /// </summary> + TonemapCudaName = 1, + + /// <summary> + /// The tonemap_opencl_bt2390. + /// </summary> + TonemapOpenclBt2390 = 2 + } +} diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 76a9fd7c7..31913acef 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -55,9 +55,21 @@ namespace MediaBrowser.Controller.MediaEncoding /// Whether given filter is supported. /// </summary> /// <param name="filter">The filter.</param> + /// <returns><c>true</c> if the filter is supported, <c>false</c> otherwise.</returns> + bool SupportsFilter(string filter); + + /// <summary> + /// Whether filter is supported with the given option. + /// </summary> /// <param name="option">The option.</param> /// <returns><c>true</c> if the filter is supported, <c>false</c> otherwise.</returns> - bool SupportsFilter(string filter, string option); + bool SupportsFilterWithOption(FilterOptionType option); + + /// <summary> + /// Get the version of media encoder. + /// </summary> + /// <returns>The version of media encoder.</returns> + Version GetMediaEncoderVersion(); /// <summary> /// Extracts the audio image. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f782e65bd..1ec159c9a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -89,6 +89,24 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc_videotoolbox" }; + private static readonly string[] _requiredFilters = new[] + { + "scale_cuda", + "yadif_cuda", + "hwupload_cuda", + "overlay_cuda", + "tonemap_cuda", + "tonemap_opencl", + "tonemap_vaapi", + }; + + private static readonly IReadOnlyDictionary<int, string[]> _filterOptionsDict = new Dictionary<int, string[]> + { + { 0, new string[] { "scale_cuda", "Output format (default \"same\")" } }, + { 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } }, + { 2, new string[] { "tonemap_opencl", "bt2390" } } + }; + // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below private static readonly IReadOnlyDictionary<string, Version> _ffmpegMinimumLibraryVersions = new Dictionary<string, Version> { @@ -156,7 +174,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Work out what the version under test is - var version = GetFFmpegVersion(versionOutput); + var version = GetFFmpegVersionInternal(versionOutput); _logger.LogInformation("Found ffmpeg version {Version}", version != null ? version.ToString() : "unknown"); @@ -200,6 +218,34 @@ namespace MediaBrowser.MediaEncoding.Encoder public IEnumerable<string> GetHwaccels() => GetHwaccelTypes(); + public IEnumerable<string> GetFilters() => GetFFmpegFilters(); + + public IDictionary<int, bool> GetFiltersWithOption() => GetFFmpegFiltersWithOption(); + + public Version? GetFFmpegVersion() + { + string output; + try + { + output = GetProcessOutput(_encoderPath, "-version"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error validating encoder"); + return null; + } + + if (string.IsNullOrWhiteSpace(output)) + { + _logger.LogError("FFmpeg validation: The process returned no result"); + return null; + } + + _logger.LogDebug("ffmpeg output: {Output}", output); + + return GetFFmpegVersionInternal(output); + } + /// <summary> /// Using the output from "ffmpeg -version" work out the FFmpeg version. /// For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy @@ -208,7 +254,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// </summary> /// <param name="output">The output from "ffmpeg -version".</param> /// <returns>The FFmpeg version.</returns> - internal Version? GetFFmpegVersion(string output) + internal Version? GetFFmpegVersionInternal(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output var match = Regex.Match(output, @"^ffmpeg version n?((?:[0-9]+\.?)+)"); @@ -297,9 +343,9 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } - public bool CheckFilter(string filter, string option) + public bool CheckFilterWithOption(string filter, string option) { - if (string.IsNullOrEmpty(filter)) + if (string.IsNullOrEmpty(filter) || string.IsNullOrEmpty(option)) { return false; } @@ -317,11 +363,6 @@ namespace MediaBrowser.MediaEncoding.Encoder if (output.Contains("Filter " + filter, StringComparison.Ordinal)) { - if (string.IsNullOrEmpty(option)) - { - return true; - } - return output.Contains(option, StringComparison.Ordinal); } @@ -362,6 +403,49 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } + private IEnumerable<string> GetFFmpegFilters() + { + string output; + try + { + output = GetProcessOutput(_encoderPath, "-filters"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error detecting available filters"); + return Enumerable.Empty<string>(); + } + + if (string.IsNullOrWhiteSpace(output)) + { + return Enumerable.Empty<string>(); + } + + var found = Regex + .Matches(output, @"^\s\S{3}\s(?<filter>[\w|-]+)\s+.+$", RegexOptions.Multiline) + .Cast<Match>() + .Select(x => x.Groups["filter"].Value) + .Where(x => _requiredFilters.Contains(x)); + + _logger.LogInformation("Available filters: {Filters}", found); + + return found; + } + + private IDictionary<int, bool> GetFFmpegFiltersWithOption() + { + IDictionary<int, bool> dict = new Dictionary<int, bool>(); + for (int i = 0; i < _filterOptionsDict.Count; i++) + { + if (_filterOptionsDict.TryGetValue(i, out var val) && val.Length == 2) + { + dict.Add(i, CheckFilterWithOption(val[0], val[1])); + } + } + + return dict; + } + private string GetProcessOutput(string path, string arguments) { using (var process = new Process() diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 412a95321..238627e96 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -66,7 +66,10 @@ namespace MediaBrowser.MediaEncoding.Encoder private List<string> _encoders = new List<string>(); private List<string> _decoders = new List<string>(); private List<string> _hwaccels = new List<string>(); + private List<string> _filters = new List<string>(); + private IDictionary<int, bool> _filtersWithOption = new Dictionary<int, bool>(); + private Version _ffmpegVersion = null; private string _ffmpegPath = string.Empty; private string _ffprobePath; private int threads; @@ -130,7 +133,11 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); + SetAvailableFilters(validator.GetFilters()); + SetAvailableFiltersWithOption(validator.GetFiltersWithOption()); SetAvailableHwaccels(validator.GetHwaccels()); + SetMediaEncoderVersion(validator); + threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); } @@ -278,6 +285,21 @@ namespace MediaBrowser.MediaEncoding.Encoder _hwaccels = list.ToList(); } + public void SetAvailableFilters(IEnumerable<string> list) + { + _filters = list.ToList(); + } + + public void SetAvailableFiltersWithOption(IDictionary<int, bool> dict) + { + _filtersWithOption = dict; + } + + public void SetMediaEncoderVersion(EncoderValidator validator) + { + _ffmpegVersion = validator.GetFFmpegVersion(); + } + public bool SupportsEncoder(string encoder) { return _encoders.Contains(encoder, StringComparer.OrdinalIgnoreCase); @@ -293,17 +315,26 @@ namespace MediaBrowser.MediaEncoding.Encoder return _hwaccels.Contains(hwaccel, StringComparer.OrdinalIgnoreCase); } - public bool SupportsFilter(string filter, string option) + public bool SupportsFilter(string filter) { - if (_ffmpegPath != null) + return _filters.Contains(filter, StringComparer.OrdinalIgnoreCase); + } + + public bool SupportsFilterWithOption(FilterOptionType option) + { + if (_filtersWithOption.TryGetValue((int)option, out var val)) { - var validator = new EncoderValidator(_logger, _ffmpegPath); - return validator.CheckFilter(filter, option); + return val; } return false; } + public Version GetMediaEncoderVersion() + { + return _ffmpegVersion; + } + public bool CanEncodeToAudioCodec(string codec) { if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c9ad3c41e..d6799a170 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -739,6 +739,23 @@ namespace MediaBrowser.MediaEncoding.Probing stream.BitDepth = streamInfo.BitsPerRawSample; } + if (!stream.BitDepth.HasValue) + { + if (!string.IsNullOrEmpty(streamInfo.PixelFormat) + && streamInfo.PixelFormat.Contains("p10", StringComparison.OrdinalIgnoreCase)) + { + stream.BitDepth = 10; + } + + if (!string.IsNullOrEmpty(streamInfo.Profile) + && (streamInfo.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase) + || streamInfo.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase) + || streamInfo.Profile.Contains("Profile 2", StringComparison.OrdinalIgnoreCase))) + { + stream.BitDepth = 10; + } + } + // stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase); -- cgit v1.2.3 From c07e83fdf87e61f30e4cca4e458113ac315918ae Mon Sep 17 00:00:00 2001 From: Rich Lander <rlander@microsoft.com> Date: Fri, 30 Jul 2021 00:49:28 -0700 Subject: Invert code and style analysis configuration (#6334) Co-authored-by: Bond-009 <bond.009@outlook.com> --- Directory.Build.props | 14 ++++++++++++++ DvdLib/DvdLib.csproj | 3 ++- Emby.Dlna/Emby.Dlna.csproj | 7 +------ Emby.Drawing/Emby.Drawing.csproj | 7 +------ Emby.Naming/Emby.Naming.csproj | 4 +--- Emby.Notifications/Emby.Notifications.csproj | 4 ---- Emby.Photos/Emby.Photos.csproj | 4 ---- .../Emby.Server.Implementations.csproj | 9 +++++---- Jellyfin.Api/Jellyfin.Api.csproj | 7 +------ Jellyfin.Data/Jellyfin.Data.csproj | 4 ---- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 4 ---- Jellyfin.Networking/Jellyfin.Networking.csproj | 4 ---- .../Jellyfin.Server.Implementations.csproj | 8 -------- Jellyfin.Server/Jellyfin.Server.csproj | 5 ----- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ---- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 9 +++++---- .../MediaBrowser.LocalMetadata.csproj | 4 ---- .../MediaBrowser.MediaEncoding.csproj | 4 ---- MediaBrowser.Model/MediaBrowser.Model.csproj | 9 +++++---- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 9 ++++++--- MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 4 ---- RSSDP/RSSDP.csproj | 4 +++- src/Jellyfin.Extensions/Jellyfin.Extensions.csproj | 4 ---- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 3 --- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 3 --- .../Jellyfin.Controller.Tests.csproj | 3 --- tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 3 --- .../Jellyfin.Extensions.Tests.csproj | 3 --- .../Jellyfin.MediaEncoding.Tests.csproj | 3 --- tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj | 3 --- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 3 --- .../Jellyfin.Networking.Tests.csproj | 3 --- .../Jellyfin.Providers.Tests.csproj | 3 --- .../Jellyfin.Server.Implementations.Tests.csproj | 3 --- .../Jellyfin.Server.Integration.Tests.csproj | 3 --- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 3 --- .../Jellyfin.XbmcMetadata.Tests.csproj | 3 --- 37 files changed, 44 insertions(+), 133 deletions(-) create mode 100644 Directory.Build.props (limited to 'MediaBrowser.MediaEncoding') diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..b899999ef --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,14 @@ +<Project> + <!-- Sets defaults for all projects in the repo --> + + <PropertyGroup> + <Nullable>enable</Nullable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/jellyfin.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + </PropertyGroup> + +</Project> diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index 7bbd9acf8..b8301e2f2 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -13,7 +13,8 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> + <Nullable>disable</Nullable> </PropertyGroup> </Project> diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index a40578e40..970c16d2e 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -20,8 +20,7 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> </PropertyGroup> <!-- Code Analyzers--> @@ -31,10 +30,6 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <EmbeddedResource Include="Images\logo120.jpg" /> <EmbeddedResource Include="Images\logo120.png" /> diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 5c5afe1c6..baf350c6f 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -9,8 +9,7 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> </PropertyGroup> <ItemGroup> @@ -30,8 +29,4 @@ <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.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 3224ff412..db1b8ac9d 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -9,12 +9,11 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> - <Nullable>enable</Nullable> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> </PropertyGroup> <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> @@ -51,7 +50,6 @@ </ItemGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> </Project> diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 5a2aea642..5edcf2f29 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -9,10 +9,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 2b6618159..00b2f0f94 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -22,10 +22,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- Code Analyzers--> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index fe233df6c..4c9e05821 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -44,12 +44,13 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> <NoWarn>AD0001</NoWarn> - <AnalysisMode Condition=" '$(Configuration)' == 'Debug' ">AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <!-- Code Analyzers--> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index d1d0ac708..261637687 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -8,10 +8,9 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> <NoWarn>AD0001</NoWarn> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> </PropertyGroup> <ItemGroup> @@ -33,10 +32,6 @@ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - <ItemGroup> <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> <_Parameter1>Jellyfin.Api.Tests</_Parameter1> diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 3b14d3312..65bbd49da 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -4,10 +4,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - <Nullable>enable</Nullable> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 96fe00384..8cee5dcae 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -9,10 +9,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 63557e91f..227a41ce4 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -3,10 +3,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index f73492b7c..728f9021d 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -4,14 +4,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - </PropertyGroup> - - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- Code analysers--> diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 958a44fda..49529b794 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -12,11 +12,6 @@ <ServerGarbageCollection>false</ServerGarbageCollection> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> - <!-- <DisableImplicitAspNetCoreAnalyzers>true</DisableImplicitAspNetCoreAnalyzers> --> </PropertyGroup> <ItemGroup> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 0299a8456..12cfaf978 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -32,10 +32,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4bed112e4..0f697bccc 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -35,14 +35,15 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode Condition=" '$(Configuration)' == 'Debug' ">AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index eb2077a5f..1cf8fcd1b 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -14,10 +14,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 7733e715f..411b7c82b 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -9,10 +9,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <ItemGroup> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c475d905a..a371afc2c 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -17,14 +17,15 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode> --> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> <PublishRepositoryUrl>true</PublishRepositoryUrl> <EmbedUntrackedSources>true</EmbedUntrackedSources> <IncludeSymbols>true</IncludeSymbols> <SymbolPackageFormat>snupkg</SymbolPackageFormat> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index cdb07a15d..6174f18b2 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -29,9 +29,12 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release'">true</TreatWarningsAsErrors> - <AnalysisMode Condition=" '$(Configuration)' == 'Debug'">AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <Nullable>disable</Nullable> + </PropertyGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Release'"> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <!-- Code Analyzers--> diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 2904b40ec..3e2a9bacf 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -18,10 +18,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- Code Analyzers--> diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index c64ee9389..54113d464 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -13,7 +13,9 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <AnalysisMode>AllDisabledByDefault</AnalysisMode> + <Nullable>disable</Nullable> + <NoWarn>CA2016</NoWarn> </PropertyGroup> </Project> diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj index f343be1e3..981b796e0 100644 --- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -4,10 +4,6 @@ <TargetFramework>net5.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> - <CodeAnalysisRuleSet>../../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <PropertyGroup> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 3cbae0863..4edd84384 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index fa0ef2511..e4350c336 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 285e9a2a9..5b269a4b2 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index d7d0a8f43..713f6423c 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index c4d05b8f5..9272d5eef 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index fcd9d6cb5..a6a948e2b 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 7299a47dc..06ff22c7e 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index d7987ba96..510c8f60a 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 3078e648a..2c6e2e5f6 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 26506a92b..195fc8801 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index ae957c2ab..387f259ce 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -8,9 +8,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> <RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 982d2081a..cf4215339 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -2,9 +2,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 73c1170fd..2f95f5c01 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 278e4f076..78837bba6 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -3,9 +3,6 @@ <PropertyGroup> <TargetFramework>net5.0</TargetFramework> <IsPackable>false</IsPackable> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> - <Nullable>enable</Nullable> - <AnalysisMode>AllEnabledByDefault</AnalysisMode> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> -- cgit v1.2.3 From 534e088105641d848b5469315e27b97c6aef4aca Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Mon, 5 Jul 2021 03:27:03 +0200 Subject: Prefer original data when getting premiere date from ffprobe --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c9ad3c41e..875ee6f04 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -121,6 +121,7 @@ namespace MediaBrowser.MediaEncoding.Probing // Several different forms of retail/premiere date info.PremiereDate = + FFProbeHelpers.GetDictionaryDateTime(tags, "originaldate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ?? FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ?? -- cgit v1.2.3 From ba609aefea484b0c10a5cf366f00a252f0402243 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Mon, 5 Jul 2021 03:52:46 +0200 Subject: Attempt to parse YYYY format dates in GetDictionaryDateTime DateTime.TryParse doesn't properly parse year-only dates, so parsing results from FFProbe sometimes returns null (for example, some music tagged with Beets has yyyy format dates for release dates). As a result, Jellyfin would previously no get the date from the FFProbe results. This adds DateTime.TryParseExact with a format of 'yyyy' as a fallback, to attempt to properly parse the value, even if it's only a year. --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index d0a76c4ca..f1062a4ae 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -63,7 +63,8 @@ namespace MediaBrowser.MediaEncoding.Probing public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary<string, string> tags, string key) { if (tags.TryGetValue(key, out var val) - && DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime)) + && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) || + DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) { return dateTime.ToUniversalTime(); } -- cgit v1.2.3 From 6c2cbafee056b425291f4e762303e5399c9fb558 Mon Sep 17 00:00:00 2001 From: Julien Machiels <julien.machiels@protonmail.com> Date: Sun, 8 Aug 2021 16:37:35 +0200 Subject: Update MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs Co-authored-by: Cody Robibero <cody@robibe.ro> --- MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index f1062a4ae..9196fe139 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -63,8 +63,8 @@ namespace MediaBrowser.MediaEncoding.Probing public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary<string, string> tags, string key) { if (tags.TryGetValue(key, out var val) - && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) || - DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) + && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) + || DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) { return dateTime.ToUniversalTime(); } -- cgit v1.2.3 From c4d8e6f056605b98c36c37b9be169ee1a9030c71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:00:53 +0000 Subject: Bump UTF.Unknown from 2.3.0 to 2.4.0 Bumps [UTF.Unknown](https://github.com/CharsetDetector/UTF-unknown) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/CharsetDetector/UTF-unknown/releases) - [Commits](https://github.com/CharsetDetector/UTF-unknown/compare/v2.3...v2.4) --- updated-dependencies: - dependency-name: UTF.Unknown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 411b7c82b..6da9886a4 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -26,7 +26,7 @@ <PackageReference Include="libse" Version="3.6.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> - <PackageReference Include="UTF.Unknown" Version="2.3.0" /> + <PackageReference Include="UTF.Unknown" Version="2.4.0" /> </ItemGroup> <!-- Code Analyzers--> -- cgit v1.2.3 From 2345646ff159f474588e24c29ab94a97a4f41e6d Mon Sep 17 00:00:00 2001 From: boolemancer <boolemancer@gmail.com> Date: Sat, 14 Aug 2021 02:55:51 -0700 Subject: Fix explicit stream selection in MediaEncoder.ExtractImageInternal --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 12 ++---------- MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs | 18 +----------------- 2 files changed, 3 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 412a95321..e0a8102f9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -503,15 +503,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var inputArgument = GetInputArgument(inputFile, mediaSource); - if (isAudio) - { - if (imageStreamIndex.HasValue && imageStreamIndex.Value > 0) - { - // It seems for audio files we need to subtract 1 (for the audio stream??) - imageStreamIndex = imageStreamIndex.Value - 1; - } - } - else + if (!isAudio) { // The failure of HDR extraction usually occurs when using custom ffmpeg that does not contain the zscale filter. try @@ -582,7 +574,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _ => string.Empty }; - var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; + var mapArg = imageStreamIndex.HasValue ? (" -map 0:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; var enableHdrExtraction = allowTonemap && string.Equals(videoStream?.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase); if (enableHdrExtraction) diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 30af6710a..453938be7 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -88,22 +88,6 @@ namespace MediaBrowser.Providers.MediaInfo if (imageStream != null) { - // Instead of using the raw stream index, we need to use nth video/embedded image stream - var videoIndex = -1; - foreach (var mediaStream in mediaStreams) - { - if (mediaStream.Type == MediaStreamType.Video || - mediaStream.Type == MediaStreamType.EmbeddedImage) - { - videoIndex++; - } - - if (mediaStream == imageStream) - { - break; - } - } - MediaSourceInfo mediaSource = new MediaSourceInfo { VideoType = item.VideoType, @@ -111,7 +95,7 @@ namespace MediaBrowser.Providers.MediaInfo Protocol = item.PathProtocol.Value, }; - extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, imageStream, videoIndex, cancellationToken).ConfigureAwait(false); + extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false); } else { -- cgit v1.2.3 From f35a527608fb3f6efde3f76042e0e701768eb3f2 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Tue, 27 Jul 2021 17:09:23 +0200 Subject: Add performers to the ffprobe normalization for audio --- .../Probing/ProbeResultNormalizer.cs | 21 +++++++++++++++++++++ .../Probing/ProbeResultNormalizerTests.cs | 5 ++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 875ee6f04..20dead077 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Xml; using Jellyfin.Extensions; using MediaBrowser.Controller.Library; @@ -1111,6 +1112,26 @@ namespace MediaBrowser.MediaEncoding.Probing } } + if (tags.TryGetValue("performer", out var performer) && !string.IsNullOrWhiteSpace(performer)) + { + foreach (var person in Split(performer, false)) + { + Regex pattern = new Regex(@"(?<name>.*) \((?<instrument>.*)\)"); + Match match = pattern.Match(person); + + // If the performer doesn't have any instrument/role associated, it won't match. In that case, chances are it's simply a band name, so we skip it. + if (match.Success) + { + people.Add(new BaseItemPerson + { + Name = match.Groups["name"].Value, + Type = PersonType.Actor, + Role = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(match.Groups["instrument"].Value) + }); + } + } + } + // Check for writer some music is tagged that way as alternative to composer/lyricist if (tags.TryGetValue("writer", out var writer) && !string.IsNullOrWhiteSpace(writer)) { diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 4d6b7a514..928f275d7 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -107,7 +107,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal(2020, res.ProductionYear); Assert.True(res.PremiereDate.HasValue); Assert.Equal(DateTime.Parse("2020-10-26T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); - Assert.Equal(4, res.People.Length); + Assert.Equal(18, res.People.Length); Assert.Equal("Krysta Youngs", res.People[0].Name); Assert.Equal(PersonType.Composer, res.People[0].Type); Assert.Equal("Julia Ross", res.People[1].Name); @@ -116,6 +116,9 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal(PersonType.Composer, res.People[2].Type); Assert.Equal("Ji-hyo Park", res.People[3].Name); Assert.Equal(PersonType.Lyricist, res.People[3].Type); + Assert.Equal("Yiwoomin", res.People[4].Name); + Assert.Equal(PersonType.Actor, res.People[4].Type); + Assert.Equal("Electric Piano", res.People[4].Role); Assert.Equal(4, res.Genres.Length); Assert.Contains("Electronic", res.Genres); Assert.Contains("Trance", res.Genres); -- cgit v1.2.3 From c9b1cd1d8cfa3764eff3dfe97baac10ce229d2e9 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Tue, 27 Jul 2021 23:52:05 +0200 Subject: Add some new music-related person types and parse from ffprobe --- .../Probing/ProbeResultNormalizer.cs | 34 ++++++++++++++++++- MediaBrowser.Model/Entities/PersonType.cs | 38 +++++++++++++++++----- .../Probing/ProbeResultNormalizerTests.cs | 2 +- 3 files changed, 63 insertions(+), 11 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 20dead077..aa6674468 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1132,7 +1132,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - // Check for writer some music is tagged that way as alternative to composer/lyricist + // In cases where there isn't sufficient information as to which role a writer performed on a recording, tagging software uses the "writer" tag. if (tags.TryGetValue("writer", out var writer) && !string.IsNullOrWhiteSpace(writer)) { foreach (var person in Split(writer, false)) @@ -1141,6 +1141,38 @@ namespace MediaBrowser.MediaEncoding.Probing } } + if (tags.TryGetValue("arranger", out var arranger) && !string.IsNullOrWhiteSpace(arranger)) + { + foreach (var person in Split(arranger, false)) + { + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Arranger }); + } + } + + if (tags.TryGetValue("engineer", out var engineer) && !string.IsNullOrWhiteSpace(engineer)) + { + foreach (var person in Split(engineer, false)) + { + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Engineer }); + } + } + + if (tags.TryGetValue("mixer", out var mixer) && !string.IsNullOrWhiteSpace(mixer)) + { + foreach (var person in Split(mixer, false)) + { + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Mixer }); + } + } + + if (tags.TryGetValue("remixer", out var remixer) && !string.IsNullOrWhiteSpace(remixer)) + { + foreach (var person in Split(remixer, false)) + { + people.Add(new BaseItemPerson { Name = person, Type = PersonType.Remixer }); + } + } + audio.People = people.ToArray(); // Set album artist diff --git a/MediaBrowser.Model/Entities/PersonType.cs b/MediaBrowser.Model/Entities/PersonType.cs index 81db9c613..7b780f7d7 100644 --- a/MediaBrowser.Model/Entities/PersonType.cs +++ b/MediaBrowser.Model/Entities/PersonType.cs @@ -1,42 +1,42 @@ namespace MediaBrowser.Model.Entities { /// <summary> - /// Struct PersonType. + /// Types of persons. /// </summary> - public class PersonType + public static class PersonType { /// <summary> - /// The actor. + /// A person whose profession is acting on the stage, in films, or on television. /// </summary> public const string Actor = "Actor"; /// <summary> - /// The director. + /// A person who supervises the actors and other staff in a film, play, or similar production. /// </summary> public const string Director = "Director"; /// <summary> - /// The composer. + /// A person who writes music, especially as a professional occupation. /// </summary> public const string Composer = "Composer"; /// <summary> - /// The writer. + /// A writer of a book, article, or document. Can also be used as a generic term for music writer if there is a lack of specificity. /// </summary> public const string Writer = "Writer"; /// <summary> - /// The guest star. + /// A well-known actor or other performer who appears in a work in which they do not have a regular role. /// </summary> public const string GuestStar = "GuestStar"; /// <summary> - /// The producer. + /// A person responsible for the financial and managerial aspects of the making of a film or broadcast or for staging a play, opera, etc. /// </summary> public const string Producer = "Producer"; /// <summary> - /// The conductor. + /// A person who directs the performance of an orchestra or choir. /// </summary> public const string Conductor = "Conductor"; @@ -44,5 +44,25 @@ namespace MediaBrowser.Model.Entities /// The lyricist. /// </summary> public const string Lyricist = "Lyricist"; + + /// <summary> + /// A person who writes the words to a song or musical. + /// </summary> + public const string Arranger = "Arranger"; + + /// <summary> + /// An audio engineer who performed a general engineering role. + /// </summary> + public const string Engineer = "Engineer"; + + /// <summary> + /// An engineer responsible for using a mixing console to mix a recorded track into a single piece of music suitable for release. + /// </summary> + public const string Mixer = "Mixer"; + + /// <summary> + /// A person who remixed a recording by taking one or more other tracks, substantially altering them and mixing them together with other material. + /// </summary> + public const string Remixer = "Remixer"; } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 928f275d7..fcb85a3ac 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -107,7 +107,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal(2020, res.ProductionYear); Assert.True(res.PremiereDate.HasValue); Assert.Equal(DateTime.Parse("2020-10-26T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); - Assert.Equal(18, res.People.Length); + Assert.Equal(22, res.People.Length); Assert.Equal("Krysta Youngs", res.People[0].Name); Assert.Equal(PersonType.Composer, res.People[0].Type); Assert.Equal("Julia Ross", res.People[1].Name); -- cgit v1.2.3 From d82c2e423766566883be850d60e94cc36656f0e8 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Mon, 2 Aug 2021 03:48:45 +0200 Subject: Address comments --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index aa6674468..cdfdbc5da 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -28,7 +28,9 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly Regex _performerPattern = new (@"(?<name>.*) \((?<instrument>.*)\)"); + + private readonly CultureInfo _usCulture = new ("en-US"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; @@ -1116,8 +1118,7 @@ namespace MediaBrowser.MediaEncoding.Probing { foreach (var person in Split(performer, false)) { - Regex pattern = new Regex(@"(?<name>.*) \((?<instrument>.*)\)"); - Match match = pattern.Match(person); + Match match = _performerPattern.Match(person); // If the performer doesn't have any instrument/role associated, it won't match. In that case, chances are it's simply a band name, so we skip it. if (match.Success) -- cgit v1.2.3 From 7f52cda03c9731fcbd57fd8c9ed8806c6965d054 Mon Sep 17 00:00:00 2001 From: MrTimscampi <julien.machiels@protonmail.com> Date: Sat, 7 Aug 2021 21:58:19 +0200 Subject: Make performer regex static --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index cdfdbc5da..e83e533c9 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; - private readonly Regex _performerPattern = new (@"(?<name>.*) \((?<instrument>.*)\)"); + private static readonly Regex _performerPattern = new (@"(?<name>.*) \((?<instrument>.*)\)"); private readonly CultureInfo _usCulture = new ("en-US"); private readonly ILogger _logger; -- cgit v1.2.3 From 963ab2dab6a8c4dafadae61312b36ed5fbb1f323 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 4 Apr 2021 23:02:28 +0200 Subject: Simplify the way we choose our ffmpeg * no longer search $PATH * no longer require a full path * don't fall back --- Emby.Server.Implementations/ApplicationHost.cs | 1 - .../MediaEncoding/IMediaEncoder.cs | 6 -- .../Encoder/EncoderValidator.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 107 ++++++--------------- MediaBrowser.Model/System/SystemInfo.cs | 1 + .../EncoderValidatorTests.cs | 8 +- 6 files changed, 38 insertions(+), 89 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bf7ddace2..0b5322f39 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1099,7 +1099,6 @@ namespace Emby.Server.Implementations ServerName = FriendlyName, LocalAddress = GetSmartApiUrl(source), SupportsLibraryMonitor = true, - EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, PackageName = _startupOptions.PackageName }; diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index ff2456070..63308fa09 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -10,7 +10,6 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.System; namespace MediaBrowser.Controller.MediaEncoding { @@ -19,11 +18,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// </summary> public interface IMediaEncoder : ITranscoderSupport { - /// <summary> - /// Gets location of the discovered FFmpeg tool. - /// </summary> - FFmpegLocation EncoderLocation { get; } - /// <summary> /// Gets the encoder path. /// </summary> diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index f782e65bd..ef831ab82 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -12,8 +12,6 @@ namespace MediaBrowser.MediaEncoding.Encoder { public class EncoderValidator { - private const string DefaultEncoderPath = "ffmpeg"; - private static readonly string[] _requiredDecoders = new[] { "h264", @@ -106,7 +104,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string _encoderPath; - public EncoderValidator(ILogger logger, string encoderPath = DefaultEncoderPath) + public EncoderValidator(ILogger logger, string encoderPath) { _logger = logger; _encoderPath = encoderPath; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 412a95321..f8ba78e46 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -23,7 +23,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -69,7 +68,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private string _ffmpegPath = string.Empty; private string _ffprobePath; - private int threads; + private int _threads; public MediaEncoder( ILogger<MediaEncoder> logger, @@ -89,9 +88,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <inheritdoc /> public string EncoderPath => _ffmpegPath; - /// <inheritdoc /> - public FFmpegLocation EncoderLocation { get; private set; } - /// <summary> /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. @@ -100,20 +96,23 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetFFmpegPath() { // 1) Custom path stored in config/encoding xml file under tag <EncoderAppPath> takes precedence - if (!ValidatePath(_configurationManager.GetEncodingOptions().EncoderAppPath, FFmpegLocation.Custom)) + var ffmpegPath = _configurationManager.GetEncodingOptions().EncoderAppPath; + if (string.IsNullOrEmpty(ffmpegPath)) { // 2) Check if the --ffmpeg CLI switch has been given - if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + ffmpegPath = _startupOptionFFmpegPath; + if (string.IsNullOrEmpty(ffmpegPath)) { - // 3) Search system $PATH environment variable for valid FFmpeg - if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) - { - EncoderLocation = FFmpegLocation.NotFound; - _ffmpegPath = null; - } + // 3) Check "ffmpeg" + ffmpegPath = "ffmpeg"; } } + if (!ValidatePath(ffmpegPath)) + { + _ffmpegPath = null; + } + // Write the FFmpeg path to the config/encoding.xml file as <EncoderAppPathDisplay> so it appears in UI var config = _configurationManager.GetEncodingOptions(); config.EncoderAppPathDisplay = _ffmpegPath ?? string.Empty; @@ -131,10 +130,10 @@ namespace MediaBrowser.MediaEncoding.Encoder SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); SetAvailableHwaccels(validator.GetHwaccels()); - threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); + _threads = EncodingHelper.GetNumberOfThreads(null, _configurationManager.GetEncodingOptions(), null); } - _logger.LogInformation("FFmpeg: {EncoderLocation}: {FfmpegPath}", EncoderLocation, _ffmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {FfmpegPath}", _ffmpegPath ?? string.Empty); } /// <summary> @@ -153,15 +152,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { throw new ArgumentException("Unexpected pathType value"); } - else if (string.IsNullOrWhiteSpace(path)) + + if (string.IsNullOrWhiteSpace(path)) { // User had cleared the custom path in UI newPath = string.Empty; } - else if (File.Exists(path)) - { - newPath = path; - } else if (Directory.Exists(path)) { // Given path is directory, so resolve down to filename @@ -169,7 +165,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } else { - throw new ResourceNotFoundException(); + newPath = path; } // Write the new ffmpeg path to the xml as <EncoderAppPath> @@ -184,37 +180,26 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <summary> /// Validates the supplied FQPN to ensure it is a ffmpeg utility. - /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. + /// If checks pass, global variable FFmpegPath is updated. /// </summary> /// <param name="path">FQPN to test.</param> - /// <param name="location">Location (External, Custom, System) of tool.</param> /// <returns><c>true</c> if the version validation succeeded; otherwise, <c>false</c>.</returns> - private bool ValidatePath(string path, FFmpegLocation location) + private bool ValidatePath(string path) { - bool rc = false; - - if (!string.IsNullOrEmpty(path)) + if (string.IsNullOrEmpty(path)) { - if (File.Exists(path)) - { - rc = new EncoderValidator(_logger, path).ValidateVersion(); - - if (!rc) - { - _logger.LogWarning("FFmpeg: {Location}: Failed version check: {Path}", location, path); - } + return false; + } - _ffmpegPath = path; - EncoderLocation = location; - return true; - } - else - { - _logger.LogWarning("FFmpeg: {Location}: File not found: {Path}", location, path); - } + bool rc = new EncoderValidator(_logger, path).ValidateVersion(); + if (!rc) + { + _logger.LogWarning("FFmpeg: Failed version check: {Path}", path); + return false; } - return rc; + _ffmpegPath = path; + return true; } private string GetEncoderPathFromDirectory(string path, string filename, bool recursive = false) @@ -235,34 +220,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - /// <summary> - /// Search the system $PATH environment variable looking for given filename. - /// </summary> - /// <param name="fileName">The filename.</param> - /// <returns>The full path to the file.</returns> - private string ExistsOnSystemPath(string fileName) - { - var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true); - if (!string.IsNullOrEmpty(inJellyfinPath)) - { - return inJellyfinPath; - } - - var values = Environment.GetEnvironmentVariable("PATH"); - - foreach (var path in values.Split(Path.PathSeparator)) - { - var candidatePath = GetEncoderPathFromDirectory(path, fileName); - - if (!string.IsNullOrEmpty(candidatePath)) - { - return candidatePath; - } - } - - return null; - } - public void SetAvailableEncoders(IEnumerable<string> list) { _encoders = list.ToList(); @@ -394,7 +351,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var args = extractChapters ? "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_chapters -show_format" : "{0} -i {1} -threads {2} -v warning -print_format json -show_streams -show_format"; - args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, threads).Trim(); + args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath, _threads).Trim(); var process = new Process { @@ -615,7 +572,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0}{3} -threads {4} -v quiet -vframes 1 {2} -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, _threads); if (offset.HasValue) { @@ -728,7 +685,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Directory.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, threads); + var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, _threads); if (!string.IsNullOrWhiteSpace(container)) { diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index e45b2f33a..a82c1c8c0 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -133,6 +133,7 @@ namespace MediaBrowser.Model.System [Obsolete("This should be handled by the package manager")] public bool HasUpdateAvailable { get; set; } + [Obsolete("This isn't set correctly anymore")] public FFmpegLocation EncoderLocation { get; set; } public Architecture SystemArchitecture { get; set; } diff --git a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs index 39fd8afda..cc429b442 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/EncoderValidatorTests.cs @@ -9,12 +9,13 @@ namespace Jellyfin.MediaEncoding.Tests { public class EncoderValidatorTests { + private readonly EncoderValidator _encoderValidator = new EncoderValidator(new NullLogger<EncoderValidatorTests>(), "ffmpeg"); + [Theory] [ClassData(typeof(GetFFmpegVersionTestData))] public void GetFFmpegVersionTest(string versionOutput, Version? version) { - var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>()); - Assert.Equal(version, val.GetFFmpegVersion(versionOutput)); + Assert.Equal(version, _encoderValidator.GetFFmpegVersion(versionOutput)); } [Theory] @@ -28,8 +29,7 @@ namespace Jellyfin.MediaEncoding.Tests [InlineData(EncoderValidatorTestsData.FFmpegGitUnknownOutput, false)] public void ValidateVersionInternalTest(string versionOutput, bool valid) { - var val = new EncoderValidator(new NullLogger<EncoderValidatorTests>()); - Assert.Equal(valid, val.ValidateVersionInternal(versionOutput)); + Assert.Equal(valid, _encoderValidator.ValidateVersionInternal(versionOutput)); } private class GetFFmpegVersionTestData : IEnumerable<object?[]> -- cgit v1.2.3 From e3dac4fda2033801085eb7086a3a534c473a00a0 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 12 Jun 2021 22:20:35 +0200 Subject: Use async FileStreams where it makes sense --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 2 +- .../Channels/ChannelManager.cs | 4 +- .../IO/ManagedFileSystem.cs | 2 +- .../Library/LiveStreamHelper.cs | 5 +- .../Library/MediaSourceManager.cs | 2 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 4 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 +- .../LiveTv/TunerHosts/BaseTunerHost.cs | 4 +- .../LiveTv/TunerHosts/LiveStream.cs | 4 +- .../LiveTv/TunerHosts/M3uParser.cs | 3 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 62 +++++++++++----------- .../Plugins/PluginManager.cs | 3 +- .../Serialization/MyXmlSerializer.cs | 2 +- Jellyfin.Api/Controllers/ImageByNameController.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 2 +- Jellyfin.Api/Controllers/SystemController.cs | 2 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 2 +- Jellyfin.Api/Helpers/ProgressiveFileCopier.cs | 3 +- Jellyfin.Api/Helpers/ProgressiveFileStream.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../Users/DefaultPasswordResetProvider.cs | 5 +- Jellyfin.Server/Program.cs | 3 +- .../Attachments/AttachmentExtractor.cs | 2 +- .../BdInfo/BdInfoFileInfo.cs | 6 +-- .../Probing/ProbeResultNormalizer.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 8 +-- MediaBrowser.Model/IO/AsyncFile.cs | 34 ++++++++++++ MediaBrowser.Providers/Manager/ImageSaver.cs | 2 +- .../Manager/ItemImageProvider.cs | 2 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../Plugins/AudioDb/AudioDbAlbumImageProvider.cs | 3 +- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 4 +- .../Plugins/AudioDb/AudioDbArtistImageProvider.cs | 3 +- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 4 +- .../Plugins/Omdb/OmdbProvider.cs | 22 ++------ .../Studios/StudiosImageProvider.cs | 2 +- .../Subtitles/SubtitleManager.cs | 2 +- .../FFprobeParserTests.cs | 3 +- 40 files changed, 127 insertions(+), 100 deletions(-) create mode 100644 MediaBrowser.Model/IO/AsyncFile.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index af70793cc..68fc80c0a 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -366,7 +366,7 @@ namespace Emby.Dlna Directory.CreateDirectory(systemProfilesPath); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 7d952aa23..0ad8bca31 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -102,7 +102,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true)) + using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index aa54510a7..1478e9313 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -815,7 +815,7 @@ namespace Emby.Server.Implementations.Channels { if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) { - await using FileStream jsonStream = File.OpenRead(cachePath); + await using FileStream jsonStream = AsyncFile.OpenRead(cachePath); var cachedResult = await JsonSerializer.DeserializeAsync<ChannelItemResult>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (cachedResult != null) { @@ -838,7 +838,7 @@ namespace Emby.Server.Implementations.Channels { if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) { - await using FileStream jsonStream = File.OpenRead(cachePath); + await using FileStream jsonStream = AsyncFile.OpenRead(cachePath); var cachedResult = await JsonSerializer.DeserializeAsync<ChannelItemResult>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (cachedResult != null) { diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 7c3c7da23..af0d88ea5 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -248,7 +248,7 @@ namespace Emby.Server.Implementations.IO { try { - using (Stream thisFileStream = File.OpenRead(fileInfo.FullName)) + using (Stream thisFileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1)) { result.Length = thisFileStream.Length; } diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 806269182..16b45161f 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -17,6 +17,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; @@ -49,7 +50,7 @@ namespace Emby.Server.Implementations.Library { try { - await using FileStream jsonStream = File.OpenRead(cacheFilePath); + await using FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); mediaInfo = await JsonSerializer.DeserializeAsync<MediaInfo>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Found cached media info"); @@ -86,7 +87,7 @@ namespace Emby.Server.Implementations.Library if (cacheFilePath != null) { Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - await using FileStream createStream = File.OpenWrite(cacheFilePath); + await using FileStream createStream = AsyncFile.OpenWrite(cacheFilePath); await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Saved media info to {0}", cacheFilePath); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 91c9e61cf..4e0434b92 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -638,7 +638,7 @@ namespace Emby.Server.Implementations.Library { try { - await using FileStream jsonStream = File.OpenRead(cacheFilePath); + await using FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); mediaInfo = await JsonSerializer.DeserializeAsync<MediaInfo>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Found cached media info"); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index bb3d635d1..c5a9a92ec 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) { onStarted(); @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None); + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index e10bc7647..d806a0295 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index ebad4eddf..8202fab86 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew)) + await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO)) { await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 5941613cf..f87212cf3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts try { Directory.CreateDirectory(Path.GetDirectoryName(channelCacheFile)); - await using var writeStream = File.OpenWrite(channelCacheFile); + await using var writeStream = AsyncFile.OpenWrite(channelCacheFile); await JsonSerializer.SerializeAsync(writeStream, channels, cancellationToken: cancellationToken).ConfigureAwait(false); } catch (IOException) @@ -108,7 +108,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - await using var readStream = File.OpenRead(channelCacheFile); + await using var readStream = AsyncFile.OpenRead(channelCacheFile); var channels = await JsonSerializer.DeserializeAsync<List<ChannelInfo>>(readStream, cancellationToken: cancellationToken) .ConfigureAwait(false); list.AddRange(channels); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 96a678c1d..2c21a4a89 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -155,15 +155,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token); cancellationToken = linkedCancellationTokenSource.Token; - // use non-async filestream on windows along with read due to https://github.com/dotnet/corefx/issues/6039 - var allowAsync = Environment.OSVersion.Platform != PlatformID.Win32NT; - bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; var nextFileInfo = GetNextFile(null); var nextFile = nextFileInfo.file; var isLastFile = nextFileInfo.isLastFile; + var allowAsync = AsyncFile.UseAsyncIO; while (!string.IsNullOrEmpty(nextFile)) { var emptyReadLimit = isLastFile ? EmptyReadLimit : 1; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index d28c39e21..23071a430 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -14,6 +14,7 @@ using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using Microsoft.Extensions.Logging; @@ -50,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { - return File.OpenRead(info.Url); + return AsyncFile.OpenRead(info.Url); } using var requestMessage = new HttpRequestMessage(HttpMethod.Get, info.Url); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index f572151b8..862993877 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -129,37 +129,39 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts private Task StartStreaming(HttpResponseMessage response, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) { - return Task.Run(async () => - { - try - { - Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); - using var message = response; - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); - await StreamHelper.CopyToAsync( - stream, - fileStream, - IODefaults.CopyToBufferSize, - () => Resolve(openTaskCompletionSource), - cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException ex) - { - Logger.LogInformation("Copying of {0} to {1} was canceled", GetType().Name, TempFilePath); - openTaskCompletionSource.TrySetException(ex); - } - catch (Exception ex) + return Task.Run( + async () => { - Logger.LogError(ex, "Error copying live stream {0} to {1}.", GetType().Name, TempFilePath); - openTaskCompletionSource.TrySetException(ex); - } - - openTaskCompletionSource.TrySetResult(false); - - EnableStreamSharing = false; - await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false); - }, CancellationToken.None); + try + { + Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); + using var message = response; + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await StreamHelper.CopyToAsync( + stream, + fileStream, + IODefaults.CopyToBufferSize, + () => Resolve(openTaskCompletionSource), + cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException ex) + { + Logger.LogInformation("Copying of {0} to {1} was canceled", GetType().Name, TempFilePath); + openTaskCompletionSource.TrySetException(ex); + } + catch (Exception ex) + { + Logger.LogError(ex, "Error copying live stream {0} to {1}.", GetType().Name, TempFilePath); + openTaskCompletionSource.TrySetException(ex); + } + + openTaskCompletionSource.TrySetResult(false); + + EnableStreamSharing = false; + await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false); + }, + CancellationToken.None); } private void Resolve(TaskCompletionSource<bool> openTaskCompletionSource) diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index fc0920edf..b8e1dc2c0 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -15,6 +15,7 @@ using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Updates; using Microsoft.Extensions.DependencyInjection; @@ -371,7 +372,7 @@ namespace Emby.Server.Implementations.Plugins var url = new Uri(packageInfo.ImageUrl); imagePath = Path.Join(path, url.Segments[^1]); - await using var fileStream = File.OpenWrite(imagePath); + await using var fileStream = AsyncFile.OpenWrite(imagePath); try { diff --git a/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs b/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs index 5ff73de81..059211a0b 100644 --- a/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs +++ b/Emby.Server.Implementations/Serialization/MyXmlSerializer.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.Serialization /// <param name="file">The file.</param> public void SerializeToFile(object obj, string file) { - using (var stream = new FileStream(file, FileMode.Create)) + using (var stream = new FileStream(file, FileMode.Create, FileAccess.Write)) { SerializeToStream(obj, stream); } diff --git a/Jellyfin.Api/Controllers/ImageByNameController.cs b/Jellyfin.Api/Controllers/ImageByNameController.cs index e1b808098..99ab7f232 100644 --- a/Jellyfin.Api/Controllers/ImageByNameController.cs +++ b/Jellyfin.Api/Controllers/ImageByNameController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers } var contentType = MimeTypes.GetMimeType(path); - return File(System.IO.File.OpenRead(path), contentType); + return File(AsyncFile.OpenRead(path), contentType); } /// <summary> diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index ec836f43e..8fec7d6df 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -208,7 +208,7 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index bbbe5fb8d..e6584f0fe 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers // For older files, assume fully static var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite; - FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare); + FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); return File(stream, "text/plain; charset=utf-8"); } diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index d1cdaf867..0c226f429 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -39,7 +39,7 @@ namespace Jellyfin.Api.Helpers FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, - FileOptions.SequentialScan); + (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan); await using (fileStream.ConfigureAwait(false)) { using var reader = new StreamReader(fileStream); diff --git a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs index 963e17724..1fb4798ee 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs @@ -85,8 +85,7 @@ namespace Jellyfin.Api.Helpers var fileOptions = FileOptions.SequentialScan; var allowAsyncFileRead = false; - // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (AsyncFile.UseAsyncIO) { fileOptions |= FileOptions.Asynchronous; allowAsyncFileRead = true; diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs index 499dbe84d..82f35fc35 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Api.Helpers _allowAsyncFileRead = false; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (AsyncFile.UseAsyncIO) { fileOptions |= FileOptions.Asynchronous; _allowAsyncFileRead = true; diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 05fa5b135..b168e6d00 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -557,7 +557,7 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index c99c5e4ef..6e98ad863 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -10,6 +10,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Users; namespace Jellyfin.Server.Implementations.Users @@ -53,7 +54,7 @@ namespace Jellyfin.Server.Implementations.Users foreach (var resetFile in Directory.EnumerateFiles(_passwordResetFileBaseDir, $"{BaseResetFileName}*")) { SerializablePasswordReset spr; - await using (var str = File.OpenRead(resetFile)) + await using (var str = AsyncFile.OpenRead(resetFile)) { spr = await JsonSerializer.DeserializeAsync<SerializablePasswordReset>(str).ConfigureAwait(false) ?? throw new ResourceNotFoundException($"Provided path ({resetFile}) is not valid."); @@ -110,7 +111,7 @@ namespace Jellyfin.Server.Implementations.Users UserName = user.Username }; - await using (FileStream fileStream = File.OpenWrite(filePath)) + await using (FileStream fileStream = AsyncFile.OpenWrite(filePath)) { await JsonSerializer.SerializeAsync(fileStream, spr).ConfigureAwait(false); await fileStream.FlushAsync().ConfigureAwait(false); diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7018d537f..6e87c8939 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -15,6 +15,7 @@ using Jellyfin.Server.Implementations; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Extensions; +using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -546,7 +547,7 @@ namespace Jellyfin.Server ?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'"); // Copy the resource contents to the expected file path for the config file - await using Stream dst = File.Open(configPath, FileMode.CreateNew); + await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await resource.CopyToAsync(dst).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index a0ec3bd90..a524aeaa9 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -89,7 +89,7 @@ namespace MediaBrowser.MediaEncoding.Attachments CancellationToken cancellationToken) { var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource, mediaAttachment, cancellationToken).ConfigureAwait(false); - return File.OpenRead(attachmentPath); + return AsyncFile.OpenRead(attachmentPath); } private async Task<string> GetReadableFile( diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs index 41143c259..d55688e3d 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo public bool IsDir => _impl.IsDirectory; - public System.IO.Stream OpenRead() + public Stream OpenRead() { return new FileStream( FullName, @@ -33,9 +33,9 @@ namespace MediaBrowser.MediaEncoding.BdInfo FileShare.Read); } - public System.IO.StreamReader OpenText() + public StreamReader OpenText() { - return new System.IO.StreamReader(OpenRead()); + return new StreamReader(OpenRead()); } } } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 93093bb18..8510a2f54 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1498,7 +1498,7 @@ namespace MediaBrowser.MediaEncoding.Probing { var packetBuffer = new byte[197]; - using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1)) { fs.Read(packetBuffer); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 608ebf443..6f6178af2 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -192,7 +192,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - return File.OpenRead(fileInfo.Path); + return AsyncFile.OpenRead(fileInfo.Path); } private async Task<SubtitleInfo> GetReadableFile( @@ -671,7 +671,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles string text; Encoding encoding; - using (var fileStream = File.OpenRead(file)) + using (var fileStream = AsyncFile.OpenRead(file)) using (var reader = new StreamReader(fileStream, true)) { encoding = reader.CurrentEncoding; @@ -684,7 +684,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) using (var writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false); @@ -750,7 +750,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } case MediaProtocol.File: - return File.OpenRead(path); + return AsyncFile.OpenRead(path); default: throw new ArgumentOutOfRangeException(nameof(protocol)); } diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs new file mode 100644 index 000000000..b888a4163 --- /dev/null +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; + +namespace MediaBrowser.Model.IO +{ + /// <summary> + /// Helper class to create async <see cref="FileStream" />s. + /// </summary> + public static class AsyncFile + { + /// <summary> + /// Gets a value indicating whether we should use async IO on this platform. + /// <see href="https://github.com/dotnet/runtime/issues/16354" />. + /// </summary> + /// <returns>Returns <c>false</c> on Windows; otherwise <c>true</c>.</returns> + public static bool UseAsyncIO => !OperatingSystem.IsWindows(); + + /// <summary> + /// Opens an existing file for reading. + /// </summary> + /// <param name="path">The file to be opened for reading.</param> + /// <returns>A read-only <see cref="FileStream" /> on the specified path.</returns> + public static FileStream OpenRead(string path) + => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, UseAsyncIO); + + /// <summary> + /// Opens an existing file for writing. + /// </summary> + /// <param name="path">The file to be opened for writing.</param> + /// <returns>An unshared <see cref="FileStream" /> object on the specified path with Write access.</returns> + public static FileStream OpenWrite(string path) + => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, UseAsyncIO); + } +} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index fb1d4f490..3763c6d14 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -264,7 +264,7 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 607fd127b..ce3ce66fa 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true); + var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 2dfaa372c..84d71f0b1 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -209,7 +209,7 @@ namespace MediaBrowser.Providers.Manager throw new ArgumentNullException(nameof(source)); } - var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, true); + var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs index 36d8eeb40..81bbc26b8 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumImageProvider.cs @@ -13,6 +13,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Plugins.AudioDb @@ -57,7 +58,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = AudioDbAlbumProvider.GetAlbumInfoPath(_config.ApplicationPaths, id); - await using FileStream jsonStream = File.OpenRead(path); + await using FileStream jsonStream = AsyncFile.OpenRead(path); var obj = await JsonSerializer.DeserializeAsync<AudioDbAlbumProvider.RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (obj != null && obj.album != null && obj.album.Count > 0) diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index 9f2f7fc11..c1226febf 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = GetAlbumInfoPath(_config.ApplicationPaths, id); - await using FileStream jsonStream = File.OpenRead(path); + await using FileStream jsonStream = AsyncFile.OpenRead(path); var obj = await JsonSerializer.DeserializeAsync<RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (obj != null && obj.album != null && obj.album.Count > 0) @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs index aa61a56f6..3ffdcdbeb 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistImageProvider.cs @@ -13,6 +13,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Plugins.AudioDb @@ -59,7 +60,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = AudioDbArtistProvider.GetArtistInfoPath(_config.ApplicationPaths, id); - await using FileStream jsonStream = File.OpenRead(path); + await using FileStream jsonStream = AsyncFile.OpenRead(path); var obj = await JsonSerializer.DeserializeAsync<AudioDbArtistProvider.RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (obj != null && obj.artists != null && obj.artists.Count > 0) diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index 2857c6c13..8572b3413 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = GetArtistInfoPath(_config.ApplicationPaths, id); - await using FileStream jsonStream = File.OpenRead(path); + await using FileStream jsonStream = AsyncFile.OpenRead(path); var obj = await JsonSerializer.DeserializeAsync<RootObject>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (obj != null && obj.artists != null && obj.artists.Count > 0) @@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 1ae712e9e..1dea3dece 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -236,31 +236,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb internal async Task<RootObject> GetRootObject(string imdbId, CancellationToken cancellationToken) { var path = await EnsureItemInfo(imdbId, cancellationToken).ConfigureAwait(false); - await using var stream = File.OpenRead(path); + await using var stream = AsyncFile.OpenRead(path); return await JsonSerializer.DeserializeAsync<RootObject>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); } internal async Task<SeasonRootObject> GetSeasonRootObject(string imdbId, int seasonId, CancellationToken cancellationToken) { var path = await EnsureSeasonInfo(imdbId, seasonId, cancellationToken).ConfigureAwait(false); - await using var stream = File.OpenRead(path); + await using var stream = AsyncFile.OpenRead(path); return await JsonSerializer.DeserializeAsync<SeasonRootObject>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); } - internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds) - { - if (seriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string id)) - { - // This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet. - if (!string.IsNullOrWhiteSpace(id)) - { - return true; - } - } - - return false; - } - /// <summary>Gets OMDB URL.</summary> /// <param name="query">Appends query string to URL.</param> /// <returns>OMDB URL with optional query string.</returns> @@ -309,7 +295,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb imdbParam)); var rootObject = await GetDeserializedOmdbResponse<RootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; @@ -349,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb seasonId)); var rootObject = await GetDeserializedOmdbResponse<SeasonRootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 63e78d15e..7a057c065 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Studios Directory.CreateDirectory(Path.GetDirectoryName(file)); await using var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(file, FileMode.Create); + await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 0c791a2fe..d6c346ba1 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(savePath)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, true); + using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, AsyncFile.UseAsyncIO); await stream.CopyToAsync(fs).ConfigureAwait(false); return; diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 2955104a2..97dbb3be0 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Extensions.Json; using MediaBrowser.MediaEncoding.Probing; +using MediaBrowser.Model.IO; using Xunit; namespace Jellyfin.MediaEncoding.Tests @@ -14,7 +15,7 @@ namespace Jellyfin.MediaEncoding.Tests public async Task Test(string fileName) { var path = Path.Join("Test Data", fileName); - await using (var stream = File.OpenRead(path)) + await using (var stream = AsyncFile.OpenRead(path)) { var res = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(stream, JsonDefaults.Options).ConfigureAwait(false); Assert.NotNull(res); -- cgit v1.2.3 From b53c36ee4a9792cc45e2876c3d1f6fe4ad284d8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:01:30 +0000 Subject: Bump libse from 3.6.0 to 3.6.2 Bumps [libse](https://github.com/SubtitleEdit/subtitleedit) from 3.6.0 to 3.6.2. - [Release notes](https://github.com/SubtitleEdit/subtitleedit/releases) - [Changelog](https://github.com/SubtitleEdit/subtitleedit/blob/master/Changelog.txt) - [Commits](https://github.com/SubtitleEdit/subtitleedit/compare/3.6.0...3.6.2) --- updated-dependencies: - dependency-name: libse dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 6da9886a4..5deaecc95 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -23,7 +23,7 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> - <PackageReference Include="libse" Version="3.6.0" /> + <PackageReference Include="libse" Version="3.6.2" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> <PackageReference Include="UTF.Unknown" Version="2.4.0" /> -- cgit v1.2.3 From ea3e66e9187810f9dc789b63429f67b221930a5a Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Mon, 13 Sep 2021 06:32:26 -0600 Subject: Fix namespace --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 24ceb1b57..3d864e29c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -5,7 +5,7 @@ using System.Threading; using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; -using Nikse.SubtitleEdit.Core; +using Nikse.SubtitleEdit.Core.Common; using ILogger = Microsoft.Extensions.Logging.ILogger; using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat; -- cgit v1.2.3 From 34b38454e06ab0e3c6a2eed2968ba365dde8d510 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 18 Sep 2021 15:08:17 +0200 Subject: Fix SubtitleEncoder and add regression tests --- .../Subtitles/SubtitleEncoder.cs | 28 ++++---- .../Jellyfin.MediaEncoding.Tests.csproj | 6 +- .../Subtitles/SubtitleEncoderTests.cs | 83 ++++++++++++++++++++++ 3 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 6f6178af2..f8451e92c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return AsyncFile.OpenRead(fileInfo.Path); } - private async Task<SubtitleInfo> GetReadableFile( + internal async Task<SubtitleInfo> GetReadableFile( MediaSourceInfo mediaSource, MediaStream subtitleStream, CancellationToken cancellationToken) @@ -205,9 +205,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles string outputFormat; string outputCodec; - if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) || - string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase) || - string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) + || string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase) + || string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase)) { // Extract outputCodec = "copy"; @@ -238,7 +238,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec) .TrimStart('.'); - if (TryGetReader(currentFormat, out _)) + if (!TryGetReader(currentFormat, out _)) { // Convert var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, ".srt"); @@ -248,12 +248,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new SubtitleInfo(outputPath, MediaProtocol.File, "srt", true); } - if (subtitleStream.IsExternal) - { - return new SubtitleInfo(subtitleStream.Path, _mediaSourceManager.GetPathProtocol(subtitleStream.Path), currentFormat, true); - } - - return new SubtitleInfo(subtitleStream.Path, mediaSource.Protocol, currentFormat, true); + // It's possbile that the subtitleStream and mediaSource don't share the same protocol (e.g. .STRM file with local subs) + return new SubtitleInfo(subtitleStream.Path, _mediaSourceManager.GetPathProtocol(subtitleStream.Path), currentFormat, true); } private bool TryGetReader(string format, [NotNullWhen(true)] out ISubtitleParser? value) @@ -756,7 +752,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private struct SubtitleInfo + internal readonly struct SubtitleInfo { public SubtitleInfo(string path, MediaProtocol protocol, string format, bool isExternal) { @@ -766,13 +762,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles IsExternal = isExternal; } - public string Path { get; set; } + public string Path { get; } - public MediaProtocol Protocol { get; set; } + public MediaProtocol Protocol { get; } - public string Format { get; set; } + public string Format { get; } - public bool IsExternal { get; set; } + public bool IsExternal { get; } } } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 7ea503913..e9cd8c062 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -18,10 +18,14 @@ </ItemGroup> <ItemGroup> + <PackageReference Include="AutoFixture" Version="4.17.0" /> + <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> + <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> + <PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> + <PackageReference Include="Moq" Version="4.16.1" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="3.1.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs new file mode 100644 index 000000000..7c4d0cf53 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SubtitleEncoderTests.cs @@ -0,0 +1,83 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using AutoFixture.AutoMoq; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.MediaEncoding.Subtitles; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.MediaEncoding.Subtitles.Tests +{ + public class SubtitleEncoderTests + { + internal static TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo> GetReadableFile_Valid_TestData() + { + var data = new TheoryData<MediaSourceInfo, MediaStream, SubtitleEncoder.SubtitleInfo>(); + + data.Add( + new MediaSourceInfo() + { + Protocol = MediaProtocol.File + }, + new MediaStream() + { + Path = "/media/sub.ass", + IsExternal = true + }, + new SubtitleEncoder.SubtitleInfo("/media/sub.ass", MediaProtocol.File, "ass", true)); + + data.Add( + new MediaSourceInfo() + { + Protocol = MediaProtocol.File + }, + new MediaStream() + { + Path = "/media/sub.ssa", + IsExternal = true + }, + new SubtitleEncoder.SubtitleInfo("/media/sub.ssa", MediaProtocol.File, "ssa", true)); + + data.Add( + new MediaSourceInfo() + { + Protocol = MediaProtocol.File + }, + new MediaStream() + { + Path = "/media/sub.srt", + IsExternal = true + }, + new SubtitleEncoder.SubtitleInfo("/media/sub.srt", MediaProtocol.File, "srt", true)); + + return data; + } + + [Theory] + [MemberData(nameof(GetReadableFile_Valid_TestData))] + internal async Task GetReadableFile_Valid_Success(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleEncoder.SubtitleInfo subtitleInfo) + { + var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); + var subtitleEncoder = fixture.Create<SubtitleEncoder>(); + var result = await subtitleEncoder.GetReadableFile(mediaSource, subtitleStream, CancellationToken.None).ConfigureAwait(false); + Assert.Equal(subtitleInfo.Path, result.Path); + Assert.Equal(subtitleInfo.Protocol, result.Protocol); + Assert.Equal(subtitleInfo.Format, result.Format); + Assert.Equal(subtitleInfo.IsExternal, result.IsExternal); + } + } +} -- cgit v1.2.3 From a6d1e542e62548f177523f0acd67260f58066731 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 19 Sep 2021 20:53:31 +0200 Subject: Reduce allocations --- Emby.Dlna/Eventing/DlnaEventManager.cs | 5 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 7 +-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 59 ++++++++++------------ .../LiveTv/TunerHosts/M3uParser.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 +- Jellyfin.Api/Helpers/StreamingHelpers.cs | 3 +- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 4 +- .../Parsers/BaseItemXmlParser.cs | 3 +- .../Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs | 4 +- MediaBrowser.Model/Net/MimeTypes.cs | 3 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 3 +- src/Jellyfin.Extensions/StringExtensions.cs | 34 +++++++++++++ .../StringExtensionsTests.cs | 21 ++++++++ 14 files changed, 105 insertions(+), 48 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index 3c9136090..b39bd5ce9 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -11,6 +11,7 @@ using System.Net.Http; using System.Net.Mime; using System.Text; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using Microsoft.Extensions.Logging; @@ -82,9 +83,7 @@ namespace Emby.Dlna.Eventing if (!string.IsNullOrEmpty(header)) { // Starts with SECOND- - header = header.Split('-')[^1]; - - if (int.TryParse(header, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, _usCulture, out var val)) { return val; } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 8202fab86..cb9801c17 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using Jellyfin.XmlTv; using Jellyfin.XmlTv.Entities; using MediaBrowser.Common.Extensions; @@ -89,11 +90,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings return UnzipIfNeeded(path, cacheFile); } - private string UnzipIfNeeded(string originalUrl, string file) + private string UnzipIfNeeded(ReadOnlySpan<char> originalUrl, string file) { - string ext = Path.GetExtension(originalUrl.Split('?')[0]); + ReadOnlySpan<char> ext = Path.GetExtension(originalUrl.LeftPart('?')); - if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".gz", StringComparison.OrdinalIgnoreCase)) { try { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2bd12a9c8..4d538c604 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -36,7 +36,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; - private readonly INetworkManager _networkManager; private readonly IStreamHelper _streamHelper; private readonly JsonSerializerOptions _jsonOptions; @@ -50,7 +49,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, ISocketFactory socketFactory, - INetworkManager networkManager, IStreamHelper streamHelper, IMemoryCache memoryCache) : base(config, logger, fileSystem, memoryCache) @@ -58,7 +56,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _httpClientFactory = httpClientFactory; _appHost = appHost; _socketFactory = socketFactory; - _networkManager = networkManager; _streamHelper = streamHelper; _jsonOptions = JsonDefaults.Options; @@ -70,7 +67,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun protected override string ChannelIdPrefix => "hdhr_"; - private string GetChannelId(TunerHostInfo info, Channels i) + private string GetChannelId(Channels i) => ChannelIdPrefix + i.GuideNumber; internal async Task<List<Channels>> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) @@ -103,7 +100,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { Name = i.GuideName, Number = i.GuideNumber, - Id = GetChannelId(tuner, i), + Id = GetChannelId(i), IsFavorite = i.Favorite, TunerHostId = tuner.Id, IsHD = i.HD, @@ -255,7 +252,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - var tuners = new List<LiveTvTunerInfo>(); + var tuners = new List<LiveTvTunerInfo>(model.TunerCount); var uri = new Uri(GetApiUrl(info)); @@ -264,10 +261,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Legacy HdHomeruns are IPv4 only var ipInfo = IPAddress.Parse(uri.Host); - for (int i = 0; i < model.TunerCount; ++i) + for (int i = 0; i < model.TunerCount; i++) { var name = string.Format(CultureInfo.InvariantCulture, "Tuner {0}", i + 1); - var currentChannel = "none"; // @todo Get current channel and map back to Station Id + var currentChannel = "none"; // TODO: Get current channel and map back to Station Id var isAvailable = await manager.CheckTunerAvailability(ipInfo, i, cancellationToken).ConfigureAwait(false); var status = isAvailable ? LiveTvTunerStatus.Available : LiveTvTunerStatus.LiveTv; tuners.Add(new LiveTvTunerInfo @@ -455,28 +452,28 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Path = url, Protocol = MediaProtocol.Udp, MediaStreams = new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = isInterlaced, - Codec = videoCodec, - Width = width, - Height = height, - BitRate = videoBitrate, - NalLengthSize = nal - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1, - Codec = audioCodec, - BitRate = audioBitrate - } - }, + { + new MediaStream + { + Type = MediaStreamType.Video, + // Set the index to -1 because we don't know the exact index of the video stream within the container + Index = -1, + IsInterlaced = isInterlaced, + Codec = videoCodec, + Width = width, + Height = height, + BitRate = videoBitrate, + NalLengthSize = nal + }, + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1, + Codec = audioCodec, + BitRate = audioBitrate + } + }, RequiresOpening = true, RequiresClosing = true, BufferMs = 0, @@ -551,7 +548,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - var profile = streamId.Split('_')[0]; + var profile = streamId.AsSpan().LeftPart('_').ToString(); Logger.LogInformation("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channel.Id, streamId, profile); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 23071a430..506ef5548 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -238,7 +238,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { try { - numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/')[^1]); + numberString = Path.GetFileNameWithoutExtension(mediaUrl.AsSpan().RightPart('/')).ToString(); if (!IsValidChannelNumber(numberString)) { diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 7a2c23991..bcb2b50c7 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -7,6 +7,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -199,7 +200,7 @@ namespace Jellyfin.Api.Controllers throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType)); } - var ext = response.Content.Headers.ContentType.MediaType.Split('/')[^1]; + var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 0041251e3..4fc791665 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; @@ -81,7 +82,7 @@ namespace Jellyfin.Api.Helpers throw new ResourceNotFoundException(nameof(httpRequest.Path)); } - var url = httpRequest.Path.Value.Split('.')[^1]; + var url = httpRequest.Path.Value.AsSpan().RightPart('.').ToString(); if (string.IsNullOrEmpty(streamingRequest.AudioCodec)) { diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index aa5e2c403..c4ddc5618 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -120,7 +120,7 @@ namespace MediaBrowser.Controller.MediaEncoding var size = part.Split('=', 2)[^1]; int? scale = null; - if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) + if (size.Contains("kb", StringComparison.OrdinalIgnoreCase)) { scale = 1024; size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); @@ -139,7 +139,7 @@ namespace MediaBrowser.Controller.MediaEncoding var rate = part.Split('=', 2)[^1]; int? scale = null; - if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) + if (rate.Contains("kbits/s", StringComparison.OrdinalIgnoreCase)) { scale = 1024; rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index ef130ee74..9103bf647 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -331,7 +332,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, _usCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 2516aad1c..c377f1720 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1378,7 +1378,7 @@ namespace MediaBrowser.MediaEncoding.Probing { var disc = tags.GetValueOrDefault(tagName); - if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.Split('/')[0], out var discNum)) + if (!string.IsNullOrEmpty(disc) && int.TryParse(disc.AsSpan().LeftPart('/'), out var discNum)) { return discNum; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs index ad32cb794..6d56dda91 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs @@ -18,14 +18,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { writer.WriteLine("WEBVTT"); - writer.WriteLine(string.Empty); + writer.WriteLine(); writer.WriteLine("REGION"); writer.WriteLine("id:subtitle"); writer.WriteLine("width:80%"); writer.WriteLine("lines:3"); writer.WriteLine("regionanchor:50%,100%"); writer.WriteLine("viewportanchor:50%,90%"); - writer.WriteLine(string.Empty); + writer.WriteLine(); foreach (var trackEvent in info.TrackEvents) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 96f5ab51a..7b3c17c85 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Net { @@ -221,7 +222,7 @@ namespace MediaBrowser.Model.Net } // handle text/html; charset=UTF-8 - mimeType = mimeType.Split(';')[0]; + mimeType = mimeType.AsSpan().LeftPart(';').ToString(); if (_extensionLookup.TryGetValue(mimeType, out string? result)) { diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index f975278fb..b3efb8634 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Providers; using MediaBrowser.Controller.Entities; @@ -474,7 +475,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, UsCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, UsCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index acc695ed2..3a7707253 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -27,5 +27,39 @@ namespace Jellyfin.Extensions return count; } + + /// <summary> + /// Returns the part on the left of the <c>needle</c>. + /// </summary> + /// <param name="haystack">The string to seek.</param> + /// <param name="needle">The needle to find.</param> + /// <returns>The part left of the <paramref name="needle" />.</returns> + public static ReadOnlySpan<char> LeftPart(this ReadOnlySpan<char> haystack, char needle) + { + var pos = haystack.IndexOf(needle); + return pos == -1 ? haystack : haystack[..pos]; + } + + /// <summary> + /// Returns the part on the right of the <c>needle</c>. + /// </summary> + /// <param name="haystack">The string to seek.</param> + /// <param name="needle">The needle to find.</param> + /// <returns>The part right of the <paramref name="needle" />.</returns> + public static ReadOnlySpan<char> RightPart(this ReadOnlySpan<char> haystack, char needle) + { + var pos = haystack.LastIndexOf(needle); + if (pos == -1) + { + return haystack; + } + + if (pos == haystack.Length - 1) + { + return ReadOnlySpan<char>.Empty; + } + + return haystack[(pos + 1)..]; + } } } diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs index d1aa2e476..17671d13b 100644 --- a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs @@ -14,5 +14,26 @@ namespace Jellyfin.Extensions.Tests { Assert.Equal(count, str.AsSpan().Count(needle)); } + + [Theory] + [InlineData("", 'q', "")] + [InlineData("Banana split", ' ', "Banana")] + [InlineData("Banana split", 'q', "Banana split")] + public void LeftPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult) + { + var result = str.AsSpan().LeftPart(needle).ToString(); + Assert.Equal(expectedResult, result); + } + + [Theory] + [InlineData("", 'q', "")] + [InlineData("Banana split", ' ', "split")] + [InlineData("Banana split", 'q', "Banana split")] + [InlineData("Banana split.", '.', "")] + public void RightPart_ValidArgsCharNeedle_Correct(string str, char needle, string expectedResult) + { + var result = str.AsSpan().RightPart(needle).ToString(); + Assert.Equal(expectedResult, result); + } } } -- cgit v1.2.3 From 653df7d8e5b3474010b3797d7f15d51225932ca7 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 21 Sep 2021 01:21:45 +0200 Subject: Specify DateTimeStyles when possible --- Emby.Server.Implementations/Data/SqliteExtensions.cs | 6 +++--- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 +- Jellyfin.Api/Controllers/TimeSyncController.cs | 4 ++-- Jellyfin.Api/Controllers/TvShowsController.cs | 2 +- MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs | 12 ++++++------ MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 6 +++--- .../Probing/ProbeResultNormalizer.cs | 6 +++--- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 16 ++++++++-------- .../Probing/ProbeResultNormalizerTests.cs | 6 +++--- 9 files changed, 30 insertions(+), 30 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index 3289e7609..381eb92a8 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Data dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, - DateTimeStyles.None).ToUniversalTime(); + DateTimeStyles.AdjustToUniversal); } public static bool TryReadDateTime(this IReadOnlyList<ResultSetValue> reader, int index, out DateTime result) @@ -108,9 +108,9 @@ namespace Emby.Server.Implementations.Data var dateText = item.ToString(); - if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out var dateTimeResult)) + if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out var dateTimeResult)) { - result = dateTimeResult.ToUniversalTime(); + result = dateTimeResult; return true; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 026b6bc0b..64e54aa99 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1990,7 +1990,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString( "dateadded", - DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat, CultureInfo.InvariantCulture)); + DateTime.Now.ToString(DateAddedFormat, CultureInfo.InvariantCulture)); if (item.ProductionYear.HasValue) { diff --git a/Jellyfin.Api/Controllers/TimeSyncController.cs b/Jellyfin.Api/Controllers/TimeSyncController.cs index 7df51c7af..e7c5a7125 100644 --- a/Jellyfin.Api/Controllers/TimeSyncController.cs +++ b/Jellyfin.Api/Controllers/TimeSyncController.cs @@ -21,10 +21,10 @@ namespace Jellyfin.Api.Controllers public ActionResult<UtcTimeResponse> GetUtcTime() { // Important to keep the following line at the beginning - var requestReceptionTime = DateTime.UtcNow.ToUniversalTime(); + var requestReceptionTime = DateTime.UtcNow; // Important to keep the following line at the end - var responseTransmissionTime = DateTime.UtcNow.ToUniversalTime(); + var responseTransmissionTime = DateTime.UtcNow; // Implementing NTP on such a high level results in this useless // information being sent. On the other hand it enables future additions. diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 7c5b8a43b..6eada67cf 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -147,7 +147,7 @@ namespace Jellyfin.Api.Controllers ? _userManager.GetUserById(userId.Value) : null; - var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1); + var minPremiereDate = DateTime.UtcNow.Date.AddDays(-1); var parentIdGuid = parentId ?? Guid.Empty; diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 9103bf647..7c9e681d6 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -145,9 +145,9 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (DateTime.TryParse(val, out var added)) + if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var added)) { - item.DateCreated = added.ToUniversalTime(); + item.DateCreated = added; } else { @@ -535,9 +535,9 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(firstAired)) { - if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var airDate) && airDate.Year > 1850) + if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal, out var airDate) && airDate.Year > 1850) { - item.PremiereDate = airDate.ToUniversalTime(); + item.PremiereDate = airDate; item.ProductionYear = airDate.Year; } } @@ -552,9 +552,9 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(firstAired)) { - if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var airDate) && airDate.Year > 1850) + if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal, out var airDate) && airDate.Year > 1850) { - item.EndDate = airDate.ToUniversalTime(); + item.EndDate = airDate; } } diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 9196fe139..a9e753726 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -63,10 +63,10 @@ namespace MediaBrowser.MediaEncoding.Probing public static DateTime? GetDictionaryDateTime(IReadOnlyDictionary<string, string> tags, string key) { if (tags.TryGetValue(key, out var val) - && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out var dateTime) - || DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal, out dateTime))) + && (DateTime.TryParse(val, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var dateTime) + || DateTime.TryParseExact(val, "yyyy", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out dateTime))) { - return dateTime.ToUniversalTime(); + return dateTime; } return null; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c377f1720..26f629a31 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1450,9 +1450,9 @@ namespace MediaBrowser.MediaEncoding.Probing // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/ // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None) - if (tags.TryGetValue("WM/MediaOriginalBroadcastDateTime", out var premiereDateString) && DateTime.TryParse(year, null, DateTimeStyles.None, out var parsedDate)) + if (tags.TryGetValue("WM/MediaOriginalBroadcastDateTime", out var premiereDateString) && DateTime.TryParse(year, null, DateTimeStyles.AdjustToUniversal, out var parsedDate)) { - video.PremiereDate = parsedDate.ToUniversalTime(); + video.PremiereDate = parsedDate; } var description = tags.GetValueOrDefault("WM/SubTitleDescription"); @@ -1468,7 +1468,7 @@ namespace MediaBrowser.MediaEncoding.Probing // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S] if (string.IsNullOrWhiteSpace(subTitle) && !string.IsNullOrWhiteSpace(description) - && description.AsSpan()[0..Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)].IndexOf(':') != -1) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename + && description.AsSpan()[..Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)].Contains(':')) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename { string[] descriptionParts = description.Split(':'); if (descriptionParts.Length > 0) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index b3efb8634..f7f4ea065 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -268,9 +268,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var added)) + if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var added)) { - item.DateCreated = added.ToUniversalTime(); + item.DateCreated = added; } else { @@ -384,9 +384,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val) && userData != null) { - if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var added)) + if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var added)) { - userData.LastPlayedDate = added.ToUniversalTime(); + userData.LastPlayedDate = added; } else { @@ -685,9 +685,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var date) && date.Year > 1850) + if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var date) && date.Year > 1850) { - item.PremiereDate = date.ToUniversalTime(); + item.PremiereDate = date; item.ProductionYear = date.Year; } } @@ -703,9 +703,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var date) && date.Year > 1850) + if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var date) && date.Year > 1850) { - item.EndDate = date.ToUniversalTime(); + item.EndDate = date; } } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index d002d5a34..d0d472e4d 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -69,7 +69,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal("Album", res.Album); Assert.Equal(2021, res.ProductionYear); Assert.True(res.PremiereDate.HasValue); - Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); + Assert.Equal(DateTime.Parse("2021-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate); } [Fact] @@ -85,7 +85,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal("City to City", res.Album); Assert.Equal(1978, res.ProductionYear); Assert.True(res.PremiereDate.HasValue); - Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); + Assert.Equal(DateTime.Parse("1978-01-01T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate); Assert.Contains("Electronic", res.Genres); Assert.Contains("Ambient", res.Genres); Assert.Contains("Pop", res.Genres); @@ -105,7 +105,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal("Eyes wide open", res.Album); Assert.Equal(2020, res.ProductionYear); Assert.True(res.PremiereDate.HasValue); - Assert.Equal(DateTime.Parse("2020-10-26T00:00Z", DateTimeFormatInfo.CurrentInfo).ToUniversalTime(), res.PremiereDate); + Assert.Equal(DateTime.Parse("2020-10-26T00:00Z", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.AdjustToUniversal), res.PremiereDate); Assert.Equal(22, res.People.Length); Assert.Equal("Krysta Youngs", res.People[0].Name); Assert.Equal(PersonType.Composer, res.People[0].Type); -- cgit v1.2.3 From 52585a865e921196c6e47fe18b19b63107398d8d Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Tue, 21 Sep 2021 13:28:34 +0200 Subject: Validate ffmpeg path --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a7bcaf544..4cbd1bbc8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -165,14 +165,22 @@ namespace MediaBrowser.MediaEncoding.Encoder // User had cleared the custom path in UI newPath = string.Empty; } - else if (Directory.Exists(path)) - { - // Given path is directory, so resolve down to filename - newPath = GetEncoderPathFromDirectory(path, "ffmpeg"); - } else { - newPath = path; + if (Directory.Exists(path)) + { + // Given path is directory, so resolve down to filename + newPath = GetEncoderPathFromDirectory(path, "ffmpeg"); + } + else + { + newPath = path; + } + + if (!new EncoderValidator(_logger, newPath).ValidateVersion()) + { + throw new ResourceNotFoundException(); + } } // Write the new ffmpeg path to the xml as <EncoderAppPath> -- cgit v1.2.3 From 95f344722ce34dde75408bce4138fe47b7eef6d0 Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Sat, 11 Sep 2021 16:20:49 +0200 Subject: Don't set ffmpeg path from null to its Display value + add 404 --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4cbd1bbc8..057293b66 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -151,6 +151,16 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <param name="pathType">The path type.</param> public void UpdateEncoderPath(string path, string pathType) { + var config = _configurationManager.GetEncodingOptions(); + + // Filesystem may not be case insensitive, but EncoderAppPathDisplay should always point to a valid file? + if (string.IsNullOrEmpty(config.EncoderAppPath) + && string.Equals(config.EncoderAppPathDisplay, path, StringComparison.OrdinalIgnoreCase)) + { + _logger.LogDebug("Existing ffmpeg path is empty and the new path is the same as {EncoderAppPathDisplay}. Skipping", nameof(config.EncoderAppPathDisplay)); + return; + } + string newPath; _logger.LogInformation("Attempting to update encoder path to {Path}. pathType: {PathType}", path ?? string.Empty, pathType ?? string.Empty); @@ -183,9 +193,14 @@ namespace MediaBrowser.MediaEncoding.Encoder } } + // Don't save an invalid path + if (!File.Exists(path)) + { + throw new FileNotFoundException(); + } + // Write the new ffmpeg path to the xml as <EncoderAppPath> // This ensures its not lost on next startup - var config = _configurationManager.GetEncodingOptions(); config.EncoderAppPath = newPath; _configurationManager.SaveConfiguration("encoding", config); -- cgit v1.2.3 From a353081ea33b3f635e9472371f228bab63669347 Mon Sep 17 00:00:00 2001 From: Claus Vium <cvium@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:54:11 +0200 Subject: Update MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 ------ 1 file changed, 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 057293b66..22ed9a8eb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -193,12 +193,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - // Don't save an invalid path - if (!File.Exists(path)) - { - throw new FileNotFoundException(); - } - // Write the new ffmpeg path to the xml as <EncoderAppPath> // This ensures its not lost on next startup config.EncoderAppPath = newPath; -- cgit v1.2.3 From 13fbfe6091e61450aedc07bc78c96bf4c414bc65 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 14 Feb 2021 15:11:46 +0100 Subject: Target net6.0 --- DvdLib/DvdLib.csproj | 2 +- DvdLib/Ifo/Dvd.cs | 3 ++- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 3 +-- Emby.Dlna/Service/BaseService.cs | 8 ++++---- Emby.Drawing/Emby.Drawing.csproj | 2 +- Emby.Naming/Emby.Naming.csproj | 2 +- Emby.Notifications/Emby.Notifications.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- .../Emby.Server.Implementations.csproj | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../FirstTimeSetupOrDefaultHandler.cs | 6 +++--- .../FirstTimeSetupOrElevatedHandler.cs | 6 +++--- Jellyfin.Api/Controllers/ImageController.cs | 10 +++++----- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 3 ++- Jellyfin.Api/Jellyfin.Api.csproj | 2 +- Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs | 5 +++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 7 +------ Jellyfin.Networking/Jellyfin.Networking.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 2 +- Jellyfin.Server/Configuration/CorsPolicyProvider.cs | 4 ++-- .../SymlinkFollowingPhysicalFileResultExecutor.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- .../Middleware/QueryStringDecodingMiddleware.cs | 6 +++++- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- MediaBrowser.Controller/Dlna/IDlnaManager.cs | 2 +- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 +- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 7 ++++++- .../MediaBrowser.LocalMetadata.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 2 +- .../Subtitles/SubtitleEditParser.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Model/Net/MimeTypes.cs | 12 +++++++----- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 +- .../Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs | 2 +- .../MediaBrowser.XbmcMetadata.csproj | 2 +- RSSDP/DisposableManagedObjectBase.cs | 5 +++-- RSSDP/RSSDP.csproj | 2 +- RSSDP/SsdpDevice.cs | 13 ++++++++----- RSSDP/SsdpDevicePublisher.cs | 15 ++++++++------- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 2 +- .../Jellyfin.Controller.Tests.csproj | 2 +- tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 2 +- .../Jellyfin.Extensions.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj | 2 +- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Networking.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 2 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 2 +- 56 files changed, 103 insertions(+), 90 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj index b8301e2f2..755d29160 100644 --- a/DvdLib/DvdLib.csproj +++ b/DvdLib/DvdLib.csproj @@ -10,7 +10,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <AnalysisMode>AllDisabledByDefault</AnalysisMode> diff --git a/DvdLib/Ifo/Dvd.cs b/DvdLib/Ifo/Dvd.cs index b4a11ed5d..7f8ece47d 100644 --- a/DvdLib/Ifo/Dvd.cs +++ b/DvdLib/Ifo/Dvd.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; @@ -76,7 +77,7 @@ namespace DvdLib.Ifo private void ReadVTS(ushort vtsNum, IReadOnlyList<FileInfo> allFiles) { - var filename = string.Format("VTS_{0:00}_0.IFO", vtsNum); + var filename = string.Format(CultureInfo.InvariantCulture, "VTS_{0:00}_0.IFO", vtsNum); var vtsPath = allFiles.FirstOrDefault(i => string.Equals(i.Name, filename, StringComparison.OrdinalIgnoreCase)) ?? allFiles.FirstOrDefault(i => string.Equals(i.Name, Path.ChangeExtension(filename, ".bup"), StringComparison.OrdinalIgnoreCase)); diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 68fc80c0a..385550432 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -486,7 +486,7 @@ namespace Emby.Dlna } /// <inheritdoc /> - public ImageStream GetIcon(string filename) + public ImageStream? GetIcon(string filename) { var format = filename.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ? ImageFormat.Png diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 970c16d2e..1d4e3b047 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -17,7 +17,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <AnalysisMode>AllDisabledByDefault</AnalysisMode> diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 3f3dfccd3..09525aae4 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -250,8 +250,7 @@ namespace Emby.Dlna.Server url = _serverAddress.TrimEnd('/') + "/dlna/" + _serverUdn + "/" + url.TrimStart('/'); - // TODO: @bond remove null-coalescing operator when https://github.com/dotnet/runtime/pull/52442 is merged/released - return SecurityElement.Escape(url) ?? string.Empty; + return SecurityElement.Escape(url); } private IEnumerable<DeviceIcon> GetIcons() diff --git a/Emby.Dlna/Service/BaseService.cs b/Emby.Dlna/Service/BaseService.cs index a97c4d63a..68fd98758 100644 --- a/Emby.Dlna/Service/BaseService.cs +++ b/Emby.Dlna/Service/BaseService.cs @@ -23,14 +23,14 @@ namespace Emby.Dlna.Service return EventManager.CancelEventSubscription(subscriptionId); } - public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl) + public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl) { - return EventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl); + return EventManager.RenewEventSubscription(subscriptionId, notificationType, requestedTimeoutString, callbackUrl); } - public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl) + public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl) { - return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl); + return EventManager.CreateEventSubscription(notificationType, requestedTimeoutString, callbackUrl); } } } diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index baf350c6f..300eea968 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <AnalysisMode>AllDisabledByDefault</AnalysisMode> diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 07d879e96..96f8f389b 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index 5edcf2f29..d200682e6 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index 00b2f0f94..bf6252c19 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -19,7 +19,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 769972d8c..0e1386ef5 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -42,7 +42,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index a8f761fde..6a2e7f699 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -196,7 +196,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun cancellationToken, timeOutSource.Token)) { - var resTask = udpClient.ReceiveAsync(); + var resTask = udpClient.ReceiveAsync(linkedSource.Token).AsTask(); if (await Task.WhenAny(resTask, Task.Delay(30000, linkedSource.Token)).ConfigureAwait(false) != resTask) { resTask.Dispose(); diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs index 9815e252e..dd0bd4ec2 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrDefaultPolicy/FirstTimeSetupOrDefaultHandler.cs @@ -32,18 +32,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrDefaultPolicy } /// <inheritdoc /> - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrDefaultRequirement firstTimeSetupOrDefaultRequirement) + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrDefaultRequirement requirement) { if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted) { - context.Succeed(firstTimeSetupOrDefaultRequirement); + context.Succeed(requirement); return Task.CompletedTask; } var validated = ValidateClaims(context.User); if (validated) { - context.Succeed(firstTimeSetupOrDefaultRequirement); + context.Succeed(requirement); } else { diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs index decbe0c03..90b76ee99 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs @@ -33,18 +33,18 @@ namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy } /// <inheritdoc /> - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement firstTimeSetupOrElevatedRequirement) + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement requirement) { if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted) { - context.Succeed(firstTimeSetupOrElevatedRequirement); + context.Succeed(requirement); return Task.CompletedTask; } var validated = ValidateClaims(context.User); if (validated && context.User.IsInRole(UserRoles.Administrator)) { - context.Succeed(firstTimeSetupOrElevatedRequirement); + context.Succeed(requirement); } else { diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 9dc280e13..b1c860d61 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -106,7 +106,7 @@ namespace Jellyfin.Api.Controllers await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); // Handle image/png; charset=utf-8 - var mimeType = Request.ContentType.Split(';').FirstOrDefault(); + var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); if (user.ProfileImage != null) { @@ -153,7 +153,7 @@ namespace Jellyfin.Api.Controllers await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); // Handle image/png; charset=utf-8 - var mimeType = Request.ContentType.Split(';').FirstOrDefault(); + var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); if (user.ProfileImage != null) { @@ -341,7 +341,7 @@ namespace Jellyfin.Api.Controllers await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); // Handle image/png; charset=utf-8 - var mimeType = Request.ContentType.Split(';').FirstOrDefault(); + var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); @@ -377,7 +377,7 @@ namespace Jellyfin.Api.Controllers await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false); // Handle image/png; charset=utf-8 - var mimeType = Request.ContentType.Split(';').FirstOrDefault(); + var mimeType = Request.ContentType?.Split(';').FirstOrDefault(); await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); @@ -2026,7 +2026,7 @@ namespace Jellyfin.Api.Controllers return NoContent(); } - return PhysicalFile(imagePath, imageContentType); + return PhysicalFile(imagePath, imageContentType ?? MediaTypeNames.Text.Plain); } } } diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index b0fd59e5e..6385b62c9 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Net.Http; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.PlaybackDtos; @@ -40,7 +41,7 @@ namespace Jellyfin.Api.Helpers // Can't dispose the response as it's required up the call chain. var response = await httpClient.GetAsync(new Uri(state.MediaPath), cancellationToken).ConfigureAwait(false); - var contentType = response.Content.Headers.ContentType?.ToString(); + var contentType = response.Content.Headers.ContentType?.ToString() ?? MediaTypeNames.Text.Plain; httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 7f4eb0378..8cc4711a7 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateDocumentationFile>true</GenerateDocumentationFile> <!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 --> <NoWarn>AD0001</NoWarn> diff --git a/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs b/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs index be2045fba..d2e78ac88 100644 --- a/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs +++ b/Jellyfin.Api/ModelBinders/NullableEnumModelBinder.cs @@ -32,7 +32,8 @@ namespace Jellyfin.Api.ModelBinders { try { - var convertedValue = converter.ConvertFromString(valueProviderResult.FirstValue); + // REVIEW: This shouldn't be null here + var convertedValue = converter.ConvertFromString(valueProviderResult.FirstValue!); bindingContext.Result = ModelBindingResult.Success(convertedValue); } catch (FormatException e) @@ -44,4 +45,4 @@ namespace Jellyfin.Api.ModelBinders return Task.CompletedTask; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 65bbd49da..19aef704c 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 8cee5dcae..5fa386eca 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> @@ -28,11 +28,6 @@ <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> </ItemGroup> - <ItemGroup> - <!-- Needed for https://github.com/dotnet/roslyn-analyzers/issues/4382 which is in the SDK yet --> - <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3" PrivateAssets="All" /> - </ItemGroup> - <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 227a41ce4..0cd9a5915 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 434c414a4..337f5cb82 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/Jellyfin.Server/Configuration/CorsPolicyProvider.cs b/Jellyfin.Server/Configuration/CorsPolicyProvider.cs index 0d04b6bb1..b061be33b 100644 --- a/Jellyfin.Server/Configuration/CorsPolicyProvider.cs +++ b/Jellyfin.Server/Configuration/CorsPolicyProvider.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Configuration } /// <inheritdoc /> - public Task<CorsPolicy> GetPolicyAsync(HttpContext context, string policyName) + public Task<CorsPolicy?> GetPolicyAsync(HttpContext context, string? policyName) { var corsHosts = _serverConfigurationManager.Configuration.CorsHosts; var builder = new CorsPolicyBuilder() @@ -43,7 +43,7 @@ namespace Jellyfin.Server.Configuration .AllowCredentials(); } - return Task.FromResult(builder.Build()); + return Task.FromResult<CorsPolicy?>(builder.Build()); } } } diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index e171fc145..4abd5b36d 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Server.Infrastructure } /// <inheritdoc /> - protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue range, long rangeLength) + protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength) { if (context == null) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index fc935cecb..074d43fba 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -8,7 +8,7 @@ <PropertyGroup> <AssemblyName>jellyfin</AssemblyName> <OutputType>Exe</OutputType> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <ServerGarbageCollection>false</ServerGarbageCollection> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> diff --git a/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs b/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs index fd0ebbf43..cdd86e28e 100644 --- a/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs +++ b/Jellyfin.Server/Middleware/QueryStringDecodingMiddleware.cs @@ -27,7 +27,11 @@ namespace Jellyfin.Server.Middleware /// <returns>The async task.</returns> public async Task Invoke(HttpContext httpContext) { - httpContext.Features.Set<IQueryFeature>(new UrlDecodeQueryFeature(httpContext.Features.Get<IQueryFeature>())); + var feature = httpContext.Features.Get<IQueryFeature>(); + if (feature != null) + { + httpContext.Features.Set<IQueryFeature>(new UrlDecodeQueryFeature(feature)); + } await _next(httpContext).ConfigureAwait(false); } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 12cfaf978..6358c0000 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -29,7 +29,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/MediaBrowser.Controller/Dlna/IDlnaManager.cs b/MediaBrowser.Controller/Dlna/IDlnaManager.cs index a64919700..cc0a107a8 100644 --- a/MediaBrowser.Controller/Dlna/IDlnaManager.cs +++ b/MediaBrowser.Controller/Dlna/IDlnaManager.cs @@ -74,6 +74,6 @@ namespace MediaBrowser.Controller.Dlna /// </summary> /// <param name="filename">The filename.</param> /// <returns>DlnaIconResponse.</returns> - ImageStream GetIcon(string filename); + ImageStream? GetIcon(string filename); } } diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index c7f61a90b..7ca0e851b 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Drawing /// <returns>Guid.</returns> string GetImageCacheTag(BaseItem item, ItemImageInfo image); - string GetImageCacheTag(BaseItem item, ChapterInfo info); + string GetImageCacheTag(BaseItem item, ChapterInfo chapter); string? GetImageCacheTag(User user); diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 0f697bccc..47cec7d77 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -32,7 +32,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index b09b7dba6..e92c4a08a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -541,7 +541,12 @@ namespace MediaBrowser.Controller.MediaEncoding return MimeType; } - return MimeTypes.GetMimeType(outputPath, enableStreamDefault); + if (enableStreamDefault) + { + return MimeTypes.GetMimeType(outputPath); + } + + return MimeTypes.GetMimeType(outputPath, null); } public bool DeInterlace(string videoCodec, bool forceDeinterlaceIfSourceIsInterlaced) diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 1cf8fcd1b..a3db717b9 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -11,7 +11,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 5deaecc95..30cfb904e 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 3d864e29c..20e4be780 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subRip.LoadSubtitle(subtitle, lines, "untitled"); if (subRip.ErrorCount > 0) { - _logger.LogError("{ErrorCount} errors encountered while parsing subtitle."); + _logger.LogError("{ErrorCount} errors encountered while parsing subtitle.", subRip.ErrorCount); } var trackInfo = new SubtitleTrackInfo(); diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index a371afc2c..b0a12a9c9 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -14,7 +14,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <PublishRepositoryUrl>true</PublishRepositoryUrl> diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 7b3c17c85..1d9150f02 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Jellyfin.Extensions; @@ -164,15 +165,16 @@ namespace MediaBrowser.Model.Net return dict; } - public static string? GetMimeType(string path) => GetMimeType(path, true); + public static string GetMimeType(string path) => GetMimeType(path, "application/octet-stream"); /// <summary> /// Gets the type of the MIME. /// </summary> /// <param name="filename">The filename to find the MIME type of.</param> - /// <param name="enableStreamDefault">Whether of not to return a default value if no fitting MIME type is found.</param> - /// <returns>The worrect MIME type for the given filename, or `null` if it wasn't found and <paramref name="enableStreamDefault"/> is false.</returns> - public static string? GetMimeType(string filename, bool enableStreamDefault) + /// <param name="defaultValue">Theefault value to return if no fitting MIME type is found.</param> + /// <returns>The correct MIME type for the given filename, or <paramref name="defaultValue"/> if it wasn't found.</returns> + [return: NotNullIfNotNullAttribute("defaultValue")] + public static string? GetMimeType(string filename, string? defaultValue = null) { if (filename.Length == 0) { @@ -211,7 +213,7 @@ namespace MediaBrowser.Model.Net return "application/octet-stream"; } - return enableStreamDefault ? "application/octet-stream" : null; + return defaultValue; } public static string? ToExtension(string mimeType) diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 3a6e16274..29d6b01f2 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -26,7 +26,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> diff --git a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs index 268538815..19d90b9a1 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb if (reader.TokenType == JsonTokenType.String) { var str = reader.GetString(); - if (str != null && str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) + if (str == null || str.Equals("N/A", StringComparison.OrdinalIgnoreCase)) { return null; } diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 3e2a9bacf..926be5a92 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -15,7 +15,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> diff --git a/RSSDP/DisposableManagedObjectBase.cs b/RSSDP/DisposableManagedObjectBase.cs index 7d6a471f9..5d7da4124 100644 --- a/RSSDP/DisposableManagedObjectBase.cs +++ b/RSSDP/DisposableManagedObjectBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text; namespace Rssdp.Infrastructure @@ -45,11 +46,11 @@ namespace Rssdp.Infrastructure const string ArgFormat = "{0}: {1}\r\n"; - builder.AppendFormat("{0}\r\n", header); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}\r\n", header); foreach (var pair in values) { - builder.AppendFormat(ArgFormat, pair.Key, pair.Value); + builder.AppendFormat(CultureInfo.InvariantCulture, ArgFormat, pair.Key, pair.Value); } builder.Append("\r\n"); diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 54113d464..77130983b 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -11,7 +11,7 @@ </ItemGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <AnalysisMode>AllDisabledByDefault</AnalysisMode> <Nullable>disable</Nullable> diff --git a/RSSDP/SsdpDevice.cs b/RSSDP/SsdpDevice.cs index 4005d836d..c826830f1 100644 --- a/RSSDP/SsdpDevice.cs +++ b/RSSDP/SsdpDevice.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; using Rssdp.Infrastructure; namespace Rssdp @@ -134,11 +135,13 @@ namespace Rssdp { get { - return String.Format("urn:{0}:{3}:{1}:{2}", - this.DeviceTypeNamespace ?? String.Empty, - this.DeviceType ?? String.Empty, - this.DeviceVersion, - this.DeviceClass ?? "device"); + return String.Format( + CultureInfo.InvariantCulture, + "urn:{0}:{3}:{1}:{2}", + this.DeviceTypeNamespace ?? String.Empty, + this.DeviceType ?? String.Empty, + this.DeviceVersion, + this.DeviceClass ?? "device"); } } diff --git a/RSSDP/SsdpDevicePublisher.cs b/RSSDP/SsdpDevicePublisher.cs index c9e795d56..64d19803d 100644 --- a/RSSDP/SsdpDevicePublisher.cs +++ b/RSSDP/SsdpDevicePublisher.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; using System.Linq; using System.Net; using System.Threading; @@ -233,7 +234,7 @@ namespace Rssdp.Infrastructure { if (String.IsNullOrEmpty(searchTarget)) { - WriteTrace(String.Format("Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString())); + WriteTrace(String.Format(CultureInfo.InvariantCulture, "Invalid search request received From {0}, Target is null/empty.", remoteEndPoint.ToString())); return; } @@ -340,7 +341,7 @@ namespace Rssdp.Infrastructure private string GetUsn(string udn, string fullDeviceType) { - return String.Format("{0}::{1}", udn, fullDeviceType); + return String.Format(CultureInfo.InvariantCulture, "{0}::{1}", udn, fullDeviceType); } private async void SendSearchResponse( @@ -363,7 +364,7 @@ namespace Rssdp.Infrastructure values["DATE"] = DateTime.UtcNow.ToString("r"); values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds; values["ST"] = searchTarget; - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["USN"] = uniqueServiceName; values["LOCATION"] = rootDevice.Location.ToString(); @@ -497,7 +498,7 @@ namespace Rssdp.Infrastructure values["DATE"] = DateTime.UtcNow.ToString("r"); values["CACHE-CONTROL"] = "max-age = " + rootDevice.CacheLifetime.TotalSeconds; values["LOCATION"] = rootDevice.Location.ToString(); - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["NTS"] = "ssdp:alive"; values["NT"] = notificationType; values["USN"] = uniqueServiceName; @@ -522,7 +523,7 @@ namespace Rssdp.Infrastructure } tasks.Add(SendByeByeNotification(device, device.Udn, device.Udn, cancellationToken)); - tasks.Add(SendByeByeNotification(device, String.Format("urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken)); + tasks.Add(SendByeByeNotification(device, String.Format(CultureInfo.InvariantCulture, "urn:{0}", device.FullDeviceType), GetUsn(device.Udn, device.FullDeviceType), cancellationToken)); foreach (var childDevice in device.Devices) { @@ -542,7 +543,7 @@ namespace Rssdp.Infrastructure // If needed later for non-server devices, these headers will need to be dynamic values["HOST"] = "239.255.255.250:1900"; values["DATE"] = DateTime.UtcNow.ToString("r"); - values["SERVER"] = string.Format("{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); + values["SERVER"] = string.Format(CultureInfo.InvariantCulture, "{0}/{1} UPnP/1.0 RSSDP/{2}", _OSName, _OSVersion, ServerVersion); values["NTS"] = "ssdp:byebye"; values["NT"] = notificationType; values["USN"] = uniqueServiceName; @@ -550,7 +551,7 @@ namespace Rssdp.Infrastructure var message = BuildMessage(header, values); var sendCount = IsDisposed ? 1 : 3; - WriteTrace(String.Format("Sent byebye notification"), device); + WriteTrace(String.Format(CultureInfo.InvariantCulture, "Sent byebye notification"), device); return _CommsServer.SendMulticastMessage(message, sendCount, _sendOnlyMatchedHost ? device.ToRootDevice().Address : null, cancellationToken); } diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 9dac63e70..b52ea078a 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 1619fa89c..1fe4e2565 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index a5778b59c..e9a951571 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 5a48631c2..1fb95aab4 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index 20680157f..2dc4ac19a 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e9cd8c062..201f63a2d 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 09b8a7a94..a37e5ac92 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index a4ebab141..75d466198 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 5fa2ecfe9..75d9b9ea9 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 9b6ab7bdf..5ecd84604 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -6,7 +6,7 @@ </PropertyGroup> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> <RootNamespace>Jellyfin.Server.Implementations.Tests</RootNamespace> diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 42e60df5f..7939c7118 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 4f0bbc36c..b30e690a5 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index e08590758..94294c8bf 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net5.0</TargetFramework> + <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> -- cgit v1.2.3 From 4643fd5dcbc6d1a4fbe973efc68d92ca71e3ab3b Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 25 Sep 2021 18:15:46 +0200 Subject: Address comments --- Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs | 10 +++++++--- MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs | 2 +- .../EncodedQueryStringTest.cs | 1 + tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs | 3 --- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs index 35959ee32..b5f515cda 100644 --- a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs +++ b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs @@ -52,10 +52,14 @@ namespace Jellyfin.Server.Middleware return; } - var pairs = new Dictionary<string, StringValues>(); - var queryString = HttpUtility.UrlDecode(key).SpanSplit('&'); + if (!key.Contains('=')) + { + _store = value; + return; + } - foreach (var pair in queryString) + var pairs = new Dictionary<string, StringValues>(); + foreach (var pair in key.SpanSplit('&')) { var i = pair.IndexOf('='); if (i == -1) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 20e4be780..52c1b6467 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles subRip.LoadSubtitle(subtitle, lines, "untitled"); if (subRip.ErrorCount > 0) { - _logger.LogError("{ErrorCount} errors encountered while parsing subtitle.", subRip.ErrorCount); + _logger.LogError("{ErrorCount} errors encountered while parsing subtitle", subRip.ErrorCount); } var trackInfo = new SubtitleTrackInfo(); diff --git a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs index 732b4f050..2361e4aa4 100644 --- a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs +++ b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs @@ -21,6 +21,7 @@ namespace Jellyfin.Server.Integration.Tests [InlineData("a=1", "a=1")] // won't be processed as it has a value [InlineData("a%3D1%26b%3D2%26c%3D3", "a=1&b=2&c=3")] // will be processed. [InlineData("a=b&a=c", "a=b")] + [InlineData("a%3D1", "a=1")] [InlineData("a%3Db%26a%3Dc", "a=b")] public async Task Ensure_Decoding_Of_Urls_Is_Working(string sourceUrl, string unencodedUrl) { diff --git a/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs index 419afb2dc..d15c9d6f5 100644 --- a/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs +++ b/tests/Jellyfin.Server.Tests/UrlDecodeQueryFeatureTests.cs @@ -12,9 +12,6 @@ namespace Jellyfin.Server.Tests { [Theory] [InlineData("e0a72cb2a2c7", "e0a72cb2a2c7")] // isn't encoded - [InlineData("random+test", "random test")] // encoded - [InlineData("random%20test", "random test")] // encoded - [InlineData("++", " ")] // encoded public static void EmptyValueTest(string query, string key) { var dict = new Dictionary<string, StringValues> -- cgit v1.2.3 From f31224fa8f1dccb730703c048c26e14b5d14fa55 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sat, 25 Sep 2021 19:44:40 +0200 Subject: Remove sync FileStream hack --- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Drawing/ImageProcessor.cs | 2 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 4 ++-- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 2 +- .../LiveTv/TunerHosts/LiveStream.cs | 6 +++--- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 2 +- Jellyfin.Api/Controllers/SystemController.cs | 2 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 2 +- Jellyfin.Api/Helpers/ProgressiveFileStream.cs | 24 ++-------------------- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../SymlinkFollowingPhysicalFileResultExecutor.cs | 2 +- Jellyfin.Server/Program.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/IO/AsyncFile.cs | 11 ++-------- MediaBrowser.Providers/Manager/ImageSaver.cs | 2 +- .../Manager/ItemImageProvider.cs | 2 +- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 2 +- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 2 +- .../Plugins/Omdb/OmdbProvider.cs | 4 ++-- .../Studios/StudiosImageProvider.cs | 2 +- .../Subtitles/SubtitleManager.cs | 2 +- 23 files changed, 29 insertions(+), 56 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 305e43a3c..8fe9d484e 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -366,7 +366,7 @@ namespace Emby.Dlna Directory.CreateDirectory(systemProfilesPath); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 0ad8bca31..9b130fdfd 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -102,7 +102,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index f6e0111b6..41381d55b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { onStarted(); @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO); + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index a943efcc7..3633fa3e1 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index cb9801c17..2e51ac807 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO)) + await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous)) { await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 817b1f804..20a9a705b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public Stream GetStream() { - var stream = GetInputStream(TempFilePath, AsyncFile.UseAsyncIO); + var stream = GetInputStream(TempFilePath); bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10; if (seekFile) { @@ -107,14 +107,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return stream; } - protected FileStream GetInputStream(string path, bool allowAsyncFileRead) + protected FileStream GetInputStream(string path) => new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, - allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan); + FileOptions.SequentialScan | FileOptions.Asynchronous); protected async Task DeleteTempFiles(string path, int retryCount = 0) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 84a878e51..3b69e55b0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -118,7 +118,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await StreamHelper.CopyToAsync( stream, fileStream, diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index bcb2b50c7..8a33b12f4 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -206,7 +206,7 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index e6584f0fe..741bdfee9 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers // For older files, assume fully static var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite; - FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); return File(stream, "text/plain; charset=utf-8"); } diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index f36769dc2..456762147 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -38,7 +38,7 @@ namespace Jellyfin.Api.Helpers FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, - (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan); + FileOptions.Asynchronous | FileOptions.SequentialScan); await using (fileStream.ConfigureAwait(false)) { using var reader = new StreamReader(fileStream); diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs index c57018351..61e18220a 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs @@ -17,7 +17,6 @@ namespace Jellyfin.Api.Helpers private readonly TranscodingJobDto? _job; private readonly TranscodingJobHelper? _transcodingJobHelper; private readonly int _timeoutMs; - private readonly bool _allowAsyncFileRead; private int _bytesWritten; private bool _disposed; @@ -34,17 +33,7 @@ namespace Jellyfin.Api.Helpers _transcodingJobHelper = transcodingJobHelper; _timeoutMs = timeoutMs; - var fileOptions = FileOptions.SequentialScan; - _allowAsyncFileRead = false; - - // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 - if (AsyncFile.UseAsyncIO) - { - fileOptions |= FileOptions.Asynchronous; - _allowAsyncFileRead = true; - } - - _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); + _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan); } /// <summary> @@ -57,7 +46,6 @@ namespace Jellyfin.Api.Helpers _job = null; _transcodingJobHelper = null; _timeoutMs = timeoutMs; - _allowAsyncFileRead = AsyncFile.UseAsyncIO; _stream = stream; } @@ -103,15 +91,7 @@ namespace Jellyfin.Api.Helpers while (remainingBytesToRead > 0) { cancellationToken.ThrowIfCancellationRequested(); - int bytesRead; - if (_allowAsyncFileRead) - { - bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false); - } - else - { - bytesRead = _stream.Read(buffer, newOffset, remainingBytesToRead); - } + int bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false); remainingBytesToRead -= bytesRead; newOffset += bytesRead; diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 4e1e98df0..14f287aef 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -557,7 +557,7 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 4abd5b36d..f3fbab77e 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -132,7 +132,7 @@ namespace Jellyfin.Server.Infrastructure FileAccess.Read, FileShare.ReadWrite, bufferSize: BufferSize, - options: (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan); + options: FileOptions.Asynchronous | FileOptions.SequentialScan); fileStream.Seek(offset, SeekOrigin.Begin); await StreamCopyOperation diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 1300ce3b6..f36675b95 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -547,7 +547,7 @@ namespace Jellyfin.Server ?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'"); // Copy the resource contents to the expected file path for the config file - await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await resource.CopyToAsync(dst).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index f8451e92c..022cdbe9d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -680,7 +680,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs index b888a4163..f38ed9ae3 100644 --- a/MediaBrowser.Model/IO/AsyncFile.cs +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -8,20 +8,13 @@ namespace MediaBrowser.Model.IO /// </summary> public static class AsyncFile { - /// <summary> - /// Gets a value indicating whether we should use async IO on this platform. - /// <see href="https://github.com/dotnet/runtime/issues/16354" />. - /// </summary> - /// <returns>Returns <c>false</c> on Windows; otherwise <c>true</c>.</returns> - public static bool UseAsyncIO => !OperatingSystem.IsWindows(); - /// <summary> /// Opens an existing file for reading. /// </summary> /// <param name="path">The file to be opened for reading.</param> /// <returns>A read-only <see cref="FileStream" /> on the specified path.</returns> public static FileStream OpenRead(string path) - => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, UseAsyncIO); + => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); /// <summary> /// Opens an existing file for writing. @@ -29,6 +22,6 @@ namespace MediaBrowser.Model.IO /// <param name="path">The file to be opened for writing.</param> /// <returns>An unshared <see cref="FileStream" /> object on the specified path with Write access.</returns> public static FileStream OpenWrite(string path) - => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, UseAsyncIO); + => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); } } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 6c14c8de1..7d259a9d3 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -264,7 +264,7 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO)) + await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 81529e984..73bca5aa5 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index c1226febf..3e0b0014e 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index 8572b3413..e0b2f9c58 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 1dea3dece..479ae0f39 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -295,7 +295,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb imdbParam)); var rootObject = await GetDeserializedOmdbResponse<RootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; @@ -335,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb seasonId)); var rootObject = await GetDeserializedOmdbResponse<SeasonRootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); - await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false); return path; diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 7a057c065..7b2454efc 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Studios Directory.CreateDirectory(Path.GetDirectoryName(file)); await using var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO); + await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index d6c346ba1..772e617ab 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(savePath)); // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, AsyncFile.UseAsyncIO); + using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous); await stream.CopyToAsync(fs).ConfigureAwait(false); return; -- cgit v1.2.3 From 9234e5bf80194e45acac25c60cb76f401bffaf96 Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Sun, 26 Sep 2021 08:14:36 -0600 Subject: Remove all instances of en-US culture --- Emby.Dlna/Didl/DidlBuilder.cs | 28 +++++++-------- Emby.Dlna/Eventing/DlnaEventManager.cs | 8 ++--- Emby.Dlna/PlayTo/Device.cs | 12 +++---- Emby.Dlna/PlayTo/PlayToController.cs | 8 ++--- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 8 ++--- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 5 ++- .../MediaEncoder/EncodingManager.cs | 3 +- Jellyfin.Api/Controllers/ImageController.cs | 2 +- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- MediaBrowser.Controller/Entities/Year.cs | 4 +-- .../MediaEncoding/EncodingHelper.cs | 42 +++++++++++----------- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 11 +++--- .../Images/LocalImageProvider.cs | 4 +-- .../Parsers/BaseItemXmlParser.cs | 8 ++--- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 12 +++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 11 ++---- .../Probing/ProbeResultNormalizer.cs | 27 +++++++------- .../Globalization/ILocalizationManager.cs | 4 +-- MediaBrowser.Providers/Manager/ImageSaver.cs | 18 +++++----- .../Plugins/Omdb/OmdbProvider.cs | 13 ++++--- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 10 +++--- .../Parsers/EpisodeNfoParser.cs | 10 +++--- .../Savers/EpisodeNfoSaver.cs | 18 +++++----- 23 files changed, 116 insertions(+), 152 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index c00078499..0a84f30c4 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -41,8 +41,6 @@ namespace Emby.Dlna.Didl private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/"; private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/"; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly DeviceProfile _profile; private readonly IImageProcessor _imageProcessor; private readonly string _serverAddress; @@ -317,7 +315,7 @@ namespace Emby.Dlna.Didl if (mediaSource.RunTimeTicks.HasValue) { - writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); + writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture)); } if (filter.Contains("res@size")) @@ -328,7 +326,7 @@ namespace Emby.Dlna.Didl if (size.HasValue) { - writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); + writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture)); } } } @@ -342,7 +340,7 @@ namespace Emby.Dlna.Didl if (targetChannels.HasValue) { - writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); + writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture)); } if (filter.Contains("res@resolution")) @@ -361,12 +359,12 @@ namespace Emby.Dlna.Didl if (targetSampleRate.HasValue) { - writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); + writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } if (totalBitrate.HasValue) { - writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture)); + writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(CultureInfo.InvariantCulture)); } var mediaProfile = _profile.GetVideoMediaProfile( @@ -552,7 +550,7 @@ namespace Emby.Dlna.Didl if (mediaSource.RunTimeTicks.HasValue) { - writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); + writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture)); } if (filter.Contains("res@size")) @@ -563,7 +561,7 @@ namespace Emby.Dlna.Didl if (size.HasValue) { - writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); + writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture)); } } } @@ -575,17 +573,17 @@ namespace Emby.Dlna.Didl if (targetChannels.HasValue) { - writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); + writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture)); } if (targetSampleRate.HasValue) { - writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); + writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } if (targetAudioBitrate.HasValue) { - writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture)); + writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(CultureInfo.InvariantCulture)); } var mediaProfile = _profile.GetAudioMediaProfile( @@ -639,7 +637,7 @@ namespace Emby.Dlna.Didl writer.WriteAttributeString("restricted", "1"); writer.WriteAttributeString("searchable", "1"); - writer.WriteAttributeString("childCount", childCount.ToString(_usCulture)); + writer.WriteAttributeString("childCount", childCount.ToString(CultureInfo.InvariantCulture)); var clientId = GetClientId(folder, stubType); @@ -931,11 +929,11 @@ namespace Emby.Dlna.Didl if (item.IndexNumber.HasValue) { - AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp); + AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp); if (item is Episode) { - AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp); + AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp); } } } diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index b39bd5ce9..d17e23871 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -26,8 +26,6 @@ namespace Emby.Dlna.Eventing private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; @@ -83,7 +81,7 @@ namespace Emby.Dlna.Eventing if (!string.IsNullOrEmpty(header)) { // Starts with SECOND- - if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return val; } @@ -106,7 +104,7 @@ namespace Emby.Dlna.Eventing var response = new EventSubscriptionResponse(string.Empty, "text/plain"); response.Headers["SID"] = subscriptionId; - response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString; + response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(CultureInfo.InvariantCulture)) : requestedTimeoutString; return response; } @@ -163,7 +161,7 @@ namespace Emby.Dlna.Eventing options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType); options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange"); options.Headers.TryAddWithoutValidation("SID", subscription.Id); - options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture)); + options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(CultureInfo.InvariantCulture)); try { diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 11fcd81cf..0b2288000 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo { public class Device : IDisposable { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; @@ -640,7 +638,7 @@ namespace Emby.Dlna.PlayTo return; } - Volume = int.Parse(volumeValue, UsCulture); + Volume = int.Parse(volumeValue, CultureInfo.InvariantCulture); if (Volume > 0) { @@ -842,7 +840,7 @@ namespace Emby.Dlna.PlayTo if (!string.IsNullOrWhiteSpace(duration) && !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { - Duration = TimeSpan.Parse(duration, UsCulture); + Duration = TimeSpan.Parse(duration, CultureInfo.InvariantCulture); } else { @@ -854,7 +852,7 @@ namespace Emby.Dlna.PlayTo if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { - Position = TimeSpan.Parse(position, UsCulture); + Position = TimeSpan.Parse(position, CultureInfo.InvariantCulture); } var track = result.Document.Descendants("TrackMetaData").FirstOrDefault(); @@ -1194,8 +1192,8 @@ namespace Emby.Dlna.PlayTo var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth")); var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url")); - var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture); - var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture); + var widthValue = int.Parse(width, NumberStyles.Integer, CultureInfo.InvariantCulture); + var heightValue = int.Parse(height, NumberStyles.Integer, CultureInfo.InvariantCulture); return new DeviceIcon { diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 0e49fd2c0..f25d8017e 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -30,8 +30,6 @@ namespace Emby.Dlna.PlayTo { public class PlayToController : ISessionController, IDisposable { - private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US")); - private readonly SessionInfo _session; private readonly ISessionManager _sessionManager; private readonly ILibraryManager _libraryManager; @@ -716,7 +714,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetAudioStreamIndex: if (command.Arguments.TryGetValue("Index", out string index)) { - if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return SetAudioStreamIndex(val); } @@ -728,7 +726,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetSubtitleStreamIndex: if (command.Arguments.TryGetValue("Index", out index)) { - if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return SetSubtitleStreamIndex(val); } @@ -740,7 +738,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetVolume: if (command.Arguments.TryGetValue("Volume", out string vol)) { - if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume)) + if (int.TryParse(vol, NumberStyles.Integer, CultureInfo.InvariantCulture, out var volume)) { return _device.SetVolume(volume, cancellationToken); } diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 4b92fbff4..cade7b4c2 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50"; private const string FriendlyName = "Jellyfin"; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IHttpClientFactory _httpClientFactory; public SsdpHttpClient(IHttpClientFactory httpClientFactory) @@ -80,10 +78,10 @@ namespace Emby.Dlna.PlayTo { using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url); options.Headers.UserAgent.ParseAdd(USERAGENT); - options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture)); - options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">"); + options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(CultureInfo.InvariantCulture)); + options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(CultureInfo.InvariantCulture) + ">"); options.Headers.TryAddWithoutValidation("NT", "upnp:event"); - options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture)); + options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(CultureInfo.InvariantCulture)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .SendAsync(options, HttpCompletionOption.ResponseHeadersRead) diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 09525aae4..80a45f2b2 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -15,7 +15,6 @@ namespace Emby.Dlna.Server { private readonly DeviceProfile _profile; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly string _serverUdn; private readonly string _serverAddress; private readonly string _serverName; @@ -193,10 +192,10 @@ namespace Emby.Dlna.Server .Append(SecurityElement.Escape(icon.MimeType ?? string.Empty)) .Append("</mimetype>"); builder.Append("<width>") - .Append(SecurityElement.Escape(icon.Width.ToString(_usCulture))) + .Append(SecurityElement.Escape(icon.Width.ToString(CultureInfo.InvariantCulture))) .Append("</width>"); builder.Append("<height>") - .Append(SecurityElement.Escape(icon.Height.ToString(_usCulture))) + .Append(SecurityElement.Escape(icon.Height.ToString(CultureInfo.InvariantCulture))) .Append("</height>"); builder.Append("<depth>") .Append(SecurityElement.Escape(icon.Depth ?? string.Empty)) diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 8aaa1f7bb..ac6606d39 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -23,7 +23,6 @@ namespace Emby.Server.Implementations.MediaEncoder { public class EncodingManager : IEncodingManager { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IFileSystem _fileSystem; private readonly ILogger<EncodingManager> _logger; private readonly IMediaEncoder _encoder; @@ -193,7 +192,7 @@ namespace Emby.Server.Implementations.MediaEncoder private string GetChapterImagePath(Video video, long chapterPositionTicks) { - var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; + var filename = video.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + "_" + chapterPositionTicks.ToString(CultureInfo.InvariantCulture) + ".jpg"; return Path.Combine(GetChapterImagesPath(video), filename); } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index b1c860d61..86933074d 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -2007,7 +2007,7 @@ namespace Jellyfin.Api.Controllers Response.Headers.Add(HeaderNames.CacheControl, "public"); } - Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", new CultureInfo("en-US", false))); + Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", CultureInfo.InvariantCulture)); // if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified if (!(dateImageModified > ifModifiedSinceHeader) && cacheDuration.HasValue) diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 11f67ee89..1849dd047 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -376,7 +376,7 @@ namespace Jellyfin.Api.Controllers var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks); var url = string.Format( - CultureInfo.CurrentCulture, + CultureInfo.InvariantCulture, "stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}", positionTicks.ToString(CultureInfo.InvariantCulture), endPositionTicks.ToString(CultureInfo.InvariantCulture), diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 0853200dd..afdaf448b 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -57,9 +57,7 @@ namespace MediaBrowser.Controller.Entities public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) { - var usCulture = new CultureInfo("en-US"); - - if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out var year)) + if (!int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year)) { return new List<BaseItem>(); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index bdb379332..5715194b8 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -21,8 +21,6 @@ namespace MediaBrowser.Controller.MediaEncoding { public class EncodingHelper { - private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; @@ -816,7 +814,7 @@ namespace MediaBrowser.Controller.MediaEncoding public static string NormalizeTranscodingLevel(EncodingJobInfo state, string level) { - if (double.TryParse(level, NumberStyles.Any, _usCulture, out double requestLevel)) + if (double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out double requestLevel)) { if (string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase) || string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase)) @@ -911,7 +909,7 @@ namespace MediaBrowser.Controller.MediaEncoding CultureInfo.InvariantCulture, "subtitles='{0}:si={1}'{2}", _mediaEncoder.EscapeSubtitleFilterPath(mediaPath), - state.InternalSubtitleStreamOffset.ToString(_usCulture), + state.InternalSubtitleStreamOffset.ToString(CultureInfo.InvariantCulture), // fallbackFontParam, setPtsParam); } @@ -1217,7 +1215,7 @@ namespace MediaBrowser.Controller.MediaEncoding param += string.Format( CultureInfo.InvariantCulture, " -speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", - profileScore.ToString(_usCulture), + profileScore.ToString(CultureInfo.InvariantCulture), crf, qmin, qmax); @@ -1289,7 +1287,7 @@ namespace MediaBrowser.Controller.MediaEncoding var framerate = GetFramerateParam(state); if (framerate.HasValue) { - param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(_usCulture)); + param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(CultureInfo.InvariantCulture)); } var targetVideoCodec = state.ActualOutputVideoCodec; @@ -1393,7 +1391,7 @@ namespace MediaBrowser.Controller.MediaEncoding else if (string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) { // hevc_qsv use -level 51 instead of -level 153. - if (double.TryParse(level, NumberStyles.Any, _usCulture, out double hevcLevel)) + if (double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out double hevcLevel)) { param += " -level " + (hevcLevel / 3); } @@ -1555,7 +1553,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a specific level was requested, the source must match or be less than var level = state.GetRequestedLevel(videoStream.Codec); if (!string.IsNullOrEmpty(level) - && double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel)) + && double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out var requestLevel)) { if (!videoStream.Level.HasValue) { @@ -1803,7 +1801,7 @@ namespace MediaBrowser.Controller.MediaEncoding && state.AudioStream.Channels.Value > 5 && !encodingOptions.DownMixAudioBoost.Equals(1)) { - filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture)); + filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(CultureInfo.InvariantCulture)); } var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive; @@ -2434,8 +2432,8 @@ namespace MediaBrowser.Controller.MediaEncoding { if (isExynosV4L2) { - var widthParam = requestedWidth.Value.ToString(_usCulture); - var heightParam = requestedHeight.Value.ToString(_usCulture); + var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); + var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); filters.Add( string.Format( @@ -2453,8 +2451,8 @@ namespace MediaBrowser.Controller.MediaEncoding // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size else if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue) { - var maxWidthParam = requestedMaxWidth.Value.ToString(_usCulture); - var maxHeightParam = requestedMaxHeight.Value.ToString(_usCulture); + var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); + var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2486,7 +2484,7 @@ namespace MediaBrowser.Controller.MediaEncoding } else { - var widthParam = requestedWidth.Value.ToString(_usCulture); + var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); filters.Add( string.Format( @@ -2499,7 +2497,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a fixed height was requested else if (requestedHeight.HasValue) { - var heightParam = requestedHeight.Value.ToString(_usCulture); + var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2522,7 +2520,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a max width was requested else if (requestedMaxWidth.HasValue) { - var maxWidthParam = requestedMaxWidth.Value.ToString(_usCulture); + var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2545,7 +2543,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a max height was requested else if (requestedMaxHeight.HasValue) { - var maxHeightParam = requestedMaxHeight.Value.ToString(_usCulture); + var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -4122,12 +4120,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (bitrate.HasValue) { - args += " -ab " + bitrate.Value.ToString(_usCulture); + args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture); } if (state.OutputAudioSampleRate.HasValue) { - args += " -ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture); + args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture); } args += GetAudioFilterParam(state, encodingOptions); @@ -4143,12 +4141,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (bitrate.HasValue) { - audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture)); } if (state.OutputAudioChannels.HasValue) { - audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture)); } // opus will fail on 44100 @@ -4156,7 +4154,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (state.OutputAudioSampleRate.HasValue) { - audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } } diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index c4ddc5618..933f440ac 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -13,7 +13,6 @@ namespace MediaBrowser.Controller.MediaEncoding { public class JobLogger { - private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US")); private readonly ILogger _logger; public JobLogger(ILogger logger) @@ -87,7 +86,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var rate = parts[i + 1]; - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { framerate = val; } @@ -96,7 +95,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var rate = part.Split('=', 2)[^1]; - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { framerate = val; } @@ -106,7 +105,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var time = part.Split('=', 2)[^1]; - if (TimeSpan.TryParse(time, _usCulture, out var val)) + if (TimeSpan.TryParse(time, CultureInfo.InvariantCulture, out var val)) { var currentMs = startMs + val.TotalMilliseconds; @@ -128,7 +127,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (scale.HasValue) { - if (long.TryParse(size, NumberStyles.Any, _usCulture, out var val)) + if (long.TryParse(size, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { bytesTranscoded = val * scale.Value; } @@ -147,7 +146,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (scale.HasValue) { - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { bitRate = (int)Math.Ceiling(val * scale.Value); } diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index b7398880e..988581df9 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -60,8 +60,6 @@ namespace MediaBrowser.LocalMetadata.Images private readonly IFileSystem _fileSystem; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// <summary> /// Initializes a new instance of the <see cref="LocalImageProvider"/> class. /// </summary> @@ -434,7 +432,7 @@ namespace MediaBrowser.LocalMetadata.Images var seasonMarker = seasonNumber.Value == 0 ? "-specials" - : seasonNumber.Value.ToString("00", _usCulture); + : seasonNumber.Value.ToString("00", CultureInfo.InvariantCulture); // Get this one directly from the file system since we have to go up a level if (!string.Equals(prefix, seasonMarker, StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 7c9e681d6..5a36c1663 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -21,8 +21,6 @@ namespace MediaBrowser.LocalMetadata.Parsers public class BaseItemXmlParser<T> where T : BaseItem { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private Dictionary<string, string>? _validProviderIds; /// <summary> @@ -180,7 +178,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrEmpty(text)) { - if (float.TryParse(text, NumberStyles.Any, _usCulture, out var value)) + if (float.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { item.CriticRating = value; } @@ -332,7 +330,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, _usCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } @@ -1095,7 +1093,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (int.TryParse(val, NumberStyles.Integer, _usCulture, out var intVal)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) { sortOrder = intVal; } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 6a3896eb6..6f66fd61b 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -25,8 +25,6 @@ namespace MediaBrowser.LocalMetadata.Savers /// </summary> public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; - private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// <summary> /// Initializes a new instance of the <see cref="BaseXmlSaver"/> class. /// </summary> @@ -205,7 +203,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (item.CriticRating.HasValue) { - writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(_usCulture)); + writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)); } if (!string.IsNullOrEmpty(item.Overview)) @@ -289,12 +287,12 @@ namespace MediaBrowser.LocalMetadata.Savers if (item.CommunityRating.HasValue) { - writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(_usCulture)); + writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)); } if (item.ProductionYear.HasValue && item is not Person) { - writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture)); + writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)); } if (item is IHasAspectRatio hasAspectRatio) @@ -322,7 +320,7 @@ namespace MediaBrowser.LocalMetadata.Savers { var timespan = TimeSpan.FromTicks(runTimeTicks.Value); - writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(_usCulture)); + writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(CultureInfo.InvariantCulture)); } if (item.ProviderIds != null) @@ -395,7 +393,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (person.SortOrder.HasValue) { - writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(_usCulture)); + writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(CultureInfo.InvariantCulture)); } writer.WriteEndElement(); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4cbd1bbc8..06fe95ce8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -43,11 +43,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// </summary> internal const int DefaultHdrImageExtractionTimeout = 20000; - /// <summary> - /// The us culture. - /// </summary> - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly ILogger<MediaEncoder> _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; @@ -687,7 +682,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetTimeParameter(TimeSpan time) { - return time.ToString(@"hh\:mm\:ss\.fff", _usCulture); + return time.ToString(@"hh\:mm\:ss\.fff", CultureInfo.InvariantCulture); } public async Task ExtractVideoImagesOnInterval( @@ -704,11 +699,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { var inputArgument = GetInputArgument(inputFile, mediaSource); - var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); + var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(CultureInfo.InvariantCulture); if (maxWidth.HasValue) { - var maxWidthParam = maxWidth.Value.ToString(_usCulture); + var maxWidthParam = maxWidth.Value.ToString(CultureInfo.InvariantCulture); vf += string.Format(CultureInfo.InvariantCulture, ",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 26f629a31..9ed6c264e 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.MediaEncoding.Probing private static readonly Regex _performerPattern = new (@"(?<name>.*) \((?<instrument>.*)\)"); - private readonly CultureInfo _usCulture = new ("en-US"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; @@ -83,7 +82,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(data.Format.BitRate)) { - if (int.TryParse(data.Format.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(data.Format.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { info.Bitrate = value; } @@ -191,7 +190,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) { - info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.Format.Duration, _usCulture)).Ticks; + info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.Format.Duration, CultureInfo.InvariantCulture)).Ticks; } FetchWtvInfo(info, data); @@ -673,7 +672,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(streamInfo.SampleRate)) { - if (int.TryParse(streamInfo.SampleRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.SampleRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { stream.SampleRate = value; } @@ -802,7 +801,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(streamInfo.BitRate)) { - if (int.TryParse(streamInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { bitrate = value; } @@ -815,7 +814,7 @@ namespace MediaBrowser.MediaEncoding.Probing && (stream.Type == MediaStreamType.Video || (isAudio && stream.Type == MediaStreamType.Audio))) { // If the stream info doesn't have a bitrate get the value from the media format info - if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { bitrate = value; } @@ -921,8 +920,8 @@ namespace MediaBrowser.MediaEncoding.Probing var parts = (original ?? string.Empty).Split(':'); if (!(parts.Length == 2 && - int.TryParse(parts[0], NumberStyles.Any, _usCulture, out var width) && - int.TryParse(parts[1], NumberStyles.Any, _usCulture, out var height) && + int.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var width) && + int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var height) && width > 0 && height > 0)) { @@ -1008,11 +1007,11 @@ namespace MediaBrowser.MediaEncoding.Probing if (parts.Length == 2) { - result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); + result = float.Parse(parts[0], CultureInfo.InvariantCulture) / float.Parse(parts[1], CultureInfo.InvariantCulture); } else { - result = float.Parse(parts[0], _usCulture); + result = float.Parse(parts[0], CultureInfo.InvariantCulture); } return float.IsNaN(result) ? null : result; @@ -1039,7 +1038,7 @@ namespace MediaBrowser.MediaEncoding.Probing // If we got something, parse it if (!string.IsNullOrEmpty(duration)) { - data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; + data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, CultureInfo.InvariantCulture)).Ticks; } } @@ -1101,7 +1100,7 @@ namespace MediaBrowser.MediaEncoding.Probing return; } - info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, _usCulture); + info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, CultureInfo.InvariantCulture); } private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary<string, string> tags) @@ -1144,7 +1143,7 @@ namespace MediaBrowser.MediaEncoding.Probing { Name = match.Groups["name"].Value, Type = PersonType.Actor, - Role = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(match.Groups["instrument"].Value) + Role = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(match.Groups["instrument"].Value) }); } } @@ -1443,7 +1442,7 @@ namespace MediaBrowser.MediaEncoding.Probing .ToArray(); } - if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, _usCulture, out var parsedYear)) + if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) { video.ProductionYear = parsedYear; } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index b213e7aa0..406d32cde 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -56,10 +56,10 @@ namespace MediaBrowser.Model.Globalization IEnumerable<LocalizationOption> GetLocalizationOptions(); /// <summary> - /// Returns the correct <see cref="CultureInfo" /> for the given language. + /// Returns the correct <see cref="CultureDto" /> for the given language. /// </summary> /// <param name="language">The language.</param> - /// <returns>The correct <see cref="CultureInfo" /> for the given language.</returns> + /// <returns>The correct <see cref="CultureDto" /> for the given language.</returns> CultureDto? FindLanguageInfo(string language); } } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 7d259a9d3..4b05edd67 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -29,8 +29,6 @@ namespace MediaBrowser.Providers.Manager /// </summary> public class ImageSaver { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// <summary> /// The _config. /// </summary> @@ -377,7 +375,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-landscape" + extension; @@ -400,7 +398,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-banner" + extension; @@ -495,12 +493,12 @@ namespace MediaBrowser.Providers.Manager var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList(); var current = 1; - while (filenames.Contains(numberedIndexPrefix + current.ToString(UsCulture), StringComparer.OrdinalIgnoreCase)) + while (filenames.Contains(numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase)) { current++; } - return numberedIndexPrefix + current.ToString(UsCulture); + return numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture); } /// <summary> @@ -539,7 +537,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-fanart" + extension; @@ -556,7 +554,7 @@ namespace MediaBrowser.Providers.Manager if (item.IsInMixedFolder) { - return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + outputIndex.ToString(UsCulture), extension) }; + return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + outputIndex.ToString(CultureInfo.InvariantCulture), extension) }; } var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", outputIndex); @@ -568,7 +566,7 @@ namespace MediaBrowser.Providers.Manager if (EnableExtraThumbsDuplication) { - list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)); + list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(CultureInfo.InvariantCulture) + extension)); } return list.ToArray(); @@ -582,7 +580,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-poster" + extension; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 479ae0f39..b2bc58eea 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -26,7 +26,6 @@ namespace MediaBrowser.Providers.Plugins.Omdb private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; private readonly IHttpClientFactory _httpClientFactory; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IApplicationHost _appHost; private readonly JsonSerializerOptions _jsonOptions; @@ -79,7 +78,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year) && year >= 0) { item.ProductionYear = year; @@ -93,14 +92,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.imdbVotes) - && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) + && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount) && voteCount >= 0) { // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) - && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating) + && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating) && imdbRating >= 0) { item.CommunityRating = imdbRating; @@ -191,7 +190,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year) && year >= 0) { item.ProductionYear = year; @@ -205,14 +204,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.imdbVotes) - && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) + && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount) && voteCount >= 0) { // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) - && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating) + && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating) && imdbRating >= 0) { item.CommunityRating = imdbRating; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index f7f4ea065..9d558b6ce 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -58,8 +58,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers _directoryService = directoryService; } - protected CultureInfo UsCulture { get; } = new CultureInfo("en-US"); - /// <summary> /// Gets the logger. /// </summary> @@ -309,7 +307,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrEmpty(text)) { - if (float.TryParse(text, NumberStyles.Any, UsCulture, out var value)) + if (float.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { item.CriticRating = value; } @@ -370,7 +368,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val) && userData != null) { - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var count)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var count)) { userData.PlayCount = count; } @@ -475,7 +473,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, UsCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } @@ -1265,7 +1263,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var intVal)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) { sortOrder = intVal; } diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index 3a305024e..d2f349ad7 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; } @@ -179,7 +179,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsAfterSeasonNumber = rval; } @@ -195,7 +195,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; } @@ -211,7 +211,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; } @@ -227,7 +227,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; } diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs index 62f80e81b..2cd3fdf02 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -17,8 +17,6 @@ namespace MediaBrowser.XbmcMetadata.Savers /// </summary> public class EpisodeNfoSaver : BaseNfoSaver { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// <summary> /// Initializes a new instance of the <see cref="EpisodeNfoSaver"/> class. /// </summary> @@ -60,17 +58,17 @@ namespace MediaBrowser.XbmcMetadata.Savers if (episode.IndexNumber.HasValue) { - writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(_usCulture)); + writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.IndexNumberEnd.HasValue) { - writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(_usCulture)); + writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.ParentIndexNumber.HasValue) { - writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(_usCulture)); + writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.PremiereDate.HasValue) @@ -84,28 +82,28 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (episode.AirsAfterSeasonNumber.HasValue && episode.AirsAfterSeasonNumber.Value != -1) { - writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeEpisodeNumber.HasValue && episode.AirsBeforeEpisodeNumber.Value != -1) { - writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeSeasonNumber.HasValue && episode.AirsBeforeSeasonNumber.Value != -1) { - writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeEpisodeNumber.HasValue && episode.AirsBeforeEpisodeNumber.Value != -1) { - writer.WriteElementString("displayepisode", episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)); + writer.WriteElementString("displayepisode", episode.AirsBeforeEpisodeNumber.Value.ToString(CultureInfo.InvariantCulture)); } var specialSeason = episode.AiredSeasonNumber; if (specialSeason.HasValue && specialSeason.Value != -1) { - writer.WriteElementString("displayseason", specialSeason.Value.ToString(_usCulture)); + writer.WriteElementString("displayseason", specialSeason.Value.ToString(CultureInfo.InvariantCulture)); } } } -- cgit v1.2.3 From ce0457faf5dd0ecc7413fbb3618b52e1f0636446 Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Thu, 30 Sep 2021 22:24:46 +0200 Subject: Add mp4 track title fallback (#6638) --- .../Probing/ProbeResultNormalizer.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 9ed6c264e..df9753b38 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -688,6 +688,16 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.BitDepth = streamInfo.BitsPerRawSample; } + + if (string.IsNullOrEmpty(stream.Title)) + { + // mp4 missing track title workaround: fall back to handler_name if populated + string handlerName = GetDictionaryValue(streamInfo.Tags, "handler_name"); + if (!string.IsNullOrEmpty(handlerName)) + { + stream.Title = handlerName; + } + } } else if (string.Equals(streamInfo.CodecType, "subtitle", StringComparison.OrdinalIgnoreCase)) { @@ -696,6 +706,16 @@ namespace MediaBrowser.MediaEncoding.Probing stream.LocalizedUndefined = _localization.GetLocalizedString("Undefined"); stream.LocalizedDefault = _localization.GetLocalizedString("Default"); stream.LocalizedForced = _localization.GetLocalizedString("Forced"); + + if (string.IsNullOrEmpty(stream.Title)) + { + // mp4 missing track title workaround: fall back to handler_name if populated and not the default "SubtitleHandler" + string handlerName = GetDictionaryValue(streamInfo.Tags, "handler_name"); + if (!string.IsNullOrEmpty(handlerName) && !string.Equals(handlerName, "SubtitleHandler", StringComparison.OrdinalIgnoreCase)) + { + stream.Title = handlerName; + } + } } else if (string.Equals(streamInfo.CodecType, "video", StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From e3fccd5ae67b44be1fa44e82fb0954f29cc825ef Mon Sep 17 00:00:00 2001 From: KonH <konh@yandex.ru> Date: Sun, 3 Oct 2021 11:00:45 +0700 Subject: Fix warning: Qualifier is redundant (#2149) --- Jellyfin.Api/Helpers/AudioHelper.cs | 2 +- Jellyfin.Server/Program.cs | 6 +++--- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/BaseItemExtensions.cs | 2 +- MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs | 2 +- RSSDP/SsdpCommunicationsServer.cs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index a5e47b8ec..bec961dad 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -147,7 +147,7 @@ namespace Jellyfin.Api.Helpers } var outputPath = state.OutputFilePath; - var outputPathExists = System.IO.File.Exists(outputPath); + var outputPathExists = File.Exists(outputPath); var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); var isTranscodeCached = outputPathExists && transcodingJob != null; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index f36675b95..45699f3af 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -594,7 +594,7 @@ namespace Jellyfin.Server try { // Serilog.Log is used by SerilogLoggerFactory when no logger is specified - Serilog.Log.Logger = new LoggerConfiguration() + Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .Enrich.FromLogContext() .Enrich.WithThreadId() @@ -602,7 +602,7 @@ namespace Jellyfin.Server } catch (Exception ex) { - Serilog.Log.Logger = new LoggerConfiguration() + Log.Logger = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}") .WriteTo.Async(x => x.File( Path.Combine(appPaths.LogDirectoryPath, "log_.log"), @@ -613,7 +613,7 @@ namespace Jellyfin.Server .Enrich.WithThreadId() .CreateLogger(); - Serilog.Log.Logger.Fatal(ex, "Failed to create/read logger configuration"); + Log.Logger.Fatal(ex, "Failed to create/read logger configuration"); } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1237268d7..838a9f2f8 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2997,7 +2997,7 @@ namespace MediaBrowser.Controller.Entities } /// <inheritdoc /> - public bool Equals(BaseItem other) => object.Equals(Id, other?.Id); + public bool Equals(BaseItem other) => Equals(Id, other?.Id); /// <inheritdoc /> public override int GetHashCode() => HashCode.Combine(Id); diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs index e88121212..33870e2fb 100644 --- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs +++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="file">The file.</param> public static void SetImagePath(this BaseItem item, ImageType imageType, string file) { - if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase)) + if (file.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { item.SetImage( new ItemImageInfo diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index e86e518be..409379c35 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.MediaEncoding.BdInfo x => new BdInfoFileInfo(x)); } - public static IDirectoryInfo FromFileSystemPath(Model.IO.IFileSystem fs, string path) + public static IDirectoryInfo FromFileSystemPath(IFileSystem fs, string path) { return new BdInfoDirectoryInfo(fs, path); } diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs index e0116c068..58dabc628 100644 --- a/RSSDP/SsdpCommunicationsServer.cs +++ b/RSSDP/SsdpCommunicationsServer.cs @@ -395,7 +395,7 @@ namespace Rssdp.Infrastructure // Strange cannot convert compiler error here if I don't explicitly // assign or cast to Action first. Assignment is easier to read, // so went with that. - ProcessMessage(System.Text.UTF8Encoding.UTF8.GetString(result.Buffer, 0, result.ReceivedBytes), result.RemoteEndPoint, result.LocalIPAddress); + ProcessMessage(UTF8Encoding.UTF8.GetString(result.Buffer, 0, result.ReceivedBytes), result.RemoteEndPoint, result.LocalIPAddress); } } catch (ObjectDisposedException) -- cgit v1.2.3 From 9af16fcb6c892238b734c267873b1fc137d38e66 Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Sun, 3 Oct 2021 19:52:38 +0200 Subject: Remove workaround for dotnet/runtime#42790 --- Emby.Dlna/DlnaManager.cs | 9 ++++--- Emby.Drawing/ImageProcessor.cs | 2 +- .../AppBase/ConfigurationHelper.cs | 9 +++---- .../LiveTv/EmbyTV/DirectRecorder.cs | 6 ++--- .../LiveTv/EmbyTV/EmbyTV.cs | 12 +++------ .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 31 ---------------------- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 12 +++++++-- .../Subtitles/SubtitleEncoder.cs | 1 - MediaBrowser.Model/IO/AsyncFile.cs | 19 +++++++++++++ MediaBrowser.Providers/Manager/ImageSaver.cs | 6 +++-- .../Manager/ItemImageProvider.cs | 2 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 3 +-- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 7 +++-- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 6 +++-- .../Studios/StudiosImageProvider.cs | 7 ++--- .../Subtitles/SubtitleManager.cs | 6 +++-- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 11 ++++++-- 18 files changed, 77 insertions(+), 74 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 8fe9d484e..73e8a0008 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -359,14 +359,17 @@ namespace Emby.Dlna // The stream should exist as we just got its name from GetManifestResourceNames using (var stream = _assembly.GetManifestResourceStream(name)!) { + var length = stream.Length; var fileInfo = _fileSystem.GetFileInfo(path); - if (!fileInfo.Exists || fileInfo.Length != stream.Length) + if (!fileInfo.Exists || fileInfo.Length != length) { Directory.CreateDirectory(systemProfilesPath); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + var fileOptions = AsyncFile.WriteOptions; + fileOptions.Mode = FileMode.CreateNew; + fileOptions.PreallocationSize = length; + using (var fileStream = new FileStream(path, fileOptions)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 9b130fdfd..ac73cfa42 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -102,7 +102,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + using (var fileStream = AsyncFile.OpenRead(file.Item1)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 0308a68e4..3a916e5c0 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -41,20 +41,19 @@ namespace Emby.Server.Implementations.AppBase xmlSerializer.SerializeToStream(configuration, stream); // Take the object we just got and serialize it back to bytes - byte[] newBytes = stream.GetBuffer(); - int newBytesLen = (int)stream.Length; + Span<byte> newBytes = stream.GetBuffer().AsSpan(0, (int)stream.Length); // If the file didn't exist before, or if something has changed, re-save - if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer)) + if (buffer == null || !newBytes.SequenceEqual(buffer)) { var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); + // Save it after load in case we got new items - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { - fs.Write(newBytes, 0, newBytesLen); + fs.Write(newBytes); } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 41381d55b..6937cc097 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -46,8 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { onStarted(); @@ -79,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); + await using var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 64e54aa99..980b42729 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1848,14 +1848,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false + Encoding = Encoding.UTF8 }; using (var writer = XmlWriter.Create(stream, settings)) @@ -1913,14 +1911,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false + Encoding = Encoding.UTF8 }; var options = _config.GetNfoConfiguration(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3633fa3e1..016a3e83f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + _logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 8a33b12f4..35921ede8 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -183,36 +183,5 @@ namespace Jellyfin.Api.Controllers { return Path.Combine(_applicationPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); } - - /// <summary> - /// Downloads the image. - /// </summary> - /// <param name="url">The URL.</param> - /// <param name="urlHash">The URL hash.</param> - /// <param name="pointerCachePath">The pointer cache path.</param> - /// <returns>Task.</returns> - private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath) - { - var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); - using var response = await httpClient.GetAsync(url).ConfigureAwait(false); - if (response.Content.Headers.ContentType?.MediaType == null) - { - throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType)); - } - - var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString(); - var fullCachePath = GetFullCachePath(urlHash + "." + ext); - - var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); - Directory.CreateDirectory(fullCacheDirectory); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); - await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); - Directory.CreateDirectory(pointerCacheDirectory); - await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) - .ConfigureAwait(false); - } } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 6f66fd61b..5e7af23fc 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -113,11 +113,19 @@ namespace MediaBrowser.LocalMetadata.Savers { var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); + // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + var fileStreamOptions = new FileStreamOptions() + { + Mode = FileMode.Create, + Access = FileAccess.Write, + Share = FileShare.None, + PreallocationSize = stream.Length + }; + + using (var filestream = new FileStream(path, fileStreamOptions)) { stream.CopyTo(filestream); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 022cdbe9d..bfc17904c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -679,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var writer = new StreamWriter(fileStream, encoding)) { diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs index caee9c528..3c8007d1c 100644 --- a/MediaBrowser.Model/IO/AsyncFile.cs +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -7,6 +7,25 @@ namespace MediaBrowser.Model.IO /// </summary> public static class AsyncFile { + /// <summary> + /// Gets the default <see cref="FileStreamOptions"/> for reading files async. + /// </summary> + public static FileStreamOptions ReadOptions => new FileStreamOptions() + { + Options = FileOptions.Asynchronous + }; + + /// <summary> + /// Gets the default <see cref="FileStreamOptions"/> for writing files async. + /// </summary> + public static FileStreamOptions WriteOptions => new FileStreamOptions() + { + Mode = FileMode.OpenOrCreate, + Access = FileAccess.Write, + Share = FileShare.None, + Options = FileOptions.Asynchronous + }; + /// <summary> /// Opens an existing file for reading. /// </summary> diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 4b05edd67..3d8dd1486 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -261,8 +261,10 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = source.Length; + await using (var fs = new FileStream(path, fileStreamOptions)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 73bca5aa5..3593697d7 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + var stream = AsyncFile.OpenRead(response.Path); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index b51a25417..9be887e9c 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -210,8 +210,7 @@ namespace MediaBrowser.Providers.Manager throw new ArgumentNullException(nameof(source)); } - var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - + var fileStream = AsyncFile.OpenRead(source); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index 3e0b0014e..ebdcb94eb 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -172,8 +172,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = stream.Length; + await using var xmlFileStream = new FileStream(path, fileStreamOptions); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index e0b2f9c58..321013b17 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -154,8 +154,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = stream.Length; + await using var xmlFileStream = new FileStream(path, fileStreamOptions); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 7b2454efc..a1873eaae 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -172,19 +172,16 @@ namespace MediaBrowser.Providers.Studios public IEnumerable<string> GetAvailableImages(string file) { - using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); + using var fileStream = File.OpenRead(file); using var reader = new StreamReader(fileStream); - var lines = new List<string>(); foreach (var line in reader.ReadAllLines()) { if (!string.IsNullOrWhiteSpace(line)) { - lines.Add(line); + yield return line; } } - - return lines; } } } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 772e617ab..e625b0dd2 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -244,8 +244,10 @@ namespace MediaBrowser.Providers.Subtitles { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous); + var fileOptions = AsyncFile.WriteOptions; + fileOptions.Mode = FileMode.CreateNew; + fileOptions.PreallocationSize = stream.Length; + using var fs = new FileStream(savePath, fileOptions); await stream.CopyToAsync(fs).ConfigureAwait(false); return; diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 38726a6f0..594402258 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -203,8 +203,15 @@ namespace MediaBrowser.XbmcMetadata.Savers // On Windows, saving the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + var fileStreamOptions = new FileStreamOptions() + { + Mode = FileMode.Create, + Access = FileAccess.Write, + Share = FileShare.None, + PreallocationSize = stream.Length + }; + + using (var filestream = new FileStream(path, fileStreamOptions)) { stream.CopyTo(filestream); } -- cgit v1.2.3 From 017380f1ddccb46ce270f1d0df8e07d639ba3704 Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Mon, 4 Oct 2021 07:43:40 -0600 Subject: Reference dotnet6-rc1 packages --- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- .../Security/AuthorizationContext.cs | 2 +- Jellyfin.Server.Implementations/Users/UserManager.cs | 5 +++++ Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 6 +++--- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 6 +++--- 16 files changed, 43 insertions(+), 38 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 1d4e3b047..5348aed63 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -73,7 +73,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> </ItemGroup> </Project> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 428cad071..fb1972610 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ <ItemGroup> <PackageReference Include="DiscUtils.Udf" Version="0.16.13" /> <PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" /> - <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.10" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.1.21452.10" /> <PackageReference Include="Mono.Nat" Version="3.0.1" /> <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.1" /> <PackageReference Include="sharpcompress" Version="0.30.0" /> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 1c451ef6c..f46c0cbd1 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,8 +14,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.10" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.2" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.2.2" /> </ItemGroup> diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 19aef704c..f1bfaa63e 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0-rc.1.21451.13" /> </ItemGroup> <ItemGroup> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 337f5cb82..d9e6d794b 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ <ItemGroup> <PackageReference Include="System.Linq.Async" Version="5.0.0" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.10" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.10" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.10"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0-rc.1.21452.10" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.1.21452.10" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0-rc.1.21452.10"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.10"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0-rc.1.21452.10"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index ba2cfc724..3ab043c64 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -2,12 +2,12 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; namespace Jellyfin.Server.Implementations.Security diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 02377bfd7..704a6a84e 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -701,6 +701,11 @@ namespace Jellyfin.Server.Implementations.Users /// <inheritdoc/> public async Task ClearProfileImageAsync(User user) { + if (user.ProfileImage == null) + { + return; + } + await using var dbContext = _dbProvider.CreateContext(); dbContext.Remove(user.ProfileImage); await dbContext.SaveChangesAsync().ConfigureAwait(false); diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 074d43fba..6603105fa 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ <ItemGroup> <PackageReference Include="CommandLineParser" Version="2.8.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="5.0.10" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="5.0.10" /> + <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.0-rc.1.21452.15" /> <PackageReference Include="prometheus-net" Version="5.0.1" /> <PackageReference Include="prometheus-net.AspNetCore" Version="5.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="4.1.0" /> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 6358c0000..c87d58a14 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 47cec7d77..997772c04 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ <ItemGroup> <PackageReference Include="Diacritics" Version="2.1.20036.1" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="System.Threading.Tasks.Dataflow" Version="5.0.0" /> + <PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0-rc.1.21451.13" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 30cfb904e..22bba2366 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> <PackageReference Include="libse" Version="3.6.2" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> - <PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="UTF.Unknown" Version="2.4.0" /> </ItemGroup> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b0a12a9c9..0ac58e355 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -35,9 +35,9 @@ <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="System.Globalization" Version="4.3.0" /> - <PackageReference Include="System.Text.Json" Version="5.0.2" /> + <PackageReference Include="System.Text.Json" Version="6.0.0-rc.1.21451.13" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 29d6b01f2..71a3554fd 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" /> <PackageReference Include="PlaylistsNET" Version="1.1.3" /> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index b52ea078a..8b581857f 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 7939c7118..38687ae61 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,14 +9,14 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> <PackageReference Include="Xunit.Priority" Version="1.1.6" /> <PackageReference Include="coverlet.collector" Version="3.1.0" /> - <PackageReference Include="Moq" Version="4.16.0" /> + <PackageReference Include="Moq" Version="4.16.1" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index b30e690a5..db24df240 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,13 +10,13 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> <PackageReference Include="coverlet.collector" Version="3.1.0" /> - <PackageReference Include="Moq" Version="4.16.0" /> + <PackageReference Include="Moq" Version="4.16.1" /> </ItemGroup> <!-- Code Analyzers --> -- cgit v1.2.3 From ef99225c40692b000ca67a1ec9f31cc04fac4743 Mon Sep 17 00:00:00 2001 From: Dominik Krivohlavek <lyarenei@gmail.com> Date: Wed, 6 Oct 2021 10:32:28 +0200 Subject: Add 22/7 to split whitelist --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index df9753b38..fee3bf12e 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -49,7 +49,8 @@ namespace MediaBrowser.MediaEncoding.Probing "LOONA 1/3", "LOONA / yyxy", "LOONA / ODD EYE CIRCLE", - "K/DA" + "K/DA", + "22/7" }; public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType? videoType, bool isAudio, string path, MediaProtocol protocol) -- cgit v1.2.3 From c26e6d89b43cfd81c5735ae1a2ecd47cc43fda90 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo <ashephard0@gmail.com> Date: Sun, 10 Oct 2021 19:48:11 +0300 Subject: Move FfmpegException to MediaBrowser.Common --- MediaBrowser.Common/FfmpegException.cs | 39 ++++++++++++++++++++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + MediaBrowser.MediaEncoding/FfmpegException.cs | 39 ---------------------- .../Subtitles/SubtitleEncoder.cs | 1 + 4 files changed, 41 insertions(+), 39 deletions(-) create mode 100644 MediaBrowser.Common/FfmpegException.cs delete mode 100644 MediaBrowser.MediaEncoding/FfmpegException.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Common/FfmpegException.cs b/MediaBrowser.Common/FfmpegException.cs new file mode 100644 index 000000000..be420196d --- /dev/null +++ b/MediaBrowser.Common/FfmpegException.cs @@ -0,0 +1,39 @@ +using System; + +namespace MediaBrowser.Common +{ + /// <summary> + /// Represents errors that occur during interaction with FFmpeg. + /// </summary> + public class FfmpegException : Exception + { + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class. + /// </summary> + public FfmpegException() + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message. + /// </summary> + /// <param name="message">The message that describes the error.</param> + public FfmpegException(string message) : base(message) + { + } + + /// <summary> + /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message and a + /// reference to the inner exception that is the cause of this exception. + /// </summary> + /// <param name="message">The error message that explains the reason for the exception.</param> + /// <param name="innerException"> + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if + /// no inner exception is specified. + /// </param> + public FfmpegException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 06fe95ce8..3dbbeda8a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -12,6 +12,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Jellyfin.Extensions.Json; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; diff --git a/MediaBrowser.MediaEncoding/FfmpegException.cs b/MediaBrowser.MediaEncoding/FfmpegException.cs deleted file mode 100644 index 1697fd33a..000000000 --- a/MediaBrowser.MediaEncoding/FfmpegException.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; - -namespace MediaBrowser.MediaEncoding -{ - /// <summary> - /// Represents errors that occur during interaction with FFmpeg. - /// </summary> - public class FfmpegException : Exception - { - /// <summary> - /// Initializes a new instance of the <see cref="FfmpegException"/> class. - /// </summary> - public FfmpegException() - { - } - - /// <summary> - /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message. - /// </summary> - /// <param name="message">The message that describes the error.</param> - public FfmpegException(string message) : base(message) - { - } - - /// <summary> - /// Initializes a new instance of the <see cref="FfmpegException"/> class with a specified error message and a - /// reference to the inner exception that is the cause of this exception. - /// </summary> - /// <param name="message">The error message that explains the reason for the exception.</param> - /// <param name="innerException"> - /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if - /// no inner exception is specified. - /// </param> - public FfmpegException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index bfc17904c..2b2de2ff6 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -11,6 +11,7 @@ using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; -- cgit v1.2.3 From 6ce8cce12c8d24cc0a49aac7a0d371e5ebf1b3a3 Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Wed, 6 Oct 2021 01:13:08 +0200 Subject: Add handling for embedded background and logo --- .../Probing/ProbeResultNormalizer.cs | 15 +++- .../MediaInfo/EmbeddedImageProvider.cs | 91 +++++++++++++++++++--- 2 files changed, 90 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index fee3bf12e..5f6539495 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -735,14 +735,15 @@ namespace MediaBrowser.MediaEncoding.Probing else if (string.Equals(stream.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase)) { // How to differentiate between video and embedded image? - // The only difference I've seen thus far is presence of codec tag, also embedded images have high (unusual) framerates - if (!string.IsNullOrWhiteSpace(stream.CodecTag)) + // check disposition, alternately: presence of codec tag, also embedded images have high (unusual) framerates + if ((streamInfo.Disposition != null && streamInfo.Disposition.GetValueOrDefault("attached_pic") == 1) || + string.IsNullOrWhiteSpace(stream.CodecTag)) { - stream.Type = MediaStreamType.Video; + stream.Type = MediaStreamType.EmbeddedImage; } else { - stream.Type = MediaStreamType.EmbeddedImage; + stream.Type = MediaStreamType.Video; } } else @@ -811,6 +812,12 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.ColorPrimaries = streamInfo.ColorPrimaries; } + + // workaround for mkv attached_pics losing filename due to being classified as video based on codec + if (stream.Type == MediaStreamType.EmbeddedImage && streamInfo.Tags != null && string.IsNullOrEmpty(stream.Comment)) + { + stream.Comment = GetDictionaryValue(streamInfo.Tags, "filename"); + } } else { diff --git a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs index 64a47611d..11fdfcdf9 100644 --- a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; @@ -22,6 +24,27 @@ namespace MediaBrowser.Providers.MediaInfo /// </summary> public class EmbeddedImageProvider : IDynamicImageProvider, IHasOrder { + private static readonly string[] _primaryImageFileNames = + { + "poster", + "folder", + "cover", + "default" + }; + + private static readonly string[] _backdropImageFileNames = + { + "backdrop", + "fanart", + "background", + "art" + }; + + private static readonly string[] _logoImageFileNames = + { + "logo", + }; + private readonly IMediaEncoder _mediaEncoder; private readonly ILogger<EmbeddedImageProvider> _logger; @@ -41,7 +64,25 @@ namespace MediaBrowser.Providers.MediaInfo /// <inheritdoc /> public IEnumerable<ImageType> GetSupportedImages(BaseItem item) { - return new[] { ImageType.Primary }; + if (item is Video) + { + if (item is Episode) + { + return new List<ImageType> + { + ImageType.Primary, + }; + } + + return new List<ImageType> + { + ImageType.Primary, + ImageType.Backdrop, + ImageType.Logo, + }; + } + + return ImmutableList<ImageType>.Empty; } /// <inheritdoc /> @@ -62,10 +103,10 @@ namespace MediaBrowser.Providers.MediaInfo return Task.FromResult(new DynamicImageResponse { HasImage = false }); } - return GetEmbeddedImage(video, cancellationToken); + return GetEmbeddedImage(video, type, cancellationToken); } - private async Task<DynamicImageResponse> GetEmbeddedImage(Video item, CancellationToken cancellationToken) + private async Task<DynamicImageResponse> GetEmbeddedImage(Video item, ImageType type, CancellationToken cancellationToken) { MediaSourceInfo mediaSource = new MediaSourceInfo { @@ -74,27 +115,53 @@ namespace MediaBrowser.Providers.MediaInfo Protocol = item.PathProtocol ?? MediaProtocol.File, }; + string[] imageFileNames; + switch (type) + { + case ImageType.Backdrop: + imageFileNames = _backdropImageFileNames; + break; + case ImageType.Logo: + imageFileNames = _logoImageFileNames; + break; + case ImageType.Primary: + default: + imageFileNames = _primaryImageFileNames; + break; + } + var imageStreams = item.GetMediaStreams() .Where(i => i.Type == MediaStreamType.EmbeddedImage) .ToList(); - string extractedImagePath; - - if (imageStreams.Count == 0) + if (!imageStreams.Any()) { // Can't extract if we don't have any EmbeddedImage streams return new DynamicImageResponse { HasImage = false }; } - else - { - var imageStream = imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("front", StringComparison.OrdinalIgnoreCase)) - ?? imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.OrdinalIgnoreCase)) - ?? imageStreams[0]; - extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false); + // Extract first stream containing an element of imageFileNames + var imageStream = imageStreams + .Where(stream => !string.IsNullOrEmpty(stream.Comment)) + .First(stream => imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase))); + + // Primary type only: default to first image if none found by label + if (imageStream == null) + { + if (type == ImageType.Primary) + { + imageStream = imageStreams[0]; + } + else + { + // No streams matched, abort + return new DynamicImageResponse { HasImage = false }; + } } + string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false); + return new DynamicImageResponse { Format = ImageFormat.Jpg, -- cgit v1.2.3 From 8d70cc2dde81aad0f484a2f0d0c5b90e6e1b97cd Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Thu, 7 Oct 2021 22:37:59 +0200 Subject: Add support for non-jpg image extractions --- .../MediaEncoding/IMediaEncoder.cs | 3 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 21 ++++---- .../Probing/ProbeResultNormalizer.cs | 18 +++---- .../MediaInfo/EmbeddedImageProvider.cs | 60 ++++++++++++++++------ 4 files changed, 62 insertions(+), 40 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index c5522bc3c..638588560 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -95,9 +95,10 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="mediaSource">Media source information.</param> /// <param name="imageStream">Media stream information.</param> /// <param name="imageStreamIndex">Index of the stream to extract from.</param> + /// <param name="outputExtension">The extension of the file to write.</param> /// <param name="cancellationToken">CancellationToken to use for operation.</param> /// <returns>Location of video image.</returns> - Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, string outputExtension, CancellationToken cancellationToken); /// <summary> /// Extracts the video images on interval. diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 06fe95ce8..30bc7125d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -468,17 +468,17 @@ namespace MediaBrowser.MediaEncoding.Encoder Protocol = MediaProtocol.File }; - return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, cancellationToken); + return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, "jpg", cancellationToken); } public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { - return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, cancellationToken); + return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, "jpg", cancellationToken); } - public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken) + public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, string outputExtension, CancellationToken cancellationToken) { - return ExtractImage(inputFile, container, imageStream, imageStreamIndex, mediaSource, false, null, null, cancellationToken); + return ExtractImage(inputFile, container, imageStream, imageStreamIndex, mediaSource, false, null, null, outputExtension, cancellationToken); } private async Task<string> ExtractImage( @@ -490,6 +490,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, + string outputExtension, CancellationToken cancellationToken) { var inputArgument = GetInputArgument(inputFile, mediaSource); @@ -499,7 +500,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // The failure of HDR extraction usually occurs when using custom ffmpeg that does not contain the zscale filter. try { - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, true, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, true, outputExtension, cancellationToken).ConfigureAwait(false); } catch (ArgumentException) { @@ -512,7 +513,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, true, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, true, outputExtension, cancellationToken).ConfigureAwait(false); } catch (ArgumentException) { @@ -525,7 +526,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, false, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, true, false, outputExtension, cancellationToken).ConfigureAwait(false); } catch (ArgumentException) { @@ -537,17 +538,17 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, false, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, container, videoStream, imageStreamIndex, threedFormat, offset, false, false, outputExtension, cancellationToken).ConfigureAwait(false); } - private async Task<string> ExtractImageInternal(string inputPath, string container, MediaStream videoStream, int? imageStreamIndex, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, bool allowTonemap, CancellationToken cancellationToken) + private async Task<string> ExtractImageInternal(string inputPath, string container, MediaStream videoStream, int? imageStreamIndex, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, bool allowTonemap, string outputExtension, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { throw new ArgumentNullException(nameof(inputPath)); } - var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); + var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + "." + outputExtension); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 5f6539495..775689095 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -582,7 +582,8 @@ namespace MediaBrowser.MediaEncoding.Probing /// <returns>MediaAttachments.</returns> private MediaAttachment GetMediaAttachment(MediaStreamInfo streamInfo) { - if (!string.Equals(streamInfo.CodecType, "attachment", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(streamInfo.CodecType, "attachment", StringComparison.OrdinalIgnoreCase) && + !(streamInfo.Disposition != null && streamInfo.Disposition.GetValueOrDefault("attached_pic") == 1)) { return null; } @@ -735,15 +736,14 @@ namespace MediaBrowser.MediaEncoding.Probing else if (string.Equals(stream.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase)) { // How to differentiate between video and embedded image? - // check disposition, alternately: presence of codec tag, also embedded images have high (unusual) framerates - if ((streamInfo.Disposition != null && streamInfo.Disposition.GetValueOrDefault("attached_pic") == 1) || - string.IsNullOrWhiteSpace(stream.CodecTag)) + // The only difference I've seen thus far is presence of codec tag, also embedded images have high (unusual) framerates + if (!string.IsNullOrWhiteSpace(stream.CodecTag)) { - stream.Type = MediaStreamType.EmbeddedImage; + stream.Type = MediaStreamType.Video; } else { - stream.Type = MediaStreamType.Video; + stream.Type = MediaStreamType.EmbeddedImage; } } else @@ -812,12 +812,6 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.ColorPrimaries = streamInfo.ColorPrimaries; } - - // workaround for mkv attached_pics losing filename due to being classified as video based on codec - if (stream.Type == MediaStreamType.EmbeddedImage && streamInfo.Tags != null && string.IsNullOrEmpty(stream.Comment)) - { - stream.Comment = GetDictionaryValue(streamInfo.Tags, "filename"); - } } else { diff --git a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs index 11fdfcdf9..ad95cdb06 100644 --- a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -15,6 +16,7 @@ using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.MediaInfo @@ -115,25 +117,49 @@ namespace MediaBrowser.Providers.MediaInfo Protocol = item.PathProtocol ?? MediaProtocol.File, }; - string[] imageFileNames; - switch (type) + string[] imageFileNames = type switch { - case ImageType.Backdrop: - imageFileNames = _backdropImageFileNames; - break; - case ImageType.Logo: - imageFileNames = _logoImageFileNames; - break; - case ImageType.Primary: - default: - imageFileNames = _primaryImageFileNames; - break; + ImageType.Primary => _primaryImageFileNames, + ImageType.Backdrop => _backdropImageFileNames, + ImageType.Logo => _logoImageFileNames, + _ => _primaryImageFileNames + }; + + // Try attachments first + var attachmentSources = item.GetMediaSources(false).SelectMany(source => source.MediaAttachments).ToList(); + var attachmentStream = attachmentSources + .Where(stream => !string.IsNullOrEmpty(stream.FileName)) + .First(stream => imageFileNames.Any(name => stream.FileName.Contains(name, StringComparison.OrdinalIgnoreCase))); + + if (attachmentStream != null) + { + var extension = (string.IsNullOrEmpty(attachmentStream.MimeType) ? + Path.GetExtension(attachmentStream.FileName) : + MimeTypes.ToExtension(attachmentStream.MimeType)) ?? "jpg"; + + string extractedAttachmentPath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, null, attachmentStream.Index, extension, cancellationToken).ConfigureAwait(false); + + ImageFormat format = extension switch + { + "bmp" => ImageFormat.Bmp, + "gif" => ImageFormat.Gif, + "jpg" => ImageFormat.Jpg, + "png" => ImageFormat.Png, + "webp" => ImageFormat.Webp, + _ => ImageFormat.Jpg + }; + + return new DynamicImageResponse + { + Format = format, + HasImage = true, + Path = extractedAttachmentPath, + Protocol = MediaProtocol.File + }; } - var imageStreams = - item.GetMediaStreams() - .Where(i => i.Type == MediaStreamType.EmbeddedImage) - .ToList(); + // Fall back to EmbeddedImage streams + var imageStreams = item.GetMediaStreams().FindAll(i => i.Type == MediaStreamType.EmbeddedImage); if (!imageStreams.Any()) { @@ -160,7 +186,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false); + string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, "jpg", cancellationToken).ConfigureAwait(false); return new DynamicImageResponse { -- cgit v1.2.3 From e3eee10d05e9ecc7e3fac1f8fdad92329d38a4db Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Mon, 11 Oct 2021 12:34:18 +0200 Subject: Add image provider tests and clean up --- .../MediaEncoding/IMediaEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +- .../MediaInfo/EmbeddedImageProvider.cs | 41 ++-- .../MediaInfo/VideoImageProvider.cs | 9 +- .../MediaInfo/EmbeddedImageProviderTests.cs | 211 +++++++++++++++++++++ .../MediaInfo/VideoImageProviderTests.cs | 168 ++++++++++++++++ 6 files changed, 408 insertions(+), 29 deletions(-) create mode 100644 tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs create mode 100644 tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 638588560..e6511ca8d 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="mediaSource">Media source information.</param> /// <param name="imageStream">Media stream information.</param> /// <param name="imageStreamIndex">Index of the stream to extract from.</param> - /// <param name="outputExtension">The extension of the file to write.</param> + /// <param name="outputExtension">The extension of the file to write, including the '.'.</param> /// <param name="cancellationToken">CancellationToken to use for operation.</param> /// <returns>Location of video image.</returns> Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, string outputExtension, CancellationToken cancellationToken); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 30bc7125d..dac2c6a26 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -468,12 +468,12 @@ namespace MediaBrowser.MediaEncoding.Encoder Protocol = MediaProtocol.File }; - return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, "jpg", cancellationToken); + return ExtractImage(path, null, null, imageStreamIndex, mediaSource, true, null, null, ".jpg", cancellationToken); } public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { - return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, "jpg", cancellationToken); + return ExtractImage(inputFile, container, videoStream, null, mediaSource, false, threedFormat, offset, ".jpg", cancellationToken); } public Task<string> ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, string outputExtension, CancellationToken cancellationToken) @@ -548,7 +548,7 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ArgumentNullException(nameof(inputPath)); } - var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + "." + outputExtension); + var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + outputExtension); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar. diff --git a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs index ad95cdb06..df87f2d49 100644 --- a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs @@ -1,9 +1,7 @@ -#nullable enable #pragma warning disable CS1591 using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.IO; using System.Linq; using System.Threading; @@ -17,7 +15,6 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; -using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.MediaInfo { @@ -48,12 +45,10 @@ namespace MediaBrowser.Providers.MediaInfo }; private readonly IMediaEncoder _mediaEncoder; - private readonly ILogger<EmbeddedImageProvider> _logger; - public EmbeddedImageProvider(IMediaEncoder mediaEncoder, ILogger<EmbeddedImageProvider> logger) + public EmbeddedImageProvider(IMediaEncoder mediaEncoder) { _mediaEncoder = mediaEncoder; - _logger = logger; } /// <inheritdoc /> @@ -84,7 +79,7 @@ namespace MediaBrowser.Providers.MediaInfo }; } - return ImmutableList<ImageType>.Empty; + return new List<ImageType>(); } /// <inheritdoc /> @@ -98,13 +93,6 @@ namespace MediaBrowser.Providers.MediaInfo return Task.FromResult(new DynamicImageResponse { HasImage = false }); } - // Can't extract if we didn't find any video streams in the file - if (!video.DefaultVideoStreamIndex.HasValue) - { - _logger.LogInformation("Skipping image extraction due to missing DefaultVideoStreamIndex for {Path}.", video.Path ?? string.Empty); - return Task.FromResult(new DynamicImageResponse { HasImage = false }); - } - return GetEmbeddedImage(video, type, cancellationToken); } @@ -128,24 +116,29 @@ namespace MediaBrowser.Providers.MediaInfo // Try attachments first var attachmentSources = item.GetMediaSources(false).SelectMany(source => source.MediaAttachments).ToList(); var attachmentStream = attachmentSources - .Where(stream => !string.IsNullOrEmpty(stream.FileName)) - .First(stream => imageFileNames.Any(name => stream.FileName.Contains(name, StringComparison.OrdinalIgnoreCase))); + .Where(attachment => !string.IsNullOrEmpty(attachment.FileName)) + .FirstOrDefault(attachment => imageFileNames.Any(name => attachment.FileName.Contains(name, StringComparison.OrdinalIgnoreCase))); if (attachmentStream != null) { - var extension = (string.IsNullOrEmpty(attachmentStream.MimeType) ? + var extension = string.IsNullOrEmpty(attachmentStream.MimeType) ? Path.GetExtension(attachmentStream.FileName) : - MimeTypes.ToExtension(attachmentStream.MimeType)) ?? "jpg"; + MimeTypes.ToExtension(attachmentStream.MimeType); + + if (string.IsNullOrEmpty(extension)) + { + extension = ".jpg"; + } string extractedAttachmentPath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, null, attachmentStream.Index, extension, cancellationToken).ConfigureAwait(false); ImageFormat format = extension switch { - "bmp" => ImageFormat.Bmp, - "gif" => ImageFormat.Gif, - "jpg" => ImageFormat.Jpg, - "png" => ImageFormat.Png, - "webp" => ImageFormat.Webp, + ".bmp" => ImageFormat.Bmp, + ".gif" => ImageFormat.Gif, + ".jpg" => ImageFormat.Jpg, + ".png" => ImageFormat.Png, + ".webp" => ImageFormat.Webp, _ => ImageFormat.Jpg }; @@ -170,7 +163,7 @@ namespace MediaBrowser.Providers.MediaInfo // Extract first stream containing an element of imageFileNames var imageStream = imageStreams .Where(stream => !string.IsNullOrEmpty(stream.Comment)) - .First(stream => imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase))); + .FirstOrDefault(stream => imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase))); // Primary type only: default to first image if none found by label if (imageStream == null) diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 8f2009950..60739f156 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -81,7 +81,14 @@ namespace MediaBrowser.Providers.MediaInfo ? TimeSpan.FromTicks(item.RunTimeTicks.Value / 10) : TimeSpan.FromSeconds(10); - var videoStream = item.GetMediaStreams().FirstOrDefault(i => i.Type == MediaStreamType.Video); + var videoStream = item.GetDefaultVideoStream() ?? item.GetMediaStreams().FirstOrDefault(i => i.Type == MediaStreamType.Video); + + if (videoStream == null) + { + _logger.LogInformation("Skipping image extraction: no video stream found for {Path}.", item.Path ?? string.Empty); + return new DynamicImageResponse { HasImage = false }; + } + string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); return new DynamicImageResponse diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs new file mode 100644 index 000000000..fcea1532a --- /dev/null +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs @@ -0,0 +1,211 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Providers.MediaInfo; +using Moq; +using Xunit; + +namespace Jellyfin.Providers.Tests.MediaInfo +{ + public class EmbeddedImageProviderTests + { + public static TheoryData<BaseItem> GetSupportedImages_Empty_TestData => + new () + { + new AudioBook(), + new BoxSet(), + new Series(), + new Season(), + }; + + public static TheoryData<BaseItem, IEnumerable<ImageType>> GetSupportedImages_Populated_TestData => + new TheoryData<BaseItem, IEnumerable<ImageType>> + { + { new Episode(), new List<ImageType> { ImageType.Primary } }, + { new Movie(), new List<ImageType> { ImageType.Logo, ImageType.Backdrop, ImageType.Primary } }, + }; + + private EmbeddedImageProvider GetEmbeddedImageProvider(IMediaEncoder? mediaEncoder) + { + return new EmbeddedImageProvider(mediaEncoder); + } + + [Theory] + [MemberData(nameof(GetSupportedImages_Empty_TestData))] + public void GetSupportedImages_Empty(BaseItem item) + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + Assert.False(embeddedImageProvider.GetSupportedImages(item).Any()); + } + + [Theory] + [MemberData(nameof(GetSupportedImages_Populated_TestData))] + public void GetSupportedImages_Populated(BaseItem item, IEnumerable<ImageType> expected) + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + var actual = embeddedImageProvider.GetSupportedImages(item); + Assert.Equal(expected.OrderBy(i => i.ToString()), actual.OrderBy(i => i.ToString())); + } + + [Fact] + public async void GetImage_Empty_NoStreams() + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo>()); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>()); + + var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Empty_NoLabeledAttachments() + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + + var input = new Mock<Movie>(); + // add an attachment without a filename - has a list to look through but finds nothing + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { new () } } }); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>()); + + var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Empty_NoEmbeddedLabeledBackdrop() + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo>()); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream> { new () { Type = MediaStreamType.EmbeddedImage } }); + + var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Attached() + { + // first tests file extension detection, second uses mimetype, third defaults to jpg + MediaAttachment sampleAttachment1 = new () { FileName = "clearlogo.png", Index = 1 }; + MediaAttachment sampleAttachment2 = new () { FileName = "backdrop", MimeType = "image/bmp", Index = 2 }; + MediaAttachment sampleAttachment3 = new () { FileName = "poster", Index = 3 }; + string targetPath1 = "path1.png"; + string targetPath2 = "path2.bmp"; + string targetPath3 = "path2.jpg"; + + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 1, ".png", CancellationToken.None)) + .Returns(Task.FromResult(targetPath1)); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 2, ".bmp", CancellationToken.None)) + .Returns(Task.FromResult(targetPath2)); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), 3, ".jpg", CancellationToken.None)) + .Returns(Task.FromResult(targetPath3)); + var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { sampleAttachment1, sampleAttachment2, sampleAttachment3 } } }); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>()); + + var actualLogo = await embeddedImageProvider.GetImage(input.Object, ImageType.Logo, CancellationToken.None); + Assert.NotNull(actualLogo); + Assert.True(actualLogo.HasImage); + Assert.Equal(targetPath1, actualLogo.Path); + Assert.Equal(ImageFormat.Png, actualLogo.Format); + + var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); + Assert.NotNull(actualBackdrop); + Assert.True(actualBackdrop.HasImage); + Assert.Equal(targetPath2, actualBackdrop.Path); + Assert.Equal(ImageFormat.Bmp, actualBackdrop.Format); + + var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actualPrimary); + Assert.True(actualPrimary.HasImage); + Assert.Equal(targetPath3, actualPrimary.Path); + Assert.Equal(ImageFormat.Jpg, actualPrimary.Format); + } + + [Fact] + public async void GetImage_EmbeddedDefault() + { + MediaStream sampleStream = new () { Type = MediaStreamType.EmbeddedImage, Index = 1 }; + string targetPath = "path"; + + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream, 1, "jpg", CancellationToken.None)) + .Returns(Task.FromResult(targetPath)); + var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo>()); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>() { sampleStream }); + + var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.True(actual.HasImage); + Assert.Equal(targetPath, actual.Path); + Assert.Equal(ImageFormat.Jpg, actual.Format); + } + + [Fact] + public async void GetImage_EmbeddedSelection() + { + // primary is second stream to ensure it's not defaulting, backdrop is first + MediaStream sampleStream1 = new () { Type = MediaStreamType.EmbeddedImage, Index = 1, Comment = "backdrop" }; + MediaStream sampleStream2 = new () { Type = MediaStreamType.EmbeddedImage, Index = 2, Comment = "cover" }; + string targetPath1 = "path1.jpg"; + string targetPath2 = "path2.jpg"; + + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream1, 1, "jpg", CancellationToken.None)) + .Returns(Task.FromResult(targetPath1)); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream2, 2, "jpg", CancellationToken.None)) + .Returns(Task.FromResult(targetPath2)); + var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo>()); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream> { sampleStream1, sampleStream2 }); + + var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actualPrimary); + Assert.True(actualPrimary.HasImage); + Assert.Equal(targetPath2, actualPrimary.Path); + Assert.Equal(ImageFormat.Jpg, actualPrimary.Format); + + var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); + Assert.NotNull(actualBackdrop); + Assert.True(actualBackdrop.HasImage); + Assert.Equal(targetPath1, actualBackdrop.Path); + Assert.Equal(ImageFormat.Jpg, actualBackdrop.Format); + } + } +} diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs new file mode 100644 index 000000000..9a5cd79bb --- /dev/null +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Providers.MediaInfo; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Providers.Tests.MediaInfo +{ + public class VideoImageProviderTests + { + private VideoImageProvider GetVideoImageProvider(IMediaEncoder? mediaEncoder) + { + // strict to ensure this isn't accidentally used where a prepared mock is intended + mediaEncoder ??= new Mock<IMediaEncoder>(MockBehavior.Strict).Object; + return new VideoImageProvider(mediaEncoder, new NullLogger<VideoImageProvider>()); + } + + [Fact] + public async void GetImage_Empty_IsPlaceholder() + { + var videoImageProvider = GetVideoImageProvider(null); + + var input = new Mock<Movie>(); + input.Object.IsPlaceHolder = true; + + var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Empty_NoDefaultVideoStream() + { + var videoImageProvider = GetVideoImageProvider(null); + + var input = new Mock<Movie>(); + + var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Empty_DefaultSet_NoVideoStream() + { + var videoImageProvider = GetVideoImageProvider(null); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>()); + // set a default index but don't put anything there (invalid input, but provider shouldn't break) + input.Object.DefaultVideoStreamIndex = 1; + + var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_Extract_DefaultStream() + { + MediaStream firstStream = new () { Type = MediaStreamType.Video, Index = 0 }; + MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 1 }; + string targetPath = "path.jpg"; + + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), firstStream, It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Returns(Task.FromResult("wrong stream called!")); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), targetStream, It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Returns(Task.FromResult(targetPath)); + var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetDefaultVideoStream()) + .Returns(targetStream); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>() { firstStream, targetStream }); + input.Object.DefaultVideoStreamIndex = 1; + + var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.True(actual.HasImage); + Assert.Equal(targetPath, actual.Path); + Assert.Equal(ImageFormat.Jpg, actual.Format); + } + + [Fact] + public async void GetImage_Extract_FallbackToFirstVideoStream() + { + MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + string targetPath = "path.jpg"; + + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), targetStream, It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Returns(Task.FromResult(targetPath)); + var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>() { targetStream }); + // default must be set, ensure a stream is still found if not pointed at a video + input.Object.DefaultVideoStreamIndex = 5; + + var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + Assert.NotNull(actual); + Assert.True(actual.HasImage); + Assert.Equal(targetPath, actual.Path); + Assert.Equal(ImageFormat.Jpg, actual.Format); + } + + [Fact] + public async void GetImage_Time_Default() + { + MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + + TimeSpan? actualTimeSpan = null; + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Callback<string, string, MediaSourceInfo, MediaStream, Video3DFormat?, TimeSpan?, CancellationToken>((_, _, _, _, _, timeSpan, _) => actualTimeSpan = timeSpan) + .Returns(Task.FromResult("path")); + var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>() { targetStream }); + // default must be set + input.Object.DefaultVideoStreamIndex = 0; + + // not testing return, just verifying what gets requested for time span + await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + + Assert.Equal(TimeSpan.FromSeconds(10), actualTimeSpan); + } + + [Fact] + public async void GetImage_Time_Calculated() + { + MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + + TimeSpan? actualTimeSpan = null; + var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) + .Callback<string, string, MediaSourceInfo, MediaStream, Video3DFormat?, TimeSpan?, CancellationToken>((_, _, _, _, _, timeSpan, _) => actualTimeSpan = timeSpan) + .Returns(Task.FromResult("path")); + var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); + + var input = new Mock<Movie>(); + input.Setup(movie => movie.GetMediaStreams()) + .Returns(new List<MediaStream>() { targetStream }); + // default must be set + input.Object.DefaultVideoStreamIndex = 0; + input.Object.RunTimeTicks = 5000; + + // not testing return, just verifying what gets requested for time span + await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + + Assert.Equal(TimeSpan.FromTicks(500), actualTimeSpan); + } + } +} -- cgit v1.2.3 From 2b10251b32ad00290f6be00060ec6ccf47574b5d Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Tue, 12 Oct 2021 18:31:58 -0600 Subject: Update to dotnet6.rc2 --- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- deployment/Dockerfile.centos.amd64 | 2 +- deployment/Dockerfile.fedora.amd64 | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 4 ++-- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 4 ++-- 19 files changed, 40 insertions(+), 40 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index e4f30d4e0..c8332e44e 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -72,7 +72,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> </ItemGroup> </Project> diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index dafcded08..9372cba9f 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ <ItemGroup> <PackageReference Include="DiscUtils.Udf" Version="0.16.13" /> <PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.1.21452.10" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.2*" /> <PackageReference Include="Mono.Nat" Version="3.0.1" /> <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.1" /> <PackageReference Include="sharpcompress" Version="0.30.0" /> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index cdc69618a..8a559704c 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -13,8 +13,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.0-rc.1.21452.15" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.2" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.2.2" /> </ItemGroup> diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index f1bfaa63e..2de53e7c8 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0-rc.2*" /> </ItemGroup> <ItemGroup> diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index d9e6d794b..e26cf093b 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ <ItemGroup> <PackageReference Include="System.Linq.Async" Version="5.0.0" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0-rc.1.21452.10" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.1.21452.10" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0-rc.1.21452.10"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0-rc.2*"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0-rc.1.21452.10"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0-rc.2*"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index be2318c54..8983eb50f 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ <ItemGroup> <PackageReference Include="CommandLineParser" Version="2.8.0" /> - <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.0-rc.1.21452.15" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.0-rc.1.21452.15" /> + <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.0-rc.2*" /> <PackageReference Include="prometheus-net" Version="5.0.1" /> <PackageReference Include="prometheus-net.AspNetCore" Version="5.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="4.1.0" /> diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index c87d58a14..9c8ce4ac5 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0-rc.2*" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 007355acd..d37880865 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ <ItemGroup> <PackageReference Include="Diacritics" Version="3.3.4" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0-rc.2*" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0-rc.2*" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 22bba2366..a6caca8db 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ <ItemGroup> <PackageReference Include="BDInfo" Version="0.7.6.1" /> <PackageReference Include="libse" Version="3.6.2" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> + <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0-rc.2*" /> <PackageReference Include="UTF.Unknown" Version="2.4.0" /> </ItemGroup> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index e6a5b1711..16bc4adf8 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -30,9 +30,9 @@ <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0-rc.2*" /> <PackageReference Include="System.Globalization" Version="4.3.0" /> - <PackageReference Include="System.Text.Json" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="System.Text.Json" Version="6.0.0-rc.2*" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 71a3554fd..15badfad7 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0-rc.1.21451.13" /> - <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" /> <PackageReference Include="PlaylistsNET" Version="1.1.3" /> diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 178f94f71..78f051e4f 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index f0f2977a4..14eeb6eed 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index fe1b4981b..8733be89c 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index d984f5d89..6ae0d53cc 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index c013e6797..154388148 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 8b581857f..922b3d94f 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.2*" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 38687ae61..9d7b447ed 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,8 +9,8 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.2*" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index db24df240..67ae0e080 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,8 +10,8 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.1.21452.15" /> - <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.1.21451.13" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.0-rc.2*" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0-rc.2*" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> -- cgit v1.2.3 From 31baea072a1ed25346437150f27a93916cb4cca0 Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Mon, 11 Oct 2021 21:25:12 +0200 Subject: Address review comments Clean up style Fix references in class summaries Combine Where+FirstOrDefault queries Break up large method, long lines Add validation on file extension Apply test naming conventions Extract mock of Movie class, comment on why not mocking interface Co-authored-by: Cody Robibero <cody@robibe.ro> Co-authored-by: Claus Vium <cvium@users.noreply.github.com> --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 9 ++ .../Probing/ProbeResultNormalizer.cs | 4 +- .../MediaInfo/EmbeddedImageProvider.cs | 95 +++++++------ .../MediaInfo/VideoImageProvider.cs | 10 +- .../MediaInfo/EmbeddedImageProviderTests.cs | 155 +++++++++++---------- .../MediaInfo/VideoImageProviderTests.cs | 108 +++++++------- 6 files changed, 208 insertions(+), 173 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index dac2c6a26..102b4f943 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -548,6 +548,15 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ArgumentNullException(nameof(inputPath)); } + if (string.IsNullOrEmpty(outputExtension)) + { + outputExtension = ".jpg"; + } + else if (outputExtension[0] != '.') + { + outputExtension = "." + outputExtension; + } + var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + outputExtension); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 775689095..9279cb220 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -582,8 +582,8 @@ namespace MediaBrowser.MediaEncoding.Probing /// <returns>MediaAttachments.</returns> private MediaAttachment GetMediaAttachment(MediaStreamInfo streamInfo) { - if (!string.Equals(streamInfo.CodecType, "attachment", StringComparison.OrdinalIgnoreCase) && - !(streamInfo.Disposition != null && streamInfo.Disposition.GetValueOrDefault("attached_pic") == 1)) + if (!string.Equals(streamInfo.CodecType, "attachment", StringComparison.OrdinalIgnoreCase) + && streamInfo.Disposition?.GetValueOrDefault("attached_pic") != 1) { return null; } diff --git a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs index df87f2d49..1d9d1e02a 100644 --- a/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.IO; @@ -19,7 +17,7 @@ using MediaBrowser.Model.Net; namespace MediaBrowser.Providers.MediaInfo { /// <summary> - /// Uses ffmpeg to extract embedded images. + /// Uses <see cref="IMediaEncoder"/> to extract embedded images. /// </summary> public class EmbeddedImageProvider : IDynamicImageProvider, IHasOrder { @@ -46,6 +44,10 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IMediaEncoder _mediaEncoder; + /// <summary> + /// Initializes a new instance of the <see cref="EmbeddedImageProvider"/> class. + /// </summary> + /// <param name="mediaEncoder">The media encoder for extracting attached/embedded images.</param> public EmbeddedImageProvider(IMediaEncoder mediaEncoder) { _mediaEncoder = mediaEncoder; @@ -65,13 +67,13 @@ namespace MediaBrowser.Providers.MediaInfo { if (item is Episode) { - return new List<ImageType> + return new[] { ImageType.Primary, }; } - return new List<ImageType> + return new[] { ImageType.Primary, ImageType.Backdrop, @@ -79,7 +81,7 @@ namespace MediaBrowser.Providers.MediaInfo }; } - return new List<ImageType>(); + return Array.Empty<ImageType>(); } /// <inheritdoc /> @@ -114,47 +116,20 @@ namespace MediaBrowser.Providers.MediaInfo }; // Try attachments first - var attachmentSources = item.GetMediaSources(false).SelectMany(source => source.MediaAttachments).ToList(); - var attachmentStream = attachmentSources - .Where(attachment => !string.IsNullOrEmpty(attachment.FileName)) - .FirstOrDefault(attachment => imageFileNames.Any(name => attachment.FileName.Contains(name, StringComparison.OrdinalIgnoreCase))); + var attachmentStream = item.GetMediaSources(false) + .SelectMany(source => source.MediaAttachments) + .FirstOrDefault(attachment => !string.IsNullOrEmpty(attachment.FileName) + && imageFileNames.Any(name => attachment.FileName.Contains(name, StringComparison.OrdinalIgnoreCase))); if (attachmentStream != null) { - var extension = string.IsNullOrEmpty(attachmentStream.MimeType) ? - Path.GetExtension(attachmentStream.FileName) : - MimeTypes.ToExtension(attachmentStream.MimeType); - - if (string.IsNullOrEmpty(extension)) - { - extension = ".jpg"; - } - - string extractedAttachmentPath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, null, attachmentStream.Index, extension, cancellationToken).ConfigureAwait(false); - - ImageFormat format = extension switch - { - ".bmp" => ImageFormat.Bmp, - ".gif" => ImageFormat.Gif, - ".jpg" => ImageFormat.Jpg, - ".png" => ImageFormat.Png, - ".webp" => ImageFormat.Webp, - _ => ImageFormat.Jpg - }; - - return new DynamicImageResponse - { - Format = format, - HasImage = true, - Path = extractedAttachmentPath, - Protocol = MediaProtocol.File - }; + return await ExtractAttachment(item, cancellationToken, attachmentStream, mediaSource); } // Fall back to EmbeddedImage streams var imageStreams = item.GetMediaStreams().FindAll(i => i.Type == MediaStreamType.EmbeddedImage); - if (!imageStreams.Any()) + if (imageStreams.Count == 0) { // Can't extract if we don't have any EmbeddedImage streams return new DynamicImageResponse { HasImage = false }; @@ -162,8 +137,8 @@ namespace MediaBrowser.Providers.MediaInfo // Extract first stream containing an element of imageFileNames var imageStream = imageStreams - .Where(stream => !string.IsNullOrEmpty(stream.Comment)) - .FirstOrDefault(stream => imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase))); + .FirstOrDefault(stream => !string.IsNullOrEmpty(stream.Comment) + && imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase))); // Primary type only: default to first image if none found by label if (imageStream == null) @@ -179,7 +154,9 @@ namespace MediaBrowser.Providers.MediaInfo } } - string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, "jpg", cancellationToken).ConfigureAwait(false); + string extractedImagePath = + await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, ".jpg", cancellationToken) + .ConfigureAwait(false); return new DynamicImageResponse { @@ -190,6 +167,40 @@ namespace MediaBrowser.Providers.MediaInfo }; } + private async Task<DynamicImageResponse> ExtractAttachment(Video item, CancellationToken cancellationToken, MediaAttachment attachmentStream, MediaSourceInfo mediaSource) + { + var extension = string.IsNullOrEmpty(attachmentStream.MimeType) + ? Path.GetExtension(attachmentStream.FileName) + : MimeTypes.ToExtension(attachmentStream.MimeType); + + if (string.IsNullOrEmpty(extension)) + { + extension = ".jpg"; + } + + string extractedAttachmentPath = + await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, null, attachmentStream.Index, extension, cancellationToken) + .ConfigureAwait(false); + + ImageFormat format = extension switch + { + ".bmp" => ImageFormat.Bmp, + ".gif" => ImageFormat.Gif, + ".jpg" => ImageFormat.Jpg, + ".png" => ImageFormat.Png, + ".webp" => ImageFormat.Webp, + _ => ImageFormat.Jpg + }; + + return new DynamicImageResponse + { + Format = format, + HasImage = true, + Path = extractedAttachmentPath, + Protocol = MediaProtocol.File + }; + } + /// <inheritdoc /> public bool Supports(BaseItem item) { diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 60739f156..d226182c0 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -1,6 +1,3 @@ -#nullable enable -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.Linq; @@ -18,13 +15,18 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.MediaInfo { /// <summary> - /// Uses ffmpeg to create still images from the main video. + /// Uses <see cref="IMediaEncoder"/> to create still images from the main video. /// </summary> public class VideoImageProvider : IDynamicImageProvider, IHasOrder { private readonly IMediaEncoder _mediaEncoder; private readonly ILogger<VideoImageProvider> _logger; + /// <summary> + /// Initializes a new instance of the <see cref="VideoImageProvider"/> class. + /// </summary> + /// <param name="mediaEncoder">The media encoder for capturing images.</param> + /// <param name="logger">The logger.</param> public VideoImageProvider(IMediaEncoder mediaEncoder, ILogger<VideoImageProvider> logger) { _mediaEncoder = mediaEncoder; diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs index fcea1532a..b194e3885 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs @@ -17,38 +17,37 @@ namespace Jellyfin.Providers.Tests.MediaInfo { public class EmbeddedImageProviderTests { - public static TheoryData<BaseItem> GetSupportedImages_Empty_TestData => - new () + private static TheoryData<BaseItem> GetSupportedImages_UnsupportedBaseItems_ReturnsEmpty_TestData() + { + return new () { new AudioBook(), new BoxSet(), new Series(), new Season(), }; - - public static TheoryData<BaseItem, IEnumerable<ImageType>> GetSupportedImages_Populated_TestData => - new TheoryData<BaseItem, IEnumerable<ImageType>> - { - { new Episode(), new List<ImageType> { ImageType.Primary } }, - { new Movie(), new List<ImageType> { ImageType.Logo, ImageType.Backdrop, ImageType.Primary } }, - }; - - private EmbeddedImageProvider GetEmbeddedImageProvider(IMediaEncoder? mediaEncoder) - { - return new EmbeddedImageProvider(mediaEncoder); } [Theory] - [MemberData(nameof(GetSupportedImages_Empty_TestData))] - public void GetSupportedImages_Empty(BaseItem item) + [MemberData(nameof(GetSupportedImages_UnsupportedBaseItems_ReturnsEmpty_TestData))] + public void GetSupportedImages_UnsupportedBaseItems_ReturnsEmpty(BaseItem item) { var embeddedImageProvider = GetEmbeddedImageProvider(null); - Assert.False(embeddedImageProvider.GetSupportedImages(item).Any()); + Assert.Empty(embeddedImageProvider.GetSupportedImages(item)); + } + + private static TheoryData<BaseItem, IEnumerable<ImageType>> GetSupportedImages_SupportedBaseItems_ReturnsPopulated_TestData() + { + return new TheoryData<BaseItem, IEnumerable<ImageType>> + { + { new Episode(), new List<ImageType> { ImageType.Primary } }, + { new Movie(), new List<ImageType> { ImageType.Logo, ImageType.Backdrop, ImageType.Primary } }, + }; } [Theory] - [MemberData(nameof(GetSupportedImages_Populated_TestData))] - public void GetSupportedImages_Populated(BaseItem item, IEnumerable<ImageType> expected) + [MemberData(nameof(GetSupportedImages_SupportedBaseItems_ReturnsPopulated_TestData))] + public void GetSupportedImages_SupportedBaseItems_ReturnsPopulated(BaseItem item, IEnumerable<ImageType> expected) { var embeddedImageProvider = GetEmbeddedImageProvider(null); var actual = embeddedImageProvider.GetSupportedImages(item); @@ -56,56 +55,34 @@ namespace Jellyfin.Providers.Tests.MediaInfo } [Fact] - public async void GetImage_Empty_NoStreams() + public async void GetImage_InputWithNoStreams_ReturnsNoImage() { var embeddedImageProvider = GetEmbeddedImageProvider(null); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo>()); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>()); + var input = GetMovie(new List<MediaAttachment>(), new List<MediaStream>()); - var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await embeddedImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.False(actual.HasImage); } [Fact] - public async void GetImage_Empty_NoLabeledAttachments() + public async void GetImage_InputWithUnlabeledAttachments_ReturnsNoImage() { var embeddedImageProvider = GetEmbeddedImageProvider(null); - var input = new Mock<Movie>(); // add an attachment without a filename - has a list to look through but finds nothing - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { new () } } }); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>()); + var input = GetMovie( + new List<MediaAttachment> { new () }, + new List<MediaStream>()); - var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await embeddedImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.False(actual.HasImage); } [Fact] - public async void GetImage_Empty_NoEmbeddedLabeledBackdrop() - { - var embeddedImageProvider = GetEmbeddedImageProvider(null); - - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo>()); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream> { new () { Type = MediaStreamType.EmbeddedImage } }); - - var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); - Assert.NotNull(actual); - Assert.False(actual.HasImage); - } - - [Fact] - public async void GetImage_Attached() + public async void GetImage_InputWithLabeledAttachments_ReturnsCorrectSelection() { // first tests file extension detection, second uses mimetype, third defaults to jpg MediaAttachment sampleAttachment1 = new () { FileName = "clearlogo.png", Index = 1 }; @@ -124,25 +101,23 @@ namespace Jellyfin.Providers.Tests.MediaInfo .Returns(Task.FromResult(targetPath3)); var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = new List<MediaAttachment> { sampleAttachment1, sampleAttachment2, sampleAttachment3 } } }); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>()); + var input = GetMovie( + new List<MediaAttachment> { sampleAttachment1, sampleAttachment2, sampleAttachment3 }, + new List<MediaStream>()); - var actualLogo = await embeddedImageProvider.GetImage(input.Object, ImageType.Logo, CancellationToken.None); + var actualLogo = await embeddedImageProvider.GetImage(input, ImageType.Logo, CancellationToken.None); Assert.NotNull(actualLogo); Assert.True(actualLogo.HasImage); Assert.Equal(targetPath1, actualLogo.Path); Assert.Equal(ImageFormat.Png, actualLogo.Format); - var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); + var actualBackdrop = await embeddedImageProvider.GetImage(input, ImageType.Backdrop, CancellationToken.None); Assert.NotNull(actualBackdrop); Assert.True(actualBackdrop.HasImage); Assert.Equal(targetPath2, actualBackdrop.Path); Assert.Equal(ImageFormat.Bmp, actualBackdrop.Format); - var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actualPrimary = await embeddedImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actualPrimary); Assert.True(actualPrimary.HasImage); Assert.Equal(targetPath3, actualPrimary.Path); @@ -150,23 +125,35 @@ namespace Jellyfin.Providers.Tests.MediaInfo } [Fact] - public async void GetImage_EmbeddedDefault() + public async void GetImage_InputWithUnlabeledEmbeddedImages_BackdropReturnsNoImage() + { + var embeddedImageProvider = GetEmbeddedImageProvider(null); + + var input = GetMovie( + new List<MediaAttachment>(), + new List<MediaStream> { new () { Type = MediaStreamType.EmbeddedImage } }); + + var actual = await embeddedImageProvider.GetImage(input, ImageType.Backdrop, CancellationToken.None); + Assert.NotNull(actual); + Assert.False(actual.HasImage); + } + + [Fact] + public async void GetImage_InputWithUnlabeledEmbeddedImages_PrimaryReturnsImage() { MediaStream sampleStream = new () { Type = MediaStreamType.EmbeddedImage, Index = 1 }; string targetPath = "path"; var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); - mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream, 1, "jpg", CancellationToken.None)) + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream, 1, ".jpg", CancellationToken.None)) .Returns(Task.FromResult(targetPath)); var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo>()); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>() { sampleStream }); + var input = GetMovie( + new List<MediaAttachment>(), + new List<MediaStream> { sampleStream }); - var actual = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await embeddedImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.True(actual.HasImage); Assert.Equal(targetPath, actual.Path); @@ -174,7 +161,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo } [Fact] - public async void GetImage_EmbeddedSelection() + public async void GetImage_InputWithLabeledEmbeddedImages_ReturnsCorrectSelection() { // primary is second stream to ensure it's not defaulting, backdrop is first MediaStream sampleStream1 = new () { Type = MediaStreamType.EmbeddedImage, Index = 1, Comment = "backdrop" }; @@ -183,29 +170,47 @@ namespace Jellyfin.Providers.Tests.MediaInfo string targetPath2 = "path2.jpg"; var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); - mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream1, 1, "jpg", CancellationToken.None)) + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream1, 1, ".jpg", CancellationToken.None)) .Returns(Task.FromResult(targetPath1)); - mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream2, 2, "jpg", CancellationToken.None)) + mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), sampleStream2, 2, ".jpg", CancellationToken.None)) .Returns(Task.FromResult(targetPath2)); var embeddedImageProvider = GetEmbeddedImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaSources(It.IsAny<bool>())) - .Returns(new List<MediaSourceInfo>()); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream> { sampleStream1, sampleStream2 }); + var input = GetMovie( + new List<MediaAttachment>(), + new List<MediaStream> { sampleStream1, sampleStream2 }); - var actualPrimary = await embeddedImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actualPrimary = await embeddedImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actualPrimary); Assert.True(actualPrimary.HasImage); Assert.Equal(targetPath2, actualPrimary.Path); Assert.Equal(ImageFormat.Jpg, actualPrimary.Format); - var actualBackdrop = await embeddedImageProvider.GetImage(input.Object, ImageType.Backdrop, CancellationToken.None); + var actualBackdrop = await embeddedImageProvider.GetImage(input, ImageType.Backdrop, CancellationToken.None); Assert.NotNull(actualBackdrop); Assert.True(actualBackdrop.HasImage); Assert.Equal(targetPath1, actualBackdrop.Path); Assert.Equal(ImageFormat.Jpg, actualBackdrop.Format); } + + private static EmbeddedImageProvider GetEmbeddedImageProvider(IMediaEncoder? mediaEncoder) + { + return new EmbeddedImageProvider(mediaEncoder); + } + + private static Movie GetMovie(List<MediaAttachment> mediaAttachments, List<MediaStream> mediaStreams) + { + // Mocking IMediaSourceManager GetMediaAttachments and GetMediaStreams instead of mocking Movie works, but + // has concurrency problems between this and VideoImageProviderTests due to BaseItem.MediaSourceManager + // being static + var movie = new Mock<Movie>(); + + movie.Setup(item => item.GetMediaSources(It.IsAny<bool>())) + .Returns(new List<MediaSourceInfo> { new () { MediaAttachments = mediaAttachments } } ); + movie.Setup(item => item.GetMediaStreams()) + .Returns(mediaStreams); + + return movie.Object; + } } } diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs index 9a5cd79bb..0f51a2b8f 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs @@ -16,56 +16,51 @@ namespace Jellyfin.Providers.Tests.MediaInfo { public class VideoImageProviderTests { - private VideoImageProvider GetVideoImageProvider(IMediaEncoder? mediaEncoder) - { - // strict to ensure this isn't accidentally used where a prepared mock is intended - mediaEncoder ??= new Mock<IMediaEncoder>(MockBehavior.Strict).Object; - return new VideoImageProvider(mediaEncoder, new NullLogger<VideoImageProvider>()); - } - [Fact] - public async void GetImage_Empty_IsPlaceholder() + public async void GetImage_InputIsPlaceholder_ReturnsNoImage() { var videoImageProvider = GetVideoImageProvider(null); - var input = new Mock<Movie>(); - input.Object.IsPlaceHolder = true; + var input = new Movie + { + IsPlaceHolder = true + }; - var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.False(actual.HasImage); } [Fact] - public async void GetImage_Empty_NoDefaultVideoStream() + public async void GetImage_NoDefaultVideoStream_ReturnsNoImage() { var videoImageProvider = GetVideoImageProvider(null); - var input = new Mock<Movie>(); + var input = new Movie + { + DefaultVideoStreamIndex = null + }; - var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.False(actual.HasImage); } [Fact] - public async void GetImage_Empty_DefaultSet_NoVideoStream() + public async void GetImage_DefaultSetButNoVideoStream_ReturnsNoImage() { var videoImageProvider = GetVideoImageProvider(null); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>()); // set a default index but don't put anything there (invalid input, but provider shouldn't break) - input.Object.DefaultVideoStreamIndex = 1; + var input = GetMovie(0, null, new List<MediaStream>()); - var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.False(actual.HasImage); } [Fact] - public async void GetImage_Extract_DefaultStream() + public async void GetImage_DefaultSetMultipleVideoStreams_ReturnsDefaultStreamImage() { MediaStream firstStream = new () { Type = MediaStreamType.Video, Index = 0 }; MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 1 }; @@ -78,14 +73,9 @@ namespace Jellyfin.Providers.Tests.MediaInfo .Returns(Task.FromResult(targetPath)); var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetDefaultVideoStream()) - .Returns(targetStream); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>() { firstStream, targetStream }); - input.Object.DefaultVideoStreamIndex = 1; + var input = GetMovie(1, targetStream, new List<MediaStream> { firstStream, targetStream } ); - var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.True(actual.HasImage); Assert.Equal(targetPath, actual.Path); @@ -93,7 +83,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo } [Fact] - public async void GetImage_Extract_FallbackToFirstVideoStream() + public async void GetImage_InvalidDefaultSingleVideoStream_ReturnsFirstVideoStreamImage() { MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; string targetPath = "path.jpg"; @@ -103,13 +93,10 @@ namespace Jellyfin.Providers.Tests.MediaInfo .Returns(Task.FromResult(targetPath)); var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>() { targetStream }); - // default must be set, ensure a stream is still found if not pointed at a video - input.Object.DefaultVideoStreamIndex = 5; + // provide query results for default (empty) and all streams (populated) + var input = GetMovie(5, null, new List<MediaStream> { targetStream }); - var actual = await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + var actual = await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.NotNull(actual); Assert.True(actual.HasImage); Assert.Equal(targetPath, actual.Path); @@ -117,10 +104,12 @@ namespace Jellyfin.Providers.Tests.MediaInfo } [Fact] - public async void GetImage_Time_Default() + public async void GetImage_NoTimeSpanSet_CallsEncoderWithDefaultTime() { MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + // use a callback to catch the actual value + // provides more information on failure than verifying a specific input was called on the mock TimeSpan? actualTimeSpan = null; var mediaEncoder = new Mock<IMediaEncoder>(MockBehavior.Strict); mediaEncoder.Setup(encoder => encoder.ExtractVideoImage(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MediaSourceInfo>(), It.IsAny<MediaStream>(), It.IsAny<Video3DFormat?>(), It.IsAny<TimeSpan?>(), CancellationToken.None)) @@ -128,20 +117,16 @@ namespace Jellyfin.Providers.Tests.MediaInfo .Returns(Task.FromResult("path")); var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>() { targetStream }); - // default must be set - input.Object.DefaultVideoStreamIndex = 0; + var input = GetMovie(0, targetStream, new List<MediaStream> { targetStream }); // not testing return, just verifying what gets requested for time span - await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.Equal(TimeSpan.FromSeconds(10), actualTimeSpan); } [Fact] - public async void GetImage_Time_Calculated() + public async void GetImage_TimeSpanSet_CallsEncoderWithCalculatedTime() { MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; @@ -152,17 +137,40 @@ namespace Jellyfin.Providers.Tests.MediaInfo .Returns(Task.FromResult("path")); var videoImageProvider = GetVideoImageProvider(mediaEncoder.Object); - var input = new Mock<Movie>(); - input.Setup(movie => movie.GetMediaStreams()) - .Returns(new List<MediaStream>() { targetStream }); - // default must be set - input.Object.DefaultVideoStreamIndex = 0; - input.Object.RunTimeTicks = 5000; + var input = GetMovie(0, targetStream, new List<MediaStream> { targetStream }); + input.RunTimeTicks = 5000; // not testing return, just verifying what gets requested for time span - await videoImageProvider.GetImage(input.Object, ImageType.Primary, CancellationToken.None); + await videoImageProvider.GetImage(input, ImageType.Primary, CancellationToken.None); Assert.Equal(TimeSpan.FromTicks(500), actualTimeSpan); } + + private static VideoImageProvider GetVideoImageProvider(IMediaEncoder? mediaEncoder) + { + // strict to ensure this isn't accidentally used where a prepared mock is intended + mediaEncoder ??= new Mock<IMediaEncoder>(MockBehavior.Strict).Object; + return new VideoImageProvider(mediaEncoder, new NullLogger<VideoImageProvider>()); + } + + private static Movie GetMovie(int defaultVideoStreamIndex, MediaStream? defaultStream, List<MediaStream> mediaStreams) + { + // Mocking IMediaSourceManager GetMediaStreams instead of mocking Movie works, but has concurrency problems + // between this and EmbeddedImageProviderTests due to BaseItem.MediaSourceManager being static + var movie = new Mock<Movie> + { + Object = + { + DefaultVideoStreamIndex = defaultVideoStreamIndex + } + }; + + movie.Setup(item => item.GetDefaultVideoStream()) + .Returns(defaultStream!); + movie.Setup(item => item.GetMediaStreams()) + .Returns(mediaStreams); + + return movie.Object; + } } } -- cgit v1.2.3 From 2372931b13d2ec74fafcffe6a07bd157b911ef62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 12:01:04 +0000 Subject: Bump UTF.Unknown from 2.4.0 to 2.5.0 Bumps [UTF.Unknown](https://github.com/CharsetDetector/UTF-unknown) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/CharsetDetector/UTF-unknown/releases) - [Commits](https://github.com/CharsetDetector/UTF-unknown/compare/v2.4...v2.5) --- updated-dependencies: - dependency-name: UTF.Unknown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> --- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index a6caca8db..c1fd8e5fb 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -26,7 +26,7 @@ <PackageReference Include="libse" Version="3.6.2" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-rc.2*" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0-rc.2*" /> - <PackageReference Include="UTF.Unknown" Version="2.4.0" /> + <PackageReference Include="UTF.Unknown" Version="2.5.0" /> </ItemGroup> <!-- Code Analyzers--> -- cgit v1.2.3