aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_browser.js31
-rw-r--r--src/library_sdl.js118
-rwxr-xr-xtests/runner.py4
-rw-r--r--tests/sdl_audio.c29
4 files changed, 146 insertions, 36 deletions
diff --git a/src/library_browser.js b/src/library_browser.js
index 7f79b2bd..0db2cc44 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -70,18 +70,6 @@ mergeInto(LibraryManager.library, {
// (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.).
- function getMimetype(name) {
- return {
- 'jpg': 'image/jpeg',
- 'jpeg': 'image/jpeg',
- 'png': 'image/png',
- 'bmp': 'image/bmp',
- 'ogg': 'audio/ogg',
- 'wav': 'audio/wav',
- 'mp3': 'audio/mpeg'
- }[name.substr(name.lastIndexOf('.')+1)];
- }
-
var imagePlugin = {};
imagePlugin['canHandle'] = function(name) {
return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
@@ -90,10 +78,10 @@ mergeInto(LibraryManager.library, {
var b = null;
if (Browser.hasBlobConstructor) {
try {
- b = new Blob([byteArray], { type: getMimetype(name) });
+ b = new Blob([byteArray], { type: Browser.getMimetype(name) });
if (b.size !== byteArray.length) { // Safari bug #118630
// Safari's Blob can only take an ArrayBuffer
- b = new Blob([(new Uint8Array(byteArray)).buffer], { type: getMimetype(name) });
+ b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
}
} catch(e) {
Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
@@ -148,7 +136,7 @@ mergeInto(LibraryManager.library, {
}
if (Browser.hasBlobConstructor) {
try {
- var b = new Blob([byteArray], { type: getMimetype(name) });
+ var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
} catch(e) {
return fail();
}
@@ -391,6 +379,18 @@ mergeInto(LibraryManager.library, {
}, timeout);
},
+ getMimetype: function(name) {
+ return {
+ 'jpg': 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'png': 'image/png',
+ 'bmp': 'image/bmp',
+ 'ogg': 'audio/ogg',
+ 'wav': 'audio/wav',
+ 'mp3': 'audio/mpeg'
+ }[name.substr(name.lastIndexOf('.')+1)];
+ },
+
getUserMedia: function(func) {
if(!window.getUserMedia) {
window.getUserMedia = navigator['getUserMedia'] ||
@@ -399,6 +399,7 @@ mergeInto(LibraryManager.library, {
window.getUserMedia(func);
},
+
getMovementX: function(event) {
return event['movementX'] ||
event['mozMovementX'] ||
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 9287bd3e..7078aa9d 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -28,6 +28,7 @@ var LibrarySDL = {
// The currently preloaded audio elements ready to be played
audios: [null],
+ rwops: [null],
// The currently playing audio element. There's only one music track.
music: {
audio: null,
@@ -1228,9 +1229,24 @@ var LibrarySDL = {
return flags; // We support JPG, PNG, TIF because browsers do
},
- IMG_Load__deps: ['SDL_LockSurface'],
- IMG_Load: function(filename) {
- filename = FS.standardizePath(Pointer_stringify(filename));
+ IMG_Load_RW__deps: ['SDL_LockSurface'],
+ IMG_Load_RW: function(rwopsID, freesrc) {
+ var rwops = SDL.rwops[rwopsID];
+
+ if (rwops === undefined) {
+ return 0;
+ }
+
+ var filename = rwops.filename;
+
+ if (filename === undefined) {
+ Runtime.warnOnce('Only file names that have been preloaded are supported for IMG_Load_RW.');
+ // TODO. Support loading image data from embedded files, similarly to Mix_LoadWAV_RW
+ // TODO. Support loading image data from byte arrays, similarly to Mix_LoadWAV_RW
+ return 0;
+ }
+
+ filename = FS.standardizePath(filename);
if (filename[0] == '/') {
// Convert the path to relative
filename = filename.substr(1);
@@ -1262,8 +1278,14 @@ var LibrarySDL = {
return surf;
},
SDL_LoadBMP: 'IMG_Load',
- SDL_LoadBMP_RW: 'IMG_Load',
- IMG_Load_RW: 'IMG_Load',
+ SDL_LoadBMP_RW: 'IMG_Load_RW',
+ IMG_Load__deps: ['IMG_Load_RW', 'SDL_RWFromFile', 'SDL_FreeRW'],
+ IMG_Load: function(filename){
+ var rwops = _SDL_RWFromFile(filename);
+ var result = _IMG_Load_RW(rwops);
+ _SDL_FreeRW(rwops);
+ return result;
+ },
// SDL_Audio
@@ -1399,22 +1421,62 @@ var LibrarySDL = {
return 0; // error
},
- Mix_LoadWAV_RW: function(filename, freesrc) {
- filename = FS.standardizePath(Pointer_stringify(filename));
- var raw = Module["preloadedAudios"][filename];
- if (!raw) {
- if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!');
- Runtime.warnOnce('Cannot find preloaded audio ' + filename);
+ Mix_LoadWAV_RW: function(rwopsID, freesrc) {
+ var rwops = SDL.rwops[rwopsID];
+
+ if (rwops === undefined)
+ return 0;
+
+ var filename = '';
+ var audio;
+ var bytes;
+
+ if (rwops.filename !== undefined) {
+ filename = rwops.filename;
+ filename = FS.standardizePath(filename);
+ var raw = Module["preloadedAudios"][filename];
+ if (!raw) {
+ if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!');
+ Runtime.warnOnce('Cannot find preloaded audio ' + filename);
+
+ // see if we can read the file-contents from the in-memory FS
+ var fileObject = FS.findObject(filename);
+
+ if (fileObject === null) Module.printErr('Couldn\'t find file for: ' + filename);
+
+ // We found the file. Load the contents
+ if (fileObject && !fileObject.isFolder && fileObject.read) {
+ bytes = fileObject.contents
+ } else {
+ return 0;
+ }
+ }
+ if (Module['freePreloadedMediaOnUse']) {
+ Module["preloadedAudios"][filename] = null;
+ }
+ audio = raw;
+ }
+ else if (rwops.bytes !== undefined) {
+ bytes = HEAPU8.subarray(rwops.bytes, rwops.bytes + rwops.count);
+ }
+ else {
return 0;
}
- if (Module['freePreloadedMediaOnUse']) {
- Module["preloadedAudios"][filename] = null;
+
+ // Here, we didn't find a preloaded audio but we either were passed a filepath for
+ // which we loaded bytes, or we were passed some bytes
+ if (audio === undefined && bytes) {
+ var blob = new Blob([new Uint8Array(bytes)], {type: rwops.mimetype});
+ var url = URL.createObjectURL(blob);
+ audio = new Audio();
+ audio.src = url;
}
+
var id = SDL.audios.length;
// Keep the loaded audio in the audio arrays, ready for playback
SDL.audios.push({
source: filename,
- audio: raw
+ audio: audio
});
return id;
},
@@ -1574,8 +1636,14 @@ var LibrarySDL = {
return SDL.setGetVolume(SDL.music, volume);
},
- Mix_LoadMUS: 'Mix_LoadWAV_RW',
Mix_LoadMUS_RW: 'Mix_LoadWAV_RW',
+ Mix_LoadMUS__deps: ['Mix_LoadMUS_RW', 'SDL_RWFromFile', 'SDL_FreeRW'],
+ Mix_LoadMUS: function(filename) {
+ var rwops = _SDL_RWFromFile(filename);
+ var result = _Mix_LoadMUS_RW(rwops);
+ _SDL_FreeRW(rwops);
+ return result;
+ },
Mix_FreeMusic: 'Mix_FreeChunk',
@@ -1978,9 +2046,24 @@ var LibrarySDL = {
// Misc
SDL_InitSubSystem: function(flags) { return 0 },
+ SDL_RWFromConstMem: function(mem, size) {
+ var id = SDL.rwops.length; // TODO: recycle ids when they are null
+ SDL.rwops.push({ bytes: mem, count: size });
+ return id;
+ },
- SDL_RWFromFile: function(filename, mode) {
- return filename; // XXX We just forward the filename
+ SDL_RWFromFile: function(_name, mode) {
+ var id = SDL.rwops.length; // TODO: recycle ids when they are null
+ var name = Pointer_stringify(_name)
+ SDL.rwops.push({ filename: name, mimetype: Browser.getMimetype(name) });
+ return id;
+ },
+
+ SDL_FreeRW: function(rwopsID) {
+ SDL.rwops[rwopsID] = null;
+ while (SDL.rwops.length > 0 && SDL.rwops[SDL.rwops.length-1] === null) {
+ SDL.rwops.pop();
+ }
},
SDL_EnableUNICODE: function(on) {
@@ -2007,7 +2090,6 @@ var LibrarySDL = {
SDL_GetThreadID: function() { throw 'SDL_GetThreadID' },
SDL_ThreadID: function() { throw 'SDL_ThreadID' },
SDL_AllocRW: function() { throw 'SDL_AllocRW: TODO' },
- SDL_FreeRW: function() { throw 'SDL_FreeRW: TODO' },
SDL_CondBroadcast: function() { throw 'SDL_CondBroadcast: TODO' },
SDL_CondWaitTimeout: function() { throw 'SDL_CondWaitTimeout: TODO' },
SDL_WM_IconifyWindow: function() { throw 'SDL_WM_IconifyWindow TODO' },
diff --git a/tests/runner.py b/tests/runner.py
index e16fc12e..4a9bf623 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -12998,11 +12998,13 @@ Press any key to continue.'''
def test_sdl_audio(self):
shutil.copyfile(path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg'))
shutil.copyfile(path_from_root('tests', 'sounds', 'alarmcreatemiltaryfoot_1.wav'), os.path.join(self.get_dir(), 'sound2.wav'))
+ shutil.copyfile(path_from_root('tests', 'sounds', 'noise.ogg'), os.path.join(self.get_dir(), 'noise.ogg'))
+ shutil.copyfile(path_from_root('tests', 'sounds', 'the_entertainer.ogg'), os.path.join(self.get_dir(), 'the_entertainer.ogg'))
open(os.path.join(self.get_dir(), 'bad.ogg'), 'w').write('I claim to be audio, but am lying')
open(os.path.join(self.get_dir(), 'sdl_audio.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio.c')).read()))
# use closure to check for a possible bug with closure minifying away newer Audio() attributes
- Popen([PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '--preload-file', 'bad.ogg', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]']).communicate()
+ Popen([PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '--embed-file', 'the_entertainer.ogg', '--preload-file', 'noise.ogg', '--preload-file', 'bad.ogg', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]']).communicate()
self.run_browser('page.html', '', '/report_result?1')
def test_sdl_audio_mix_channels(self):
diff --git a/tests/sdl_audio.c b/tests/sdl_audio.c
index ae1b89e9..7373d220 100644
--- a/tests/sdl_audio.c
+++ b/tests/sdl_audio.c
@@ -1,11 +1,13 @@
#include <stdio.h>
+#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <assert.h>
#include <emscripten.h>
+#include <sys/stat.h>
-Mix_Chunk *sound, *sound2;
-
+Mix_Chunk *sound, *sound2, *sound3;
+Mix_Music * music;
int play2();
int play() {
@@ -28,6 +30,9 @@ int play2() {
int channel2 = Mix_PlayChannel(-1, sound2, 0);
assert(channel2 == 1);
+ int channel3 = Mix_PlayChannel(-1, sound3, 0);
+ assert(channel3 == 2);
+ assert(Mix_PlayMusic(music, 1) == 0);
return channel2;
}
@@ -39,6 +44,26 @@ int main(int argc, char **argv) {
sound = Mix_LoadWAV("sound.ogg");
assert(sound);
+
+ {
+ struct stat info;
+ int result = stat("noise.ogg", &info);
+ char * bytes = malloc( info.st_size );
+ FILE * f = fopen( "noise.ogg", "rb" );
+ fread( bytes, 1, info.st_size, f );
+ fclose(f);
+
+ SDL_RWops * ops = SDL_RWFromConstMem(bytes, info.st_size);
+ sound3 = Mix_LoadWAV_RW(ops, 0);
+ SDL_FreeRW(ops);
+ free(bytes);
+ }
+
+ {
+ music = Mix_LoadMUS("the_entertainer.ogg");
+ }
+
+
sound2 = Mix_LoadWAV("sound2.wav");
assert(sound);