Skip to content

Commit 2326c73

Browse files
committed
examples: Added basic examples!
Reference Issue #807.
1 parent d85c04c commit 2326c73

File tree

24 files changed

+2036
-0
lines changed

24 files changed

+2036
-0
lines changed

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ endif()
117117

118118
option(SDLMIXER_TESTS "Build unit tests?" OFF)
119119
option(SDLMIXER_TESTS_INSTALL "Install unit tests?" OFF)
120+
option(SDLMIXER_EXAMPLES "Build the examples directory" OFF)
120121

121122
# These are implemented in SDL_mixer itself, not using a third-party library.
122123
option(SDLMIXER_AIFF "Enable AIFF audio" ON)
@@ -1203,6 +1204,13 @@ if(SDLMIXER_TESTS)
12031204
add_subdirectory(test)
12041205
endif()
12051206

1207+
##### Examples subproject (must appear after the install/uninstall targets) #####
1208+
1209+
if(SDLMIXER_EXAMPLES)
1210+
set(HAVE_EXAMPLES ON)
1211+
add_subdirectory(examples)
1212+
endif()
1213+
12061214
set(available_deps)
12071215
set(unavailable_deps)
12081216
foreach(dep IN LISTS SDLMIXER_BACKENDS)

examples/CMakeLists.txt

Lines changed: 345 additions & 0 deletions
Large diffs are not rendered by default.

