Dlna controller on NixOS?

I’m looking for a dlna / upnp media controller application for my NixOS linux desktop.

I’ve found this, but sadly couldn’t find a NixOS package for it:

There’s also “eezUPnP” which doesn’t have a NixOS package neither. Though it seems that one isn’t open-source, just free to use?

I’ve also now stumbled upon Rygel which does have a NixOS package, but fails to start:

$ nix run nixpkgs#rygel   
Rygel-Message: 15:34:02.448: Rygel v45.0 starting…

(rygel:283221): Rygel-WARNING **: 15:34:02.448: Failed to load user configuration: No such file or directory

(rygel:283221): RygelCore-WARNING **: 15:34:02.449: Failed to get log level from configuration: No value available
Rygel-Message: 15:34:02.449: rygel-acl.vala:145: No ACL fallback policy found. Using “allow”
RygelCore-Message: 15:34:02.463: New plugin “ExampleRendererPluginC” available
RygelCore-Message: 15:34:02.464: New plugin “ExampleRendererPluginVala” available
[1]    283221 trace trap (core dumped)  nix run nixpkgs#rygel

Is there anything that we have in the NixOS repo that can fulfill that function?

You installed the rygel executable package. So it’s complaining about a missing config file.

In NixOS, you shoud always check if there is a module available for what you want. The module brings you the package + everything needed around it.

So try

services.gnome.rygel.enable = true;

2 Likes

will this work without using the gnome desktop? I’m on KDE.

I don’t see any reason why it wouldn’t work. It might bring in some gnome dependencies along with it. If you don’t like it or it doesn’t work properly, just delete that line, rebuild/switch and cleanup old generations and there won’t be a trace of gnome on your machine any more.

Yeah, it specifically creates a config file:

I have not actually tested it outside of GNOME so no guarantees but if if it does not work, it is a bug so a report would be appreciated.

2 Likes

thanks for your messages!

I’ve now installed rygel on my NixOS machine with the service.gnome line.

Starting it now doesn’t show any window but also doesn’t crash, the terminal output reads:

Rygel-Message: 20:57:48.222: Rygel v45.0 starting…

(rygel:678665): RygelCore-WARNING **: 20:57:48.224: Failed to load user configuration from file “/home/user/.config/rygel.conf”: No such file or directory

(rygel:678665): RygelLocalSearch-WARNING **: 20:57:48.251: Could not connect to org.freedesktop.LocalSearch3, falling back to old Tracker3 service

(rygel:678665): RygelLocalSearch-WARNING **: 20:57:48.253: Failed to start LocalSearch service: The name org.freedesktop.Tracker3.Miner.Files was not provided by any .service files. Plugin disabled.
RygelCore-Message: 20:57:48.622: New plugin “MediaExport” available
RygelCore-Message: 20:57:48.627: New plugin “Playbin” available
MediaExport-Message: 20:57:48.868: “file:///home/user/Videos” harvested
MediaExport-Message: 20:57:48.868: rygel-media-export-harvesting-task.vala:316: Harvesting of file:///home/user/Videos done in 0.016919
MxExtract-Message: 20:57:48.883: rygel-media-export-extract.vala:180: Started with descriptors 3 (in) 4 (out), extracting meta-data: true
MxExtract-Message: 20:57:48.883: rygel-media-export-extract.vala:180: Started with descriptors 3 (in) 4 (out), extracting meta-data: true
MxExtract-Message: 20:57:48.886: rygel-media-export-extract.vala:180: Started with descriptors 3 (in) 4 (out), extracting meta-data: true
RygelServer-Message: 20:57:48.906: rygel-thumbnailer.vala:132: No D-Bus thumbnailer available
MediaExport-Message: 20:57:48.910: “file:///home/user/Pictures” harvested
MediaExport-Message: 20:57:48.910: rygel-media-export-harvesting-task.vala:316: Harvesting of file:///home/user/Pictures done in 0.055470
MediaExport-Message: 20:57:49.067: “file:///home/user/Music” harvested
MediaExport-Message: 20:57:49.076: rygel-media-export-harvesting-task.vala:316: Harvesting of file:///home/user/Music done in 0.228931

