blob: f5b68d44885ff2862115cf396272fc31ed7f9cfe [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('hotword', function() {
'use strict';
/**
* Class used to manage speaker training. Starts a hotwording session
* if training is on, and automatically restarts the detector when a
* a hotword is triggered.
* @param {!hotword.StateManager} stateManager
* @constructor
* @extends {hotword.BaseSessionManager}
*/
function TrainingManager(stateManager) {
/**
* Chrome event listeners. Saved so that they can be de-registered when
* hotwording is disabled.
* @private
*/
this.finalizedSpeakerModelListener_ =
this.handleFinalizeSpeakerModel_.bind(this);
hotword.BaseSessionManager.call(
this, stateManager, hotword.constants.SessionSource.TRAINING);
}
/**
* Handles a success event on mounting the file system event and deletes
* the user data files.
* @param {FileSystem} fs The FileSystem object.
* @private
*/
TrainingManager.deleteFiles_ = function(fs) {
fs.root.getFile(
hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false},
TrainingManager.deleteFile_, TrainingManager.fileErrorHandler_);
for (var i = 0; i < hotword.constants.NUM_TRAINING_UTTERANCES; ++i) {
fs.root.getFile(
hotword.constants.UTTERANCE_FILE_PREFIX + i +
hotword.constants.UTTERANCE_FILE_EXTENSION,
{create: false}, TrainingManager.deleteFile_,
TrainingManager.fileErrorHandler_);
}
};
/**
* Deletes a file.
* @param {FileEntry} fileEntry The FileEntry object.
* @private
*/
TrainingManager.deleteFile_ = function(fileEntry) {
if (fileEntry.isFile) {
hotword.debug('File found: ' + fileEntry.fullPath);
if (hotword.DEBUG || window.localStorage['hotword.DEBUG']) {
fileEntry.getMetadata(function(md) {
hotword.debug('File size: ' + md.size);
});
}
fileEntry.remove(function() {
hotword.debug('File removed: ' + fileEntry.fullPath);
}, TrainingManager.fileErrorHandler_);
}
};
/**
* Handles a failure event on mounting the file system event.
* @param {FileError} e The FileError object.
* @private
*/
TrainingManager.fileErrorHandler_ = function(e) {
hotword.debug('File error: ' + e.code);
};
/**
* Handles a failure event on checking for the existence of the speaker model.
* @param {FileError} e The FileError object.
* @private
*/
TrainingManager.sendNoSpeakerModelResponse_ = function(e) {
chrome.hotwordPrivate.speakerModelExistsResult(false);
};
/**
* Handles a success event on mounting the file system and checks for the
* existence of the speaker model.
* @param {FileSystem} fs The FileSystem object.
* @private
*/
TrainingManager.speakerModelExists_ = function(fs) {
fs.root.getFile(
hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false},
TrainingManager.sendSpeakerModelExistsResponse_,
TrainingManager.sendNoSpeakerModelResponse_);
};
/**
* Sends a response through the HotwordPrivateApi indicating whether
* the speaker model exists.
* @param {FileEntry} fileEntry The FileEntry object.
* @private
*/
TrainingManager.sendSpeakerModelExistsResponse_ = function(fileEntry) {
if (fileEntry.isFile) {
hotword.debug('File found: ' + fileEntry.fullPath);
if (hotword.DEBUG || window.localStorage['hotword.DEBUG']) {
fileEntry.getMetadata(function(md) {
hotword.debug('File size: ' + md.size);
});
}
}
chrome.hotwordPrivate.speakerModelExistsResult(fileEntry.isFile);
};
/**
* Handles a request to delete the speaker model.
*/
TrainingManager.handleDeleteSpeakerModel = function() {
window.webkitRequestFileSystem(
PERSISTENT, hotword.constants.FILE_SYSTEM_SIZE_BYTES,
TrainingManager.deleteFiles_, TrainingManager.fileErrorHandler_);
};
/**
* Handles a request for the speaker model existence.
*/
TrainingManager.handleSpeakerModelExists = function() {
window.webkitRequestFileSystem(
PERSISTENT, hotword.constants.FILE_SYSTEM_SIZE_BYTES,
TrainingManager.speakerModelExists_, TrainingManager.fileErrorHandler_);
};
TrainingManager.prototype = {
__proto__: hotword.BaseSessionManager.prototype,
/** @override */
enabled: function() {
return this.stateManager.isTrainingEnabled();
},
/** @override */
updateListeners: function() {
hotword.BaseSessionManager.prototype.updateListeners.call(this);
if (this.enabled()) {
// Detect when the speaker model needs to be finalized.
if (!chrome.hotwordPrivate.onFinalizeSpeakerModel.hasListener(
this.finalizedSpeakerModelListener_)) {
chrome.hotwordPrivate.onFinalizeSpeakerModel.addListener(
this.finalizedSpeakerModelListener_);
}
this.startSession(hotword.constants.RecognizerStartMode.NEW_MODEL);
} else {
chrome.hotwordPrivate.onFinalizeSpeakerModel.removeListener(
this.finalizedSpeakerModelListener_);
}
},
/** @override */
handleHotwordTrigger: function(log) {
if (this.enabled()) {
hotword.BaseSessionManager.prototype.handleHotwordTrigger.call(
this, log);
this.startSession(hotword.constants.RecognizerStartMode.ADAPT_MODEL);
}
},
/** @override */
startSession: function(opt_mode) {
this.stateManager.startSession(
this.sessionSource_,
function() {
chrome.hotwordPrivate.setHotwordSessionState(true, function() {});
},
this.handleHotwordTrigger.bind(this),
this.handleSpeakerModelSaved_.bind(this), opt_mode);
},
/**
* Handles a hotwordPrivate.onFinalizeSpeakerModel event.
* @private
*/
handleFinalizeSpeakerModel_: function() {
if (this.enabled())
this.stateManager.finalizeSpeakerModel();
},
/**
* Handles a hotwordPrivate.onFinalizeSpeakerModel event.
* @private
*/
handleSpeakerModelSaved_: function() {
if (this.enabled())
chrome.hotwordPrivate.notifySpeakerModelSaved();
},
};
return {TrainingManager: TrainingManager};
});