Files
lgtv_audio_cap/test/run-tests.sh
T
Rene KievitsandClaude Opus 5 aae5a33283 Add a brightness-only sink: keep the grabber's colour, pulse with sound
Every existing HyperHDR route replaces whatever else is on the LEDs:
routes 1/2 hand HyperHDR's own audio effect a device to read, route 3
sends a synthetic spectrum image, and both take over via HyperHDR's
priority system. For a setup that already has a real colour source
(a screen grabber, a USB capture card) feeding an ambilight-style LED
run, none of that is what's wanted -- the colour should stay put and
only brightness should react.

Read HyperHDR's own source (sources/api/JSONRPC_schema/schema-adjustment.json)
rather than guess: "adjustment" is a post-processing command with a
scaleOutput parameter (0-2.0) that applies regardless of which
priority is currently active. Confirmed the wire format too --
sources/jsonserver/JsonClientConnection.cpp frames it as plain
newline-delimited JSON over TCP (default port 19444), nothing like the
length-prefixed Flatbuffers protocol the visualiser sink speaks, and
with no handshake or registration needed before the first write.

sink_hyperhdr_adjust.c sends only that: no image, no priority, so it
never competes with an existing grabber. Non-blocking connect with the
same poll()+SO_ERROR pattern net/hyperion.c already uses, reconnects
every 5s, rate-limited to 20 Hz (a HyperHDR command every audio block
would be pointless flooding), and resets scaleOutput to 1.0 on close
rather than leaving the LEDs stuck at whatever it last sent. Cross-
compiles clean under -Wall -Wextra on the real webOS toolchain.

Wired through the same path every other sink follows: registered in
sink.c/sink.h, defaults in config.c, fields in frontend/js/app.js
(SINK_FIELDS/SINK_HELP), mock.js and ui_smoke.js updated for the new
sink card. Bumped to 1.0.3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 14:36:31 +02:00

106 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Host-side tests. These build the parts of the service that are not tied to
# webOS with the system compiler and run them, so the risky code (FlatBuffers
# encoding, the capture pipeline, socket framing) is verified before anything
# is ever copied to a TV.
set -euo pipefail
cd "$(dirname "$0")/.."
CC="${CC:-cc}"
# verify_rtp.py imports the host receiver by path; without this it would leave a
# __pycache__ next to it.
export PYTHONDONTWRITEBYTECODE=1
OUT=$(mktemp -d)
trap 'rm -rf "$OUT"' EXIT
CFLAGS=(-std=c11 -Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE -Inative/src -O1 -g)
SOURCES=(
native/src/engine.c
native/src/config.c
native/src/dsp.c
native/src/common/log.c
native/src/common/json.c
native/src/common/ringbuf.c
native/src/capture/capture.c
native/src/capture/cap_pulse.c
native/src/capture/cap_alsa.c
native/src/capture/cap_exec.c
native/src/capture/cap_tone.c
native/src/net/flatbuf.c
native/src/net/hyperion.c
native/src/net/streamserv.c
native/src/sinks/sink.c
native/src/sinks/sink_hyperhdr.c
native/src/sinks/sink_hyperhdr_viz.c
native/src/sinks/sink_hyperhdr_adjust.c
native/src/sinks/sink_udp.c
native/src/sinks/sink_tcp.c
native/src/sinks/sink_http.c
)
echo "== Syntax-checking the webOS-only sources against stub headers"
for f in native/src/service.c native/src/main.c; do
"$CC" "${CFLAGS[@]}" -Itest/stubs -fsyntax-only "$f"
echo " ok $f"
done
echo
echo "== FlatBuffers wire format"
if python3 -c "import flatbuffers" 2>/dev/null; then
python3 test/verify_flatbuf.py
else
echo " SKIP: the 'flatbuffers' Python package is not installed"
echo " python3 -m venv /tmp/fbvenv && /tmp/fbvenv/bin/pip install flatbuffers"
echo " CC=$CC /tmp/fbvenv/bin/python test/verify_flatbuf.py"
fi
echo
echo "== RTP wire format, against the host receiver"
"$CC" "${CFLAGS[@]}" -o "$OUT/rtp_send" test/rtp_send.c "${SOURCES[@]}" -lpthread -lm
python3 test/verify_rtp.py "$OUT/rtp_send"
echo
echo "== Capture pipeline end to end"
"$CC" "${CFLAGS[@]}" -o "$OUT/engine_smoke" test/engine_smoke.c "${SOURCES[@]}" -lpthread -lm
"$OUT/engine_smoke"
echo
echo "== Unraid plugin"
python3 test/verify_unraid_plugin.py
echo
echo "== Receiver container"
if command -v docker >/dev/null 2>&1; then
docker build -f docker/Dockerfile -t lgtv-audiocap-receiver:test-run . >/dev/null 2>&1
docker run --rm lgtv-audiocap-receiver:test-run --help >/dev/null
echo " ok image builds and forwards --help"
docker rmi lgtv-audiocap-receiver:test-run >/dev/null 2>&1
else
echo " SKIP: docker is not installed"
fi
echo
echo "== Frontend"
if command -v node >/dev/null 2>&1; then
for f in frontend/js/*.js; do
node --check "$f"
echo " ok $f"
done
# jsdom is a test-only dependency; the app itself has none. `npm install`
# puts it in node_modules, or point JSDOM_PATH at an install elsewhere.
if [ -z "${JSDOM_PATH:-}" ] && [ -d node_modules/jsdom ]; then
JSDOM_PATH="$PWD/node_modules"
fi
JSDOM_PATH="${JSDOM_PATH:-/tmp/audiocap-domtest/node_modules}"
if NODE_PATH="$JSDOM_PATH" node -e "require('jsdom')" 2>/dev/null; then
NODE_PATH="$JSDOM_PATH" node test/ui_smoke.js
else
echo " SKIP: jsdom is not installed, so the page was not run"
echo " mkdir -p /tmp/audiocap-domtest && cd /tmp/audiocap-domtest && npm i jsdom"
fi
else
echo " SKIP: node is not installed"
fi