Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2353)

Unified Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js

Issue 2563013003: Support audio ducking and suspension in ChromeVox (Closed)
Patch Set: Support audio ducking and suspension in ChromeVox Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
index 8a57c06b0289f5dded396959f3f76eb4fa569425..7678e8fdffffc93607ea4c2e3e3364e4edc2ae13 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/media_automation_handler.js
@@ -3,12 +3,15 @@
// found in the LICENSE file.
/**
- * @fileoverview Handles media events automation.
+ * @fileoverview Handles media automation events. Note that to perform any of
+ * the actions below such as ducking, and suspension of media sessions, the
+ * --enable-default-media-session flag must be passed at the command line.
*/
goog.provide('MediaAutomationHandler');
goog.require('BaseAutomationHandler');
+goog.require('cvox.TtsCapturingEventListener');
goog.scope(function() {
var AutomationEvent = chrome.automation.AutomationEvent;
@@ -17,32 +20,117 @@ var EventType = chrome.automation.EventType;
var RoleType = chrome.automation.RoleType;
/**
- * @param {!AutomationNode} node The root to observe media changes.
* @constructor
* @extends {BaseAutomationHandler}
+ * @implements {cvox.TtsCapturingEventListener}
*/
-MediaAutomationHandler = function(node) {
- BaseAutomationHandler.call(this, node);
+MediaAutomationHandler = function() {
+ /** @type {!Set<AutomationNode>} @private */
+ this.mediaRoots_ = new Set();
- var e = EventType;
- this.addListener_(e.mediaStartedPlaying, this.onMediaStartedPlaying);
- this.addListener_(e.mediaStoppedPlaying, this.onMediaStoppedPlaying);
+ /** @type {Date} @private */
+ this.lastTtsEvent_ = new Date();
+
+ cvox.ChromeVox.tts.addCapturingEventListener(this);
+
+ chrome.automation.getDesktop(function(node) {
+ BaseAutomationHandler.call(this, node);
+ this.setInitialState_(node);
+ var e = EventType;
+ this.addListener_(e.mediaStartedPlaying, this.onMediaStartedPlaying);
+ this.addListener_(e.mediaStoppedPlaying, this.onMediaStoppedPlaying);
+ }.bind(this));
};
+/** @type {number} */
+MediaAutomationHandler.MIN_WAITTIME_MS = 1000;
+
MediaAutomationHandler.prototype = {
__proto__: BaseAutomationHandler.prototype,
+ /** @override */
+ onTtsStart: function() {
+ this.lastTtsEvent_ = new Date();
+ this.update_({start: true});
+ },
+
+ /** @override */
+ onTtsEnd: function() {
+ var now = new Date();
+ setTimeout(function() {
+ var then = this.lastTtsEvent_;
+ if (now < then)
+ return;
+ this.lastTtsEvent_ = now;
+ this.update_({end: true});
+ }.bind(this), MediaAutomationHandler.MIN_WAITTIME_MS);
+ },
+
/**
* @param {!AutomationEvent} evt
*/
onMediaStartedPlaying: function(evt) {
+ this.mediaRoots_.add(evt.target);
+ if (cvox.ChromeVox.tts.isSpeaking())
+ this.update_({start: true});
},
/**
* @param {!AutomationEvent} evt
*/
onMediaStoppedPlaying: function(evt) {
+ // Intentionally does nothing (to cover resume).
+ },
+
+ /**
+ * Sets the initial state of audio for all tabs.
+ * We do this on ChromeVox startup.
+ * @param {AutomationNode} node
+ */
+ setInitialState_: function(node) {
+ var roots = node.findAll({role: RoleType.rootWebArea});
+ if (!roots.length) {
+ var listener = this.setInitialState_.bind(this, node);
+ window.setTimeout(listener, 1000);
+ return;
+ }
+
+ roots.forEach(function(r) {
+ // Doing this allows us to get any currently playing media in our
+ // mediaStartedPlaying handler.
+ r.suspendMedia();
+ r.resumeMedia();
+ });
+ },
+
+ /**
+ * Updates the media state for all observed automation roots.
+ * @param {{start: (boolean|undefined),
+ * end: (boolean|undefined)}} options
+ * @private
+ */
+ update_: function(options) {
+ var it = this.mediaRoots_.values();
+ var item = it.next();
+ var audioStrategy = localStorage['audioStrategy'];
+ while (!item.done) {
+ var root = item.value;
+ if (options.start) {
+ if (audioStrategy == 'audioDuck')
+ root.startDuckingMedia();
+ else if (audioStrategy == 'audioSuspend')
+ root.suspendMedia();
+ } else if (options.end) {
+ if (audioStrategy == 'audioDuck')
+ root.stopDuckingMedia();
+ else if (audioStrategy == 'audioSuspend')
+ root.resumeMedia();
+ }
+ item = it.next();
+ }
}
};
}); // goog.scope
+
+new MediaAutomationHandler();

Powered by Google App Engine
This is Rietveld 408576698