Restrict the brightness sink to one app, picked by name not typed
Confirmed the brightness command applies globally, not per-LED
(serverinfo showed exactly one adjustment object, "id": "default",
covering the whole string), so no LED-count configuration is needed
for this at all -- that question resolved itself once the mechanism
was actually inspected instead of assumed.
For "only react while Spotify is running": only one app can be in the
foreground on webOS at a time, so a "capture the current app" button
in this app's own UI can never work -- pressing it means this app is
foreground, not Spotify. The only workable UI is picking a target from
every *installed* app by name, regardless of what's currently running.
That needed a new native capability this service never had: calling
OUT to another Luna service, not just being called. Two additions:
foreground_app.c subscribes once, at startup, to
com.webos.applicationManager/getForegroundAppInfo
and keeps a thread-safe cache the audio thread can
read without a blocking Luna call
service.c new listApps method, bridging to
com.webos.applicationManager/listApps so the
frontend never has to call another service
directly -- same rule as everywhere else here
Until the subscription has delivered at least one reply, a restricted
sink treats the target app as inactive, not active -- reacting to
audio when the user explicitly restricted it to one app would be the
wrong failure mode. Verified end to end on the host: engine_smoke.c
opens the sink with a restriction set, confirms it reports itself
correctly inactive against the stub Luna bus (which always "fails" to
call out, exactly like a real host with no bus).
Needed real, linkable stub bodies for LSCall/LSCallOneReply/
LSCallCancel/LSMessageGetPayload/LSErrorInit/LSErrorFree
(test/stubs/luna-service2/lunaservice_stub.c) since foreground_app.c
is the first source file here that's actually linked into a host test
binary rather than only syntax-checked -- service.c/main.c's existing
stub declarations were never called, only compiled against. Confirmed
those really are the correct symbol names by cross-compiling clean
against the real webOS SDK's actual libluna-service2, not just the
stub.
Bumped to 1.0.5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e9f6c87d27
commit
d3e4cb6410
+17
-2
@@ -112,6 +112,19 @@ and what a given build actually acts on are not always the same thing.
|
||||
| `level` | `"rms"` | `rms` (steadier) or `peak` (punchier) |
|
||||
| `minBrightness` | `20` | brightness (0-100) during silence |
|
||||
| `maxBrightness` | `100` | brightness (0-100) at full level; HyperHDR does not go above 100 |
|
||||
| `restrictToApp` | `""` | a webOS app id; blank means always active |
|
||||
|
||||
`restrictToApp` is set from a picker of installed apps in the UI (by name,
|
||||
never typed), backed by a new `listApps` Luna method that proxies to
|
||||
`com.webos.applicationManager/listApps` — the frontend never calls another
|
||||
service's Luna API directly, everything goes through this service, same as
|
||||
everywhere else. The service also subscribes once, at startup, to
|
||||
`com.webos.applicationManager/getForegroundAppInfo` to know which app is
|
||||
currently in front. Until that subscription has delivered at least one
|
||||
reply, a restricted sink treats the target app as *not* active — the safe
|
||||
failure mode, since silently reacting to audio when the user explicitly
|
||||
restricted it to one app would be the wrong one. `getDiagnostics` exposes
|
||||
the live value as `foregroundApp` if you want to confirm tracking is working.
|
||||
|
||||
### `udp`, `tcp`, `http`
|
||||
|
||||
@@ -149,7 +162,8 @@ luna-send -n 1 -f luna://org.webosbrew.audiocap.service/getStatus '{}'
|
||||
| `resetConfig` | `{}` | `{saved, settings}` |
|
||||
| `listBackends` | `{}` | `{backends:[{id,name,description,available}]}` |
|
||||
| `listSinks` | `{}` | `{sinks:[{id,name,description}]}` |
|
||||
| `getDiagnostics` | `{}` | `{backends, system}` — see below |
|
||||
| `listApps` | `{}` | `{apps:[{id,title}]}` — every installed app, for the "restrict to app" picker |
|
||||
| `getDiagnostics` | `{}` | `{backends, system, foregroundApp}` — see below |
|
||||
| `getLogs` | `{"clear":true}` optional | `{logs}` |
|
||||
| `quit` | `{}` | ends the process; the next call starts a new one |
|
||||
|
||||
@@ -199,7 +213,8 @@ Each sink adds its own fields. `packetsSent`/`bytesSent`/`sendErrors` for the
|
||||
datagram sinks, `clients`/`droppedBytes` for the stream servers,
|
||||
`connected`/`registered`/`framesSent`/`connectFailures`/`lastError` for the
|
||||
visualiser, `connected`/`updatesSent`/`minBrightness`/`maxBrightness`/`lastError`
|
||||
for the brightness sink.
|
||||
for the brightness sink, plus `restrictToApp`/`restrictedAppActive` when a
|
||||
restriction is set.
|
||||
|
||||
### Diagnostics
|
||||
|
||||
|
||||
@@ -186,6 +186,9 @@ service.c the Luna methods and the status subscription
|
||||
engine.c the capture thread: read a block, analyse it, hand it to every sink
|
||||
config.c load/merge/atomic-save of config.json
|
||||
dsp.c peak/RMS envelopes and the 16-band analysis
|
||||
foreground_app.c tracks which app is in front, for the "restrict to app"
|
||||
brightness option -- the one place this service calls out
|
||||
to another Luna service instead of being called
|
||||
capture/ one file per backend, all dlopen-based
|
||||
sinks/ one file per output
|
||||
net/ RTP, FlatBuffers, the shared stream server
|
||||
|
||||
@@ -195,6 +195,15 @@ TV ──RTP or local──► audiocap-service ──JSON-RPC "adjustment"─
|
||||
| Follows | Average level (steadier) or Peak level (punchier) |
|
||||
| Minimum brightness | `0`-`100`; applied during quiet parts |
|
||||
| Maximum brightness | `0`-`100`; applied at full level. HyperHDR does not go above 100 |
|
||||
| Restrict to app | optional — only react to audio while one specific app is in the foreground |
|
||||
|
||||
*Restrict to app* is picked from a list of installed apps by name (e.g.
|
||||
"Spotify"), never typed — only one app can be foreground at a time, so
|
||||
there is no way to "capture the current app" from a button in this app's
|
||||
own UI; you'd just be capturing yourself. Until the TV confirms which app
|
||||
is actually in front, the sink treats the target as inactive rather than
|
||||
guessing yes, so it can't accidentally react to the wrong thing while
|
||||
starting up.
|
||||
|
||||
Needs a working capture source the same as every other route — see the top
|
||||
of this document for picking one. On close, the sink resets brightness to
|
||||
|
||||
Reference in New Issue
Block a user