mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-27 19:08:27 +01:00
Merge branch 'master' into network-rewrite
This commit is contained in:
@@ -169,8 +169,8 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
|
||||
var childUpdateType = ItemUpdateType.None;
|
||||
|
||||
// Refresh songs
|
||||
foreach (var item in items)
|
||||
// Refresh songs only and not m3u files in album folder
|
||||
foreach (var item in items.OfType<Audio>())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
|
||||
@@ -2616,7 +2616,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
return ExtraIds
|
||||
.Select(LibraryManager.GetItemById)
|
||||
.Where(i => i != null)
|
||||
.Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value));
|
||||
.Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value))
|
||||
.OrderBy(i => i.SortName);
|
||||
}
|
||||
|
||||
public virtual long GetRunTimeTicksForPlayState()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -13,7 +11,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
public abstract class BasePluginFolder : Folder, ICollectionFolder
|
||||
{
|
||||
[JsonIgnore]
|
||||
public virtual string CollectionType => null;
|
||||
public virtual string? CollectionType => null;
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool SupportsInheritedParentImages => false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Jellyfin.Extensions;
|
||||
@@ -19,9 +17,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <param name="url">Trailer URL.</param>
|
||||
public static void AddTrailerUrl(this BaseItem item, string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
ArgumentNullException.ThrowIfNull(url, nameof(url));
|
||||
|
||||
if (url.Length == 0)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
throw new ArgumentException("String can't be empty", nameof(url));
|
||||
}
|
||||
|
||||
var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
@@ -860,7 +860,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||
if (query.AdjacentTo.HasValue && !query.AdjacentTo.Value.Equals(default))
|
||||
{
|
||||
Logger.LogDebug("Query requires post-filtering due to AdjacentTo");
|
||||
return true;
|
||||
@@ -892,29 +892,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private static BaseItem[] SortItemsByRequest(InternalItemsQuery query, IReadOnlyList<BaseItem> items)
|
||||
{
|
||||
var ids = query.ItemIds;
|
||||
int size = items.Count;
|
||||
|
||||
// ids can potentially contain non-unique guids, but query result cannot,
|
||||
// so we include only first occurrence of each guid
|
||||
var positions = new Dictionary<Guid, int>(size);
|
||||
int index = 0;
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
{
|
||||
if (positions.TryAdd(ids[i], index))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
var newItems = new BaseItem[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
var item = items[i];
|
||||
newItems[positions[item.Id]] = item;
|
||||
}
|
||||
|
||||
return newItems;
|
||||
return items.OrderBy(i => Array.IndexOf(query.ItemIds, i.Id)).ToArray();
|
||||
}
|
||||
|
||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||
@@ -1029,9 +1007,9 @@ namespace MediaBrowser.Controller.Entities
|
||||
#pragma warning restore CA1309
|
||||
|
||||
// This must be the last filter
|
||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||
if (query.AdjacentTo.HasValue && !query.AdjacentTo.Value.Equals(default))
|
||||
{
|
||||
items = UserViewBuilder.FilterForAdjacency(items.ToList(), query.AdjacentTo);
|
||||
items = UserViewBuilder.FilterForAdjacency(items.ToList(), query.AdjacentTo.Value);
|
||||
}
|
||||
|
||||
return UserViewBuilder.SortAndPage(items, null, query, LibraryManager, enableSorting);
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
public Guid[] ExcludeItemIds { get; set; }
|
||||
|
||||
public string? AdjacentTo { get; set; }
|
||||
public Guid? AdjacentTo { get; set; }
|
||||
|
||||
public string[] PersonTypes { get; set; }
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
/// <summary>
|
||||
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
|
||||
/// </summary>
|
||||
/// <param name="replaceAllMetadata"><c>true</c> to replace metdata, <c>false</c> to not.</param>
|
||||
/// <param name="replaceAllMetadata"><c>true</c> to replace metadata, <c>false</c> to not.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
|
||||
{
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
DtoOptions = options
|
||||
};
|
||||
|
||||
if (!user.DisplayMissingEpisodes)
|
||||
if (user == null || !user.DisplayMissingEpisodes)
|
||||
{
|
||||
query.IsMissing = false;
|
||||
}
|
||||
|
||||
@@ -433,9 +433,9 @@ namespace MediaBrowser.Controller.Entities
|
||||
var user = query.User;
|
||||
|
||||
// This must be the last filter
|
||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||
if (query.AdjacentTo.HasValue && !query.AdjacentTo.Value.Equals(default))
|
||||
{
|
||||
items = FilterForAdjacency(items.ToList(), query.AdjacentTo);
|
||||
items = FilterForAdjacency(items.ToList(), query.AdjacentTo.Value);
|
||||
}
|
||||
|
||||
return SortAndPage(items, totalRecordLimit, query, libraryManager, true);
|
||||
@@ -985,10 +985,9 @@ namespace MediaBrowser.Controller.Entities
|
||||
return _userViewManager.GetUserSubView(parent.Id, type, localizationKey, sortName);
|
||||
}
|
||||
|
||||
public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, string adjacentToId)
|
||||
public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, Guid adjacentTo)
|
||||
{
|
||||
var adjacentToIdGuid = new Guid(adjacentToId);
|
||||
var adjacentToItem = list.FirstOrDefault(i => i.Id.Equals(adjacentToIdGuid));
|
||||
var adjacentToItem = list.FirstOrDefault(i => i.Id.Equals(adjacentTo));
|
||||
|
||||
var index = list.IndexOf(adjacentToItem);
|
||||
|
||||
@@ -1005,7 +1004,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
nextId = list[index + 1].Id;
|
||||
}
|
||||
|
||||
return list.Where(i => i.Id.Equals(previousId) || i.Id.Equals(nextId) || i.Id.Equals(adjacentToIdGuid));
|
||||
return list.Where(i => i.Id.Equals(previousId) || i.Id.Equals(nextId) || i.Id.Equals(adjacentTo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Jellyfin.Data.Entities;
|
||||
@@ -50,7 +48,7 @@ namespace MediaBrowser.Controller
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="client">The client string.</param>
|
||||
/// <returns>The dictionary of custom item display preferences.</returns>
|
||||
Dictionary<string, string> ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client);
|
||||
Dictionary<string, string?> ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the custom item display preference for the user and client.
|
||||
@@ -59,7 +57,7 @@ namespace MediaBrowser.Controller
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="client">The client id.</param>
|
||||
/// <param name="customPreferences">A dictionary of custom item display preferences.</param>
|
||||
void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary<string, string> customPreferences);
|
||||
void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary<string, string?> customPreferences);
|
||||
|
||||
/// <summary>
|
||||
/// Saves changes made to the database.
|
||||
|
||||
@@ -570,5 +570,13 @@ namespace MediaBrowser.Controller.Library
|
||||
Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason);
|
||||
|
||||
BaseItem GetParentItem(Guid? parentId, Guid? userId);
|
||||
|
||||
/// <summary>
|
||||
/// Queue a library scan.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This exists so plugins can trigger a library scan.
|
||||
/// </remarks>
|
||||
void QueueLibraryScan();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly ISubtitleEncoder _subtitleEncoder;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly Version _minKernelVersioni915Hang = new Version(5, 18);
|
||||
|
||||
private static readonly string[] _videoProfilesH264 = new[]
|
||||
{
|
||||
@@ -193,7 +194,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
/// <summary>
|
||||
/// Gets the name of the output video codec.
|
||||
/// </summary>
|
||||
/// <param name="state">Encording state.</param>
|
||||
/// <param name="state">Encoding state.</param>
|
||||
/// <param name="encodingOptions">Encoding options.</param>
|
||||
/// <returns>Encoder string.</returns>
|
||||
public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
|
||||
@@ -255,6 +256,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the referer param.
|
||||
/// </summary>
|
||||
/// <param name="state">The state.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
public string GetRefererParam(EncodingJobInfo state)
|
||||
{
|
||||
if (state.RemoteHttpHeaders.TryGetValue("Referer", out string referer))
|
||||
{
|
||||
return "-referer \"" + referer + "\"";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static string GetInputFormat(string container)
|
||||
{
|
||||
if (string.IsNullOrEmpty(container))
|
||||
@@ -930,6 +946,13 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
arg.Append(" -i \"").Append(state.AudioStream.Path).Append('"');
|
||||
}
|
||||
|
||||
// Disable auto inserted SW scaler for HW decoders in case of changed resolution.
|
||||
var isSwDecoder = string.IsNullOrEmpty(GetHardwareVideoDecoder(state, options));
|
||||
if (!isSwDecoder)
|
||||
{
|
||||
arg.Append(" -autoscale 0");
|
||||
}
|
||||
|
||||
return arg.ToString();
|
||||
}
|
||||
|
||||
@@ -1144,16 +1167,15 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (state.SubtitleStream.IsExternal)
|
||||
{
|
||||
var subtitlePath = state.SubtitleStream.Path;
|
||||
var charsetParam = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(state.SubtitleStream.Language))
|
||||
{
|
||||
var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet(
|
||||
subtitlePath,
|
||||
state.SubtitleStream.Language,
|
||||
state.MediaSource.Protocol,
|
||||
CancellationToken.None).GetAwaiter().GetResult();
|
||||
state.SubtitleStream,
|
||||
state.SubtitleStream.Language,
|
||||
state.MediaSource,
|
||||
CancellationToken.None).GetAwaiter().GetResult();
|
||||
|
||||
if (!string.IsNullOrEmpty(charenc))
|
||||
{
|
||||
@@ -1165,7 +1187,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"subtitles=f='{0}'{1}{2}{3}{4}{5}",
|
||||
_mediaEncoder.EscapeSubtitleFilterPath(subtitlePath),
|
||||
_mediaEncoder.EscapeSubtitleFilterPath(state.SubtitleStream.Path),
|
||||
charsetParam,
|
||||
alphaParam,
|
||||
sub2videoParam,
|
||||
@@ -1302,6 +1324,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// which will reduce overhead in performance intensive tasks such as 4k transcoding and tonemapping.
|
||||
var intelLowPowerHwEncoding = false;
|
||||
|
||||
// Workaround for linux 5.18+ i915 hang at cost of performance.
|
||||
// https://github.com/intel/media-driver/issues/1456
|
||||
var enableWaFori915Hang = false;
|
||||
|
||||
if (string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var isIntelVaapiDriver = _mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965;
|
||||
@@ -1317,6 +1343,20 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
else if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (OperatingSystem.IsLinux() && Environment.OSVersion.Version >= _minKernelVersioni915Hang)
|
||||
{
|
||||
var vidDecoder = GetHardwareVideoDecoder(state, encodingOptions) ?? string.Empty;
|
||||
var isIntelDecoder = vidDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase)
|
||||
|| vidDecoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase);
|
||||
var doOclTonemap = _mediaEncoder.SupportsHwaccel("qsv")
|
||||
&& IsVaapiSupported(state)
|
||||
&& IsOpenclFullSupported()
|
||||
&& !IsVaapiVppTonemapAvailable(state, encodingOptions)
|
||||
&& IsHwTonemapAvailable(state, encodingOptions);
|
||||
|
||||
enableWaFori915Hang = isIntelDecoder && doOclTonemap;
|
||||
}
|
||||
|
||||
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
intelLowPowerHwEncoding = encodingOptions.EnableIntelLowPowerH264HwEncoder;
|
||||
@@ -1325,6 +1365,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
intelLowPowerHwEncoding = encodingOptions.EnableIntelLowPowerHevcHwEncoder;
|
||||
}
|
||||
else
|
||||
{
|
||||
enableWaFori915Hang = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (intelLowPowerHwEncoding)
|
||||
@@ -1332,6 +1376,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
param += " -low_power 1";
|
||||
}
|
||||
|
||||
if (enableWaFori915Hang)
|
||||
{
|
||||
param += " -async_depth 1";
|
||||
}
|
||||
|
||||
var isVc1 = string.Equals(state.VideoStream?.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
|
||||
var isLibX265 = string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
@@ -1713,6 +1762,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
// Can't stream copy if we're burning in subtitles
|
||||
if (request.SubtitleStreamIndex.HasValue
|
||||
&& request.SubtitleStreamIndex.Value >= 0
|
||||
&& state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
|
||||
{
|
||||
return false;
|
||||
@@ -1760,7 +1810,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
var requestedRangeTypes = state.GetRequestedRangeTypes(videoStream.Codec);
|
||||
if (requestedProfiles.Length > 0)
|
||||
if (requestedRangeTypes.Length > 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(videoStream.VideoRangeType))
|
||||
{
|
||||
@@ -1945,7 +1995,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
}
|
||||
|
||||
// Cap the max target bitrate to intMax/2 to satisify the bufsize=bitrate*2.
|
||||
// Cap the max target bitrate to intMax/2 to satisfy the bufsize=bitrate*2.
|
||||
return Math.Min(bitrate ?? 0, int.MaxValue / 2);
|
||||
}
|
||||
|
||||
@@ -2026,6 +2076,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "vorbis", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "eac3", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -4503,7 +4555,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (isD3d11Supported && isCodecAvailable)
|
||||
{
|
||||
return " -hwaccel d3d11va" + (outputHwSurface ? " -hwaccel_output_format d3d11" : string.Empty) + (isAv1 ? " -c:v av1" : string.Empty);
|
||||
// set -threads 3 to intel d3d11va decoder explicitly. Lower threads may result in dead lock.
|
||||
// on newer devices such as Xe, the larger the init_pool_size, the longer the initialization time for opencl to derive from d3d11.
|
||||
return " -hwaccel d3d11va" + (outputHwSurface ? " -hwaccel_output_format d3d11" : string.Empty) + " -threads 3" + (isAv1 ? " -c:v av1" : string.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4937,14 +4991,14 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// The default value of -probesize is more than enough, so leave it as is.
|
||||
var ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration))
|
||||
{
|
||||
analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration;
|
||||
}
|
||||
else if (state.MediaSource.AnalyzeDurationMs.HasValue)
|
||||
if (state.MediaSource.AnalyzeDurationMs > 0)
|
||||
{
|
||||
analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration))
|
||||
{
|
||||
analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(analyzeDurationArgument))
|
||||
{
|
||||
@@ -4962,12 +5016,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
inputModifier = inputModifier.Trim();
|
||||
|
||||
var refererParam = GetRefererParam(state);
|
||||
|
||||
if (!string.IsNullOrEmpty(refererParam))
|
||||
{
|
||||
inputModifier += " " + refererParam;
|
||||
}
|
||||
|
||||
inputModifier = inputModifier.Trim();
|
||||
|
||||
inputModifier += " " + GetFastSeekCommandLineParameter(state, encodingOptions, segmentContainer);
|
||||
inputModifier = inputModifier.Trim();
|
||||
|
||||
if (state.InputProtocol == MediaProtocol.Rtsp)
|
||||
{
|
||||
inputModifier += " -rtsp_transport tcp -rtsp_transport udp -rtsp_flags prefer_tcp";
|
||||
inputModifier += " -rtsp_transport tcp+udp -rtsp_flags prefer_tcp";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(state.InputAudioSync))
|
||||
@@ -5496,7 +5559,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return index;
|
||||
}
|
||||
|
||||
if (string.Equals(currentMediaStream.Path, streamToFind.Path, StringComparison.Ordinal))
|
||||
if (string.Equals(currentMediaStream.Path, streamToFind.Path, StringComparison.Ordinal))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Data.Entities;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
|
||||
@@ -37,6 +37,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
/// <returns>The version of encoder.</returns>
|
||||
Version EncoderVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether p key pausing is supported.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if p key pausing is supported, <c>false</c> otherwise.</value>
|
||||
bool IsPkeyPauseSupported { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver).
|
||||
/// </summary>
|
||||
|
||||
@@ -6,7 +6,8 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
@@ -37,11 +38,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
/// <summary>
|
||||
/// Gets the subtitle language encoding parameter.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="subtitleStream">The subtitle stream.</param>
|
||||
/// <param name="language">The language.</param>
|
||||
/// <param name="protocol">The protocol.</param>
|
||||
/// <param name="mediaSource">The media source.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
Task<string> GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken);
|
||||
Task<string> GetSubtitleFileCharacterSet(MediaStream subtitleStream, string language, MediaSourceInfo mediaSource, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,10 @@ using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
public interface IWebSocketConnection
|
||||
public interface IWebSocketConnection : IAsyncDisposable, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when [closed].
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Session;
|
||||
@@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Session
|
||||
/// <summary>
|
||||
/// Class SessionInfo.
|
||||
/// </summary>
|
||||
public sealed class SessionInfo : IDisposable
|
||||
public sealed class SessionInfo : IAsyncDisposable, IDisposable
|
||||
{
|
||||
// 1 second
|
||||
private const long ProgressIncrement = 10000000;
|
||||
@@ -380,10 +381,28 @@ namespace MediaBrowser.Controller.Session
|
||||
{
|
||||
if (controller is IDisposable disposable)
|
||||
{
|
||||
_logger.LogDebug("Disposing session controller {0}", disposable.GetType().Name);
|
||||
_logger.LogDebug("Disposing session controller synchronously {TypeName}", disposable.GetType().Name);
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
StopAutomaticProgress();
|
||||
|
||||
var controllers = SessionControllers.ToList();
|
||||
|
||||
foreach (var controller in controllers)
|
||||
{
|
||||
if (controller is IAsyncDisposable disposableAsync)
|
||||
{
|
||||
_logger.LogDebug("Disposing session controller asynchronously {TypeName}", disposableAsync.GetType().Name);
|
||||
await disposableAsync.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
|
||||
|
||||
if (InitialState.Equals(GroupStateType.Playing))
|
||||
{
|
||||
// Group went from playing to waiting state and a pause request occured while waiting.
|
||||
// Group went from playing to waiting state and a pause request occurred while waiting.
|
||||
var pauseRequest = new PauseGroupRequest();
|
||||
pausedState.HandleRequest(pauseRequest, context, Type, session, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace MediaBrowser.Controller.SyncPlay.PlaybackRequests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playlist identifiers ot the items.
|
||||
/// Gets the playlist identifiers of the items.
|
||||
/// </summary>
|
||||
/// <value>The playlist identifiers ot the items.</value>
|
||||
/// <value>The playlist identifiers of the items.</value>
|
||||
public IReadOnlyList<Guid> PlaylistItemIds { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends new items to the playlist. The specified order is mantained.
|
||||
/// Appends new items to the playlist. The specified order is maintained.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the playlist.</param>
|
||||
public void Queue(IReadOnlyList<Guid> items)
|
||||
@@ -197,7 +197,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new items to the playlist right after the playing item. The specified order is mantained.
|
||||
/// Adds new items to the playlist right after the playing item. The specified order is maintained.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the playlist.</param>
|
||||
public void QueueNext(IReadOnlyList<Guid> items)
|
||||
|
||||
Reference in New Issue
Block a user