aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers/SessionController.cs
diff options
context:
space:
mode:
authorJoshua M. Boniface <joshua@boniface.me>2021-08-18 02:46:59 -0400
committerGitHub <noreply@github.com>2021-08-18 02:46:59 -0400
commit72d3f7020ad80ce1a53eeae8c5d57abeb22a4679 (patch)
treedd43e663838cdc7d99a4af565523df58ae23c856 /Jellyfin.Api/Controllers/SessionController.cs
parent7aef0fce444e6d8e06386553ec7ea1401a01bbb1 (diff)
parente5cbafdb6b47377052e0d638908ef96e30a997d6 (diff)
Merge branch 'master' into patch-2
Diffstat (limited to 'Jellyfin.Api/Controllers/SessionController.cs')
-rw-r--r--Jellyfin.Api/Controllers/SessionController.cs113
1 files changed, 61 insertions, 52 deletions
diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs
index ba8d51598..7bd0b6918 100644
--- a/Jellyfin.Api/Controllers/SessionController.cs
+++ b/Jellyfin.Api/Controllers/SessionController.cs
@@ -1,5 +1,3 @@
-#pragma warning disable CA1801
-
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -7,6 +5,8 @@ using System.Linq;
using System.Threading;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
+using Jellyfin.Api.ModelBinders;
+using Jellyfin.Api.Models.SessionDtos;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
@@ -125,10 +125,10 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult DisplayContent(
- [FromRoute, Required] string? sessionId,
- [FromQuery, Required] string? itemType,
- [FromQuery, Required] string? itemId,
- [FromQuery, Required] string? itemName)
+ [FromRoute, Required] string sessionId,
+ [FromQuery, Required] string itemType,
+ [FromQuery, Required] string itemId,
+ [FromQuery, Required] string itemName)
{
var command = new BrowseRequest
{
@@ -150,25 +150,37 @@ namespace Jellyfin.Api.Controllers
/// Instructs a session to play an item.
/// </summary>
/// <param name="sessionId">The session id.</param>
+ /// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
/// <param name="itemIds">The ids of the items to play, comma delimited.</param>
/// <param name="startPositionTicks">The starting position of the first item.</param>
- /// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
+ /// <param name="mediaSourceId">Optional. The media source id.</param>
+ /// <param name="audioStreamIndex">Optional. The index of the audio stream to play.</param>
+ /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to play.</param>
+ /// <param name="startIndex">Optional. The start index.</param>
/// <response code="204">Instruction sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Sessions/{sessionId}/Playing")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult Play(
- [FromRoute, Required] string? sessionId,
- [FromQuery] Guid[] itemIds,
+ [FromRoute, Required] string sessionId,
+ [FromQuery, Required] PlayCommand playCommand,
+ [FromQuery, Required, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] itemIds,
[FromQuery] long? startPositionTicks,
- [FromQuery] PlayCommand playCommand)
+ [FromQuery] string? mediaSourceId,
+ [FromQuery] int? audioStreamIndex,
+ [FromQuery] int? subtitleStreamIndex,
+ [FromQuery] int? startIndex)
{
var playRequest = new PlayRequest
{
ItemIds = itemIds,
StartPositionTicks = startPositionTicks,
- PlayCommand = playCommand
+ PlayCommand = playCommand,
+ MediaSourceId = mediaSourceId,
+ AudioStreamIndex = audioStreamIndex,
+ SubtitleStreamIndex = subtitleStreamIndex,
+ StartIndex = startIndex
};
_sessionManager.SendPlayCommand(
@@ -184,20 +196,29 @@ namespace Jellyfin.Api.Controllers
/// Issues a playstate command to a client.
/// </summary>
/// <param name="sessionId">The session id.</param>
- /// <param name="playstateRequest">The <see cref="PlaystateRequest"/>.</param>
+ /// <param name="command">The <see cref="PlaystateCommand"/>.</param>
+ /// <param name="seekPositionTicks">The optional position ticks.</param>
+ /// <param name="controllingUserId">The optional controlling user id.</param>
/// <response code="204">Playstate command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Sessions/{sessionId}/Playing/{command}")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendPlaystateCommand(
- [FromRoute, Required] string? sessionId,
- [FromBody] PlaystateRequest playstateRequest)
+ [FromRoute, Required] string sessionId,
+ [FromRoute, Required] PlaystateCommand command,
+ [FromQuery] long? seekPositionTicks,
+ [FromQuery] string? controllingUserId)
{
_sessionManager.SendPlaystateCommand(
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
sessionId,
- playstateRequest,
+ new PlaystateRequest()
+ {
+ Command = command,
+ ControllingUserId = controllingUserId,
+ SeekPositionTicks = seekPositionTicks,
+ },
CancellationToken.None);
return NoContent();
@@ -214,19 +235,13 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendSystemCommand(
- [FromRoute, Required] string? sessionId,
- [FromRoute, Required] string? command)
+ [FromRoute, Required] string sessionId,
+ [FromRoute, Required] GeneralCommandType command)
{
- var name = command;
- if (Enum.TryParse(name, true, out GeneralCommandType commandType))
- {
- name = commandType.ToString();
- }
-
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
var generalCommand = new GeneralCommand
{
- Name = name,
+ Name = command,
ControllingUserId = currentSession.UserId
};
@@ -246,8 +261,8 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendGeneralCommand(
- [FromRoute, Required] string? sessionId,
- [FromRoute, Required] string? command)
+ [FromRoute, Required] string sessionId,
+ [FromRoute, Required] GeneralCommandType command)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
@@ -273,7 +288,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendFullGeneralCommand(
- [FromRoute, Required] string? sessionId,
+ [FromRoute, Required] string sessionId,
[FromBody, Required] GeneralCommand command)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
@@ -298,26 +313,20 @@ namespace Jellyfin.Api.Controllers
/// Issues a command to a client to display a message to the user.
/// </summary>
/// <param name="sessionId">The session id.</param>
- /// <param name="text">The message test.</param>
- /// <param name="header">The message header.</param>
- /// <param name="timeoutMs">The message timeout. If omitted the user will have to confirm viewing the message.</param>
+ /// <param name="command">The <see cref="MessageCommand" /> object containing Header, Message Text, and TimeoutMs.</param>
/// <response code="204">Message sent.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Sessions/{sessionId}/Message")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendMessageCommand(
- [FromRoute, Required] string? sessionId,
- [FromQuery, Required] string? text,
- [FromQuery, Required] string? header,
- [FromQuery] long? timeoutMs)
+ [FromRoute, Required] string sessionId,
+ [FromBody, Required] MessageCommand command)
{
- var command = new MessageCommand
+ if (string.IsNullOrWhiteSpace(command.Header))
{
- Header = string.IsNullOrEmpty(header) ? "Message from Server" : header,
- TimeoutMs = timeoutMs,
- Text = text
- };
+ command.Header = "Message from Server";
+ }
_sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, sessionId, command, CancellationToken.None);
@@ -335,8 +344,8 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult AddUserToSession(
- [FromRoute, Required] string? sessionId,
- [FromRoute] Guid userId)
+ [FromRoute, Required] string sessionId,
+ [FromRoute, Required] Guid userId)
{
_sessionManager.AddAdditionalUser(sessionId, userId);
return NoContent();
@@ -353,8 +362,8 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RemoveUserFromSession(
- [FromRoute] string? sessionId,
- [FromRoute] Guid userId)
+ [FromRoute, Required] string sessionId,
+ [FromRoute, Required] Guid userId)
{
_sessionManager.RemoveAdditionalUser(sessionId, userId);
return NoContent();
@@ -375,9 +384,9 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostCapabilities(
- [FromQuery, Required] string? id,
- [FromQuery] string? playableMediaTypes,
- [FromQuery] string? supportedCommands,
+ [FromQuery] string? id,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] playableMediaTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] GeneralCommandType[] supportedCommands,
[FromQuery] bool supportsMediaControl = false,
[FromQuery] bool supportsSync = false,
[FromQuery] bool supportsPersistentIdentifier = true)
@@ -389,8 +398,8 @@ namespace Jellyfin.Api.Controllers
_sessionManager.ReportCapabilities(id, new ClientCapabilities
{
- PlayableMediaTypes = RequestHelpers.Split(playableMediaTypes, ',', true),
- SupportedCommands = RequestHelpers.Split(supportedCommands, ',', true),
+ PlayableMediaTypes = playableMediaTypes,
+ SupportedCommands = supportedCommands,
SupportsMediaControl = supportsMediaControl,
SupportsSync = supportsSync,
SupportsPersistentIdentifier = supportsPersistentIdentifier
@@ -410,14 +419,14 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostFullCapabilities(
[FromQuery] string? id,
- [FromBody, Required] ClientCapabilities capabilities)
+ [FromBody, Required] ClientCapabilitiesDto capabilities)
{
if (string.IsNullOrWhiteSpace(id))
{
id = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id;
}
- _sessionManager.ReportCapabilities(id, capabilities);
+ _sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities());
return NoContent();
}
@@ -434,9 +443,9 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult ReportViewing(
[FromQuery] string? sessionId,
- [FromQuery] string? itemId)
+ [FromQuery, Required] string? itemId)
{
- string session = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id;
+ string session = sessionId ?? RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id;
_sessionManager.ReportNowViewingItem(session, itemId);
return NoContent();