using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Extensions; using MediaBrowser.Common.Api; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Streaming; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers; /// /// The videos controller. /// public class VideosController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; private readonly ITranscodeManager _transcodeManager; private readonly IHttpClientFactory _httpClientFactory; private readonly EncodingHelper _encodingHelper; private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of . public VideosController( ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, ITranscodeManager transcodeManager, IHttpClientFactory httpClientFactory, EncodingHelper encodingHelper) { _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; _transcodeManager = transcodeManager; _httpClientFactory = httpClientFactory; _encodingHelper = encodingHelper; } /// /// Gets additional parts for a video. /// /// The item id. /// Optional. Filter by user id, and attach user data. /// Additional parts returned. /// A with the parts. [HttpGet("{itemId}/AdditionalParts")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId) { userId = RequestHelpers.GetUserId(User, userId); var user = userId.IsNullOrEmpty() ? null : _userManager.GetUserById(userId.Value); var item = itemId.IsEmpty() ? (userId.IsNullOrEmpty() ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder()) : _libraryManager.GetItemById(itemId, user); if (item is null) { return NotFound(); } var dtoOptions = new DtoOptions(); dtoOptions = dtoOptions.AddClientFields(User); BaseItemDto[] items; if (item is Video video) { items = video.GetAdditionalParts() .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video)) .ToArray(); } else { items = Array.Empty(); } var result = new QueryResult(items); return result; } /// /// Removes alternate video sources. /// /// The item id. /// Alternate sources deleted. /// Video not found. /// A indicating success, or a if the video doesn't exist. [HttpDelete("{itemId}/AlternateSources")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteAlternateSources([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById