From 47c6215ce883dfe3e6f8b11d9b717cd665892c60 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 19 May 2026 15:14:45 -0400
Subject: [PATCH] examples/advanced/01-tag-tracks: Added.
---
examples/CMakeLists.txt | 1 +
examples/README.md | 10 +
examples/advanced/01-tag-tracks/README.txt | 7 +
.../advanced/01-tag-tracks/onmouseover.webp | Bin 0 -> 9546 bytes
examples/advanced/01-tag-tracks/tag-tracks.c | 199 ++++++++++++++++++
examples/advanced/01-tag-tracks/thumbnail.png | Bin 0 -> 1547 bytes
examples/splash.wav | Bin 0 -> 22374 bytes
examples/spring.wav | Bin 0 -> 234642 bytes
8 files changed, 217 insertions(+)
create mode 100644 examples/advanced/01-tag-tracks/README.txt
create mode 100644 examples/advanced/01-tag-tracks/onmouseover.webp
create mode 100644 examples/advanced/01-tag-tracks/tag-tracks.c
create mode 100644 examples/advanced/01-tag-tracks/thumbnail.png
create mode 100644 examples/splash.wav
create mode 100644 examples/spring.wav
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9f877db6..2fade80c 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -132,6 +132,7 @@ add_sdlmixer_example_executable(basics-play-multiple-sounds SOURCES basics/03-pl
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 --git a/examples/README.md b/examples/README.md
index 7f55abe3..de71ee95 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -80,3 +80,13 @@ everything consistent. You can ignore it.
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 --git a/examples/advanced/01-tag-tracks/README.txt b/examples/advanced/01-tag-tracks/README.txt
new file mode 100644
index 00000000..32b9c663
--- /dev/null
+++ b/examples/advanced/01-tag-tracks/README.txt
@@ -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!)
diff --git a/examples/advanced/01-tag-tracks/onmouseover.webp b/examples/advanced/01-tag-tracks/onmouseover.webp
new file mode 100644
index 0000000000000000000000000000000000000000..d30cd8050bd77cfc313577d59739c6f1d72bb8d5
GIT binary patch
literal 9546
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
literal 0
HcmV?d00001
diff --git a/examples/advanced/01-tag-tracks/tag-tracks.c b/examples/advanced/01-tag-tracks/tag-tracks.c
new file mode 100644
index 00000000..969cf0ae
--- /dev/null
+++ b/examples/advanced/01-tag-tracks/tag-tracks.c
@@ -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();
+}
+
diff --git a/examples/advanced/01-tag-tracks/thumbnail.png b/examples/advanced/01-tag-tracks/thumbnail.png
new file mode 100644
index 0000000000000000000000000000000000000000..9db7bb5a9e63426f4e78e1f585ac72da0a3972fc
GIT binary patch
literal 1547
zcma)6Yd8}M7@pzGrE<t6%yuFcrKDVvZ3!_+v>2AVmE2mXP-Z46<#I@r)1f+H5^I*p
zaer#LW@0WgGLvm=(j;jsJ37C5&ad<RdB5*{pYMIYUtgBDm)k})12q5uuo30%avT5v
zrU3v7T%h7Q<KDI}aUE2>Jx{o<qg*Zr$N^kl>bj=ff^u;>ku<)*d6Ubt*Uk(ZGCp4A
zSC3zzWzSpGRkh^bmxaMGnxECq-APClkDV}ildb)rJQd11m|iXO<P{>to+|5>KbJfn
zwbUhrF>oUbg|Cwf6W1Kw4JT=RM<5ptY;+3bSL$pTmWWIs3EAcul)T5L+boZk)w@q_
zMmx?6_T(n?OI9a<r_Doy-{%zDD8Ub|J#`Hv4O(;yQ1l|Opi;-)EZLnjlhPB+HJ;7(
z<0hfGV><Q-N;?_G%nj{XP=ScGMW2?wt9TIMj8zt}T*E`5Gm<c%9!nUIg-wBGE$YgW
zMts5NS!h2>`2Ku547GSXh!LP(_~jc=DGg~WFE5ZgZV^^*z|nFvN<cK^FWp(CpcpUk
zHg!H(h81ZOCiDm6m80L?_OXe6WO$l*RJyp0d3EU?@)4b7iz7ZCiI4g7BA2$EiX|B+
zJX%BB_Df^vCez8@2%6jYQYf3^i;8rY#>ZHiB=txWGmX?)Xgf0v;F?1qsTA}%W6mTl
z`I&gsx!mW_R9sDc`?*Enf=Wfy_nr_9&i+<-dMT)P?Zv8QA2o(hka+z$k<?kUc#&W=
zj3Dd#1hO3cSKMM+K08f`kYobBVYNK@Y&W~LcrJ{Lkqp*`ci*_IGwL|jy1@3`iR1+K
zCN$pcz7F{4#^|_0rMS5Kk@gnloJX9|RR-nc(~j-!>iQBVym2MxH3YQCKtPNB(k`!w
z{x-yHMR;gG@76ckL9~o&0K)qwZV^n4Uo$FRM1Sj@Jzb!ro0D&wCVK#hwSY+@`}@y*
z3>NRu+*2xUI+#O@z;ON5zzuR112N$JA_3g2Cv!9~I}qi-;Y*k>H5=`o#s;7sXY`cd
zu<R!7Up*S?$uX}b;8jf30-?{Hn{>!-(nuqGW%KM0=TA{W3^f(Kv}#vm{&K4Zo5CBP
z`4+BvrqDU0STVIT1iQEGZw0PXBc5vG1T}Y*uvKnn769V%?LpYD^YjLnuiR@9P%Po(
za6X;ygi6O*5AZ{BJ1VorFC8h&3$kCq@nQq4Mwjhm8PWGP6#8!#ycDBJ7n^1uf_8&t
z){>|I{KR00<pACE%bazkmoj~!XgjnSFYbK>>b(T2I@1VG9~s)@kS`P@aX#d7BlL0!
z_mV_cu@JDBbL|d}u<NVRG=0*vr*jv06vsQSBeGbrou-tT$><I5_m7?6(kHb{)jI(I
z=C!Kq-)v{8xMq5W813OOzH{2l9N~5}(YcGtOo~%w9~RjQg+}oOyaZOP@z!}hznz{D
zOS>LKveZXZwL2)M^cXZozm7T5RkGz6mPD{lS<+-BcN9s+wd&qL_#I|Bvd61^z&tx2
zIY+B*rQ`m>rp_@K1IBn-@}bA~q;+sxMspB@-8vN4{X19%@cv-aS8|iWvl=bXF)Qn$
zln~1gw6HkI0C;Q)Fy@z4f9+HUC2z5sL0Eob2`LGe8Ui>LRHK=@;#?|cnAh4q&U?83
zS(^f0$X7L0<a2<X$3uHF>lw~@p+v<{tSQ~3UT2J=`-N=<Z*GrRr`kMX<(0n6hA`=H
z_+&hL0P9G8Rien*nD*U5;$8c8J;_-}d)SbK+LbL&K>qxWe)OS<WrAPdjb3b-pQ-a&
z0*}~qK?(9*lrn*6_VP;6ZmYR6)Dxex#dC{o700=*mr_bGHOp}YaAYusYv4f=h?XJI
zq*0W5@u8O&N-K)>R;%(pF>mRTVF^LRU_^cEXEdF76$m5T$5?(`fcrz6J*O>pBS(s%
z9U~wNoPjpS58nR1gb-pRzMDpIgVp|&fXT$+YX2*|YD)NjZ~gzXd>DDxZr>U+eeT(h
OC6ud|OYNc1^nU<Fpy+1+
literal 0
HcmV?d00001
diff --git a/examples/splash.wav b/examples/splash.wav
new file mode 100644
index 0000000000000000000000000000000000000000..52a09c204dc6511dace5f19f019cf3816e71e459
GIT binary patch
literal 22374
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
(Patch may be truncated, please check the link at the top of this post.)