mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Release the tuner noise graph after a silent dial release
A release that only selects a station now stops the looping noise source and suspends its AudioContext. The qa-radio dial scenarios start from an active stream, or expect a silent release from a stopped Radio.
This commit is contained in:
1 parent
857b007fb1
commit
cfc83a6078
3 files changed
+62
-3
No files matched your search
+12
-2
@@ -3073,20 +3073,27 @@ async function main() {
|
||||
expectedSlot: targetIndex,
|
||||
previewPlayDelta: previewPlays - playsBefore,
|
||||
commitPlayDelta: window.__qaRadioPlayCalls.length - playsBefore,
|
||||
audioState: state.audioState,
|
||||
tuningStatic: state.tuningStatic,
|
||||
samples,
|
||||
spread: Math.max(...samples) - Math.min(...samples),
|
||||
};
|
||||
});
|
||||
check(
|
||||
'pointer preview never plays and release commits the nearest station once without a needle sweep',
|
||||
'from a stopped Radio, pointer release only selects the nearest station, silently and without a needle sweep',
|
||||
tunerDirectRelease.targetId
|
||||
&& tunerDirectRelease.selectedId === tunerDirectRelease.targetId
|
||||
&& tunerDirectRelease.sliderSlot === tunerDirectRelease.expectedSlot
|
||||
&& tunerDirectRelease.previewPlayDelta === 0
|
||||
&& tunerDirectRelease.commitPlayDelta === 1
|
||||
&& tunerDirectRelease.commitPlayDelta === 0
|
||||
&& tunerDirectRelease.audioState === 'stopped'
|
||||
&& !tunerDirectRelease.tuningStatic
|
||||
&& tunerDirectRelease.spread < 0.5,
|
||||
JSON.stringify(tunerDirectRelease),
|
||||
);
|
||||
// The release plays only if a stream was active when the drag began.
|
||||
await page.evaluate(() => window.__godsEyeView.dataManager.layers.get('radio').module.togglePlayback({ origin: 'user' }));
|
||||
await page.waitForFunction(() => window.__godsEyeView.dataManager.layers.get('radio').module.getUIState().audioState === 'playing');
|
||||
// Earlier cases scroll and resize the directory. Bring the physical drag
|
||||
// target back into its scroller before deriving viewport mouse coordinates.
|
||||
await page.$eval('#radio-tuner-slider', (slider) => slider.scrollIntoView({ block: 'center', inline: 'nearest' }));
|
||||
@@ -3494,6 +3501,9 @@ async function main() {
|
||||
});
|
||||
});
|
||||
await sleep(500);
|
||||
// Next left the Radio stopped; a release plays only from an active stream.
|
||||
await page.evaluate(() => window.__godsEyeView.dataManager.layers.get('radio').module.togglePlayback({ origin: 'user' }));
|
||||
await page.waitForFunction(() => window.__godsEyeView.dataManager.layers.get('radio').module.getUIState().audioState === 'playing');
|
||||
const failedTuner = await page.evaluate(async () => {
|
||||
const gev = window.__godsEyeView;
|
||||
const slider = document.getElementById('radio-tuner-slider');
|
||||
|
||||
@@ -271,3 +271,50 @@ test('a dial release plays only if a stream was active when the drag began', asy
|
||||
assert.equal(state.playingStationId, ids[2]);
|
||||
});
|
||||
});
|
||||
|
||||
// Records the tuner noise graph so a test can see whether it was released.
|
||||
function withFakeAudioContext(body) {
|
||||
const log = { contexts: [], sources: [] };
|
||||
const node = () => ({ connect() {}, disconnect() {} });
|
||||
class FakeAudioContext {
|
||||
constructor() {
|
||||
Object.assign(this, { state: 'suspended', sampleRate: 8000, currentTime: 0, destination: {} });
|
||||
log.contexts.push(this);
|
||||
}
|
||||
resume() { this.state = 'running'; return Promise.resolve(); }
|
||||
suspend() { this.state = 'suspended'; return Promise.resolve(); }
|
||||
close() { this.state = 'closed'; return Promise.resolve(); }
|
||||
createBuffer(_channels, length) { return { getChannelData: () => new Float32Array(length) }; }
|
||||
createBufferSource() {
|
||||
const source = { ...node(), started: false, stopped: false, start() { this.started = true; }, stop() { this.stopped = true; } };
|
||||
log.sources.push(source);
|
||||
return source;
|
||||
}
|
||||
createBiquadFilter() { return { ...node(), frequency: { value: 0 }, Q: { value: 0 } }; }
|
||||
createGain() {
|
||||
return { ...node(), gain: { value: 0, cancelScheduledValues() {}, setValueAtTime() {}, linearRampToValueAtTime() {} } };
|
||||
}
|
||||
}
|
||||
const original = globalThis.AudioContext;
|
||||
globalThis.AudioContext = FakeAudioContext;
|
||||
return Promise.resolve(body(log)).finally(() => {
|
||||
if (original === undefined) delete globalThis.AudioContext;
|
||||
else globalThis.AudioContext = original;
|
||||
});
|
||||
}
|
||||
|
||||
test('a silent dial release stops the tuner noise and suspends its audio context', async () => {
|
||||
await withFakeAudioContext(async ({ contexts, sources }) => {
|
||||
await withLayer([], async ({ playUrls }) => {
|
||||
radioLayer.selectStation(ids[0], { autoplay: false });
|
||||
assert.equal(radioLayer.beginTuning(), true);
|
||||
radioLayer.previewTuningStation(ids[1], { rotate: false });
|
||||
assert.equal(radioLayer.commitTuningStation(ids[1], { origin: 'user' }).ok, true);
|
||||
await settle();
|
||||
assert.deepEqual(playUrls, []);
|
||||
assert.equal(sources[0].started, true);
|
||||
assert.equal(sources[0].stopped, true, 'noise source still looping');
|
||||
assert.equal(contexts[0].state, 'suspended', 'audio context still running');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -214,7 +214,9 @@ export function createTuning({ state: layerState, services, parts, source }) {
|
||||
layerState._playFallbackFocus = null;
|
||||
layerState._playFallbackOrigin = 'programmatic';
|
||||
layerState._playFallbackAttemptId = null;
|
||||
parts.tuningNoise.syncTuningNoiseGain();
|
||||
// Static covers only a connecting stream; a silent release frees the noise graph.
|
||||
if (autoplay) parts.tuningNoise.syncTuningNoiseGain();
|
||||
else parts.tuningNoise.clearRadioTuningNoise({ emit: false });
|
||||
parts.presentation.emitState();
|
||||
const selected = parts.selection.selectRadioStation(frozenStation.id, {
|
||||
autoplay,
|
||||
|
||||
Reference in new issue
Block a user