diff --git a/frontend/appinfo.json b/frontend/appinfo.json index f33af3c..d543072 100644 --- a/frontend/appinfo.json +++ b/frontend/appinfo.json @@ -1,6 +1,6 @@ { "id": "org.webosbrew.audiocap", - "version": "1.0.1", + "version": "1.0.2", "vendor": "Homebrew", "type": "web", "main": "index.html", diff --git a/frontend/index.html b/frontend/index.html index 33693f1..7d834f9 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,6 +3,10 @@ + + Audio Cap diff --git a/frontend/js/app.js b/frontend/js/app.js index e485043..a34f9f3 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -13,6 +13,16 @@ var ELEVATE = '/media/developer/apps/usr/palm/services/' + 'org.webosbrew.hbchannel.service/elevate-service'; + // Substituted into index.html at package time (tools/build.sh stage()). + // Unstaged — opened straight from the source tree, e.g. npm run serve — + // it is still the literal placeholder, which is exactly the tell that + // this isn't a packaged build. + function readAppVersion() { + var meta = document.querySelector('meta[name="app-version"]'); + var content = meta && meta.getAttribute('content'); + return content && content.indexOf('__') !== 0 ? content : 'dev build'; + } + var state = { settings: {}, status: null, @@ -22,6 +32,7 @@ persistent: true, bootLinked: false, diagnostics: null, + appVersion: readAppVersion(), }; var statusSub = null; @@ -192,8 +203,10 @@ // only read on the TV itself, is exactly the kind of thing a D-pad picker // exists for. Parsed from the same "pactl list short sources" text that // System > Run diagnostics already fetches — nothing new to ask the - // service for. Format is tab-separated: index, name, driver, sample_spec, - // state. + // service for. Stock PulseAudio tab-separates columns (index, name, + // driver, sample_spec, state), but split on any whitespace run rather than + // a literal tab: a TV's own pactl-alike is free to pad with spaces + // instead, and source names never contain embedded whitespace themselves. function pulseSourceOptions() { var diag = state.diagnostics && state.diagnostics.system; var text = diag && diag.pactlSources; @@ -202,7 +215,7 @@ return out; } text.split('\n').forEach(function (line) { - var cols = line.split('\t'); + var cols = line.trim().split(/\s+/); var name = cols[1]; if (!name) { return; @@ -526,6 +539,7 @@ var info = $('config-path'); UI.clear(info); + info.appendChild(infoItem('App version', state.appVersion)); info.appendChild(infoItem('Path', state.configPath || '—')); info.appendChild(infoItem('Storage', state.persistent ? 'Persistent' : 'Temporary (/tmp)')); diff --git a/frontend/js/mock.js b/frontend/js/mock.js index 974494f..b5003af 100644 --- a/frontend/js/mock.js +++ b/frontend/js/mock.js @@ -175,11 +175,13 @@ pulseSockets: ['/var/run/pulse/native'], // Realistic shape: a TV that mixes several per-app sinks down to // one common output, the case the device picker exists for. + // Space-padded, not tab-separated — some TVs' own pactl-alike + // formats it that way, and the parser has to tolerate both. pactlSources: [ - '0\ttpcm_output.monitor\tmodule-combine-sink.c\ts16le 2ch 48000Hz\tRUNNING', - '1\ttpmedia.monitor\tmodule-alsa-card.c\ts16le 2ch 48000Hz\tIDLE', - '2\ttpeffects.monitor\tmodule-alsa-card.c\ts16le 2ch 48000Hz\tIDLE', - '3\ttptts.monitor\tmodule-alsa-card.c\ts16le 2ch 48000Hz\tSUSPENDED', + '0 tpcm_output.monitor module-combine-sink.c s16le 2ch 48000Hz RUNNING', + '1 tpmedia.monitor module-alsa-card.c s16le 2ch 48000Hz IDLE', + '2 tpeffects.monitor module-alsa-card.c s16le 2ch 48000Hz IDLE', + '3 tptts.monitor module-alsa-card.c s16le 2ch 48000Hz SUSPENDED', ].join('\n'), alsaCards: ['0 [Loopback]: Loopback - Loopback'], alsaCapturePcms: ['00-01: Loopback PCM : playback 1 : capture 1'], diff --git a/package-lock.json b/package-lock.json index d318cb1..75f33eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lgtv-audio-cap", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lgtv-audio-cap", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@webosose/ares-cli": "^2.4.0", diff --git a/package.json b/package.json index 667fdaa..a5f6e36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lgtv-audio-cap", - "version": "1.0.1", + "version": "1.0.2", "private": true, "description": "Captures audio on an LG webOS 5/6 TV and streams it out \u2014 HyperHDR first, plus raw UDP, TCP and HTTP.", "keywords": [ diff --git a/servicefiles/package.json b/servicefiles/package.json index bde0171..ba85780 100644 --- a/servicefiles/package.json +++ b/servicefiles/package.json @@ -1,6 +1,6 @@ { "id": "org.webosbrew.audiocap.service", - "version": "1.0.1", + "version": "1.0.2", "description": "Captures TV audio and streams it to HyperHDR and other receivers", "main": "audiocap-service" } diff --git a/test/ui_smoke.js b/test/ui_smoke.js index 76fea64..ce128ba 100644 --- a/test/ui_smoke.js +++ b/test/ui_smoke.js @@ -114,6 +114,13 @@ async function main() { check('mock bus in use', window.Luna.available === false); check('settings loaded', !!(window.App.state.settings.capture)); eq('config path shown', $('config-path').textContent.indexOf('/var/lib/webosbrew') >= 0, true); + // This loads the raw source tree's index.html, not a packaged build, so + // the __APP_VERSION__ placeholder was never substituted — the fallback + // is the correct, honest thing to see here. + eq('unpackaged run shows the dev-build fallback, not a stale version', + window.App.state.appVersion, 'dev build'); + check('app version shown in the System panel', + $('config-path').textContent.indexOf('dev build') >= 0); console.log('status feed'); eq('starts stopped', $('state-pill').textContent, 'Stopped'); diff --git a/tools/build.sh b/tools/build.sh index 7186c0b..3fbcf0b 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -143,12 +143,14 @@ stage() { cp -R "$ROOT/frontend/." "$STAGE_APP/" # The mock only exists so the UI can be opened in a desktop browser. rm -f "$STAGE_APP/js/mock.js" - python3 - "$STAGE_APP/index.html" <<'EOF' -import re, sys -path = sys.argv[1] -html = open(path).read() + python3 - "$STAGE_APP/index.html" "$ROOT/frontend/appinfo.json" <<'EOF' +import json, re, sys +html_path, appinfo_path = sys.argv[1], sys.argv[2] +html = open(html_path).read() html = re.sub(r'\s*', '', html) -open(path, "w").write(html) +version = json.load(open(appinfo_path))["version"] +html = html.replace("__APP_VERSION__", version) +open(html_path, "w").write(html) EOF cp "$ROOT/servicefiles/services.json" "$STAGE_SERVICE/"