update SDL_mixer to SDL3_mixer 3.2.0

This commit is contained in:
Sven Balzer
2026-04-02 16:52:07 +02:00
parent 05b19704f8
commit 8a5caf5c0d
1202 changed files with 366156 additions and 152445 deletions
+196
View File
@@ -0,0 +1,196 @@
#
# CMake script for building the SDL examples
#
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
include(CheckIncludeFile)
include(CheckStructHasMember)
include(CMakePushCheckState)
set(SDLMIXER_EXAMPLE_EXECUTABLES)
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(example_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
endif()
else()
set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(NOT CMAKE_VERSION VERSION_LESS 3.20)
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
set(example_bin_dir "${example_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>")
endif()
file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.mp3 ${CMAKE_CURRENT_SOURCE_DIR}/*.wav)
set(RESOURCE_FILE_NAMES)
set(RESOURCE_FILES_BINDIR)
foreach(resource_file IN LISTS RESOURCE_FILES)
get_filename_component(res_file_name ${resource_file} NAME)
list(APPEND RESOURCE_FILE_NAMES "${res_file_name}")
set(resource_file_bindir "${example_bin_dir}/${res_file_name}")
add_custom_command(OUTPUT "${resource_file_bindir}"
COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}"
DEPENDS "${resource_file}"
)
list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}")
endforeach()
add_custom_target(copy-sdlmixer-example-resources
DEPENDS "${RESOURCE_FILES_BINDIR}"
)
set(SDLMIXER_EXAMPLE_EXECUTABLES)
macro(add_sdlmixer_example_executable TARGET)
cmake_parse_arguments(AST "BUILD_DEPENDENT" "" "SOURCES;DATAFILES" ${ARGN})
if(AST_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}")
endif()
if(NOT AST_SOURCES)
message(FATAL_ERROR "add_sdlmixer_example_executable needs at least one source")
endif()
if(ANDROID)
add_library(${TARGET} SHARED ${AST_SOURCES} ${AST_DATAFILES})
else()
add_executable(${TARGET} ${AST_SOURCES} ${AST_DATAFILES})
endif()
target_compile_definitions(${TARGET}
PRIVATE
$<TARGET_PROPERTY:${sdl3_mixer_target_name},COMPILE_DEFINITIONS>
)
sdl_add_warning_options(${TARGET} WARNING_AS_ERROR ${SDLMIXER_WERROR})
target_link_libraries(${TARGET} PRIVATE SDL3_mixer::SDL3_mixer SDL3::SDL3)
list(APPEND SDLMIXER_EXAMPLE_EXECUTABLES ${TARGET})
if(AST_DATAFILES)
if(PSP OR PS2)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E make_directory $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${AST_DATAFILES} $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
elseif(NOT APPLE AND NOT N3DS)
add_dependencies(${TARGET} copy-sdlmixer-example-resources)
endif()
if(EMSCRIPTEN)
foreach(res IN LISTS AST_DATAFILES)
get_filename_component(res_name "${res}" NAME)
target_link_options(${TARGET} PRIVATE "SHELL:--embed-file ${res}@${res_name}")
endforeach()
endif()
set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${AST_DATAFILES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>")
endif()
if(APPLE)
# Set Apple App ID / Bundle ID. This is needed to launch apps on some Apple
# platforms (iOS, for example).
set_target_properties(${TARGET} PROPERTIES
RESOURCES "${AST_DATAFILES}"
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${TARGET}"
MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
)
set_property(SOURCE ${AST_DATAFILES} PROPERTY MACOSX_PACKAGE_LOCATION "Resources")
elseif(WINDOWS)
# CET support was added in VS 16.7
if(MSVC_VERSION GREATER 1926 AND CMAKE_GENERATOR_PLATFORM MATCHES "Win32|x64")
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -CETCOMPAT")
endif()
elseif(EMSCRIPTEN)
set_property(TARGET ${TARGET} PROPERTY SUFFIX ".html")
target_link_options(${TARGET} PRIVATE -sALLOW_MEMORY_GROWTH=1)
elseif(N3DS)
set(ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/romfs/${TARGET}")
file(MAKE_DIRECTORY "${ROMFS_DIR}")
file(COPY ${AST_DATAFILES} DESTINATION "${ROMFS_DIR}")
ctr_generate_smdh("${TARGET}.smdh"
NAME "SDL-${TARGET}"
DESCRIPTION "SDL3 example application"
AUTHOR "SDL3 Contributors"
ICON "${CMAKE_CURRENT_SOURCE_DIR}/../test/n3ds/logo48x48.png"
)
ctr_create_3dsx(
${TARGET}
ROMFS "${ROMFS_DIR}"
SMDH "${TARGET}.smdh"
)
elseif(NGAGE)
string(MD5 TARGET_MD5 "${TARGET}")
string(SUBSTRING "${TARGET_MD5}" 0 8 TARGET_MD5_8)
target_link_options(${TARGET} PRIVATE "SHELL:-s UID3=0x${TARGET_MD5_8}")
endif()
endmacro()
add_sdlmixer_example_executable(basics-load-and-play SOURCES basics/01-load-and-play/load-and-play.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3)
add_sdlmixer_example_executable(basics-play-with-options SOURCES basics/02-play-with-options/play-with-options.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3)
add_sdlmixer_example_executable(basics-play-multiple-sounds SOURCES basics/03-play-multiple-sounds/play-multiple-sounds.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/music.mp3 ${CMAKE_CURRENT_SOURCE_DIR}/sword.wav)
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)
# When you add an example, remember to add the Visual Studio project as well:
# - Add a new example in examples/
# - Run python VisualC/examples/generate.py
# - Take note of the newly generated .vcxproj files
# - Modify the .vcxproj files if necessary (adding content such as PNG or WAV files)
# - Open VisualC/SDL.sln in Visual Studio or JetBrains Rider
# - Locate the appropriate folder in the Solution Explorer
# - Add the newly generated projects: Right click -> Add -> Existing project...
# - Test if they work
# - Save the SDL.sln solution
if(PSP)
# Build EBOOT files if building for PSP
foreach(APP ${SDLMIXER_EXAMPLE_EXECUTABLES})
create_pbp_file(
TARGET ${APP}
TITLE SDL-${APP}
ICON_PATH NULL
BACKGROUND_PATH NULL
PREVIEW_PATH NULL
OUTPUT_DIR $<TARGET_FILE_DIR:${APP}>/sdl-${APP}
)
endforeach()
endif()
if(RISCOS)
set(SDL_EXAMPLE_EXECUTABLES_AIF)
foreach(APP ${SDLMIXER_EXAMPLE_EXECUTABLES})
set_property(TARGET ${APP} APPEND_STRING PROPERTY LINK_FLAGS " -static")
add_custom_command(
OUTPUT ${APP},ff8
COMMAND elf2aif ${APP} ${APP},ff8
DEPENDS ${APP}
)
add_custom_target(${APP}-aif ALL DEPENDS ${APP},ff8)
list(APPEND SDL_EXAMPLE_EXECUTABLES_AIF ${CMAKE_CURRENT_BINARY_DIR}/${APP},ff8)
endforeach()
endif()
if(SDLMIXER_EXAMPLES_INSTALL)
if(RISCOS)
install(
FILES ${SDL_EXAMPLE_EXECUTABLES_AIF}
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3_mixer
)
else()
install(
TARGETS ${SDLMIXER_EXAMPLE_EXECUTABLES}
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3_mixer
)
endif()
if(MSVC)
foreach(example IN LISTS SDLMIXER_EXAMPLE_EXECUTABLES)
SDL_install_pdb(${example} "${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3_mixer")
endforeach()
endif()
install(
FILES ${RESOURCE_FILES}
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3_mixer
)
endif()
+82
View File
@@ -0,0 +1,82 @@
# Examples
## What is this?
In here are a collection of standalone SDL_mixer application examples. Unless
otherwise stated, they should work on all supported platforms out of the box.
If they don't [please file a bug to let us know](https://github.com/libsdl-org/SDL_mixer/issues/new).
## What is this SDL_AppIterate thing?
SDL can optionally build apps as a collection of callbacks instead of the
usual program structure that starts and ends in a function called `main`.
The examples use this format for two reasons.
First, it allows the examples to work when built as web applications without
a pile of ugly `#ifdef`s, and all of these examples are published on the web
at [examples.libsdl.org](https://examples.libsdl.org/), so you can easily see
them in action.
Second, it's example code! The callbacks let us cleanly break the program up
into the four logical pieces most apps care about:
- Program startup
- Event handling
- What the program actually does in a single frame
- Program shutdown
A detailed technical explanation of these callbacks is in
docs/README-main-functions.md (or view that page on the web on
[the wiki](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)).
## I would like to build and run these examples myself.
When you build SDL with CMake, you can add `-DSDLMIXER_EXAMPLES=On` to the
CMake command line. When you build SDL_mixer, these examples will be built
with it.
But most of these can just be built as a single .c file, as long as you point
your compiler at SDL3 and SDL3_mixer's headers and link against both of those
libraries.
## What is the license on the example code? Can I paste this into my project?
All code in the examples directory is considered public domain! You can do
anything you like with it, including copy/paste it into your closed-source
project, sell it, and pretend you wrote it yourself. We do not require you to
give us credit for this code (but we always appreciate if you do!).
This is only true for the examples directory. The rest of SDL and SDL_mixer
fall under the [zlib license](https://github.com/libsdl-org/SDL_mixer/blob/main/LICENSE.txt).
## What is template.html and highlight-plugin.lua in this directory?
This is what [examples.libsdl.org](https://examples.libsdl.org/) uses when
generating the web versions of these example programs. You can ignore this,
unless you are improving it, in which case we definitely would love to hear
from you!
## What is template.c in this directory?
If writing new examples, this is the skeleton code we start from, to keep
everything consistent. You can ignore it.
## License for the audio files:
- music.mp3:
Arcade Music Loop.wav by joshuaempyre ( https://www.empyreanma.com/welcome )
(We converted this to MP3 format.)
Original: https://freesound.org/s/251461/
License: https://creativecommons.org/licenses/by/4.0/
- sword.wav:
sword04.wav by Erdie
Original: https://freesound.org/s/27858/
License: https://creativecommons.org/licenses/by/4.0/
@@ -0,0 +1,3 @@
This example code creates a mixer, loads a single sound, and plays it once.
(Remember that web browsers won't make sound until you click on the page!)
@@ -0,0 +1,111 @@
/*
* This example code creates a mixer, loads a single sound, and plays it once.
*
* 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>
/* 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 *track = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
char *path = NULL;
MIX_Audio *audio = NULL;
SDL_SetAppMetadata("Example Load And Play", "1.0", "com.example.load-and-play");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/load-and-play", 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 a sound file */
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* 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);
return SDL_APP_FAILURE;
}
SDL_free(path); /* done with this, the file is loaded. */
/* we need a track 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. */
track = MIX_CreateTrack(mixer);
if (!track) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track, audio);
/* start the audio playing! */
MIX_PlayTrack(track, 0); /* no extra options this time, so a zero for the second argument. */
/* we don't save `audio`; SDL_mixer will clean it up for us during MIX_Quit(). */
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. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
/* draw a blank video frame to keep the OS happy */
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
/* when the track has finished playing, end the program. */
if (!MIX_TrackPlaying(track)) {
return SDL_APP_SUCCESS;
}
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 file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,4 @@
This example code creates a mixer, loads a single sound, and plays it, with
several playback options (fade-in, loop, etc).
(Remember that web browsers won't make sound until you click on the page!)
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

@@ -0,0 +1,126 @@
/*
* This example code creates a mixer, loads a single sound, and plays it, with
* several playback options (fade-in, loop, etc).
*
* 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>
/* 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 *track = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
char *path = NULL;
MIX_Audio *audio = NULL;
SDL_PropertiesID options = 0;
SDL_SetAppMetadata("Example Play With Options", "1.0", "com.example.play-with-options");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/play-with-options", 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 a sound file */
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* 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);
return SDL_APP_FAILURE;
}
SDL_free(path); /* done with this, the file is loaded. */
/* we need a track 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. */
track = MIX_CreateTrack(mixer);
if (!track) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track, audio);
/* start the audio playing! */
options = SDL_CreateProperties();
if (!options) {
SDL_Log("Couldn't create play options: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* note these all use MILLISECONDS, since the track is generic, but you can use equivalent FRAMES properties, for frame-perfect mixing. */
SDL_SetNumberProperty(options, MIX_PROP_PLAY_START_MILLISECOND_NUMBER, 1000); /* start the first loop 1 second into the audio. */
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). */
SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, 2); /* loop 2 times, 3rd time through doesn't loop. */
SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOP_START_MILLISECOND_NUMBER, 2000); /* when looping, start again here instead of the start of the track. */
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! */
MIX_PlayTrack(track, options);
SDL_DestroyProperties(options); /* MIX_PlayTrack makes a copy of the options, so this can go away. */
/* we don't save `audio`; SDL_mixer will clean it up for us during MIX_Quit(). */
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. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
/* draw a blank video frame to keep the OS happy */
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
/* when the track has finished playing, end the program. */
if (!MIX_TrackPlaying(track)) {
return SDL_APP_SUCCESS;
}
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 file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,3 @@
This example code creates a mixer, loads two sounds, and mixes them.
(Remember that web browsers won't make sound until you click on the page!)
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

@@ -0,0 +1,143 @@
/*
* This example code creates a mixer, loads two sounds, and mixes them.
*
* SDL_mixer is, of course, a mixer, so here are two sounds mixing together!
*
* 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>
/* 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 *track1 = 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[])
{
MIX_Audio *music = NULL;
MIX_Audio *sound = NULL;
MIX_Track *track2 = NULL;
SDL_PropertiesID options = 0;
SDL_SetAppMetadata("Example Play Multiple Sounds", "1.0", "com.example.play-multiple-sounds");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/play-multiple-sounds", 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! */
music = load_audio("music.mp3");
if (!music) {
return SDL_APP_FAILURE; /* we reported the error in load_audio */
}
sound = load_audio("sword.wav");
if (!sound) {
return SDL_APP_FAILURE; /* we reported the error in load_audio */
}
/* we need a track 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. */
track1 = MIX_CreateTrack(mixer);
if (!track1) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track1, music);
track2 = MIX_CreateTrack(mixer);
if (!track2) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track2, sound);
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 audio playing! music plays through once, with the sound effect playing in a loop at the same time. */
MIX_PlayTrack(track1, 0); /* no extra options this time, so a zero for the second argument. */
MIX_PlayTrack(track2, options);
SDL_DestroyProperties(options); /* MIX_PlayTrack makes a copy of the options, so this can go away. */
/* we don't save `music`, `sound`, or `track2`; SDL_mixer will clean them up for us during MIX_Quit(). */
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. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
/* draw a blank video frame to keep the OS happy */
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
/* when the music has finished playing, end the program. */
if (!MIX_TrackPlaying(track1)) {
return SDL_APP_SUCCESS;
}
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 file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1 @@
This example code loads a single sound, and displays metadata.
@@ -0,0 +1,145 @@
/*
* This example code loads a single sound, and displays metadata.
*
* 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>
static MIX_Audio *audio = NULL;
static char *path = NULL;
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Metadata", "1.0", "com.example.metadata");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/metadata", 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;
}
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* allocate a string of the full file path */
audio = MIX_LoadAudio(NULL, path, false); /* MIX_Audios are shared between mixers, so you can pass a NULL mixer here; non-NULL just lets it optimize for a specific output. */
/* if MIX_LoadAudio failed, it's okay, the user can drop a new file on the window. */
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_DROP_FILE) {
MIX_DestroyAudio(audio);
SDL_free(path);
path = SDL_strdup(event->drop.data);
audio = MIX_LoadAudio(NULL, path, false);
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
static void SDLCALL RenderMetadata(void *userdata, SDL_PropertiesID props, const char *name)
{
float *y = (float *) userdata;
switch (SDL_GetPropertyType(props, name)) {
case SDL_PROPERTY_TYPE_INVALID:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [invalid type]", name);
break;
case SDL_PROPERTY_TYPE_POINTER:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [pointer=%p]", name, SDL_GetPointerProperty(props, name, NULL));
break;
case SDL_PROPERTY_TYPE_STRING:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [string=\"%s\"]", name, SDL_GetStringProperty(props, name, ""));
break;
case SDL_PROPERTY_TYPE_NUMBER:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [number=%" SDL_PRIs64 "]", name, SDL_GetNumberProperty(props, name, 0));
break;
case SDL_PROPERTY_TYPE_FLOAT:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [float=%f]", name, SDL_GetFloatProperty(props, name, 0.0f));
break;
case SDL_PROPERTY_TYPE_BOOLEAN:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [boolean=%s]", name, SDL_GetBooleanProperty(props, name, false) ? "true" : "false");
break;
default:
SDL_RenderDebugTextFormat(renderer, 0.0f, *y, " - %s [unknown type]", name);
break;
}
*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)
{
/* audio file metadata is stored in an SDL Properties group; you can also hang any app-specific metadata on here, too! */
SDL_PropertiesID props = MIX_GetAudioProperties(audio);
SDL_AudioSpec audiospec;
float y = 0.0f;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); /* black */
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); /* white */
MIX_GetAudioFormat(audio, &audiospec);
SDL_RenderDebugText(renderer, 0.0f, y, "== Drop a file on this window to get its metadata. ==");
y += (float) SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2.0f;
if (audio) {
SDL_RenderDebugText(renderer, 0.0f, y, path);
y += (float) SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f;
SDL_RenderDebugTextFormat(renderer, 0.0f, y, "%s, %d channel%s, %d freq",
SDL_GetAudioFormatName(audiospec.format),
audiospec.channels,
(audiospec.channels == 1) ? "" : "s",
audiospec.freq);
y += (float) SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2.0f;
/* now draw all the metadata. It happens in the RenderMetadata function, once per metadata item. */
SDL_EnumerateProperties(props, RenderMetadata, &y);
}
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();
SDL_free(path);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,3 @@
This example code creates a mixer, and plays a sinewave forever.
(Remember that web browsers won't make sound until you click on the page!)
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

@@ -0,0 +1,106 @@
/*
* This example code creates a mixer, and plays a sinewave forever.
*
* It's not super-useful to play a sinewave, but it is _something_
* to play if you don't have anything else, and it's built-in to
* SDL_mixer.
*
* 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>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
MIX_Mixer *mixer = NULL;
MIX_Audio *audio = NULL;
MIX_Track *track = NULL;
SDL_SetAppMetadata("Example Load And Play", "1.0", "com.example.load-and-play");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/load-and-play", 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;
}
audio = MIX_CreateSineWaveAudio(mixer, 300, 0.25f, -1); // -1: play forever. You can specify milliseconds otherwise to have a limit.
if (!audio) {
SDL_Log("Couldn't generate sinewave: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* we need a track 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. */
track = MIX_CreateTrack(mixer);
if (!track) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track, audio);
/* start the audio playing! */
MIX_PlayTrack(track, 0); /* no extra options this time, so a zero for the second argument. */
/* we don't save `mixer`, `audio`, or `track`; SDL_mixer will clean it up for us during MIX_Quit(). */
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. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
/* draw a blank video frame to keep the OS happy */
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
/* there's nothing for use to do here, the sinewave will play forever until the app is manually quit. */
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 file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,4 @@
This example code creates a mixer, loads a single sound, and plays it on loop,
letting the user seek around in playback with a slider.
(Remember that web browsers won't make sound until you click on the page!)
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,144 @@
/*
* This example code creates a mixer, loads a single sound, and plays it on
* loop, letting the user seek around in playback with a slider.
*
* 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>
/* 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_Audio *audio = NULL;
static MIX_Track *track = NULL;
#define KNOB_WIDTH 30
static const SDL_FRect progressbar = { 120, 225, 400, 75 };
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
char *path = NULL;
SDL_PropertiesID options = 0;
SDL_SetAppMetadata("Example Seeking", "1.0", "com.example.seeking");
/* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */
SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5");
/* we don't need video, but we'll make a window for smooth operation. */
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/basic/seeking", 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 a sound file */
SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* 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);
return SDL_APP_FAILURE;
}
SDL_free(path); /* done with this, the file is loaded. */
/* we need a track 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. */
track = MIX_CreateTrack(mixer);
if (!track) {
SDL_Log("Couldn't create a mixer track: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
MIX_SetTrackAudio(track, audio);
/* start the audio playing! */
options = SDL_CreateProperties();
if (!options) {
SDL_Log("Couldn't create play options: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* note these all use MILLISECONDS, since the track is generic, but you can use equivalent FRAMES properties, for frame-perfect mixing. */
SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, -1); /* loop forever */
MIX_PlayTrack(track, 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! */
}
static void seek_audio(float x, float y)
{
const SDL_FPoint pt = { x, y };
if (SDL_PointInRectFloat(&pt, &progressbar)) {
/* seek to a new position in the track, based on where the mouse clicked/dragged in the progress bar. */
const float pct = (pt.x - progressbar.x) / progressbar.w;
MIX_SetTrackPlaybackPosition(track, (Sint64) ((float) MIX_GetAudioDuration(audio) * pct));
}
}
/* 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_MOUSE_BUTTON_DOWN) {
if (event->button.button == 1) {
seek_audio(event->button.x, event->button.y);
}
} else if (event->type == SDL_EVENT_MOUSE_MOTION) {
if (event->motion.state & SDL_BUTTON_LMASK) {
seek_audio(event->motion.x, event->motion.y);
}
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect knob = { progressbar.x, progressbar.y, KNOB_WIDTH, progressbar.h };
knob.x += (progressbar.w - knob.w) * (((float) MIX_GetTrackPlaybackPosition(track)) / ((float) MIX_GetAudioDuration(audio)));
SDL_SetRenderDrawColor(renderer, 0, 0, 100, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
SDL_RenderFillRect(renderer, &progressbar);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &knob);
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 file not shown.

After

Width:  |  Height:  |  Size: 416 B

@@ -0,0 +1,100 @@
-- This code adapted from https://gitlab.com/saalen/highlight/-/wikis/Plug-Ins
-- first add a description of what the plug-in does
Description="Add wiki.libsdl.org reference links to HTML, LaTeX or RTF output"
-- define the plugin categories (ie. supported output formats; languages)
Categories = { "c", "c++" }
-- the syntaxUpdate function contains code related to syntax recognition
function syntaxUpdate(desc)
-- if the current file is not C/C++ file we exit
if desc~="C and C++" then
return
end
-- this function returns a qt-project reference link of the given token
function getSDLURL(token)
-- generate the URL
url='https://wiki.libsdl.org/SDL3/'.. token
-- embed the URL in a hyperlink according to the output format
-- first HTML, then LaTeX and RTF
if (HL_OUTPUT== HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then
return '<a class="hl" target="new" href="'
.. url .. '">'.. token .. '</a>'
elseif (HL_OUTPUT == HL_FORMAT_LATEX) then
return '\\href{'..url..'}{'..token..'}'
elseif (HL_OUTPUT == HL_FORMAT_RTF) then
return '{{\\field{\\*\\fldinst HYPERLINK "'
..url..'" }{\\fldrslt\\ul\\ulc0 '..token..'}}}'
end
end
function getMixerURL(token)
-- generate the URL
url='https://wiki.libsdl.org/SDL3_mixer/'.. token
-- embed the URL in a hyperlink according to the output format
-- first HTML, then LaTeX and RTF
if (HL_OUTPUT== HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then
return '<a class="hl" target="new" href="'
.. url .. '">'.. token .. '</a>'
elseif (HL_OUTPUT == HL_FORMAT_LATEX) then
return '\\href{'..url..'}{'..token..'}'
elseif (HL_OUTPUT == HL_FORMAT_RTF) then
return '{{\\field{\\*\\fldinst HYPERLINK "'
..url..'" }{\\fldrslt\\ul\\ulc0 '..token..'}}}'
end
end
-- the Decorate function will be invoked for every recognized token
function Decorate(token, state)
-- we are only interested in keywords, preprocessor or default items
if (state ~= HL_STANDARD and state ~= HL_KEYWORD and
state ~=HL_PREPROC) then
return
end
-- SDL keywords start with SDL_
-- SDL_mixer keywords start with MIX_
-- if this pattern applies to the token, we return the URL
-- if we return nothing, the token is outputted as is
if ( (token == "Uint8") or (token == "Uint16") or (token == "Uint32") or (token == "Uint64") or
(token == "Sint8") or (token == "Sint16") or (token == "Sint32") or (token == "Sint64") or
(string.find(token, "SDL_") == 1) ) then
return getSDLURL(token)
end
if (string.find(token, "MIX_") == 1) then
return getMixerURL(token)
end
end
end
-- the themeUpdate function contains code related to the theme
function themeUpdate(desc)
-- the Injections table can be used to add style information to the theme
-- HTML: we add additional CSS style information to beautify hyperlinks,
-- they should have the same color as their surrounding tags
if (HL_OUTPUT == HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then
Injections[#Injections+1]=
"a.hl, a.hl:visited {color:inherit;font-weight:inherit;text-decoration:none}"
-- LaTeX: hyperlinks require the hyperref package, so we add this here
-- the colorlinks and pdfborderstyle options remove ugly boxes in the output
elseif (HL_OUTPUT==HL_FORMAT_LATEX) then
Injections[#Injections+1]=
"\\usepackage[colorlinks=false, pdfborderstyle={/S/U/W 1}]{hyperref}"
end
end
-- let highlight load the chunks
Plugins={
{ Type="lang", Chunk=syntaxUpdate },
{ Type="theme", Chunk=themeUpdate },
}
Binary file not shown.
@@ -0,0 +1,49 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
This is for generating thumbnails and videos of examples. Just include it
temporarily and let it override SDL_RenderPresent, etc, and it'll dump each
frame rendered to a new .png file.
*/
static bool SAVERENDERING_SDL_RenderPresent(SDL_Renderer *renderer)
{
static unsigned int framenum = 0;
SDL_Surface *surface = SDL_RenderReadPixels(renderer, NULL);
if (!surface) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to read pixels for frame #%u! (%s)", framenum, SDL_GetError());
} else {
char fname[64];
SDL_snprintf(fname, sizeof (fname), "frame%05u.png", framenum);
if (!SDL_SavePNG(surface, fname)) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to save png for frame #%u! (%s)", framenum, SDL_GetError());
}
SDL_DestroySurface(surface);
}
framenum++;
return SDL_RenderPresent(renderer);
}
#define SDL_RenderPresent SAVERENDERING_SDL_RenderPresent
Binary file not shown.
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@project_name@ Examples: @category_description@</title>
<link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" />
@preload_images_html@
<link
rel="stylesheet"
type="text/css"
href="/@project_name@/examples.css"
/>
<style>
main > h1 {
margin-top: 0;
}
</style>
<meta property="og:type" content="website">
<meta property="og:title" content="@project_name@ Examples: @category_description@">
<meta property="og:description" content="@project_name@ Examples: @category_description@">
<meta property="og:image" content="@preview_image@" />
</head>
<body>
<header>
<a href="/">@project_name@ Examples</a>
</header>
<main>
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@/">@project_name@</a></li>
<li><a href="/@project_name@/@category_name@/">@category_name@</a></li>
</ul>
</nav>
<h1>@project_name@ examples: @category_description@</h1>
<div class="list">@examples_list_html@</div>
</main>
</body>
</html>
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@project_name@ Examples</title>
<link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" />
@preload_images_html@
<link
rel="stylesheet"
type="text/css"
href="/@project_name@/examples.css"
/>
<style>
main > h1 {
margin-top: 0;
}
</style>
<meta property="og:type" content="website">
<meta property="og:title" content="@project_name@ Examples">
<meta property="og:description" content="@project_name@ Examples">
<meta property="og:image" content="@preview_image@" />
</head>
<body>
<header>
<a href="/">SDL Examples</a>
</header>
<main>
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@/">@project_name@</a></li>
</ul>
</nav>
<h1>@project_name@ examples</h1>
@homepage_list_html@
</main>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

+55
View File
@@ -0,0 +1,55 @@
/*
* This example code $WHAT_IT_DOES.
*
* 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>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example HUMAN READABLE NAME", "1.0", "com.example.CATEGORY-NAME");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/CATEGORY/NAME", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderLogicalPresentation(renderer, 640, 480, SDL_LOGICAL_PRESENTATION_LETTERBOX);
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. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
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. */
}
+284
View File
@@ -0,0 +1,284 @@
/** from ghwikipp.css */
:root {
color-scheme: dark light; /* both supported */
}
body {
background-color: white;
padding: 2vw;
color: #333;
max-width: 1200px;
margin: 0 auto;
font-size: 16px;
line-height: 1.5;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
overflow-wrap: break-word;
}
a {
color: #0969da;
/* text-decoration: none; */
}
a:visited {
color: #064998;
}
h1 {
border-bottom: 2px solid #efefef;
}
h2 {
border-bottom: 1px solid #efefef;
}
p {
max-width: 85ch;
}
li {
max-width: 85ch;
}
div.sourceCode {
background-color: #f6f8fa;
max-width: 100%;
padding: 16px;
}
code {
background-color: #f6f8fa;
padding: 0px;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
"Liberation Mono", monospace;
}
table {
border: 1px solid #808080;
border-collapse: collapse;
}
td {
border: 1px solid #808080;
padding: 5px;
}
tr:nth-child(even) {
background-color: #f6f8fa;
}
.wikitopbanner {
background-color: #efefef;
padding: 10px;
margin-bottom: 10px;
width: auto;
}
.wikibottombanner {
background-color: #efefef;
padding: 10px;
margin-top: 10px;
width: auto;
}
.alertBox {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
max-width: 60%;
padding: 10;
margin: auto;
}
.anchorImage {
visibility: hidden;
padding-left: 0.2em;
color: #fff;
}
.anchorText:hover .anchorImage {
visibility: visible;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #efefef;
margin: 1em 0;
padding: 0;
}
/* Text and background color for dark mode */
@media (prefers-color-scheme: dark) {
body {
color: #e6edf3;
background-color: #0d1117;
}
h1 {
border-color: rgba(48, 54, 61, 0.7);
}
h2 {
border-color: rgba(48, 54, 61, 0.7);
}
hr {
border-color: rgba(48, 54, 61, 0.7);
}
div.sourceCode {
background-color: #161b22;
}
code {
background-color: #161b22;
}
a {
color: #4493f8;
}
a:visited {
color: #2f66ad;
}
table {
border-color: rgba(48, 54, 61, 0.7);
}
td {
border-color: rgba(48, 54, 61, 0.7);
}
tr:nth-child(even) {
background-color: #161b22;
}
.wikitopbanner {
background-color: #263040;
}
.wikibottombanner {
background-color: #263040;
}
.anchorText:hover .anchorImage {
filter: invert(100%);
}
}
@media print {
body {
font-size: 12px;
}
table {
font-size: inherit;
}
a:visited {
color: #0969da;
}
.wikitopbanner,
.anchorText,
.wikibottombanner {
display: none;
}
}
/** additional (& overrides) for examples */
header {
background-color: #efefef;
padding: 10px;
font-size: 2rem;
}
header > a,
header > a:hover,
header > a:visited {
color: inherit;
text-decoration: none;
}
.breadcrumb {
padding: 0.75rem 0.75rem;
}
.breadcrumb ul {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 0;
padding: 0;
}
.breadcrumb li:not(:last-child)::after {
display: inline-block;
margin: 0 0.25rem;
content: "»";
}
.list {
display: flex;
flex-flow: row wrap;
gap: 24px;
}
.list > a > div {
width: 200px;
border: 5px solid #efefef;
border-radius: 5px;
background: #efefef;
display: flex;
flex-flow: column nowrap;
transition: border 0.25s;
}
.list > a > div:hover {
border-color: #064998;
}
.list > a > div > img {
width: 100%;
border-radius: 5px;
}
.list > a > div > div {
text-align: center;
}
.list > a,
.list > a:visited {
display: block;
color: inherit;
text-decoration: none;
}
.list > a:hover {
color: #0969da;
}
@media (prefers-color-scheme: dark) {
header {
background-color: #263040;
}
.breadcrumb li:not(:last-child)::after {
color: #efefef;
}
.list > a > div {
border-color: #333;
background: #333;
}
}
@media only screen and (max-width: 992px) {
.list > a > div {
width: 150px;
}
}
+292
View File
@@ -0,0 +1,292 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@project_name@ Example: @category_name@/@example_name@</title>
<link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" />
<meta property="og:type" content="website">
<meta property="og:title" content="@project_name@ Example: @category_name@/@example_name@">
<meta property="og:description" content="@short_description@">
<meta property="og:image" content="@preview_image@" />
<link rel="stylesheet" type="text/css" href="/@project_name@/examples.css" />
<style>
main {
display: flex;
}
main > #sidebar {
flex: 0 1 25%;
border-left: 2px solid #efefef;
padding: 1rem 1rem;
}
main > #content {
flex: 1 1 auto;
margin-bottom: 16px;
}
main > #content > h1 {
margin-top: 0;
}
main > #sidebar ul {
list-style-type: none;
padding: 0;
margin: 0;
}
main > #sidebar li {
padding: 2px 0;
}
#example-description {
max-width: 85ch;
margin-bottom: 16px;
}
.canvas-container {
display: flex;
align-items: center;
justify-content: center;
}
#canvas {
max-width: 100%;
box-shadow: 0 0 0.5rem #7787;
}
#output-container {
position: fixed;
top: 100%;
left: 0;
right: 0;
bottom: 0;
background-color: black;
border: none;
border-top: 1px solid #778;
margin: 0;
padding: 1rem;
transition: top 0.25s;
}
#output-container::before {
position: absolute;
bottom: 100%;
right: 1rem;
content: 'Console';
font-size: 1.5rem;
color: white;
background: black;
border: 1px solid #778;
border-bottom: none;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem 0.5rem 0 0;
}
#output-container:hover,
#output-container:focus-within {
top: 20%;
}
#output-container:focus-within {
border-top: 2px solid orange;
}
#output-container:focus-within::before {
border: 2px solid orange;
border-bottom: none;
}
#output {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: none;
background: black;
color: white;
outline: none;
resize: none;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
"Liberation Mono", monospace;
}
#source-code {
position: fixed;
top: 100%;
left: 0;
right: 0;
bottom: 0;
background: #e0eaee;
padding: 1rem;
transition: top 0.25s;
}
#source-code::before {
position: absolute;
bottom: 100%;
left: 1rem;
content: 'Source code';
font-size: 1.5rem;
background: linear-gradient(to bottom, #789, #e0eaee);
padding: 0.75rem 1.5rem;
border-radius: 0.5rem 0.5rem 0 0;
/* Used for a hack to avoid tab labels showing on top of tabs; see
comment below for details. */
transition: bottom 0.25s;
}
#source-code:hover,
#source-code:focus-within {
top: 20%;
}
#source-code:focus-within {
border-top: 2px solid orange;
}
#source-code:focus-within::before {
border: 2px solid orange;
border-bottom: none;
}
#source-code-contents {
height: 100%;
overflow: scroll;
}
/* Hack: Sinze z-index only goes one way, and both tab labels should be
behind each other's tab, put the former on top (higher z-index) and
make the latter one disappear when the former is hovered. */
#output-container:hover ~ #source-code::before,
#output-container:focus-within ~ #source-code::before {
bottom: -100%;
}
@media (prefers-color-scheme: dark) {
main > #sidebar {
border-color: rgba(48, 54, 61, 0.7);
}
}
@media only screen and (max-width: 992px) {
main {
flex-direction: column;
}
main > #sidebar {
border: none;
}
}
</style>
<link rel="stylesheet" type="text/css" href="highlight.css">
</head>
<body>
<header>
<a href="/">SDL_mixer Examples</a>
</header>
<main>
<div id="content">
<nav class="breadcrumb">
<ul>
<li><a href="/@project_name@/">@project_name@</a></li>
<li><a href="/@project_name@/@category_name@/">@category_name@</a></li>
<li><a href="/@project_name@/@category_name@/@example_name@/">@example_name@</a></li>
</ul>
</nav>
<hr/>
<div id="example-description">@description@</div>
<div class="canvas-container">
<canvas
id="canvas"
oncontextmenu="event.preventDefault()"
tabindex="-1"
></canvas>
</div>
</div>
<div id="sidebar">
<h3>Other examples:</h3>
@other_examples_html@
</div>
</main>
<div id="output-container">
<textarea id="output" rows="8" spellcheck="false" readonly></textarea>
</div>
<div id="source-code" tabindex="1">
<div id="source-code-contents">@htmlified_source_code@</div>
</div>
<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
var elem = document.getElementById('output-container');
if (elem.style['top'] == '') {
elem.style['top'] = '20%';
setTimeout(function() { elem.style['top'] = ''; }, 3000);
}
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) { Module.print(text) },
canvas: (() => {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", (e) => { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: (text) => {},
totalDependencies: 0,
monitorRunDependencies: (left) => {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = (event) => {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
Module.setStatus = (text) => {
if (text) console.error('[post-exception status] ' + text);
};
};
</script>
<script async type="text/javascript" src="@javascript_file@"></script>
</body>
</html>