OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 cr.define('hotword', function() { | 5 cr.define('hotword', function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 /** | 8 /** |
9 * Class to manage hotwording state. Starts/stops the hotword detector based | 9 * Class to manage hotwording state. Starts/stops the hotword detector based |
10 * on user settings, session requests, and any other factors that play into | 10 * on user settings, session requests, and any other factors that play into |
(...skipping 13 matching lines...) Expand all Loading... |
24 * @private {?chrome.hotwordPrivate.StatusDetails} | 24 * @private {?chrome.hotwordPrivate.StatusDetails} |
25 */ | 25 */ |
26 this.hotwordStatus_ = null; | 26 this.hotwordStatus_ = null; |
27 | 27 |
28 /** | 28 /** |
29 * NaCl plugin manager. | 29 * NaCl plugin manager. |
30 * @private {?hotword.NaClManager} | 30 * @private {?hotword.NaClManager} |
31 */ | 31 */ |
32 this.pluginManager_ = null; | 32 this.pluginManager_ = null; |
33 | 33 |
| 34 /** |
| 35 * Source of the current hotword session. |
| 36 * @private {?hotword.constants.SessionSource} |
| 37 */ |
| 38 this.sessionSource_ = null; |
| 39 |
| 40 /** |
| 41 * Callback to run when the hotword detector has successfully started. |
| 42 * @private {!function()} |
| 43 */ |
| 44 this.sessionStartedCb_ = null; |
| 45 |
34 // Get the initial status. | 46 // Get the initial status. |
35 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); | 47 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); |
36 } | 48 } |
37 | 49 |
38 /** | 50 /** |
39 * @enum {number} | 51 * @enum {number} |
40 * @private | 52 * @private |
41 */ | 53 */ |
42 StateManager.State_ = { | 54 StateManager.State_ = { |
43 STOPPED: 0, | 55 STOPPED: 0, |
(...skipping 22 matching lines...) Expand all Loading... |
66 this.hotwordStatus_ = status; | 78 this.hotwordStatus_ = status; |
67 this.updateStateFromStatus_(); | 79 this.updateStateFromStatus_(); |
68 }, | 80 }, |
69 | 81 |
70 /** | 82 /** |
71 * Updates state based on the current status. | 83 * Updates state based on the current status. |
72 * @private | 84 * @private |
73 */ | 85 */ |
74 updateStateFromStatus_: function() { | 86 updateStateFromStatus_: function() { |
75 if (this.hotwordStatus_.enabled) { | 87 if (this.hotwordStatus_.enabled) { |
76 // Hotwording is enabled. | 88 // Start the detector if there's a session, and shut it down if there |
77 // TODO(amistry): Have a separate alwaysOnEnabled flag. For now, treat | 89 // isn't. |
78 // "enabled" as "always on enabled". | 90 // TODO(amistry): Support stacking sessions. This can happen when the |
79 this.startDetector_(); | 91 // user opens google.com or the NTP, then opens the launcher. Opening |
| 92 // google.com will create one session, and opening the launcher will |
| 93 // create the second. Closing the launcher should re-activate the |
| 94 // google.com session. |
| 95 // NOTE(amistry): With always-on, we want a different behaviour with |
| 96 // sessions since the detector should always be running. The exception |
| 97 // being when the user triggers by saying 'Ok Google'. In that case, the |
| 98 // detector stops, so starting/stopping the launcher session should |
| 99 // restart the detector. |
| 100 if (this.sessionSource_) |
| 101 this.startDetector_(); |
| 102 else |
| 103 this.shutdownDetector_(); |
80 } else { | 104 } else { |
81 // Not enabled. Shut down if running. | 105 // Not enabled. Shut down if running. |
82 this.shutdownDetector_(); | 106 this.shutdownDetector_(); |
83 } | 107 } |
84 }, | 108 }, |
85 | 109 |
86 /** | 110 /** |
87 * Starts the hotword detector. | 111 * Starts the hotword detector. |
88 * @private | 112 * @private |
89 */ | 113 */ |
(...skipping 29 matching lines...) Expand all Loading... |
119 this.shutdownPluginManager_(); | 143 this.shutdownPluginManager_(); |
120 } | 144 } |
121 }.bind(this), | 145 }.bind(this), |
122 function(error) { | 146 function(error) { |
123 this.state_ = State_.ERROR; | 147 this.state_ = State_.ERROR; |
124 this.pluginManager_ = null; | 148 this.pluginManager_ = null; |
125 }.bind(this)); | 149 }.bind(this)); |
126 }.bind(this)); | 150 }.bind(this)); |
127 } else if (this.state_ != State_.STARTING) { | 151 } else if (this.state_ != State_.STARTING) { |
128 // Don't try to start a starting detector. | 152 // Don't try to start a starting detector. |
129 this.state_ = State_.RUNNING; | 153 this.startRecognizer_(); |
130 this.pluginManager_.startRecognizer(); | |
131 } | 154 } |
132 }, | 155 }, |
133 | 156 |
134 /** | 157 /** |
| 158 * Start the recognizer plugin. Assumes the plugin has been loaded and is |
| 159 * ready to start. |
| 160 * @private |
| 161 */ |
| 162 startRecognizer_: function() { |
| 163 assert(this.pluginManager_); |
| 164 if (this.state_ != State_.RUNNING) { |
| 165 this.state_ = State_.RUNNING; |
| 166 this.pluginManager_.startRecognizer(); |
| 167 } |
| 168 if (this.sessionStartedCb_) { |
| 169 this.sessionStartedCb_(); |
| 170 this.sessionStartedCb_ = null; |
| 171 } |
| 172 }, |
| 173 |
| 174 /** |
135 * Shuts down and removes the plugin manager, if it exists. | 175 * Shuts down and removes the plugin manager, if it exists. |
136 * @private | 176 * @private |
137 */ | 177 */ |
138 shutdownPluginManager_: function() { | 178 shutdownPluginManager_: function() { |
139 if (this.pluginManager_) { | 179 if (this.pluginManager_) { |
140 this.pluginManager_.shutdown(); | 180 this.pluginManager_.shutdown(); |
141 this.pluginManager_ = null; | 181 this.pluginManager_ = null; |
142 } | 182 } |
143 }, | 183 }, |
144 | 184 |
(...skipping 11 matching lines...) Expand all Loading... |
156 * @private | 196 * @private |
157 */ | 197 */ |
158 onReady_: function() { | 198 onReady_: function() { |
159 if (this.state_ != State_.STARTING) { | 199 if (this.state_ != State_.STARTING) { |
160 // At this point, we should not be in the RUNNING state. Doing so would | 200 // At this point, we should not be in the RUNNING state. Doing so would |
161 // imply the hotword detector was started without being ready. | 201 // imply the hotword detector was started without being ready. |
162 assert(this.state_ != State_.RUNNING); | 202 assert(this.state_ != State_.RUNNING); |
163 this.shutdownPluginManager_(); | 203 this.shutdownPluginManager_(); |
164 return; | 204 return; |
165 } | 205 } |
166 this.state_ = State_.RUNNING; | 206 this.startRecognizer_(); |
167 this.pluginManager_.startRecognizer(); | |
168 }, | 207 }, |
169 | 208 |
170 /** | 209 /** |
171 * Handle an error from the hotword plugin. | 210 * Handle an error from the hotword plugin. |
172 * @private | 211 * @private |
173 */ | 212 */ |
174 onError_: function() { | 213 onError_: function() { |
175 this.state_ = State_.ERROR; | 214 this.state_ = State_.ERROR; |
176 this.shutdownPluginManager_(); | 215 this.shutdownPluginManager_(); |
177 }, | 216 }, |
178 | 217 |
179 /** | 218 /** |
180 * Handle hotword triggering. | 219 * Handle hotword triggering. |
181 * @private | 220 * @private |
182 */ | 221 */ |
183 onTrigger_: function() { | 222 onTrigger_: function() { |
184 assert(this.pluginManager_); | 223 assert(this.pluginManager_); |
185 // Detector implicitly stops when the hotword is detected. | 224 // Detector implicitly stops when the hotword is detected. |
186 this.state_ = State_.STOPPED; | 225 this.state_ = State_.STOPPED; |
187 | 226 |
188 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); | 227 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); |
| 228 |
| 229 // Implicitly clear the session. A session needs to be started in order to |
| 230 // restart the detector. |
| 231 this.sessionSource_ = null; |
| 232 this.sessionStartedCb_ = null; |
| 233 }, |
| 234 |
| 235 /** |
| 236 * Start a hotwording session. |
| 237 * @param {!hotword.constants.SessionSource} source Source of the hotword |
| 238 * session request. |
| 239 * @param {!function()} started_cb Callback invoked when the session has |
| 240 * been started successfully. |
| 241 */ |
| 242 startSession: function(source, started_cb) { |
| 243 this.sessionSource_ = source; |
| 244 this.sessionStartedCb_ = started_cb; |
| 245 if (this.hotwordStatus_) |
| 246 this.updateStateFromStatus_(); |
| 247 }, |
| 248 |
| 249 /** |
| 250 * Stops a hotwording session. |
| 251 * @param {!hotword.constants.SessionSource} source Source of the hotword |
| 252 * session request. |
| 253 */ |
| 254 stopSession: function(source) { |
| 255 this.sessionSource_ = null; |
| 256 this.sessionStartedCb_ = null; |
| 257 if (this.hotwordStatus_) |
| 258 this.updateStateFromStatus_(); |
189 } | 259 } |
190 }; | 260 }; |
191 | 261 |
192 return { | 262 return { |
193 StateManager: StateManager | 263 StateManager: StateManager |
194 }; | 264 }; |
195 }); | 265 }); |
OLD | NEW |