Skip to content
Open
79 changes: 79 additions & 0 deletions test/browser/test_sdl3_mixer_wav.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2025 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/

#include <stdio.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3_mixer/SDL_mixer.h>
#include <emscripten.h>

SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
MIX_Audio *audio = NULL;
MIX_Track *track = NULL;
MIX_Mixer *mixer = NULL;

#define WIDTH 640
#define HEIGHT 480

#define WAV_PATH "/sound.wav"

void sound_loop_then_quit() {
if (MIX_TrackPlaying(track))
return;

MIX_DestroyAudio(audio);
MIX_DestroyTrack(track);
MIX_DestroyMixer(mixer);

emscripten_cancel_main_loop();
printf("Shutting down\n");
exit(0);
}

int main(int argc, char *argv[]) {
SDL_Init(SDL_INIT_VIDEO);

if (!MIX_Init()) {
printf("MIX_Init failed: %s\n", SDL_GetError());
return 1;
}

if (!SDL_CreateWindowAndRenderer("SDL3 MIXER", WIDTH, HEIGHT, 0, &window, &renderer)) {
printf("SDL_CreateWindowAndRenderer: %s\n", SDL_GetError());
return 1;
}

mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
if (!mixer) {
printf("Couldn't create mixer on default device: %s", SDL_GetError());
return 1;
}

audio = MIX_LoadAudio(mixer, WAV_PATH, false);
if (!audio) {
printf("MIX_LoadAudio: %s\n", SDL_GetError());
return 1;
}

track = MIX_CreateTrack(mixer);
if (!track) {
printf("MIX_CreateTrack: %s\n", SDL_GetError());
return 1;
}

MIX_SetTrackAudio(track, audio);
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetNumberProperty(props, MIX_PROP_PLAY_LOOPS_NUMBER, 0);

printf("Starting sound play loop\n");
MIX_PlayTrack(track, props);

emscripten_set_main_loop(sound_loop_then_quit, 0, 1);

return 0;
}
6 changes: 6 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3201,6 +3201,12 @@ def test_sdl3_canvas_write(self):
self.cflags.append('-Wno-experimental')
self.btest_exit('test_sdl3_canvas_write.c', cflags=['-sUSE_SDL=3'])

@requires_sound_hardware
def test_sdl3_mixer_wav(self):
copy_asset('sounds/the_entertainer.wav', 'sound.wav')
self.cflags.append('-Wno-experimental')
self.btest_exit('test_sdl3_mixer_wav.c', cflags=['-sUSE_SDL=3', '-sUSE_SDL_MIXER=3', '--preload-file', 'sound.wav'])

@requires_graphics_hardware
@no_wasm64('cocos2d ports does not compile with wasm64')
def test_cocos2d_hello(self):
Expand Down
4 changes: 4 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,10 @@ def test_sdl3_ttf(self):
self.emcc(test_file('browser/test_sdl3_ttf.c'), args=['-Wno-experimental', '-sUSE_SDL=3', '-sUSE_SDL_TTF=3'])
self.emcc(test_file('browser/test_sdl3_ttf.c'), args=['-Wno-experimental', '--use-port=sdl3', '--use-port=sdl3_ttf'])

@requires_network
def test_sdl3_mixer(self):
self.emcc('browser/test_sdl3_mixer_wav.c', ['-Wno-experimental', '-sUSE_SDL=3', '-sUSE_SDL_MIXER=3', '-o', 'a.out.js'])

@requires_network
def test_contrib_ports(self):
# Verify that contrib ports can be used (using the only contrib port available ATM, but can be replaced
Expand Down
8 changes: 4 additions & 4 deletions tools/ports/sdl3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

from tools import diagnostics

VERSION = '3.2.30'
VERSION = '3.4.2'
Comment thread
onesixromcom marked this conversation as resolved.
TAG = f'release-{VERSION}'
HASH = '80ef7b2f257f43fe47c7ea8aa0a64f1c6f23720d91065d5e9b42f0205c62fc98bcf8dd1f1834fe09c66bea2598a18a658b82212cb29810be2d2175dece0aadce'
HASH = 'a17fe538993a3956e0b85fda21e7b431244e803a5facb35bb7a2bfd9ee23f1aac65838ed3225f526b81410cae7c23da7c40693c2e791385281f0764239116bce'
SUBDIR = f'SDL-{TAG}'

