Skip to content

Commit

Permalink
Issue #14, persist test with fixes
Browse files Browse the repository at this point in the history
* Fix read from cache
* Update lru info on hit in cache
* Fix cache cleanup
* Better test cleanup
  • Loading branch information
parente committed Jul 17, 2011
1 parent ee382f1 commit dc88df3
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 22 deletions.
66 changes: 47 additions & 19 deletions JSonic.js
Expand Up @@ -576,7 +576,15 @@ dojo.declare('uow.audio.LRUCache', null, {
} }
}, },


get: function(key) {
var node = this._index[key];
if(node) {
return node.value;
}
},

push: function(key, value) { push: function(key, value) {
console.log('pushing', key);
// see if the key is already in the cache // see if the key is already in the cache
var curr = this._index[key]; var curr = this._index[key];
if(curr) { if(curr) {
Expand Down Expand Up @@ -660,8 +668,18 @@ dojo.declare('uow.audio.JSonicCache', dijit._Widget, {
throw new Error('no known media supported'); throw new Error('no known media supported');
} }
}, },

uninitialize: function() {
// persist cache before cleanup
this._serialize();
this._destroyed = true;
},


_serialize: function() { _serialize: function() {
if(this._destroyed) {
// don't persist if instance is destroyed
return;
}
localStorage['jsonic.cache'] = dojo.toJson(this._speechCache.toArray()); localStorage['jsonic.cache'] = dojo.toJson(this._speechCache.toArray());
}, },


Expand All @@ -679,17 +697,14 @@ dojo.declare('uow.audio.JSonicCache', dijit._Widget, {
} }
}, },


resetCache: function(args) { resetCache: function() {
if(localStorage) { if(localStorage) {
// clear out the cache // clear out the cache
delete localStorage['jsonic.cache']; delete localStorage['jsonic.cache'];
// update the version number // update the version number
localStorage['jsonic.version'] = uow.audio._jsonicVersion; localStorage['jsonic.version'] = uow.audio._jsonicVersion;
} }
this._speechCache = new uow.audio.LRUCache({maxSize : this.maxSize}); this._speechCache = new uow.audio.LRUCache({maxSize : this.maxSize});
// if(args) {
// delete this._speechCache[args.key];
// }
}, },


