Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / app_list / speech_manager.js
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview The class to Manage both offline / online speech recognition.
7  */
8
9 <include src="plugin_manager.js"/>
10 <include src="audio_manager.js"/>
11 <include src="speech_recognition_manager.js"/>
12
13 cr.define('speech', function() {
14   'use strict';
15
16   /**
17    * The state of speech recognition.
18    *
19    * @enum {string}
20    */
21   var SpeechState = {
22     READY: 'READY',
23     HOTWORD_RECOGNIZING: 'HOTWORD_RECOGNIZING',
24     RECOGNIZING: 'RECOGNIZING',
25     IN_SPEECH: 'IN_SPEECH',
26     STOPPING: 'STOPPING'
27   };
28
29   /**
30    * @constructor
31    */
32   function SpeechManager() {
33     this.audioManager_ = new speech.AudioManager();
34     this.audioManager_.addEventListener('audio', this.onAudioLevel_.bind(this));
35     this.shown_ = false;
36     this.speechRecognitionManager_ = new speech.SpeechRecognitionManager(this);
37     this.setState_(SpeechState.READY);
38   }
39
40   /**
41    * Updates the state.
42    *
43    * @param {SpeechState} newState The new state.
44    * @private
45    */
46   SpeechManager.prototype.setState_ = function(newState) {
47     if (this.state == newState)
48       return;
49
50     this.state = newState;
51     chrome.send('setSpeechRecognitionState', [this.state]);
52   };
53
54   /**
55    * Called with the mean audio level when audio data arrives.
56    *
57    * @param {cr.event.Event} event The event object for the audio data.
58    * @private
59    */
60   SpeechManager.prototype.onAudioLevel_ = function(event) {
61     var data = event.data;
62     var level = 0;
63     for (var i = 0; i < data.length; ++i)
64       level += Math.abs(data[i]);
65     level /= data.length;
66     chrome.send('speechSoundLevel', [level]);
67   };
68
69   /**
70    * Called when the hotword recognizer is ready.
71    *
72    * @param {PluginManager} pluginManager The hotword plugin manager which gets
73    *   ready.
74    * @private
75    */
76   SpeechManager.prototype.onHotwordRecognizerReady_ = function(pluginManager) {
77     this.pluginManager_ = pluginManager;
78     this.audioManager_.addEventListener(
79         'audio', pluginManager.sendAudioData.bind(pluginManager));
80     if (this.shown_) {
81       this.pluginManager_.startRecognizer();
82       this.audioManager_.start();
83       this.setState_(SpeechState.HOTWORD_RECOGNIZING);
84     } else {
85       this.setState_(SpeechState.READY);
86     }
87   };
88
89   /**
90    * Called when the hotword is recognized.
91    *
92    * @param {number} confidence The confidence store of the recognition.
93    * @private
94    */
95   SpeechManager.prototype.onHotwordRecognized_ = function(confidence) {
96     if (this.state != SpeechState.HOTWORD_RECOGNIZING)
97       return;
98     this.pluginManager_.stopRecognizer();
99     this.speechRecognitionManager_.start();
100   };
101
102   /**
103    * Called when the speech recognition has happened.
104    *
105    * @param {string} result The speech recognition result.
106    * @param {boolean} isFinal Whether the result is final or not.
107    */
108   SpeechManager.prototype.onSpeechRecognized = function(result, isFinal) {
109     chrome.send('speechResult', [result, isFinal]);
110     if (isFinal)
111       this.speechRecognitionManager_.stop();
112   };
113
114   /**
115    * Called when the speech recognition has started.
116    */
117   SpeechManager.prototype.onSpeechRecognitionStarted = function() {
118     this.setState_(SpeechState.RECOGNIZING);
119   };
120
121   /**
122    * Called when the speech recognition has ended.
123    */
124   SpeechManager.prototype.onSpeechRecognitionEnded = function() {
125     // Restarts the hotword recognition.
126     if (this.state != SpeechState.STOPPING && this.pluginManager_) {
127       this.pluginManager_.startRecognizer();
128       this.audioManager_.start();
129       this.setState_(SpeechState.HOTWORD_RECOGNIZING);
130     } else {
131       this.audioManager_.stop();
132       this.setState_(SpeechState.READY);
133     }
134   };
135
136   /**
137    * Called when a speech has started.
138    */
139   SpeechManager.prototype.onSpeechStarted = function() {
140     if (this.state == SpeechState.RECOGNIZING)
141       this.setState_(SpeechState.IN_SPEECH);
142   };
143
144   /**
145    * Called when a speech has ended.
146    */
147   SpeechManager.prototype.onSpeechEnded = function() {
148     if (this.state == SpeechState.IN_SPEECH)
149       this.setState_(SpeechState.RECOGNIZING);
150   };
151
152   /**
153    * Called when an error happened during the speech recognition.
154    *
155    * @param {SpeechRecognitionError} e The error object.
156    */
157   SpeechManager.prototype.onSpeechRecognitionError = function(e) {
158     if (this.state != SpeechState.STOPPING)
159       this.setState_(SpeechState.READY);
160   };
161
162   /**
163    * Changes the availability of the hotword plugin.
164    *
165    * @param {boolean} enabled Whether enabled or not.
166    */
167   SpeechManager.prototype.setHotwordEnabled = function(enabled) {
168     var recognizer = $('recognizer');
169     if (enabled) {
170       if (recognizer)
171         return;
172
173       var pluginManager = new speech.PluginManager(
174           this.onHotwordRecognizerReady_.bind(this),
175           this.onHotwordRecognized_.bind(this));
176       pluginManager.scheduleInitialize(
177           this.audioManager_.getSampleRate(),
178           'chrome://app-list/okgoogle_hotword.config');
179     } else {
180       if (!recognizer)
181         return;
182       document.body.removeChild(recognizer);
183       this.pluginManager_ = null;
184       if (this.state == SpeechState.HOTWORD_RECOGNIZING)
185         this.setState(SpeechState.READY);
186     }
187   };
188
189   /**
190    * Called when the app-list bubble is shown.
191    */
192   SpeechManager.prototype.onShown = function() {
193     this.shown_ = true;
194     if (!this.pluginManager_)
195       return;
196
197     if (this.state == SpeechState.HOTWORD_RECOGNIZING) {
198       console.warn('Already in recognition state...');
199       return;
200     }
201
202     this.pluginManager_.startRecognizer();
203     this.audioManager_.start();
204     this.setState_(SpeechState.HOTWORD_RECOGNIZING);
205   };
206
207   /**
208    * Called when the app-list bubble is hidden.
209    */
210   SpeechManager.prototype.onHidden = function() {
211     this.shown_ = false;
212     if (this.pluginManager_)
213       this.pluginManager_.stopRecognizer();
214
215     // SpeechRecognition is asynchronous.
216     this.audioManager_.stop();
217     if (this.state == SpeechState.RECOGNIZING ||
218         this.state == SpeechState.IN_SPEECH) {
219       this.setState_(SpeechState.STOPPING);
220       this.speechRecognitionManager_.stop();
221     } else {
222       this.setState_(SpeechState.READY);
223     }
224   };
225
226   /**
227    * Toggles the current state of speech recognition.
228    */
229   SpeechManager.prototype.toggleSpeechRecognition = function() {
230     if (this.state == SpeechState.RECOGNIZING ||
231         this.state == SpeechState.IN_SPEECH) {
232       this.audioManager_.stop();
233       this.speechRecognitionManager_.stop();
234     } else {
235       if (this.pluginManager_)
236         this.pluginManager_.stopRecognizer();
237       if (this.audioManager_.state == speech.AudioState.STOPPED)
238         this.audioManager_.start();
239       this.speechRecognitionManager_.start();
240     }
241   };
242
243   return {
244     SpeechManager: SpeechManager
245   };
246 });