examples/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Examples
2+
3+
## What is this?
4+
5+
In here are a collection of standalone SDL_mixer application examples. Unless
6+
otherwise stated, they should work on all supported platforms out of the box.
7+
If they don't [please file a bug to let us know](https://github.com/libsdl-org/SDL_mixer/issues/new).
8+
9+
10+
## What is this SDL_AppIterate thing?
11+
12+
SDL can optionally build apps as a collection of callbacks instead of the
13+
usual program structure that starts and ends in a function called `main`.
14+
The examples use this format for two reasons.
15+
16+
First, it allows the examples to work when built as web applications without
17+
a pile of ugly `#ifdef`s, and all of these examples are published on the web
18+
at [examples.libsdl.org](https://examples.libsdl.org/), so you can easily see
19+
them in action.
20+
21+
Second, it's example code! The callbacks let us cleanly break the program up
22+
into the four logical pieces most apps care about:
23+
24+
- Program startup
25+
- Event handling
26+
- What the program actually does in a single frame
27+
- Program shutdown
28+
29+
A detailed technical explanation of these callbacks is in
30+
docs/README-main-functions.md (or view that page on the web on
31+
[the wiki](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)).
32+
33+
34+
## I would like to build and run these examples myself.
35+
36+
When you build SDL with CMake, you can add `-DSDLMIXER_EXAMPLES=On` to the
37+
CMake command line. When you build SDL_mixer, these examples will be built
38+
with it.
39+
40+
But most of these can just be built as a single .c file, as long as you point
41+
your compiler at SDL3 and SDL3_mixer's headers and link against both of those
42+
libraries.
43+
44+
45+
## What is the license on the example code? Can I paste this into my project?
46+
47+
All code in the examples directory is considered public domain! You can do
48+
anything you like with it, including copy/paste it into your closed-source
49+
project, sell it, and pretend you wrote it yourself. We do not require you to
50+
give us credit for this code (but we always appreciate if you do!).
51+
52+
This is only true for the examples directory. The rest of SDL and SDL_mixer
53+
fall under the [zlib license](https://github.com/libsdl-org/SDL_mixer/blob/main/LICENSE.txt).
54+
55+
56+
## What is template.html and highlight-plugin.lua in this directory?
57+
58+
This is what [examples.libsdl.org](https://examples.libsdl.org/) uses when
59+
generating the web versions of these example programs. You can ignore this,
60+
unless you are improving it, in which case we definitely would love to hear
61+
from you!
62+
63+
64+
## What is template.c in this directory?
65+
66+
If writing new examples, this is the skeleton code we start from, to keep
67+
everything consistent. You can ignore it.
68+
69+
70+
## License for the audio files:
71+
72+
- music.mp3:
73+
Arcade Music Loop.wav by joshuaempyre ( https://www.empyreanma.com/welcome )
74+
(We converted this to MP3 format.)
75+
Original: https://freesound.org/s/251461/
76+
License: https://creativecommons.org/licenses/by/3.0/
77+
78+
- sword.wav:
79+
sword04.wav by Erdie
80+
Original: https://freesound.org/s/27858/
81+
License: https://creativecommons.org/licenses/by/3.0/
82+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This example code creates a mixer, loads a single sound, and plays it once.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* This example code creates a mixer, loads a single sound, and plays it once.
3+
*
4+
* This code is public domain. Feel free to use it for any purpose!
5+
*/
6+
7+
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
8+
#include <SDL3/SDL.h>
9+
#include <SDL3/SDL_main.h>
10+
#include <SDL3_mixer/SDL_mixer.h>
11+
12+
/* We will use this renderer to draw into this window every frame. */
13+
static SDL_Window *window = NULL;
14+
static SDL_Renderer *renderer = NULL;
15+
static MIX_Mixer *mixer = NULL;
16+
static MIX_Track *track = NULL;
17+
18+
/* This function runs once at startup. */
19+
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
20+
{
21+
char *path = NULL;
22+
MIX_Audio *audio = NULL;
23+
24+
SDL_SetAppMetadata("Example Load And Play", "1.0", "com.example.load-and-play");
25+
26+
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
27+
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
28+
29+
/* we don't need video, but we'll make a window for smooth operation. */
30+
if (!SDL_Init(SDL_INIT_VIDEO)) {
31+
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
32+
return SDL_APP_FAILURE;
33+
}
34+
35+
if (!SDL_CreateWindowAndRenderer("examples/basic/load-and-play", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
36+
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
37+
return SDL_APP_FAILURE;
38+
}
39+
40+
if (!MIX_Init()) {
41+
SDL_Log("Couldn't init SDL_mixer library: %s", SDL_GetError());
42+
return SDL_APP_FAILURE;
43+
}
44+
45+
/* Create a mixer on the default audio device. Don't care about the specific audio format. */
46+
mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
47+
if (!mixer) {
48+
SDL_Log("Couldn't create mixer on default device: %s", SDL_GetError());
49+
return SDL_APP_FAILURE;
50+
}
51+
52+
/* load a sound file */
53+
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* allocate a string of the full file path */
54+
audio = MIX_LoadAudio(mixer, path, false);
55+
if (!audio) {
56+
SDL_Log("Couldn't load %s: %s", path, SDL_GetError());
57+
SDL_free(path);
58+
return SDL_APP_FAILURE;
59+
}
60+
61+
SDL_free(path); /* done with this, the file is loaded. */
62+
63+
/* we need a track on the mixer to play the audio. Each track has audio assigned to it, and
64+
all playing tracks are mixed together for the final output. */
65+
66+
track = MIX_CreateTrack(mixer);
67+
if (!track) {
68+
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
69+
return SDL_APP_FAILURE;
70+
}
71+
MIX_SetTrackAudio(track, audio);
72+
73+
/* start the audio playing! */
74+
MIX_PlayTrack(track, 0); /* no extra options this time, so a zero for the second argument. */
75+
76+
/* we don't save `audio`; SDL_mixer will clean it up for us during MIX_Quit(). */
77+
78+
return SDL_APP_CONTINUE; /* carry on with the program! */
79+
}
80+
81+
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
82+
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
83+
{
84+
if (event->type == SDL_EVENT_QUIT) {
85+
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
86+
}
87+
return SDL_APP_CONTINUE; /* carry on with the program! */
88+
}
89+
90+
/* This function runs once per frame, and is the heart of the program. */
91+
SDL_AppResult SDL_AppIterate(void *appstate)
92+
{
93+
/* draw a blank video frame to keep the OS happy */
94+
SDL_RenderClear(renderer);
95+
SDL_RenderPresent(renderer);
96+
97+
/* when the track has finished playing, end the program. */
98+
if (!MIX_TrackPlaying(track)) {
99+
return SDL_APP_SUCCESS;
100+
}
101+
102+
return SDL_APP_CONTINUE; /* carry on with the program! */
103+
}
104+
105+
/* This function runs once at shutdown. */
106+
void SDL_AppQuit(void *appstate, SDL_AppResult result)
107+
{
108+
/* SDL will clean up the window/renderer for us, MIX_Quit() destroys any mixer objects we made. */
109+
MIX_Quit();
110+
}
111+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This example code creates a mixer, loads a single sound, and plays it, with
2+
several playback options (fade-in, loop, etc).
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* This example code creates a mixer, loads a single sound, and plays it, with
3+
* several playback options (fade-in, loop, etc).
4+
*
5+
* This code is public domain. Feel free to use it for any purpose!
6+
*/
7+
8+
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
9+
#include <SDL3/SDL.h>
10+
#include <SDL3/SDL_main.h>
11+
#include <SDL3_mixer/SDL_mixer.h>
12+
13+
/* We will use this renderer to draw into this window every frame. */
14+
static SDL_Window *window = NULL;
15+
static SDL_Renderer *renderer = NULL;
16+
static MIX_Mixer *mixer = NULL;
17+
static MIX_Track *track = NULL;
18+
19+
/* This function runs once at startup. */
20+
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
21+
{
22+
char *path = NULL;
23+
MIX_Audio *audio = NULL;
24+
SDL_PropertiesID options = 0;
25+
26+
SDL_SetAppMetadata("Example Play With Options", "1.0", "com.example.play-with-options");
27+
28+
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
29+
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
30+
31+
/* we don't need video, but we'll make a window for smooth operation. */
32+
if (!SDL_Init(SDL_INIT_VIDEO)) {
33+
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
34+
return SDL_APP_FAILURE;
35+
}
36+
37+
if (!SDL_CreateWindowAndRenderer("examples/basic/play-with-options", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
38+
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
39+
return SDL_APP_FAILURE;
40+
}
41+
42+
if (!MIX_Init()) {
43+
SDL_Log("Couldn't init SDL_mixer library: %s", SDL_GetError());
44+
return SDL_APP_FAILURE;
45+
}
46+
47+
/* Create a mixer on the default audio device. Don't care about the specific audio format. */
48+
mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
49+
if (!mixer) {
50+
SDL_Log("Couldn't create mixer on default device: %s", SDL_GetError());
51+
return SDL_APP_FAILURE;
52+
}
53+
54+
/* load a sound file */
55+
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* allocate a string of the full file path */
56+
audio = MIX_LoadAudio(mixer, path, false);
57+
if (!audio) {
58+
SDL_Log("Couldn't load %s: %s", path, SDL_GetError());
59+
SDL_free(path);
60+
return SDL_APP_FAILURE;
61+
}
62+
63+
SDL_free(path); /* done with this, the file is loaded. */
64+
65+
/* we need a track on the mixer to play the audio. Each track has audio assigned to it, and
66+
all playing tracks are mixed together for the final output. */
67+
68+
track = MIX_CreateTrack(mixer);
69+
if (!track) {
70+
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
71+
return SDL_APP_FAILURE;
72+
}
73+
MIX_SetTrackAudio(track, audio);
74+
75+
/* start the audio playing! */
76+
options = SDL_CreateProperties();
77+
if (!options) {
78+
SDL_Log("Couldn't create play options: %s", SDL_GetError());
79+
return SDL_APP_FAILURE;
80+
}
81+
82+
/* note these all use MILLISECONDS, since the track is generic, but you can use equivalent FRAMES properties, for frame-perfect mixing. */
83+
SDL_SetNumberProperty(options, MIX_PROP_PLAY_START_MILLISECOND_NUMBER, 1000); /* start the first loop 1 second into the audio. */
84+
SDL_SetNumberProperty(options, MIX_PROP_PLAY_MAX_MILLISECONDS_NUMBER, 10000); /* play at most 10 seconds of audio before ending/looping (since we started 1000 in, this will be the eleventh second). */
85+
SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, 2); /* loop 2 times, 3rd time through doesn't loop. */
86+
SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOP_START_MILLISECOND_NUMBER, 2000); /* when looping, start again here instead of the start of the track. */
87+
SDL_SetNumberProperty(options, MIX_PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER, 5000); /* fade-in the first loop over five seconds. No fade on the loops, unless the initial fade is still in progress! */
88+
MIX_PlayTrack(track, options);
89+
SDL_DestroyProperties(options); /* MIX_PlayTrack makes a copy of the options, so this can go away. */
90+
91+
/* we don't save `audio`; SDL_mixer will clean it up for us during MIX_Quit(). */
92+
93+
return SDL_APP_CONTINUE; /* carry on with the program! */
94+
}
95+
96+
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
97+
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
98+
{
99+
if (event->type == SDL_EVENT_QUIT) {
100+
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
101+
}
102+
return SDL_APP_CONTINUE; /* carry on with the program! */
103+
}
104+
105+
/* This function runs once per frame, and is the heart of the program. */
106+
SDL_AppResult SDL_AppIterate(void *appstate)
107+
{
108+
/* draw a blank video frame to keep the OS happy */
109+
SDL_RenderClear(renderer);
110+
SDL_RenderPresent(renderer);
111+
112+
/* when the track has finished playing, end the program. */
113+
if (!MIX_TrackPlaying(track)) {
114+
return SDL_APP_SUCCESS;
115+
}
116+
117+
return SDL_APP_CONTINUE; /* carry on with the program! */
118+
}
119+
120+
/* This function runs once at shutdown. */
121+
void SDL_AppQuit(void *appstate, SDL_AppResult result)
122+
{
123+
/* SDL will clean up the window/renderer for us, MIX_Quit() destroys any mixer objects we made. */
124+
MIX_Quit();
125+
}
126+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This example code creates a mixer, loads two sounds, and mixes them.

0 commit comments

Comments
 (0)