27
27
28
28
#include <emscripten.h>
29
29
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
+
30
36
typedef struct {
31
37
int id ;
32
38
SDL_RWops * src ;
33
39
SDL_bool freesrc ;
34
- void * buf ;
35
- SDL_bool freebuf ;
36
40
SDL_bool playing ;
37
41
} MusicHTML5 ;
38
42
@@ -244,7 +248,7 @@ static int MusicHTML5_Open(const SDL_AudioSpec *spec)
244
248
if (!canPlay ) {
245
249
const magic = buf .slice (0 , 2 );
246
250
if (magic [0 ] == = 0xFF && (magic [1 ] & 0xFE ) == = 0xFA )
247
- canPlay = Module ["SDL2Mixer" ].canPlayType ("audio/mp3 " );
251
+ canPlay = Module ["SDL2Mixer" ].canPlayType ("audio/mpeg " );
248
252
}
249
253
250
254
return canPlay ;
@@ -288,8 +292,6 @@ static int MusicHTML5_Open(const SDL_AudioSpec *spec)
288
292
289
293
static void * MusicHTML5_CreateFromRW (SDL_RWops * src , int freesrc )
290
294
{
291
- void * buf ;
292
- SDL_bool freebuf = SDL_FALSE ;
293
295
int id = -1 ;
294
296
int size = src -> size (src );
295
297
MusicHTML5 * music = (MusicHTML5 * )SDL_calloc (1 , sizeof * music );
@@ -299,36 +301,69 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
299
301
return NULL ;
300
302
}
301
303
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 );
324
321
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
+ {
329
343
// This violates "private" membership, but it works because
330
344
// 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
+ }
332
367
else
333
368
{
334
369
Mix_SetError ("Unsupported RWops type: %d" , src -> type );
@@ -337,31 +372,8 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
337
372
return NULL ;
338
373
}
339
374
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
-
361
375
if (id == -1 )
362
376
{
363
- if (freebuf )
364
- SDL_free (buf );
365
377
SDL_free (music );
366
378
return NULL ;
367
379
}
@@ -370,8 +382,6 @@ static void *MusicHTML5_CreateFromRW(SDL_RWops *src, int freesrc)
370
382
music -> id = id ;
371
383
music -> src = src ;
372
384
music -> freesrc = freesrc ;
373
- music -> buf = buf ;
374
- music -> freebuf = SDL_TRUE ;
375
385
music -> playing = SDL_TRUE ;
376
386
377
387
/* We're done */
@@ -383,7 +393,7 @@ static void *MusicHTML5_CreateFromFile(const char *file)
383
393
{
384
394
MusicHTML5 * music = (MusicHTML5 * )SDL_calloc (1 , sizeof * music );;
385
395
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 ;
387
397
388
398
if (music == NULL ) {
389
399
Mix_SetError ("Out of memory" );
@@ -430,7 +440,6 @@ static void *MusicHTML5_CreateFromFile(const char *file)
430
440
/* Fill the music structure */
431
441
music -> id = id ;
432
442
music -> freesrc = SDL_FALSE ;
433
- music -> freebuf = SDL_FALSE ;
434
443
music -> playing = SDL_TRUE ;
435
444
436
445
/* We're done */
@@ -596,8 +605,6 @@ static void MusicHTML5_Delete(void *context)
596
605
597
606
if (music -> freesrc && music -> src )
598
607
SDL_RWclose (music -> src );
599
- if (music -> freebuf && music -> buf )
600
- SDL_free (music -> buf );
601
608
602
609
SDL_free (music );
603
610
}
0 commit comments