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

Side by Side Diff: chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js

Issue 2782993002: Add an options page to Select-to-Speak and allow setting voice name, rate (Closed)
Patch Set: Created 3 years, 8 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var AutomationEvent = chrome.automation.AutomationEvent; 5 var AutomationEvent = chrome.automation.AutomationEvent;
6 var AutomationNode = chrome.automation.AutomationNode; 6 var AutomationNode = chrome.automation.AutomationNode;
7 var EventType = chrome.automation.EventType; 7 var EventType = chrome.automation.EventType;
8 var RoleType = chrome.automation.RoleType; 8 var RoleType = chrome.automation.RoleType;
9 9
10 /** 10 /**
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 chrome.automation.getDesktop(function(desktop) { 61 chrome.automation.getDesktop(function(desktop) {
62 desktop.addEventListener( 62 desktop.addEventListener(
63 EventType.MOUSE_PRESSED, this.onMousePressed_.bind(this), true); 63 EventType.MOUSE_PRESSED, this.onMousePressed_.bind(this), true);
64 desktop.addEventListener( 64 desktop.addEventListener(
65 EventType.MOUSE_DRAGGED, this.onMouseDragged_.bind(this), true); 65 EventType.MOUSE_DRAGGED, this.onMouseDragged_.bind(this), true);
66 desktop.addEventListener( 66 desktop.addEventListener(
67 EventType.MOUSE_RELEASED, this.onMouseReleased_.bind(this), true); 67 EventType.MOUSE_RELEASED, this.onMouseReleased_.bind(this), true);
68 desktop.addEventListener( 68 desktop.addEventListener(
69 EventType.MOUSE_CANCELED, this.onMouseCanceled_.bind(this), true); 69 EventType.MOUSE_CANCELED, this.onMouseCanceled_.bind(this), true);
70 }.bind(this)); 70 }.bind(this));
71
72 /** @private { ?string } */
73 this.voiceName_ = null;
74
75 /** @private { number } */
76 this.speechRate_ = 1.0;
77
78 this.initPreferences_();
71 }; 79 };
72 80
73 SelectToSpeak.prototype = { 81 SelectToSpeak.prototype = {
74 /** 82 /**
75 * Called when the mouse is pressed and the user is in a mode where 83 * Called when the mouse is pressed and the user is in a mode where
76 * select-to-speak is capturing mouse events (for example holding down 84 * select-to-speak is capturing mouse events (for example holding down
77 * Search). 85 * Search).
78 * 86 *
79 * @param {!AutomationEvent} evt 87 * @param {!AutomationEvent} evt
80 */ 88 */
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 190
183 /** 191 /**
184 * Enqueue speech commands for all of the given nodes. 192 * Enqueue speech commands for all of the given nodes.
185 * @param {Array<AutomationNode>} nodes The nodes to speak. 193 * @param {Array<AutomationNode>} nodes The nodes to speak.
186 */ 194 */
187 startSpeechQueue_: function(nodes) { 195 startSpeechQueue_: function(nodes) {
188 chrome.tts.stop(); 196 chrome.tts.stop();
189 for (var i = 0; i < nodes.length; i++) { 197 for (var i = 0; i < nodes.length; i++) {
190 var node = nodes[i]; 198 var node = nodes[i];
191 var isLast = (i == nodes.length - 1); 199 var isLast = (i == nodes.length - 1);
192 chrome.tts.speak(node.name || '', { 200
201 var options = {
193 lang: 'en-US', 202 lang: 'en-US',
203 rate: this.rate_,
194 'enqueue': true, 204 'enqueue': true,
195 onEvent: (function(node, isLast, event) { 205 onEvent: (function(node, isLast, event) {
196 if (event.type == 'start') { 206 if (event.type == 'start') {
197 chrome.accessibilityPrivate.setFocusRing([node.location]); 207 chrome.accessibilityPrivate.setFocusRing([node.location]);
198 } else if (event.type == 'interrupted' || 208 } else if (event.type == 'interrupted' ||
199 event.type == 'cancelled') { 209 event.type == 'cancelled') {
200 chrome.accessibilityPrivate.setFocusRing([]); 210 chrome.accessibilityPrivate.setFocusRing([]);
201 } else if (event.type == 'end') { 211 } else if (event.type == 'end') {
202 if (isLast) { 212 if (isLast) {
203 chrome.accessibilityPrivate.setFocusRing([]); 213 chrome.accessibilityPrivate.setFocusRing([]);
204 } 214 }
205 } 215 }
206 }).bind(this, node, isLast) 216 }).bind(this, node, isLast)
217 };
218 if (this.voiceName_) {
219 options['voiceName'] = this.voiceName_;
220 }
221 chrome.tts.speak(node.name || '', options);
222 }
223 },
224
225 /**
226 * Loads preferences from chrome.storage, sets default values if
227 * necessary, and registers a listener to update prefs when they
228 * change.
229 */
230 initPreferences_: function() {
231 var updatePrefs = (function() {
232 chrome.storage.sync.get(['voice', 'rate'], (function(prefs) {
233 if (prefs['voice']) {
David Tseng 2017/03/29 22:24:46 Just a warning, a voice synced in this way might b
dmazzoni 2017/03/30 20:19:17 Good catch. I made this more robust by tracking t
234 this.voiceName_ = prefs['voice'];
235 }
236 if (prefs['rate']) {
237 this.rate_ = parseFloat(prefs['rate']);
238 } else {
239 chrome.storage.sync.set({'rate': this.rate_});
240 }
241 }).bind(this));
242 }).bind(this);
243
244 updatePrefs();
245 chrome.storage.onChanged.addListener(updatePrefs);
246
247 this.updateDefaultVoice_();
248 window.speechSynthesis.onvoiceschanged =
249 this.updateDefaultVoice_.bind(this);
250 },
251
252 /**
253 * Get the list of TTS voices, and set the default voice if not already set.
254 */
255 updateDefaultVoice_: function() {
256 var uiLocale = chrome.i18n.getMessage('@@ui_locale');
257 uiLocale = uiLocale.replace('_', '-').toLowerCase();
258
259 chrome.tts.getVoices(function(voices) {
260 if (voices.length == 0)
261 return;
262
263 voices.sort(function(a, b) {
264 function score(voice) {
265 var lang = voice.lang.toLowerCase();
266 var s = 0;
267 if (lang == uiLocale)
268 s += 2;
269 if (lang.substr(0, 2) == uiLocale.substr(0, 2))
270 s += 1;
271 return s;
272 }
273 return score(b) - score(a);
207 }); 274 });
208 } 275
276 chrome.storage.sync.get(['voice'], (function(prefs) {
277 if (!prefs['voice']) {
278 chrome.storage.sync.set({'voice': voices[0].voiceName});
279 }
280 }).bind(this));
281 });
209 } 282 }
210 }; 283 };
211 284
212 new SelectToSpeak(); 285 new SelectToSpeak();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698