this.ttsPosition = -1; //chunk (paragraph) number
this.ttsBuffering = false;
this.ttsPoller = null;
+ this.ttsFormat = null;
return this;
};
}
this.autoStop();
+ this.ttsStop();
this.removeSearchHilites();
this.mode = mode;
$(this.leafEdgeL).bind('click', this, function(e) {
e.data.autoStop();
+ e.data.ttsStop();
var jumpIndex = e.data.jumpIndexForLeftEdgePageX(e.pageX);
e.data.jumpToIndex(jumpIndex);
});
$(this.leafEdgeR).bind('click', this, function(e) {
e.data.autoStop();
+ e.data.ttsStop();
var jumpIndex = e.data.jumpIndexForRightEdgePageX(e.pageX);
e.data.jumpToIndex(jumpIndex);
});
// next()
//______________________________________________________________________________
BookReader.prototype.next = function() {
- this.ttsStop();
-
if (2 == this.mode) {
this.autoStop();
this.flipFwdToIndex(null);
// prev()
//______________________________________________________________________________
BookReader.prototype.prev = function() {
- this.ttsStop();
-
if (2 == this.mode) {
this.autoStop();
this.flipBackToIndex(null);
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexL],
{ self: this },
function(e) {
+ e.data.self.ttsStop();
e.data.self.left();
e.preventDefault();
}
this.setClickHandler2UP( this.prefetchedImgs[this.twoPage.currentIndexR],
{ self: this },
function(e) {
+ e.data.self.ttsStop();
e.data.self.right();
e.preventDefault();
}
return;
}
this.autoStop();
+ this.ttsStop();
this.embedPopup = document.createElement("div");
$(this.embedPopup).css({
position: 'absolute',
$("#BookReader").append("<div id='BRtoolbar'>"
+ "<span id='BRtoolbarbuttons' style='float: right'>"
- + "<button class='BRicon rollover read_aloud' onclick='br.ttsStart(); return false;'/>"
+ + "<button class='BRicon rollover read_aloud' onclick='br.ttsToggle(); return false;'/>"
+ "<button class='BRicon print rollover' /> <button class='BRicon rollover embed' />"
+ "<form class='BRpageform' action='javascript:' onsubmit='br.jumpToPage(this.elements[0].value)'> <span class='label'>Page:<input id='BRpagenum' type='text' size='3' onfocus='br.autoStop();'></input></span></form>"
+ "<div class='BRtoolbarmode2' style='display: none'><button class='BRicon rollover book_leftmost' /><button class='BRicon rollover book_left' /><button class='BRicon rollover book_right' /><button class='BRicon rollover book_rightmost' /></div>"
if (newHash != self.oldUserHash) { // Only process new user hash once
//console.log('url change detected ' + self.oldLocationHash + " -> " + newHash);
+ self.ttsStop();
+
// Queue change if animating
if (self.animating) {
self.autoStop();
}
-// ttsStart()
+// ttsToggle()
//______________________________________________________________________________
-BookReader.prototype.ttsStart = function () {
+BookReader.prototype.ttsToggle = function () {
if (false == this.ttsPlaying) {
- console.log('starting readAloud');
- this.ttsPlaying = true;
- this.ttsIndex = this.currentIndex();
- this.ttsGetText(this.ttsIndex, 'ttsStartCB');
+ if(soundManager.supported()) {
+ this.ttsStart();
+ } else {
+ soundManager.onready(function(oStatus) {
+ if (oStatus.success) {
+ this.ttsStart();
+ } else {
+ alert('Could not load soundManger2, possibly due to FlashBlock. Audio playback is disabled');
+ }
+ }, this);
+ }
} else {
this.ttsStop();
}
}
+// ttsStart()
+//______________________________________________________________________________
+BookReader.prototype.ttsStart = function () {
+ if (soundManager.debugMode) console.log('starting readAloud');
+ this.ttsPlaying = true;
+ this.ttsIndex = this.currentIndex();
+ this.ttsFormat = 'mp3';
+ if ($.browser.mozilla) {
+ this.ttsFormat = 'ogg';
+ }
+ this.ttsGetText(this.ttsIndex, 'ttsStartCB');
+}
+
// ttsStop()
//______________________________________________________________________________
BookReader.prototype.ttsStop = function () {
if (false == this.ttsPlaying) return;
- console.log('stopping readaloud');
+ if (soundManager.debugMode) console.log('stopping readaloud');
soundManager.stopAll();
soundManager.destroySound('chunk'+this.ttsIndex+'-'+this.ttsPosition);
this.ttsRemoveHilites();
+ this.ttsRemovePopup();
this.ttsPlaying = false;
this.ttsIndex = null; //leaf index
// ttsGetText()
//______________________________________________________________________________
BookReader.prototype.ttsGetText = function(index, callback) {
- var url = 'http://'+this.server+'/BookReader/BookReaderGetTextWrapper.php?path='+this.bookPath+'_djvu.xml&page='+index;
+ var url = 'http://'+this.server+'/BookReader/BookReaderGetTextWrapper.php?path='+this.bookPath+'_djvu.xml&page='+index;
this.ttsAjax = $.ajax({url:url, dataType:'jsonp', jsonpCallback:callback});
}
// ttsStartCB(): text-to-speech callback
//______________________________________________________________________________
BookReader.prototype.ttsStartCB = function (data) {
- console.log('ttsStartCB got data:');
- console.log(data);
+ if (soundManager.debugMode) console.log('ttsStartCB got data: ' + data);
this.ttsChunks = data;
this.ttsHilites = [];
//deal with the page being blank
if (0 == data.length) {
- console.log('first page is blank!');
+ if (soundManager.debugMode) console.log('first page is blank!');
if(this.ttsAdvance(true)) {
this.ttsGetText(this.ttsIndex, 'ttsStartCB');
}
return;
- } else {
- console.log('length = ' + data.length);
- console.log((0 == data.length));
}
this.ttsShowPopup();
+ ///// whileloading: broken on safari
+ ///// onload fires on safari, but *after* the sound starts playing..
this.ttsPosition = -1;
var snd = soundManager.createSound({
id: 'chunk'+this.ttsIndex+'-0',
- //url: 'http://home.us.archive.org/~rkumar/arctic.ogg',
- url: 'http://home.us.archive.org/~rkumar/getOgg.php?string=' + escape(data[0][0]) + '&f=.ogg', //the .ogg is to trick SoundManager2 to use the HTML5 audio player
- whileloading: function(){if (this.bytesLoaded == this.bytesTotal) {$(br.popup).remove(); br.popup=null;}} //onload never fires...
+ //url: 'http://home.us.archive.org/~rkumar/arctic.ogg',
+ url: 'http://'+this.server+'/BookReader/BookReaderGetTTS.php?string=' + escape(data[0][0]) + '&format=.'+this.ttsFormat, //the .ogg is to trick SoundManager2 to use the HTML5 audio player
+ whileloading: function(){if (this.bytesLoaded == this.bytesTotal) this.br.ttsRemovePopup();}, //onload never fires in FF...
+ onload: function(){this.br.ttsRemovePopup();} //whileloading never fires in safari...
});
snd.br = this;
snd.load();
// ttsShowPopup
//______________________________________________________________________________
BookReader.prototype.ttsShowPopup = function() {
+ if (soundManager.debugMode) console.log('ttsShowPopup index='+this.ttsIndex+' pos='+this.ttsPosition);
+
this.popup = document.createElement("div");
$(this.popup).css({
- position: 'absolute',
- top: '20%',
- left: ($('#BRcontainer').attr('clientWidth')-600)/2 + 'px',
- width: '600px',
- padding: "20px",
- border: "3px double #999999",
- zIndex: 3,
- backgroundColor: "#f00",
- color: "#fff",
- fontSize: '1.875em'
- }).appendTo('#BookReader');
+ top: $('#BRtoolbar').height() + 'px',
+ left: $('.read_aloud').position().left + 'px',
+ width: $('#BRtoolbar').width()-$('.read_aloud').position().left + 'px',
+ height: '20px',
+ }).attr('className', 'BRttsPopUp').appendTo('#BookReader');
- htmlStr = '<p style="text-align:center;"><b>Ever wanted to wait while audio loads?</b><br/>';
- htmlStr += "It's OK. We all do.</p>";
+ htmlStr = ' ';
this.popup.innerHTML = htmlStr;
}
+// ttsRemovePopup
+//______________________________________________________________________________
+BookReader.prototype.ttsRemovePopup = function() {
+ $(this.popup).remove();
+ this.popup=null;
+}
+
// ttsNextPageCB
//______________________________________________________________________________
BookReader.prototype.ttsNextPageCB = function (data) {
this.ttsNextChunks = data;
- console.log('preloaded next chunks.. data is');
- console.log(data);
+ if (soundManager.debugMode) console.log('preloaded next chunks.. data is ' + data);
if (true == this.ttsBuffering) {
- console.log('ttsNextPageCB: ttsBuffering is true');
+ if (soundManager.debugMode) console.log('ttsNextPageCB: ttsBuffering is true');
this.ttsBuffering = false;
}
}
BookReader.prototype.ttsLoadChunk = function (page, pos, string) {
var snd = soundManager.createSound({
id: 'chunk'+page+'-'+pos,
- url: 'http://home.us.archive.org/~rkumar/getOgg.php?string=' + escape(string) + '&f=.ogg' //the .ogg is to trick SoundManager2 to use the HTML5 audio player
+ url: 'http://'+this.server+'/BookReader/BookReaderGetTTS.php?string=' + escape(string) + '&format=.'+this.ttsFormat //the .ogg is to trick SoundManager2 to use the HTML5 audio player
});
snd.br = this;
snd.load()
// continues after animation is finished.
BookReader.prototype.ttsNextChunk = function () {
- console.log(this);
- console.log(this.ttsPosition);
+ if (soundManager.debugMode) console.log('nextchunk pos=' + this.ttsPosition);
if (-1 != this.ttsPosition) {
soundManager.destroySound('chunk'+this.ttsIndex+'-'+this.ttsPosition);
//______________________________________________________________________________
// page flip animation has now completed
BookReader.prototype.ttsNextChunkPhase2 = function () {
+ if (null == this.ttsChunks) {
+ alert('error: ttsChunks is null?'); //TODO
+ return;
+ }
+
if (0 == this.ttsChunks.length) {
- console.log('ttsNextChunk2: ttsChunks.length is zero.. hacking...');
+ if (soundManager.debugMode) console.log('ttsNextChunk2: ttsChunks.length is zero.. hacking...');
this.ttsStartCB(this.ttsChunks);
return;
}
- console.log('next chunk is ');
- console.log(this.ttsPosition);
+ if (soundManager.debugMode) console.log('next chunk is ' + this.ttsPosition);
//prefetch next page of text
if (0 == this.ttsPosition) {
if (this.ttsPosition >= this.ttsChunks.length) {
if (this.ttsIndex == (this.numLeafs-1)) {
- console.log('tts stop');
+ if (soundManager.debugMode) console.log('tts stop');
return false;
} else {
if ((null != this.ttsNextChunks) || (starting)) {
- console.log('moving to next page!');
+ if (soundManager.debugMode) console.log('moving to next page!');
this.ttsIndex++;
this.ttsPosition = 0;
this.ttsChunks = this.ttsNextChunks;
this.ttsNextChunks = null;
+
+ //A page flip might be necessary. This code is confusing since
+ //ttsNextChunks might be null if we are starting on a blank page.
if (2 == this.mode) {
if ((this.ttsIndex != this.twoPage.currentIndexL) && (this.ttsIndex != this.twoPage.currentIndexR)) {
- this.animationFinishedCallback = this.ttsNextChunkPhase2;
- this.next();
- return false;
+ if (!starting) {
+ this.animationFinishedCallback = this.ttsNextChunkPhase2;
+ this.next();
+ return false;
+ } else {
+ this.next();
+ return true;
+ }
} else {
return true;
}
}
} else {
- console.log('ttsAdvance: ttsNextChunks is null');
+ if (soundManager.debugMode) console.log('ttsAdvance: ttsNextChunks is null');
return false;
}
}
}
-
- if ((this.constMode1up == this.mode) && (null != this.ttsChunks) && (0 != this.ttsChunks.length)) {
- var leafTop = 0;
- var h;
- var i;
- for (i=0; i<this.ttsIndex; i++) {
- h = parseInt(this._getPageHeight(i)/this.reduce);
- leafTop += h + this.padding;
- }
-
- var chunk = this.ttsChunks[this.ttsPosition];
- console.log('chunk=');
- console.log(chunk);
- var chunkTop = chunk[1][3]; //coords are in l,b,r,t order
- var chunkBot = chunk[chunk.length-1][1];
- var topOfFirstChunk = leafTop + chunkTop/this.reduce;
- var botOfLastChunk = leafTop + chunkBot/this.reduce;
-
- console.log('leafTop = ' + leafTop + ' topOfFirstChunk = ' + topOfFirstChunk + ' botOfLastChunk = ' + botOfLastChunk);
-
- var containerTop = $('#BRcontainer').attr('scrollTop');
- var containerBot = containerTop + $('#BRcontainer').height();
- console.log('containerTop = ' + containerTop + ' containerBot = ' + containerBot);
-
- if ((topOfFirstChunk < containerTop) || (botOfLastChunk > containerBot)) {
- console.log('jumping to leafTop!');
-
- //jumpToIndex scrolls so that chunkTop is centered.. we want chunkTop at the top
- //this.jumpToIndex(this.ttsIndex, null, chunkTop);
- $('#BRcontainer').animate({scrollTop: topOfFirstChunk,},'fast');
- }
- }
-
return true;
}
if(false != this.ttsBuffering) {
alert('TTS Error: prefetch() called while content still buffering!');
return;
- }
-
-
+ }
//preload next chunk
var nextPos = this.ttsPosition+1;
this.ttsLoadChunk(this.ttsIndex, nextPos, this.ttsChunks[nextPos][0]);
} else {
//for a short page, preload might nt have yet returned..
- console.log('preloading chunk 0 from next page, index='+(this.ttsIndex+1))
+ if (soundManager.debugMode) console.log('preloading chunk 0 from next page, index='+(this.ttsIndex+1));
if (null != this.ttsNextChunks) {
console.log(this.ttsNextChunks);
if (0 != this.ttsNextChunks.length) {
this.ttsLoadChunk(this.ttsIndex+1, 0, this.ttsNextChunks[0][0]);
} else {
- console.log('prefetchAudio(): ttsNextChunks is zero length!');
+ if (soundManager.debugMode) console.log('prefetchAudio(): ttsNextChunks is zero length!');
}
} else {
- console.log('ttsNextChunks is null, not preloading next page');
+ if (soundManager.debugMode) console.log('ttsNextChunks is null, not preloading next page');
this.ttsBuffering = true;
}
}
BookReader.prototype.ttsPlay = function () {
var chunk = this.ttsChunks[this.ttsPosition];
- console.log('position = ' + this.ttsPosition);
- console.log('chunk = ' + chunk);
- console.log(this.ttsChunks);
-
+ if (soundManager.debugMode) {
+ console.log('ttsPlay position = ' + this.ttsPosition);
+ console.log('chunk = ' + chunk);
+ console.log(this.ttsChunks);
+ }
+
//add new hilights
if (2 == this.mode) {
this.ttsHilite2UP(chunk);
} else {
this.ttsHilite1UP(chunk);
}
+
+ this.ttsScrollToChunk(chunk);
//play current chunk
- if (false == this.ttsBuffering) {
+ if (false == this.ttsBuffering) {
soundManager.play('chunk'+this.ttsIndex+'-'+this.ttsPosition,{onfinish:function(){br.ttsNextChunk();}});
} else {
- console.log('playing current chunk, but next chunk is not buffered yet!');
soundManager.play('chunk'+this.ttsIndex+'-'+this.ttsPosition,{onfinish:function(){br.ttsStartPolling();}});
}
}
+// scrollToChunk()
+//______________________________________________________________________________
+BookReader.prototype.ttsScrollToChunk = function(chunk) {
+ if (this.constMode1up != this.mode) return;
+
+ var leafTop = 0;
+ var h;
+ var i;
+ for (i=0; i<this.ttsIndex; i++) {
+ h = parseInt(this._getPageHeight(i)/this.reduce);
+ leafTop += h + this.padding;
+ }
+
+ var chunkTop = chunk[1][3]; //coords are in l,b,r,t order
+ var chunkBot = chunk[chunk.length-1][1];
+
+ var topOfFirstChunk = leafTop + chunkTop/this.reduce;
+ var botOfLastChunk = leafTop + chunkBot/this.reduce;
+
+ if (soundManager.debugMode) console.log('leafTop = ' + leafTop + ' topOfFirstChunk = ' + topOfFirstChunk + ' botOfLastChunk = ' + botOfLastChunk);
+
+ var containerTop = $('#BRcontainer').attr('scrollTop');
+ var containerBot = containerTop + $('#BRcontainer').height();
+ if (soundManager.debugMode) console.log('containerTop = ' + containerTop + ' containerBot = ' + containerBot);
+
+ if ((topOfFirstChunk < containerTop) || (botOfLastChunk > containerBot)) {
+ //jumpToIndex scrolls so that chunkTop is centered.. we want chunkTop at the top
+ //this.jumpToIndex(this.ttsIndex, null, chunkTop);
+ $('#BRcontainer').animate({scrollTop: topOfFirstChunk},'fast');
+ }
+}
+
// ttsHilite1UP()
//______________________________________________________________________________
BookReader.prototype.ttsHilite1UP = function(chunk) {
// We need to wait for the text for the next page to be loaded, so we can
// load the next audio chunk
BookReader.prototype.ttsStartPolling = function () {
- console.log('Starting the TTS poller...');
+ if (soundManager.debugMode) console.log('Starting the TTS poller...');
var self = this;
this.ttsPoller=setInterval(function(){
if (self.ttsBuffering) {return;}
- console.log('TTS buffering finished!');
+ if (soundManager.debugMode) console.log('TTS buffering finished!');
clearInterval(self.ttsPoller);
self.ttsPoller = null;
self.ttsPrefetchAudio();