aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library.js69
-rw-r--r--src/library_browser.js68
-rw-r--r--src/postamble.js1
-rw-r--r--src/preamble.js6
4 files changed, 119 insertions, 25 deletions
diff --git a/src/library.js b/src/library.js
index 01619b2a..2677eb10 100644
--- a/src/library.js
+++ b/src/library.js
@@ -273,10 +273,71 @@ LibraryManager.library = {
},
// Preloads a file asynchronously. You can call this before run, for example in
// preRun. run will be delayed until this file arrives and is set up.
- createPreloadedFile: function(parent, name, url, canRead, canWrite) {
- Browser.asyncLoad(url, function(data) {
- FS.createDataFile(parent, name, data, canRead, canWrite);
- });
+ // If you call it after run(), you may want to pause the main loop until it
+ // completes, if so, you can use the onload parameter to be notified when
+ // that happens.
+ // In addition to normally creating the file, we also asynchronously preload
+ // the browser-friendly versions of it: For an image, we preload an Image
+ // element and for an audio, and Audio. These are necessary for SDL_Image
+ // and _Mixer to find the files in preloadedImages/Audios.
+ createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror) {
+ Browser.ensureObjects();
+ Browser.asyncLoad(url, function(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"][name] = canvas;
+ Browser.URLObject.revokeObjectURL(url);
+ Module['removeRunDependency']();
+ if (onload) onload();
+ };
+ 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"][name] = audio;
+ if (!audio.removedDependency) {
+ Module['removeRunDependency']();
+ audio.removedDependency = true;
+ }
+ };
+ audio.onerror = function(event) {
+ if (!audio.removedDependency) {
+ console.log('Audio ' + url + ' could not be decoded or timed out trying to decode');
+ Module['removeRunDependency']();
+ 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"]['%(filename)s'] = new Audio(); // empty shim
+ Module['removeRunDependency']();
+ }
+ } else {
+ if (onload) onload();
+ }
+ }, onerror);
},
// Creates a link to a sepcific local path.
createLink: function(parent, name, target, canRead, canWrite) {
diff --git a/src/library_browser.js b/src/library_browser.js
index ce59dbdd..4d7a0aa5 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -27,6 +27,20 @@ mergeInto(LibraryManager.library, {
pointerLock: false,
moduleContextCreatedCallbacks: [],
+ ensureObjects: function() {
+ if (Browser.ensured) return;
+ Browser.ensured = true;
+ try {
+ new Blob();
+ Browser.hasBlobConstructor = true;
+ } catch(e) {
+ Browser.hasBlobConstructor = false;
+ console.log("warning: no blob constructor, cannot create blobs with mimetypes");
+ }
+ 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");
+ },
+
createContext: function(canvas, useWebGL, setInModule) {
#if !USE_TYPED_ARRAYS
if (useWebGL) {
@@ -172,38 +186,52 @@ mergeInto(LibraryManager.library, {
xhr.send(null);
},
- asyncLoad: function(url, callback) {
+ asyncLoad: function(url, onload, onerror) {
Browser.xhrLoad(url, function(arrayBuffer) {
assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
- callback(new Uint8Array(arrayBuffer));
+ onload(new Uint8Array(arrayBuffer));
removeRunDependency();
}, function(event) {
- throw 'Loading data file "' + url + '" failed.';
+ if (onerror) {
+ onerror();
+ } else {
+ throw 'Loading data file "' + url + '" failed.';
+ }
});
addRunDependency();
- }
+ },
+
+ 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(0, name.length-3)];
+ assert(ret);
+ return ret;
+ },
+
},
emscripten_async_wget: function(url, file, onload, onerror) {
- url = Pointer_stringify(url);
-
- Browser.xhrLoad(url, function(response) {
- var absolute = Pointer_stringify(file);
- var index = absolute.lastIndexOf('/');
- FS.createDataFile(
- absolute.substr(0, index),
- absolute.substr(index +1),
- new Uint8Array(response),
- true, true);
-
- if (onload) {
+ var _url = Pointer_stringify(url);
+ var _file = Pointer_stringify(file);
+ var index = _file.lastIndexOf('/');
+ FS.createPreloadedFile(
+ _file.substr(0, index),
+ _file.substr(index +1),
+ _url, true, true,
+ function() {
FUNCTION_TABLE[onload](file);
- }
- }, function(event) {
- if (onerror) {
+ },
+ function() {
FUNCTION_TABLE[onerror](file);
}
- });
+ );
},
emscripten_async_run_script__deps: ['emscripten_run_script'],
diff --git a/src/postamble.js b/src/postamble.js
index 10ac1888..2944e681 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -45,6 +45,7 @@ function run(args) {
function doRun() {
var ret = 0;
+ calledRun = true;
if (Module['_main']) {
preMain();
ret = Module.callMain(args);
diff --git a/src/preamble.js b/src/preamble.js
index 5c5e64fc..21b09985 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -793,6 +793,7 @@ var STRING_TABLE = [];
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
+var calledRun = false;
function addRunDependency() {
runDependencies++;
if (Module['monitorRunDependencies']) {
@@ -805,9 +806,12 @@ function removeRunDependency() {
if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
- if (runDependencies == 0) run();
+ if (runDependencies == 0 && !calledRun) run();
}
Module['removeRunDependency'] = removeRunDependency;
+Module["preloadedImages"] = {}; // maps url to image data
+Module["preloadedAudios"] = {}; // maps url to audio data
+
// === Body ===