Skip to content

Commit 1c8438e

Browse files
committed
Re-do CreateFromRW() for STDFILE RWops
Adjust DISABLE_TYPE_CHECK hint for HTML5_MIXER
1 parent 3ba7e09 commit 1c8438e

File tree

1 file changed

+68
-61
lines changed

1 file changed

+68
-61
lines changed

music_html5.c

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@
2727

2828
#include <emscripten.h>
2929

30+
#ifdef HTML5_MIXER
31+
#define SDL_MIXER_HTML5_DISABLE_TYPE_CHECK (SDL_TRUE)
32+
#else
33+
#define SDL_MIXER_HTML5_DISABLE_TYPE_CHECK SDL_GetHint("SDL_MIXER_HTML5_DISABLE_TYPE_CHECK")
34+
#endif
35+
3036
typedef struct {
3137
int id;
3238
SDL_RWops *src;
3339
SDL_bool freesrc;
34-
void *buf;
35-
SDL_bool freebuf;
3640
SDL_bool playing;
3741
} MusicHTML5;
3842

@@ -244,7 +248,7 @@ static int MusicHTML5_Open(const SDL_AudioSpec *spec)
244248
if (!canPlay) {
245249
const magic = buf.slice(0, 2);
246250
if (magic[0] === 0xFF && (magic[1] & 0xFE) === 0xFA)
247-
canPlay = Module["SDL2Mixer"].canPlayType("audio/mp3");
251+
canPlay = Module["SDL2Mixer"].canPlayType("audio/mpeg");
248252
}
249253

250254
return canPlay;
@@ -288,8 +292,6 @@ static int MusicHTML5_Open(const SDL_AudioSpec *spec)
288292

289293
static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
290294
{
291-
void *buf;
292-
SDL_bool freebuf = SDL_FALSE;
293295
int id = -1;
294296
int size = src->size(src);
295297
MusicHTML5 *music = (MusicHTML5 *)SDL_calloc(1, sizeof *music);
@@ -299,36 +301,69 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
299301
return NULL;
300302
}
301303

302-
if (src->type == SDL_RWOPS_STDFILE) {
303-
// We must make a copy of the whole file to a new buffer.
304-
//
305-
// Note that it's more memory-efficient for the user to call Mix_LoadMUS()
306-
// instead of Mix_LoadWAV_RW(). In the former, we query FS.readFile() in JS
307-
// and avoid copying memory.
308-
309-
Sint64 res_size = SDL_RWsize(src);
310-
void *res = malloc(res_size + 1);
311-
312-
Sint64 nb_read_total = 0, nb_read = 1;
313-
buf = res;
314-
while (nb_read_total < res_size && nb_read != 0) {
315-
nb_read = SDL_RWread(src, buf, 1, (res_size - nb_read_total));
316-
nb_read_total += nb_read;
317-
buf += nb_read;
318-
}
319-
if (nb_read_total != res_size) {
320-
free(res);
321-
return NULL;
322-
}
323-
((char *)res)[nb_read_total] = '\0';
304+
SDL_bool force = SDL_MIXER_HTML5_DISABLE_TYPE_CHECK;
305+
306+
if (src->type == SDL_RWOPS_STDFILE)
307+
{
308+
// This violates "private" membership, but this lets us avoid
309+
// copying the entire file into a new buffer. Instead, we query
310+
// FS for the file's location in MEMFS.
311+
FILE *f = src->hidden.stdio.fp;
312+
int fd = fileno(f);
313+
314+
if (f) {
315+
id = EM_ASM_INT({
316+
const fd = $0;
317+
const context = $1;
318+
const force = $2;
319+
320+
const stream = SYSCALLS.getStreamFromFD(fd);
324321

325-
// Reset buf pointer back to start of memory for re-use
326-
buf = res;
327-
freebuf = SDL_TRUE;
328-
} else if (src->type == SDL_RWOPS_MEMORY || src->type == SDL_RWOPS_MEMORY_RO)
322+
if (!stream || !stream.node || !stream.node.contents)
323+
return -1;
324+
325+
const buf = stream.node.contents;
326+
327+
let canPlay = force
328+
|| Module["SDL2Mixer"].canPlayFile(stream.path)
329+
|| Module["SDL2Mixer"].canPlayMagic(buf);
330+
331+
if (!canPlay)
332+
return -1;
333+
334+
const url = Module["SDL2Mixer"].createBlob(buf);
335+
const id = Module["SDL2Mixer"].createMusic(url, context);
336+
337+
return id;
338+
}, fd, music, force);
339+
}
340+
}
341+
else if (src->type == SDL_RWOPS_MEMORY || src->type == SDL_RWOPS_MEMORY_RO)
342+
{
329343
// This violates "private" membership, but it works because
330344
// the entire file is loaded in this pointer.
331-
buf = src->hidden.mem.base;
345+
void *buf = src->hidden.mem.base;
346+
347+
if (buf && size > 0)
348+
{
349+
id = EM_ASM_INT({
350+
const ptr = $0;
351+
const size = $1;
352+
const context = $2;
353+
const force = $3;
354+
355+
const buf = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
356+
357+
if (!force && !Module["SDL2Mixer"].canPlayMagic(buf))
358+
return -1;
359+
360+
const url = Module["SDL2Mixer"].createBlob(buf);
361+
const id = Module["SDL2Mixer"].createMusic(url, context);
362+
363+
return id;
364+
}, buf, size, music, force);
365+
}
366+
}
332367
else
333368
{
334369
Mix_SetError("Unsupported RWops type: %d", src->type);
@@ -337,31 +372,8 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
337372
return NULL;
338373
}
339374