getEngines: function() { getEngines: function() {
Expand Down Expand Up @@ -766,31 +781,38 @@ dojo.declare('uow.audio.JSonicCache', dijit._Widget, {


getSpeech: function(args, props) { getSpeech: function(args, props) {
// get the client cache key // get the client cache key
var key = this._getSpeechCacheKey(args.text, props); var key = this._getSpeechCacheKey(args.text, props),
resultDef, audioNode, fileName, speechParams, request;
args.key = key; args.key = key;
var resultDef, audioNode;
// @todo: because we don't update lru upon each result, it's not
// truly lru; to meet strict definition, need to update stats
// when audio is actually used, not just when it's returned from
// the server; trying the simple way first, probably good enough


resultDef = this._speechRenderings[key]; resultDef = this._speechRenderings[key];
if(resultDef) { if(resultDef) {
// return deferred result for synth already in progress on server // return deferred result for synth already in progress on server
return resultDef; return resultDef;
} }
var response = this._speechCache[key]; fileName = this._speechCache.get(key);
if(response) { if(fileName) {
// build a new audio node for a known speech file url console.log('known key', key);
audioNode = this._onSpeechSynthed(null, args, response); // known key
this._speechCache.push(key, fileName);
audioNode = this._buildNode(fileName);
resultDef = new dojo.Deferred(); resultDef = new dojo.Deferred();
resultDef.callback(audioNode); resultDef.callback(audioNode);
return resultDef; return resultDef;
} }
// synth on server // synth on server
var speechParams = { speechParams = {
format : this._ext, format : this._ext,
utterances : {text : args.text}, utterances : {text : args.text},
properties: props properties: props
}; };
resultDef = new dojo.Deferred(); resultDef = new dojo.Deferred();
var request = { request = {
url : this.jsonicURI+'synth', url : this.jsonicURI+'synth',
handleAs: 'json', handleAs: 'json',
postData : dojo.toJson(speechParams), postData : dojo.toJson(speechParams),
Expand Down Expand Up @@ -821,15 +843,21 @@ dojo.declare('uow.audio.JSonicCache', dijit._Widget, {


_onSpeechSynthed: function(resultDef, args, response) { _onSpeechSynthed: function(resultDef, args, response) {
delete this._speechRenderings[args.key]; delete this._speechRenderings[args.key];
var node = {}; //dojo.create('audio'); var fileName = response.result.text;
node.autobuffer = true; var node = this._buildNode(fileName);
node.preload = 'auto';
node.src = this.jsonicURI+'files/'+response.result.text+this._ext;
if(args.cache) { if(args.cache) {
// cache the speech file url and properties // cache the speech file url and properties
this._speechCache.push(args.key, response); this._speechCache.push(args.key, fileName);
} }
if(resultDef) {resultDef.callback(node);} resultDef.callback(node);
return node;
},

_buildNode: function(fileName) {
var node = {}; //dojo.create('audio');
node.autobuffer = true;
node.preload = 'auto';
node.src = this.jsonicURI+'files/'+fileName+this._ext;
return node; return node;
} }
}); });
Expand Down Expand Up @@ -1144,7 +1172,7 @@ dojo.declare('uow.audio.JSonicChannel', dijit._Widget, {
if(this._kind === 'say') { if(this._kind === 'say') {
// if speech, dump the entire local cache assuming we need a // if speech, dump the entire local cache assuming we need a
// resynth of everything // resynth of everything
this.cache.resetCache(this._args); this.cache.resetCache();
} }
// clear everything before the callback // clear everything before the callback
var cargs = this._args; var cargs = this._args;
Expand Down
6 changes: 3 additions & 3 deletions tests/index.html
Expand Up @@ -38,16 +38,16 @@
} }
}; };
QUnit.moduleDone = function(name) { QUnit.moduleDone = function(name) {
if(uow.audio.initJSonic) { if(uow.audio._jsonicInstance) {
// cleanup JSonic singleton before next module runs // cleanup JSonic singleton before next module runs
var js = uow.audio.initJSonic(); uow.audio._jsonicInstance.destroyRecursive();
js.destroyRecursive();
} }
}; };


dojo.require('uow.audio.JSonic'); dojo.require('uow.audio.JSonic');
dojo.require('uow.audio.tests.lru'); dojo.require('uow.audio.tests.lru');
dojo.require('uow.audio.tests.creation'); dojo.require('uow.audio.tests.creation');
dojo.require('uow.audio.tests.persist');
dojo.require('uow.audio.tests.simple'); dojo.require('uow.audio.tests.simple');
dojo.require('uow.audio.tests.interrupt'); dojo.require('uow.audio.tests.interrupt');
dojo.require('uow.audio.tests.sequential'); dojo.require('uow.audio.tests.sequential');
Expand Down
37 changes: 37 additions & 0 deletions tests/persist.js
@@ -0,0 +1,37 @@
/*global TO UT1 UT2 localStorage dojo ok equal getModOpts module test stop start uow*/
dojo.provide('uow.audio.tests.persist');

(function() {
module('persist', {
setup: function() {
this.js = uow.audio.initJSonic({defaultCaching : true});
},
teardown: function() {
if(this.js) {
this.js.destroyRecursive();
}
delete localStorage['jsonic.cache'];
}
});
test('persist cache', 4, function () {
stop(TO);
var self = this;
this.js.say({text : UT1}).callAfter(function() {
self.js.say({text : UT1}).callAfter(function() {
// destroy instance to force persistence of cache
self.js.destroy();
// verify cache created and its length
var arr = dojo.fromJson(localStorage['jsonic.cache']);
equal(arr.length, 2);
equal(arr[0][0].slice(0, UT2.length), UT2);
equal(arr[1][0].slice(0, UT1.length), UT1);
// build a new instance to read the cache
self.js = uow.audio.initJSonic({defaultCaching : true});
// whitebox: look at cache contents
equal(self.js._cache._speechCache.size, 2);
start();
});
});
this.js.say({text : UT2});
});
}());

0 comments on commit dc88df3

Please sign in to comment.