fix(dlna): drive AVTransport v1, v2 and v3 renderers#23
Conversation
|
@Klaudioz Thank you for the contrib ! Were you able to test it on your Philips 50PUD6654/43 ? Note: I merged a branch requested by an other PR, there is some conflicts can you check it out ? |
Service lookup matched only "urn:schemas-upnp-org:service:AVTransport:1",
an exact string compare, so renderers publishing a newer version failed to
connect even though SSDP discovery listed them: version-tolerant M-SEARCH
answers a MediaRenderer:1 probe from a MediaRenderer:3 device, and the
mismatch only surfaced later when parsing the description.
creating AVTransport client: goupnp: service
"urn:schemas-upnp-org:service:AVTransport:1" not found within device
Look services up across v3, v2 and v1, newest first, via a shared
findService helper. UPnP requires a higher service version to stay
backward compatible with the actions of lower ones, and castor calls only
SetAVTransportURI, Play and GetProtocolInfo, unchanged since v1.
Apply the same treatment to the ConnectionManager lookup added in stupside#22.
That one fails soft rather than hard: a renderer publishing only
ConnectionManager:3 degrades to fallbackCaps, so it re-encodes streams it
could have copied. The copy path was unreachable on exactly the renderers
this commit makes connectable.
Hold generic goupnp.ServiceClients rather than the av1 wrappers: those
hardcode the v1 URN as the SOAP action namespace, which a strict v3
service can reject as an invalid action.
Observed on a Philips 50PUD6654/43, which exposes RenderingControl:3,
ConnectionManager:3 and AVTransport:3 only.
Claude-Session: https://claude.ai/code/session_01SapjS1H29hRzRbzJin212o
9b24f8c to
752654c
Compare
|
Thanks for taking a look! Conflicts: rebased onto Testing: confirmed working on the Philips 50PUD6654/43. It failed to connect at all before this change; it now connects and plays, and the log shows a While resolving the conflict I noticed Both lookups now go through a shared One design note: I dropped the Unrelated, but hit it while building to test — Happy to split the ConnectionManager change into its own PR if you'd rather keep them separate. |
All good, one PR works fine, thank you for the fix I really appreciate it. For the ➜ castor git:(main) ✗ make build
cmake -S third_party/whisper.cpp -B third_party/whisper.cpp/build_go -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_EXAMPLES=OFF \
-DCMAKE_C_FLAGS="-I/Users/kilian/Documents/git/castor/third_party/whisper.cpp/ggml/include"
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 3.10 will be removed from a future version of
CMake.
Update the VERSION argument <min> value. Or, use the <min>...<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier.
-- The C compiler identification is AppleClang 21.0.0.21000101
-- The CXX compiler identification is AppleClang 21.0.0.21000101
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Git: /usr/bin/git (found version "2.50.1 (Apple Git-155)")
-- The ASM compiler identification is AppleClang
-- Found assembler: /usr/bin/cc
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- sccache found, compilation results will be cached. Disable with GGML_CCACHE=OFF.
-- CMAKE_SYSTEM_PROCESSOR: arm64
-- GGML_SYSTEM_ARCH: ARM
-- Including CPU backend
-- Accelerate framework found
-- Could NOT find OpenMP_C (missing: OpenMP_C_FLAGS OpenMP_C_LIB_NAMES)
-- Could NOT find OpenMP_CXX (missing: OpenMP_CXX_FLAGS OpenMP_CXX_LIB_NAMES)
-- Could NOT find OpenMP (missing: OpenMP_C_FOUND OpenMP_CXX_FOUND)
CMake Warning at ggml/src/ggml-cpu/CMakeLists.txt:84 (message):
OpenMP not found
Call Stack (most recent call first):
ggml/src/CMakeLists.txt:445 (ggml_add_cpu_backend_variant_impl)
-- ARM detected
-- Performing Test GGML_COMPILER_SUPPORTS_FP16_FORMAT_I3E
-- Performing Test GGML_COMPILER_SUPPORTS_FP16_FORMAT_I3E - Failed
CMake Warning at ggml/src/ggml-cpu/CMakeLists.txt:146 (message):
ARM -march/-mcpu not found, -mcpu=native will be used
Call Stack (most recent call first):
ggml/src/CMakeLists.txt:445 (ggml_add_cpu_backend_variant_impl)
-- Performing Test GGML_MACHINE_SUPPORTS_dotprod
-- Performing Test GGML_MACHINE_SUPPORTS_dotprod - Success
-- Performing Test GGML_MACHINE_SUPPORTS_i8mm
-- Performing Test GGML_MACHINE_SUPPORTS_i8mm - Success
-- Performing Test GGML_MACHINE_SUPPORTS_sve
-- Performing Test GGML_MACHINE_SUPPORTS_sve - Failed
-- Performing Test GGML_MACHINE_SUPPORTS_nosve
-- Performing Test GGML_MACHINE_SUPPORTS_nosve - Success
-- Performing Test GGML_MACHINE_SUPPORTS_sme
-- Performing Test GGML_MACHINE_SUPPORTS_sme - Failed
-- Performing Test GGML_MACHINE_SUPPORTS_nosme
-- Performing Test GGML_MACHINE_SUPPORTS_nosme - Success
-- Checking for ARM features using flags:
-- -U__ARM_FEATURE_SVE
-- -U__ARM_FEATURE_SME
-- -mcpu=native+dotprod+i8mm+nosve+nosme
-- Performing Test HAVE_DOTPROD
-- Performing Test HAVE_DOTPROD - Success
-- Performing Test HAVE_SVE
-- Performing Test HAVE_SVE - Failed
-- Performing Test HAVE_MATMUL_INT8
-- Performing Test HAVE_MATMUL_INT8 - Success
-- Performing Test HAVE_FMA
-- Performing Test HAVE_FMA - Success
-- Performing Test HAVE_FP16_VECTOR_ARITHMETIC
-- Performing Test HAVE_FP16_VECTOR_ARITHMETIC - Success
-- Performing Test HAVE_SME
-- Performing Test HAVE_SME - Failed
-- Adding CPU backend variant ggml-cpu: -U__ARM_FEATURE_SVE;-U__ARM_FEATURE_SME;-mcpu=native+dotprod+i8mm+nosve+nosme
-- Looking for dgemm_
-- Looking for dgemm_ - found
-- Found BLAS: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework
-- BLAS found, Libraries: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework
-- BLAS found, Includes:
-- Including BLAS backend
-- Metal framework found
-- Including METAL backend
-- ggml version: 0.9.8
-- ggml commit: 9386f239
-- Configuring done (4.8s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/kilian/Documents/git/castor/third_party/whisper.cpp/build_go
cmake --build third_party/whisper.cpp/build_go --target whisper -j
[ 5%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-backend.cpp.o
[ 5%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml.c.o
[ 10%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/gguf.cpp.o
[ 10%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml.cpp.o
[ 12%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-threading.cpp.o
[ 15%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml-alloc.c.o
[ 20%] Building C object ggml/src/CMakeFiles/ggml-base.dir/ggml-quants.c.o
[ 20%] Building CXX object ggml/src/CMakeFiles/ggml-base.dir/ggml-opt.cpp.o
[ 22%] Linking CXX static library libggml-base.a
[ 22%] Built target ggml-base
[ 25%] Generate assembly for embedded Metal library
Embedding Metal library
[ 27%] Building C object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/ggml-cpu.c.o
[ 30%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/hbm.cpp.o
[ 35%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/amx/amx.cpp.o
[ 35%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/ggml-cpu.cpp.o
[ 37%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/ops.cpp.o
[ 40%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/vec.cpp.o
[ 42%] Building C object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/quants.c.o
[ 45%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/binary-ops.cpp.o
[ 47%] Building C object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/arch/arm/quants.c.o
[ 50%] Building CXX object ggml/src/ggml-blas/CMakeFiles/ggml-blas.dir/ggml-blas.cpp.o
[ 52%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/traits.cpp.o
[ 55%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/repack.cpp.o
[ 57%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/arch/arm/repack.cpp.o
[ 60%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/amx/mmq.cpp.o
[ 62%] Building CXX object ggml/src/CMakeFiles/ggml-cpu.dir/ggml-cpu/unary-ops.cpp.o
[ 65%] Building C object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal-device.m.o
[ 67%] Building CXX object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal-device.cpp.o
[ 70%] Building CXX object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal.cpp.o
[ 72%] Building ASM object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/autogenerated/ggml-metal-embed.s.o
[ 75%] Building CXX object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal-ops.cpp.o
[ 77%] Building CXX object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal-common.cpp.o
[ 80%] Building C object ggml/src/ggml-metal/CMakeFiles/ggml-metal.dir/ggml-metal-context.m.o
[ 82%] Linking CXX static library libggml-blas.a
[ 85%] Linking CXX static library libggml-cpu.a
clang: warning: argument unused during compilation: '-D GGML_METAL_EMBED_LIBRARY' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D GGML_SCHED_MAX_COPIES=4' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D _DARWIN_C_SOURCE' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D _XOPEN_SOURCE=600' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-O3' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-D NDEBUG' [-Wunused-command-line-argument]
[ 85%] Built target ggml-blas
[ 87%] Linking CXX static library libggml-metal.a
[ 87%] Built target ggml-cpu
[ 87%] Built target ggml-metal
[ 92%] Building CXX object ggml/src/CMakeFiles/ggml.dir/ggml-backend-dl.cpp.o
[ 92%] Building CXX object ggml/src/CMakeFiles/ggml.dir/ggml-backend-reg.cpp.o
[ 95%] Linking CXX static library libggml.a
[ 95%] Built target ggml
[ 97%] Building CXX object src/CMakeFiles/whisper.dir/whisper.cpp.o
[100%] Linking CXX static library libwhisper.a
[100%] Built target whisper
go build -o castor . |
Problem
connectDLNAlooked the transport service up by the exact URNurn:schemas-upnp-org:service:AVTransport:1, so renderers that publish a newer version could not be connected to — even thoughcastor scanlisted them:The gap between those two lines is version tolerance: SSDP
M-SEARCHforMediaRenderer:1is answered by aMediaRenderer:3device, so discovery succeeds, and the exact-match failure only surfaces later when parsing the description.The device in question, a Philips 50PUD6654/43, publishes:
AVTransport is there — just not at v1. This should affect any renderer advertising v2 or v3.
Fix
Look the service up across v3, v2 and v1, newest first. UPnP requires a higher service version to remain backward compatible with the actions of lower ones, and castor calls only
SetAVTransportURIandPlay, both unchanged since v1.dlnaDevicenow holds the genericgoupnp.ServiceClientinstead ofav1.AVTransport1. That wrapper hardcodesURN_AVTransport_1as the SOAP action namespace in everyPerformActionCtxcall, so reusing it for a v3 service would send a mismatchedSOAPACTIONthat a strict renderer can reject as an invalid action — and goupnp ships noav2/av3package to switch to. The two actions are now issued against the service type the device actually published.Tests
TestFindAVTransportcovers v1-only (existing behaviour unchanged), v3-only, v2-only, newest-wins when several versions are published, a service nested in a sub-device, and a renderer exposing no AVTransport at all.Not verified
Service selection is tested against in-memory device descriptions. I have not yet confirmed end-to-end playback on the v3 renderer —
go build ./...needs thethird_party/whisper.cppsubmodule, which wasn't checked out in my working copy, so I built and vetted./internal/device/only. Left as a draft for that reason; happy to confirm on hardware before it's marked ready.https://claude.ai/code/session_01SapjS1H29hRzRbzJin212o