aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js117
1 files changed, 108 insertions, 9 deletions
diff --git a/src/library.js b/src/library.js
index d1ede6bc..52102f63 100644
--- a/src/library.js
+++ b/src/library.js
@@ -33,6 +33,7 @@ LibraryManager.library = {
'Module["FS_createFolder"] = FS.createFolder;' +
'Module["FS_createPath"] = FS.createPath;' +
'Module["FS_createDataFile"] = FS.createDataFile;' +
+ 'Module["FS_createPreloadedFile"] = FS.createPreloadedFile;' +
'Module["FS_createLazyFile"] = FS.createLazyFile;' +
'Module["FS_createLink"] = FS.createLink;' +
'Module["FS_createDevice"] = FS.createDevice;',
@@ -51,6 +52,15 @@ LibraryManager.library = {
// This is set to false when the runtime is initialized, allowing you
// to modify the filesystem freely before run() is called.
ignorePermissions: true,
+ joinPath: function(parts, forceRelative) {
+ var ret = parts[0];
+ for (var i = 1; i < parts.length; i++) {
+ if (ret[ret.length-1] != '/') ret += '/';
+ ret += parts[i];
+ }
+ if (forceRelative && ret[0] == '/') ret = ret.substr(1);
+ return ret;
+ },
// Converts any path to an absolute path. Resolves embedded "." and ".."
// parts.
absolutePath: function(relative, base) {
@@ -273,10 +283,87 @@ 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.
+ // You can also call this with a typed array instead of a url. It will then
+ // do preloading for the Image/Audio part, as if the typed array were the
+ // result of an XHR that you did manually.
+ 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 {
+ if (onload) onload();
+ removeRunDependency('cp ' + fullname);
+ }
+ }
+ addRunDependency('cp ' + fullname);
+ if (typeof url == 'string') {
+ Browser.asyncLoad(url, function(byteArray) {
+ finish(byteArray);
+ }, onerror);
+ } else {
+ finish(url);
+ }
},
// Creates a link to a sepcific local path.
createLink: function(parent, name, target, canRead, canWrite) {
@@ -4199,10 +4286,22 @@ LibraryManager.library = {
},
strstr: function(ptr1, ptr2) {
- var str1 = Pointer_stringify(ptr1);
- var str2 = Pointer_stringify(ptr2);
- var ret = str1.search(str2);
- return ret >= 0 ? ptr1 + ret : 0;
+ var check = 0, start;
+ do {
+ if (!check) {
+ start = ptr1;
+ check = ptr2;
+ }
+ var curr1 = {{{ makeGetValue('ptr1++', 0, 'i8') }}};
+ var curr2 = {{{ makeGetValue('check++', 0, 'i8') }}};
+ if (curr2 == 0) return start;
+ if (curr2 != curr1) {
+ // rewind to one character after start, to find ez in eeez
+ ptr1 = start + 1;
+ check = 0;
+ }
+ } while (curr1);
+ return 0;
},
strchr: function(ptr, chr) {
@@ -4926,7 +5025,7 @@ LibraryManager.library = {
floor: 'Math.floor',
floorf: 'Math.floor',
pow: 'Math.pow',
- powf: 'Math.powf',
+ powf: 'Math.pow',
llvm_sqrt_f32: 'Math.sqrt',
llvm_sqrt_f64: 'Math.sqrt',
llvm_pow_f32: 'Math.pow',