Diagnosing capture on a real TV meant reading pactlSources off the screen and typing an exact PulseAudio source name back in through the same remote-driven text field — no way to copy-paste, easy to mistype, and the one piece of information (which source, if any, is actually RUNNING) was buried in a JSON dump. Added two choice() pickers bound to the same capture.device setting: one built from pactlSources (pulse/auto backends), one built from alsaCapturePcms (alsa backend), both parsed from diagnostics the service already collects — no new Luna method needed. Diagnostics already run once at boot, so the picker is populated immediately, before the user ever presses "Run diagnostics" by hand. Picking a value writes straight into capture.device, and the plain text field stays as the fallback for anything the parser misses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
88 lines
2.7 KiB
XML
88 lines
2.7 KiB
XML
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
|
<!DOCTYPE PLUGIN [
|
|
<!ENTITY name "lgtv-audiocap-loopback">
|
|
<!ENTITY author "Crylia">
|
|
<!ENTITY version "2026.08.26">
|
|
<!ENTITY pluginURL "https://git.crylia.de/Crylia/lgtv_audio_cap/raw/branch/main/unraid/&name;.plg">
|
|
]>
|
|
|
|
<!--
|
|
This plugin does exactly one thing: load the ALSA loopback (snd-aloop) that
|
|
the LG TV Audio Cap RTP receiver plays into, and make that persist across an
|
|
Unraid reboot. Everything else - actually receiving the TV's audio and
|
|
writing it into the loopback - runs as a normal Docker container (see
|
|
docker/Dockerfile in the project repo), because that part doesn't need
|
|
bare-metal access. Only the kernel module load does: Unraid boots from a
|
|
read-only USB image each time, so anything not re-applied via /boot/config/go
|
|
or a plugin is gone on the next boot, and a container can't load a host
|
|
kernel module for itself.
|
|
|
|
hw:Loopback,0,0 - playback end, feed this to the receiver container
|
|
hw:Loopback,1,0 - capture end, point HyperHDR's sound capture at this
|
|
-->
|
|
|
|
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="6.9.0">
|
|
|
|
<CHANGES>
|
|
###2026.08.26
|
|
- Initial release.
|
|
</CHANGES>
|
|
|
|
<FILE Run="/bin/bash">
|
|
<INLINE>
|
|
set -e
|
|
NAME="&name;"
|
|
MARK="# ${NAME}: load ALSA loopback for LG TV Audio Cap (do not remove this line by hand)"
|
|
LOAD_CMD="/sbin/modprobe snd-aloop index=10 pcm_substreams=1 id=Loopback"
|
|
GO=/boot/config/go
|
|
|
|
echo "Installing ${NAME} &version;"
|
|
|
|
if ! $LOAD_CMD 2>/tmp/${NAME}.err; then
|
|
echo "warning: snd-aloop failed to load, see /tmp/${NAME}.err"
|
|
echo " this Unraid build's kernel may not include it"
|
|
fi
|
|
|
|
if ! grep -qF "$MARK" "$GO" 2>/dev/null; then
|
|
{
|
|
echo "$MARK"
|
|
echo "$LOAD_CMD"
|
|
} >> "$GO"
|
|
echo "Added the loopback load to $GO -- it will now load on every boot."
|
|
else
|
|
echo "$GO already loads the loopback; left it alone."
|
|
fi
|
|
|
|
echo ""
|
|
echo "Done. Check: cat /proc/asound/cards | grep -i loopback"
|
|
echo "In your receiver container's device settings, use hw:Loopback,0,0."
|
|
echo "In HyperHDR's sound capture settings, use hw:Loopback,1,0."
|
|
</INLINE>
|
|
</FILE>
|
|
|
|
<FILE Run="/bin/bash" Method="remove">
|
|
<INLINE>
|
|
set -e
|
|
NAME="&name;"
|
|
MARK="# ${NAME}: load ALSA loopback for LG TV Audio Cap (do not remove this line by hand)"
|
|
GO=/boot/config/go
|
|
|
|
if [ -f "$GO" ]; then
|
|
if grep -qF "$MARK" "$GO"; then
|
|
awk -v mark="$MARK" '
|
|
$0 == mark { skip = 1; next }
|
|
skip > 0 { skip--; next }
|
|
{ print }
|
|
' "$GO" > "${GO}.tmp"
|
|
mv "${GO}.tmp" "$GO"
|
|
echo "Removed the loopback load from $GO."
|
|
fi
|
|
fi
|
|
|
|
/sbin/rmmod snd_aloop 2>/dev/null || true
|
|
echo "${NAME} removed. The loopback will not load on the next boot."
|
|
</INLINE>
|
|
</FILE>
|
|
|
|
</PLUGIN>
|