Project

General

Profile

Bug #1713 ยป 0039-audio_sdl.c-Update-SDL3_mixer-support-to-use-stable-.patch

Marko Lindqvist, 11/20/2025 11:59 PM

View differences:

client/audio_sdl.c
#include "audio_sdl.h"
struct sample {
#ifdef AUDIO_SDL3
MIX_Audio *wave;
#else /* AUDIO_SDL3 */
Mix_Chunk *wave;
#endif /* AUDIO_SDL3 */
const char *tag;
};
......
const size_t buf_size = 1024;
#endif
#ifdef AUDIO_SDL3
#define MIX_CHANNELS 8
static MIX_Audio *mus = NULL;
static MIX_Mixer *mixer = NULL;
static MIX_Track *tracks[MIX_CHANNELS];
static SDL_PropertiesID forever_loop;
#else /* AUDIO_SDL3 */
static Mix_Music *mus = NULL;
#endif /* AUDIO_SDL3 */
static struct sample samples[MIX_CHANNELS];
static double sdl_audio_volume;
......
**************************************************************************/
static void sdl_audio_set_volume(double volume)
{
#ifdef AUDIO_SDL3
int i;
for (i = 0; i < MIX_CHANNELS; i++) {
MIX_SetTrackGain(tracks[i], volume);
}
#else /* AUDIO_SDL3 */
Mix_VolumeMusic(volume * MIX_MAX_VOLUME);
Mix_Volume(-1, volume * MIX_MAX_VOLUME);
#endif /* AUDIO_SDL3 */
sdl_audio_volume = volume;
}
......
return sdl_audio_volume;
}
#ifdef AUDIO_SDL3
/**********************************************************************//**
Wrap freeciv's callback within SDL3 compatible callback
**************************************************************************/
static void audio_callback_wrapper(void *cb, MIX_Track *track)
{
((audio_finished_callback)cb)();
}
#endif /* AUDIO_SDL3 */
/**********************************************************************//**
Play sound
**************************************************************************/
static bool sdl_audio_play(const char *const tag, const char *const fullpath,
bool repeat, bool music, audio_finished_callback cb)
{
int i, j;
int j;
#ifdef AUDIO_SDL3
MIX_Audio *wave = NULL;
int channel;
static int channel_turn = 1; /* Channel 0 is music */
#else /* AUDIO_SDL3 */
int i;
Mix_Chunk *wave = NULL;
#endif /* AUDIO_SDL3 */
if (!fullpath) {
return FALSE;
}
#ifdef AUDIO_SDL3
if (music) {
channel = 0;
} else {
channel = channel_turn++;
if (channel_turn >= MIX_CHANNELS) {
channel_turn = 1;
}
}
#endif /* AUDIO_SDL3 */
if (repeat) {
/* unload previous */
/* Unload previous */
#ifdef AUDIO_SDL3
MIX_StopTrack(tracks[channel], 0);
MIX_DestroyAudio(mus);
#else /* AUDIO_SDL3 */
Mix_HaltMusic();
Mix_FreeMusic(mus);
#endif /* AUDIO_SDL3 */
/* load music file */
/* Load music file */
#ifdef AUDIO_SDL3
mus = MIX_LoadAudio(mixer, fullpath, FALSE);
#else /* AUDIO_SDL3 */
mus = Mix_LoadMUS(fullpath);
#endif /* AUDIO_SDL3 */
if (mus == NULL) {
log_error("Can't open file \"%s\"", fullpath);
log_error("Can't open file \"%s\": %s",
fullpath, SDL_GetError());
}
if (cb == NULL) {
Mix_PlayMusic(mus, -1); /* -1 means loop forever */
#ifdef AUDIO_SDL3
MIX_SetTrackAudio(tracks[channel], mus);
MIX_PlayTrack(tracks[channel], forever_loop);
#else /* AUDIO_SDL3 */
Mix_PlayMusic(mus, -1); /* -1 means loop forever */
#endif /* AUDIO_SDL3 */
} else {
#ifdef AUDIO_SDL3
MIX_SetTrackAudio(tracks[channel], mus);
MIX_PlayTrack(tracks[channel], 0);
MIX_SetTrackStoppedCallback(tracks[channel],
audio_callback_wrapper, cb);
#else /* AUDIO_SDL3 */
Mix_PlayMusic(mus, 0);
Mix_HookMusicFinished(cb);
#endif /* AUDIO_SDL3 */
}
log_verbose("Playing file \"%s\" on music channel", fullpath);
/* in case we did a sdl_audio_stop() recently; add volume controls later */
/* In case we did a sdl_audio_stop() recently; add volume controls later */
#ifdef AUDIO_SDL3
MIX_SetTrackGain(tracks[0], sdl_audio_volume);
#else /* AUDIO_SDL3 */
Mix_VolumeMusic(sdl_audio_volume * MIX_MAX_VOLUME);
#endif /* AUDIO_SDL3 */
} else {
/* see if we can cache on this one */
/* See if we can cache on this one */
for (j = 0; j < MIX_CHANNELS; j++) {
if (samples[j].tag && (strcmp(samples[j].tag, tag) == 0)) {
log_debug("Playing file \"%s\" from cache (slot %d)", fullpath, j);
#ifdef AUDIO_SDL3
MIX_SetTrackAudio(tracks[channel], samples[j].wave);
MIX_PlayTrack(tracks[channel], 0);
#else /* AUDIO_SDL3 */
Mix_PlayChannel(-1, samples[j].wave, 0);
#endif /* AUDIO_SDL3 */
return TRUE;
}
} /* guess not */
} /* Guess not */
/* load wave */
/* Load wave */
#ifdef AUDIO_SDL3
wave = MIX_LoadAudio(mixer, fullpath, FALSE);
#else /* AUDIO_SDL3 */
wave = Mix_LoadWAV(fullpath);
#endif /* AUDIO_SDL3 */
if (wave == NULL) {
log_error("Can't open file \"%s\"", fullpath);
}
/* play sound sample on first available channel, returns -1 if no
/* Play sound sample on first available channel, returns -1 if no
channel found */
#ifdef AUDIO_SDL3
MIX_SetTrackAudio(tracks[channel], wave);
MIX_PlayTrack(tracks[channel], 0);
log_verbose("Playing file \"%s\" on channel %d", fullpath, channel);
/* Free previous sample on this channel. it will by definition no
longer be playing by the time we get here */
if (samples[channel].wave) {
MIX_DestroyAudio(samples[channel].wave);
samples[channel].wave = NULL;
}
/* Remember for caching */
samples[channel].wave = wave;
samples[channel].tag = tag;
#else /* AUDIO_SDL3 */
i = Mix_PlayChannel(-1, wave, 0);
if (i < 0) {
log_verbose("No available sound channel to play %s.", tag);
Mix_FreeChunk(wave);
return FALSE;
}
log_verbose("Playing file \"%s\" on channel %d", fullpath, i);
/* free previous sample on this channel. it will by definition no
/* Free previous sample on this channel. it will by definition no
longer be playing by the time we get here */
if (samples[i].wave) {
Mix_FreeChunk(samples[i].wave);
samples[i].wave = NULL;
}
/* remember for caching */
/* Remember for caching */
samples[i].wave = wave;
samples[i].tag = tag;
#endif /* AUDIO_SDL3 */
}
return TRUE;
......
**************************************************************************/
static void sdl_audio_pause(void)
{
#ifdef AUDIO_SDL3
int i;
for (i = 0; i < MIX_CHANNELS; i++) {
MIX_PauseTrack(tracks[i]);
}
#else /* AUDIO_SDL3 */
Mix_PauseMusic();
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
**************************************************************************/
static void sdl_audio_resume(void)
{
#ifdef AUDIO_SDL3
int i;
for (i = 0; i < MIX_CHANNELS; i++) {
MIX_ResumeTrack(tracks[i]);
}
#else /* AUDIO_SDL3 */
Mix_ResumeMusic();
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
static void sdl_audio_stop(void)
{
/* Fade out over 2 sec */
#ifdef AUDIO_SDL3
int i;
for (i = 0; i < MIX_CHANNELS; i++) {
MIX_StopTrack(tracks[i],
MIX_TrackMSToFrames(tracks[i], 2000));
}
#else /* AUDIO_SDL3 */
Mix_FadeOutMusic(2000);
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
**************************************************************************/
static void sdl_audio_wait(void)
{
#ifdef AUDIO_SDL3
bool wait = TRUE;
while (wait) {
int i;
wait = FALSE;
for (i = 0; i < MIX_CHANNELS && !wait; i++) {
if (MIX_TrackPlaying(tracks[i])) {
wait = TRUE;
}
}
if (wait) {
SDL_Delay(100);
}
}
#else /* AUDIO_SDL3 */
while (Mix_Playing(-1) != 0) {
SDL_Delay(100);
}
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
**************************************************************************/
static void quit_sdl_audio(void)
{
#ifdef AUDIO_SDL3
MIX_Quit();
#else /* AUDIO_SDL3 */
if (SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_QuitSubSystem(SDL_INIT_AUDIO);
} else {
SDL_Quit();
}
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
static bool init_sdl_audio(void)
{
#ifdef AUDIO_SDL3
return SDL_Init(SDL_INIT_AUDIO);
return MIX_Init();
#else /* AUDIO_SDL3 */
SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "medium");
......
/* Remove all buffers */
for (i = 0; i < MIX_CHANNELS; i++) {
if (samples[i].wave) {
#ifdef AUDIO_SDL3
MIX_StopTrack(tracks[i], 0);
MIX_DestroyAudio(samples[i].wave);
#else /* AUDIO_SDL3 */
Mix_FreeChunk(samples[i].wave);
#endif /* AUDIO_SDL3 */
}
}
#ifdef AUDIO_SDL3
MIX_DestroyAudio(mus);
MIX_DestroyMixer(mixer);
#else /* AUDIO_SDL3 */
Mix_HaltMusic();
Mix_FreeMusic(mus);
Mix_CloseAudio();
#endif /* AUDIO_SDL3 */
quit_sdl_audio();
#ifdef AUDIO_SDL3
SDL_DestroyProperties(forever_loop);
#endif /* AUDIO_SDL3 */
}
/**********************************************************************//**
......
}
#ifdef AUDIO_SDL3
if (!Mix_OpenAudio(0, NULL)) {
mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
if (mixer == NULL) {
log_error("Error calling MIX_CreateMixerDevice()");
#else /* AUDIO_SDL3 */
/* Initialize variables */
const int audio_rate = MIX_DEFAULT_FREQUENCY;
......
const int audio_channels = 2;
if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, buf_size) < 0) {
#endif /* AUDIO_SDL3 */
log_error("Error calling Mix_OpenAudio");
#endif /* AUDIO_SDL3 */
/* Try something else */
quit_sdl_audio();
return FALSE;
}
#ifdef AUDIO_SDL3
forever_loop = SDL_CreateProperties();
SDL_SetNumberProperty(forever_loop,
"MIX_PROP_PLAY_LOOPS_NUMBER", -1);
#else /* AUDIO_SDL3 */
Mix_AllocateChannels(MIX_CHANNELS);
#endif /* AUDIO_SDL3 */
for (i = 0; i < MIX_CHANNELS; i++) {
#ifdef AUDIO_SDL3
tracks[i] = MIX_CreateTrack(mixer);
#endif /* AUDIO_SDL3 */
samples[i].wave = NULL;
}
    (1-1/1)