I’m not sure what this application is supposed to be capable of, but what I’m looking for is to read metadata from a dlna media server (running on a different machine), allow the user to select one media file or even create a playlist of multiple files shared by that media server, and send the appropiate commands to a dlna media renderer running on a 3rd device.

That’s what “BubbleUpnp” offers me on Android, though sadly it’s non-free (and tries to sell a premium version by imposing arbitrary limitations) and it’s only on Android and not on my Desktop.

Oh, sorry, I missed you are looking for a controller. I believe Rygel is only a server. If I recall correctly, there was a rudimentary controller in gupnp-tools package but it has been a while since I tested it.

I’ve tried to install that package, but failed:

error: Cannot build '/nix/store/487mxb4nrzxqx5pmp28yba6qgqvlwbbd-gupnp-tools-0.12.2.drv'.
       Reason: builder failed with exit code 1.
       Output paths:
         /nix/store/1gsa4f8q64ybsag766kv35k91mgxi6lj-gupnp-tools-0.12.2
       Last 25 log lines:
       >       |         ^~~~~~~~~~~~~~~~~~~
       > /nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/parser.h:1286:16: note: declared here
       >  1286 | XMLPUBFUN int *__xmlIndentTreeOutput(void);
       >       |                ^~~~~~~~~~~~~~~~~~~~~
       > cc1: some warnings being treated as errors
       > [12/74] Merging translations for data/gupnp-network-light.desktop
       > [13/74] Merging translations for data/gupnp-av-cp.desktop
       > [14/74] Merging translations for data/gupnp-universal-cp.desktop
       > [15/74] Compiling C object src/common/libutil.a.p/meson-generated_.._common-resource.c.o
       > [16/74] Compiling C object src/av-cp/gupnp-av-cp.p/meson-generated_.._av-cp-resource.c.o
       > [17/74] Compiling C object src/discover/gssdp-discover.p/gssdp-discover.c.o
       > [18/74] Compiling C object src/upload/gupnp-upload.p/main.c.o
       > [19/74] Compiling C object src/upload/gupnp-upload.p/item-creation.c.o
       > [20/74] Compiling C object src/upload/gupnp-upload.p/container-search.c.o
       > [21/74] Compiling C object src/event-dumper/gupnp-event-dumper.p/event-dumper.c.o
       > [22/74] Compiling C object src/upload/gupnp-upload.p/control_point.c.o
       > [23/74] Compiling C object src/upload/gupnp-upload.p/transfer.c.o
       > [24/74] Compiling C object src/common/libutil.a.p/icons.c.o
       > [25/74] Compiling C object src/av-cp/gupnp-av-cp.p/gui.c.o
       > [26/74] Compiling C object src/network-light/gupnp-network-light.p/gui.c.o
       > [27/74] Compiling C object src/av-cp/gupnp-av-cp.p/didl-dialog.c.o
       > [28/74] Compiling C object src/av-cp/gupnp-av-cp.p/main.c.o
       > [29/74] Compiling C object src/network-light/gupnp-network-light.p/main.c.o
       > [30/74] Compiling C object src/av-cp/gupnp-av-cp.p/playlist-treeview.c.o
       > ninja: build stopped: subcommand failed.
       For full logs, run:
         nix log /nix/store/487mxb4nrzxqx5pmp28yba6qgqvlwbbd-gupnp-tools-0.12.2.drv
