aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorJinYi-Tsinghua <109143373+JinYi-Tsinghua@users.noreply.github.com>2022-08-29 02:32:16 +0000
committerGitHub <noreply@github.com>2022-08-29 02:32:16 +0000
commitf1bfbff9530d6b04518b7a601a1015c7a8d1443e (patch)
treeeedd01e775ab5b0d2852483584b786dfcac38996 /MediaBrowser.Controller
parenta94aec9b326935bc9583f74f3f3c15df0139cf24 (diff)
parent2b285b787408417b4ae1f8e3f364b2e5e0a66207 (diff)
Merge pull request #1 from JinYi-Tsinghua/patch-1
Patch 1
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs2
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs2
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs2
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs11
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs8
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj2
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs63
-rw-r--r--MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs9
-rw-r--r--MediaBrowser.Controller/Net/IWebSocketConnection.cs2
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs23
-rw-r--r--MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs2
-rw-r--r--MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs4
-rw-r--r--MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs4
15 files changed, 105 insertions, 39 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 03d1f3304..bd397bdd1 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -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();
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index b6983b73e..1860da4c7 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -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;
@@ -1029,9 +1029,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);
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index db1697c79..13bfd07c3 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -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; }
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index bd8df2fac..599d35da6 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -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)
{
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index 727efee50..d66802a64 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -266,7 +266,7 @@ namespace MediaBrowser.Controller.Entities.TV
DtoOptions = options
};
- if (!user.DisplayMissingEpisodes)
+ if (user == null || !user.DisplayMissingEpisodes)
{
query.IsMissing = false;
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 2996104e7..f467a6038 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -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));
}
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 313d27ce6..5905c25a5 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -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();
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 2368706fe..d4e025a43 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -8,7 +8,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Controller</PackageId>
- <VersionPrefix>10.8.0</VersionPrefix>
+ <VersionPrefix>10.9.0</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 6fb5c8874..17e410fe1 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -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)
@@ -930,6 +931,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 +1152,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 +1172,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 +1309,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 +1328,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 +1350,10 @@ namespace MediaBrowser.Controller.MediaEncoding
{
intelLowPowerHwEncoding = encodingOptions.EnableIntelLowPowerHevcHwEncoder;
}
+ else
+ {
+ enableWaFori915Hang = false;
+ }
}
if (intelLowPowerHwEncoding)
@@ -1332,6 +1361,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 +1747,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 +1795,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 +1980,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 +2061,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 +4540,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
@@ -4967,7 +5006,7 @@ namespace MediaBrowser.Controller.MediaEncoding
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 +5535,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++;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
index 4483cf708..5bf83a9e3 100644
--- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
@@ -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);
}
}
diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
index 2c6483ae2..43c7ce370 100644
--- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
@@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Controller.Net
{
- public interface IWebSocketConnection
+ public interface IWebSocketConnection : IAsyncDisposable, IDisposable
{
/// <summary>
/// Occurs when [closed].
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index c2ca23386..b4520ae48 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -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);
+ }
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
index a0c38b309..216494556 100644
--- a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
+++ b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
@@ -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);
}
diff --git a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs
index 2f38d6adc..619294e95 100644
--- a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs
+++ b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs
@@ -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>
diff --git a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
index f49876cca..3a7685f34 100644
--- a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
+++ b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
@@ -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)