aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api')
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs15
-rw-r--r--Jellyfin.Api/Controllers/SubtitleController.cs5
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs5
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs2
-rw-r--r--Jellyfin.Api/Helpers/DynamicHlsHelper.cs2
-rw-r--r--Jellyfin.Api/Helpers/TranscodingJobHelper.cs2
-rw-r--r--Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs2
-rw-r--r--Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs2
-rw-r--r--Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs6
-rw-r--r--Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs18
-rw-r--r--Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs16
11 files changed, 58 insertions, 17 deletions
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index ce684e457c..065a4ce5c6 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -1651,7 +1651,7 @@ public class DynamicHlsController : BaseJellyfinApiController
_encodingHelper.GetInputArgument(state, _encodingOptions, segmentContainer),
threads,
mapArgs,
- GetVideoArguments(state, startNumber, isEventPlaylist),
+ GetVideoArguments(state, startNumber, isEventPlaylist, segmentContainer),
GetAudioArguments(state),
maxMuxingQueueSize,
state.SegmentLength.ToString(CultureInfo.InvariantCulture),
@@ -1703,19 +1703,18 @@ public class DynamicHlsController : BaseJellyfinApiController
}
var audioCodec = _encodingHelper.GetAudioEncoder(state);
+ var bitStreamArgs = EncodingHelper.GetAudioBitStreamArguments(state, state.Request.SegmentContainer, state.MediaSource.Container);
if (!state.IsOutputVideo)
{
if (EncodingHelper.IsCopyCodec(audioCodec))
{
- var bitStreamArgs = EncodingHelper.GetAudioBitStreamArguments(state, state.Request.SegmentContainer, state.MediaSource.Container);
-
return "-acodec copy -strict -2" + bitStreamArgs;
}
var audioTranscodeParams = string.Empty;
- audioTranscodeParams += "-acodec " + audioCodec;
+ audioTranscodeParams += "-acodec " + audioCodec + bitStreamArgs;
var audioBitrate = state.OutputAudioBitrate;
var audioChannels = state.OutputAudioChannels;
@@ -1761,7 +1760,6 @@ public class DynamicHlsController : BaseJellyfinApiController
if (EncodingHelper.IsCopyCodec(audioCodec))
{
var videoCodec = _encodingHelper.GetVideoEncoder(state, _encodingOptions);
- var bitStreamArgs = EncodingHelper.GetAudioBitStreamArguments(state, state.Request.SegmentContainer, state.MediaSource.Container);
var copyArgs = "-codec:a:0 copy" + bitStreamArgs + strictArgs;
if (EncodingHelper.IsCopyCodec(videoCodec) && state.EnableBreakOnNonKeyFrames(videoCodec))
@@ -1772,7 +1770,7 @@ public class DynamicHlsController : BaseJellyfinApiController
return copyArgs;
}
- var args = "-codec:a:0 " + audioCodec + strictArgs;
+ var args = "-codec:a:0 " + audioCodec + bitStreamArgs + strictArgs;
var channels = state.OutputAudioChannels;
@@ -1816,8 +1814,9 @@ public class DynamicHlsController : BaseJellyfinApiController
/// <param name="state">The <see cref="StreamState"/>.</param>
/// <param name="startNumber">The first number in the hls sequence.</param>
/// <param name="isEventPlaylist">Whether the playlist is EVENT or VOD.</param>
+ /// <param name="segmentContainer">The segment container.</param>
/// <returns>The command line arguments for video transcoding.</returns>
- private string GetVideoArguments(StreamState state, int startNumber, bool isEventPlaylist)
+ private string GetVideoArguments(StreamState state, int startNumber, bool isEventPlaylist, string segmentContainer)
{
if (state.VideoStream is null)
{
@@ -1909,7 +1908,7 @@ public class DynamicHlsController : BaseJellyfinApiController
}
// TODO why was this not enabled for VOD?
- if (isEventPlaylist)
+ if (isEventPlaylist && string.Equals(segmentContainer, "ts", StringComparison.OrdinalIgnoreCase))
{
args += " -flags -global_header";
}
diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs
index b3e9d62972..7d02550b68 100644
--- a/Jellyfin.Api/Controllers/SubtitleController.cs
+++ b/Jellyfin.Api/Controllers/SubtitleController.cs
@@ -90,7 +90,7 @@ public class SubtitleController : BaseJellyfinApiController
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public ActionResult<Task> DeleteSubtitle(
+ public async Task<ActionResult> DeleteSubtitle(
[FromRoute, Required] Guid itemId,
[FromRoute, Required] int index)
{
@@ -101,7 +101,7 @@ public class SubtitleController : BaseJellyfinApiController
return NotFound();
}
- _subtitleManager.DeleteSubtitles(item, index);
+ await _subtitleManager.DeleteSubtitles(item, index).ConfigureAwait(false);
return NoContent();
}
@@ -416,6 +416,7 @@ public class SubtitleController : BaseJellyfinApiController
Format = body.Format,
Language = body.Language,
IsForced = body.IsForced,
+ IsHearingImpaired = body.IsHearingImpaired,
Stream = memoryStream
}).ConfigureAwait(false);
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index 7d23281f2c..bdbbd1e0db 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -68,7 +68,8 @@ public class TvShowsController : BaseJellyfinApiController
/// <param name="nextUpDateCutoff">Optional. Starting date of shows to show in Next Up section.</param>
/// <param name="enableTotalRecordCount">Whether to enable the total records count. Defaults to true.</param>
/// <param name="disableFirstEpisode">Whether to disable sending the first episode in a series as next up.</param>
- /// <param name="enableRewatching">Whether to include watched episode in next up results.</param>
+ /// <param name="enableResumable">Whether to include resumable episodes in next up results.</param>
+ /// <param name="enableRewatching">Whether to include watched episodes in next up results.</param>
/// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the next up episodes.</returns>
[HttpGet("NextUp")]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -86,6 +87,7 @@ public class TvShowsController : BaseJellyfinApiController
[FromQuery] DateTime? nextUpDateCutoff,
[FromQuery] bool enableTotalRecordCount = true,
[FromQuery] bool disableFirstEpisode = false,
+ [FromQuery] bool enableResumable = true,
[FromQuery] bool enableRewatching = false)
{
userId = RequestHelpers.GetUserId(User, userId);
@@ -104,6 +106,7 @@ public class TvShowsController : BaseJellyfinApiController
EnableTotalRecordCount = enableTotalRecordCount,
DisableFirstEpisode = disableFirstEpisode,
NextUpDateCutoff = nextUpDateCutoff ?? DateTime.MinValue,
+ EnableResumable = enableResumable,
EnableRewatching = enableRewatching
},
options);
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index 4f61af35e0..1be40111dd 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -494,7 +494,7 @@ public class UserController : BaseJellyfinApiController
var isLocal = HttpContext.IsLocal()
|| _networkManager.IsInLocalNetwork(ip);
- if (isLocal)
+ if (!isLocal)
{
_logger.LogWarning("Password reset process initiated from outside the local network with IP: {IP}", ip);
}
diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
index 63667e7e69..fe602fba39 100644
--- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
+++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
@@ -693,7 +693,7 @@ public class DynamicHlsHelper
// Currently we only transcode to 8 bits AV1
int bitDepth = 8;
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
- && state.VideoStream != null
+ && state.VideoStream is not null
&& state.VideoStream.BitDepth.HasValue)
{
bitDepth = state.VideoStream.BitDepth.Value;
diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
index cee8e0f9be..73ebb396d0 100644
--- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
+++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
@@ -620,7 +620,7 @@ public class TranscodingJobHelper : IDisposable
state.TranscodingJob = transcodingJob;
// Important - don't await the log task or we won't be able to kill FFmpeg when the user stops playback
- _ = new JobLogger(_logger).StartStreamingLog(state, process.StandardError.BaseStream, logStream);
+ _ = new JobLogger(_logger).StartStreamingLog(state, process.StandardError, logStream);
// Wait for the file to exist before proceeding
var ffmpegTargetFile = state.WaitForPath ?? outputPath;
diff --git a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
index a34fd01d5e..3e3604b2ad 100644
--- a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
+++ b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
@@ -77,7 +77,7 @@ public class CommaDelimitedArrayModelBinder : IModelBinder
var typedValueIndex = 0;
for (var i = 0; i < parsedValues.Length; i++)
{
- if (parsedValues[i] != null)
+ if (parsedValues[i] is not null)
{
typedValues.SetValue(parsedValues[i], typedValueIndex);
typedValueIndex++;
diff --git a/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs b/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs
index cb9a829557..ae9f0a8cdb 100644
--- a/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs
+++ b/Jellyfin.Api/ModelBinders/PipeDelimitedArrayModelBinder.cs
@@ -77,7 +77,7 @@ public class PipeDelimitedArrayModelBinder : IModelBinder
var typedValueIndex = 0;
for (var i = 0; i < parsedValues.Length; i++)
{
- if (parsedValues[i] != null)
+ if (parsedValues[i] is not null)
{
typedValues.SetValue(parsedValues[i], typedValueIndex);
typedValueIndex++;
diff --git a/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs b/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs
index 3c903ea6b5..2c45e704bc 100644
--- a/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs
+++ b/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs
@@ -26,6 +26,12 @@ public class UploadSubtitleDto
public bool IsForced { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether the subtitle is for hearing impaired.
+ /// </summary>
+ [Required]
+ public bool IsHearingImpaired { get; set; }
+
+ /// <summary>
/// Gets or sets the subtitle data.
/// </summary>
[Required]
diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
index 4a5e0ecd4f..5b90d65d84 100644
--- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
@@ -1,6 +1,8 @@
using System;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
+using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Session;
@@ -9,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace Jellyfin.Api.WebSocketListeners;
/// <summary>
-/// Class SessionInfoWebSocketListener.
+/// Class ActivityLogWebSocketListener.
/// </summary>
public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState>
{
@@ -56,6 +58,20 @@ public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<Activi
base.Dispose(dispose);
}
+ /// <summary>
+ /// Starts sending messages over an activity log web socket.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ protected override void Start(WebSocketMessageInfo message)
+ {
+ if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+ {
+ throw new AuthenticationException("Only admin users can retrieve the activity log.");
+ }
+
+ base.Start(message);
+ }
+
private async void OnEntryCreated(object? sender, GenericEventArgs<ActivityLogEntry> e)
{
await SendData(true).ConfigureAwait(false);
diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
index 0d8bf205c9..b403ff46d0 100644
--- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
@@ -66,6 +68,20 @@ public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnume
base.Dispose(dispose);
}
+ /// <summary>
+ /// Starts sending messages over a session info web socket.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ protected override void Start(WebSocketMessageInfo message)
+ {
+ if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+ {
+ throw new AuthenticationException("Only admin users can subscribe to session information.");
+ }
+
+ base.Start(message);
+ }
+
private async void OnSessionManagerSessionActivity(object? sender, SessionEventArgs e)
{
await SendData(false).ConfigureAwait(false);