This commit is contained in:
Jonas Rabenstein 2025-11-29 18:14:10 +01:00
commit 794925acb2
15 changed files with 516 additions and 529 deletions

View file

@ -1,32 +0,0 @@
let
v."8.0.0.0" = {
hash = "sha256-5YUX+w4n3nBhAkdgjF9D5yY/jzRKxpW+mTQCBluzsVI=";
rev = "v8";
};
v."10.0.0.0" = {
hash = "sha256-pPhMmH17RKktIX16ozSxsigxo6tU8tlST4IAm3vpjrw=";
rev = "v10";
};
dlna = {
lib,
buildJellyfinPlugin,
fetchJellyfinPlugin,
...
}@args: let
version = args.version or "10.0.0.0";
hash = args.hash or v.${version}.hash or "";
rev = args.rev or v.${version}.rev or "v${lib.versions.major version}";
extra = lib.attrsets.removeAttrs args (builtins.attrNames (lib.functionArgs dlna));
plain = buildJellyfinPlugin {
name = "dlna";
inherit version;
src = fetchJellyfinPlugin {
name = "dlna";
inherit hash rev;
};
nugetDeps = ./deps.json;
};
in plain.override extra;
in dlna

56
plugin/dlna/package.nix Normal file
View file

@ -0,0 +1,56 @@
let
v."8.0.0.0" = {
hash = "sha256-5YUX+w4n3nBhAkdgjF9D5yY/jzRKxpW+mTQCBluzsVI=";
rev = "v8";
};
v."10.0.0.0" = {
hash = "sha256-pPhMmH17RKktIX16ozSxsigxo6tU8tlST4IAm3vpjrw=";
rev = "v10";
};
latest =
lib:
builtins.foldl' (acc: next: if lib.versionOlder acc next then next else acc) "0" (
builtins.attrNames v
);
plugin =
{
lib,
buildJellyfinPlugin,
fetchJellyfinPlugin,
...
}@params:
let
argNames = builtins.attrNames (lib.trivial.functionArgs plugin) ++ [
"name"
"version"
"hash"
];
extraArgs = lib.attrsets.removeAttrs params argNames;
self = plugin params;
name = params.name or "dlna";
version = params.version or (latest lib); # "10.0.0.0"; # TODO latest
defaultRev = {
tag = "v${lib.versions.major version}";
hash = params.hash or "";
};
args = {
name = name;
version = args.src.version or version;
nugetDeps = ./deps.json;
src = fetchJellyfinPlugin (
{
inherit name version;
}
// (v.${version} or defaultRev)
);
}
// extraArgs;
in
buildJellyfinPlugin args;
in
plugin

View file

@ -0,0 +1,125 @@
diff --git a/src/Jellyfin.Plugin.Dlna/Didl/DidlBuilder.cs b/src/Jellyfin.Plugin.Dlna/Didl/DidlBuilder.cs
index 150fb49..9160d8a 100644
--- a/src/Jellyfin.Plugin.Dlna/Didl/DidlBuilder.cs
+++ b/src/Jellyfin.Plugin.Dlna/Didl/DidlBuilder.cs
@@ -239,6 +239,17 @@ public class DidlBuilder
writer.WriteFullEndElement();
}
+ private string sanitize(string input)
+ {
+ var valid = input.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray();
+ if (valid.Length == input.Length)
+ {
+ return input;
+ }
+ _logger.LogInformation("Sanitized: {0} (was: {1})", valid, input.Where(ch => true).ToArray());
+ return new string(valid);
+ }
+
private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo? streamInfo = null)
{
if (streamInfo is null)
@@ -1009,7 +1020,7 @@ public class DidlBuilder
writer.WriteStartElement("upnp", "artist", NsUpnp);
writer.WriteAttributeString("role", "AlbumArtist");
- writer.WriteString(name);
+ writer.WriteString(sanitize(name));
writer.WriteFullEndElement();
}
@@ -1023,7 +1034,7 @@ public class DidlBuilder
{
try
{
- writer.WriteElementString(prefix, name, namespaceUri, value);
+ writer.WriteElementString(prefix, name, namespaceUri, sanitize(value));
}
catch (XmlException ex)
{
diff --git a/src/Jellyfin.Plugin.Dlna/PlayTo/PlayToController.cs b/src/Jellyfin.Plugin.Dlna/PlayTo/PlayToController.cs
index 4d822e2..9105d46 100644
--- a/src/Jellyfin.Plugin.Dlna/PlayTo/PlayToController.cs
+++ b/src/Jellyfin.Plugin.Dlna/PlayTo/PlayToController.cs
@@ -386,34 +386,38 @@ public class PlayToController : ISessionController, IDisposable
? null :
_userManager.GetUserById(command.ControllingUserId);
- var items = new List<BaseItem>();
- foreach (var id in command.ItemIds)
- {
- AddItemFromId(id, items);
- }
-
var startIndex = command.StartIndex ?? 0;
- int len = items.Count - startIndex;
- if (startIndex > 0)
- {
- items = items.GetRange(startIndex, len);
- }
-
- var playlist = new PlaylistItem[len];
-
- // Not nullable enabled - so this is required.
- playlist[0] = CreatePlaylistItem(
- items[0],
- user,
- command.StartPositionTicks ?? 0,
- command.MediaSourceId ?? string.Empty,
- command.AudioStreamIndex,
- command.SubtitleStreamIndex);
+ var playlist = new List<PlaylistItem>();
+ var first = true;
+ foreach (var id in command.ItemIds) {
+ var item = _libraryManager.GetItemById(id);
+ if (item?.MediaType != MediaType.Audio && item?.MediaType != MediaType.Video)
+ {
+ continue;
+ }
- for (int i = 1; i < len; i++)
- {
- playlist[i] = CreatePlaylistItem(items[i], user, 0, string.Empty, null, null);
- }
+ if (startIndex > 0) {
+ startIndex -= 1;
+ continue;
+ }
+
+ PlaylistItem? playlistItem = null;
+ try {
+ playlistItem = CreatePlaylistItem(item, user,
+ first ? (command.StartPositionTicks ?? 0) : 0,
+ first ? (command.MediaSourceId ?? string.Empty) : string.Empty,
+ first ? command.AudioStreamIndex : null,
+ first ? command.SubtitleStreamIndex : null);
+ } catch (System.NullReferenceException) {
+ _logger.LogError("{0}: could not create playlist item.", item.Path ?? "<unknown>");
+ }
+ first = false;
+
+ if (playlistItem != null)
+ {
+ playlist.Add(playlistItem);
+ }
+ }
_logger.LogDebug("{0} - Playlist created", _session.DeviceName);
@@ -509,15 +513,6 @@ public class PlayToController : ISessionController, IDisposable
return info.IsDirectStream;
}
- private void AddItemFromId(Guid id, List<BaseItem> list)
- {
- var item = _libraryManager.GetItemById(id);
- if (item?.MediaType == MediaType.Audio || item?.MediaType == MediaType.Video)
- {
- list.Add(item);
- }
- }
-
private PlaylistItem CreatePlaylistItem(
BaseItem item,
User? user,