diff --git a/data/runs.json b/data/runs.json index 97be9c8..561bc40 100644 --- a/data/runs.json +++ b/data/runs.json @@ -742,5 +742,21 @@ "output": "hook raiseToast answered: \"shown\"\ngray box: the app was idle", "caption": "`mobium hook raiseToast \"Toast raised by test script\"` on MobiumApp, Android 15 emulator, launched with `--gray-box`: the app's own toast says what the hook was sent", "after": "/img/shots/app_hook-0-after.jpg" + }, + "app_audio[0]": { + "tool": "app_audio", + "index": 0, + "command": "mobium audio start --app dev.mobium.mobiumapp", + "verbatim": true, + "exit": 0, + "output": "capturing audio — stop it with action \"stop\" and a path" + }, + "app_audio[1]": { + "tool": "app_audio", + "index": 1, + "command": "mobium audio stop -o heard.wav --expect 440", + "verbatim": true, + "exit": 0, + "output": "saved …/heard.wav: 3.746s of audio: 0.0–0.5s silence, 0.5–0.6s sound, no one pitch (-46 dBFS), 0.6–2.6s 440 Hz (-42 dBFS), 2.6–3.7s silence — at media volume 5 of 15" } } diff --git a/examples/canonical.json b/examples/canonical.json index 042486b..8bfa89d 100644 --- a/examples/canonical.json +++ b/examples/canonical.json @@ -38,6 +38,29 @@ } } ], + "app_audio": [ + { + "title": "Start capturing what an app plays", + "cli": "mobium audio start --app dev.mobium.mobiumapp", + "args": { + "action": "start", + "app": "dev.mobium.mobiumapp" + } + }, + { + "title": "Stop, save the capture, and assert what was heard", + "cli": "mobium audio stop -o heard.wav --expect 440", + "args": { + "action": "stop", + "path": "heard.wav", + "expect": [ + { + "hz": 440 + } + ] + } + } + ], "app_background": [ { "title": "Send the app away for five seconds, and bring it back", diff --git a/examples/dotnet.json b/examples/dotnet.json index 9e94b30..13058aa 100644 --- a/examples/dotnet.json +++ b/examples/dotnet.json @@ -21,6 +21,14 @@ "code": "device.Appearance(\"dark\");" } ], + "app_audio": [ + { + "code": "device.AudioStart(\"dev.mobium.mobiumapp\");" + }, + { + "code": "var heard = device.AudioExpect(\"heard.wav\", new List>\n{\n new Dictionary { [\"hz\"] = 440 },\n});" + } + ], "app_background": [ { "code": "device.Background(5);" diff --git a/examples/go.json b/examples/go.json index cac0fec..17908c3 100644 --- a/examples/go.json +++ b/examples/go.json @@ -21,6 +21,14 @@ "code": "mode, err := dev.Appearance(ctx, \"dark\")\nif err != nil {\n\treturn err\n}\nfmt.Println(\"appearance is now\", mode)" } ], + "app_audio": [ + { + "code": "if _, err := dev.AudioStart(ctx, \"dev.mobium.mobiumapp\"); err != nil {\n\treturn err\n}" + }, + { + "code": "heard, err := dev.AudioExpect(ctx, \"heard.wav\", []mobium.AudioExpected{{Hz: 440}}, 0)\nif err != nil {\n\treturn err\n}\nfmt.Println(heard.Path, len(heard.Timeline), \"segments\")" + } + ], "app_background": [ { "code": "// \"\" means the app in front.\nif err := dev.Background(ctx, 5, \"\"); err != nil {\n\treturn err\n}" diff --git a/examples/java.json b/examples/java.json index 33ca858..482d90b 100644 --- a/examples/java.json +++ b/examples/java.json @@ -21,6 +21,14 @@ "code": "String mode = device.appearance(\"dark\"); // \"dark\", read back" } ], + "app_audio": [ + { + "code": "device.audioStart(\"dev.mobium.mobiumapp\");" + }, + { + "code": "Map heard = device.audioExpect(\"heard.wav\", List.of(Map.of(\"hz\", 440)), null);\nSystem.out.println(heard.get(\"timeline\"));" + } + ], "app_background": [ { "code": "device.background(5); // back in front, resumed, when this returns" diff --git a/examples/javascript.json b/examples/javascript.json index f326e85..2e71940 100644 --- a/examples/javascript.json +++ b/examples/javascript.json @@ -21,6 +21,14 @@ "code": "await device.appearance('dark')" } ], + "app_audio": [ + { + "code": "await device.audio({ action: 'start', app: 'dev.mobium.mobiumapp' })" + }, + { + "code": "const heard = await device.audio({ action: 'stop', path: 'heard.wav', expect: [{ hz: 440 }] })\nconsole.log(heard.timeline)" + } + ], "app_background": [ { "code": "await device.background(5)" diff --git a/examples/no-picture.json b/examples/no-picture.json index b1ea093..827d9f2 100644 --- a/examples/no-picture.json +++ b/examples/no-picture.json @@ -1,5 +1,6 @@ { "apps": "it lists what is installed, and nothing on the screen changes.", + "audio": "it captures what the device plays, and answers with a timeline of sound, silence and pitch; nothing on the screen changes.", "audit": "it reads the platform's audit of the screen, and nothing on the screen changes.", "background": "the app is off the screen for the seconds it is away, and back in front when the command returns.", "biometric": "what it presents goes to a prompt the app put up, and the app's own screen says what it made of it.", diff --git a/examples/python.json b/examples/python.json index 5445334..996cd61 100644 --- a/examples/python.json +++ b/examples/python.json @@ -21,6 +21,14 @@ "code": "device.appearance(\"dark\")" } ], + "app_audio": [ + { + "code": "device.audio(\"start\", app=\"dev.mobium.mobiumapp\")" + }, + { + "code": "heard = device.audio(\"stop\", \"heard.wav\", expect=[{\"hz\": 440}])\nfor segment in heard[\"timeline\"]:\n print(segment)" + } + ], "app_background": [ { "code": "device.background(5)" diff --git a/scripts/capture.py b/scripts/capture.py index ab69f74..ce21362 100644 --- a/scripts/capture.py +++ b/scripts/capture.py @@ -148,6 +148,10 @@ def app_screen(name): before=True, after=True, pause=2.0), dict(tool="app_record", i=0, setup=settings_root()), dict(tool="app_record", i=1, setup=["swipe up"]), + # A capture of MobiumApp's Audio Demo: started there, then its 440 Hz tone + # played for two seconds, so the stop's expect has what it asks for. + dict(tool="app_audio", i=0, setup=app_screen("Audio Demo") + ["wait testid=audioState"]), + dict(tool="app_audio", i=1, setup=["tap testid=audioTone", "$sleep 3"]), dict(tool="app_list_apps", i=0), dict(tool="app_contexts", i=0, setup=app_screen("WebViews") + ["tap 'text=Plain page'", "wait text=Back"], after=True),