Scaffold MobBridge audio output probe methods (Mob.Audio.output_status/level)#25
Conversation
Adds the app-owned Kotlin bridge methods that back mob's new audio output probes (Mob.Audio.output_status/0, output_level/1): - audioOutputStatus(): FloatArray — volume / mute / route / other-audio via AudioManager, returned as float[4] for the NIF to decode. - audioOutputLevel(source): FloatArray? — peak/RMS dB from a short-lived Visualizer on the global output mix (session 0), so it observes audio from native players that bypass Mob.Audio (e.g. a game's own AudioTrack). Returns null on failure (usually RECORD_AUDIO not granted); the mob NIF caches it with cacheOptional so a drifted bridge no-ops. ktlint clean (mix test --only lint); a focused template test pins both methods, the session-0 mix tap, and the peak/RMS measurement mode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Device verification (moto g power 2021, Android 11) showed a session-0 Visualizer fails with ERROR_NO_INIT for a normal app even with RECORD_AUDIO + MODIFY_AUDIO_SETTINGS — global output capture is privileged. So audioOutputLevel now meters Mob.Audio's OWN player session (audioPlayer.audioSessionId), which works with RECORD_AUDIO, and returns a length-1 error code (1 unsupported / 2 needs_record_audio / 3 not_playing) for the NIF to map. "mix" is reported unsupported; global capture moves to a separate MediaProjection plugin. Template test updated to assert the own-session tap and that session 0 is not used. ktlint clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review — approve (scaffold half of the output probes)The generated Merge alongside mob #54 (this is its Android half). The mob side uses Two follow-ups tracked on mob #54 apply here: the Android |
What
Scaffolds the app-owned Kotlin bridge methods backing mob's audio output probes (GenericJam/mob#54):
audioOutputStatus(): FloatArray— volume / mute / route / other-audio viaAudioManager, asfloat[4].audioOutputLevel(source): FloatArray— peak/RMS dB from a short-livedVisualizeron Mob.Audio's own player session (audioPlayer.audioSessionId), which works withRECORD_AUDIO. Returns a length-1 error code (1 unsupported / 2 needs_record_audio / 3 not_playing) the NIF maps to an atom.Why not session 0 (global mix)
The first cut tapped session 0 to observe foreign audio. Device testing (moto g power 2021, Android 11) showed a session-0
Visualizerfails withERROR_NO_INITeven withRECORD_AUDIO+MODIFY_AUDIO_SETTINGS— global output capture is privileged. SoaudioOutputLevelmeters only the app's own player session; global device-audio capture moves to a separate MediaProjection-based plugin (test-env dep).Tests
mix test --only lintgenerates a project and lints the real Kotlin).audioPlayer?.audioSessionId) and that session 0 is not used.Merge alongside GenericJam/mob#54.
🤖 Generated with Claude Code