Audio capture and streaming app for webOS 5/6
Captures the TV's audio and sends it out over several transports. The
primary one is HyperHDR: RTP/L16 to a host-side loopback device, since
HyperHDR has no network audio input of its own. A second route renders
the spectrum on the TV and sends FlatBuffers images to port 19400
instead, for setups where touching the host's sound config is not an
option.
native/ the service: capture backends (PulseAudio, ALSA, exec,
test tone, all dlopen-based), DSP, and one file per sink
frontend/ D-pad driven UI at a fixed 1920x1080
servicefiles/ native service manifest plus the boot script
host/ RTP receiver and the loopback installer for the HyperHDR
machine
tools/ build/package, asset generation, Homebrew Channel
manifest, on-TV probe
test/ host-side suites: FlatBuffers and RTP verified against
real decoders, the engine end to end, the page in jsdom
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+143
@@ -0,0 +1,143 @@
|
||||
#!/bin/sh
|
||||
# Reports what audio a rooted webOS TV actually exposes.
|
||||
#
|
||||
# Which capture backend works depends on the model and firmware: some sets run
|
||||
# PulseAudio with a monitor source, some only offer ALSA, some need an external
|
||||
# helper. Run this once on the TV and the answer is usually obvious.
|
||||
#
|
||||
# On the TV:
|
||||
# sh tv-probe.sh
|
||||
#
|
||||
# From here, over the Homebrew Channel's ssh:
|
||||
# ssh -p 9922 root@TV-IP 'sh -s' < tools/tv-probe.sh
|
||||
# ares-shell --device tv -r "$(cat tools/tv-probe.sh)"
|
||||
#
|
||||
# Reads only. Nothing here changes the TV.
|
||||
|
||||
header() {
|
||||
printf '\n=== %s\n' "$1"
|
||||
}
|
||||
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
show() {
|
||||
# show <label> <file>
|
||||
if [ -r "$2" ]; then
|
||||
printf -- '--- %s\n' "$1"
|
||||
cat "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
header "Identity"
|
||||
printf 'uid: %s\n' "$(id -u 2>/dev/null)"
|
||||
printf 'kernel: %s\n' "$(uname -r 2>/dev/null)"
|
||||
printf 'machine: %s\n' "$(uname -m 2>/dev/null)"
|
||||
for f in /etc/starfish-release /etc/os-release; do
|
||||
show "$f" "$f"
|
||||
done
|
||||
if [ -r /var/run/nyx/device_info.json ]; then
|
||||
printf -- '--- device info\n'
|
||||
cat /var/run/nyx/device_info.json
|
||||
printf '\n'
|
||||
fi
|
||||
|
||||
header "Sound devices"
|
||||
if [ -d /dev/snd ]; then
|
||||
ls -l /dev/snd
|
||||
else
|
||||
echo "no /dev/snd — the ALSA backend cannot work"
|
||||
fi
|
||||
|
||||
header "ALSA"
|
||||
show "cards" /proc/asound/cards
|
||||
show "pcm" /proc/asound/pcm
|
||||
show "modules" /proc/asound/modules
|
||||
if [ -d /proc/asound ]; then
|
||||
for dir in /proc/asound/card*/pcm*c; do
|
||||
[ -d "$dir" ] || continue
|
||||
printf -- '--- capture stream %s\n' "$dir"
|
||||
[ -r "$dir/info" ] && cat "$dir/info"
|
||||
done
|
||||
else
|
||||
echo "no /proc/asound — no ALSA on this firmware"
|
||||
fi
|
||||
|
||||
header "Tools"
|
||||
for tool in arecord aplay amixer pactl parec pacat pulseaudio gst-launch-1.0 ffmpeg luna-send; do
|
||||
if have "$tool"; then
|
||||
printf '%-16s %s\n' "$tool" "$(command -v "$tool")"
|
||||
else
|
||||
printf '%-16s -\n' "$tool"
|
||||
fi
|
||||
done
|
||||
|
||||
header "Libraries"
|
||||
# The service dlopen()s these rather than linking them, so what matters is
|
||||
# whether the file exists at all and under which soname.
|
||||
for pattern in \
|
||||
/usr/lib/libasound.so* /lib/libasound.so* \
|
||||
/usr/lib/libpulse.so* /lib/libpulse.so* \
|
||||
/usr/lib/libpulse-simple.so* /lib/libpulse-simple.so*
|
||||
do
|
||||
for lib in $pattern; do
|
||||
[ -e "$lib" ] && ls -l "$lib"
|
||||
done
|
||||
done 2>/dev/null
|
||||
|
||||
header "PulseAudio"
|
||||
ps ax 2>/dev/null | grep -i '[p]ulseaudio' || ps 2>/dev/null | grep -i '[p]ulseaudio' \
|
||||
|| echo "no pulseaudio process found"
|
||||
printf -- '--- sockets\n'
|
||||
for sock in /var/run/pulse/native /run/pulse/native /tmp/pulse-*/native \
|
||||
/var/run/pulse/*.socket /dev/socket/pulse/*
|
||||
do
|
||||
[ -e "$sock" ] && ls -l "$sock"
|
||||
done 2>/dev/null
|
||||
printf -- '--- environment of the audio daemon\n'
|
||||
for pid in $(ps ax 2>/dev/null | grep -i '[a]udiod\|[p]ulseaudio' | awk '{print $1}'); do
|
||||
if [ -r "/proc/$pid/environ" ]; then
|
||||
printf 'pid %s: ' "$pid"
|
||||
tr '\0' '\n' < "/proc/$pid/environ" | grep -i 'PULSE\|XDG_RUNTIME' | tr '\n' ' '
|
||||
printf '\n'
|
||||
fi
|
||||
done
|
||||
|
||||
if have pactl; then
|
||||
printf -- '--- pactl info\n'
|
||||
PULSE_SERVER="${PULSE_SERVER:-unix:/var/run/pulse/native}" pactl info 2>&1 | head -20
|
||||
printf -- '--- sources (monitors are what to capture)\n'
|
||||
PULSE_SERVER="${PULSE_SERVER:-unix:/var/run/pulse/native}" pactl list short sources 2>&1
|
||||
fi
|
||||
|
||||
if have arecord; then
|
||||
header "ALSA capture devices (arecord -l)"
|
||||
arecord -l 2>&1
|
||||
printf -- '--- PCMs (arecord -L)\n'
|
||||
arecord -L 2>&1 | head -40
|
||||
fi
|
||||
|
||||
header "What to put in the app"
|
||||
cat <<'EOF'
|
||||
Look at the output above and set Capture > Backend accordingly:
|
||||
|
||||
PulseAudio a pulseaudio process and a socket exist, and pactl lists a
|
||||
source ending in ".monitor". Use that name as the Device, or
|
||||
leave Device blank to take the default monitor.
|
||||
|
||||
ALSA /proc/asound lists a card with a capture PCM. Use hw:X,Y with
|
||||
the card and device numbers from "arecord -l".
|
||||
|
||||
Command neither works but arecord/parec/gst-launch is present. Set the
|
||||
Command to something that writes raw S16LE to stdout, e.g.
|
||||
arecord -D hw:0,0 -f S16_LE -r 48000 -c 2 -t raw
|
||||
|
||||
Test tone nothing at all. Use this to prove the network path works while
|
||||
you keep looking.
|
||||
|
||||
If everything is missing, the audio path on this firmware is locked inside the
|
||||
proprietary audio daemon. Every sink depends on captured audio, so the test
|
||||
tone is all that will run until a capture route is found — use it to prove the
|
||||
network side, then come back to this list.
|
||||
EOF
|
||||
Reference in New Issue
Block a user