Files
lgtv_audio_cap/frontend/index.html
T
Rene KievitsandClaude Opus 5 f0f68a1aa7 Tolerate space-padded pactl output, and show the running app version
The device-source parser assumed pactl list short sources is strictly
tab-separated, true for stock PulseAudio but not guaranteed for a
TV's own heavily customized audio stack (this one names sources
tpcm_output/tpmedia/tptts/... — clearly not vanilla). A different
separator would have silently produced zero parsed sources with no
error, and the picker's own `when` guard would then just hide the row
entirely rather than show anything broken. Split on any whitespace
run instead of a literal tab; source names never contain embedded
whitespace, so this is strictly more permissive with no new failure
mode. Confirmed end to end on real hardware: tptts.monitor lit up
during the accessibility voice guide and reached HyperHDR.

Also: the System panel now shows the app's actual running version,
read from a <meta> tag substituted at package time (tools/build.sh
stage()) from frontend/appinfo.json — not hand-maintained, so it can't
drift from what was actually built. Requested after a version bump
alone wasn't enough to tell whether a reinstall had truly picked up
new files versus served something cached along the way; this settles
that question by inspection instead of by inference. Bumped to 1.0.2.

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

128 lines
4.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=1920, initial-scale=1">
<!-- Substituted at package time from frontend/appinfo.json (tools/build.sh
stage()), so what the System panel shows is what actually got built
into this ipk — not something that can itself go stale in a cache. -->
<meta name="app-version" content="__APP_VERSION__">
<title>Audio Cap</title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div id="app">
<header id="header">
<div class="brand">
<h1>Audio Cap</h1>
<div class="subtitle">TV audio to HyperHDR and friends</div>
</div>
<div class="header-status">
<span id="state-pill" class="pill">Connecting</span>
<span id="uptime" class="uptime"></span>
</div>
<button id="power" type="button" class="focusable btn primary">Start</button>
</header>
<nav id="tabs">
<button type="button" class="focusable tab" data-panel="panel-status">Status</button>
<button type="button" class="focusable tab" data-panel="panel-sinks">Outputs</button>
<button type="button" class="focusable tab" data-panel="panel-capture">Capture</button>
<button type="button" class="focusable tab" data-panel="panel-system">System</button>
</nav>
<main id="content">
<section id="panel-status" class="panel">
<div class="card">
<h2>Level</h2>
<div class="meter">
<div class="meter-row">
<span class="meter-label">Peak</span>
<div id="meter-peak" class="bar peak"><div class="bar-fill"></div></div>
<span id="meter-peak-db" class="meter-db">—</span>
</div>
<div class="meter-row">
<span class="meter-label">RMS</span>
<div id="meter-rms" class="bar rms"><div class="bar-fill"></div></div>
<span id="meter-rms-db" class="meter-db">—</span>
</div>
</div>
<div id="bands" class="bands"></div>
<div id="clip" class="clip hidden">Clipping</div>
</div>
<div class="card">
<h2>Capture</h2>
<div id="capture-info" class="info-grid"></div>
</div>
<div class="card">
<h2>Outputs</h2>
<div id="sink-status" class="sink-status">
<div class="muted">Not running.</div>
</div>
</div>
<div id="error-card" class="card error hidden">
<h2>Error</h2>
<div id="error-text"></div>
</div>
</section>
<section id="panel-sinks" class="panel hidden">
<div id="sink-cards"></div>
</section>
<section id="panel-capture" class="panel hidden">
<div class="card">
<h2>Source</h2>
<div id="capture-fields"></div>
</div>
<div class="card">
<h2>Level follower</h2>
<p class="blurb">
How quickly the reported level rises and falls. Lower is faster.
</p>
<div id="dsp-fields"></div>
</div>
</section>
<section id="panel-system" class="panel hidden">
<div class="card">
<h2>Service</h2>
<div id="system-fields"></div>
</div>
<div class="card">
<h2>Diagnostics</h2>
<p class="blurb">
What the service can see on this TV: audio libraries, capture
devices and whether it is running as root.
</p>
<div class="actions">
<button id="run-diagnostics" type="button" class="focusable btn">Run diagnostics</button>
<button id="load-logs" type="button" class="focusable btn">Show log</button>
<button id="clear-logs" type="button" class="focusable btn">Clear log</button>
</div>
<pre id="output" class="output hidden"></pre>
</div>
<div class="card">
<h2>Settings file</h2>
<div id="config-path" class="info-grid"></div>
<div class="actions">
<button id="reset-config" type="button" class="focusable btn danger">Reset to defaults</button>
</div>
</div>
</section>
</main>
<div id="toast" class="toast hidden"></div>
</div>
<script src="js/mock.js"></script>
<script src="js/luna.js"></script>
<script src="js/nav.js"></script>
<script src="js/ui.js"></script>
<script src="js/app.js"></script>
</body>
</html>