Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56b05f4e2b | |||
| e8148ec0bd | |||
| 77c5c53598 | |||
| d2db73b876 | |||
| 49873c3d7f | |||
| 0b577c8a44 | |||
| 6386606a53 | |||
| cc908210d9 | |||
| dec30ade8f | |||
| 55a8d2555e | |||
| b7c3510da1 | |||
| fd102abd81 | |||
| f8f7767cc5 | |||
| e8436814dc | |||
| 14f63e8f2f | |||
| e764de0c80 | |||
| 40147c9bb7 |
@@ -1,59 +0,0 @@
|
|||||||
parameters:
|
|
||||||
- name: LinuxImage
|
|
||||||
type: string
|
|
||||||
default: "ubuntu-latest"
|
|
||||||
- name: GeneratorVersion
|
|
||||||
type: string
|
|
||||||
default: "5.0.1"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- job: GenerateApiClients
|
|
||||||
displayName: 'Generate Api Clients'
|
|
||||||
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
|
|
||||||
dependsOn: Test
|
|
||||||
|
|
||||||
pool:
|
|
||||||
vmImage: "${{ parameters.LinuxImage }}"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- task: DownloadPipelineArtifact@2
|
|
||||||
displayName: 'Download OpenAPI Spec Artifact'
|
|
||||||
inputs:
|
|
||||||
source: 'current'
|
|
||||||
artifact: "OpenAPI Spec"
|
|
||||||
path: "$(System.ArtifactsDirectory)/openapispec"
|
|
||||||
runVersion: "latest"
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: 'Download OpenApi Generator'
|
|
||||||
inputs:
|
|
||||||
script: "wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/${{ parameters.GeneratorVersion }}/openapi-generator-cli-${{ parameters.GeneratorVersion }}.jar -O openapi-generator-cli.jar"
|
|
||||||
|
|
||||||
## Authenticate with npm registry
|
|
||||||
- task: npmAuthenticate@0
|
|
||||||
inputs:
|
|
||||||
workingFile: ./.npmrc
|
|
||||||
customEndpoint: 'jellyfin-bot for NPM'
|
|
||||||
|
|
||||||
## Generate npm api client
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: 'Build stable typescript axios client'
|
|
||||||
inputs:
|
|
||||||
script: "bash ./apiclient/templates/typescript/axios/generate.sh $(System.ArtifactsDirectory)"
|
|
||||||
|
|
||||||
## Run npm install
|
|
||||||
- task: Npm@1
|
|
||||||
displayName: 'Install npm dependencies'
|
|
||||||
inputs:
|
|
||||||
command: install
|
|
||||||
workingDir: ./apiclient/generated/typescript/axios
|
|
||||||
|
|
||||||
## Publish npm packages
|
|
||||||
- task: Npm@1
|
|
||||||
displayName: 'Publish stable typescript axios client'
|
|
||||||
inputs:
|
|
||||||
command: custom
|
|
||||||
customCommand: publish --access public
|
|
||||||
publishRegistry: useExternalRegistry
|
|
||||||
publishEndpoint: 'jellyfin-bot for NPM'
|
|
||||||
workingDir: ./apiclient/generated/typescript/axios
|
|
||||||
@@ -61,6 +61,3 @@ jobs:
|
|||||||
|
|
||||||
- ${{ if or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) }}:
|
- ${{ if or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) }}:
|
||||||
- template: azure-pipelines-package.yml
|
- template: azure-pipelines-package.yml
|
||||||
|
|
||||||
- ${{ if or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) }}:
|
|
||||||
- template: azure-pipelines-api-client.yml
|
|
||||||
|
|||||||
@@ -144,6 +144,7 @@
|
|||||||
- [nielsvanvelzen](https://github.com/nielsvanvelzen)
|
- [nielsvanvelzen](https://github.com/nielsvanvelzen)
|
||||||
- [skyfrk](https://github.com/skyfrk)
|
- [skyfrk](https://github.com/skyfrk)
|
||||||
- [ianjazz246](https://github.com/ianjazz246)
|
- [ianjazz246](https://github.com/ianjazz246)
|
||||||
|
- [peterspenler](https://github.com/peterspenler)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|||||||
@@ -974,28 +974,15 @@ namespace Emby.Dlna.Didl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove these default values
|
var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, "jpg");
|
||||||
var albumArtUrlInfo = GetImageUrl(
|
|
||||||
imageInfo,
|
|
||||||
_profile.MaxAlbumArtWidth ?? 10000,
|
|
||||||
_profile.MaxAlbumArtHeight ?? 10000,
|
|
||||||
"jpg");
|
|
||||||
|
|
||||||
writer.WriteStartElement("upnp", "albumArtURI", NsUpnp);
|
writer.WriteStartElement("upnp", "albumArtURI", NsUpnp);
|
||||||
if (!string.IsNullOrEmpty(_profile.AlbumArtPn))
|
writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
|
||||||
{
|
writer.WriteString(albumartUrlInfo.url);
|
||||||
writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteString(albumArtUrlInfo.url);
|
|
||||||
writer.WriteFullEndElement();
|
writer.WriteFullEndElement();
|
||||||
|
|
||||||
// TODO: Remove these default values
|
// TOOD: Remove these default values
|
||||||
var iconUrlInfo = GetImageUrl(
|
var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
|
||||||
imageInfo,
|
|
||||||
_profile.MaxIconWidth ?? 48,
|
|
||||||
_profile.MaxIconHeight ?? 48,
|
|
||||||
"jpg");
|
|
||||||
writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
|
writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
|
||||||
|
|
||||||
if (!_profile.EnableAlbumArtInDidl)
|
if (!_profile.EnableAlbumArtInDidl)
|
||||||
@@ -1219,7 +1206,8 @@ namespace Emby.Dlna.Didl
|
|||||||
|
|
||||||
if (width.HasValue && height.HasValue)
|
if (width.HasValue && height.HasValue)
|
||||||
{
|
{
|
||||||
var newSize = DrawingUtils.Resize(new ImageDimensions(width.Value, height.Value), 0, 0, maxWidth, maxHeight);
|
var newSize = DrawingUtils.Resize(
|
||||||
|
new ImageDimensions(width.Value, height.Value), 0, 0, maxWidth, maxHeight);
|
||||||
|
|
||||||
width = newSize.Width;
|
width = newSize.Width;
|
||||||
height = newSize.Height;
|
height = newSize.Height;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Naming</PackageId>
|
<PackageId>Jellyfin.Naming</PackageId>
|
||||||
<VersionPrefix>10.7.3</VersionPrefix>
|
<VersionPrefix>10.7.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -106,8 +106,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
NatUtility.StartDiscovery();
|
NatUtility.StartDiscovery();
|
||||||
|
|
||||||
_timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
|
_timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
|
||||||
|
|
||||||
_deviceDiscovery.DeviceDiscovered += OnDeviceDiscoveryDeviceDiscovered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Stop()
|
private void Stop()
|
||||||
@@ -118,13 +116,6 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
NatUtility.DeviceFound -= OnNatUtilityDeviceFound;
|
NatUtility.DeviceFound -= OnNatUtilityDeviceFound;
|
||||||
|
|
||||||
_timer?.Dispose();
|
_timer?.Dispose();
|
||||||
|
|
||||||
_deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDeviceDiscoveryDeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
|
||||||
{
|
|
||||||
NatUtility.Search(e.Argument.LocalIpAddress, NatProtocol.Upnp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e)
|
private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e)
|
||||||
|
|||||||
@@ -200,11 +200,6 @@ namespace Emby.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
|
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
|
||||||
}
|
}
|
||||||
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding);
|
|
||||||
source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,8 +90,14 @@ namespace Emby.Server.Implementations.Library
|
|||||||
// We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results
|
// We have to ensure that the sub path ends with a directory separator otherwise we'll get weird results
|
||||||
// when the sub path matches a similar but in-complete subpath
|
// when the sub path matches a similar but in-complete subpath
|
||||||
var oldSubPathEndsWithSeparator = subPath[^1] == newDirectorySeparatorChar;
|
var oldSubPathEndsWithSeparator = subPath[^1] == newDirectorySeparatorChar;
|
||||||
if (!path.StartsWith(subPath, StringComparison.OrdinalIgnoreCase)
|
if (!path.StartsWith(subPath, StringComparison.OrdinalIgnoreCase))
|
||||||
|| (!oldSubPathEndsWithSeparator && path[subPath.Length] != newDirectorySeparatorChar))
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.Length > subPath.Length
|
||||||
|
&& !oldSubPathEndsWithSeparator
|
||||||
|
&& path[subPath.Length] != newDirectorySeparatorChar)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1543,23 +1543,26 @@ namespace Emby.Server.Implementations.Session
|
|||||||
Limit = 1
|
Limit = 1
|
||||||
}).Items.FirstOrDefault();
|
}).Items.FirstOrDefault();
|
||||||
|
|
||||||
var allExistingForDevice = _authRepo.Get(
|
if (!string.IsNullOrEmpty(deviceId))
|
||||||
new AuthenticationInfoQuery
|
|
||||||
{
|
|
||||||
DeviceId = deviceId
|
|
||||||
}).Items;
|
|
||||||
|
|
||||||
foreach (var auth in allExistingForDevice)
|
|
||||||
{
|
{
|
||||||
if (existing == null || !string.Equals(auth.AccessToken, existing.AccessToken, StringComparison.Ordinal))
|
var allExistingForDevice = _authRepo.Get(
|
||||||
|
new AuthenticationInfoQuery
|
||||||
|
{
|
||||||
|
DeviceId = deviceId
|
||||||
|
}).Items;
|
||||||
|
|
||||||
|
foreach (var auth in allExistingForDevice)
|
||||||
{
|
{
|
||||||
try
|
if (existing == null || !string.Equals(auth.AccessToken, existing.AccessToken, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
Logout(auth);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
Logout(auth);
|
||||||
{
|
}
|
||||||
_logger.LogError(ex, "Error while logging out.");
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while logging out.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
/// <param name="startPositionTicks">The start position of the subtitle in ticks.</param>
|
/// <param name="startPositionTicks">The start position of the subtitle in ticks.</param>
|
||||||
/// <response code="200">File returned.</response>
|
/// <response code="200">File returned.</response>
|
||||||
/// <returns>A <see cref="FileContentResult"/> with the subtitle file.</returns>
|
/// <returns>A <see cref="FileContentResult"/> with the subtitle file.</returns>
|
||||||
[HttpGet("Videos/{routeItemId}/routeMediaSourceId/Subtitles/{routeIndex}/Stream.{routeFormat}")]
|
[HttpGet("Videos/{routeItemId}/{routeMediaSourceId}/Subtitles/{routeIndex}/Stream.{routeFormat}")]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesFile("text/*")]
|
[ProducesFile("text/*")]
|
||||||
public async Task<ActionResult> GetSubtitle(
|
public async Task<ActionResult> GetSubtitle(
|
||||||
|
|||||||
@@ -298,9 +298,9 @@ namespace Jellyfin.Api.Controllers
|
|||||||
{
|
{
|
||||||
Type = DlnaProfileType.Audio,
|
Type = DlnaProfileType.Audio,
|
||||||
Context = EncodingContext.Streaming,
|
Context = EncodingContext.Streaming,
|
||||||
Container = transcodingContainer ?? "mp3",
|
Container = transcodingContainer,
|
||||||
AudioCodec = audioCodec ?? "mp3",
|
AudioCodec = audioCodec,
|
||||||
Protocol = transcodingProtocol ?? "http",
|
Protocol = transcodingProtocol,
|
||||||
BreakOnNonKeyFrames = breakOnNonKeyFrames ?? false,
|
BreakOnNonKeyFrames = breakOnNonKeyFrames ?? false,
|
||||||
MaxAudioChannels = transcodingAudioChannels?.ToString(CultureInfo.InvariantCulture)
|
MaxAudioChannels = transcodingAudioChannels?.ToString(CultureInfo.InvariantCulture)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Data</PackageId>
|
<PackageId>Jellyfin.Data</PackageId>
|
||||||
<VersionPrefix>10.7.3</VersionPrefix>
|
<VersionPrefix>10.7.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Common</PackageId>
|
<PackageId>Jellyfin.Common</PackageId>
|
||||||
<VersionPrefix>10.7.3</VersionPrefix>
|
<VersionPrefix>10.7.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Controller</PackageId>
|
<PackageId>Jellyfin.Controller</PackageId>
|
||||||
<VersionPrefix>10.7.3</VersionPrefix>
|
<VersionPrefix>10.7.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -598,7 +598,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
&& string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)
|
&& string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)
|
||||||
&& isNvdecDecoder)
|
&& isNvdecDecoder)
|
||||||
{
|
{
|
||||||
arg.Append("-hwaccel_output_format cuda ");
|
// Fix for 'No decoder surfaces left' error. https://trac.ffmpeg.org/ticket/7562
|
||||||
|
arg.Append("-hwaccel_output_format cuda -extra_hw_frames 3 -autorotate 0 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.IsVideoRequest
|
if (state.IsVideoRequest
|
||||||
@@ -1072,7 +1073,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
|
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
|
||||||
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_nvenc)
|
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_nvenc)
|
||||||
{
|
{
|
||||||
// following preset will be deprecated in ffmpeg 4.4, use p1~p7 instead.
|
|
||||||
switch (encodingOptions.EncoderPreset)
|
switch (encodingOptions.EncoderPreset)
|
||||||
{
|
{
|
||||||
case "veryslow":
|
case "veryslow":
|
||||||
@@ -1253,7 +1253,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase)
|
if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase)
|
||||||
&& profile.Contains("constrainedbaseline", StringComparison.OrdinalIgnoreCase))
|
&& profile.Contains("baseline", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
profile = "constrained_baseline";
|
profile = "constrained_baseline";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,6 +273,16 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
|
|
||||||
public int? GetRequestedAudioChannels(string codec)
|
public int? GetRequestedAudioChannels(string codec)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(codec))
|
||||||
|
{
|
||||||
|
var value = BaseRequest.GetOption(codec, "audiochannels");
|
||||||
|
if (!string.IsNullOrEmpty(value)
|
||||||
|
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (BaseRequest.MaxAudioChannels.HasValue)
|
if (BaseRequest.MaxAudioChannels.HasValue)
|
||||||
{
|
{
|
||||||
return BaseRequest.MaxAudioChannels;
|
return BaseRequest.MaxAudioChannels;
|
||||||
@@ -288,16 +298,6 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
return BaseRequest.TranscodingMaxAudioChannels;
|
return BaseRequest.TranscodingMaxAudioChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(codec))
|
|
||||||
{
|
|
||||||
var value = BaseRequest.GetOption(codec, "audiochannels");
|
|
||||||
if (!string.IsNullOrEmpty(value)
|
|
||||||
&& int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
#nullable disable
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
@@ -9,17 +9,25 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
{
|
{
|
||||||
public class ContainerProfile
|
public class ContainerProfile
|
||||||
{
|
{
|
||||||
[Required]
|
|
||||||
[XmlAttribute("type")]
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
public ProfileCondition[]? Conditions { get; set; } = Array.Empty<ProfileCondition>();
|
public ProfileCondition[] Conditions { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("container")]
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; } = string.Empty;
|
public string Container { get; set; }
|
||||||
|
|
||||||
public static string[] SplitValue(string? value)
|
public ContainerProfile()
|
||||||
|
{
|
||||||
|
Conditions = Array.Empty<ProfileCondition>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetContainers()
|
||||||
|
{
|
||||||
|
return SplitValue(Container);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] SplitValue(string value)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
{
|
{
|
||||||
@@ -29,14 +37,14 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
return value.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
return value.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsContainer(string? container)
|
public bool ContainsContainer(string container)
|
||||||
{
|
{
|
||||||
var containers = SplitValue(Container);
|
var containers = GetContainers();
|
||||||
|
|
||||||
return ContainsContainer(containers, container);
|
return ContainsContainer(containers, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ContainsContainer(string? profileContainers, string? inputContainer)
|
public static bool ContainsContainer(string profileContainers, string inputContainer)
|
||||||
{
|
{
|
||||||
var isNegativeList = false;
|
var isNegativeList = false;
|
||||||
if (profileContainers != null && profileContainers.StartsWith('-'))
|
if (profileContainers != null && profileContainers.StartsWith('-'))
|
||||||
@@ -48,29 +56,46 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
return ContainsContainer(SplitValue(profileContainers), isNegativeList, inputContainer);
|
return ContainsContainer(SplitValue(profileContainers), isNegativeList, inputContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ContainsContainer(string[]? profileContainers, string? inputContainer)
|
public static bool ContainsContainer(string[] profileContainers, string inputContainer)
|
||||||
{
|
{
|
||||||
return ContainsContainer(profileContainers, false, inputContainer);
|
return ContainsContainer(profileContainers, false, inputContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ContainsContainer(string[]? profileContainers, bool isNegativeList, string? inputContainer)
|
public static bool ContainsContainer(string[] profileContainers, bool isNegativeList, string inputContainer)
|
||||||
{
|
{
|
||||||
if (profileContainers == null || profileContainers.Length == 0)
|
if (profileContainers.Length == 0)
|
||||||
{
|
{
|
||||||
return isNegativeList;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allInputContainers = SplitValue(inputContainer);
|
if (isNegativeList)
|
||||||
|
|
||||||
foreach (var container in allInputContainers)
|
|
||||||
{
|
{
|
||||||
if (profileContainers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
var allInputContainers = SplitValue(inputContainer);
|
||||||
|
|
||||||
|
foreach (var container in allInputContainers)
|
||||||
{
|
{
|
||||||
return !isNegativeList;
|
if (profileContainers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return isNegativeList;
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var allInputContainers = SplitValue(inputContainer);
|
||||||
|
|
||||||
|
foreach (var container in allInputContainers)
|
||||||
|
{
|
||||||
|
if (profileContainers.Contains(container, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
#nullable disable
|
||||||
#pragma warning disable CA1819 // Properties should not return arrays
|
#pragma warning disable CA1819 // Properties should not return arrays
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
@@ -13,104 +13,121 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
[XmlRoot("Profile")]
|
[XmlRoot("Profile")]
|
||||||
public class DeviceProfile
|
public class DeviceProfile
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="DeviceProfile"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public DeviceProfile()
|
||||||
|
{
|
||||||
|
DirectPlayProfiles = Array.Empty<DirectPlayProfile>();
|
||||||
|
TranscodingProfiles = Array.Empty<TranscodingProfile>();
|
||||||
|
ResponseProfiles = Array.Empty<ResponseProfile>();
|
||||||
|
CodecProfiles = Array.Empty<CodecProfile>();
|
||||||
|
ContainerProfiles = Array.Empty<ContainerProfile>();
|
||||||
|
SubtitleProfiles = Array.Empty<SubtitleProfile>();
|
||||||
|
|
||||||
|
XmlRootAttributes = Array.Empty<XmlAttribute>();
|
||||||
|
|
||||||
|
SupportedMediaTypes = "Audio,Photo,Video";
|
||||||
|
MaxStreamingBitrate = 8000000;
|
||||||
|
MaxStaticBitrate = 8000000;
|
||||||
|
MusicStreamingTranscodingBitrate = 128000;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Name.
|
/// Gets or sets the Name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Id.
|
/// Gets or sets the Id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public string? Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Identification.
|
/// Gets or sets the Identification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DeviceIdentification? Identification { get; set; }
|
public DeviceIdentification Identification { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the FriendlyName.
|
/// Gets or sets the FriendlyName.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FriendlyName { get; set; }
|
public string FriendlyName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Manufacturer.
|
/// Gets or sets the Manufacturer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Manufacturer { get; set; }
|
public string Manufacturer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ManufacturerUrl.
|
/// Gets or sets the ManufacturerUrl.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ManufacturerUrl { get; set; }
|
public string ManufacturerUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ModelName.
|
/// Gets or sets the ModelName.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ModelName { get; set; }
|
public string ModelName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ModelDescription.
|
/// Gets or sets the ModelDescription.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ModelDescription { get; set; }
|
public string ModelDescription { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ModelNumber.
|
/// Gets or sets the ModelNumber.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ModelNumber { get; set; }
|
public string ModelNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ModelUrl.
|
/// Gets or sets the ModelUrl.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ModelUrl { get; set; }
|
public string ModelUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SerialNumber.
|
/// Gets or sets the SerialNumber.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? SerialNumber { get; set; }
|
public string SerialNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether EnableAlbumArtInDidl.
|
/// Gets or sets a value indicating whether EnableAlbumArtInDidl.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool EnableAlbumArtInDidl { get; set; }
|
public bool EnableAlbumArtInDidl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether EnableSingleAlbumArtLimit.
|
/// Gets or sets a value indicating whether EnableSingleAlbumArtLimit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool EnableSingleAlbumArtLimit { get; set; }
|
public bool EnableSingleAlbumArtLimit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether EnableSingleSubtitleLimit.
|
/// Gets or sets a value indicating whether EnableSingleSubtitleLimit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool EnableSingleSubtitleLimit { get; set; }
|
public bool EnableSingleSubtitleLimit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SupportedMediaTypes.
|
/// Gets or sets the SupportedMediaTypes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SupportedMediaTypes { get; set; } = "Audio,Photo,Video";
|
public string SupportedMediaTypes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the UserId.
|
/// Gets or sets the UserId.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AlbumArtPn.
|
/// Gets or sets the AlbumArtPn.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? AlbumArtPn { get; set; }
|
public string AlbumArtPn { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxAlbumArtWidth.
|
/// Gets or sets the MaxAlbumArtWidth.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxAlbumArtWidth { get; set; }
|
public int MaxAlbumArtWidth { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxAlbumArtHeight.
|
/// Gets or sets the MaxAlbumArtHeight.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxAlbumArtHeight { get; set; }
|
public int MaxAlbumArtHeight { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxIconWidth.
|
/// Gets or sets the MaxIconWidth.
|
||||||
@@ -125,97 +142,92 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxStreamingBitrate.
|
/// Gets or sets the MaxStreamingBitrate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxStreamingBitrate { get; set; } = 8000000;
|
public int? MaxStreamingBitrate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxStaticBitrate.
|
/// Gets or sets the MaxStaticBitrate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxStaticBitrate { get; set; } = 8000000;
|
public int? MaxStaticBitrate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MusicStreamingTranscodingBitrate.
|
/// Gets or sets the MusicStreamingTranscodingBitrate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MusicStreamingTranscodingBitrate { get; set; } = 128000;
|
public int? MusicStreamingTranscodingBitrate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MaxStaticMusicBitrate.
|
/// Gets or sets the MaxStaticMusicBitrate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxStaticMusicBitrate { get; set; } = 8000000;
|
public int? MaxStaticMusicBitrate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.
|
/// Gets or sets the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? SonyAggregationFlags { get; set; }
|
public string SonyAggregationFlags { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ProtocolInfo.
|
/// Gets or sets the ProtocolInfo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ProtocolInfo { get; set; }
|
public string ProtocolInfo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the TimelineOffsetSeconds.
|
/// Gets or sets the TimelineOffsetSeconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(0)]
|
|
||||||
public int TimelineOffsetSeconds { get; set; }
|
public int TimelineOffsetSeconds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether RequiresPlainVideoItems.
|
/// Gets or sets a value indicating whether RequiresPlainVideoItems.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool RequiresPlainVideoItems { get; set; }
|
public bool RequiresPlainVideoItems { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether RequiresPlainFolders.
|
/// Gets or sets a value indicating whether RequiresPlainFolders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool RequiresPlainFolders { get; set; }
|
public bool RequiresPlainFolders { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether EnableMSMediaReceiverRegistrar.
|
/// Gets or sets a value indicating whether EnableMSMediaReceiverRegistrar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool EnableMSMediaReceiverRegistrar { get; set; }
|
public bool EnableMSMediaReceiverRegistrar { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether IgnoreTranscodeByteRangeRequests.
|
/// Gets or sets a value indicating whether IgnoreTranscodeByteRangeRequests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
public bool IgnoreTranscodeByteRangeRequests { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the XmlRootAttributes.
|
/// Gets or sets the XmlRootAttributes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public XmlAttribute[] XmlRootAttributes { get; set; } = Array.Empty<XmlAttribute>();
|
public XmlAttribute[] XmlRootAttributes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the direct play profiles.
|
/// Gets or sets the direct play profiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DirectPlayProfile[] DirectPlayProfiles { get; set; } = Array.Empty<DirectPlayProfile>();
|
public DirectPlayProfile[] DirectPlayProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the transcoding profiles.
|
/// Gets or sets the transcoding profiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TranscodingProfile[] TranscodingProfiles { get; set; } = Array.Empty<TranscodingProfile>();
|
public TranscodingProfile[] TranscodingProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ContainerProfiles.
|
/// Gets or sets the ContainerProfiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ContainerProfile[] ContainerProfiles { get; set; } = Array.Empty<ContainerProfile>();
|
public ContainerProfile[] ContainerProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the CodecProfiles.
|
/// Gets or sets the CodecProfiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CodecProfile[] CodecProfiles { get; set; } = Array.Empty<CodecProfile>();
|
public CodecProfile[] CodecProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ResponseProfiles.
|
/// Gets or sets the ResponseProfiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ResponseProfile[] ResponseProfiles { get; set; } = Array.Empty<ResponseProfile>();
|
public ResponseProfile[] ResponseProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SubtitleProfiles.
|
/// Gets or sets the SubtitleProfiles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SubtitleProfile[] SubtitleProfiles { get; set; } = Array.Empty<SubtitleProfile>();
|
public SubtitleProfile[] SubtitleProfiles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GetSupportedMediaTypes.
|
/// The GetSupportedMediaTypes.
|
||||||
@@ -232,13 +244,13 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <param name="container">The container.</param>
|
/// <param name="container">The container.</param>
|
||||||
/// <param name="audioCodec">The audio Codec.</param>
|
/// <param name="audioCodec">The audio Codec.</param>
|
||||||
/// <returns>A <see cref="TranscodingProfile"/>.</returns>
|
/// <returns>A <see cref="TranscodingProfile"/>.</returns>
|
||||||
public TranscodingProfile? GetAudioTranscodingProfile(string? container, string? audioCodec)
|
public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
|
||||||
{
|
{
|
||||||
container = (container ?? string.Empty).TrimStart('.');
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
foreach (var i in TranscodingProfiles)
|
foreach (var i in TranscodingProfiles)
|
||||||
{
|
{
|
||||||
if (i.Type != DlnaProfileType.Audio)
|
if (i.Type != MediaBrowser.Model.Dlna.DlnaProfileType.Audio)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -266,13 +278,13 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <param name="audioCodec">The audio Codec.</param>
|
/// <param name="audioCodec">The audio Codec.</param>
|
||||||
/// <param name="videoCodec">The video Codec.</param>
|
/// <param name="videoCodec">The video Codec.</param>
|
||||||
/// <returns>The <see cref="TranscodingProfile"/>.</returns>
|
/// <returns>The <see cref="TranscodingProfile"/>.</returns>
|
||||||
public TranscodingProfile? GetVideoTranscodingProfile(string? container, string? audioCodec, string? videoCodec)
|
public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
|
||||||
{
|
{
|
||||||
container = (container ?? string.Empty).TrimStart('.');
|
container = (container ?? string.Empty).TrimStart('.');
|
||||||
|
|
||||||
foreach (var i in TranscodingProfiles)
|
foreach (var i in TranscodingProfiles)
|
||||||
{
|
{
|
||||||
if (i.Type != DlnaProfileType.Video)
|
if (i.Type != MediaBrowser.Model.Dlna.DlnaProfileType.Video)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -287,7 +299,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(videoCodec, i.VideoCodec, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(videoCodec, i.VideoCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -308,7 +320,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <param name="audioSampleRate">The audio sample rate.</param>
|
/// <param name="audioSampleRate">The audio sample rate.</param>
|
||||||
/// <param name="audioBitDepth">The audio bit depth.</param>
|
/// <param name="audioBitDepth">The audio bit depth.</param>
|
||||||
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
||||||
public ResponseProfile? GetAudioMediaProfile(string container, string? audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
|
public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
|
||||||
{
|
{
|
||||||
foreach (var i in ResponseProfiles)
|
foreach (var i in ResponseProfiles)
|
||||||
{
|
{
|
||||||
@@ -372,7 +384,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <param name="width">The width.</param>
|
/// <param name="width">The width.</param>
|
||||||
/// <param name="height">The height.</param>
|
/// <param name="height">The height.</param>
|
||||||
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
||||||
public ResponseProfile? GetImageMediaProfile(string container, int? width, int? height)
|
public ResponseProfile GetImageMediaProfile(string container, int? width, int? height)
|
||||||
{
|
{
|
||||||
foreach (var i in ResponseProfiles)
|
foreach (var i in ResponseProfiles)
|
||||||
{
|
{
|
||||||
@@ -430,10 +442,10 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
/// <param name="videoCodecTag">The video Codec tag.</param>
|
/// <param name="videoCodecTag">The video Codec tag.</param>
|
||||||
/// <param name="isAvc">True if Avc.</param>
|
/// <param name="isAvc">True if Avc.</param>
|
||||||
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
/// <returns>The <see cref="ResponseProfile"/>.</returns>
|
||||||
public ResponseProfile? GetVideoMediaProfile(
|
public ResponseProfile GetVideoMediaProfile(
|
||||||
string container,
|
string container,
|
||||||
string? audioCodec,
|
string audioCodec,
|
||||||
string? videoCodec,
|
string videoCodec,
|
||||||
int? width,
|
int? width,
|
||||||
int? height,
|
int? height,
|
||||||
int? bitDepth,
|
int? bitDepth,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
#nullable disable
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
@@ -8,15 +8,14 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
public class DirectPlayProfile
|
public class DirectPlayProfile
|
||||||
{
|
{
|
||||||
[XmlAttribute("container")]
|
[XmlAttribute("container")]
|
||||||
public string? Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
[XmlAttribute("audioCodec")]
|
[XmlAttribute("audioCodec")]
|
||||||
public string? AudioCodec { get; set; }
|
public string AudioCodec { get; set; }
|
||||||
|
|
||||||
[XmlAttribute("videoCodec")]
|
[XmlAttribute("videoCodec")]
|
||||||
public string? VideoCodec { get; set; }
|
public string VideoCodec { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("type")]
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,69 +1,54 @@
|
|||||||
|
#nullable disable
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
public class TranscodingProfile
|
public class TranscodingProfile
|
||||||
{
|
{
|
||||||
[Required]
|
|
||||||
[XmlAttribute("container")]
|
[XmlAttribute("container")]
|
||||||
public string Container { get; set; } = string.Empty;
|
public string Container { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("type")]
|
[XmlAttribute("type")]
|
||||||
public DlnaProfileType Type { get; set; }
|
public DlnaProfileType Type { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("videoCodec")]
|
[XmlAttribute("videoCodec")]
|
||||||
public string VideoCodec { get; set; } = string.Empty;
|
public string VideoCodec { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("audioCodec")]
|
[XmlAttribute("audioCodec")]
|
||||||
public string AudioCodec { get; set; } = string.Empty;
|
public string AudioCodec { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[XmlAttribute("protocol")]
|
[XmlAttribute("protocol")]
|
||||||
public string Protocol { get; set; } = string.Empty;
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[XmlAttribute("estimateContentLength")]
|
[XmlAttribute("estimateContentLength")]
|
||||||
public bool EstimateContentLength { get; set; }
|
public bool EstimateContentLength { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[XmlAttribute("enableMpegtsM2TsMode")]
|
[XmlAttribute("enableMpegtsM2TsMode")]
|
||||||
public bool EnableMpegtsM2TsMode { get; set; }
|
public bool EnableMpegtsM2TsMode { get; set; }
|
||||||
|
|
||||||
[DefaultValue(TranscodeSeekInfo.Auto)]
|
|
||||||
[XmlAttribute("transcodeSeekInfo")]
|
[XmlAttribute("transcodeSeekInfo")]
|
||||||
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[XmlAttribute("copyTimestamps")]
|
[XmlAttribute("copyTimestamps")]
|
||||||
public bool CopyTimestamps { get; set; }
|
public bool CopyTimestamps { get; set; }
|
||||||
|
|
||||||
[DefaultValue(EncodingContext.Streaming)]
|
|
||||||
[XmlAttribute("context")]
|
[XmlAttribute("context")]
|
||||||
public EncodingContext Context { get; set; }
|
public EncodingContext Context { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[XmlAttribute("enableSubtitlesInManifest")]
|
[XmlAttribute("enableSubtitlesInManifest")]
|
||||||
public bool EnableSubtitlesInManifest { get; set; }
|
public bool EnableSubtitlesInManifest { get; set; }
|
||||||
|
|
||||||
[XmlAttribute("maxAudioChannels")]
|
[XmlAttribute("maxAudioChannels")]
|
||||||
public string? MaxAudioChannels { get; set; }
|
public string MaxAudioChannels { get; set; }
|
||||||
|
|
||||||
[DefaultValue(0)]
|
|
||||||
[XmlAttribute("minSegments")]
|
[XmlAttribute("minSegments")]
|
||||||
public int MinSegments { get; set; }
|
public int MinSegments { get; set; }
|
||||||
|
|
||||||
[DefaultValue(0)]
|
|
||||||
[XmlAttribute("segmentLength")]
|
[XmlAttribute("segmentLength")]
|
||||||
public int SegmentLength { get; set; }
|
public int SegmentLength { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
|
||||||
[XmlAttribute("breakOnNonKeyFrames")]
|
[XmlAttribute("breakOnNonKeyFrames")]
|
||||||
public bool BreakOnNonKeyFrames { get; set; }
|
public bool BreakOnNonKeyFrames { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Jellyfin Contributors</Authors>
|
<Authors>Jellyfin Contributors</Authors>
|
||||||
<PackageId>Jellyfin.Model</PackageId>
|
<PackageId>Jellyfin.Model</PackageId>
|
||||||
<VersionPrefix>10.7.3</VersionPrefix>
|
<VersionPrefix>10.7.6</VersionPrefix>
|
||||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("10.7.3")]
|
[assembly: AssemblyVersion("10.7.6")]
|
||||||
[assembly: AssemblyFileVersion("10.7.3")]
|
[assembly: AssemblyFileVersion("10.7.6")]
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Prevent generator from creating these files:
|
|
||||||
git_push.sh
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
artifactsDirectory="${1}"
|
|
||||||
|
|
||||||
java -jar openapi-generator-cli.jar generate \
|
|
||||||
--input-spec ${artifactsDirectory}/openapispec/openapi.json \
|
|
||||||
--generator-name typescript-axios \
|
|
||||||
--output ./apiclient/generated/typescript/axios \
|
|
||||||
--template-dir ./apiclient/templates/typescript/axios \
|
|
||||||
--ignore-file-override ./apiclient/.openapi-generator-ignore \
|
|
||||||
--additional-properties=useSingleRequestParameter="true",withSeparateModelsAndApi="true",modelPackage="models",apiPackage="api",npmName="axios"
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@jellyfin/client-axios",
|
|
||||||
"version": "10.7.0{{snapshotVersion}}",
|
|
||||||
"description": "Jellyfin api client using axios",
|
|
||||||
"author": "Jellyfin Contributors",
|
|
||||||
"keywords": [
|
|
||||||
"axios",
|
|
||||||
"typescript",
|
|
||||||
"jellyfin"
|
|
||||||
],
|
|
||||||
"license": "GPL-3.0-only",
|
|
||||||
"main": "./dist/index.js",
|
|
||||||
"typings": "./dist/index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc --outDir dist/",
|
|
||||||
"prepublishOnly": "npm run build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^0.19.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^12.11.5",
|
|
||||||
"typescript": "^3.6.4"
|
|
||||||
}{{#npmRepository}},{{/npmRepository}}
|
|
||||||
{{#npmRepository}}
|
|
||||||
"publishConfig": {
|
|
||||||
"registry": "{{npmRepository}}"
|
|
||||||
}
|
|
||||||
{{/npmRepository}}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
# We just wrap `build` so this is really it
|
# We just wrap `build` so this is really it
|
||||||
name: "jellyfin"
|
name: "jellyfin"
|
||||||
version: "10.7.3"
|
version: "10.7.6"
|
||||||
packages:
|
packages:
|
||||||
- debian.amd64
|
- debian.amd64
|
||||||
- debian.arm64
|
- debian.arm64
|
||||||
|
|||||||
Vendored
+18
@@ -1,3 +1,21 @@
|
|||||||
|
jellyfin-server (10.7.6-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream version 10.7.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.6
|
||||||
|
|
||||||
|
-- Jellyfin Packaging Team <packaging@jellyfin.org> Thu, 20 May 2021 22:06:13 -0400
|
||||||
|
|
||||||
|
jellyfin-server (10.7.5-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream version 10.7.5; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.5
|
||||||
|
|
||||||
|
-- Jellyfin Packaging Team <packaging@jellyfin.org> Tue, 04 May 2021 22:08:42 -0400
|
||||||
|
|
||||||
|
jellyfin-server (10.7.4-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream version 10.7.4; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.4
|
||||||
|
|
||||||
|
-- Jellyfin Packaging Team <packaging@jellyfin.org> Tue, 04 May 2021 21:15:42 -0400
|
||||||
|
|
||||||
jellyfin-server (10.7.3-1) unstable; urgency=medium
|
jellyfin-server (10.7.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
* New upstream version 10.7.3; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.3
|
* New upstream version 10.7.3; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.3
|
||||||
|
|||||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ Homepage: https://jellyfin.org
|
|||||||
Standards-Version: 3.9.2
|
Standards-Version: 3.9.2
|
||||||
|
|
||||||
Package: jellyfin
|
Package: jellyfin
|
||||||
Version: 10.7.3
|
Version: 10.7.6
|
||||||
Maintainer: Jellyfin Packaging Team <packaging@jellyfin.org>
|
Maintainer: Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
Depends: jellyfin-server, jellyfin-web
|
Depends: jellyfin-server, jellyfin-web
|
||||||
Description: Provides the Jellyfin Free Software Media System
|
Description: Provides the Jellyfin Free Software Media System
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
Name: jellyfin
|
Name: jellyfin
|
||||||
Version: 10.7.3
|
Version: 10.7.6
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: The Free Software Media System
|
Summary: The Free Software Media System
|
||||||
License: GPLv3
|
License: GPLv3
|
||||||
@@ -137,6 +137,12 @@ fi
|
|||||||
%systemd_postun_with_restart jellyfin.service
|
%systemd_postun_with_restart jellyfin.service
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu May 20 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
|
- New upstream version 10.7.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.6
|
||||||
|
* Tue May 04 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
|
- New upstream version 10.7.5; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.5
|
||||||
|
* Tue May 04 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
|
- New upstream version 10.7.4; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.4
|
||||||
* Tue May 04 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
* Tue May 04 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
- New upstream version 10.7.3; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.3
|
- New upstream version 10.7.3; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.7.3
|
||||||
* Sun Apr 11 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
* Sun Apr 11 2021 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ namespace Jellyfin.Dlna.Tests
|
|||||||
var fileSystem = new Mock<IFileSystem>();
|
var fileSystem = new Mock<IFileSystem>();
|
||||||
var appPaths = new Mock<IApplicationPaths>();
|
var appPaths = new Mock<IApplicationPaths>();
|
||||||
var loggerFactory = new Mock<ILoggerFactory>();
|
var loggerFactory = new Mock<ILoggerFactory>();
|
||||||
|
var jsonSerializer = new Mock<IJsonSerializer>();
|
||||||
var appHost = new Mock<IServerApplicationHost>();
|
var appHost = new Mock<IServerApplicationHost>();
|
||||||
|
|
||||||
return new DlnaManager(xmlSerializer.Object, fileSystem.Object, appPaths.Object, loggerFactory.Object, appHost.Object);
|
return new DlnaManager(xmlSerializer.Object, fileSystem.Object, appPaths.Object, loggerFactory.Object, jsonSerializer.Object, appHost.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library
|
|||||||
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")]
|
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")]
|
||||||
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")]
|
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")]
|
||||||
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")]
|
[InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")]
|
||||||
|
[InlineData("/o", "/o", "/s", "/s")] // regression test for #5977
|
||||||
public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult)
|
public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult)
|
||||||
{
|
{
|
||||||
Assert.True(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result));
|
Assert.True(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result));
|
||||||
|
|||||||
Reference in New Issue
Block a user