Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package SDL3_mixer for openSUSE:Factory checked in at 2026-10-31 23:11:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/SDL3_mixer (Old) and /work/SRC/openSUSE:Factory/.SDL3_mixer.new.1255 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "SDL3_mixer" Sat Oct 31 23:11:54 2026 rev:3 rq:1394195 version:3.2.4 Changes: -------- --- /work/SRC/openSUSE:Factory/SDL3_mixer/SDL3_mixer.changes 2026-05-12 19:30:49.905440351 +0200 +++ /work/SRC/openSUSE:Factory/.SDL3_mixer.new.1255/SDL3_mixer.changes 2026-10-31 23:15:01.230510467 +0100 @@ -1,0 +2,14 @@ +Sat Oct 31 15:24:22 UTC 2026 - Andrea Manzini <[email protected]> + +- Update to release 3.2.4: + * Added MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN to ignore + looping information in an audio file's metadata. + * Fixed crash bug in MIX_SetTrackGroup(). + * Fixed crash in MIX_StopTrack(t, 0) if callback destroys track. + * Fixed crash when MIX_PROP_PLAY_MAX_* is less than track start. + * Fixed unexpected decoding failures when using MIX_AudioDecoder. + * Fixed .OXM files being treated as Ogg Vorbis. + * Support custom FluidSynth string settings. + * Various small bug fixes and memory leaks. + +------------------------------------------------------------------- Old: ---- SDL3_mixer-3.2.2.tar.gz SDL3_mixer-3.2.2.tar.gz.sig New: ---- SDL3_mixer-3.2.4.tar.gz SDL3_mixer-3.2.4.tar.gz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ SDL3_mixer.spec ++++++ --- /var/tmp/diff_new_pack.HfEQgw/_old 2026-10-31 23:15:01.918538978 +0100 +++ /var/tmp/diff_new_pack.HfEQgw/_new 2026-10-31 23:15:01.920539061 +0100 @@ -19,11 +19,10 @@ %define sover 0 Name: SDL3_mixer -Version: 3.2.2 +Version: 3.2.4 Release: 0 Summary: SDL3 sound mixer library License: Zlib -Group: Development/Libraries/C and C++ URL: https://wiki.libsdl.org/SDL3_mixer #Git-Clone: https://github.com/libsdl-org/SDL_mixer Source: https://github.com/libsdl-org/SDL_mixer/releases/download/release-%{version}/%{name}-%{version}.tar.gz @@ -49,7 +48,6 @@ %package -n lib%{name}%{sover} Summary: Simple DirectMedia Layer 3 – Sound mixer library -Group: System/Libraries Provides: SDL3_mixer = %{version}-%{release} %description -n lib%{name}%{sover} @@ -59,7 +57,6 @@ %package devel Summary: Development files for the SDL3 sound mixer library -Group: Development/Libraries/C and C++ Requires: lib%{name}%{sover} = %{version} %description devel ++++++ SDL3_mixer-3.2.2.tar.gz -> SDL3_mixer-3.2.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/.git-hash new/SDL3_mixer-3.2.4/.git-hash --- old/SDL3_mixer-3.2.2/.git-hash 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/.git-hash 2026-06-03 01:56:16.000000000 +0200 @@ -1 +1 @@ -a5e1890afc5115ffd16cefdbb4d50f74bf4970ce +72a81869b45e249e8e67102db4e98dd2441f05a1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/CMakeLists.txt new/SDL3_mixer-3.2.4/CMakeLists.txt --- old/SDL3_mixer-3.2.2/CMakeLists.txt 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/CMakeLists.txt 2026-06-03 01:56:16.000000000 +0200 @@ -9,7 +9,7 @@ # See docs/release_checklist.md set(MAJOR_VERSION 3) set(MINOR_VERSION 2) -set(MICRO_VERSION 2) +set(MICRO_VERSION 4) set(SDL_REQUIRED_VERSION 3.4.0) project(SDL3_mixer @@ -92,7 +92,7 @@ include(PkgConfigHelper) set(PLATFORM_SUPPORTS_SHARED ON) -if(EMSCRIPTEN OR VITA OR PSP OR PS2 OR N3DS OR RISCOS) +if(EMSCRIPTEN OR VITA OR PSP OR PS2 OR N3DS OR RISCOS OR DOS) set(PLATFORM_SUPPORTS_SHARED OFF) endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/REVISION.txt new/SDL3_mixer-3.2.4/REVISION.txt --- old/SDL3_mixer-3.2.2/REVISION.txt 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/REVISION.txt 2026-06-03 01:56:16.000000000 +0200 @@ -1 +1 @@ -release-3.2.2-0-ga5e1890a +release-3.2.4-0-g72a81869 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/VisualC/SDL_mixer.vcxproj new/SDL3_mixer-3.2.4/VisualC/SDL_mixer.vcxproj --- old/SDL3_mixer-3.2.2/VisualC/SDL_mixer.vcxproj 2026-04-25 16:38:33.000000000 +0200 +++ new/SDL3_mixer-3.2.4/VisualC/SDL_mixer.vcxproj 2026-05-25 20:21:55.000000000 +0200 @@ -116,7 +116,7 @@ <ClCompile> <Optimization>Disabled</Optimization> <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\src;$(ProjectDir)..\external\flac\include;$(ProjectDir)..\external\libxmp\include;$(ProjectDir)..\external\ogg\include;$(ProjectDir)..\external\vorbis\include;$(ProjectDir)..\external\libgme;$(ProjectDir)\external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DLL_EXPORT;_DEBUG;WIN32;_WINDOWS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_VORBISFILE;DECODER_OGGVORBIS_STB;VORBIS_DYNAMIC="libvorbisfile-3.dll";DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>DLL_EXPORT;_DEBUG;WIN32;_WINDOWS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_STB;DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>OldStyle</DebugInformationFormat> @@ -144,7 +144,7 @@ <ClCompile> <Optimization>Disabled</Optimization> <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\src;$(ProjectDir)..\external\flac\include;$(ProjectDir)..\external\libxmp\include;$(ProjectDir)..\external\ogg\include;$(ProjectDir)..\external\vorbis\include;$(ProjectDir)..\external\libgme;$(ProjectDir)\external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DLL_EXPORT;_DEBUG;WIN32;_WINDOWS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_VORBISFILE;DECODER_OGGVORBIS_STB;VORBIS_DYNAMIC="libvorbisfile-3.dll";DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>DLL_EXPORT;_DEBUG;WIN32;_WINDOWS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_STB;DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>OldStyle</DebugInformationFormat> @@ -170,7 +170,7 @@ </Midl> <ClCompile> <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\src;$(ProjectDir)..\external\flac\include;$(ProjectDir)..\external\libxmp\include;$(ProjectDir)..\external\ogg\include;$(ProjectDir)..\external\vorbis\include;$(ProjectDir)..\external\libgme;$(ProjectDir)\external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DLL_EXPORT;NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_VORBISFILE;DECODER_OGGVORBIS_STB;VORBIS_DYNAMIC="libvorbisfile-3.dll";DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>DLL_EXPORT;NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_STB;DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <WarningLevel>Level3</WarningLevel> <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> @@ -197,7 +197,7 @@ </Midl> <ClCompile> <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\src;$(ProjectDir)..\external\flac\include;$(ProjectDir)..\external\libxmp\include;$(ProjectDir)..\external\ogg\include;$(ProjectDir)..\external\vorbis\include;$(ProjectDir)..\external\libgme;$(ProjectDir)\external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DLL_EXPORT;NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_VORBISFILE;DECODER_OGGVORBIS_STB;VORBIS_DYNAMIC="libvorbisfile-3.dll";DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>DLL_EXPORT;NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;DECODER_WAV;DECODER_AIFF;DECODER_VOC;DECODER_AU;DECODER_WAVPACK;DECODER_FLAC_DRFLAC;DECODER_MOD_XMP;XMP_DYNAMIC="libxmp.dll";DECODER_MP3_DRMP3;DECODER_OGGVORBIS_STB;DECODER_OPUS;OPUS_DYNAMIC="libopusfile-0.dll";WAVPACK_DYNAMIC="libwavpack-1.dll";DECODER_MIDI_TIMIDITY;DECODER_GME;GME_DYNAMIC="libgme.dll";%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <WarningLevel>Level3</WarningLevel> </ClCompile> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/Xcode/Info-Framework.plist new/SDL3_mixer-3.2.4/Xcode/Info-Framework.plist --- old/SDL3_mixer-3.2.2/Xcode/Info-Framework.plist 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/Xcode/Info-Framework.plist 2026-06-03 01:56:16.000000000 +0200 @@ -15,8 +15,8 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>3.2.2</string> + <string>3.2.4</string> <key>CFBundleVersion</key> - <string>3.2.2</string> + <string>3.2.4</string> </dict> </plist> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/Xcode/SDL_mixer.xcodeproj/project.pbxproj new/SDL3_mixer-3.2.4/Xcode/SDL_mixer.xcodeproj/project.pbxproj --- old/SDL3_mixer-3.2.2/Xcode/SDL_mixer.xcodeproj/project.pbxproj 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/Xcode/SDL_mixer.xcodeproj/project.pbxproj 2026-06-03 01:56:16.000000000 +0200 @@ -648,7 +648,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEPLOYMENT_POSTPROCESSING = YES; DYLIB_COMPATIBILITY_VERSION = 201.0.0; - DYLIB_CURRENT_VERSION = 201.2.0; + DYLIB_CURRENT_VERSION = 201.4.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; "FRAMEWORK_SEARCH_PATHS[sdk=appletv*]" = "\"$(PROJECT_DIR)/iOS\""; "FRAMEWORK_SEARCH_PATHS[sdk=iphone*]" = "\"$(PROJECT_DIR)/iOS\""; @@ -678,7 +678,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 3.2.2; + MARKETING_VERSION = 3.2.4; PRODUCT_BUNDLE_IDENTIFIER = "org.libsdl.SDL3-mixer"; PRODUCT_NAME = SDL3_mixer; SUPPORTED_PLATFORMS = "xrsimulator xros macosx iphonesimulator iphoneos appletvsimulator appletvos"; @@ -698,7 +698,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 201.0.0; - DYLIB_CURRENT_VERSION = 201.2.0; + DYLIB_CURRENT_VERSION = 201.4.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_TESTABILITY = YES; "FRAMEWORK_SEARCH_PATHS[sdk=appletv*]" = "\"$(PROJECT_DIR)/iOS\""; @@ -729,7 +729,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 3.2.2; + MARKETING_VERSION = 3.2.4; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.libsdl.SDL3-mixer"; PRODUCT_NAME = SDL3_mixer; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/build-scripts/test-versioning.sh new/SDL3_mixer-3.2.4/build-scripts/test-versioning.sh --- old/SDL3_mixer-3.2.2/build-scripts/test-versioning.sh 2026-01-01 21:14:23.000000000 +0100 +++ new/SDL3_mixer-3.2.4/build-scripts/test-versioning.sh 2026-05-15 18:23:42.000000000 +0200 @@ -92,6 +92,17 @@ not_ok "Info-Framework.plist CFBundleVersion $version disagrees with SDL_mixer.h $ref_version" fi +marketing=$(sed -Ene 's/.*MARKETING_VERSION = (.*);/\1/p' Xcode/SDL_mixer.xcodeproj/project.pbxproj) + +ref="$ref_version +$ref_version" + +if [ "$ref" = "$marketing" ]; then + ok "project.pbxproj MARKETING_VERSION is consistent" +else + not_ok "project.pbxproj MARKETING_VERSION is inconsistent, expected $ref, got $marketing" +fi + # For simplicity this assumes we'll never break ABI before SDL 3. dylib_compat=$(sed -Ene 's/.*DYLIB_COMPATIBILITY_VERSION = (.*);$/\1/p' Xcode/SDL_mixer.xcodeproj/project.pbxproj) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/examples/CMakeLists.txt new/SDL3_mixer-3.2.4/examples/CMakeLists.txt --- old/SDL3_mixer-3.2.2/examples/CMakeLists.txt 2026-02-04 21:50:29.000000000 +0100 +++ new/SDL3_mixer-3.2.4/examples/CMakeLists.txt 2026-05-19 21:15:51.000000000 +0200 @@ -132,6 +132,7 @@ add_sdlmixer_example_executable(basics-metadata SOURCES basics/04-metadata/metadata.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3) add_sdlmixer_example_executable(basics-sinewave SOURCES basics/05-sinewave/sinewave.c) add_sdlmixer_example_executable(basics-seeking SOURCES basics/06-seeking/seeking.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3) +add_sdlmixer_example_executable(advanced-tag-tracks SOURCES advanced/01-tag-tracks/tag-tracks.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3 ${CMAKE_CURRENT_SOURCE_DIR}/sword.wav ${CMAKE_CURRENT_SOURCE_DIR}/spring.wav ${CMAKE_CURRENT_SOURCE_DIR}/splash.wav) # When you add an example, remember to add the Visual Studio project as well: # - Add a new example in examples/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/examples/README.md new/SDL3_mixer-3.2.4/examples/README.md --- old/SDL3_mixer-3.2.2/examples/README.md 2026-01-26 21:52:14.000000000 +0100 +++ new/SDL3_mixer-3.2.4/examples/README.md 2026-05-19 21:15:51.000000000 +0200 @@ -80,3 +80,13 @@ Original: https://freesound.org/s/27858/ License: https://creativecommons.org/licenses/by/4.0/ +- splash.wav: + SPLASH.wav by petenice + Original: https://freesound.org/s/9508/ + License: https://creativecommons.org/publicdomain/zero/1.0/ + +- spring.wav: + Game Over Arcade.wav by myfox14 + Original: https://freesound.org/s/382310/ + License: https://creativecommons.org/publicdomain/zero/1.0/ + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/README.txt new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/README.txt --- old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/README.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/README.txt 2026-05-19 21:15:51.000000000 +0200 @@ -0,0 +1,7 @@ +This example code creates a mixer, plays sounds, and tags them into groups. + +We'll play a background music track, and tag the other sounds as "in-game". +So when you click the "pause" button, (what would be) your game sounds can +all pause at once, but the background music can continue on. + +(Remember that web browsers won't make sound until you click on the page!) Binary files old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/onmouseover.webp and new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/onmouseover.webp differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/tag-tracks.c new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/tag-tracks.c --- old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/tag-tracks.c 1970-01-01 01:00:00.000000000 +0100 +++ new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/tag-tracks.c 2026-05-19 21:15:51.000000000 +0200 @@ -0,0 +1,199 @@ +/* + * This example code creates a mixer, plays sounds, and tags them into groups. + * + * We'll play a background music track, and tag the other sounds as "in-game". + * So when you click the "pause" button, (what would be) your game sounds can + * all pause at once, but the background music can continue on. + * + * This code is public domain. Feel free to use it for any purpose! + */ + +#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ +#include <SDL3/SDL.h> +#include <SDL3/SDL_main.h> +#include <SDL3_mixer/SDL_mixer.h> + +#define TAG_INGAME "in-game" + +/* We will use this renderer to draw into this window every frame. */ +static SDL_Window *window = NULL; +static SDL_Renderer *renderer = NULL; + +static MIX_Mixer *mixer = NULL; +static MIX_Track *tracks[32]; + +static Uint64 next_play_ticks = 0; /* next time we will start a sound effect. */ +static size_t next_play_track = 1; /* next track we'll use when we start a sound effect. */ +static bool paused = false; /* whether our fake game is paused at the moment. */ + +static struct { + const char *filename; + MIX_Audio *audio; +} loaded_audio[] = { + { "music.mp3", NULL }, + { "sword.wav", NULL }, + { "splash.wav", NULL }, + { "spring.wav", NULL } +}; + +static MIX_Audio *load_audio(const char *fname) +{ + char *path = NULL; + MIX_Audio *audio; + SDL_asprintf(&path, "%s%s", SDL_GetBasePath(), fname); /* allocate a string of the full file path */ + audio = MIX_LoadAudio(mixer, path, false); + if (!audio) { + SDL_Log("Couldn't load %s: %s", path, SDL_GetError()); + } + + SDL_free(path); /* done with this. */ + return audio; +} + +/* This function runs once at startup. */ +SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) +{ + SDL_PropertiesID options = 0; + int i; + + SDL_SetAppMetadata("Example Tagging Tracks", "1.0", "com.example.tagging-tracks"); + + if (!SDL_Init(SDL_INIT_VIDEO)) { + SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + if (!SDL_CreateWindowAndRenderer("examples/advanced/tagging-tracks", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) { + SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + if (!MIX_Init()) { + SDL_Log("Couldn't init SDL_mixer library: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + /* Create a mixer on the default audio device. Don't care about the specific audio format. */ + mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL); + if (!mixer) { + SDL_Log("Couldn't create mixer on default device: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + /* load our audio files. Note that you can use any supported file format! */ + for (i = 0; i < (int) SDL_arraysize(loaded_audio); i++) { + loaded_audio[i].audio = load_audio(loaded_audio[i].filename); + if (!loaded_audio[i].audio) { + return SDL_APP_FAILURE; /* we reported the error in load_audio */ + } + } + + /* we need tracks on the mixer to play the audio. Each track has audio + assigned to it, and all playing tracks are mixed together for the final + output. */ + for (i = 0; i < (int) SDL_arraysize(tracks); i++) { + tracks[i] = MIX_CreateTrack(mixer); + if (!tracks[i]) { + SDL_Log("Couldn't create a mixer track: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + if (i > 0) { /* everything but the background music is tagged as in-game for this example. */ + if (!MIX_TagTrack(tracks[i], TAG_INGAME)) { + SDL_Log("Couldn't tag mixer track #%d: %s", i, SDL_GetError()); + return SDL_APP_FAILURE; + } + } + } + + /* Put the music (first thing we loaded) on track[0], for simplicity here. */ + MIX_SetTrackAudio(tracks[0], loaded_audio[0].audio); + + options = SDL_CreateProperties(); + if (!options) { + SDL_Log("Couldn't create play options: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, -1); /* loop forever. */ + + /* start the music playing! it loops forever. */ + MIX_PlayTrack(tracks[0], options); + SDL_DestroyProperties(options); /* MIX_PlayTrack makes a copy of the options, so this can go away. */ + + return SDL_APP_CONTINUE; /* carry on with the program! */ +} + +/* This function runs when a new event (mouse input, keypresses, etc) occurs. */ +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) +{ + if (event->type == SDL_EVENT_QUIT) { + return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ + } else if ((event->type == SDL_EVENT_KEY_DOWN) && (event->key.key == SDLK_SPACE)) { + paused = !paused; + if (paused) { + MIX_PauseTag(mixer, TAG_INGAME); + } else { + MIX_ResumeTag(mixer, TAG_INGAME); + } + } + return SDL_APP_CONTINUE; /* carry on with the program! */ +} + +static void draw_centered_text(SDL_Renderer *renderer, const int rw, int *y, const char *str) +{ + const int x = (rw - (((int) SDL_strlen(str)) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2; + SDL_RenderDebugText(renderer, (float) x, (float) *y, str); + *y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2; +} + +/* This function runs once per frame, and is the heart of the program. */ +SDL_AppResult SDL_AppIterate(void *appstate) +{ + const Uint64 now = SDL_GetTicks(); + int rw, rh, y; + + if (!paused && (now >= next_play_ticks)) { /* simulate video game sounds by starting a new one every now and then, with some randomness. */ + MIX_Track *track = tracks[next_play_track]; + /* these sounds are short enough that the tracks will finish playing before we reuse them */ + MIX_SetTrackAudio(track, loaded_audio[SDL_rand(SDL_arraysize(loaded_audio) - 1) + 1].audio); /* pick a random not-music audio sound. */ + MIX_PlayTrack(track, 0); + next_play_track++; + if (next_play_track >= SDL_arraysize(tracks)) { + next_play_track = 1; /* tracks[0] is the music, skip it. */ + } + next_play_ticks = now + SDL_rand(1000); + } + + SDL_GetCurrentRenderOutputSize(renderer, &rw, &rh); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* clear to black */ + SDL_RenderClear(renderer); + + y = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 8; + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); /* white text */ + draw_centered_text(renderer, rw, &y, "PRETEND THIS IS A VIDEO GAME."); + draw_centered_text(renderer, rw, &y, "THERE ARE SOUND EFFECTS AND BACKGROUND MUSIC."); + draw_centered_text(renderer, rw, &y, "THE EFFECTS ARE ON TRACKS TAGGED AS \"in-game\"."); + draw_centered_text(renderer, rw, &y, "PRESS SPACE TO PAUSE/UNPAUSE THE GAME."); + draw_centered_text(renderer, rw, &y, "THE IN-GAME SOUNDS WILL PAUSE."); + draw_centered_text(renderer, rw, &y, "THE MUSIC TRACK, NOT TAGGED, WILL NOT."); + + y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 8; + if (paused) { + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); /* red text */ + draw_centered_text(renderer, rw, &y, "[ CURRENTLY PAUSED ]"); + } else { + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); /* green text */ + draw_centered_text(renderer, rw, &y, "[ CURRENTLY UNPAUSED ]"); + } + + SDL_RenderPresent(renderer); + + return SDL_APP_CONTINUE; /* carry on with the program! */ +} + +/* This function runs once at shutdown. */ +void SDL_AppQuit(void *appstate, SDL_AppResult result) +{ + /* SDL will clean up the window/renderer for us, MIX_Quit() destroys any mixer objects we made. */ + MIX_Quit(); +} + Binary files old/SDL3_mixer-3.2.2/examples/advanced/01-tag-tracks/thumbnail.png and new/SDL3_mixer-3.2.4/examples/advanced/01-tag-tracks/thumbnail.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/examples/categories.txt new/SDL3_mixer-3.2.4/examples/categories.txt --- old/SDL3_mixer-3.2.2/examples/categories.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/SDL3_mixer-3.2.4/examples/categories.txt 2026-05-19 22:53:12.000000000 +0200 @@ -0,0 +1,8 @@ +# Blank lines and lines that start with '#' in this file are ignored. + +# Categories, by directory name, go in here, in the order they should be +# listed on the main page. If this file is missing, it'll assume any +# subdirectory is a category and sort them alphabetically. + +basics +advanced Binary files old/SDL3_mixer-3.2.2/examples/splash.wav and new/SDL3_mixer-3.2.4/examples/splash.wav differ Binary files old/SDL3_mixer-3.2.2/examples/spring.wav and new/SDL3_mixer-3.2.4/examples/spring.wav differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/include/SDL3_mixer/SDL_mixer.h new/SDL3_mixer-3.2.4/include/SDL3_mixer/SDL_mixer.h --- old/SDL3_mixer-3.2.2/include/SDL3_mixer/SDL_mixer.h 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/include/SDL3_mixer/SDL_mixer.h 2026-06-03 01:56:16.000000000 +0200 @@ -217,7 +217,7 @@ * * \since This macro is available since SDL_mixer 3.0.0. */ -#define SDL_MIXER_MICRO_VERSION 2 +#define SDL_MIXER_MICRO_VERSION 4 /** * This is the current version number macro of the SDL_mixer headers. @@ -747,7 +747,6 @@ * SDL_PropertiesID are discussed in * [SDL's documentation](https://wiki.libsdl.org/SDL3/CategoryProperties) * . - * * These are the supported properties: * * - `MIX_PROP_AUDIO_LOAD_IOSTREAM_POINTER`: a pointer to an SDL_IOStream to @@ -763,6 +762,11 @@ * metadata tags, like ID3 and APE tags. This can be used to speed up * loading _if the data definitely doesn't have these tags_. Some decoders * will fail if these tags are present when this property is true. + * - `MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN`: true to ignore metadata in + * the audio data specifying loop points. This will make a file decode from + * start to finish without looping, even if the file specified it should + * have. This audio can still be looped at playback time via MIX_Track loop + * settings, regardless of this setting. Default false. * - `MIX_PROP_AUDIO_DECODER_STRING`: the name of the decoder to use for this * data. Optional. If not specified, SDL_mixer will examine the data and * choose the best decoder. These names are the same returned from @@ -791,6 +795,7 @@ #define MIX_PROP_AUDIO_LOAD_PREDECODE_BOOLEAN "SDL_mixer.audio.load.predecode" #define MIX_PROP_AUDIO_LOAD_PREFERRED_MIXER_POINTER "SDL_mixer.audio.load.preferred_mixer" #define MIX_PROP_AUDIO_LOAD_SKIP_METADATA_TAGS_BOOLEAN "SDL_mixer.audio.load.skip_metadata_tags" +#define MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN "SDL_mixer.audio.load.ignore_loops" #define MIX_PROP_AUDIO_DECODER_STRING "SDL_mixer.audio.decoder" /** @@ -3244,8 +3249,9 @@ * * This function allows properties to be specified. This is intended to supply * file-specific settings, such as where to find SoundFonts for a MIDI file, - * etc. In most cases, the caller should pass a zero to specify no extra - * properties. + * etc. Most of the properties available to MIX_LoadAudioWithProperties() + * apply here, too. In most cases, the caller should pass a zero to specify no + * extra properties. * * If `closeio` is true, then `io` will be closed when this decoder is done * with it. If this function fails and `closeio` is true, then `io` will be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/SDL_mixer.c new/SDL3_mixer-3.2.4/src/SDL_mixer.c --- old/SDL3_mixer-3.2.2/src/SDL_mixer.c 2026-04-16 20:28:48.000000000 +0200 +++ new/SDL3_mixer-3.2.4/src/SDL_mixer.c 2026-06-02 23:39:50.000000000 +0200 @@ -242,6 +242,8 @@ static void ApplyFade(MIX_Track *track, int channels, float *pcm, int frames) { + SDL_assert(frames >= 0); + // !!! FIXME: this is probably pretty naive. if (track->fade_direction == 0) { @@ -412,6 +414,9 @@ const Sint64 newpos = (Sint64)(track->position + frames_read); if (newpos >= maxpos) { // we read past the end of the fade out or maxframes, we need to clamp. br -= (int)(((newpos - maxpos) * raw_channels) * sizeof(float)); + if (br < 0) { + br = 0; + } frames_read = br / (sizeof (float) * raw_channels); end_of_audio = true; } @@ -576,7 +581,7 @@ for (MIX_Track *track = group->tracks; track; track = next_track) { next_track = track->group_next; // this won't save you from a callback going totally rogue, but it'll deal with the current track leaving the group. - track->currently_mixing = true; + track->currently_inuse = true; const int to_be_read = (additional_amount / SDL_AUDIO_FRAMESIZE(mixer->spec)) * SDL_AUDIO_FRAMESIZE(track->output_spec); const int br = SDL_GetAudioStreamData(track->output_stream, getbuf, to_be_read); @@ -610,7 +615,7 @@ } } - track->currently_mixing = false; + track->currently_inuse = false; if (track->destroy_requested) { // callback asked to destroy the track while we were still using it. MIX_DestroyTrack(track); // actually kill it now. } @@ -720,14 +725,15 @@ } // actually shutting down now. - while (all_audiodecoders) { - MIX_DestroyAudioDecoder(all_audiodecoders); - } while (all_mixers) { MIX_DestroyMixer(all_mixers); } + while (all_audiodecoders) { + MIX_DestroyAudioDecoder(all_audiodecoders); + } + while (all_audios) { MIX_DestroyAudio(all_audios); } @@ -1515,7 +1521,7 @@ // handle the case where someone destroys a track during a mixer callback. :O // tracks are not currently reference-counted like MIX_Audio objects are, but // we'll catch this specific case for now. - if (track->currently_mixing) { + if (track->currently_inuse) { track->destroy_requested = true; UnlockMixer(mixer); return; @@ -2399,7 +2405,9 @@ if (track->internal_stream) { SDL_ClearAudioStream(track->internal_stream); // make sure we don't leave old data hanging around. } + track->currently_inuse = true; TrackStopped(track); + track->currently_inuse = false; } else { track->total_fade_frames = fadeOut; track->fade_frames = fadeOut; @@ -2408,6 +2416,10 @@ } } UnlockTrack(track); + + if (track->destroy_requested) { // callback asked to destroy the track while we were still touching it. + MIX_DestroyTrack(track); // actually kill it now. + } } bool MIX_StopTrack(MIX_Track *track, Sint64 fade_out_frames) @@ -2999,17 +3011,17 @@ MIX_Group *oldgroup = track->group; if (group != oldgroup) { if (oldgroup) { // remove from current group, if in one. + if (track->group_next) { + track->group_next->group_prev = track->group_prev; + } if (track->group_prev) { track->group_prev->group_next = track->group_next; - track->group_prev = NULL; } else { oldgroup->tracks = track->group_next; } - if (track->group_next) { - track->group_next->group_prev = track->group_prev; - } } + track->group_prev = NULL; track->group_next = group->tracks; if (group->tracks) { group->tracks->group_prev = track; @@ -3085,16 +3097,16 @@ if (!audiodecoder->audio) { SDL_free(audiodecoder); return NULL; - } - - if (!audiodecoder->audio->decoder->init_track(audiodecoder->audio->decoder_userdata, io, &audiodecoder->audio->spec, audiodecoder->audio->props, &audiodecoder->track_userdata)) { + } else if (!audiodecoder->audio->decoder->init_track(audiodecoder->audio->decoder_userdata, io, &audiodecoder->audio->spec, audiodecoder->audio->props, &audiodecoder->track_userdata)) { MIX_DestroyAudio(audiodecoder->audio); SDL_free(audiodecoder); return NULL; - } - - audiodecoder->stream = SDL_CreateAudioStream(&audiodecoder->audio->spec, &audiodecoder->audio->spec); - if (!audiodecoder->stream) { + } else if (!audiodecoder->audio->decoder->seek(audiodecoder->track_userdata, 0)) { + audiodecoder->audio->decoder->quit_track(audiodecoder->track_userdata); + MIX_DestroyAudio(audiodecoder->audio); + SDL_free(audiodecoder); + return NULL; + } else if ((audiodecoder->stream = SDL_CreateAudioStream(&audiodecoder->audio->spec, &audiodecoder->audio->spec)) == NULL) { audiodecoder->audio->decoder->quit_track(audiodecoder->track_userdata); MIX_DestroyAudio(audiodecoder->audio); SDL_free(audiodecoder); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/SDL_mixer_internal.h new/SDL3_mixer-3.2.4/src/SDL_mixer_internal.h --- old/SDL3_mixer-3.2.2/src/SDL_mixer_internal.h 2026-04-16 20:28:48.000000000 +0200 +++ new/SDL3_mixer-3.2.4/src/SDL_mixer_internal.h 2026-05-19 04:46:46.000000000 +0200 @@ -148,7 +148,7 @@ MIX_Audio *input_audio; // non-NULL if used with MIX_SetTrackAudioStream. Holds a reference. SDL_IOStream *io; // used for MIX_SetTrackAudio and MIX_SetTrackIOStream. Might be owned by us (SDL_IOFromConstMem of MIX_Audio::precache), or owned by the app. MIX_IoClamp ioclamp; // used for MIX_SetTrackAudio and MIX_SetTrackIOStream. - bool currently_mixing; // true when the mixer is running on this track. + bool currently_inuse; // true when we want to delay an app's MIX_DestroyTrack request (they destroyed it from a mixer callback). bool destroy_requested; // true if MIX_DestroyTrack called while the track is actively mixing. bool closeio; // true if we should close `io` when changing track data. bool halt_when_exhausted; // true if we should stop the track when input runs out. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/SDL_mixer_metadata_tags.c new/SDL3_mixer-3.2.4/src/SDL_mixer_metadata_tags.c --- old/SDL3_mixer-3.2.2/src/SDL_mixer_metadata_tags.c 2026-02-28 17:44:53.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/SDL_mixer_metadata_tags.c 2026-05-19 16:21:29.000000000 +0200 @@ -118,8 +118,10 @@ { if (!SDL_HasProperty(props, key)) { // in case there are multiple ID3v1 tags appended to a file, we'll take the last one, since we parse backwards from the end of file. char *src_buf = parse_id3v1_ansi_string(buffer, len); - if (src_buf && *src_buf) { - SDL_SetStringProperty(props, key, src_buf); + if (src_buf) { + if (*src_buf) { + SDL_SetStringProperty(props, key, src_buf); + } SDL_free(src_buf); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_drflac.c new/SDL3_mixer-3.2.4/src/decoder_drflac.c --- old/SDL3_mixer-3.2.2/src/decoder_drflac.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_drflac.c 2026-05-17 01:17:05.000000000 +0200 @@ -176,7 +176,8 @@ adata->framesize = SDL_AUDIO_FRAMESIZE(*spec); - if (adata->loop.end > (Sint64)decoder->totalPCMFrameCount) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); + if (ignore_loops || (adata->loop.end > (Sint64)decoder->totalPCMFrameCount)) { adata->loop.active = false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_flac.c new/SDL3_mixer-3.2.4/src/decoder_flac.c --- old/SDL3_mixer-3.2.2/src/decoder_flac.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_flac.c 2026-05-17 01:17:05.000000000 +0200 @@ -376,7 +376,8 @@ SDL_copyp(spec, &tdata.spec); - if (adata->loop.end > total_frames) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); + if (ignore_loops || (adata->loop.end > total_frames)) { adata->loop.active = false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_fluidsynth.c new/SDL3_mixer-3.2.4/src/decoder_fluidsynth.c --- old/SDL3_mixer-3.2.2/src/decoder_fluidsynth.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_fluidsynth.c 2026-06-01 19:19:34.000000000 +0200 @@ -50,6 +50,7 @@ MIX_LOADER_FUNCTION(true,int,fluid_player_get_total_ticks,(fluid_player_t *)) \ MIX_LOADER_FUNCTION(true,int,fluid_settings_setint,(fluid_settings_t*, const char*, int)) \ MIX_LOADER_FUNCTION(true,int,fluid_settings_setnum,(fluid_settings_t*, const char*, double)) \ + MIX_LOADER_FUNCTION(true,int,fluid_settings_setstr,(fluid_settings_t*, const char*, const char *)) \ MIX_LOADER_FUNCTION(true,int,fluid_settings_getnum,(fluid_settings_t*, const char*, double*)) \ MIX_LOADER_FUNCTION(true,int,fluid_sfloader_set_callbacks,(fluid_sfloader_t *,fluid_sfloader_callback_open_t,fluid_sfloader_callback_read_t,fluid_sfloader_callback_seek_t,fluid_sfloader_callback_tell_t,fluid_sfloader_callback_close_t)) \ MIX_LOADER_FUNCTION(true,void,fluid_synth_add_sfloader,(fluid_synth_t *, fluid_sfloader_t *)) \ @@ -129,10 +130,16 @@ } } - #ifdef SDL_PLATFORM_UNIX // this happens to be where Ubuntu stores a usable soundfont, at least on my laptop. Try it if nothing else worked out. - if (!sfio) { + #ifdef SDL_PLATFORM_UNIX + if (!sfio) { // this happens to be where Ubuntu stores a usable soundfont, at least on my laptop. Try it if nothing else worked out. sfio = SDL_IOFromFile("/usr/share/sounds/sf2/default-GM.sf2", "rb"); } + if (!sfio) { // Fedora is storing it here. + sfio = SDL_IOFromFile("/usr/share/soundfonts/default.sf2", "rb"); + } + if (!sfio) { // Fedora is _also_ storing it here. Both are symlinks to the same thing elsewhere, but try both in case one was an older path. + sfio = SDL_IOFromFile("/usr/share/sounds/sf2/default.sf2", "rb"); + } #endif // !!! FIXME: should we fail if there's no soundfont? It's not going to generate sound without one, unless there's a system-provided one in some cases...? @@ -253,6 +260,9 @@ case SDL_PROPERTY_TYPE_FLOAT: fluidsynth.fluid_settings_setnum(tdata->settings, name, (double) SDL_GetFloatProperty(props, name, 0.0f)); break; + case SDL_PROPERTY_TYPE_STRING: + fluidsynth.fluid_settings_setstr(tdata->settings, name, SDL_GetStringProperty(props, name, "")); + break; default: break; // oh well. } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_opus.c new/SDL3_mixer-3.2.4/src/decoder_opus.c --- old/SDL3_mixer-3.2.2/src/decoder_opus.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_opus.c 2026-05-17 01:17:05.000000000 +0200 @@ -179,7 +179,8 @@ opus.op_raw_seek(of, 0); // !!! FIXME: it's not clear if this seek is necessary, but https://stackoverflow.com/a/72482773 suggests it might be, at least on older libvorbisfile releases... const Sint64 full_length = (Sint64) opus.op_pcm_total(of, -1); - if (adata->loop.end > full_length) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); + if (ignore_loops || (adata->loop.end > full_length)) { adata->loop.active = false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_voc.c new/SDL3_mixer-3.2.4/src/decoder_voc.c --- old/SDL3_mixer-3.2.2/src/decoder_voc.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_voc.c 2026-05-17 01:17:05.000000000 +0200 @@ -106,6 +106,7 @@ // this runs during VOC_audio_init to walk the whole .VOC for metadata and sanity checks. static bool ParseVocFile(SDL_IOStream *io, VOC_AudioData *adata, SDL_PropertiesID props, SDL_AudioSpec *spec, Sint64 *duration_frames) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); Sint64 total_frames = 0; VOC_Block *loop_start = NULL; int loop_start_loop_count = 0; @@ -255,6 +256,10 @@ } case VOC_LOOP: { + if (ignore_loops) { + break; // technically this can make a file with bogus loops load where it wouldn't otherwise, but good enough. + } + Uint16 iterations = 0; // !!! FIXME: can LOOP/LOOPEND sections nest? https://moddingwiki.shikadi.net/wiki/VOC_Format suggests no, saying LOOPEND goes back to _most recent_ LOOP start. @@ -286,6 +291,10 @@ } case VOC_LOOPEND: { + if (ignore_loops) { + break; // technically this can make a file with bogus loops load where it wouldn't otherwise, but good enough. + } + if (!loop_start) { return SDL_SetError("VOC has a LOOPEND without a matching LOOP"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_vorbis.c new/SDL3_mixer-3.2.4/src/decoder_vorbis.c --- old/SDL3_mixer-3.2.2/src/decoder_vorbis.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_vorbis.c 2026-05-19 16:46:25.000000000 +0200 @@ -159,8 +159,20 @@ static bool SDLCALL VORBIS_init_audio(SDL_IOStream *io, SDL_AudioSpec *spec, SDL_PropertiesID props, Sint64 *duration_frames, void **audio_userdata) { + Uint8 buffer[17]; + if (SDL_ReadIO(io, buffer, sizeof (buffer)) != sizeof (buffer)) { + return false; + } else if (SDL_memcmp(buffer, "Extended Module: ", 17) == 0) { // this is an XM file that _might_ be OXM and we would incorrectly claim it. Drop out now. + return SDL_SetError("Not an Ogg Vorbis audio stream"); + } + + // Go back and let ov_test_callbacks() take a run at it, too. + if (SDL_SeekIO(io, 0, SDL_IO_SEEK_SET) < 0) { + return false; + } + // just load the bare minimum from the IOStream to verify it's an Ogg Vorbis file. - // !!! FIXME: is ov_open_callbacks going to return more slowly if this isn't an Opus file? It's probably better to just do the full open. + // !!! FIXME: is ov_open_callbacks going to return more slowly if this isn't a Vorbis file? It's probably better to just do the full open. OggVorbis_File vf; if (vorbis.ov_test_callbacks(io, &vf, NULL, 0, VORBIS_IoCallbacks) < 0) { return SDL_SetError("Not an Ogg Vorbis audio stream"); @@ -205,7 +217,8 @@ vorbis.ov_raw_seek(&vf, 0); // !!! FIXME: it's not clear if this seek is necessary, but https://stackoverflow.com/a/72482773 suggests it might be, at least on older libvorbisfile releases... const Sint64 full_length = (Sint64) vorbis.ov_pcm_total(&vf, -1); - if (adata->loop.end > full_length) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); + if (ignore_loops || (adata->loop.end > full_length)) { adata->loop.active = false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/decoder_wav.c new/SDL3_mixer-3.2.4/src/decoder_wav.c --- old/SDL3_mixer-3.2.2/src/decoder_wav.c 2026-03-10 22:58:33.000000000 +0100 +++ new/SDL3_mixer-3.2.4/src/decoder_wav.c 2026-05-17 01:17:05.000000000 +0200 @@ -1242,6 +1242,7 @@ static bool WAV_init_audio_internal(WAV_AudioData *adata, SDL_IOStream *io, SDL_AudioSpec *spec, SDL_PropertiesID props) { + const bool ignore_loops = SDL_GetBooleanProperty(props, MIX_PROP_AUDIO_LOAD_IGNORE_LOOPS_BOOLEAN, false); Sint64 flen = SDL_GetIOSize(io); bool found_FMT = false; bool found_DATA = false; @@ -1299,7 +1300,9 @@ chunk_okay = ParseDATA(adata, io, chunk_length); break; case SMPL: - chunk_okay = ParseSMPL(adata, io, chunk_length); + if (!ignore_loops) { + chunk_okay = ParseSMPL(adata, io, chunk_length); + } break; case LIST: chunk_okay = ParseLIST(adata, io, props, chunk_length); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/src/version.rc new/SDL3_mixer-3.2.4/src/version.rc --- old/SDL3_mixer-3.2.2/src/version.rc 2026-05-12 00:31:34.000000000 +0200 +++ new/SDL3_mixer-3.2.4/src/version.rc 2026-06-03 01:56:16.000000000 +0200 @@ -9,8 +9,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,2,2,0 - PRODUCTVERSION 3,2,2,0 + FILEVERSION 3,2,4,0 + PRODUCTVERSION 3,2,4,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -23,12 +23,12 @@ BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "SDL_mixer\0" - VALUE "FileVersion", "3, 2, 2, 0\0" + VALUE "FileVersion", "3, 2, 4, 0\0" VALUE "InternalName", "SDL_mixer\0" VALUE "LegalCopyright", "Copyright (C) 2026 Sam Lantinga\0" VALUE "OriginalFilename", "SDL3_mixer.dll\0" VALUE "ProductName", "Simple DirectMedia Layer\0" - VALUE "ProductVersion", "3, 2, 2, 0\0" + VALUE "ProductVersion", "3, 2, 4, 0\0" END END BLOCK "VarFileInfo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SDL3_mixer-3.2.2/test/testaudiodecoder.c new/SDL3_mixer-3.2.4/test/testaudiodecoder.c --- old/SDL3_mixer-3.2.2/test/testaudiodecoder.c 2026-03-05 14:54:35.000000000 +0100 +++ new/SDL3_mixer-3.2.4/test/testaudiodecoder.c 2026-06-02 20:35:18.000000000 +0200 @@ -24,22 +24,20 @@ #include <SDL3/SDL_main.h> #include "SDL3_mixer/SDL_mixer.h" -static bool done = false; +static SDL_AudioStream *stream = NULL; +static SDL_AtomicInt done; /* the device callback happens in another thread, so use an atomic int for this flag. */ static SDL_AudioSpec spec; static void SDLCALL AudioDeviceCallback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount) { MIX_AudioDecoder *audiodecoder = (MIX_AudioDecoder *) userdata; - if (!additional_amount) { - return; - } - Uint8 buffer[1024]; + while (additional_amount > 0) { const int needed = SDL_min((int)sizeof(buffer), additional_amount); const int br = MIX_DecodeAudio(audiodecoder, buffer, needed, &spec); if (br <= 0) { - done = true; + SDL_SetAtomicInt(&done, 1); break; } @@ -74,7 +72,7 @@ return SDL_APP_FAILURE; } - SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL, AudioDeviceCallback, audiodecoder); + stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL, AudioDeviceCallback, audiodecoder); if (!stream) { SDL_Log("Failed to open audio device: %s", SDL_GetError()); return SDL_APP_FAILURE; @@ -84,6 +82,8 @@ SDL_ResumeAudioStreamDevice(stream); + SDL_SetAtomicInt(&done, 0); + return SDL_APP_CONTINUE; } @@ -97,12 +97,15 @@ SDL_AppResult SDL_AppIterate(void *appstate) { - return done ? SDL_APP_SUCCESS : SDL_APP_CONTINUE; + return SDL_GetAtomicInt(&done) ? SDL_APP_SUCCESS : SDL_APP_CONTINUE; } void SDL_AppQuit(void *appstate, SDL_AppResult result) { - // SDL will clean up the audio device for us. + // SDL and MIX_Quit will normally clean up everything we used here, but + // we need to make sure the callback doesn't fire while MIX_Quit is + // destroying things, so we destroy the audio stream manually. + SDL_DestroyAudioStream(stream); MIX_Quit(); // SDL_mixer will clean up the audiodecoder. } ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.HfEQgw/_old 2026-10-31 23:15:02.414559532 +0100 +++ /var/tmp/diff_new_pack.HfEQgw/_new 2026-10-31 23:15:02.420559780 +0100 @@ -1,5 +1,5 @@ -mtime: 1778577151 -commit: 446562d8d6efce73e6b6aa3d347c6a451e6951ddf9b04c5338be397b1bc2fb42 +mtime: 1793465846 +commit: 1697888247f83f951e49a730843df44dc07f58dfd8e848626d50efb42241500d url: https://src.opensuse.org/jengelh/SDL3_mixer revision: master ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-10-31 17:57:26.000000000 +0100 @@ -0,0 +1 @@ +.osc
