diff options
Diffstat (limited to 'src/library.js')
-rw-r--r-- | src/library.js | 117 |
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', |