340-
if (buf && size > 0)
341-
{
342-
SDL_bool force = (SDL_GetHint("SDL_MIXER_HTML5_DISABLE_TYPE_CHECK") != NULL);
343-
id = EM_ASM_INT({
344-
const ptr = $0;
345-
const size = $1;
346-
const context = $2;
347-
const force = $3;
348-
349-
const buf = new Uint8Array(Module.HEAPU8.buffer, ptr, size);
350-
351-
if (!force && !Module["SDL2Mixer"].canPlayMagic(buf))
352-
return -1;
353-
354-
const url = Module["SDL2Mixer"].createBlob(buf);
355-
const id = Module["SDL2Mixer"].createMusic(url, context);
356-
357-
return id;
358-
}, buf, size, music, force);
359-
}
360-
361375
if (id == -1)
362376
{
363-
if (freebuf)
364-
SDL_free(buf);
365377
SDL_free(music);
366378
return NULL;
367379
}
@@ -370,8 +382,6 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
370382
music->id = id;
371383
music->src = src;
372384
music->freesrc = freesrc;
373-
music->buf = buf;
374-
music->freebuf = SDL_TRUE;
375385
music->playing = SDL_TRUE;
376386

377387
/* We're done */
@@ -383,7 +393,7 @@ static void *MusicHTML5_CreateFromFile(const char *file)
383393
{
384394
MusicHTML5 *music = (MusicHTML5 *)SDL_calloc(1, sizeof *music);;
385395
int id = -1;
386-
SDL_bool force = (SDL_GetHint("SDL_MIXER_HTML5_DISABLE_TYPE_CHECK") != NULL);
396+
SDL_bool force = SDL_MIXER_HTML5_DISABLE_TYPE_CHECK;
387397

388398
if (music == NULL) {
389399
Mix_SetError("Out of memory");
@@ -430,7 +440,6 @@ static void *MusicHTML5_CreateFromFile(const char *file)
430440
/* Fill the music structure */
431441
music->id = id;
432442
music->freesrc = SDL_FALSE;
433-
music->freebuf = SDL_FALSE;
434443
music->playing = SDL_TRUE;
435444

436445
/* We're done */
@@ -596,8 +605,6 @@ static void MusicHTML5_Delete(void *context)
596605

597606
if (music->freesrc && music->src)
598607
SDL_RWclose(music->src);
599-
if (music->freebuf && music->buf)
600-
SDL_free(music->buf);
601608

602609
SDL_free(music);
603610
}

0 commit comments

Comments
 (0)