diff options
| author | Stepan Goremykin <goremukin@gmail.com> | 2023-10-12 20:11:16 +0200 |
|---|---|---|
| committer | Stepan Goremykin <goremukin@gmail.com> | 2023-10-12 20:11:16 +0200 |
| commit | 8d7e4229ca694d8222cd7b97519b63a5c79f770b (patch) | |
| tree | 81def03b33fb5bb737467c2f92a289e17fb9a53d /MediaBrowser.Controller | |
| parent | 96c3bde3463ad0457d894ed532093ed28e868ba8 (diff) | |
| parent | 075b828cbf42804439fd847b5ae3701061906fda (diff) | |
Merge branch 'master' into fix-resharper-warnings
# Conflicts:
# Emby.Server.Implementations/Net/SocketFactory.cs
# RSSDP/SsdpCommunicationsServer.cs
# RSSDP/SsdpDeviceLocator.cs
# RSSDP/SsdpDevicePublisher.cs
Diffstat (limited to 'MediaBrowser.Controller')
6 files changed, 238 insertions, 33 deletions
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index cdc3d52b9..0d1e2a5a0 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Entities; @@ -74,14 +73,6 @@ namespace MediaBrowser.Controller.Drawing /// Processes the image. /// </summary> /// <param name="options">The options.</param> - /// <param name="toStream">To stream.</param> - /// <returns>Task.</returns> - Task ProcessImage(ImageProcessingOptions options, Stream toStream); - - /// <summary> - /// Processes the image. - /// </summary> - /// <param name="options">The options.</param> /// <returns>Task.</returns> Task<(string Path, string? MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options); @@ -97,7 +88,5 @@ namespace MediaBrowser.Controller.Drawing /// <param name="options">The options.</param> /// <param name="libraryName">The library name to draw onto the collage.</param> void CreateImageCollage(ImageCollageOptions options, string? libraryName); - - bool SupportsTransparency(string path); } } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index 7912c5e87..953cfe698 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -119,7 +119,8 @@ namespace MediaBrowser.Controller.Drawing private bool IsFormatSupported(string originalImagePath) { var ext = Path.GetExtension(originalImagePath); - return SupportedOutputFormats.Any(outputFormat => string.Equals(ext, "." + outputFormat, StringComparison.OrdinalIgnoreCase)); + ext = ext.Replace(".jpeg", ".jpg", StringComparison.OrdinalIgnoreCase); + return SupportedOutputFormats.Any(outputFormat => string.Equals(ext, outputFormat.GetExtension(), StringComparison.OrdinalIgnoreCase)); } } } diff --git a/MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs b/MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs new file mode 100644 index 000000000..2742f21e3 --- /dev/null +++ b/MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml; +using Jellyfin.Data.Enums; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Extensions; + +/// <summary> +/// Provides extension methods for <see cref="XmlReader"/> to parse <see cref="BaseItem"/>'s. +/// </summary> +public static class XmlReaderExtensions +{ + /// <summary> + /// Reads a trimmed string from the current node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <returns>The trimmed content.</returns> + public static string ReadNormalizedString(this XmlReader reader) + { + ArgumentNullException.ThrowIfNull(reader); + + return reader.ReadElementContentAsString().Trim(); + } + + /// <summary> + /// Reads an int from the current node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <param name="value">The parsed <c>int</c>.</param> + /// <returns>A value indicating whether the parsing succeeded.</returns> + public static bool TryReadInt(this XmlReader reader, out int value) + { + ArgumentNullException.ThrowIfNull(reader); + + return int.TryParse(reader.ReadElementContentAsString(), CultureInfo.InvariantCulture, out value); + } + + /// <summary> + /// Parses a <see cref="DateTime"/> from the current node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <param name="value">The parsed <see cref="DateTime"/>.</param> + /// <returns>A value indicating whether the parsing succeeded.</returns> + public static bool TryReadDateTime(this XmlReader reader, out DateTime value) + { + ArgumentNullException.ThrowIfNull(reader); + + return DateTime.TryParse( + reader.ReadElementContentAsString(), + CultureInfo.InvariantCulture, + DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, + out value); + } + + /// <summary> + /// Parses a <see cref="DateTime"/> from the current node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <param name="formatString">The date format string.</param> + /// <param name="value">The parsed <see cref="DateTime"/>.</param> + /// <returns>A value indicating whether the parsing succeeded.</returns> + public static bool TryReadDateTimeExact(this XmlReader reader, string formatString, out DateTime value) + { + ArgumentNullException.ThrowIfNull(reader); + ArgumentNullException.ThrowIfNull(formatString); + + return DateTime.TryParseExact( + reader.ReadElementContentAsString(), + formatString, + CultureInfo.InvariantCulture, + DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, + out value); + } + + /// <summary> + /// Parses a <see cref="PersonInfo"/> from the xml node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <returns>A <see cref="PersonInfo"/>, or <c>null</c> if none is found.</returns> + public static PersonInfo? GetPersonFromXmlNode(this XmlReader reader) + { + ArgumentNullException.ThrowIfNull(reader); + + if (reader.IsEmptyElement) + { + reader.Read(); + return null; + } + + var name = string.Empty; + var type = PersonKind.Actor; // If type is not specified assume actor + var role = string.Empty; + int? sortOrder = null; + string? imageUrl = null; + + using var subtree = reader.ReadSubtree(); + subtree.MoveToContent(); + subtree.Read(); + + while (subtree is { EOF: false, ReadState: ReadState.Interactive }) + { + if (subtree.NodeType != XmlNodeType.Element) + { + subtree.Read(); + continue; + } + + switch (subtree.Name) + { + case "name": + case "Name": + name = subtree.ReadNormalizedString(); + break; + case "role": + case "Role": + role = subtree.ReadNormalizedString(); + break; + case "type": + case "Type": + Enum.TryParse(subtree.ReadElementContentAsString(), true, out type); + break; + case "order": + case "sortorder": + case "SortOrder": + if (subtree.TryReadInt(out var sortOrderVal)) + { + sortOrder = sortOrderVal; + } + + break; + case "thumb": + imageUrl = subtree.ReadNormalizedString(); + break; + default: + subtree.Skip(); + break; + } + } + + if (string.IsNullOrWhiteSpace(name)) + { + return null; + } + + return new PersonInfo + { + Name = name, + Role = role, + Type = type, + SortOrder = sortOrder, + ImageUrl = imageUrl + }; + } + + /// <summary> + /// Used to split names of comma or pipe delimited genres and people. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <returns>IEnumerable{System.String}.</returns> + public static IEnumerable<string> GetStringArray(this XmlReader reader) + { + ArgumentNullException.ThrowIfNull(reader); + var value = reader.ReadElementContentAsString(); + + // 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.Contains('|', StringComparison.Ordinal) + && !value.Contains(';', StringComparison.Ordinal) + ? new[] { ',' } + : new[] { '|', ';' }; + + foreach (var part in value.Trim().Trim(separator).Split(separator)) + { + if (!string.IsNullOrWhiteSpace(part)) + { + yield return part.Trim(); + } + } + } + + /// <summary> + /// Parses a <see cref="PersonInfo"/> array from the xml node. + /// </summary> + /// <param name="reader">The <see cref="XmlReader"/>.</param> + /// <param name="personKind">The <see cref="PersonKind"/>.</param> + /// <returns>The <see cref="IEnumerable{PersonInfo}"/>.</returns> + public static IEnumerable<PersonInfo> GetPersonArray(this XmlReader reader, PersonKind personKind) + => reader.GetStringArray() + .Select(part => new PersonInfo { Name = part, Type = personKind }); +} diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 45ac5c3a8..e9c4d9e19 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -4,7 +4,6 @@ using System.Net; using MediaBrowser.Common; -using MediaBrowser.Model.System; using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller @@ -16,8 +15,6 @@ namespace MediaBrowser.Controller { bool CoreStartupHasCompleted { get; } - bool CanLaunchWebBrowser { get; } - /// <summary> /// Gets the HTTP server port. /// </summary> @@ -42,15 +39,6 @@ namespace MediaBrowser.Controller string FriendlyName { get; } /// <summary> - /// Gets the system info. - /// </summary> - /// <param name="request">The HTTP request.</param> - /// <returns>SystemInfo.</returns> - SystemInfo GetSystemInfo(HttpRequest request); - - PublicSystemInfo GetPublicSystemInfo(HttpRequest request); - - /// <summary> /// Gets a URL specific for the request. /// </summary> /// <param name="request">The <see cref="HttpRequest"/> instance.</param> diff --git a/MediaBrowser.Controller/ISystemManager.cs b/MediaBrowser.Controller/ISystemManager.cs new file mode 100644 index 000000000..ef3034d2f --- /dev/null +++ b/MediaBrowser.Controller/ISystemManager.cs @@ -0,0 +1,34 @@ +using MediaBrowser.Model.System; +using Microsoft.AspNetCore.Http; + +namespace MediaBrowser.Controller; + +/// <summary> +/// A service for managing the application instance. +/// </summary> +public interface ISystemManager +{ + /// <summary> + /// Gets the system info. + /// </summary> + /// <param name="request">The HTTP request.</param> + /// <returns>The <see cref="SystemInfo"/>.</returns> + SystemInfo GetSystemInfo(HttpRequest request); + + /// <summary> + /// Gets the public system info. + /// </summary> + /// <param name="request">The HTTP request.</param> + /// <returns>The <see cref="PublicSystemInfo"/>.</returns> + PublicSystemInfo GetPublicSystemInfo(HttpRequest request); + + /// <summary> + /// Starts the application restart process. + /// </summary> + void Restart(); + + /// <summary> + /// Starts the application shutdown process. + /// </summary> + void Shutdown(); +} diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8d51c800f..08ce19f69 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -548,25 +548,25 @@ namespace MediaBrowser.Controller.MediaEncoding /// <returns>System.Nullable{VideoCodecs}.</returns> public string InferVideoCodec(string url) { - var ext = Path.GetExtension(url); + var ext = Path.GetExtension(url.AsSpan()); - if (string.Equals(ext, ".asf", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".asf", StringComparison.OrdinalIgnoreCase)) { return "wmv"; } - if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".webm", StringComparison.OrdinalIgnoreCase)) { // TODO: this may not always mean VP8, as the codec ages return "vp8"; } - if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".ogg", StringComparison.OrdinalIgnoreCase) || ext.Equals(".ogv", StringComparison.OrdinalIgnoreCase)) { return "theora"; } - if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase)) + if (ext.Equals(".m3u8", StringComparison.OrdinalIgnoreCase) || ext.Equals(".ts", StringComparison.OrdinalIgnoreCase)) { return "h264"; } @@ -1080,10 +1080,10 @@ namespace MediaBrowser.Controller.MediaEncoding && state.SubtitleStream.IsExternal) { var subtitlePath = state.SubtitleStream.Path; - var subtitleExtension = Path.GetExtension(subtitlePath); + var subtitleExtension = Path.GetExtension(subtitlePath.AsSpan()); - if (string.Equals(subtitleExtension, ".sub", StringComparison.OrdinalIgnoreCase) - || string.Equals(subtitleExtension, ".sup", StringComparison.OrdinalIgnoreCase)) + if (subtitleExtension.Equals(".sub", StringComparison.OrdinalIgnoreCase) + || subtitleExtension.Equals(".sup", StringComparison.OrdinalIgnoreCase)) { var idxFile = Path.ChangeExtension(subtitlePath, ".idx"); if (File.Exists(idxFile)) @@ -6038,7 +6038,7 @@ namespace MediaBrowser.Controller.MediaEncoding var format = string.Empty; var keyFrame = string.Empty; - if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) + if (Path.GetExtension(outputPath.AsSpan()).Equals(".mp4", StringComparison.OrdinalIgnoreCase) && state.BaseRequest.Context == EncodingContext.Streaming) { // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js |
