Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rules, fix issues and cleanup #96

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
532 changes: 532 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

103 changes: 76 additions & 27 deletions src/Jellyfin.Plugin.Dlna.Model/ContentFeatureBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#nullable disable
#pragma warning disable CS1591

using System;
using System.Collections.Generic;
using System.Globalization;
Expand All @@ -10,17 +7,29 @@

namespace Jellyfin.Plugin.Dlna.Model;

/// <summary>
/// Defines the <see cref="ContentFeatureBuilder" />.
/// </summary>
public static class ContentFeatureBuilder
{
/// <summary>
/// Gets the image header.
/// </summary>
/// <param name="profile">The <see cref="DlnaDeviceProfile"/>.</param>
/// <param name="container">The container.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="isDirectStream">Value indicating wether the stream is direct.</param>
/// <param name="orgPn">The orgPn.</param>
public static string BuildImageHeader(
DlnaDeviceProfile profile,
string container,
int? width,
int? height,
bool isDirectStream,
string orgPn = null)
string? orgPn = null)
{
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();
var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();

// 0 = native, 1 = transcoded
var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
Expand All @@ -29,14 +38,14 @@ public static string BuildImageHeader(
DlnaFlags.InteractiveTransferMode |
DlnaFlags.DlnaV15;

string dlnaflags = string.Format(
var dlnaflags = string.Format(
CultureInfo.InvariantCulture,
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));

if (string.IsNullOrEmpty(orgPn))
{
ResponseProfile mediaProfile = profile.GetImageMediaProfile(
ResponseProfile? mediaProfile = profile.GetImageMediaProfile(
container,
width,
height);
Expand All @@ -57,10 +66,23 @@ public static string BuildImageHeader(
return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
}

/// <summary>
/// Gets the audio header.
/// </summary>
/// <param name="profile">The <see cref="DlnaDeviceProfile"/>.</param>
/// <param name="container">The container.</param>
/// <param name="audioCodec">The codec.</param>
/// <param name="audioBitrate">The bitrate.</param>
/// <param name="audioSampleRate">The sample rate.</param>
/// <param name="audioChannels">The channel count.</param>
/// <param name="audioBitDepth">The bit depth.</param>
/// <param name="isDirectStream">Value indicating wether the stream is direct.</param>
/// <param name="runtimeTicks">The runtime ticks.</param>
/// <param name="transcodeSeekInfo">The <see cref="TranscodeSeekInfo"/>.</param>
public static string BuildAudioHeader(
DlnaDeviceProfile profile,
string container,
string audioCodec,
string? container,
string? audioCodec,
int? audioBitrate,
int? audioSampleRate,
int? audioChannels,
Expand All @@ -70,10 +92,10 @@ public static string BuildAudioHeader(
TranscodeSeekInfo transcodeSeekInfo)
{
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);
var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);

// 0 = native, 1 = transcoded
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";

var flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
Expand All @@ -89,20 +111,20 @@ public static string BuildAudioHeader(
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
// }

string dlnaflags = string.Format(
var dlnaflags = string.Format(
CultureInfo.InvariantCulture,
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));

ResponseProfile mediaProfile = profile.GetAudioMediaProfile(
ResponseProfile? mediaProfile = profile.GetAudioMediaProfile(
container,
audioCodec,
audioChannels,
audioBitrate,
audioSampleRate,
audioBitDepth);

string orgPn = mediaProfile?.OrgPn;
var orgPn = mediaProfile?.OrgPn;

if (string.IsNullOrEmpty(orgPn))
{
Expand All @@ -117,19 +139,46 @@ public static string BuildAudioHeader(
return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
}

/// <summary>
/// Gets the video header.
/// </summary>
/// <param name="profile">The <see cref="DlnaDeviceProfile"/>.</param>
/// <param name="container">The container.</param>
/// <param name="videoCodec">The video codec.</param>
/// <param name="audioCodec">The audio codec.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="bitDepth">The bit depth.</param>
/// <param name="videoBitrate">The video bitrate.</param>
/// <param name="timestamp">The <see cref="TransportStreamTimestamp"/>.</param>
/// <param name="isDirectStream">Value indicating wether the stream is direct.</param>
/// <param name="runtimeTicks">The runtime ticks.</param>
/// <param name="videoProfile">The video profile.</param>
/// <param name="videoRangeType">The <see cref="VideoRangeType"/>.</param>
/// <param name="videoLevel">The video level.</param>
/// <param name="videoFramerate">The video framerate.</param>
/// <param name="packetLength">The packet length.</param>
/// <param name="transcodeSeekInfo">The <see cref="TranscodeSeekInfo"/>.</param>
/// <param name="isAnamorphic">Value indicating wether the stream is anamorphic.</param>
/// <param name="isInterlaced">Value indicating wether the stream is interlaced.</param>
/// <param name="refFrames">The reference frames.</param>
/// <param name="numVideoStreams">The number of video streams.</param>
/// <param name="numAudioStreams">The number of audio streams.</param>
/// <param name="videoCodecTag">The video codec tag.</param>
/// <param name="isAvc">Value indicating wether the stream is AVC.</param>
public static IEnumerable<string> BuildVideoHeader(
DlnaDeviceProfile profile,
string container,
string videoCodec,
string audioCodec,
string? container,
string? videoCodec,
string? audioCodec,
int? width,
int? height,
int? bitDepth,
int? videoBitrate,
TransportStreamTimestamp timestamp,
bool isDirectStream,
long? runtimeTicks,
string videoProfile,
string? videoProfile,
VideoRangeType videoRangeType,
double? videoLevel,
float? videoFramerate,
Expand All @@ -140,14 +189,14 @@ public static IEnumerable<string> BuildVideoHeader(
int? refFrames,
int? numVideoStreams,
int? numAudioStreams,
string videoCodecTag,
string? videoCodecTag,
bool? isAvc)
{
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);
var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);

// 0 = native, 1 = transcoded
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";

var flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
Expand All @@ -165,12 +214,12 @@ public static IEnumerable<string> BuildVideoHeader(
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
// }

string dlnaflags = string.Format(
var dlnaflags = string.Format(
CultureInfo.InvariantCulture,
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));

ResponseProfile mediaProfile = profile.GetVideoMediaProfile(
var mediaProfile = profile.GetVideoMediaProfile(
container,
audioCodec,
videoCodec,
Expand Down Expand Up @@ -234,14 +283,14 @@ public static IEnumerable<string> BuildVideoHeader(
return contentFeatureList;
}

private static string GetImageOrgPnValue(string container, int? width, int? height)
private static string? GetImageOrgPnValue(string container, int? width, int? height)
{
MediaFormatProfile? format = MediaFormatProfileResolver.ResolveImageFormat(container, width, height);

return format.HasValue ? format.Value.ToString() : null;
}

private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
private static string? GetAudioOrgPnValue(string? container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
{
MediaFormatProfile? format = MediaFormatProfileResolver.ResolveAudioFormat(
container,
Expand All @@ -252,8 +301,8 @@ private static string GetAudioOrgPnValue(string container, int? audioBitrate, in
return format.HasValue ? format.Value.ToString() : null;
}

private static MediaFormatProfile[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
private static MediaFormatProfile[] GetVideoOrgPnValue(string? container, string? videoCodec, string? audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
{
return MediaFormatProfileResolver.ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
}
}
}
7 changes: 5 additions & 2 deletions src/Jellyfin.Plugin.Dlna.Model/DeviceIdentification.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
#pragma warning disable CA1819 // Properties should not return arrays

namespace Jellyfin.Plugin.Dlna.Model;

/// <summary>
/// Defines the <see cref="DeviceIdentification" />.
/// </summary>
public class DeviceIdentification
{
/// <summary>
Expand Down Expand Up @@ -56,5 +59,5 @@ public class DeviceIdentification
/// Gets or sets the headers.
/// </summary>
/// <value>The headers.</value>
public HttpHeaderInfo[] Headers { get; set; } = Array.Empty<HttpHeaderInfo>();
public HttpHeaderInfo[] Headers { get; set; } = [];
}
Shadowghost marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions src/Jellyfin.Plugin.Dlna.Model/DeviceProfileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Jellyfin.Plugin.Dlna.Model;

/// <summary>
/// Defines the <see cref="DeviceProfileInfo" />.
/// </summary>
public class DeviceProfileInfo
{
/// <summary>
Expand Down
10 changes: 10 additions & 0 deletions src/Jellyfin.Plugin.Dlna.Model/DeviceProfileType.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
namespace Jellyfin.Plugin.Dlna.Model;

/// <summary>
/// Defines the <see cref="DeviceProfileType" />.
/// </summary>
public enum DeviceProfileType
{
/// <summary>
/// System profile.
/// </summary>
System = 0,

/// <summary>
/// User profile.
/// </summary>
User = 1
}
20 changes: 15 additions & 5 deletions src/Jellyfin.Plugin.Dlna.Model/DlnaDeviceProfile.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma warning disable CA1819 // Properties should not return arrays

using System;
using System.ComponentModel;
using System.Linq;
Expand All @@ -10,6 +12,9 @@

namespace Jellyfin.Plugin.Dlna.Model;

/// <summary>
/// Defines the <see cref="DlnaDeviceProfile" />.
/// </summary>
[XmlRoot("Profile")]
public class DlnaDeviceProfile : DeviceProfile
{
Expand Down Expand Up @@ -154,18 +159,18 @@ public class DlnaDeviceProfile : DeviceProfile
/// <summary>
/// Gets or sets the XmlRootAttributes.
/// </summary>
public XmlAttribute[] XmlRootAttributes { get; set; } = Array.Empty<XmlAttribute>();
public XmlAttribute[] XmlRootAttributes { get; set; } = [];

/// <summary>
/// Gets or sets the ResponseProfiles.
/// </summary>
public ResponseProfile[] ResponseProfiles { get; set; } = Array.Empty<ResponseProfile>();
public ResponseProfile[] ResponseProfiles { get; set; } = [];

/// <summary>
/// The GetSupportedMediaTypes.
/// The supported media types.
/// </summary>
/// <returns>The .</returns>
public MediaType[] GetSupportedMediaTypes()
public MediaType[] FetchSupportedMediaTypes()
{
return ContainerHelper.Split(SupportedMediaTypes)
.Select(m => Enum.TryParse<MediaType>(m, out var parsed) ? parsed : MediaType.Unknown)
Expand Down Expand Up @@ -265,8 +270,13 @@ public MediaType[] GetSupportedMediaTypes()
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <returns>The <see cref="ResponseProfile"/>.</returns>
public ResponseProfile? GetImageMediaProfile(string container, int? width, int? height)
public ResponseProfile? GetImageMediaProfile(string? container, int? width, int? height)
{
if (container is null)
{
return null;
}

foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Photo)
Expand Down
Loading
Loading