mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-22 01:54:42 +01:00
Merge branch 'master' into fix-resharper-warnings
# Conflicts: # Emby.Server.Implementations/Net/SocketFactory.cs # RSSDP/SsdpCommunicationsServer.cs # RSSDP/SsdpDeviceLocator.cs # RSSDP/SsdpDevicePublisher.cs
This commit is contained in:
@@ -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;
|
||||
@@ -70,14 +69,6 @@ namespace MediaBrowser.Controller.Drawing
|
||||
|
||||
string? GetImageCacheTag(User user);
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
193
MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs
Normal file
193
MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs
Normal file
@@ -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 });
|
||||
}
|
||||
@@ -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>
|
||||
@@ -41,15 +38,6 @@ namespace MediaBrowser.Controller
|
||||
/// <value>The name of the friendly.</value>
|
||||
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>
|
||||
|
||||
34
MediaBrowser.Controller/ISystemManager.cs
Normal file
34
MediaBrowser.Controller/ISystemManager.cs
Normal file
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user