Commit fb6d0dcd authored by Wei Lee's avatar Wei Lee Committed by Chromium LUCI CQ

[CCA] Remove timeout mechanism for playing sound

We can use 'ended' event instead of timeout.

Bug: b/172341904
Test: Manually
Change-Id: I9f2704aa5edc41ba5a04c9d02e0824778d3d59e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2640515
Commit-Queue: Wei Lee <wtlee@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Auto-Submit: Wei Lee <wtlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845998}
parent 5fafea43
...@@ -2,29 +2,61 @@ ...@@ -2,29 +2,61 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import * as dom from './dom.js'; import {AsyncJobQueue} from './async_job_queue.js';
import {WaitableEvent} from './waitable_event.js';
/**
* @type {!Map<!HTMLAudioElement, !AsyncJobQueue>}
*/
const jobQueueMap = new Map();
/**
* Gets the audio job queue for the element.
* @param {!HTMLAudioElement} el
* @return {!AsyncJobQueue}
*/
function getQueueFor(el) {
if (!jobQueueMap.has(el)) {
jobQueueMap.set(el, new AsyncJobQueue());
}
return jobQueueMap.get(el);
}
/** /**
* Plays a sound. * Plays a sound.
* @param {string} selector Selector of the sound. * @param {!HTMLAudioElement} el Audio element to play.
* @return {{promise: !Promise, cancel: function()}} Promise for waiting * @return {!Promise} Promise which will be resolved once the sound is ended or
* finishing playing and function for canceling wait. * paused.
*/ */
export function play(selector) { export function play(el) {
// Use a timeout to wait for sound finishing playing instead of end-event cancel(el);
// as it might not be played at all (crbug.com/135780). const queue = getQueueFor(el);
// TODO(yuli): Don't play sounds if the speaker settings is muted. const job = async () => {
let cancel; el.currentTime = 0;
const promise = new Promise((resolve, reject) => { await el.play();
const element = dom.get(selector, HTMLAudioElement);
const timeout = const audioEnded = new WaitableEvent();
setTimeout(resolve, Number(element.dataset['timeout'] || 0)); const events = ['ended', 'pause'];
cancel = () => { const onAudioStopped = () => {
clearTimeout(timeout); audioEnded.signal();
reject(new Error('cancel')); for (const event of events) {
el.removeEventListener(event, onAudioStopped);
}
}; };
element.currentTime = 0; for (const event of events) {
element.play(); el.addEventListener(event, onAudioStopped);
}); }
return {promise, cancel}; return audioEnded.wait();
};
return queue.push(job);
}
/**
* Cancel a sound from playing.
* @param {!HTMLAudioElement} el Audio element to cancel.
* @return {!Promise}
*/
export async function cancel(el) {
el.pause();
await getQueueFor(el).flush();
} }
...@@ -449,7 +449,7 @@ export class Camera extends View { ...@@ -449,7 +449,7 @@ export class Camera extends View {
* @override * @override
*/ */
playShutterEffect() { playShutterEffect() {
sound.play('#sound-shutter'); sound.play(dom.get('#sound-shutter', HTMLAudioElement));
animate.play(this.preview_.video); animate.play(this.preview_.video);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import {AsyncJobQueue} from '../../../async_job_queue.js'; import {AsyncJobQueue} from '../../../async_job_queue.js';
import {browserProxy} from '../../../browser_proxy/browser_proxy.js'; import {browserProxy} from '../../../browser_proxy/browser_proxy.js';
import {assert, assertString} from '../../../chrome_util.js'; import {assert, assertString} from '../../../chrome_util.js';
import * as dom from '../../../dom.js';
import {Filenamer} from '../../../models/file_namer.js'; import {Filenamer} from '../../../models/file_namer.js';
import { import {
VideoSaver, // eslint-disable-line no-unused-vars VideoSaver, // eslint-disable-line no-unused-vars
...@@ -131,13 +132,6 @@ export class Video extends ModeBase { ...@@ -131,13 +132,6 @@ export class Video extends ModeBase {
*/ */
this.handler_ = handler; this.handler_ = handler;
/**
* Promise for play start sound delay.
* @type {?{promise: !Promise, cancel: function()}}
* @private
*/
this.startSound_ = null;
/** /**
* MediaRecorder object to record motion pictures. * MediaRecorder object to record motion pictures.
* @type {?MediaRecorder} * @type {?MediaRecorder}
...@@ -221,7 +215,9 @@ export class Video extends ModeBase { ...@@ -221,7 +215,9 @@ export class Video extends ModeBase {
}; };
const playEffect = async () => { const playEffect = async () => {
state.set(state.State.RECORDING_UI_PAUSED, toBePaused); state.set(state.State.RECORDING_UI_PAUSED, toBePaused);
await sound.play(toBePaused ? '#sound-rec-pause' : '#sound-rec-start'); await sound.play(dom.get(
toBePaused ? '#sound-rec-pause' : '#sound-rec-start',
HTMLAudioElement));
}; };
this.mediaRecorder_.addEventListener(toggledEvent, onToggled); this.mediaRecorder_.addEventListener(toggledEvent, onToggled);
...@@ -244,13 +240,8 @@ export class Video extends ModeBase { ...@@ -244,13 +240,8 @@ export class Video extends ModeBase {
async start_() { async start_() {
this.snapshots_ = new AsyncJobQueue(); this.snapshots_ = new AsyncJobQueue();
this.togglePaused_ = null; this.togglePaused_ = null;
this.startSound_ = sound.play('#sound-rec-start');
this.everPaused_ = false; this.everPaused_ = false;
try { await sound.play(dom.get('#sound-rec-start', HTMLAudioElement));
await this.startSound_.promise;
} finally {
this.startSound_ = null;
}
if (this.mediaRecorder_ === null) { if (this.mediaRecorder_ === null) {
try { try {
...@@ -276,7 +267,7 @@ export class Video extends ModeBase { ...@@ -276,7 +267,7 @@ export class Video extends ModeBase {
} finally { } finally {
duration = this.recordTime_.stop({pause: false}); duration = this.recordTime_.stop({pause: false});
} }
sound.play('#sound-rec-end'); sound.play(dom.get('#sound-rec-end', HTMLAudioElement));
const settings = this.stream_.getVideoTracks()[0].getSettings(); const settings = this.stream_.getVideoTracks()[0].getSettings();
const resolution = new Resolution(settings.width, settings.height); const resolution = new Resolution(settings.width, settings.height);
...@@ -300,9 +291,8 @@ export class Video extends ModeBase { ...@@ -300,9 +291,8 @@ export class Video extends ModeBase {
* @override * @override
*/ */
stop_() { stop_() {
if (this.startSound_ !== null) { sound.cancel(dom.get('#sound-rec-start', HTMLAudioElement));
this.startSound_.cancel();
}
if (this.mediaRecorder_ && if (this.mediaRecorder_ &&
(this.mediaRecorder_.state === 'recording' || (this.mediaRecorder_.state === 'recording' ||
this.mediaRecorder_.state === 'paused')) { this.mediaRecorder_.state === 'paused')) {
......
...@@ -46,7 +46,7 @@ export function start() { ...@@ -46,7 +46,7 @@ export function start() {
resolve(); resolve();
} else { } else {
if (sounds[tickCounter] !== undefined) { if (sounds[tickCounter] !== undefined) {
play(sounds[tickCounter]); play(dom.get(sounds[tickCounter], HTMLAudioElement));
} }
tickMsg.textContent = tickCounter + ''; tickMsg.textContent = tickCounter + '';
animate.play(tickMsg); animate.play(tickMsg);
......
...@@ -433,17 +433,13 @@ ...@@ -433,17 +433,13 @@
</div> </div>
<div id="toast" class="centered-overlay" aria-live="polite"></div> <div id="toast" class="centered-overlay" aria-live="polite"></div>
<div id="tooltip" aria-hidden="true"></div> <div id="tooltip" aria-hidden="true"></div>
<audio id="sound-tick-final" src="/sounds/tick_final.ogg" <audio id="sound-tick-final" src="/sounds/tick_final.ogg">
data-timeout="1000"> <audio id="sound-tick-inc" src="/sounds/tick_inc.ogg">
<audio id="sound-tick-inc" src="/sounds/tick_inc.ogg" data-timeout="1000"> <audio id="sound-tick-start" src="/sounds/tick_start.ogg">
<audio id="sound-tick-start" src="/sounds/tick_start.ogg" <audio id="sound-shutter" src="/sounds/shutter.ogg">
data-timeout="1000"> <audio id="sound-rec-start" src="/sounds/record_start.ogg">
<audio id="sound-shutter" src="/sounds/shutter.ogg" data-timeout="350"> <audio id="sound-rec-end" src="/sounds/record_end.ogg">
<audio id="sound-rec-start" src="/sounds/record_start.ogg" <audio id="sound-rec-pause" src="/sounds/record_pause.ogg">
data-timeout="300">
<audio id="sound-rec-end" src="/sounds/record_end.ogg" data-timeout="450">
<audio id="sound-rec-pause" src="/sounds/record_pause.ogg"
data-timeout="500">
<template id="preview-video-template"> <template id="preview-video-template">
<video id="preview-video" class="preview-content" aria-hidden="true" <video id="preview-video" class="preview-content" aria-hidden="true"
muted></video> muted></video>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment