From 01fd42cf9555d85469c07ce3d0c0e5842359eb2b Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 9 Nov 2023 14:42:37 -0500 Subject: [PATCH] Remove DLNA API code --- .../Attributes/DlnaEnabledAttribute.cs | 25 -- .../Attributes/HttpSubscribeAttribute.cs | 29 -- .../Attributes/HttpUnsubscribeAttribute.cs | 29 -- Jellyfin.Api/Controllers/AudioController.cs | 7 +- Jellyfin.Api/Controllers/DlnaController.cs | 133 ------- .../Controllers/DlnaServerController.cs | 330 ------------------ .../Controllers/DynamicHlsController.cs | 37 +- Jellyfin.Api/Controllers/VideosController.cs | 25 +- Jellyfin.Api/Helpers/AudioHelper.cs | 22 -- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 12 - Jellyfin.Api/Helpers/StreamingHelpers.cs | 239 +------------ Jellyfin.Api/Jellyfin.Api.csproj | 2 +- .../Models/StreamingDtos/StreamState.cs | 10 - .../StreamingDtos/StreamingRequestDto.cs | 5 - 14 files changed, 13 insertions(+), 892 deletions(-) delete mode 100644 Jellyfin.Api/Attributes/DlnaEnabledAttribute.cs delete mode 100644 Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs delete mode 100644 Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs delete mode 100644 Jellyfin.Api/Controllers/DlnaController.cs delete mode 100644 Jellyfin.Api/Controllers/DlnaServerController.cs diff --git a/Jellyfin.Api/Attributes/DlnaEnabledAttribute.cs b/Jellyfin.Api/Attributes/DlnaEnabledAttribute.cs deleted file mode 100644 index d3a6ac9c81..0000000000 --- a/Jellyfin.Api/Attributes/DlnaEnabledAttribute.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Emby.Dlna; -using MediaBrowser.Controller.Configuration; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.DependencyInjection; - -namespace Jellyfin.Api.Attributes; - -/// -public sealed class DlnaEnabledAttribute : ActionFilterAttribute -{ - /// - public override void OnActionExecuting(ActionExecutingContext context) - { - var serverConfigurationManager = context.HttpContext.RequestServices.GetRequiredService(); - - var enabled = serverConfigurationManager.GetDlnaConfiguration().EnableServer; - - if (!enabled) - { - context.Result = new StatusCodeResult(StatusCodes.Status503ServiceUnavailable); - } - } -} diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs deleted file mode 100644 index cbd32ed822..0000000000 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Routing; - -namespace Jellyfin.Api.Attributes; - -/// -/// Identifies an action that supports the HTTP GET method. -/// -public sealed class HttpSubscribeAttribute : HttpMethodAttribute -{ - private static readonly IEnumerable _supportedMethods = new[] { "SUBSCRIBE" }; - - /// - /// Initializes a new instance of the class. - /// - public HttpSubscribeAttribute() - : base(_supportedMethods) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The route template. May not be null. - public HttpSubscribeAttribute(string template) - : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template); -} diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs deleted file mode 100644 index f4a6dcdaf9..0000000000 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Routing; - -namespace Jellyfin.Api.Attributes; - -/// -/// Identifies an action that supports the HTTP GET method. -/// -public sealed class HttpUnsubscribeAttribute : HttpMethodAttribute -{ - private static readonly IEnumerable _supportedMethods = new[] { "UNSUBSCRIBE" }; - - /// - /// Initializes a new instance of the class. - /// - public HttpUnsubscribeAttribute() - : base(_supportedMethods) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The route template. May not be null. - public HttpUnsubscribeAttribute(string template) - : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template); -} diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 968193a6f8..5bc5330861 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -15,7 +15,6 @@ namespace Jellyfin.Api.Controllers; /// /// The audio controller. /// -// TODO: In order to authenticate this in the future, Dlna playback will require updating public class AudioController : BaseJellyfinApiController { private readonly AudioHelper _audioHelper; @@ -95,7 +94,7 @@ public class AudioController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -147,7 +146,6 @@ public class AudioController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -260,7 +258,7 @@ public class AudioController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -312,7 +310,6 @@ public class AudioController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, diff --git a/Jellyfin.Api/Controllers/DlnaController.cs b/Jellyfin.Api/Controllers/DlnaController.cs deleted file mode 100644 index 79a41ce3b4..0000000000 --- a/Jellyfin.Api/Controllers/DlnaController.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using Jellyfin.Api.Constants; -using MediaBrowser.Common.Api; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Model.Dlna; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Jellyfin.Api.Controllers; - -/// -/// Dlna Controller. -/// -[Authorize(Policy = Policies.RequiresElevation)] -public class DlnaController : BaseJellyfinApiController -{ - private readonly IDlnaManager _dlnaManager; - - /// - /// Initializes a new instance of the class. - /// - /// Instance of the interface. - public DlnaController(IDlnaManager dlnaManager) - { - _dlnaManager = dlnaManager; - } - - /// - /// Get profile infos. - /// - /// Device profile infos returned. - /// An containing the device profile infos. - [HttpGet("ProfileInfos")] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetProfileInfos() - { - return Ok(_dlnaManager.GetProfileInfos()); - } - - /// - /// Gets the default profile. - /// - /// Default device profile returned. - /// An containing the default profile. - [HttpGet("Profiles/Default")] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetDefaultProfile() - { - return _dlnaManager.GetDefaultProfile(); - } - - /// - /// Gets a single profile. - /// - /// Profile Id. - /// Device profile returned. - /// Device profile not found. - /// An containing the profile on success, or a if device profile not found. - [HttpGet("Profiles/{profileId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetProfile([FromRoute, Required] string profileId) - { - var profile = _dlnaManager.GetProfile(profileId); - if (profile is null) - { - return NotFound(); - } - - return profile; - } - - /// - /// Deletes a profile. - /// - /// Profile id. - /// Device profile deleted. - /// Device profile not found. - /// A on success, or a if profile not found. - [HttpDelete("Profiles/{profileId}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteProfile([FromRoute, Required] string profileId) - { - var existingDeviceProfile = _dlnaManager.GetProfile(profileId); - if (existingDeviceProfile is null) - { - return NotFound(); - } - - _dlnaManager.DeleteProfile(profileId); - return NoContent(); - } - - /// - /// Creates a profile. - /// - /// Device profile. - /// Device profile created. - /// A . - [HttpPost("Profiles")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult CreateProfile([FromBody] DeviceProfile deviceProfile) - { - _dlnaManager.CreateProfile(deviceProfile); - return NoContent(); - } - - /// - /// Updates a profile. - /// - /// Profile id. - /// Device profile. - /// Device profile updated. - /// Device profile not found. - /// A on success, or a if profile not found. - [HttpPost("Profiles/{profileId}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateProfile([FromRoute, Required] string profileId, [FromBody] DeviceProfile deviceProfile) - { - var existingDeviceProfile = _dlnaManager.GetProfile(profileId); - if (existingDeviceProfile is null) - { - return NotFound(); - } - - _dlnaManager.UpdateProfile(profileId, deviceProfile); - return NoContent(); - } -} diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs deleted file mode 100644 index ce8d910ffd..0000000000 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ /dev/null @@ -1,330 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Net.Mime; -using System.Threading.Tasks; -using Emby.Dlna; -using Jellyfin.Api.Attributes; -using Jellyfin.Api.Constants; -using MediaBrowser.Common.Api; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Model.Net; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace Jellyfin.Api.Controllers; - -/// -/// Dlna Server Controller. -/// -[Route("Dlna")] -[DlnaEnabled] -[Authorize(Policy = Policies.AnonymousLanAccessPolicy)] -public class DlnaServerController : BaseJellyfinApiController -{ - private readonly IDlnaManager _dlnaManager; - private readonly IContentDirectory _contentDirectory; - private readonly IConnectionManager _connectionManager; - private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar; - - /// - /// Initializes a new instance of the class. - /// - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - public DlnaServerController( - IDlnaManager dlnaManager, - IContentDirectory contentDirectory, - IConnectionManager connectionManager, - IMediaReceiverRegistrar mediaReceiverRegistrar) - { - _dlnaManager = dlnaManager; - _contentDirectory = contentDirectory; - _connectionManager = connectionManager; - _mediaReceiverRegistrar = mediaReceiverRegistrar; - } - - /// - /// Get Description Xml. - /// - /// Server UUID. - /// Description xml returned. - /// DLNA is disabled. - /// An containing the description xml. - [HttpGet("{serverId}/description")] - [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public ActionResult GetDescriptionXml([FromRoute, Required] string serverId) - { - var url = GetAbsoluteUri(); - var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase)); - var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers, serverId, serverAddress); - return Ok(xml); - } - - /// - /// Gets Dlna content directory xml. - /// - /// Server UUID. - /// Dlna content directory returned. - /// DLNA is disabled. - /// An containing the dlna content directory xml. - [HttpGet("{serverId}/ContentDirectory")] - [HttpGet("{serverId}/ContentDirectory/ContentDirectory", Name = "GetContentDirectory_2")] - [HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml", Name = "GetContentDirectory_3")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetContentDirectory([FromRoute, Required] string serverId) - { - return Ok(_contentDirectory.GetServiceXml()); - } - - /// - /// Gets Dlna media receiver registrar xml. - /// - /// Server UUID. - /// Dlna media receiver registrar xml returned. - /// DLNA is disabled. - /// Dlna media receiver registrar xml. - [HttpGet("{serverId}/MediaReceiverRegistrar")] - [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar", Name = "GetMediaReceiverRegistrar_2")] - [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml", Name = "GetMediaReceiverRegistrar_3")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetMediaReceiverRegistrar([FromRoute, Required] string serverId) - { - return Ok(_mediaReceiverRegistrar.GetServiceXml()); - } - - /// - /// Gets Dlna media receiver registrar xml. - /// - /// Server UUID. - /// Dlna media receiver registrar xml returned. - /// DLNA is disabled. - /// Dlna media receiver registrar xml. - [HttpGet("{serverId}/ConnectionManager")] - [HttpGet("{serverId}/ConnectionManager/ConnectionManager", Name = "GetConnectionManager_2")] - [HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml", Name = "GetConnectionManager_3")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetConnectionManager([FromRoute, Required] string serverId) - { - return Ok(_connectionManager.GetServiceXml()); - } - - /// - /// Process a content directory control request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Control response. - [HttpPost("{serverId}/ContentDirectory/Control")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public async Task> ProcessContentDirectoryControlRequest([FromRoute, Required] string serverId) - { - return await ProcessControlRequestInternalAsync(serverId, Request.Body, _contentDirectory).ConfigureAwait(false); - } - - /// - /// Process a connection manager control request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Control response. - [HttpPost("{serverId}/ConnectionManager/Control")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public async Task> ProcessConnectionManagerControlRequest([FromRoute, Required] string serverId) - { - return await ProcessControlRequestInternalAsync(serverId, Request.Body, _connectionManager).ConfigureAwait(false); - } - - /// - /// Process a media receiver registrar control request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Control response. - [HttpPost("{serverId}/MediaReceiverRegistrar/Control")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public async Task> ProcessMediaReceiverRegistrarControlRequest([FromRoute, Required] string serverId) - { - return await ProcessControlRequestInternalAsync(serverId, Request.Body, _mediaReceiverRegistrar).ConfigureAwait(false); - } - - /// - /// Processes an event subscription request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Event subscription response. - [HttpSubscribe("{serverId}/MediaReceiverRegistrar/Events")] - [HttpUnsubscribe("{serverId}/MediaReceiverRegistrar/Events")] - [ApiExplorerSettings(IgnoreApi = true)] // Ignore in openapi docs - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public ActionResult ProcessMediaReceiverRegistrarEventRequest(string serverId) - { - return ProcessEventRequest(_mediaReceiverRegistrar); - } - - /// - /// Processes an event subscription request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Event subscription response. - [HttpSubscribe("{serverId}/ContentDirectory/Events")] - [HttpUnsubscribe("{serverId}/ContentDirectory/Events")] - [ApiExplorerSettings(IgnoreApi = true)] // Ignore in openapi docs - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public ActionResult ProcessContentDirectoryEventRequest(string serverId) - { - return ProcessEventRequest(_contentDirectory); - } - - /// - /// Processes an event subscription request. - /// - /// Server UUID. - /// Request processed. - /// DLNA is disabled. - /// Event subscription response. - [HttpSubscribe("{serverId}/ConnectionManager/Events")] - [HttpUnsubscribe("{serverId}/ConnectionManager/Events")] - [ApiExplorerSettings(IgnoreApi = true)] // Ignore in openapi docs - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [Produces(MediaTypeNames.Text.Xml)] - [ProducesFile(MediaTypeNames.Text.Xml)] - public ActionResult ProcessConnectionManagerEventRequest(string serverId) - { - return ProcessEventRequest(_connectionManager); - } - - /// - /// Gets a server icon. - /// - /// Server UUID. - /// The icon filename. - /// Request processed. - /// Not Found. - /// DLNA is disabled. - /// Icon stream. - [HttpGet("{serverId}/icons/{fileName}")] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [ProducesImageFile] - public ActionResult GetIconId([FromRoute, Required] string serverId, [FromRoute, Required] string fileName) - { - return GetIconInternal(fileName); - } - - /// - /// Gets a server icon. - /// - /// The icon filename. - /// Icon stream. - /// Request processed. - /// Not Found. - /// DLNA is disabled. - [HttpGet("icons/{fileName}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)] - [ProducesImageFile] - public ActionResult GetIcon([FromRoute, Required] string fileName) - { - return GetIconInternal(fileName); - } - - private ActionResult GetIconInternal(string fileName) - { - var icon = _dlnaManager.GetIcon(fileName); - if (icon is null) - { - return NotFound(); - } - - return File(icon.Stream, MimeTypes.GetMimeType(fileName)); - } - - private string GetAbsoluteUri() - { - return $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}"; - } - - private Task ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service) - { - return service.ProcessControlRequestAsync(new ControlRequest(Request.Headers) - { - InputXml = requestStream, - TargetServerUuId = id, - RequestedUrl = GetAbsoluteUri() - }); - } - - private EventSubscriptionResponse ProcessEventRequest(IDlnaEventManager dlnaEventManager) - { - var subscriptionId = Request.Headers["SID"]; - if (string.Equals(Request.Method, "subscribe", StringComparison.OrdinalIgnoreCase)) - { - var notificationType = Request.Headers["NT"]; - var callback = Request.Headers["CALLBACK"]; - var timeoutString = Request.Headers["TIMEOUT"]; - - if (string.IsNullOrEmpty(notificationType)) - { - return dlnaEventManager.RenewEventSubscription( - subscriptionId, - notificationType, - timeoutString, - callback); - } - - return dlnaEventManager.CreateEventSubscription(notificationType, timeoutString, callback); - } - - return dlnaEventManager.CancelEventSubscription(subscriptionId); - } -} diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 38953dc21f..9e9c610cc5 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -17,8 +17,6 @@ using Jellyfin.Extensions; using Jellyfin.MediaEncoding.Hls.Playlist; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Encoder; @@ -49,12 +47,10 @@ public class DynamicHlsController : BaseJellyfinApiController private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; - private readonly IDlnaManager _dlnaManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; - private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly ILogger _logger; private readonly EncodingHelper _encodingHelper; @@ -67,12 +63,10 @@ public class DynamicHlsController : BaseJellyfinApiController /// /// 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 the class. /// Instance of the interface. /// Instance of . @@ -81,12 +75,10 @@ public class DynamicHlsController : BaseJellyfinApiController public DynamicHlsController( ILibraryManager libraryManager, IUserManager userManager, - IDlnaManager dlnaManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, - IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, ILogger logger, DynamicHlsHelper dynamicHlsHelper, @@ -95,12 +87,10 @@ public class DynamicHlsController : BaseJellyfinApiController { _libraryManager = libraryManager; _userManager = userManager; - _dlnaManager = dlnaManager; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; - _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _logger = logger; _dynamicHlsHelper = dynamicHlsHelper; @@ -176,7 +166,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -231,7 +221,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -294,8 +283,6 @@ public class DynamicHlsController : BaseJellyfinApiController _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, TranscodingJobType, cancellationToken) @@ -422,7 +409,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -477,7 +464,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -594,7 +580,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -647,7 +633,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -760,7 +745,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -814,7 +799,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -928,7 +912,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -981,7 +965,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -1105,7 +1088,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -1161,7 +1144,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -1286,7 +1268,7 @@ public class DynamicHlsController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -1341,7 +1323,6 @@ public class DynamicHlsController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -1402,8 +1383,6 @@ public class DynamicHlsController : BaseJellyfinApiController _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, TranscodingJobType, cancellationTokenSource.Token) @@ -1442,8 +1421,6 @@ public class DynamicHlsController : BaseJellyfinApiController _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, TranscodingJobType, cancellationToken) diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 7aa5d01e23..5d9868eb9f 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -16,8 +16,6 @@ using MediaBrowser.Common.Api; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -42,11 +40,9 @@ public class VideosController : BaseJellyfinApiController private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; - private readonly IDlnaManager _dlnaManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; private readonly EncodingHelper _encodingHelper; @@ -59,11 +55,9 @@ public class VideosController : BaseJellyfinApiController /// 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 the class. /// Instance of the interface. /// Instance of . @@ -71,11 +65,9 @@ public class VideosController : BaseJellyfinApiController ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, - IDlnaManager dlnaManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, IHttpClientFactory httpClientFactory, EncodingHelper encodingHelper) @@ -83,11 +75,9 @@ public class VideosController : BaseJellyfinApiController _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; - _dlnaManager = dlnaManager; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; _encodingHelper = encodingHelper; @@ -324,7 +314,7 @@ public class VideosController : BaseJellyfinApiController [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, - [FromQuery] string? deviceProfileId, + [FromQuery, ParameterObsolete] string? deviceProfileId, [FromQuery] string? playSessionId, [FromQuery] string? segmentContainer, [FromQuery] int? segmentLength, @@ -381,7 +371,6 @@ public class VideosController : BaseJellyfinApiController Static = @static ?? false, Params = @params, Tag = tag, - DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, @@ -438,8 +427,6 @@ public class VideosController : BaseJellyfinApiController _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, _transcodingJobType, cancellationTokenSource.Token) @@ -447,8 +434,6 @@ public class VideosController : BaseJellyfinApiController if (@static.HasValue && @static.Value && state.DirectStreamProvider is not null) { - StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager); - var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); if (liveStreamInfo is null) { @@ -463,8 +448,6 @@ public class VideosController : BaseJellyfinApiController // Static remote stream if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http) { - StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager); - var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, HttpContext).ConfigureAwait(false); } @@ -475,12 +458,6 @@ public class VideosController : BaseJellyfinApiController } var outputPath = state.OutputFilePath; - var outputPathExists = System.IO.File.Exists(outputPath); - - var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); - var isTranscodeCached = outputPathExists && transcodingJob is not null; - - StreamingHelpers.AddDlnaHeaders(state, Response.Headers, (@static.HasValue && @static.Value) || isTranscodeCached, state.Request.StartTimeTicks, Request, _dlnaManager); // Static stream if (@static.HasValue && @static.Value) diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 2b18c389d7..926ce99dd8 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -7,8 +7,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.MediaInfo; @@ -23,13 +21,11 @@ namespace Jellyfin.Api.Helpers; /// public class AudioHelper { - private readonly IDlnaManager _dlnaManager; private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContextAccessor; @@ -38,37 +34,31 @@ public class AudioHelper /// /// 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 . /// Instance of the interface. /// Instance of the interface. /// Instance of . public AudioHelper( - IDlnaManager dlnaManager, IUserManager userManager, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor, EncodingHelper encodingHelper) { - _dlnaManager = dlnaManager; _userManager = userManager; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; _httpContextAccessor = httpContextAccessor; @@ -104,8 +94,6 @@ public class AudioHelper _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, transcodingJobType, cancellationTokenSource.Token) @@ -113,8 +101,6 @@ public class AudioHelper if (streamingRequest.Static && state.DirectStreamProvider is not null) { - StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); - var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); if (liveStreamInfo is null) { @@ -129,8 +115,6 @@ public class AudioHelper // Static remote stream if (streamingRequest.Static && state.InputProtocol == MediaProtocol.Http) { - StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); - var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false); } @@ -141,12 +125,6 @@ public class AudioHelper } var outputPath = state.OutputFilePath; - var outputPathExists = File.Exists(outputPath); - - var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); - var isTranscodeCached = outputPathExists && transcodingJob is not null; - - StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, streamingRequest.Static || isTranscodeCached, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); // Static stream if (streamingRequest.Static) diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index a8df628f0d..05f7d44bf0 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -16,8 +16,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Trickplay; @@ -38,11 +36,9 @@ public class DynamicHlsHelper { private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; - private readonly IDlnaManager _dlnaManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; - private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly INetworkManager _networkManager; private readonly ILogger _logger; @@ -55,11 +51,9 @@ public class DynamicHlsHelper /// /// 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 . /// Instance of the interface. /// Instance of the interface. @@ -69,11 +63,9 @@ public class DynamicHlsHelper public DynamicHlsHelper( ILibraryManager libraryManager, IUserManager userManager, - IDlnaManager dlnaManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, - IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, INetworkManager networkManager, ILogger logger, @@ -83,11 +75,9 @@ public class DynamicHlsHelper { _libraryManager = libraryManager; _userManager = userManager; - _dlnaManager = dlnaManager; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; - _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _networkManager = networkManager; _logger = logger; @@ -140,8 +130,6 @@ public class DynamicHlsHelper _serverConfigurationManager, _mediaEncoder, _encodingHelper, - _dlnaManager, - _deviceManager, _transcodingJobHelper, transcodingJobType, cancellationTokenSource.Token) diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 7d9a389312..71c62b2356 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -12,15 +12,12 @@ using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; namespace Jellyfin.Api.Helpers; @@ -41,8 +38,6 @@ public static class StreamingHelpers /// Instance of the interface. /// Instance of the interface. /// Instance of . - /// Instance of the interface. - /// Instance of the interface. /// Initialized . /// The . /// The . @@ -56,21 +51,11 @@ public static class StreamingHelpers IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, EncodingHelper encodingHelper, - IDlnaManager dlnaManager, - IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, TranscodingJobType transcodingJobType, CancellationToken cancellationToken) { var httpRequest = httpContext.Request; - // Parse the DLNA time seek header - if (!streamingRequest.StartTimeTicks.HasValue) - { - var timeSeek = httpRequest.Headers["TimeSeekRange.dlna.org"]; - - streamingRequest.StartTimeTicks = ParseTimeSeekHeader(timeSeek.ToString()); - } - if (!string.IsNullOrWhiteSpace(streamingRequest.Params)) { ParseParams(streamingRequest); @@ -89,16 +74,11 @@ public static class StreamingHelpers streamingRequest.AudioCodec = encodingHelper.InferAudioCodec(url); } - var enableDlnaHeaders = !string.IsNullOrWhiteSpace(streamingRequest.Params) || - streamingRequest.StreamOptions.ContainsKey("dlnaheaders") || - string.Equals(httpRequest.Headers["GetContentFeatures.DLNA.ORG"], "1", StringComparison.OrdinalIgnoreCase); - var state = new StreamState(mediaSourceManager, transcodingJobType, transcodingJobHelper) { Request = streamingRequest, RequestedUrl = url, - UserAgent = httpRequest.Headers[HeaderNames.UserAgent], - EnableDlnaHeaders = enableDlnaHeaders + UserAgent = httpRequest.Headers[HeaderNames.UserAgent] }; var userId = httpContext.User.GetUserId(); @@ -243,8 +223,6 @@ public static class StreamingHelpers } } - ApplyDeviceProfileSettings(state, dlnaManager, deviceManager, httpRequest, streamingRequest.DeviceProfileId, streamingRequest.Static); - var ext = string.IsNullOrWhiteSpace(state.OutputContainer) ? GetOutputFileExtension(state, mediaSource) : ("." + state.OutputContainer); @@ -254,123 +232,6 @@ public static class StreamingHelpers return state; } - /// - /// Adds the dlna headers. - /// - /// The state. - /// The response headers. - /// if set to true [is statically streamed]. - /// The start time in ticks. - /// The . - /// Instance of the interface. - public static void AddDlnaHeaders( - StreamState state, - IHeaderDictionary responseHeaders, - bool isStaticallyStreamed, - long? startTimeTicks, - HttpRequest request, - IDlnaManager dlnaManager) - { - if (!state.EnableDlnaHeaders) - { - return; - } - - var profile = state.DeviceProfile; - - StringValues transferMode = request.Headers["transferMode.dlna.org"]; - responseHeaders.Append("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); - responseHeaders.Append("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); - - if (state.RunTimeTicks.HasValue) - { - if (string.Equals(request.Headers["getMediaInfo.sec"], "1", StringComparison.OrdinalIgnoreCase)) - { - var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds; - responseHeaders.Append("MediaInfo.sec", string.Format( - CultureInfo.InvariantCulture, - "SEC_Duration={0};", - Convert.ToInt32(ms))); - } - - if (!isStaticallyStreamed && profile is not null) - { - AddTimeSeekResponseHeaders(state, responseHeaders, startTimeTicks); - } - } - - profile ??= dlnaManager.GetDefaultProfile(); - - var audioCodec = state.ActualOutputAudioCodec; - - if (!state.IsVideoRequest) - { - responseHeaders.Append("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( - profile, - state.OutputContainer, - audioCodec, - state.OutputAudioBitrate, - state.OutputAudioSampleRate, - state.OutputAudioChannels, - state.OutputAudioBitDepth, - isStaticallyStreamed, - state.RunTimeTicks, - state.TranscodeSeekInfo)); - } - else - { - var videoCodec = state.ActualOutputVideoCodec; - - responseHeaders.Append( - "contentFeatures.dlna.org", - ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoRangeType, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); - } - } - - /// - /// Parses the time seek header. - /// - /// The time seek header string. - /// A nullable representing the seek time in ticks. - private static long? ParseTimeSeekHeader(ReadOnlySpan value) - { - if (value.IsEmpty) - { - return null; - } - - const string npt = "npt="; - if (!value.StartsWith(npt, StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException("Invalid timeseek header"); - } - - var index = value.IndexOf('-'); - value = index == -1 - ? value.Slice(npt.Length) - : value.Slice(npt.Length, index - npt.Length); - if (!value.Contains(':')) - { - // Parses npt times in the format of '417.33' - if (double.TryParse(value, CultureInfo.InvariantCulture, out var seconds)) - { - return TimeSpan.FromSeconds(seconds).Ticks; - } - - throw new ArgumentException("Invalid timeseek header"); - } - - try - { - // Parses npt times in the format of '10:19:25.7' - return TimeSpan.Parse(value, CultureInfo.InvariantCulture).Ticks; - } - catch - { - throw new ArgumentException("Invalid timeseek header"); - } - } - /// /// Parses query parameters as StreamOptions. /// @@ -393,29 +254,6 @@ public static class StreamingHelpers return streamOptions; } - /// - /// Adds the dlna time seek headers to the response. - /// - /// The current . - /// The of the response. - /// The start time in ticks. - private static void AddTimeSeekResponseHeaders(StreamState state, IHeaderDictionary responseHeaders, long? startTimeTicks) - { - var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks!.Value).TotalSeconds.ToString(CultureInfo.InvariantCulture); - var startSeconds = TimeSpan.FromTicks(startTimeTicks ?? 0).TotalSeconds.ToString(CultureInfo.InvariantCulture); - - responseHeaders.Append("TimeSeekRange.dlna.org", string.Format( - CultureInfo.InvariantCulture, - "npt={0}-{1}/{1}", - startSeconds, - runtimeSeconds)); - responseHeaders.Append("X-AvailableSeekRange", string.Format( - CultureInfo.InvariantCulture, - "1 npt={0}-{1}", - startSeconds, - runtimeSeconds)); - } - /// /// Gets the output file extension. /// @@ -519,79 +357,6 @@ public static class StreamingHelpers return Path.Combine(folder, filename + ext); } - private static void ApplyDeviceProfileSettings(StreamState state, IDlnaManager dlnaManager, IDeviceManager deviceManager, HttpRequest request, string? deviceProfileId, bool? @static) - { - if (!string.IsNullOrWhiteSpace(deviceProfileId)) - { - state.DeviceProfile = dlnaManager.GetProfile(deviceProfileId); - - if (state.DeviceProfile is null) - { - var caps = deviceManager.GetCapabilities(deviceProfileId); - state.DeviceProfile = caps is null ? dlnaManager.GetProfile(request.Headers) : caps.DeviceProfile; - } - } - - var profile = state.DeviceProfile; - - if (profile is null) - { - // Don't use settings from the default profile. - // Only use a specific profile if it was requested. - return; - } - - var audioCodec = state.ActualOutputAudioCodec; - var videoCodec = state.ActualOutputVideoCodec; - - var mediaProfile = !state.IsVideoRequest - ? profile.GetAudioMediaProfile(state.OutputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioBitDepth) - : profile.GetVideoMediaProfile( - state.OutputContainer, - audioCodec, - videoCodec, - state.OutputWidth, - state.OutputHeight, - state.TargetVideoBitDepth, - state.OutputVideoBitrate, - state.TargetVideoProfile, - state.TargetVideoRangeType, - state.TargetVideoLevel, - state.TargetFramerate, - state.TargetPacketLength, - state.TargetTimestamp, - state.IsTargetAnamorphic, - state.IsTargetInterlaced, - state.TargetRefFrames, - state.TargetVideoStreamCount, - state.TargetAudioStreamCount, - state.TargetVideoCodecTag, - state.IsTargetAVC); - - if (mediaProfile is not null) - { - state.MimeType = mediaProfile.MimeType; - } - - if (!(@static.HasValue && @static.Value)) - { - var transcodingProfile = !state.IsVideoRequest ? profile.GetAudioTranscodingProfile(state.OutputContainer, audioCodec) : profile.GetVideoTranscodingProfile(state.OutputContainer, audioCodec, videoCodec); - - if (transcodingProfile is not null) - { - state.EstimateContentLength = transcodingProfile.EstimateContentLength; - // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; - state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - - if (state.VideoRequest is not null) - { - state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; - state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; - } - } - } - } - /// /// Parses the parameters. /// @@ -619,7 +384,7 @@ public static class StreamingHelpers switch (i) { case 0: - request.DeviceProfileId = val; + // DeviceProfileId break; case 1: request.DeviceId = val; diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 2473fb288a..d8fd70ac3c 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -18,7 +18,7 @@ - + diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index f249f3bc6c..cc1f9163e5 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -138,16 +138,6 @@ public class StreamState : EncodingJobInfo, IDisposable /// public TranscodeSeekInfo TranscodeSeekInfo { get; set; } - /// - /// Gets or sets a value indicating whether to enable dlna headers. - /// - public bool EnableDlnaHeaders { get; set; } - - /// - /// Gets or sets the device profile. - /// - public DeviceProfile? DeviceProfile { get; set; } - /// /// Gets or sets the transcoding job. /// diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs index 389d6006d0..a357498d4c 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs @@ -7,11 +7,6 @@ namespace Jellyfin.Api.Models.StreamingDtos; /// public class StreamingRequestDto : BaseEncodingJobOptions { - /// - /// Gets or sets the device profile. - /// - public string? DeviceProfileId { get; set; } - /// /// Gets or sets the params. ///