aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rwxr-xr-xemcc30
-rw-r--r--emlink.py15
-rw-r--r--src/library.js67
-rw-r--r--src/library_jansson.js2
-rw-r--r--src/library_openal.js596
-rw-r--r--src/library_sdl.js168
-rw-r--r--src/postamble.js94
-rw-r--r--src/preamble.js73
-rw-r--r--src/settings.js1655
-rw-r--r--system/include/bsd/sys/mman.h2
-rw-r--r--system/include/libc/math.h8
-rw-r--r--tests/cases/i24_mem_ta2.ll (renamed from tests/cases/i32_mem.ll)0
-rw-r--r--tests/cases/i24_mem_ta2.txt (renamed from tests/cases/i32_mem.txt)0
-rw-r--r--tests/openal_buffers.c187
-rwxr-xr-xtests/runner.py225
-rw-r--r--tests/sdl_stb_image.c49
-rw-r--r--tests/sdl_stb_image_data.c55
-rw-r--r--tests/sounds/the_entertainer.wavbin0 -> 264644 bytes
-rw-r--r--third_party/stb_image.c4673
-rw-r--r--tools/file_packager.py11
-rw-r--r--tools/shared.py8
22 files changed, 6778 insertions, 1141 deletions
diff --git a/AUTHORS b/AUTHORS
index 6e28d590..d3cdd156 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -90,5 +90,6 @@ a license to everyone to use it as detailed in LICENSE.)
* Soeren Balko <soeren.balko@gmail.com>
* Ryan Kelly (ryan@rfk.id.au)
* Michael Lelli <toadking@toadking.com>
+* Yu Kobayashi <yukoba@accelart.jp>
* Pin Zhang <zhangpin04@gmail.com>
diff --git a/emcc b/emcc
index 91b109b6..e92dac87 100755
--- a/emcc
+++ b/emcc
@@ -53,6 +53,15 @@ from tools import shared, jsrun
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
from tools.response_file import read_response_file
+CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
+SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
+BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
+DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
+STATICLIB_SUFFIXES = ('.a',)
+ASSEMBLY_SUFFIXES = ('.ll',)
+LIB_PREFIXES = ('', 'lib')
+JS_CONTAINING_SUFFIXES = ('js', 'html')
+
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
# llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing
@@ -532,7 +541,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
if debug_configure: open(tempout, 'a').write('============= ' + arg + '\n' + src + '\n=============\n\n')
except:
pass
- if arg.endswith('.s'):
+ elif arg.endswith('.s'):
if debug_configure: open(tempout, 'a').write('(compiling .s assembly, must use clang\n')
use_js = 0
@@ -615,15 +624,6 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS)
# ---------------- Utilities ---------------
-SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
-BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
-DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
-STATICLIB_SUFFIXES = ('.a',)
-ASSEMBLY_SUFFIXES = ('.ll',)
-LIB_PREFIXES = ('', 'lib')
-
-JS_CONTAINING_SUFFIXES = ('js', 'html')
-
seen_names = {}
def uniquename(name):
if name not in seen_names:
@@ -1030,6 +1030,10 @@ try:
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
+ if bind and shared.Settings.ASM_JS:
+ logging.warning('disabling asm.js since embind is not ready for it yet')
+ shared.Settings.ASM_JS = 0
+
if shared.Settings.ASM_JS:
assert opt_level >= 1, 'asm.js requires -O1 or above'
@@ -1083,6 +1087,10 @@ try:
if shared.Settings.DLOPEN_SUPPORT:
shared.Settings.LINKABLE = 1
+ if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES:
+ input_files.append(shared.path_from_root('third_party', 'stb_image.c'))
+ shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free']
+
## Compile source code to bitcode
logging.debug('compiling to bitcode')
@@ -1097,6 +1105,8 @@ try:
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
+ if input_file.endswith(CXX_SUFFIXES):
+ args += shared.EMSDK_CXX_OPTS
logging.debug("running:" + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
diff --git a/emlink.py b/emlink.py
index d59cb5d3..387b7de8 100644
--- a/emlink.py
+++ b/emlink.py
@@ -56,7 +56,7 @@ class AsmModule():
self.imports = {}
for imp in js_optimizer.import_sig.finditer(self.imports_js):
key, value = imp.group(0).split('var ')[1][:-1].split('=', 1)
- self.imports[key] = value
+ self.imports[key.strip()] = value.strip()
#print >> sys.stderr, 'imports', self.imports
# funcs
@@ -124,19 +124,20 @@ class AsmModule():
del all_sendings[key] # import of external value no longer needed
main.imports_js = '\n'.join(['var %s = %s;' % (key, value) for key, value in all_imports.iteritems()]) + '\n'
- if added_sending:
- sendings_js = ', '.join(['%s: %s' % (key, value) for key, value in all_sendings.iteritems()])
- sendings_start = main.post_js.find('}, { ')+5
- sendings_end = main.post_js.find(' }, buffer);')
- main.post_js = main.post_js[:sendings_start] + sendings_js + main.post_js[sendings_end:]
-
# check for undefined references to global variables
def check_import(key, value):
if value.startswith('+') or value.endswith('|0'): # ignore functions
if key not in all_sendings:
print >> sys.stderr, 'warning: external variable %s is still not defined after linking' % key
+ all_sendings[key] = '0'
for key, value in all_imports.iteritems(): check_import(key, value)
+ if added_sending:
+ sendings_js = ', '.join(['%s: %s' % (key, value) for key, value in all_sendings.iteritems()])
+ sendings_start = main.post_js.find('}, { ')+5
+ sendings_end = main.post_js.find(' }, buffer);')
+ main.post_js = main.post_js[:sendings_start] + sendings_js + main.post_js[sendings_end:]
+
# tables
f_bases = {}
f_sizes = {}
diff --git a/src/library.js b/src/library.js
index 28886671..8342decf 100644
--- a/src/library.js
+++ b/src/library.js
@@ -1165,7 +1165,7 @@ LibraryManager.library = {
['i32', 'f_namemax']]),
statvfs__deps: ['$FS', '__statvfs_struct_layout'],
statvfs: function(path, buf) {
- // http://pubs.opengroup.org/onlinepubs/7908799/xsh/stat.html
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/statvfs.html
// int statvfs(const char *restrict path, struct statvfs *restrict buf);
var offsets = ___statvfs_struct_layout;
// NOTE: None of the constants here are true. We're just returning safe and
@@ -2133,20 +2133,7 @@ LibraryManager.library = {
_exit: function(status) {
// void _exit(int status);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
-
- function ExitStatus() {
- this.name = "ExitStatus";
- this.message = "Program terminated with exit(" + status + ")";
- this.status = status;
- Module.print('Exit Status: ' + status);
- };
- ExitStatus.prototype = new Error();
- ExitStatus.prototype.constructor = ExitStatus;
-
- exitRuntime();
- ABORT = true;
-
- throw new ExitStatus();
+ Module['exit'](status);
},
fork__deps: ['__setErrNo', '$ERRNO_CODES'],
fork: function() {
@@ -3653,29 +3640,19 @@ LibraryManager.library = {
___setErrNo(ERRNO_CODES.EAGAIN);
return -1;
},
- fscanf__deps: ['$FS', '__setErrNo', '$ERRNO_CODES',
- '_scanString', 'fgetc', 'fseek', 'ftell'],
+ fscanf__deps: ['$FS', '_scanString', 'fgetc', 'ungetc'],
fscanf: function(stream, format, varargs) {
// int fscanf(FILE *restrict stream, const char *restrict format, ... );
// http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
if (FS.streams[stream]) {
- var i = _ftell(stream), SEEK_SET = 0;
- // if the stream does not support seeking backwards (e.g. stdin), buffer it here
- var buffer = [], bufferIndex = 0;
+ var buffer = [];
var get = function() {
- if (bufferIndex < buffer.length) {
- return buffer[bufferIndex++];
- }
- i++;
- bufferIndex++;
var c = _fgetc(stream);
buffer.push(c);
return c;
};
var unget = function() {
- if (_fseek(stream, --i, SEEK_SET) !== 0) {
- bufferIndex--;
- }
+ _ungetc(buffer.pop(), stream);
};
return __scanString(format, get, unget, varargs);
} else {
@@ -3939,8 +3916,7 @@ LibraryManager.library = {
__cxa_atexit: 'atexit',
abort: function() {
- ABORT = true;
- throw 'abort() at ' + (new Error().stack);
+ Module['abort']();
},
bsearch: function(key, base, num, size, compar) {
@@ -4463,6 +4439,13 @@ LibraryManager.library = {
llvm_memmove_p0i8_p0i8_i32: 'memmove',
llvm_memmove_p0i8_p0i8_i64: 'memmove',
+ bcopy__deps: ['memmove'],
+ bcopy: function(src, dest, num) {
+ // void bcopy(const void *s1, void *s2, size_t n);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/bcopy.html
+ _memmove(dest, src, num);
+ },
+
memset__inline: function(ptr, value, num, align) {
return makeSetValues(ptr, 0, value, 'null', num, align);
},
@@ -4951,7 +4934,17 @@ LibraryManager.library = {
(chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}});
},
isspace: function(chr) {
- return chr in { 32: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0 };
+ switch(chr) {
+ case 32:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ return true;
+ default:
+ return false;
+ };
},
isblank: function(chr) {
return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}};
@@ -6165,9 +6158,14 @@ LibraryManager.library = {
{{{ makeSetValue('tmPtr', 'offsets.tm_wday', 'date.getUTCDay()', 'i32') }}}
{{{ makeSetValue('tmPtr', 'offsets.tm_gmtoff', '0', 'i32') }}}
{{{ makeSetValue('tmPtr', 'offsets.tm_isdst', '0', 'i32') }}}
-
- var start = new Date(date.getFullYear(), 0, 1);
- var yday = Math.round((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
+ var start = new Date(date); // define date using UTC, start from Jan 01 00:00:00 UTC
+ start.setUTCDate(1);
+ start.setUTCMonth(0);
+ start.setUTCHours(0);
+ start.setUTCMinutes(0);
+ start.setUTCSeconds(0);
+ start.setUTCMilliseconds(0);
+ var yday = Math.floor((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
{{{ makeSetValue('tmPtr', 'offsets.tm_yday', 'yday', 'i32') }}}
var timezone = "GMT";
@@ -6178,7 +6176,6 @@ LibraryManager.library = {
return tmPtr;
},
-
timegm__deps: ['mktime'],
timegm: function(tmPtr) {
_tzset();
diff --git a/src/library_jansson.js b/src/library_jansson.js
index 93f239fc..da8c5aa8 100644
--- a/src/library_jansson.js
+++ b/src/library_jansson.js
@@ -79,7 +79,7 @@ var LibraryJansson = {
load: function(string, flags, error) {
// This is potentially a security problem.
// TODO: Make sure everything is properly escaped
- var json_obj = eval('(' + string + ')');
+ var json_obj = JSON.parse(string);
if (json_obj != null) {
// The context is an array storing all child nodes.
diff --git a/src/library_openal.js b/src/library_openal.js
index 6a97fce7..d2516559 100644
--- a/src/library_openal.js
+++ b/src/library_openal.js
@@ -5,6 +5,8 @@ var LibraryOpenAL = {
$AL: {
contexts: [],
currentContext: null,
+ QUEUE_INTERVAL: 25,
+ QUEUE_LOOKAHEAD: 100
},
alcProcessContext: function(context) {},
@@ -39,6 +41,7 @@ var LibraryOpenAL = {
alcDestroyContext: function(context) {
// Stop playback, etc
+ clearInterval(context.interval);
},
alcCloseDevice: function(device) {
@@ -54,6 +57,7 @@ var LibraryOpenAL = {
}
},
+ alcCreateContext__deps: ['updateSources'],
alcCreateContext: function(device, attrList) {
if (device != 1) {
return 0;
@@ -76,18 +80,152 @@ var LibraryOpenAL = {
}
if (ctx) {
- AL.contexts.push({ctx: ctx, err: 0, src: [], buf: []});
+ var context = {
+ ctx: ctx,
+ err: 0,
+ src: [],
+ buf: [],
+ interval: setInterval(function () { _updateSources(context); }, AL.QUEUE_INTERVAL)
+ };
+ AL.contexts.push(context);
return AL.contexts.length;
} else {
return 0;
}
},
+ updateSources__deps: ['updateSource'],
+ updateSources: function (context) {
+ for (var i = 0; i < context.src.length; i++) {
+ _updateSource(context.src[i]);
+ }
+ },
+
+ updateSource__deps: ['setSourceState'],
+ updateSource: function (src) {
+#if OPENAL_DEBUG
+ var idx = AL.currentContext.src.indexOf(src);
+#endif
+ if (src.state !== 0x1012 /* AL_PLAYING */) {
+ return;
+ }
+
+ var currentTime = AL.currentContext.ctx.currentTime;
+ var startTime = src.bufferPosition;
+
+ for (var i = src.buffersPlayed; i < src.queue.length; i++) {
+ var entry = src.queue[i];
+
+ var startOffset = startTime - currentTime;
+ var endTime = startTime + entry.buffer.duration;
+
+ // Clean up old buffers.
+ if (currentTime >= endTime) {
+ // Update our location in the queue.
+ src.bufferPosition = endTime;
+ src.buffersPlayed = i + 1;
+
+ // Stop / restart the source when we hit the end.
+ if (src.buffersPlayed >= src.queue.length) {
+ if (src.loop) {
+ _setSourceState(src, 0x1012 /* AL_PLAYING */);
+ } else {
+ _setSourceState(src, 0x1014 /* AL_STOPPED */);
+ }
+ }
+ }
+ // Process all buffers that'll be played before the next tick.
+ else if (startOffset < (AL.QUEUE_LOOKAHEAD / 1000) && !entry.src) {
+ // If the start offset is negative, we need to offset the actual buffer.
+ var offset = Math.abs(Math.min(startOffset, 0));
+
+ entry.src = AL.currentContext.ctx.createBufferSource();
+ entry.src.buffer = entry.buffer;
+ entry.src.connect(src.gain);
+ entry.src.start(startTime, offset);
+
+#if OPENAL_DEBUG
+ console.log('updateSource queuing buffer ' + i + ' for source ' + idx + ' at ' + startTime + ' (offset by ' + offset + ')');
+#endif
+ }
+
+ startTime = endTime;
+ }
+ },
+
+ setSourceState__deps: ['updateSource', 'stopSourceQueue'],
+ setSourceState: function (src, state) {
+#if OPENAL_DEBUG
+ var idx = AL.currentContext.src.indexOf(src);
+#endif
+ if (state === 0x1012 /* AL_PLAYING */) {
+ if (src.state !== 0x1013 /* AL_PAUSED */) {
+ src.state = 0x1012 /* AL_PLAYING */;
+ // Reset our position.
+ src.bufferPosition = AL.currentContext.ctx.currentTime;
+ src.buffersPlayed = 0;
+#if OPENAL_DEBUG
+ console.log('setSourceState resetting and playing source ' + idx);
+#endif
+ } else {
+ src.state = 0x1012 /* AL_PLAYING */;
+ // Use the current offset from src.bufferPosition to resume at the correct point.
+ src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition;
+#if OPENAL_DEBUG
+ console.log('setSourceState resuming source ' + idx + ' at ' + src.bufferPosition.toFixed(4));
+#endif
+ }
+ _stopSourceQueue(src);
+ _updateSource(src);
+ } else if (state === 0x1013 /* AL_PAUSED */) {
+ if (src.state === 0x1012 /* AL_PLAYING */) {
+ src.state = 0x1013 /* AL_PAUSED */;
+ // Store off the current offset to restore with on resume.
+ src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition;
+ _stopSourceQueue(src);
+#if OPENAL_DEBUG
+ console.log('setSourceState pausing source ' + idx + ' at ' + src.bufferPosition.toFixed(4));
+#endif
+ }
+ } else if (state === 0x1014 /* AL_STOPPED */) {
+ if (src.state !== 0x1011 /* AL_INITIAL */) {
+ src.state = 0x1014 /* AL_STOPPED */;
+ src.buffersPlayed = src.queue.length;
+ _stopSourceQueue(src);
+#if OPENAL_DEBUG
+ console.log('setSourceState stopping source ' + idx);
+#endif
+ }
+ } else if (state == 0x1011 /* AL_INITIAL */) {
+ if (src.state !== 0x1011 /* AL_INITIAL */) {
+ src.state = 0x1011 /* AL_INITIAL */;
+ src.bufferPosition = 0;
+ src.buffersPlayed = 0;
+#if OPENAL_DEBUG
+ console.log('setSourceState initializing source ' + idx);
+#endif
+ }
+ }
+ },
+
+ stopSourceQueue: function (src) {
+ for (var i = 0; i < src.queue.length; i++) {
+ var entry = src.queue[i];
+ if (entry.src) {
+ entry.src.stop(0);
+ entry.src = null;
+ }
+ }
+ },
+
alGetError: function() {
if (!AL.currentContext) {
return 0xA004 /* AL_INVALID_OPERATION */;
} else {
- return AL.currentContext.err;
+ // Reset error on get.
+ var err = AL.currentContext.err;
+ AL.currentContext.err = 0 /* AL_NO_ERROR */;
+ return err;
}
},
@@ -97,12 +235,12 @@ var LibraryOpenAL = {
return _alGetError();
},
- alDeleteSources: function(count, sources)
- {
+ alDeleteSources: function(count, sources) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
console.error("alDeleteSources called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
for (var i = 0; i < count; ++i) {
@@ -116,57 +254,126 @@ var LibraryOpenAL = {
#if OPENAL_DEBUG
console.error("alGenSources called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
for (var i = 0; i < count; ++i) {
var gain = AL.currentContext.ctx.createGain();
- var panner = AL.currentContext.ctx.createPanner();
- panner.panningModel = "equalpower";
- panner.distanceModel = "linear";
- panner.rolloffFactor = 0.3;
- gain.connect(panner);
- panner.connect(AL.currentContext.ctx.destination);
+ gain.connect(AL.currentContext.ctx.destination);
AL.currentContext.src.push({
+ state: 0x1011 /* AL_INITIAL */,
+ queue: [],
loop: false,
- buffer: null,
+ get refDistance() {
+ return this._refDistance || 1;
+ },
+ set refDistance(val) {
+ this._refDistance = val;
+ if (this.panner) this.panner.refDistance = val;
+ },
+ get maxDistance() {
+ return this._maxDistance || 10000;
+ },
+ set maxDistance(val) {
+ this._maxDistance = val;
+ if (this.panner) this.panner.maxDistance = val;
+ },
+ get rolloffFactor() {
+ return this._rolloffFactor || 1;
+ },
+ set rolloffFactor(val) {
+ this._rolloffFactor = val;
+ if (this.panner) this.panner.rolloffFactor = val;
+ },
+ get position() {
+ return this._position || [0, 0, 0];
+ },
+ set position(val) {
+ this._position = val;
+ if (this.panner) this.panner.setPosition(val[0], val[1], val[2]);
+ },
+ get velocity() {
+ return this._velocity || [0, 0, 0];
+ },
+ set velocity(val) {
+ this._velocity = val;
+ if (this.panner) this.panner.setVelocity(val[0], val[1], val[2]);
+ },
gain: gain,
- panner: panner,
- paused: false,
- playTime: -1,
- pausedTime: 0
+ panner: null,
+ buffersPlayed: 0,
+ bufferPosition: 0
});
{{{ makeSetValue('sources', 'i*4', 'AL.currentContext.src.length', 'i32') }}};
}
},
+ alSourcei__deps: ['updateSource'],
alSourcei: function(source, param, value) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
console.error("alSourcei called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
- if (source > AL.currentContext.src.length) {
+ var src = AL.currentContext.src[source - 1];
+ if (!src) {
#if OPENAL_DEBUG
console.error("alSourcei called with an invalid source");
#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
switch (param) {
case 0x1007 /* AL_LOOPING */:
- AL.currentContext.src[source - 1].loop = (value != 0 /* AL_FALSE */);
+ src.loop = (value === 1 /* AL_TRUE */);
break;
case 0x1009 /* AL_BUFFER */:
+ var buffer = AL.currentContext.buf[value - 1];
if (value == 0) {
- AL.currentContext.src[source - 1].buffer = null;
+ src.queue = [];
+ } else {
+ src.queue = [{ buffer: buffer }];
+ }
+ _updateSource(src);
+ break;
+ case 0x202 /* AL_SOURCE_RELATIVE */:
+ if (value === 1 /* AL_TRUE */) {
+ if (src.panner) {
+ src.panner = null;
+
+ // Disconnect from the panner.
+ src.gain.disconnect();
+
+ src.gain.connect(AL.currentContext.ctx.destination);
+ }
+ } else if (value === 0 /* AL_FALSE */) {
+ if (!src.panner) {
+ var panner = src.panner = AL.currentContext.ctx.createPanner();
+ panner.panningModel = "equalpower";
+ panner.distanceModel = "linear";
+ panner.refDistance = src.refDistance;
+ panner.maxDistance = src.maxDistance;
+ panner.rolloffFactor = src.rolloffFactor;
+ panner.setPosition(src.position[0], src.position[1], src.position[2]);
+ panner.setVelocity(src.velocity[0], src.velocity[1], src.velocity[2]);
+ panner.connect(AL.currentContext.ctx.destination);
+
+ // Disconnect from the default source.
+ src.gain.disconnect();
+
+ src.gain.connect(panner);
+ }
} else {
- AL.currentContext.src[source - 1].buffer = AL.currentContext.buf[value - 1].buf;
+ AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */;
}
break;
default:
#if OPENAL_DEBUG
console.log("alSourcei with param " + param + " not implemented yet");
#endif
+ AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */;
break;
}
},
@@ -176,130 +383,168 @@ var LibraryOpenAL = {
#if OPENAL_DEBUG
console.error("alSourcef called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
- if (source > AL.currentContext.src.length) {
+ var src = AL.currentContext.src[source - 1];
+ if (!src) {
#if OPENAL_DEBUG
console.error("alSourcef called with an invalid source");
#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
switch (param) {
- case 0x100A /* AL_GAIN */:
- if (AL.currentContext.src[source - 1]) {
- AL.currentContext.src[source - 1].gain.gain.value = value;
- }
- break;
case 0x1003 /* AL_PITCH */:
#if OPENAL_DEBUG
- console.log("alSourcef was called with AL_PITCH, but Web Audio does not support static pitch changes");
+ console.log("alSourcef was called with 0x1003 /* AL_PITCH */, but Web Audio does not support static pitch changes");
#endif
break;
+ case 0x100A /* AL_GAIN */:
+ src.gain.gain.value = value;
+ break;
+ // case 0x100D /* AL_MIN_GAIN */:
+ // break;
+ // case 0x100E /* AL_MAX_GAIN */:
+ // break;
+ case 0x1023 /* AL_MAX_DISTANCE */:
+ src.maxDistance = value;
+ break;
+ case 0x1021 /* AL_ROLLOFF_FACTOR */:
+ src.rolloffFactor = value;
+ break;
+ // case 0x1022 /* AL_CONE_OUTER_GAIN */:
+ // break;
+ // case 0x1001 /* AL_CONE_INNER_ANGLE */:
+ // break;
+ // case 0x1002 /* AL_CONE_OUTER_ANGLE */:
+ // break;
+ case 0x1020 /* AL_REFERENCE_DISTANCE */:
+ src.refDistance = value;
+ break;
default:
#if OPENAL_DEBUG
console.log("alSourcef with param " + param + " not implemented yet");
#endif
+ AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */;
break;
}
},
- alSourcefv: function(source, param, value) {
+ alSource3f: function(source, param, v1, v2, v3) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
- console.error("alSourcefv called without a valid context");
+ console.error("alSource3f called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
- if (source > AL.currentContext.src.length) {
+ var src = AL.currentContext.src[source - 1];
+ if (!src) {
#if OPENAL_DEBUG
- console.error("alSourcefv called with an invalid source");
+ console.error("alSource3f called with an invalid source");
#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
switch (param) {
case 0x1004 /* AL_POSITION */:
- AL.currentContext.src[source - 1].panner.setPosition(
- {{{ makeGetValue('value', '0', 'float') }}},
- {{{ makeGetValue('value', '4', 'float') }}},
- {{{ makeGetValue('value', '8', 'float') }}}
- );
+ src.position = [v1, v2, v3];
break;
case 0x1006 /* AL_VELOCITY */:
- AL.currentContext.src[source - 1].panner.setVelocity(
- {{{ makeGetValue('value', '0', 'float') }}},
- {{{ makeGetValue('value', '4', 'float') }}},
- {{{ makeGetValue('value', '8', 'float') }}}
- );
+ src.velocity = [v1, v2, v3];
break;
default:
#if OPENAL_DEBUG
- console.log("alSourcefv with param " + param + " not implemented yet");
+ console.log("alSource3f with param " + param + " not implemented yet");
#endif
+ AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */;
break;
}
},
+ alSourcefv__deps: ['alSource3f'],
+ alSourcefv: function(source, param, value) {
+ _alSource3f(source, param,
+ {{{ makeGetValue('value', '0', 'float') }}},
+ {{{ makeGetValue('value', '4', 'float') }}},
+ {{{ makeGetValue('value', '8', 'float') }}});
+ },
+
+ alSourceQueueBuffers__deps: ["updateSource"],
alSourceQueueBuffers: function(source, count, buffers) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
console.error("alSourceQueueBuffers called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
- if (source > AL.currentContext.src.length) {
+ var src = AL.currentContext.src[source - 1];
+ if (!src) {
#if OPENAL_DEBUG
console.error("alSourceQueueBuffers called with an invalid source");
#endif
- return;
- }
- if (count != 1) {
-#if OPENAL_DEBUG
- console.error("Queuing multiple buffers using alSourceQueueBuffers is not supported yet");
-#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
for (var i = 0; i < count; ++i) {
- var buffer = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
- if (buffer > AL.currentContext.buf.length) {
+ var bufferIdx = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
+ if (bufferIdx > AL.currentContext.buf.length) {
#if OPENAL_DEBUG
console.error("alSourceQueueBuffers called with an invalid buffer");
#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
- AL.currentContext.src[source - 1].buffer = AL.currentContext.buf[buffer - 1].buf;
}
+
+ for (var i = 0; i < count; ++i) {
+ var bufferIdx = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
+ var buffer = AL.currentContext.buf[bufferIdx - 1];
+ src.queue.push({ buffer: buffer, src: null });
+ }
+
+ _updateSource(src);
},
- alSourceUnqueueBuffers: function(source, count, buffers)
- {
+ alSourceUnqueueBuffers__deps: ["updateSource"],
+ alSourceUnqueueBuffers: function(source, count, buffers) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
console.error("alSourceUnqueueBuffers called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
return;
}
- if (source > AL.currentContext.src.length) {
+ var src = AL.currentContext.src[source - 1];
+ if (!src) {
#if OPENAL_DEBUG
console.error("alSourceUnqueueBuffers called with an invalid source");
#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
return;
}
- if (count != 1) {
-#if OPENAL_DEBUG
- console.error("Queuing multiple buffers using alSourceUnqueueBuffers is not supported yet");
-#endif
+
+ if (count > src.buffersPlayed) {
+ AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */;
return;
}
- for (var i = 0; i < count; ++i) {
- var buffer = AL.currentContext.src[source - 1].buffer;
- for (var j = 0; j < AL.currentContext.buf.length; ++j) {
- if (buffer == AL.currentContext.buf[j].buf) {
+
+ for (var i = 0; i < count; i++) {
+ var entry = src.queue.shift();
+ // Write the buffers index out to the return list.
+ for (var j = 0; j < AL.currentContext.buf.length; j++) {
+ var b = AL.currentContext.buf[j];
+ if (b && b == entry.buffer) {
{{{ makeSetValue('buffers', 'i*4', 'j+1', 'i32') }}};
- AL.currentContext.src[source - 1].buffer = null;
break;
}
}
+ src.buffersPlayed--;
}
+
+ _updateSource(src);
},
alDeleteBuffers: function(count, buffers)
@@ -308,21 +553,43 @@ var LibraryOpenAL = {
#if OPENAL_DEBUG
console.error("alDeleteBuffers called without a valid context");
#endif
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
+ return;
+ }
+ if (count > AL.currentContext.buf.length) {
+ AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */;
return;
}
+
for (var i = 0; i < count; ++i) {
var bufferIdx = {{{ makeGetValue('buffers', 'i*4', 'i32') }}} - 1;
- if (bufferIdx < AL.currentContext.buf.length && AL.currentContext.buf[bufferIdx]) {
- var buffer = AL.currentContext.buf[bufferIdx].buf;
- for (var j = 0; j < AL.currentContext.src.length; ++j) {
- if (buffer == AL.currentContext.src[j].buffer) {
- AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
+
+ // Make sure the buffer index is valid.
+ if (bufferIdx >= AL.currentContext.buf.length || !AL.currentContext.buf[bufferIdx]) {
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
+ return;
+ }
+
+ // Make sure the buffer is no longer in use.
+ var buffer = AL.currentContext.buf[bufferIdx];
+ for (var j = 0; j < AL.currentContext.src.length; ++j) {
+ var src = AL.currentContext.src[j];
+ if (!src) {
+ continue;
+ }
+ for (var k = 0; k < src.queue.length; k++) {
+ if (buffer === src.queue[k].buffer) {
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;