diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-07-22 16:42:14 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-07-22 16:47:21 -0700 |
commit | 3501bc15bf13876d49acb2562a706f013e406c2b (patch) | |
tree | 6c8a31cbbb9f2c9efcbabd9df95a85bacc0c011c | |
parent | 82ce326a9a9a1f4fa4291b05b57d2e4d7c487314 (diff) |
refactor preload processing into plugins
-rw-r--r-- | src/library.js | 72 | ||||
-rw-r--r-- | src/library_browser.js | 97 |
2 files changed, 95 insertions, 74 deletions
diff --git a/src/library.js b/src/library.js index 52102f63..5ac890d9 100644 --- a/src/library.js +++ b/src/library.js @@ -296,73 +296,29 @@ LibraryManager.library = { createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror) { Browser.ensureObjects(); var fullname = FS.joinPath([parent, name], true); - function finish(byteArray) { - FS.createDataFile(parent, name, byteArray, canRead, canWrite); - if (Browser.isImageFile(name)) { - var bb = new Browser.BlobBuilder(); - bb.append(byteArray.buffer); - var b = bb.getBlob(); - var url = Browser.URLObject.createObjectURL(b); - var img = new Image(); - img.onload = function() { - assert(img.complete, 'Image ' + url + ' could not be decoded'); - var canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - var ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - Module["preloadedImages"][fullname] = canvas; - Browser.URLObject.revokeObjectURL(url); - if (onload) onload(); - removeRunDependency('cp ' + fullname); - }; - img.onerror = function(event) { - console.log('Image ' + url + ' could not be decoded'); - if (onerror) onerror(); - }; - img.src = url; - } else if (Browser.isAudioFile(name)) { - if (Browser.hasBlobConstructor) { - var b = new Blob([byteArray.buffer], { type: Browser.getAudioMimetype(name) }); - var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! - var audio = new Audio(); - audio.removedDependency = false; - audio['oncanplaythrough'] = function() { // XXX string for closure - audio['oncanplaythrough'] = null; - Module["preloadedAudios"][fullname] = audio; - if (!audio.removedDependency) { - if (onload) onload(); - removeRunDependency('cp ' + fullname); - audio.removedDependency = true; - } - }; - audio.onerror = function(event) { - if (!audio.removedDependency) { - console.log('Audio ' + url + ' could not be decoded or timed out trying to decode'); - if (onerror) onerror(); - removeRunDependency('cp ' + fullname); // keep calm and carry on - audio.removedDependency = true; - } - }; - setTimeout(audio.onerror, 2000); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) - audio.src = url; - } else { - Module["preloadedAudios"][fullname] = new Audio(); // empty shim - if (onerror) onerror(); - removeRunDependency('cp ' + fullname); - } - } else { + function processData(byteArray) { + function finish(byteArray) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite); if (onload) onload(); removeRunDependency('cp ' + fullname); } + var handled = false; + Module['preloadPlugins'].forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, onerror); + handled = true; + } + }); + if (!handled) finish(byteArray); } addRunDependency('cp ' + fullname); if (typeof url == 'string') { Browser.asyncLoad(url, function(byteArray) { - finish(byteArray); + processData(byteArray); }, onerror); } else { - finish(url); + processData(url); } }, // Creates a link to a sepcific local path. diff --git a/src/library_browser.js b/src/library_browser.js index f4b5164c..fc58e7da 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -6,7 +6,8 @@ mergeInto(LibraryManager.library, { $Browser__postset: 'Module["requestFullScreen"] = function() { Browser.requestFullScreen() };\n' + // exports 'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' + 'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' + - 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n', + 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n' + + 'Module["preloadPlugins"] = Browser.preloadPlugins;\n', $Browser: { mainLoop: { scheduler: null, @@ -54,6 +55,76 @@ mergeInto(LibraryManager.library, { } Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : console.log("warning: cannot build blobs")); Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); + + // preload plugins + var imagePlugin = {}; + imagePlugin['canHandle'] = function(name) { + return name.substr(-4) in { '.jpg': 1, '.png': 1, '.bmp': 1 }; + }; + imagePlugin['handle'] = function(byteArray, name, onload, onerror) { + var bb = new Browser.BlobBuilder(); + bb.append(byteArray.buffer); + var b = bb.getBlob(); + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function() { + assert(img.complete, 'Image ' + name + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][name] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(byteArray); + }; + img.onerror = function(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + }; + Module['preloadPlugins'].push(imagePlugin); + + var audioPlugin = { + getAudioMimetype: function(name) { + var ret = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' }[name.substr(-3)]; + assert(ret); + return ret; + } + }; + audioPlugin['canHandle'] = function(name) { + return name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }; + audioPlugin['handle'] = function(byteArray, name, onload, onerror) { + if (Browser.hasBlobConstructor) { + var b = new Blob([byteArray.buffer], { type: audioPlugin.getAudioMimetype(name) }); + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + var cleanedUp = false; + audio['oncanplaythrough'] = function() { // XXX string for closure + audio['oncanplaythrough'] = null; + Module["preloadedAudios"][name] = audio; + if (!cleanedUp) { + if (onload) onload(byteArray); + cleanedUp = true; + } + }; + audio.onerror = function(event) { + if (!cleanedUp) { + console.log('Audio ' + url + ' could not be decoded or timed out trying to decode'); + if (onerror) onerror(); + cleanedUp = true; + } + }; + setTimeout(audio.onerror, 2000); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) + audio.src = url; + } else { + Module["preloadedAudios"][name] = new Audio(); // empty shim + if (onerror) onerror(); + } + }; + Module['preloadPlugins'].push(audioPlugin); }, createContext: function(canvas, useWebGL, setInModule) { @@ -216,20 +287,14 @@ mergeInto(LibraryManager.library, { addRunDependency('al ' + url); }, - isImageFile: function(name) { - return name.substr(-4) in { '.jpg': 1, '.png': 1, '.bmp': 1 }; - }, - - isAudioFile: function(name) { - return name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; - }, - - getAudioMimetype: function(name) { - var ret = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' }[name.substr(-3)]; - assert(ret); - return ret; - }, - + // A list of plugins that can process preloaded files. You can add more of these to + // your app by appending to Module.preloadPlugins. + // + // Each plugin is asked if it can handle a file based on the file's name. If it can, + // it is given the file's raw data. When it is done, it calls a callback with the file's + // (possibly modified) data. For example, a plugin might decompress a file, or it + // might create some side data structure for use later (like an Image element, etc.). + preloadPlugins: [], }, emscripten_async_wget: function(url, file, onload, onerror) { @@ -279,7 +344,7 @@ mergeInto(LibraryManager.library, { Browser.mainLoop.remainingBlockers = (8*remaining + next)/9; } } - console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms, left: ' + Browser.mainLoop.remainingBlockers); + console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers); Browser.mainLoop.updateStatus(); setTimeout(wrapper, 0); return; |