error: Cannot build '/nix/store/blw1w90zs1bfv06042d7z63h2y7cm9cv-system-path.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/n3wp3krc5qyi6s7gwflgwf55rd38d18z-system-path
error: Cannot build '/nix/store/c6fi8lk3938pn5sd74jpamq18wpnflzd-nixos-system-Lenovo_P16v_nixos-25.11.20251209.09eb77e.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/sknw8zzp7lnks5aaxfx4m2wh2ayz86nk-nixos-system-Lenovo_P16v_nixos-25.11.20251209.09eb77e
Command 'nix --extra-experimental-features 'nix-command flakes' build --print-out-paths '/etc/nixos#nixosConfigurations."LenovoP16vnixos".config.system.build.toplevel' --no-link' returned non-zero exit status 1.

looking at the suggested nix log shows:

../src/common/pretty-print.c: In function 'pretty_print_xml':
../src/common/pretty-print.c:47:9: error: '__xmlIndentTreeOutput' is deprecated: See https://gnome.pages.gitlab.gnome.org/libxml2/html/deprecated.html [-Werror=deprecated-declarations]
   47 |         old_value = xmlIndentTreeOutput;
      |         ^~~~~~~~~
In file included from /nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/HTMLparser.h:22,
                 from /nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/globals.h:21,
                 from ../src/common/pretty-print.c:25:
/nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/parser.h:1286:16: note: declared here
 1286 | XMLPUBFUN int *__xmlIndentTreeOutput(void);
      |                ^~~~~~~~~~~~~~~~~~~~~
../src/common/pretty-print.c:48:9: error: '__xmlIndentTreeOutput' is deprecated: See https://gnome.pages.gitlab.gnome.org/libxml2/html/deprecated.html [-Werror=deprecated-declarations]
   48 |         xmlIndentTreeOutput = 1;
      |         ^~~~~~~~~~~~~~~~~~~
/nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/parser.h:1286:16: note: declared here
 1286 | XMLPUBFUN int *__xmlIndentTreeOutput(void);
      |                ^~~~~~~~~~~~~~~~~~~~~
../src/common/pretty-print.c:54:9: error: '__xmlIndentTreeOutput' is deprecated: See https://gnome.pages.gitlab.gnome.org/libxml2/html/deprecated.html [-Werror=deprecated-declarations]
   54 |         xmlIndentTreeOutput = old_value;
      |         ^~~~~~~~~~~~~~~~~~~
/nix/store/www785flca9qwyacn033z0p18p8vp00l-libxml2-2.15.1-dev/include/libxml2/libxml/parser.h:1286:16: note: declared here
 1286 | XMLPUBFUN int *__xmlIndentTreeOutput(void);
      |                ^~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

update, managed to get it installed by doing some vibe-coding:

gupnp-tools = prev.gupnp-tools.overrideAttrs (old: {
        # Add a compiler flag to ignore deprecation warnings
        NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or [ ]) ++ [
          "-Wno-error=deprecated-declarations"
        ];
      });

But both included control-point applications (gupnp-universal-cp & gupnp-av-cp) are very unergonomic to use. I much prefer upplay. I did manage to build it’s dependencies npupnp & libupnpp but failed to get the also required qtwebkit-5.212.0-alpha4 to build..

...
In file included from /build/source/Source/WTF/wtf/FastMalloc.h:26,
                 from /build/source/Source/WTF/config.h:51,
                 from /build/source/Source/WTF/wtf/Atomics.cpp:26:
/build/source/Source/WTF/wtf/StdLibExtras.h:330:36: error: conflicting declaration of template 'template<long unsigned int ...indexes> struct std::index_sequence'
  330 | template<size_t... indexes> struct index_sequence {
      |                                    ^~~~~~~~~~~~~~
In file included from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/stl_pair.h:62,
                 from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:69,
                 from /nix/store/5f0nxzggzzqlfyn0gfcj83sna1igmsl3-qtbase-5.15.18-dev/include/QtCore/qglobal.h:47,
                 from /build/source/Source/WTF/wtf/Platform.h:1055,
                 from /build/source/Source/WTF/config.h:26:
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:182:11: note: previous declaration 'template<long unsigned int ..._Idx> using std::index_sequence = std::integer_sequence<long unsigned int, _Idx ...>'
  182 |     using index_sequence = integer_sequence<size_t, _Idx...>;
      |           ^~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:344:32: error: conflicting declaration of template 'template<long unsigned int length> struct std::make_index_sequence'
  344 | template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { };
      |                                ^~~~~~~~~~~~~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:186:11: note: previous declaration 'template<long unsigned int _Num> using std::make_index_sequence = std::make_integer_sequence<long unsigned int, _Num>'
  186 |     using make_index_sequence = make_integer_sequence<size_t, _Num>;
      |           ^~~~~~~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:348:3: error: redefinition of 'template<class T, class U> T std::exchange(T&, U&&)'
  348 | T exchange(T& t, U&& newValue)
      |   ^~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:107:5: note: 'template<class _Tp, class _Up> _Tp std::exchange(_Tp&, _Up&&)' previously declared here
  107 |     exchange(_Tp& __obj, _Up&& __new_val)
      |     ^~~~~~~~
make[2]: *** [Source/WTF/wtf/CMakeFiles/WTF.dir/build.make:105: Source/WTF/wtf/CMakeFiles/WTF.dir/Atomics.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
[  0%] Building CXX object Source/ThirdParty/woff2/CMakeFiles/woff2.dir/src/woff2_dec.cc.o
In file included from /build/source/Source/WTF/wtf/FastMalloc.h:26,
                 from /build/source/Source/WTF/config.h:51,
                 from /build/source/Source/WTF/wtf/BitVector.cpp:26:
/build/source/Source/WTF/wtf/StdLibExtras.h:330:36: error: conflicting declaration of template 'template<long unsigned int ...indexes> struct std::index_sequence'
  330 | template<size_t... indexes> struct index_sequence {
      |                                    ^~~~~~~~~~~~~~
In file included from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/stl_pair.h:62,
                 from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:69,
                 from /nix/store/5f0nxzggzzqlfyn0gfcj83sna1igmsl3-qtbase-5.15.18-dev/include/QtCore/qglobal.h:47,
                 from /build/source/Source/WTF/wtf/Platform.h:1055,
                 from /build/source/Source/WTF/config.h:26:
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:182:11: note: previous declaration 'template<long unsigned int ..._Idx> using std::index_sequence = std::integer_sequence<long unsigned int, _Idx ...>'
  182 |     using index_sequence = integer_sequence<size_t, _Idx...>;
      |           ^~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:344:32: error: conflicting declaration of template 'template<long unsigned int length> struct std::make_index_sequence'
  344 | template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { };
      |                                ^~~~~~~~~~~~~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:186:11: note: previous declaration 'template<long unsigned int _Num> using std::make_index_sequence = std::make_integer_sequence<long unsigned int, _Num>'
  186 |     using make_index_sequence = make_integer_sequence<size_t, _Num>;
      |           ^~~~~~~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:348:3: error: redefinition of 'template<class T, class U> T std::exchange(T&, U&&)'
  348 | T exchange(T& t, U&& newValue)
      |   ^~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:107:5: note: 'template<class _Tp, class _Up> _Tp std::exchange(_Tp&, _Up&&)' previously declared here
  107 |     exchange(_Tp& __obj, _Up&& __new_val)
      |     ^~~~~~~~
make[2]: *** [Source/WTF/wtf/CMakeFiles/WTF.dir/build.make:119: Source/WTF/wtf/CMakeFiles/WTF.dir/BitVector.cpp.o] Error 1
[  0%] Building CXX object Source/ThirdParty/woff2/CMakeFiles/woff2.dir/src/woff2_out.cc.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/Operator.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp.o
In file included from /build/source/Source/WTF/wtf/FastMalloc.h:26,
                 from /build/source/Source/WTF/config.h:51,
                 from /build/source/Source/WTF/wtf/CompilationThread.cpp:26:
/build/source/Source/WTF/wtf/StdLibExtras.h:330:36: error: conflicting declaration of template 'template<long unsigned int ...indexes> struct std::index_sequence'
  330 | template<size_t... indexes> struct index_sequence {
      |                                    ^~~~~~~~~~~~~~
In file included from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/stl_pair.h:62,
                 from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:69,
                 from /nix/store/5f0nxzggzzqlfyn0gfcj83sna1igmsl3-qtbase-5.15.18-dev/include/QtCore/qglobal.h:47,
                 from /build/source/Source/WTF/wtf/Platform.h:1055,
                 from /build/source/Source/WTF/config.h:26:
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:182:11: note: previous declaration 'template<long unsigned int ..._Idx> using std::index_sequence = std::integer_sequence<long unsigned int, _Idx ...>'
  182 |     using index_sequence = integer_sequence<size_t, _Idx...>;
      |           ^~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:344:32: error: conflicting declaration of template 'template<long unsigned int length> struct std::make_index_sequence'
  344 | template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { };
      |                                ^~~~~~~~~~~~~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:186:11: note: previous declaration 'template<long unsigned int _Num> using std::make_index_sequence = std::make_integer_sequence<long unsigned int, _Num>'
  186 |     using make_index_sequence = make_integer_sequence<size_t, _Num>;
      |           ^~~~~~~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:348:3: error: redefinition of 'template<class T, class U> T std::exchange(T&, U&&)'
  348 | T exchange(T& t, U&& newValue)
      |   ^~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:107:5: note: 'template<class _Tp, class _Up> _Tp std::exchange(_Tp&, _Up&&)' previously declared here
  107 |     exchange(_Tp& __obj, _Up&& __new_val)
      |     ^~~~~~~~
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp.o
In file included from /build/source/Source/WTF/wtf/FastMalloc.h:26,
                 from /build/source/Source/WTF/config.h:51,
                 from /build/source/Source/WTF/wtf/Assertions.cpp:34:
/build/source/Source/WTF/wtf/StdLibExtras.h:330:36: error: conflicting declaration of template 'template<long unsigned int ...indexes> struct std::index_sequence'
  330 | template<size_t... indexes> struct index_sequence {
      |                                    ^~~~~~~~~~~~~~
In file included from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/stl_pair.h:62,
                 from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:69,
                 from /nix/store/5f0nxzggzzqlfyn0gfcj83sna1igmsl3-qtbase-5.15.18-dev/include/QtCore/qglobal.h:47,
                 from /build/source/Source/WTF/wtf/Platform.h:1055,
                 from /build/source/Source/WTF/config.h:26:
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:182:11: note: previous declaration 'template<long unsigned int ..._Idx> using std::index_sequence = std::integer_sequence<long unsigned int, _Idx ...>'
  182 |     using index_sequence = integer_sequence<size_t, _Idx...>;
      |           ^~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:344:32: error: conflicting declaration of template 'template<long unsigned int length> struct std::make_index_sequence'
  344 | template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { };
      |                                ^~~~~~~~~~~~~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/utility.h:186:11: note: previous declaration 'template<long unsigned int _Num> using std::make_index_sequence = std::make_integer_sequence<long unsigned int, _Num>'
  186 |     using make_index_sequence = make_integer_sequence<size_t, _Num>;
      |           ^~~~~~~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:348:3: error: redefinition of 'template<class T, class U> T std::exchange(T&, U&&)'
  348 | T exchange(T& t, U&& newValue)
      |   ^~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/utility:107:5: note: 'template<class _Tp, class _Up> _Tp std::exchange(_Tp&, _Up&&)' previously declared here
  107 |     exchange(_Tp& __obj, _Up&& __new_val)
      |     ^~~~~~~~
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp.o
make[2]: *** [Source/WTF/wtf/CMakeFiles/WTF.dir/build.make:133: Source/WTF/wtf/CMakeFiles/WTF.dir/CompilationThread.cpp.o] Error 1
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/PruneEmptyDeclarations.cpp.o
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp.o
In file included from /build/source/Source/WTF/wtf/text/StringConcatenate.h:36,
                 from /build/source/Source/WTF/wtf/text/AtomicString.h:378,
                 from /build/source/Source/WTF/wtf/text/WTFString.h:769,
                 from /build/source/Source/WTF/wtf/Assertions.cpp:41:
/build/source/Source/WTF/wtf/text/StringView.h:503:35: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
  503 |     StringTypeAdapter<StringView>(StringView string)
      |                                   ^~~~~~~~~~
/build/source/Source/WTF/wtf/text/StringView.h:503:35: note: remove the '< >'
/build/source/Source/WTF/wtf/text/StringConcatenate.h:53:28: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
   53 |     StringTypeAdapter<char>(char character)
      |                            ^
/build/source/Source/WTF/wtf/text/StringConcatenate.h:53:28: note: remove the '< >'
/build/source/Source/WTF/wtf/text/StringConcatenate.h:80:30: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
   80 |     StringTypeAdapter<UChar>(UChar character)
      |                              ^~~~~
/build/source/Source/WTF/wtf/text/StringConcatenate.h:80:30: note: remove the '< >'
/build/source/Source/WTF/wtf/text/StringConcatenate.h:227:30: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
  227 |     StringTypeAdapter<String>(const String& string)
      |                              ^
/build/source/Source/WTF/wtf/text/StringConcatenate.h:227:30: note: remove the '< >'
In file included from /build/source/Source/WTF/wtf/text/StringConcatenate.h:839:
/build/source/Source/WTF/wtf/text/StringOperators.h:88:63: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
   88 |     StringTypeAdapter<StringAppend<StringType1, StringType2>>(StringAppend<StringType1, StringType2>& buffer)
      |                                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/build/source/Source/WTF/wtf/text/StringOperators.h:88:63: note: remove the '< >'
[  0%] Building CXX object Source/WebCore/CMakeFiles/ANGLESupport.dir/__/ThirdParty/ANGLE/src/compiler/translator/RegenerateStructNames.cpp.o
/build/source/Source/WTF/wtf/Assertions.cpp: In function 'void vprintf_stderr_with_prefix(const char*, const char*, __va_list_tag*)':
/build/source/Source/WTF/wtf/Assertions.cpp:152:53: error: call of overloaded 'make_unique<char []>(size_t)' is ambiguous
  152 |     auto formatWithPrefix = std::make_unique<char[]>(prefixLength + formatLength + 1);
      |                             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/memory:78,
                 from /build/source/Source/WTF/wtf/StdLibExtras.h:31:
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/unique_ptr.h:1091:5: note: candidate: 'std::__detail::__unique_ptr_array_t<_Tp> std::make_unique(size_t) [with _Tp = char []; __detail::__unique_ptr_array_t<_Tp> = __detail::__unique_ptr_array_t<char []>; size_t = long unsigned int]'
 1091 |     make_unique(size_t __num)
      |     ^~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:315:1: note: candidate: 'typename std::_Unique_if<T>::_Unknown_bound std::make_unique(size_t) [with T = char []; typename _Unique_if<T>::_Unknown_bound = unique_ptr<char [], default_delete<char []> >; size_t = long unsigned int]'
  315 | make_unique(size_t n)
      | ^~~~~~~~~~~
/build/source/Source/WTF/wtf/Assertions.cpp: In function 'void vprintf_stderr_with_trailing_newline(const char*, __va_list_tag*)':
/build/source/Source/WTF/wtf/Assertions.cpp:168:54: error: call of overloaded 'make_unique<char []>(size_t)' is ambiguous
  168 |     auto formatWithNewline = std::make_unique<char[]>(formatLength + 2);
      |                              ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/bits/unique_ptr.h:1091:5: note: candidate: 'std::__detail::__unique_ptr_array_t<_Tp> std::make_unique(size_t) [with _Tp = char []; __detail::__unique_ptr_array_t<_Tp> = __detail::__unique_ptr_array_t<char []>; size_t = long unsigned int]'
 1091 |     make_unique(size_t __num)
      |     ^~~~~~~~~~~
/build/source/Source/WTF/wtf/StdLibExtras.h:315:1: note: candidate: 'typename std::_Unique_if<T>::_Unknown_bound std::make_unique(size_t) [with T = char []; typename _Unique_if<T>::_Unknown_bound = unique_ptr<char [], default_delete<char []> >; size_t = long unsigned int]'
  315 | make_unique(size_t n)
      | ^~~~~~~~~~~
...

So I now ended up using an ubuntu docker container using the authors ubuntu ppa repository. Ugly, but at least it works..

My vibe coded Dockerfile:

FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
    && apt-get install -y ca-certificates curl software-properties-common \
    && add-apt-repository ppa:jean-francois-dockes/upnpp1 \
    && apt-get update \
    && apt-get install -y upplay \
    && rm -rf /var/lib/apt/lists/*
RUN useradd -m upplay
USER upplay
WORKDIR /home/upplay
ENV QT_SCALE_FACTOR=1.5
ENV QT_AUTO_SCREEN_SCALE_FACTOR=0
ENV QT_ENABLE_HIGHDPI_SCALING=0
ENV QT_FONT_DPI=120
ENV QT_QUICK_BACKEND=software
ENV QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu --disable-gpu-compositing"
ENV LIBGL_ALWAYS_SOFTWARE=1
CMD ["upplay"]%                                                                                                                                                                                                      

I’ve now found that eezupnp, even though it sadly is not open source, works better and natively on my NixOS machine (don’t need an ubuntu docker machine like for upplay). My vibe-coded package definition for eezupnp:

self: super:

let
  # Basic metadata
  pname = "eezupnp";
  version = "4.0.0";

  # Pick an FHS env builder that exists in your nixpkgs
  buildFHS =
    if super ? buildFHSUserEnv then
      super.buildFHSUserEnv
    else if super ? buildFHSEnv then
      super.buildFHSEnv
    else if super ? buildFHSUserEnvBubblewrap then
      super.buildFHSUserEnvBubblewrap
    else
      throw "No FHS env builder found in nixpkgs (buildFHSUserEnv / buildFHSEnv / buildFHSUserEnvBubblewrap)";

  eezupnp-unpacked = super.stdenv.mkDerivation {
    inherit pname version;
    src = super.fetchzip {
      url = "https://www.eezupnp.de/archives/${pname}-${version}.linux.gtk.x86_64.zip";
      sha256 = "aUno5CIDDWLa8jzdBIGFuUUXkAjBGXBthkWt1WkxTZs=";
    };
    dontBuild = true;
    installPhase = ''
      mkdir -p $out
      cp -R ./* $out/
    '';
  };
in
{
  eezupnp = buildFHS {
    name = pname;
    targetPkgs =
      pkgs: with pkgs; [
        glib
        gtk3

        xorg.libX11
        xorg.libXrender
        xorg.libXext
        xorg.libXrandr
        xorg.libXi
        xorg.libXfixes
        xorg.libXinerama

        cairo
        pango
        gdk-pixbuf

        alsa-lib
        fontconfig
        freetype
        libpng
        zlib
        dbus
      ];
    runScript = "${super.writeShellScriptBin "eezupnp-launch" ''
      cd ${eezupnp-unpacked}
      exec ./CP "$@"
    ''}/bin/eezupnp-launch";
  };
}

UPDATE: I’ve published packages to the NUR for both control point apps I’ve tried (besides gupnp-tools from the main nixpkgs repo):

nur.repos.thomas725.upplay
nur.repos.thomas725.eezupnp