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>
106 lines
3.3 KiB
Bash
Executable File
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
|