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.
6 * @fileoverview The manager of offline hotword speech recognizer plugin.
9 cr.define('speech', function() {
13 * The type of the plugin state.
19 SAMPLING_RATE_READY: 2,
25 * The command names of the plugin.
28 var pluginCommands = {
29 SET_SAMPLING_RATE: 'h',
31 START_RECOGNIZING: 'r',
36 * The regexp pattern of the hotword recognition result.
38 var recognitionPattern = /^HotwordFiredEvent: \[(.*)\] confidence: (.*)/;
41 * Checks the availability of the plugin.
42 * @return {boolean} True only if the plugin is available.
44 function isPluginAvailable() {
45 return !!($('recognizer') && $('recognizer').postMessage);
51 function PluginManager(onReady, onRecognized) {
52 this.state = PluginState.UNINITIALIZED;
53 this.onReady_ = onReady;
54 this.onRecognized_ = onRecognized;
55 this.samplingRate_ = null;
57 if (isPluginAvailable()) {
58 $('recognizer').addEventListener('message', this.onMessage_.bind(this));
59 $('recognizer').addEventListener('load', this.onLoad_.bind(this));
64 * The event handler of the plugin status.
66 * @param {Event} messageEvent the event object from the plugin.
69 PluginManager.prototype.onMessage_ = function(messageEvent) {
70 if (this.state == PluginState.LOADED) {
71 if (messageEvent.data == 'stopped')
72 this.state = PluginState.SAMPLING_RATE_READY;
76 if (messageEvent.data == 'audio') {
77 if (this.state < PluginState.READY)
79 this.state = PluginState.RECOGNIZING;
80 } else if (messageEvent.data == 'stopped') {
81 this.state = PluginState.READY;
83 var matched = recognitionPattern.exec(messageEvent.data);
84 if (matched && matched[1] == 'hotword_ok_google')
85 this.onRecognized_(Number(matched[2]));
90 * The event handler when the plugin is loaded.
94 PluginManager.prototype.onLoad_ = function() {
95 if (this.state == PluginState.UNINITIALIZED) {
96 this.state = PluginState.LOADED;
97 if (this.samplingRate_ && this.config_)
98 this.initialize_(this.samplingRate_, this.config_);
103 * Sends the initialization messages to the plugin. This method is private.
104 * The initialization will happen from onLoad_ or scheduleInitialize.
106 * @param {number} samplingRate the sampling rate the plugin accepts.
107 * @param {string} config the url of the config file.
110 PluginManager.prototype.initialize_ = function(samplingRate, config) {
111 $('recognizer').postMessage(
112 pluginCommands.SET_SAMPLING_RATE + samplingRate);
113 $('recognizer').postMessage(pluginCommands.SET_CONFIG + config);
117 * Initializes the plugin with the specified parameter, or schedules the
118 * initialization if the plugin is not ready.
120 * @param {number} samplingRate the sampling rate the plugin accepts.
121 * @param {string} config the url of the config file.
123 PluginManager.prototype.scheduleInitialize = function(samplingRate, config) {
124 if (this.state == PluginState.UNINITIALIZED) {
125 this.samplingRate_ = samplingRate;
126 this.config_ = config;
128 this.initialize_(samplingRate, config);
133 * Asks the plugin to start recognizing the hotword.
135 PluginManager.prototype.startRecognizer = function() {
136 if (this.state == PluginState.READY)
137 $('recognizer').postMessage(pluginCommands.START_RECOGNIZING);
141 * Asks the plugin to stop recognizing the hotword.
143 PluginManager.prototype.stopRecognizer = function() {
144 if (this.state == PluginState.RECOGNIZING)
145 $('recognizer').postMessage(pluginCommands.STOP_RECOGNIZING);
149 * Sends the actual audio wave data.
151 * @param {cr.event.Event} event The event for the audio data.
153 PluginManager.prototype.sendAudioData = function(event) {
154 if (this.state == PluginState.RECOGNIZING)
155 $('recognizer').postMessage(event.data.buffer);
159 PluginManager: PluginManager,
160 PluginState: PluginState,
161 isPluginAvailable: isPluginAvailable