variants = {'sdl3-mt': {'PTHREADS': 1}}
Expand All @@ -29,7 +29,7 @@ def get(ports, settings, shared):
diagnostics.warning('experimental', 'sdl3 port is still experimental')

# get the port
ports.fetch_project('sdl3', f'https://github.com/libsdl-org/SDL/archive/{TAG}.zip', sha512hash=HASH)
ports.fetch_project('sdl3', f'https://github.com/libsdl-org/SDL/archive/refs/tags/{TAG}.zip', sha512hash=HASH)

def create(final):
root_dir = ports.get_dir('sdl3', SUBDIR)
Expand All @@ -53,7 +53,7 @@ def create(final):
'atomic/*.c',
'audio/*.c',
'camera/*.c',
'core/*.c',
'core/unix/*.c',
'cpuinfo/*.c',
'dynapi/*.c',
'events/*.c',
Expand Down
2 changes: 2 additions & 0 deletions tools/ports/sdl3/SDL_build_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
#define HAVE_STRING_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_WCHAR_H 1
#define HAVE_GETRESGID 1
#define HAVE_GETRESUID 1
/* #undef HAVE_PTHREAD_NP_H */

/* C library functions */
Expand Down
77 changes: 77 additions & 0 deletions tools/ports/sdl3_mixer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Copyright 2025 The Emscripten Authors. All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License. Both these licenses can be
# found in the LICENSE file.

import os

from typing import Dict, Set
Comment thread
onesixromcom marked this conversation as resolved.
Outdated

VERSION = '3.2.0'
TAG = f'release-{VERSION}'
HASH = '96f374b3ca96202973fca84228e7775db3d6e38888888573d0ba0d045bc1d3cc6f876984e50dcce1b65875c80f8e263b5ff687570f4b4c720f48ca3cfaff0648'
SUBDIR = f'SDL3_mixer-{TAG}'

deps = ['sdl3']

variants = {'sdl3_mixer-mt': {'PTHREADS': 1}}


def needed(settings):
return settings.USE_SDL_MIXER == 3


def get_lib_name(settings):
return 'libSDL3_mixer' + ('-mt' if settings.PTHREADS else '') + '.a'


def get(ports, settings, shared):
ports.fetch_project('sdl3_mixer', f'https://github.com/libsdl-org/SDL_mixer/archive/refs/tags/{TAG}.zip', sha512hash=HASH)

def create(final):
src_root = ports.get_dir('sdl3_mixer', 'SDL_mixer-' + TAG)
ports.install_header_dir(os.path.join(src_root, 'include'), target='.')
srcs = [
"src/SDL_mixer.c",
"src/SDL_mixer_metadata_tags.c",
"src/SDL_mixer_spatialization.c",
"src/decoder_aiff.c",
"src/decoder_au.c",
"src/decoder_drflac.c",
"src/decoder_drmp3.c",
"src/decoder_flac.c",
"src/decoder_fluidsynth.c",
"src/decoder_gme.c",
"src/decoder_mpg123.c",
"src/decoder_opus.c",
"src/decoder_raw.c",
"src/decoder_sinewave.c",
"src/decoder_stb_vorbis.c",
"src/decoder_timidity.c",
"src/decoder_voc.c",
"src/decoder_vorbis.c",
"src/decoder_wav.c",
"src/decoder_wavpack.c",
"src/decoder_xmp.c",
Comment thread
onesixromcom marked this conversation as resolved.
Outdated
]

flags = ['-sUSE_SDL=3', '-DDECODER_WAV','-Wno-format-security', '-Wno-experimental']

if settings.PTHREADS:
flags += ['-pthread']

ports.build_port(src_root, final, 'sdl3_mixer', flags=flags, srcs=srcs)

return [shared.cache.get_lib(get_lib_name(settings), create, what='port')]


def clear(ports, settings, shared):
shared.cache.erase_lib(get_lib_name(settings))


def process_dependencies(settings):
settings.USE_SDL = 3


def show():
return 'sdl3_mixer (-sUSE_SDL_MIXER=3 or --use-port=sdl3_mixer; zlib license)'
Comment thread
onesixromcom marked this conversation as resolved.
Outdated