OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 /** | 5 /** |
6 * @fileoverview Implementation of the speech rule engine. | 6 * @fileoverview Implementation of the speech rule engine. |
7 * | 7 * |
8 * The speech rule engine chooses and applies speech rules. Rules are chosen | 8 * The speech rule engine chooses and applies speech rules. Rules are chosen |
9 * from a set of rule stores wrt. their applicability to a node in a particular | 9 * from a set of rule stores wrt. their applicability to a node in a particular |
10 * markup type such as MathML or HTML. Rules are dispatched either by | 10 * markup type such as MathML or HTML. Rules are dispatched either by |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 /** | 48 /** |
49 * Parameterizes the speech rule engine. | 49 * Parameterizes the speech rule engine. |
50 * @param {cvox.BaseRuleStore} store A speech rule store. | 50 * @param {cvox.BaseRuleStore} store A speech rule store. |
51 */ | 51 */ |
52 cvox.SpeechRuleEngine.prototype.parameterize = function(store) { | 52 cvox.SpeechRuleEngine.prototype.parameterize = function(store) { |
53 try { | 53 try { |
54 store.initialize(); | 54 store.initialize(); |
55 } catch (err) { | 55 } catch (err) { |
56 if (err.name == 'StoreError') { | 56 if (err.name == 'StoreError') { |
57 console.log('Store Error:', err.message); | 57 console.log('Store Error:', err.message); |
58 } | 58 } else { |
59 else { | |
60 throw err; | 59 throw err; |
61 } | 60 } |
62 } | 61 } |
63 this.activeStore_ = store; | 62 this.activeStore_ = store; |
64 }; | 63 }; |
65 | 64 |
66 | 65 |
67 /** | 66 /** |
68 * Parameterizes the dynamic constraint annotation for the speech rule | 67 * Parameterizes the dynamic constraint annotation for the speech rule |
69 * engine. This is a separate function as this can be done interactively, while | 68 * engine. This is a separate function as this can be done interactively, while |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 case cvox.SpeechRule.Type.NODE: | 138 case cvox.SpeechRule.Type.NODE: |
140 var selected = this.activeStore_.applyQuery(node, content); | 139 var selected = this.activeStore_.applyQuery(node, content); |
141 if (selected) { | 140 if (selected) { |
142 navs = this.evaluateTree_(selected); | 141 navs = this.evaluateTree_(selected); |
143 } | 142 } |
144 break; | 143 break; |
145 case cvox.SpeechRule.Type.MULTI: | 144 case cvox.SpeechRule.Type.MULTI: |
146 selected = this.activeStore_.applySelector(node, content); | 145 selected = this.activeStore_.applySelector(node, content); |
147 if (selected.length > 0) { | 146 if (selected.length > 0) { |
148 navs = this.evaluateNodeList_( | 147 navs = this.evaluateNodeList_( |
149 selected, | 148 selected, component['sepFunc'], |
150 component['sepFunc'], | |
151 this.constructString(node, component['separator']), | 149 this.constructString(node, component['separator']), |
152 component['ctxtFunc'], | 150 component['ctxtFunc'], |
153 this.constructString(node, component['context'])); | 151 this.constructString(node, component['context'])); |
154 } | 152 } |
155 break; | 153 break; |
156 case cvox.SpeechRule.Type.TEXT: | 154 case cvox.SpeechRule.Type.TEXT: |
157 selected = this.constructString(node, content); | 155 selected = this.constructString(node, content); |
158 if (selected) { | 156 if (selected) { |
159 navs = [new cvox.NavDescription({text: selected})]; | 157 navs = [new cvox.NavDescription({text: selected})]; |
160 } | 158 } |
161 break; | 159 break; |
162 case cvox.SpeechRule.Type.PERSONALITY: | 160 case cvox.SpeechRule.Type.PERSONALITY: |
163 default: | 161 default: |
164 navs = [new cvox.NavDescription({text: content})]; | 162 navs = [new cvox.NavDescription({text: content})]; |
165 } | 163 } |
166 // Adding overall context if it exists. | 164 // Adding overall context if it exists. |
167 if (navs[0] && component['context'] && | 165 if (navs[0] && component['context'] && |
168 component.type != cvox.SpeechRule.Type.MULTI) { | 166 component.type != cvox.SpeechRule.Type.MULTI) { |
169 navs[0]['context'] = | 167 navs[0]['context'] = this.constructString(node, component['context']) + |
170 this.constructString(node, component['context']) + | 168 (navs[0]['context'] || ''); |
171 (navs[0]['context'] || ''); | |
172 } | 169 } |
173 // Adding personality to the nav descriptions. | 170 // Adding personality to the nav descriptions. |
174 result = result.concat(this.addPersonality_(navs, component)); | 171 result = result.concat(this.addPersonality_(navs, component)); |
175 } | 172 } |
176 return result; | 173 return result; |
177 }; | 174 }; |
178 | 175 |
179 | 176 |
180 /** | 177 /** |
181 * Evaluates a list of nodes into a list of navigation descriptions. | 178 * Evaluates a list of nodes into a list of navigation descriptions. |
(...skipping 10 matching lines...) Expand all Loading... |
192 * @private | 189 * @private |
193 */ | 190 */ |
194 cvox.SpeechRuleEngine.prototype.evaluateNodeList_ = function( | 191 cvox.SpeechRuleEngine.prototype.evaluateNodeList_ = function( |
195 nodes, sepFunc, separator, ctxtFunc, context) { | 192 nodes, sepFunc, separator, ctxtFunc, context) { |
196 if (nodes == []) { | 193 if (nodes == []) { |
197 return []; | 194 return []; |
198 } | 195 } |
199 var sep = separator || ''; | 196 var sep = separator || ''; |
200 var cont = context || ''; | 197 var cont = context || ''; |
201 var cFunc = this.activeStore_.contextFunctions.lookup(ctxtFunc); | 198 var cFunc = this.activeStore_.contextFunctions.lookup(ctxtFunc); |
202 var ctxtClosure = cFunc ? cFunc(nodes, cont) : function() {return cont;}; | 199 var ctxtClosure = cFunc ? cFunc(nodes, cont) : function() { |
| 200 return cont; |
| 201 }; |
203 var sFunc = this.activeStore_.contextFunctions.lookup(sepFunc); | 202 var sFunc = this.activeStore_.contextFunctions.lookup(sepFunc); |
204 var sepClosure = sFunc ? sFunc(nodes, sep) : function() {return sep;}; | 203 var sepClosure = sFunc ? sFunc(nodes, sep) : function() { |
| 204 return sep; |
| 205 }; |
205 var result = []; | 206 var result = []; |
206 for (var i = 0, node; node = nodes[i]; i++) { | 207 for (var i = 0, node; node = nodes[i]; i++) { |
207 var navs = this.evaluateTree_(node); | 208 var navs = this.evaluateTree_(node); |
208 if (navs.length > 0) { | 209 if (navs.length > 0) { |
209 navs[0]['context'] = ctxtClosure() + (navs[0]['context'] || ''); | 210 navs[0]['context'] = ctxtClosure() + (navs[0]['context'] || ''); |
210 result = result.concat(navs); | 211 result = result.concat(navs); |
211 if (i < nodes.length - 1) { | 212 if (i < nodes.length - 1) { |
212 var text = sepClosure(); | 213 var text = sepClosure(); |
213 if (text) { | 214 if (text) { |
214 result.push(new cvox.NavDescription({text: text})); | 215 result.push(new cvox.NavDescription({text: text})); |
215 } | 216 } |
216 } | 217 } |
217 } | 218 } |
218 } | 219 } |
219 return result; | 220 return result; |
220 }; | 221 }; |
221 | 222 |
222 | 223 |
223 /** | 224 /** |
224 * Maps properties in speech rules to personality properties. | 225 * Maps properties in speech rules to personality properties. |
225 * @type {{pitch : string, | 226 * @type {{pitch : string, |
226 * rate: string, | 227 * rate: string, |
227 * volume: string, | 228 * volume: string, |
228 * pause: string}} | 229 * pause: string}} |
229 * @const | 230 * @const |
230 */ | 231 */ |
231 cvox.SpeechRuleEngine.propMap = {'pitch': cvox.AbstractTts.RELATIVE_PITCH, | 232 cvox.SpeechRuleEngine.propMap = { |
232 'rate': cvox.AbstractTts.RELATIVE_RATE, | 233 'pitch': cvox.AbstractTts.RELATIVE_PITCH, |
233 'volume': cvox.AbstractTts.RELATIVE_VOLUME, | 234 'rate': cvox.AbstractTts.RELATIVE_RATE, |
234 'pause': cvox.AbstractTts.PAUSE | 235 'volume': cvox.AbstractTts.RELATIVE_VOLUME, |
235 }; | 236 'pause': cvox.AbstractTts.PAUSE |
| 237 }; |
236 | 238 |
237 | 239 |
238 /** | 240 /** |
239 * Adds personality to every Navigation Descriptions in input list. | 241 * Adds personality to every Navigation Descriptions in input list. |
240 * @param {Array<cvox.NavDescription>} navs A list of Navigation descriptions. | 242 * @param {Array<cvox.NavDescription>} navs A list of Navigation descriptions. |
241 * @param {Object} props Property dictionary. | 243 * @param {Object} props Property dictionary. |
242 * TODO (sorge) Fully specify, when we have finalised the speech rule | 244 * TODO (sorge) Fully specify, when we have finalised the speech rule |
243 * format. | 245 * format. |
244 * @return {Array<cvox.NavDescription>} The modified array. | 246 * @return {Array<cvox.NavDescription>} The modified array. |
245 * @private | 247 * @private |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 cvox.SpeechRuleEngine.debugMode = false; | 313 cvox.SpeechRuleEngine.debugMode = false; |
312 | 314 |
313 | 315 |
314 /** | 316 /** |
315 * Give debug output. | 317 * Give debug output. |
316 * @param {...*} output Rest elements of debug output. | 318 * @param {...*} output Rest elements of debug output. |
317 */ | 319 */ |
318 cvox.SpeechRuleEngine.outputDebug = function(output) { | 320 cvox.SpeechRuleEngine.outputDebug = function(output) { |
319 if (cvox.SpeechRuleEngine.debugMode) { | 321 if (cvox.SpeechRuleEngine.debugMode) { |
320 var outputList = Array.prototype.slice.call(arguments, 0); | 322 var outputList = Array.prototype.slice.call(arguments, 0); |
321 console.log.apply(console, | 323 console.log.apply( |
322 ['Speech Rule Engine Debugger:'].concat(outputList)); | 324 console, ['Speech Rule Engine Debugger:'].concat(outputList)); |
323 } | 325 } |
324 }; | 326 }; |
325 | 327 |
326 | 328 |
327 /** | 329 /** |
328 * Prints the list of all current rules in ChromeVox to the console. | 330 * Prints the list of all current rules in ChromeVox to the console. |
329 * @return {string} A textual representation of all rules in the speech rule | 331 * @return {string} A textual representation of all rules in the speech rule |
330 * engine. | 332 * engine. |
331 */ | 333 */ |
332 cvox.SpeechRuleEngine.prototype.toString = function() { | 334 cvox.SpeechRuleEngine.prototype.toString = function() { |
333 var allRules = this.activeStore_.findAllRules(function(x) {return true;}); | 335 var allRules = this.activeStore_.findAllRules(function(x) { |
334 return allRules.map(function(rule) {return rule.toString();}). | 336 return true; |
335 join('\n'); | 337 }); |
| 338 return allRules |
| 339 .map(function(rule) { |
| 340 return rule.toString(); |
| 341 }) |
| 342 .join('\n'); |
336 }; | 343 }; |
337 | 344 |
338 | 345 |
339 /** | 346 /** |
340 * Test the precondition of a speech rule in debugging mode. | 347 * Test the precondition of a speech rule in debugging mode. |
341 * @param {cvox.SpeechRule} rule A speech rule. | 348 * @param {cvox.SpeechRule} rule A speech rule. |
342 * @param {!Node} node DOM node to test applicability of the rule. | 349 * @param {!Node} node DOM node to test applicability of the rule. |
343 */ | 350 */ |
344 cvox.SpeechRuleEngine.debugSpeechRule = function(rule, node) { | 351 cvox.SpeechRuleEngine.debugSpeechRule = function(rule, node) { |
345 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; | 352 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; |
346 if (store) { | 353 if (store) { |
347 var prec = rule.precondition; | 354 var prec = rule.precondition; |
348 cvox.SpeechRuleEngine.outputDebug( | 355 cvox.SpeechRuleEngine.outputDebug( |
349 prec.query, store.applyQuery(node, prec.query)); | 356 prec.query, store.applyQuery(node, prec.query)); |
350 prec.constraints.forEach( | 357 prec.constraints.forEach(function(cstr) { |
351 function(cstr) { | 358 cvox.SpeechRuleEngine.outputDebug( |
352 cvox.SpeechRuleEngine.outputDebug( | 359 cstr, store.applyConstraint(node, cstr)); |
353 cstr, store.applyConstraint(node, cstr));}); | 360 }); |
354 } | 361 } |
355 }; | 362 }; |
356 | 363 |
357 | 364 |
358 /** | 365 /** |
359 * Test the precondition of a speech rule in debugging mode. | 366 * Test the precondition of a speech rule in debugging mode. |
360 * @param {string} name Rule to debug. | 367 * @param {string} name Rule to debug. |
361 * @param {!Node} node DOM node to test applicability of the rule. | 368 * @param {!Node} node DOM node to test applicability of the rule. |
362 */ | 369 */ |
363 cvox.SpeechRuleEngine.debugNamedSpeechRule = function(name, node) { | 370 cvox.SpeechRuleEngine.debugNamedSpeechRule = function(name, node) { |
364 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; | 371 var store = cvox.SpeechRuleEngine.getInstance().activeStore_; |
365 var allRules = store.findAllRules( | 372 var allRules = store.findAllRules(function(rule) { |
366 function(rule) {return rule.name == name;}); | 373 return rule.name == name; |
| 374 }); |
367 for (var i = 0, rule; rule = allRules[i]; i++) { | 375 for (var i = 0, rule; rule = allRules[i]; i++) { |
368 cvox.SpeechRuleEngine.outputDebug('Rule', name, 'number', i); | 376 cvox.SpeechRuleEngine.outputDebug('Rule', name, 'number', i); |
369 cvox.SpeechRuleEngine.debugSpeechRule(rule, node); | 377 cvox.SpeechRuleEngine.debugSpeechRule(rule, node); |
370 } | 378 } |
371 }; | 379 }; |
OLD | NEW |