Documentation
Documentation
I. SDL Guide
Preface
About SDL
About SDLdoc
Credits
1. The Basics
Introduction
Initializing SDL
2. Graphics and Video
Introduction to SDL Video
Using OpenGL With SDL
3. Input handling
Handling Joysticks
Handling the Keyboard
4. Examples
Introduction
Event Examples
Audio Examples
CDROM Examples
Time Examples
II. SDL Reference
5. General
SDL_Init — Initializes SDL
SDL_InitSubSystem — Initialize subsystems
SDL_QuitSubSystem — Shut down a subsystem
SDL_Quit — Shut down SDL
SDL_WasInit — Check which subsystems are initialized
SDL_GetError — Get SDL error string
6. Video
SDL_GetVideoSurface — returns a pointer to the current display
surface
SDL_GetVideoInfo — returns a pointer to information about the video
hardware
SDL_VideoDriverName — Obtain the name of the video driver
SDL_ListModes — Returns a pointer to an array of available screen
dimensions for the given format and video flags
SDL_VideoModeOK — Check to see if a particular video mode is
supported.
SDL_SetVideoMode — Set up a video mode with the specified width,
height and bits-per-pixel.
SDL_UpdateRect — Makes sure the given area is updated on the
given screen.
SDL_UpdateRects — Makes sure the given list of rectangles is
updated on the given screen.
SDL_Flip — Swaps screen buffers
SDL_SetColors — Sets a portion of the colormap for the given 8-bit
surface.
SDL_SetPalette — Sets the colors in the palette of an 8-bit surface.
SDL_SetGamma — Sets the color gamma function for the display
SDL_GetGammaRamp — Gets the color gamma lookup tables for the
display
SDL_SetGammaRamp — Sets the color gamma lookup tables for the
display
SDL_MapRGB — Map a RGB color value to a pixel format.
SDL_MapRGBA — Map a RGBA color value to a pixel format.
SDL_GetRGB — Get RGB values from a pixel in the specified pixel
format.
SDL_GetRGBA — Get RGBA values from a pixel in the specified
pixel format.
SDL_CreateRGBSurface — Create an empty SDL_Surface
SDL_CreateRGBSurfaceFrom — Create an SDL_Surface from pixel
data
SDL_FreeSurface — Frees (deletes) a SDL_Surface
SDL_LockSurface — Lock a surface for directly access.
SDL_UnlockSurface — Unlocks a previously locked surface.
SDL_LoadBMP — Load a Windows BMP file into an SDL_Surface.
SDL_SaveBMP — Save an SDL_Surface as a Windows BMP file.
SDL_SetColorKey — Sets the color key (transparent pixel) in a
blittable surface and RLE acceleration.
SDL_SetAlpha — Adjust the alpha properties of a surface
SDL_SetClipRect — Sets the clipping rectangle for a surface.
SDL_GetClipRect — Gets the clipping rectangle for a surface.
SDL_ConvertSurface — Converts a surface to the same format as
another surface.
SDL_BlitSurface — This performs a fast blit from the source surface
to the destination surface.
SDL_FillRect — This function performs a fast fill of the given
rectangle with some color
SDL_DisplayFormat — Convert a surface to the display format
SDL_DisplayFormatAlpha — Convert a surface to the display format
SDL_WarpMouse — Set the position of the mouse cursor.
SDL_CreateCursor — Creates a new mouse cursor.
SDL_FreeCursor — Frees a cursor created with SDL_CreateCursor.
SDL_SetCursor — Set the currently active mouse cursor.
SDL_GetCursor — Get the currently active mouse cursor.
SDL_ShowCursor — Toggle whether or not the cursor is shown on the
screen.
SDL_GL_LoadLibrary — Specify an OpenGL library
SDL_GL_GetProcAddress — Get the address of a GL function
SDL_GL_GetAttribute — Get the value of a special SDL/OpenGL
attribute
SDL_GL_SetAttribute — Set a special SDL/OpenGL attribute
SDL_GL_SwapBuffers — Swap OpenGL framebuffers/Update
Display
SDL_CreateYUVOverlay — Create a YUV video overlay
SDL_LockYUVOverlay — Lock an overlay
SDL_UnlockYUVOverlay — Unlock an overlay
SDL_DisplayYUVOverlay — Blit the overlay to the display
SDL_FreeYUVOverlay — Free a YUV video overlay
SDL_GLattr — SDL GL Attributes
SDL_Rect — Defines a rectangular area
SDL_Color — Format independent color description
SDL_Palette — Color palette for 8-bit pixel formats
SDL_PixelFormat — Stores surface format information
SDL_Surface — Graphical Surface Structure
SDL_VideoInfo — Video Target information
SDL_Overlay — YUV video overlay
7. Window Management
SDL_WM_SetCaption — Sets the window tile and icon name.
SDL_WM_GetCaption — Gets the window title and icon name.
SDL_WM_SetIcon — Sets the icon for the display window.
SDL_WM_IconifyWindow — Iconify/Minimise the window
SDL_WM_ToggleFullScreen — Toggles fullscreen mode
SDL_WM_GrabInput — Grabs mouse and keyboard input.
8. Events
Introduction
SDL Event Structures.
Event Functions.
9. Joystick
SDL_NumJoysticks — Count available joysticks.
SDL_JoystickName — Get joystick name.
SDL_JoystickOpen — Opens a joystick for use.
SDL_JoystickOpened — Determine if a joystick has been opened
SDL_JoystickIndex — Get the index of an SDL_Joystick.
SDL_JoystickNumAxes — Get the number of joystick axes
SDL_JoystickNumBalls — Get the number of joystick trackballs
SDL_JoystickNumHats — Get the number of joystick hats
SDL_JoystickNumButtons — Get the number of joysitck buttons
SDL_JoystickUpdate — Updates the state of all joysticks
SDL_JoystickGetAxis — Get the current state of an axis
SDL_JoystickGetHat — Get the current state of a joystick hat
SDL_JoystickGetButton — Get the current state of a given button on a
given joystick
SDL_JoystickGetBall — Get relative trackball motion
SDL_JoystickClose — Closes a previously opened joystick
10. Audio
SDL_AudioSpec — Audio Specification Structure
SDL_OpenAudio — Opens the audio device with the desired
parameters.
SDL_PauseAudio — Pauses and unpauses the audio callback
processing
SDL_GetAudioStatus — Get the current audio state
SDL_LoadWAV — Load a WAVE file
SDL_FreeWAV — Frees previously opened WAV data
SDL_AudioCVT — Audio Conversion Structure
SDL_BuildAudioCVT — Initializes a SDL_AudioCVT structure for
conversion
SDL_ConvertAudio — Convert audio data to a desired audio format.
SDL_MixAudio — Mix audio data
SDL_LockAudio — Lock out the callback function
SDL_UnlockAudio — Unlock the callback function
SDL_CloseAudio — Shuts down audio processing and closes the
audio device.
11. CD-ROM
SDL_CDNumDrives — Returns the number of CD-ROM drives on
the system.
SDL_CDName — Returns a human-readable, system-dependent
identifier for the CD-ROM.
SDL_CDOpen — Opens a CD-ROM drive for access.
SDL_CDStatus — Returns the current status of the given drive.
SDL_CDPlay — Play a CD
SDL_CDPlayTracks — Play the given CD track(s)
SDL_CDPause — Pauses a CDROM
SDL_CDResume — Resumes a CDROM
SDL_CDStop — Stops a CDROM
SDL_CDEject — Ejects a CDROM
SDL_CDClose — Closes a SDL_CD handle
SDL_CD — CDROM Drive Information
SDL_CDtrack — CD Track Information Structure
12. Multi-threaded Programming
SDL_CreateThread — Creates a new thread of execution that shares
its parent's properties.
SDL_ThreadID — Get the 32-bit thread identifier for the current
thread.
SDL_GetThreadID — Get the SDL thread ID of a SDL_Thread
SDL_WaitThread — Wait for a thread to finish.
SDL_KillThread — Gracelessly terminates the thread.
SDL_CreateMutex — Create a mutex
SDL_DestroyMutex — Destroy a mutex
SDL_mutexP — Lock a mutex
SDL_mutexV — Unlock a mutex
SDL_CreateSemaphore — Creates a new semaphore and assigns an
initial value to it.
SDL_DestroySemaphore — Destroys a semaphore that was created by
SDL_CreateSemaphore.
SDL_SemWait — Lock a semaphore and suspend the thread if the
semaphore value is zero.
SDL_SemTryWait — Attempt to lock a semaphore but don't suspend
the thread.
SDL_SemWaitTimeout — Lock a semaphore, but only wait up to a
specified maximum time.
SDL_SemPost — Unlock a semaphore.
SDL_SemValue — Return the current value of a semaphore.
SDL_CreateCond — Create a condition variable
SDL_DestroyCond — Destroy a condition variable
SDL_CondSignal — Restart a thread wait on a condition variable
SDL_CondBroadcast — Restart all threads waiting on a condition
variable
SDL_CondWait — Wait on a condition variable
SDL_CondWaitTimeout — Wait on a condition variable, with timeout
13. Time
SDL_GetTicks — Get the number of milliseconds since the SDL
library initialization.
SDL_Delay — Wait a specified number of milliseconds before
returning.
SDL_AddTimer — Add a timer which will call a callback after the
specified number of milliseconds has elapsed.
SDL_RemoveTimer — Remove a timer which was added with
SDL_AddTimer.
SDL_SetTimer — Set a callback to run after the specified number of
milliseconds has elapsed.
List of Tables
8-1. SDL Keysym definitions
8-2. SDL modifier definitions
List of Examples
1-1. Initializing SDL
2-1. Initializing the Video Display
2-2. Initializing the Best Video Mode
2-3. Loading and Displaying a BMP File
2-4. getpixel()
2-5. putpixel()
2-6. Using putpixel()
2-7. Initializing SDL with OpenGL
2-8. SDL and OpenGL
3-1. Initializing SDL with Joystick Support
3-2. Querying the Number of Available Joysticks
3-3. Opening a Joystick
3-4. Joystick Axis Events
3-5. More Joystick Axis Events
3-6. Joystick Button Events
3-7. Joystick Ball Events
3-8. Joystick Hat Events
3-9. Querying Joystick Characteristics
3-10. Reading Keyboard Events
3-11. Interpreting Key Event Information
3-12. Proper Game Movement
Next
SDL Guide
SDL Library Documentation
Prev Next
I. SDL Guide
Table of Contents
Preface
1. The Basics
2. Graphics and Video
3. Input handling
4. Examples
To initialize the default subsystems, the Video subsystem and the Timers
subsystem you would call:
SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER );
With SDL_Init and SDL_Quit firmly embedded in your programmers toolkit you
can write your first and most basic SDL application. However, we must be
prepare to handle errors. Many SDL functions return a value and indicates
whether the function has succeeded or failed, SDL_Init, for instance, returns -1
if it could not initialize a subsystem. SDL provides a useful facility that allows
you to determine exactly what the problem was, every time an error occurs
within SDL an error message is stored which can be retrieved using
SDL_GetError. Use this often, you can never know too much about an error.
int main() {
printf("Initializing SDL.\n");
printf("SDL initialized.\n");
printf("Quiting SDL.\n");
printf("Quiting....\n");
exit(0);
}
/* Clean up on exit */
atexit(SDL_Quit);
/*
* Initialize the display in a 640x480 8-bit palettized mode,
* requesting a software surface
*/
screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
exit(1);
}
Initializing the Best Video Mode
If you have a preference for a certain pixel depth but will accept any other, use
SDL_SetVideoMode with SDL_ANYFORMAT as below. You can also use
SDL_VideoModeOK() to find the native video mode that is closest to the mode
you request.
/*
* Palettized screen modes will have a default palette (a standard
* 8*8*4 colour cube), but if the image is palettized as well we can
* use that palette for a nicer colour matching
*/
if (image->format->palette && screen->format->palette) {
SDL_SetColors(screen, image->format->palette->colors, 0,
image->format->palette->ncolors);
}
To convert between pixel values and their red, green, blue components, use
SDL_GetRGB() and SDL_MapRGB().
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
The following code uses the putpixel() function above to set a yellow pixel in the
middle of the screen.
int x, y;
Uint32 yellow;
x = screen->w / 2;
y = screen->h / 2;
putpixel(screen, x, y, yellow);
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
/* Update just the part of the display that we've changed */
SDL_UpdateRect(screen, x, y, 1, 1);
return;
if( !info ) {
/* This should probably never happen. */
fprintf( stderr, "Video query failed: %s\n",
SDL_GetError( ) );
quit_tutorial( 1 );
}
/*
* Set our width/height to 640/480 (you would
* of course let the user decide this in a normal
* app). We get the bpp we will request from
* the display. On X11, VidMode can't change
* resolution, so this is probably being overly
* safe. Under Win32, ChangeDisplaySettings
* can change the bpp.
*/
width = 640;
height = 480;
bpp = info->vfmt->BitsPerPixel;
/*
* Now, we want to setup our requested
* window attributes for our OpenGL window.
* We want *at least* 5 bits of red, green
* and blue. We also want at least a 16-bit
* depth buffer.
*
* The last thing we do is request a double
* buffered window. '1' turns on double
* buffering, '0' turns it off.
*
* Note that we do not use SDL_DOUBLEBUF in
* the flags to SDL_SetVideoMode. That does
* not affect the GL attribute state, only
* the standard 2D blitting setup.
*/
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
/*
* We want to request that SDL provide us
* with an OpenGL window, in a fullscreen
* video mode.
*
* EXERCISE:
* Make starting windowed an option, and
* handle the resize events properly with
* glViewport.
*/
flags = SDL_OPENGL | SDL_FULLSCREEN;
/*
* Set the video mode
*/
if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
/*
* This could happen for a variety of reasons,
* including DISPLAY not being set, the specified
* resolution not being available, etc.
*/
fprintf( stderr, "Video mode set failed: %s\n",
SDL_GetError( ) );
quit_tutorial( 1 );
}
Drawing
Apart from initialisation, using OpenGL within SDL is the same as using
OpenGL with any other API, e.g. GLUT. You still use all the same function calls
and data types. However if you are using a double-buffered display, then you
must use SDL_GL_SwapBuffers() to swap the buffers and update the display. To
request double-buffering with OpenGL, use SDL_GL_SetAttribute with
SDL_GL_DOUBLEBUFFER, and use SDL_GL_GetAttribute to see if you actually got
it.
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
/* Exit program. */
exit( code );
}
static void handle_key_down( SDL_keysym* keysym )
{
/*
* We're only interested if 'Esc' has
* been presssed.
*
* EXERCISE:
* Handle the arrow keys and have that change the
* viewing position/angle.
*/
switch( keysym->sym ) {
case SDLK_ESCAPE:
quit_tutorial( 0 );
break;
case SDLK_SPACE:
should_rotate = !should_rotate;
break;
default:
break;
}
switch( event.type ) {
case SDL_KEYDOWN:
/* Handle key presses. */
handle_key_down( &event.key.keysym );
break;
case SDL_QUIT:
/* Handle quit requests (like Ctrl-c). */
quit_tutorial( 0 );
break;
}
/*
* EXERCISE:
* Replace this awful mess with vertex
* arrays and a call to glDrawElements.
*
* EXERCISE:
* After completing the above, change
* it to use compiled vertex arrays.
*
* EXERCISE:
* Verify my windings are correct here ;).
*/
static GLfloat v0[] = { -1.0f, -1.0f, 1.0f };
static GLfloat v1[] = { 1.0f, -1.0f, 1.0f };
static GLfloat v2[] = { 1.0f, 1.0f, 1.0f };
static GLfloat v3[] = { -1.0f, 1.0f, 1.0f };
static GLfloat v4[] = { -1.0f, -1.0f, -1.0f };
static GLfloat v5[] = { 1.0f, -1.0f, -1.0f };
static GLfloat v6[] = { 1.0f, 1.0f, -1.0f };
static GLfloat v7[] = { -1.0f, 1.0f, -1.0f };
static GLubyte red[] = { 255, 0, 0, 255 };
static GLubyte green[] = { 0, 255, 0, 255 };
static GLubyte blue[] = { 0, 0, 255, 255 };
static GLubyte white[] = { 255, 255, 255, 255 };
static GLubyte yellow[] = { 0, 255, 255, 255 };
static GLubyte black[] = { 0, 0, 0, 255 };
static GLubyte orange[] = { 255, 255, 0, 255 };
static GLubyte purple[] = { 255, 0, 255, 0 };
/* Rotate. */
glRotatef( angle, 0.0, 1.0, 0.0 );
if( should_rotate ) {
glColor4ubv( red );
glVertex3fv( v0 );
glColor4ubv( green );
glVertex3fv( v1 );
glColor4ubv( blue );
glVertex3fv( v2 );
glColor4ubv( red );
glVertex3fv( v0 );
glColor4ubv( blue );
glVertex3fv( v2 );
glColor4ubv( white );
glVertex3fv( v3 );
glColor4ubv( green );
glVertex3fv( v1 );
glColor4ubv( black );
glVertex3fv( v5 );
glColor4ubv( orange );
glVertex3fv( v6 );
glColor4ubv( green );
glVertex3fv( v1 );
glColor4ubv( orange );
glVertex3fv( v6 );
glColor4ubv( blue );
glVertex3fv( v2 );
glColor4ubv( black );
glVertex3fv( v5 );
glColor4ubv( yellow );
glVertex3fv( v4 );
glColor4ubv( purple );
glVertex3fv( v7 );
glColor4ubv( black );
glVertex3fv( v5 );
glColor4ubv( purple );
glVertex3fv( v7 );
glColor4ubv( orange );
glVertex3fv( v6 );
glColor4ubv( yellow );
glVertex3fv( v4 );
glColor4ubv( red );
glVertex3fv( v0 );
glColor4ubv( white );
glVertex3fv( v3 );
glColor4ubv( yellow );
glVertex3fv( v4 );
glColor4ubv( white );
glVertex3fv( v3 );
glColor4ubv( purple );
glVertex3fv( v7 );
glColor4ubv( white );
glVertex3fv( v3 );
glColor4ubv( blue );
glVertex3fv( v2 );
glColor4ubv( orange );
glVertex3fv( v6 );
glColor4ubv( white );
glVertex3fv( v3 );
glColor4ubv( orange );
glVertex3fv( v6 );
glColor4ubv( purple );
glVertex3fv( v7 );
glColor4ubv( green );
glVertex3fv( v1 );
glColor4ubv( red );
glVertex3fv( v0 );
glColor4ubv( yellow );
glVertex3fv( v4 );
glColor4ubv( green );
glVertex3fv( v1 );
glColor4ubv( yellow );
glVertex3fv( v4 );
glColor4ubv( black );
glVertex3fv( v5 );
glEnd( );
/*
* EXERCISE:
* Draw text telling the user that 'Spc'
* pauses the rotation and 'Esc' quits.
* Do it using vetors and textured quads.
*/
/*
* Swap the buffers. This this tells the driver to
* render the next frame from the contents of the
* back-buffer, and to set all rendering operations
* to occur on what was the front-buffer.
*
* Double buffering prevents nasty visual tearing
* from the application drawing on areas of the
* screen that are being updated at the same time.
*/
SDL_GL_SwapBuffers( );
}
/* Culling. */
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
glEnable( GL_CULL_FACE );
/*
* Change to the projection matrix and set
* our viewing volume.
*/
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
/*
* EXERCISE:
* Replace this with a call to glFrustum.
*/
gluPerspective( 60.0, ratio, 1.0, 1024.0 );
}
if( !info ) {
/* This should probably never happen. */
fprintf( stderr, "Video query failed: %s\n",
SDL_GetError( ) );
quit_tutorial( 1 );
}
/*
* Set our width/height to 640/480 (you would
* of course let the user decide this in a normal
* app). We get the bpp we will request from
* the display. On X11, VidMode can't change
* resolution, so this is probably being overly
* safe. Under Win32, ChangeDisplaySettings
* can change the bpp.
*/
width = 640;
height = 480;
bpp = info->vfmt->BitsPerPixel;
/*
* Now, we want to setup our requested
* window attributes for our OpenGL window.
* We want *at least* 5 bits of red, green
* and blue. We also want at least a 16-bit
* depth buffer.
*
* The last thing we do is request a double
* buffered window. '1' turns on double
* buffering, '0' turns it off.
*
* Note that we do not use SDL_DOUBLEBUF in
* the flags to SDL_SetVideoMode. That does
* not affect the GL attribute state, only
* the standard 2D blitting setup.
*/
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
/*
* We want to request that SDL provide us
* with an OpenGL window, in a fullscreen
* video mode.
*
* EXERCISE:
* Make starting windowed an option, and
* handle the resize events properly with
* glViewport.
*/
flags = SDL_OPENGL | SDL_FULLSCREEN;
/*
* Set the video mode
*/
if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
/*
* This could happen for a variety of reasons,
* including DISPLAY not being set, the specified
* resolution not being available, etc.
*/
fprintf( stderr, "Video mode set failed: %s\n",
SDL_GetError( ) );
quit_tutorial( 1 );
}
/*
* At this point, we should have a properly setup
* double-buffered window for use with OpenGL.
*/
setup_opengl( width, height );
/*
* Now we want to begin our normal app process--
* an event loop with a lot of redrawing.
*/
while( 1 ) {
/* Process incoming events. */
process_events( );
/* Draw the screen. */
draw_screen( );
}
/*
* EXERCISE:
* Record timings using SDL_GetTicks() and
* and print out frames per second at program
* end.
*/
/* Never reached. */
return 0;
}
This will attempt to start SDL with both the video and the joystick subsystems
activated.
Querying
If we have reached this point then we can safely assume that the SDL library has
been initialized and that the Joystick subsystem is active. We can now call some
video and/or sound functions to get things going before we need the joystick.
Eventually we have to make sure that there is actually a joystick to work with.
It's wise to always check even if you know a joystick will be present on the
system because it can also help detect when the joystick is unplugged. The
function used to check for joysticks is SDL_NumJoysticks.
This function simply returns the number of joysticks available on the system. If
it is at least one then we are in good shape. The next step is to determine which
joystick the user wants to use. If the number of joysticks available is only one
then it is safe to assume that one joystick is the one the user wants to use. SDL
has a function to get the name of the joysticks as assigned by the operations
system and that function is SDL_JoystickName. The joystick is specified by an
index where 0 is the first joystick and the last joystick is the number returned by
SDL_NumJoysticks - 1. In the demonstration a list of all available joysticks is
printed to stdout.
Events are received from all joysticks opened. The first thing that needs to be
done in order to receive joystick events is to call SDL_JoystickEventState with
the SDL_ENABLE flag. Next you must open the joysticks that you want to receive
envents from. This is done with the SDL_JoystickOpen function. For the
example we are only interested in events from the first joystick on the system,
regardless of what it may be. To receive events from it we would do this:
SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(0);
If we wanted to receive events for other joysticks we would open them with calls
to SDL_JoystickOpen just like we opened joystick 0, except we would store the
SDL_Joystick structure they return in a different pointer. We only need the
joystick pointer when we are querying the joysticks or when we are closing the
joystick.
Up to this point all the code we have is used just to initialize the joysticks in
order to read values at run time. All we need now is an event loop, which is
something that all SDL programs should have anyway to receive the systems
quit events. We must now add code to check the event loop for at least some of
the above mentioned events. Let's assume our event loop looks like this:
SDL_Event event;
/* Other initializtion code goes here */
/* Start main game loop here */
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
/* handle keyboard stuff here */
break;
case SDL_QUIT:
/* Set whatever flags are necessary to */
/* end the main game loop here */
break;
}
}
To handle Joystick events we merely add cases for them, first we'll add axis
handling code. Axis checks can get kinda of tricky because alot of the joystick
events received are junk. Joystick axis have a tendency to vary just a little
between polling due to the way they are designed. To compensate for this you
have to set a threshold for changes and ignore the events that have'nt exceeded
the threshold. 10% is usually a good threshold value. This sounds a lot more
complicated than it is. Here is the Axis event handler:
Another trick with axis events is that up-down and left-right movement are two
different sets of axes. The most important axis is axis 0 (left-right) and axis 1
(up-down). To handle them seperatly in the code we do the following:
if( event.jaxis.axis == 1)
{
/* Up-Down movement code goes here */
}
}
break;
Ideally the code here should use event.jaxis.value to scale something. For
example lets assume you are using the joystick to control the movement of a
spaceship. If the user is using an analog joystick and they push the stick a little
bit they expect to move less than if they pushed it a lot. Designing your code for
this situation is preferred because it makes the experience for users of analog
controls better and remains the same for users of digital controls.
If your joystick has any additional axis then they may be used for other sticks or
throttle controls and those axis return values too just with different
event.jaxis.axis values.
Button checks are simpler than axis checks because a button can only be pressed
or not pressed. The SDL_JOYBUTTONDOWN event is triggered when a button is
pressed and the SDL_JOYBUTTONUP event is fired when a button is released. We do
have to know what button was pressed though, that is done by reading the
event.jbutton.button field.
Lastly when we are through using our joysticks we should close them with a call
to SDL_JoystickClose. To close our opened joystick 0 we would do this at the
end of our program:
SDL_JoystickClose(joystick);
Advanced Joystick Functions
That takes care of the controls that you can count on being on every joystick
under the sun, but there are a few extra things that SDL can support. Joyballs are
next on our list, they are alot like axis with a few minor differences. Joyballs
store relative changes unlike the the absolute postion stored in a axis event. Also
one trackball event contains both the change in x and they change in y. Our case
for it is as follows:
The above checks the first joyball on the joystick. The change in position will be
stored in event.jball.xrel and event.jball.yrel.
Finally we have the hat event. Hats report only the direction they are pushed in.
We check hat's position with the bitmasks:
SDL_HAT_CENTERED
SDL_HAT_UP
SDL_HAT_RIGHT
SDL_HAT_DOWN
SDL_HAT_LEFT
SDL_HAT_RIGHTUP
SDL_HAT_RIGHTDOWN
SDL_HAT_LEFTUP
SDL_HAT_LEFTDOWN
In addition to the queries for number of joysticks on the system and their names
there are additional functions to query the capabilities of attached joysticks:
To use these functions we just have to pass in the joystick structure we got when
we opened the joystick. For Example:
joystick = SDL_JoystickOpen(0);
number_of_buttons = SDL_JoystickNumButtons(joystick);
This block of code would get the number of buttons on the first joystick in the
system.
SDLKey
SDLMod
SDL_keysym
typedef struct{
Uint8 scancode;
SDLKey sym;
SDLMod mod;
Uint16 unicode;
} SDL_keysym;
The SDL_keysym structure describes a key press or a key release. The scancode
field is hardware specific and should be ignored unless you know what your
doing. The sym field is the SDLKey value of the key being pressed or released.
The mod field describes the state of the keyboard modifiers at the time the key
press or release occurred. So a value of KMOD_NUM | KMOD_CAPS | KMOD_LSHIFT
would mean that Numlock, Capslock and the left shift key were all press (or
enabled in the case of the lock keys). Finally, the unicode field stores the 16-bit
unicode value of the key.
Note: It should be noted and understood that this field is only valid when
the SDL_keysym is describing a key press, not a key release. Unicode
values only make sense on a key press because the unicode value describes
an international character and only key presses produce characters. More
information on Unicode can be found at www.unicode.org
SDL_KeyboardEvent
typedef struct{
Uint8 type;
Uint8 state;
SDL_keysym keysym;
} SDL_KeyboardEvent;
case SDL_KEYUP:
printf( "Key release detected\n" );
break;
default:
break;
}
}
.
.
This is a very basic example. No information about the key press or release is
interpreted. We will explore the other extreme out our first full example below -
reporting all available information about a keyboard event.
A More Detailed Look
Before we can read events SDL must be initialised with SDL_Init and a video
mode must be set using SDL_SetVideoMode. There are, however, two other
functions we must use to obtain all the information required. We must enable
unicode translation by calling SDL_EnableUNICODE(1) and we must convert
SDLKey values into something printable, using SDL_GetKeyName
Note: It is useful to note that unicode values < 0x80 translate directly a
characters ASCII value. THis is used in the example below
/* Function Prototypes */
void PrintKeyInfo( SDL_KeyboardEvent *key );
void PrintModifiers( SDLMod mod );
/* main */
int main( int argc, char *argv[] ){
SDL_Event event;
int quit = 0;
/* Initialise SDL */
if( SDL_Init( SDL_INIT_VIDEO ) < 0){
fprintf( stderr, "Could not initialise SDL: %s\n", SDL_GetError() )
exit( -1 );
}
switch( event.type ){
/* Keyboard event */
/* Pass the event data onto PrintKeyInfo() */
case SDL_KEYDOWN:
case SDL_KEYUP:
PrintKeyInfo( &event.key );
break;
default:
break;
}
/* Clean up */
SDL_Quit();
exit( 0 );
}
Keyboard events only take place when a keys state changes from being
unpressed to pressed, and vice versa.
Imagine you have an image of an alien that you wish to move around using the
cursor keys - when you pressed the left arrow key you want him to slide over to
the left, when you press the down key you want him to slide down the screen.
Examine the following code, it highlights and error that many people have made.
/* Alien screen coordinates */
int alien_x=0, alien_y=0;
.
.
/* Initialise SDL and video modes and all that */
.
/* Main game loop */
/* Check for events */
while( SDL_PollEvent( &event ) ){
switch( event.type ){
/* Look for a keypress */
case SDL_KEYDOWN:
/* Check the SDLKey values and move change the coords */
switch( event.key.keysym.sym ){
case SDLK_LEFT:
alien_x -= 1;
break;
case SDLK_RIGHT:
alien_x += 1;
break;
case SDLK_UP:
alien_y -= 1;
break;
case SDLK_DOWN:
alien_y += 1;
break;
default:
break;
}
}
}
}
.
.
At first glance you may think this is a perfectly reasonable piece of code for the
task, but it isn't. Like I said keyboard events only occur when a key changes
state, so the user would have to press and release the left cursor key 100 times to
move the alien 100 pixels to the left.
To get around this problem we must not use the events to change the position of
the alien, we use the events to set flags which are then used in a seperate section
of code to move the alien. Something like this:
default:
break;
}
}
.
.
/* Update the alien position */
alien_x += alien_xvel;
alien_y += alien_yvel;
As can be seen, we use two extra variables, alien_xvel and alien_yvel, which
represent the motion of the ship, it is these variables that we update when we
detect keypresses and releases.
#include "SDL.h"
/* The mouse isn't much use unless we have a display for reference */
if ( SDL_SetVideoMode(640, 480, 8, 0) == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
exit(1);
}
case SDL_MOUSEBUTTONDOWN: {
Uint8 *keys;
keys = SDL_GetKeyState(NULL);
if ( keys[SDLK_ESCAPE] == SDL_PRESSED ) {
printf("Bye bye...\n");
exit(0);
}
printf("Mouse button pressed\n");
}
break;
case SDL_QUIT: {
printf("Quit requested, quitting.\n");
exit(0);
}
break;
}
}
/* This should never happen */
printf("SDL_WaitEvent error: %s\n", SDL_GetError());
exit(1);
}
;;;;;
audio_pos = audio_chunk;
/* Do some processing */
;;;;;
/* Find out how many CD-ROM drives are connected to the system */
printf("Drives available: %d\n", SDL_CDNumDrives());
for ( i=0; i<SDL_CDNumDrives(); ++i ) {
printf("Drive %d: \"%s\"\n", i, SDL_CDName(i));
}
Opening the default drive
SDL_CD *cdrom;
CDstatus status;
char *status_str;
cdrom = SDL_CDOpen(0);
if ( cdrom == NULL ) {
fprintf(stderr, "Couldn't open default CD-ROM drive: %s\n",
SDL_GetError());
exit(2);
}
status = SDL_CDStatus(cdrom);
switch (status) {
case CD_TRAYEMPTY:
status_str = "tray empty";
break;
case CD_STOPPED:
status_str = "stopped";
break;
case CD_PLAYING:
status_str = "playing";
break;
case CD_PAUSED:
status_str = "paused";
break;
case CD_ERROR:
status_str = "error state";
break;
}
printf("Drive status: %s\n", status_str);
if ( status >= CD_PLAYING ) {
int m, s, f;
FRAMES_TO_MSF(cdrom->cur_frame, &m, &s, &f);
printf("Currently playing track %d, %d:%2.2d\n",
cdrom->track[cdrom->cur_track].id, m, s);
}
Listing the tracks on a CD
SDL_CD *cdrom; /* Assuming this has already been set.. */
int i;
int m, s, f;
SDL_CDStatus(cdrom);
printf("Drive tracks: %d\n", cdrom->numtracks);
for ( i=0; i<cdrom->numtracks; ++i ) {
FRAMES_TO_MSF(cdrom->track[i].length, &m, &s, &f);
if ( f > 0 )
++s;
printf("\tTrack (index %d) %d: %d:%2.2d\n", i,
cdrom->track[i].id, m, s);
}
Play an entire CD
SDL_CD *cdrom; /* Assuming this has already been set.. */
Uint32 time_left(void)
{
Uint32 now;
now = SDL_GetTicks();
if(next_time <= now)
return 0;
else
return next_time - now;
}
/* Clean up on exit */
atexit(SDL_Quit);
SDL_UpdateRects(screen, 1, &dest);
Sint32 X, Y;
Uint32 pixel;
Uint8 *bits, bpp;
r = (pixel>>screen->format->Rshift)&0xFF;
g = (pixel>>screen->format->Gshift)&0xFF;
b = (pixel>>screen->format->Bshift)&0xFF;
*((bits)+screen->format->Rshift/8) = r;
*((bits)+screen->format->Gshift/8) = g;
*((bits)+screen->format->Bshift/8) = b;
}
break;
case 4:
*((Uint32 *)(bits)) = (Uint32)pixel;
break;
}
/* Update the display */
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
SDL_UpdateRect(screen, X, Y, 1, 1);
return;
Fastest possible surface blit
There are three different ways you can draw an image to the screen:
void ComplainAndExit(void)
{
fprintf(stderr, "Problem: %s\n", SDL_GetError());
exit(1);
}
/* Initialize SDL */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
ComplainAndExit();
}
atexit(SDL_Quit);
SDL must also be shut down before the program exits to make sure it cleans up
correctly. Calling SDL_Quit shuts down all subsystems and frees any resources
allocated to SDL.
void SDL_Quit(void);
Description
SDL_Quit shuts down all SDL subsystems and frees the resources allocated to
them. This should always be called before you exit. For the sake of simplicity
you can set SDL_Quit as your atexit call, like:
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO);
atexit(SDL_Quit);
.
.
Note: While using atexit maybe be fine for small programs, more
advanced users should shut down SDL in their own cleanup code. Plus,
using atexit in a library is a sure way to crash dynamically loaded code
See Also
SDL_QuitSubsystem, SDL_Init
subsystem_init=SDL_WasInit(SDL_INIT_EVERYTHING);
if(subsystem_init&SDL_INIT_VIDEO)
printf("Video is initialized.\n");
else
printf("Video is not initialized.\n");
if(SDL_WasInit(SDL_INIT_VIDEO)!=0)
printf("Video is initialized.\n");
else
printf("Video is not initialized.\n");
Uint32 subsystem_mask=SDL_INIT_VIDEO|SDL_INIT_AUDIO;
if(SDL_WasInit(subsystem_mask)==subsystem_mask)
printf("Video and Audio initialized.\n");
else
printf("Video and Audio not initialized.\n");
See Also
SDL_Init, SDL_Subsystem
char *SDL_GetError(void);
Description
SDL_GetError returns a NULL terminated string containing information about
the last internal SDL error.
Return Value
SDL_GetError returns a string containing the last error.
SDL presents a very simple interface to the display framebuffer. The framebuffer
is represented as an offscreen surface to which you can write directly. If you
want the screen to show what you have written, call the update function which
will guarantee that the desired portion of the screen is updated.
Before you call any of the SDL video functions, you must first call
SDL_Init(SDL_INIT_VIDEO), which initializes the video and events in the
SDL library. Check the return code, which should be 0, to see if there were any
errors in starting up.
If you use both sound and video in your application, you need to call
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) before opening the sound
device, otherwise under Win32 DirectX, you won't be able to set full-screen
display modes.
After you have initialized the library, you can start up the video display in a
number of ways. The easiest way is to pick a common screen resolution and
depth and just initialize the video, checking for errors. You will probably get
what you want, but SDL may be emulating your requested mode and converting
the display on update. The best way is to query, for the best video mode closest
to the desired one, and then convert your images to that pixel format.
SDL currently supports any bit depth >= 8 bits per pixel. 8 bpp formats are
considered 8-bit palettized modes, while 12, 15, 16, 24, and 32 bits per pixel are
considered "packed pixel" modes, meaning each pixel contains the RGB color
components packed in the bits of the pixel.
After you have initialized your video mode, you can take the surface that was
returned, and write to it like any other framebuffer, calling the update routine as
you go.
When you have finished your video access and are ready to quit your
application, you should call "SDL_Quit()" to shutdown the video and events.
SDL_Surface *SDL_GetVideoSurface(void);
Description
This function returns a pointer to the current display surface. If SDL is doing
format conversion on the display surface, this function returns the publicly
visible surface, not the real video surface.
See Also
SDL_Surface
SDL_VideoInfo *SDL_GetVideoInfo(void);
Description
This function returns a read-only pointer to information about the video
hardware. If this is called before SDL_SetVideoMode, the vfmt member of the
returned structure will contain the pixel format of the "best" video mode.
See Also
SDL_SetVideoMode, SDL_VideoInfo
If format is NULL, the mode list will be for the format returned by
SDL_GetVideoInfo()->vfmt. The flag parameter is an OR'd combination of
surface flags. The flags are the same as those used SDL_SetVideoMode and they
play a strong role in deciding what modes are valid. For instance, if you pass
SDL_HWSURFACE as a flag only modes that support hardware video surfaces will
be returned.
Example
SDL_Rect **modes;
int i;
.
.
.
The bits-per-pixel value returned is only a suggested mode. You can usually
request and bpp you want when setting the video mode and SDL will emulate
that color depth with a shadow video surface.
The arguments to SDL_VideoModeOK are the same ones you would pass to
SDL_SetVideoMode
Example
SDL_Surface *screen;
Uint32 bpp;
.
.
.
printf("Checking mode 640x480@16bpp.\n");
bpp=SDL_VideoModeOK(640, 480, 16, SDL_HWSURFACE);
if(!bpp){
printf("Mode not available.\n");
exit(-1);
}
The flags parameter is the same as the flags field of the SDL_Surface
structure. OR'd combinations of the following values are valid.
Note: Whatever flags SDL_SetVideoMode could satisfy are set in the flags
member of the returned surface.
Note: The bpp parameter is the number of bits per pixel, so a bpp of 24 uses
the packed representation of 3 bytes/pixel. For the more common 4
bytes/pixel mode, use a bpp of 32. Somewhat oddly, both 15 and 16 will
request a 2 bytes/pixel mode, but different pixel formats.
Return Value
The framebuffer surface, or NULL if it fails. The surface returned is freed by
SDL_Quit() and should nt be freed by the caller.
See Also
SDL_LockSurface, SDL_SetColors, SDL_Flip, SDL_Surface
If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire screen.
Note: It is adviced to call this function only once per frame, since each call
has some processing overhead. This is no restriction since you can pass any
number of rectangles each time.
When surface is the surface associated with the current display, the display
colormap will be updated with the requested colors. If SDL_HWPALETTE was set in
SDL_SetVideoMode flags, SDL_SetColors will always return 1, and the palette
is guaranteed to be set the way you desire, even if the window colormap has to
be warped or run under emulation.
The color components of a SDL_Color structure are 8-bits in size, giving you a
total of 2563 =16777216 colors.
Palettized (8-bit) screen surfaces with the SDL_HWPALETTE flag have two palettes,
a logical palette that is used for mapping blits to/from the surface and a physical
palette (that determines how the hardware will map the colors to the display).
SDL_SetColors modifies both palettes (if present), and is equivalent to calling
SDL_SetPalette with the flags set to (SDL_LOGPAL | SDL_PHYSPAL).
Return Value
If surface is not a palettized surface, this function does nothing, returning 0. If
all of the colors were set as passed to SDL_SetColors, it will return 1. If not all
the color entries were set exactly as given, it will return 0, and you should look
at the surface palette to determine the actual color palette.
Example
/* Create a display surface with a grayscale palette */
SDL_Surface *screen;
SDL_Color colors[256];
int i;
.
.
.
/* Fill colors with color information */
for(i=0;i<256;i++){
colors[i].r=i;
colors[i].g=i;
colors[i].b=i;
}
/* Create display */
screen=SDL_SetVideoMode(640, 480, 8, SDL_HWPALETTE);
if(!screen){
printf("Couldn't set video mode: %s\n", SDL_GetError());
exit(-1);
}
/* Set palette */
SDL_SetColors(screen, colors, 0, 256);
.
.
.
.
See Also
SDL_Color SDL_Surface, SDL_SetPalette, SDL_SetVideoMode
Palettized (8-bit) screen surfaces with the SDL_HWPALETTE flag have two palettes,
a logical palette that is used for mapping blits to/from the surface and a physical
palette (that determines how the hardware will map the colors to the display).
SDL_BlitSurface always uses the logical palette when blitting surfaces (if it has
to convert between surface pixel formats). Because of this, it is often useful to
modify only one or the other palette to achieve various special color effects (e.g.,
screen fading, color flashes, screen dimming).
This function can modify either the logical or physical palette by specifing
SDL_LOGPAL or SDL_PHYSPALthe in the flags parameter.
When surface is the surface associated with the current display, the display
colormap will be updated with the requested colors. If SDL_HWPALETTE was set in
SDL_SetVideoMode flags, SDL_SetPalette will always return 1, and the palette
is guaranteed to be set the way you desire, even if the window colormap has to
be warped or run under emulation.
The color components of a SDL_Color structure are 8-bits in size, giving you a
total of 2563=16777216 colors.
Return Value
If surface is not a palettized surface, this function does nothing, returning 0. If
all of the colors were set as passed to SDL_SetPalette, it will return 1. If not all
the color entries were set exactly as given, it will return 0, and you should look
at the surface palette to determine the actual color palette.
Example
/* Create a display surface with a grayscale palette */
SDL_Surface *screen;
SDL_Color colors[256];
int i;
.
.
.
/* Fill colors with color information */
for(i=0;i<256;i++){
colors[i].r=i;
colors[i].g=i;
colors[i].b=i;
}
/* Create display */
screen=SDL_SetVideoMode(640, 480, 8, SDL_HWPALETTE);
if(!screen){
printf("Couldn't set video mode: %s\n", SDL_GetError());
exit(-1);
}
/* Set palette */
SDL_SetPalette(screen, SDL_LOGPAL|SDL_PHYSPAL, colors, 0, 256);
.
.
.
.
See Also
SDL_SetColors, SDL_SetVideoMode, SDL_Surface, SDL_Color
This function adjusts the gamma based on the "gamma function" parameter, you
can directly specify lookup tables for gamma adjustment with
SDL_SetGammaRamp.
This function adjusts the gamma based on lookup tables, you can also have the
gamma calculated based on a "gamma function" parameter with
SDL_SetGamma.
If the format has a palette (8-bit) the index of the closest matching color in the
palette will be returned.
If the specified pixel format has an alpha component it will be returned as all 1
bits (fully opaque).
Return Value
A pixel value best approximating the given RGB color value for a given pixel
format. If the pixel format bpp (color depth) is less than 32-bpp then the unused
upper bits of the return value can safely be ignored (e.g., with a 16-bpp format
the return value can be assigned to a Uint16, and similarly a Uint8 for an 8-bpp
format).
See Also
SDL_GetRGB, SDL_GetRGBA, SDL_MapRGBA, SDL_PixelFormat
If the format has a palette (8-bit) the index of the closest matching color in the
palette will be returned.
If the specified pixel format has no alpha component the alpha value will be
ignored (as it will be in formats with a palette).
Return Value
A pixel value best approximating the given RGBA color value for a given pixel
format. If the pixel format bpp (color depth) is less than 32-bpp then the unused
upper bits of the return value can safely be ignored (e.g., with a 16-bpp format
the return value can be assigned to a Uint16, and similarly a Uint8 for an 8-bpp
format).
See Also
SDL_GetRGB, SDL_GetRGBA, SDL_MapRGB, SDL_PixelFormat
This function uses the entire 8-bit [0..255] range when converting color
components from pixel formats with less than 8-bits per RGB component (e.g., a
completely white pixel in 16-bit RGB565 format would return [0xff, 0xff, 0xff]
not [0xf8, 0xfc, 0xf8]).
See Also
SDL_GetRGBA, SDL_MapRGB, SDL_MapRGBA, SDL_PixelFormat
This function uses the entire 8-bit [0..255] range when converting color
components from pixel formats with less than 8-bits per RGB component (e.g., a
completely white pixel in 16-bit RGB565 format would return [0xff, 0xff, 0xff]
not [0xf8, 0xfc, 0xf8]).
If the surface has no alpha component, the alpha will be returned as 0xff (100%
opaque).
See Also
SDL_GetRGB, SDL_MapRGB, SDL_MapRGBA, SDL_PixelFormat
/* SDL interprets each pixel as a 32-bit number, so our masks must depend
on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
It should be noted, that since SDL 1.1.8 surface locks are recursive. This means
that you can lock a surface multiple times, but each lock must have a match
unlock.
.
.
SDL_LockSurface( surface );
.
/* Surface is locked */
/* Direct pixel access on surface here */
.
SDL_LockSurface( surface );
.
/* More direct pixel access on surface */
.
SDL_UnlockSurface( surface );
/* Surface is still locked */
/* Note: Is versions < 1.1.8, the surface would have been */
/* no longer locked at this stage */
.
SDL_UnlockSurface( surface );
/* Surface is now unlocked */
.
.
Return Value
SDL_LockSurface returns 0, or -1 if the surface couldn't be locked.
See Also
SDL_UnlockSurface
It should be noted that since 1.1.8, surface locks are recursive. See
SDL_LockSurface.
See Also
SDL_LockSurface
If flag is SDL_SRCCOLORKEY then key is the transparent pixel value in the source
image of a blit.
If flag is OR'd with SDL_RLEACCEL then the surface will be draw using RLE
acceleration when drawn with SDL_BlitSurface. The surface will actually be
encoded for RLE acceleration the first time SDL_BlitSurface or
SDL_DisplayFormat is called on the surface.
SDL_SetAlpha is used for setting the per-surface alpha value and/or enabling and
disabling alpha blending.
Thesurface parameter specifies which surface whose alpha attributes you wish
to adjust. flags is used to specify whether alpha blending should be used
(SDL_SRCALPHA) and whether the surface should use RLE acceleration for blitting
(SDL_RLEACCEL). flags can be an OR'd combination of these two options, one of
these options or 0. If SDL_SRCALPHA is not passed as a flag then all alpha
information is ignored when blitting the surface. The alpha parameter is the per-
surface alpha value; a surface need not have an alpha channel to use per-surface
alpha and blitting can still be accelerated with SDL_RLEACCEL.
Note: The per-surface alpha value of 128 is considered a special case and is
optimised, so it's much faster than other per-surface values.
RGBA->RGB The source is alpha-blended with the destination, using the alpha
with channel. SDL_SRCCOLORKEY and the per-surface alpha are ignored.
SDL_SRCALPHA
RGBA->RGB The RGB data is copied from the source. The source alpha
without channel and the per-surface alpha value are ignored.
SDL_SRCALPHA
RGBA- The source is alpha-blended with the destination using the source
>RGBA with alpha channel. The alpha channel in the destination surface is left
SDL_SRCALPHA untouched. SDL_SRCCOLORKEY is ignored.
RGB->RGB The source is alpha-blended with the destination using the per-
with surface alpha value. If SDL_SRCCOLORKEY is set, only the pixels
SDL_SRCALPHA not matching the colorkey value are copied.
Note: Note that RGBA->RGBA blits (with SDL_SRCALPHA set) keep the
alpha of the destination surface. This means that you cannot compose two
arbitrary RGBA surfaces this way and get the result you would expect from
"overlaying" them; the destination alpha will work as a mask.
Also note that per-pixel and per-surface alpha cannot be combined; the per-
pixel alpha is always used if available
Return Value
This function returns 0, or -1 if there was an error.
See Also
SDL_MapRGBA, SDL_GetRGBA, SDL_DisplayFormatAlpha, SDL_BlitSurface
The rectangle pointed to by rect will be clipped to the edges of the surface so
that the clip rectangle for a surface can never fall outside the edges of the
surface.
If rect is NULL the clipping rectangle will be set to the full size of the surface.
See Also
SDL_GetClipRect, SDL_BlitSurface, SDL_Surface
The rectangle pointed to by rect will be filled with the clipping rectangle of the
surface.
See Also
SDL_SetClipRect, SDL_BlitSurface, SDL_Surface
Only the position is used in the dstrect (the width and height are ignored).
If either srcrect or dstrect are NULL, the entire surface (src or dst) is copied.
The final blit rectangle is saved in dstrect after all clipping is performed
(srcrect is not modified).
If either of the surfaces were in video memory, and the blit returns -2, the video
memory was lost, so it should be reloaded with artwork and re-blitted:
while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) {
while ( SDL_LockSurface(image)) < 0 )
Sleep(10);
-- Write image pixels to image->pixels --
SDL_UnlockSurface(image);
}
This happens under DirectX 5.0 when the system switches away from your
fullscreen application. Locking the surface will also fail until you have access to
the video memory again.
See Also
SDL_LockSurface, SDL_FillRect, SDL_Surface, SDL_Rect
The color should be a pixel of the format used by the surface, and can be
generated by the SDL_MapRGB or SDL_MapRGBA functions. If the color
value contains an alpha value then the destination is simply "filled" with that
alpha information, no blending takes place.
If there is a clip rectangle set on the destination (set via SDL_SetClipRect) then
this function will clip based on the intersection of the clip rectangle and the
dstrect rectangle and the dstrect rectangle will be modified to represent the area
actually filled.
Return Value
This function returns 0 on success, or -1 on error.
See Also
SDL_MapRGB, SDL_MapRGBA, SDL_BlitSurface, SDL_Rect
/* XPM */
static const char *arrow[] = {
/* width height num_colors chars_per_pixel */
" 32 32 3 1",
/* colors */
"X c #000000",
". c #ffffff",
" c None",
/* pixels */
"X ",
"XX ",
"X.X ",
"X..X ",
"X...X ",
"X....X ",
"X.....X ",
"X......X ",
"X.......X ",
"X........X ",
"X.....XXXXX ",
"X..X..X ",
"X.X X..X ",
"XX X..X ",
"X X..X ",
" X..X ",
" X..X ",
" X..X ",
" XX ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"0,0"
};
i = -1;
for ( row=0; row<32; ++row ) {
for ( col=0; col<32; ++col ) {
if ( col % 8 ) {
data[i] <<= 1;
mask[i] <<= 1;
} else {
++i;
data[i] = mask[i] = 0;
}
switch (image[4+row][col]) {
case 'X':
data[i] |= 0x01;
k[i] |= 0x01;
break;
case '.':
mask[i] |= 0x01;
break;
case ' ':
break;
}
}
}
sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
}
See Also
SDL_FreeCursor, SDL_SetCursor, SDL_ShowCursor
SDL_Cursor *SDL_GetCursor(void);
Description
Returns the currently active mouse cursor.
See Also
SDL_SetCursor, SDL_CreateCursor, SDL_ShowCursor
void SDL_GL_SwapBuffers(void );
Description
Swap the OpenGL buffers, if double-buffering is supported.
See Also
SDL_SetVideoMode, SDL_GL_SetAttribute
The term 'overlay' is a misnomer since, unless the overlay is created in hardware,
the contents for the display surface underneath the area where the overlay is
shown will be overwritten when the overlay is displayed.
See Also
SDL_Overlay, SDL_DisplayYUVOverlay, SDL_FreeYUVOverlay
8-bit pixel formats are the easiest to understand. Since its an 8-bit format, we
have 8 BitsPerPixel and 1 BytesPerPixel. Since BytesPerPixel is 1, all
pixels are represented by a Uint8 which contains an index into palette-
>colors. So, to determine the color of a pixel in a 8-bit surface: we read the
color index from surface->pixels and we use that index to read the SDL_Color
structure from surface->format->palette->colors. Like so:
SDL_Surface *surface;
SDL_PixelFormat *fmt;
SDL_Color *color;
Uint8 index;
.
.
/* Create surface */
.
.
fmt=surface->format;
Pixel formats above 8-bit are an entirely different experience. They are
considered to be "TrueColor" formats and the color information is stored in the
pixels themselves, not in a palette. The mask, shift and loss fields tell us how the
color information is encoded. The mask fields allow us to isolate each color
component, the shift fields tell us the number of bits to the right of each
component in the pixel value and the loss fields tell us the number of bits lost
from each component when packing 8-bit color component in a pixel.
/* Extracting color components from a 32-bit color value */
SDL_PixelFormat *fmt;
SDL_Surface *surface;
Uint32 temp, pixel;
Uint8 red, green, blue, alpha;
.
.
.
fmt=surface->format;
SDL_LockSurface(surface);
pixel=*((Uint32*)surface->pixels);
SDL_UnlockSurface(surface);
printf("Pixel Color -> R: %d, G: %d, B: %d, A: %d\n", red, green, blue, alph
.
.
.
See Also
SDL_Surface, SDL_MapRGB
/* clipping information */
SDL_Rect clip_rect; /* Read-only */
If mask is NULL, the entire icon surface will be used as the icon.
Example
SDL_WM_SetIcon(SDL_LoadBMP("icon.bmp"), NULL);
See Also
SDL_SetVideoMode, SDL_WM_SetCaption
int SDL_WM_IconifyWindow(void);
Description
If the application is running in a window managed environment SDL attempts to
iconify/minimise it. If SDL_WM_IconifyWindow is successful, the application will
receive a SDL_APPACTIVE loss event.
Return Value
Returns non-zero on success or 0 if iconification is not support or was refused by
the window manager.
When mode is SDL_GRAB_QUERY the grab mode is not changed, but the current
grab mode is returned.
typedef enum {
SDL_GRAB_QUERY,
SDL_GRAB_OFF,
SDL_GRAB_ON
} SDL_GrabMode;
Return Value
The current/new SDL_GrabMode.
Internally, SDL stores all the events waiting to be handled in an event queue.
Using functions like SDL_PollEvent and SDL_PeepEvents you can observe and
handle waiting input events.
The key to event handling in SDL is the SDL_Event union. The event queue
itself is composed of a series of SDL_Event unions, one for each waiting event.
SDL_Event unions are read from the queue with the SDL_PollEvent function
and it is then up to the application to process the information stored with them.
Reading events from the event queue is done with either SDL_PollEvent or
SDL_PeepEvents. We'll use SDL_PollEvent and step through an example.
SDL_PollEvent removes the next event from the event queue, if there are no
events on the queue it returns 0 otherwise it returns 1. We use a while loop to
process each event in turn.
while(SDL_PollEvent(&test_event)) {
We need to know what kind of events we're looking for and the event type's of
those events. So lets assume we want to detect where the user is moving the
mouse pointer within our application. We look through our event types and
notice that SDL_MOUSEMOTION is, more than likely, the event we're looking for. A
little more research tells use that SDL_MOUSEMOTION events are handled within the
SDL_MouseMotionEvent structure which is the motion member of SDL_Event.
We can check for the SDL_MOUSEMOTION event type within our switch statement
like so:
case SDL_MOUSEMOTION:
All we need do now is read the information out of the motion member of
test_event.
printf("We got a motion event.\n");
printf("Current mouse position is: (%d, %d)\n", test_event.motion.x, test
break;
default:
printf("Unhandled Event!\n");
break;
}
}
printf("Event queue empty.\n");
It is also possible to push events onto the event queue and so use it as a two-way
communication path. Both SDL_PushEvent and SDL_PeepEvents allow you to
place events onto the event queue. This is usually used to place a SDL_USEREVENT
on the event queue, however you could use it to post fake input events if you
wished. Creating your own events is a simple matter of choosing the event type
you want, setting the type member and filling the appropriate member structure
with information.
SDL_Event user_event;
user_event.type=SDL_USEREVENT;
user_event.user.code=2;
user_event.user.data1=NULL;
user_event.user.data2=NULL;
SDL_PushEvent(&user_event);
See Also
SDL_PollEvent, SDL_PushEvent, SDL_PeepEvents
When the mouse leaves or enters the window area a SDL_APPMOUSEFOCUS type
activation event occurs, if the mouse entered the window then gain will be 1,
otherwise gain will be 0. A SDL_APPINPUTFOCUS type activation event occurs
when the application loses or gains keyboard focus. This usually occurs when
another application is made active. Finally, a SDL_APPACTIVE type event occurs
when the application is either minimised/iconified (gain=0) or restored.
Note: This event does not occur when an application window is first
created.
See Also
SDL_Event, SDL_GetAppState
The type and state actually report the same information, they just use different
values to do it! A keyboard event occurs when a key is released
(type=SDK_KEYUP or state=SDL_RELEASED) and when a key is pressed
(type=SDL_KEYDOWN or state=SDL_PRESSED). The information on what key was
pressed or released is in the keysym structure.
Simply put, a SDL_MOUSEMOTION type event occurs when a user moves the mouse
within the application window or when SDL_WarpMouse is called. Both the
absolute (x and y) and relative (xrel and yrel) coordinates are reported along
with the current button states (state). The button state can be interpreted using
the SDL_BUTTON macro (see SDL_GetMouseState).
When a mouse button press or release is detected then number of the button
pressed (from 1 to 255, with 1 usually being the left button and 2 the right) is
placed into button, the position of the mouse when this event occured is stored
in the x and the y fields. Like SDL_KeyboardEvent, information on whether the
event was a press or a release event is stored in both the type and state fields,
but this should be obvious.
See Also
SDL_Event, SDL_MouseMotionEvent
A SDL_JOYHATMOTION event occurs when ever a user moves a hat on the joystick.
The field which is the index of the joystick that reported the event and hat is the
index of the hat (for a more detailed exlaination see the Joystick section). value
is the current position of the hat. It is a logically OR'd combination of the
following values (whose meanings should be pretty obvious:) :
SDL_HAT_CENTERED
SDL_HAT_UP
SDL_HAT_RIGHT
SDL_HAT_DOWN
SDL_HAT_LEFT
SDL_HAT_RIGHTUP
SDL_HAT_RIGHTDOWN
SDL_HAT_LEFTUP
SDL_HAT_LEFTDOWN
See Also
SDL_Event, Joystick Functions, SDL_JoystickEventState,
SDL_JoystickGetHat
A VIDEOEXPOSE event is triggered when the screen has been modified outside
of the application, usually by the window manager and needs to be redrawn.
See Also
SDL_Event, SDL_SetEventFilter
event.type = SDL_USEREVENT;
event.user.code = my_event_code;
event.user.data1 = significant_data;
event.user.data2 = 0;
SDL_PushEvent(&event);
See Also
SDL_Event, SDL_PushEvent
The scancode field should generally be left alone, it is the hardware dependent
scancode returned by the keyboard. The sym field is extremely useful. It is the
SDL-defined value of the key (see SDL Key Syms. This field is very useful
when you are checking for certain key presses, like so:
.
.
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_KEYDOWN:
if(event.key.keysym.sym==SDLK_LEFT)
move_left();
break;
.
.
.
}
}
.
.
UNICODE translation does have a slight overhead so don't enable it unless its
needed.
See Also
SDLKey
SDLK_n 'n' n
SDLK_o 'o' o
SDLK_p 'p' p
SDLK_q 'q' q
SDLK_r 'r' r
SDLK_s 's' s
SDLK_t 't' t
SDLK_u 'u' u
SDLK_v 'v' v
SDLK_w 'w' w
SDLK_x 'x' x
SDLK_y 'y' y
SDLK_z 'z' z
SDLK_DELETE '^?' delete
SDLK_KP0 keypad 0
SDLK_KP1 keypad 1
SDLK_KP2 keypad 2
SDLK_KP3 keypad 3
SDLK_KP4 keypad 4
SDLK_KP5 keypad 5
SDLK_KP6 keypad 6
SDLK_KP7 keypad 7
SDLK_KP8 keypad 8
SDLK_KP9 keypad 9
SDLK_KP_PERIOD '.' keypad period
SDLK_KP_DIVIDE '/' keypad divide
SDLK_KP_MULTIPLY '*' keypad multiply
SDLK_KP_MINUS '-' keypad minus
SDLK_KP_PLUS '+' keypad plus
SDLK_KP_ENTER '\r' keypad enter
SDLK_KP_EQUALS '=' keypad equals
SDLK_UP up arrow
SDLK_DOWN down arrow
SDLK_RIGHT right arrow
SDLK_LEFT left arrow
SDLK_INSERT insert
SDLK_HOME home
SDLK_END end
SDLK_PAGEUP page up
SDLK_PAGEDOWN page down
SDLK_F1 F1
SDLK_F2 F2
SDLK_F3 F3
SDLK_F4 F4
SDLK_F5 F5
SDLK_F6 F6
SDLK_F7 F7
SDLK_F8 F8
SDLK_F9 F9
SDLK_F10 F10
SDLK_F11 F11
SDLK_F12 F12
SDLK_F13 F13
SDLK_F14 F14
SDLK_F15 F15
SDLK_NUMLOCK numlock
SDLK_CAPSLOCK capslock
SDLK_SCROLLOCK scrollock
SDLK_RSHIFT right shift
SDLK_LSHIFT left shift
SDLK_RCTRL right ctrl
SDLK_LCTRL left ctrl
void SDL_PumpEvents(void);
Description
Pumps the event loop, gathering events from the input devices.
SDL_PumpEvents gathers all the pending input information from devices and
places it on the event queue. Without calls to SDL_PumpEvents no events would
ever be placed on the queue. Often calls the need for SDL_PumpEvents is hidden
from the user since SDL_PollEvent and SDL_WaitEvent implicitly call
SDL_PumpEvents. However, if you are not polling or waiting for events (e.g. your
filtering them), then you must call SDL_PumpEvents to force an event queue
update.
Note: You can only call this function in the thread that set the video mode.
See Also
SDL_PollEvent
If event is not NULL, the next event is removed from the queue and stored in that
area.
See Also
SDL_Event, SDL_PollEvent
If event is not NULL, the next event is removed from the queue and stored in that
area.
Examples
SDL_Event event; /* Event structure */
.
.
.
/* Check for events */
while(SDL_PollEvent(&event)){ /* Loop until there are no events left on the qu
switch(event.type){ /* Process the appropiate event type */
case SDL_KEYDOWN: /* Handle a KEYDOWN event */
printf("Oh! Key press\n");
break;
case SDL_MOUSEMOTION:
.
.
.
default: /* Report an unhandled event */
printf("I don't know what this event is!\n");
}
}
See Also
SDL_Event, SDL_WaitEvent, SDL_PeepEvents
Note: Pushing device input events onto the queue doesn't modify the state
of the device within SDL.
Return Value
Returns 0 on success or -1 if the event couldn't be pushed.
Examples
See SDL_Event.
See Also
SDL_PollEvent, SDL_PeepEvents, SDL_Event
If the filter returns 1, then the event will be added to the internal queue. If it
returns 0, then the event will be dropped from the queue. This allows selective
filtering of dynamically.
There is one caveat when dealing with the SDL_QUITEVENT event type. The event
filter is only called when the window manager desires to close the application
window. If the event filter returns 1, then the window will be closed, otherwise
the window will remain open if possible. If the quit event is generated by an
interrupt signal, it will bypass the internal queue and be delivered to the
application at the next event poll.
Note: Be Careful! The event filter function may run in a different thread so
be careful what you do within it.
See Also
SDL_Event, SDL_GetEventFilter, SDL_PushEvent
SDL_EventFilter SDL_GetEventFilter(void);
Description
This function retrieces a pointer to the event filter that was previously set using
SDL_SetEventFilter. An SDL_EventFilter function is defined as:
SDLMod SDL_GetModState(void);
Description
Returns the current state of the modifier keys (CTRL, ALT, etc.).
Return Value
The return value can be an OR'd combination of the SDLMod enum.
SDLMod
typedef enum {
KMOD_NONE = 0x0000,
KMOD_LSHIFT= 0x0001,
KMOD_RSHIFT= 0x0002,
KMOD_LCTRL = 0x0040,
KMOD_RCTRL = 0x0080,
KMOD_LALT = 0x0100,
KMOD_RALT = 0x0200,
KMOD_LMETA = 0x0400,
KMOD_RMETA = 0x0800,
KMOD_NUM = 0x1000,
KMOD_CAPS = 0x2000,
KMOD_MODE = 0x4000,
} SDLMod;
Simply pass your desired modifier states into modstate. This value my be a
logical OR'd combination of the following:
typedef enum {
KMOD_NONE = 0x0000,
KMOD_LSHIFT= 0x0001,
KMOD_RSHIFT= 0x0002,
KMOD_LCTRL = 0x0040,
KMOD_RCTRL = 0x0080,
KMOD_LALT = 0x0100,
KMOD_RALT = 0x0200,
KMOD_LMETA = 0x0400,
KMOD_RMETA = 0x0800,
KMOD_NUM = 0x1000,
KMOD_CAPS = 0x2000,
KMOD_MODE = 0x4000,
} SDLMod;
See Also
SDL_GetModState
A value of 1 for enable enables Unicode translation; 0 disables it, and -1 leaves
it unchanged (useful for querying the current translation mode).
Note that only key press events will be translated, not release events.
Return Value
Returns the previous translation mode (0 or 1).
See Also
SDL_keysym
Setting delay to 0 disables key repeating completely. Good default values are
SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL.
Return Value
Returns 0 on success and -1 on failure.
Uint8 SDL_GetAppState(void);
Description
This function returns the current state of the application. The value returned is a
bitwise combination of:
Joysticks, and other similar input devices, have a very strong role in game
playing and SDL provides comprehensive support for them. Axes, Buttons, POV
Hats and trackballs are all supported.
While using the functions describe in this secton may seem like the best way to
access and read from joysticks, in most cases they aren't. Ideally joysticks should
be read using the event system. To enable this, you must set the joystick event
processing state with SDL_JoystickEventState. Joysticks must be opened
before they can be used of course.
Note: If you are not handling the joystick via the event queue then you
must explicitly request a joystick update by calling SDL_JoystickUpdate.
int SDL_NumJoysticks(void);
Description
Counts the number of joysticks attached to the system.
Return Value
Returns the number of attached joysticks
See Also
SDL_JoystickName, SDL_JoystickOpen
if(joy)
{
printf("Opened Joystick 0\n");
printf("Name: %s\n", SDL_JoystickName(0));
printf("Number of Axes: %d\n", SDL_JoystickNumAxes(joy));
printf("Number of Buttons: %d\n", SDL_JoystickNumButtons(joy));
printf("Number of Balls: %d\n", SDL_JoystickNumBalls(joy));
}
else
printf("Couldn't open Joystick 0\n");
// Close if opened
if(SDL_JoystickOpened(0))
SDL_JoystickClose(joy);
}
See Also
SDL_JoystickClose
void SDL_JoystickUpdate(void);
Description
Updates the state(position, buttons, etc.) of all open joysticks. If joystick events
have been enabled with SDL_JoystickEventState then this is called
automatically in the event loop.
See Also
SDL_JoystickEventState
On most modern joysticks the X axis is usually represented by axis 0 and the Y
axis by axis 1. The value returned by SDL_JoystickGetAxis is a signed integer
(-32768 to 32768) representing the current position of the axis, it maybe
necessary to impose certain tolerances on these values to account for jitter. It is
worth noting that some joysticks use axes 2 and 3 for extra buttons.
Return Value
Returns a 16-bit signed integer representing the current position of the axis.
Examples
Sint16 x_move, y_move;
SDL_Joystick *joy1;
.
.
x_move=SDL_JoystickGetAxis(joy1, 0);
y_move=SDL_JoystickGetAxis(joy1, 1);
See Also
SDL_JoystickNumAxes
SDL_HAT_CENTERED
SDL_HAT_UP
SDL_HAT_RIGHT
SDL_HAT_DOWN
SDL_HAT_LEFT
SDL_HAT_RIGHTUP
SDL_HAT_RIGHTDOWN
SDL_HAT_LEFTUP
SDL_HAT_LEFTDOWN
See Also
SDL_JoystickNumHats
Trackballs can only return relative motion since the last call to
SDL_JoystickGetBall, these motion deltas a placed into dx and dy.
Return Value
Returns 0 on success or -1 on failure
Examples
int delta_x, delta_y;
SDL_Joystick *joy;
.
.
.
SDL_JoystickUpdate();
if(SDL_JoystickGetBall(joy, 0, &delta_x, &delta_y)==-1)
printf("TrackBall Read Error!\n");
printf("Trackball Delta- X:%d, Y:%d\n", delta_x, delta_y);
See Also
SDL_JoystickNumBalls
Sound on the computer is translated from waves that you hear into a series of
values, or samples, each representing the amplitude of the wave. When these
samples are sent in a stream to a sound card, an approximation of the original
wave can be recreated. The more bits used to represent the amplitude, and the
greater frequency these samples are gathered, the closer the approximated sound
is to the original, and the better the quality of sound.
This library supports both 8 and 16 bit signed and unsigned sound samples, at
frequencies ranging from 11025 Hz to 44100 Hz, depending on the underlying
hardware. If the hardware doesn't support the desired audio format or frequency,
it can be emulated if desired (See SDL_OpenAudio())
freq
The number of samples sent to the sound device every second.
Common values are 11025, 22050 and 44100. The higher the better.
AUDIO_U16 or AUDIO_U16LSB
AUDIO_S16 or AUDIO_S16LSB
channels
The number of seperate sound channels. 1 is mono (single channel), 2
is stereo (dual channel).
When used with SDL_OpenAudio this refers to the size of the audio
samples
buffer in samples. A sample a chunk of audio data of the size
specified in format mulitplied by the number of channels. When the
SDL_AudioSpec is used with SDL_LoadWAV samples is set to 4096.
See Also
SDL_OpenAudio, SDL_LoadWAV
You must then fill this structure with your desired audio specifications.
desired->freq
desired->format
desired->samples
The desired size of the audio buffer in samples. This number should be a
power of two, and may be adjusted by the audio driver to a value more
suitable for the hardware. Good values seem to range between 512 and
8192 inclusive, depending on the application and CPU speed. Smaller
values yield faster response time, but can lead to underflow if the
application is doing heavy processing and cannot fill the audio buffer in
time. A stereo sample consists of both right and left channels in LR
ordering. Note that the number of samples is directly related to time by the
following formula: ms = (samples*1000)/freq
desired->callback
This should be set to a function that will be called when the audio device is
ready for more data. It is passed a pointer to the audio buffer, and the length
in bytes of the audio buffer. This function usually runs in a separate thread,
and so you should protect data structures that it accesses by calling
SDL_LockAudio and SDL_UnlockAudio in your code. The callback prototype
is:
void callback(void *userdata, Uint8 *stream, int len);
desired->userdata
SDL_OpenAudio calculates the size and silence fields for both the desired and
obtained specifications. The size field stores the total size of the audio buffer in
bytes, while the silence stores the value used to represent silence in the audio
buffer
The audio device starts out playing silence when it's opened, and should be
enabled for playing by calling SDL_PauseAudio(0) when you are ready for your
audio callback function to be called. Since the audio driver may modify the
requested size of the audio buffer, you should allocate any local mixing buffers
after you open the audio device.
Examples
/* Prototype of our callback function */
void my_audio_callback(void *userdata, Uint8 *stream, int len);
/* Mono */
desired->channels=0;
/* Large audio buffer reduces risk of dropouts but increases response time */
desired->samples=8192;
desired->userdata=NULL;
SDL_audiostatusSDL_GetAudioStatus(void);
Description
typedef enum{
SDL_AUDIO_STOPPED,
SDL_AUDIO_PAUSED,
SDL_AUDIO_PLAYING
} SDL_audiostatus;
If this function succeeds, it returns the given SDL_AudioSpec, filled with the
audio data format of the wave data, and sets audio_buf to a malloc'd buffer
containing the audio data, and sets audio_len to the length of that audio buffer,
in bytes. You need to free the audio buffer with SDL_FreeWAV when you are done
with it.
This function returns NULL and sets the SDL error message if the wave file
cannot be opened, uses an unknown data format, or is corrupt. Currently raw,
MS-ADPCM and IMA-ADPCM WAVE files are supported.
Example
SDL_AudioSpec wav_spec;
Uint32 wav_length;
Uint8 *wav_buffer;
Uint8 *buf
This points to the audio data that will be used in the conversion. It is both
the source and the destination, which means the converted audio data
overwrites the original data. It also means that the converted data may be
larger than the original data (if you were converting from 8-bit to 16-bit, for
instance), so you must ensure buf is large enough. See below.
int len
int len_mult
As explained above, the audio buffer needs to be big enough to store the
converted data, which may be bigger than the original audio data. The
length of buf should be len*len_mult.
double len_ratio
When you have finished converting your audio data, you need to know how
much of your audio buffer is valid. len*len_ratio is the size of the
converted audio data in bytes. This is very similar to len_mult, however
when the convert audio data is shorter than the original len_mult would be
1. len_ratio, on the other hand, would be a fractional number between 0
and 1.
See Also
SDL_BuildAudioCVT, SDL_ConvertAudio, SDL_AudioSpec
src_format and dst_format are the source and destination format of the
conversion. (For information on audio formats see SDL_AudioSpec).
src_channels and dst_channels are the number of channels in the source and
destination formats. Finally, src_rate and dst_rate are the frequency or
samples-per-second of the source and destination formats. Once again, see
SDL_AudioSpec.
Return Values
Returns -1 if the filter could not be built or 1 if it could.
Examples
See SDL_ConvertAudio.
See Also
SDL_ConvertAudio, SDL_AudioCVT
If the conversion completed successfully then the converted audio data can be
read from cvt->buf. The amount of valid, converted, audio data in the buffer is
equal to cvt->len*cvt->len_ratio.
Examples
/* Converting some WAV data to hardware format */
void my_audio_callback(void *userdata, Uint8 *stream, int len);
free(desired);
/* Build AudioCVT */
ret = SDL_BuildAudioCVT(&wav_cvt,
wav_spec.format, wav_spec.channels, wav_spec.freq,
obtained->format, obtained->channels, obtained->freq);
/* do whatever */
.
.
.
.
See Also
SDL_BuildAudioCVT, SDL_AudioCVT
Note: Do not use this function for mixing together more than two streams
of sample data. The output from repeated application of this function may
be distorted by clipping, because there is no accumulator with greater range
than the input (not to mention this being an inefficient way of doing it). Use
mixing functions from SDL_mixer, OpenAL, or write your own mixer
instead.
See Also
SDL_OpenAudio
void SDL_LockAudio(void);
Description
The lock manipulated by these functions protects the callback function. During a
LockAudio period, you can be guaranteed that the callback function is not
running. Do not call these from the callback function or you will cause deadlock.
See Also
SDL_OpenAudio
void SDL_UnlockAudio(void);
Description
Unlocks a previous SDL_LockAudio call.
See Also
SDL_OpenAudio
void SDL_CloseAudio(void);
Description
This function shuts down audio processing and closes the audio device.
See Also
SDL_OpenAudio
You use this API to perform all the basic functions of a CD player, including
listing the tracks, playing, stopping, and ejecting the CD-ROM. (Currently,
multi-changer CD drives are not supported.)
Before you call any of the SDL CD-ROM functions, you must first call
"SDL_Init(SDL_INIT_CDROM)", which scans the system for CD-ROM drives, and
sets the program up for audio control. Check the return code, which should be 0,
to see if there were any errors in starting up.
After you have initialized the library, you can find out how many drives are
available using the SDL_CDNumDrives() function. The first drive listed is the
system default CD-ROM drive. After you have chosen a drive, and have opened
it with SDL_CDOpen(), you can check the status and start playing if there's a CD
in the drive.
int SDL_CDNumDrives(void);
Description
Returns the number of CD-ROM drives on the system.
See Also
SDL_CDOpen
"E:"
"/dev/disk/ide/1/master"
See Also
SDL_CDNumDrives
Drives are numbered starting with 0. Drive 0 is the system default CD-ROM.
Examples
SDL_CD *cdrom;
int cur_track;
int min, sec, frame;
SDL_Init(SDL_INIT_CDROM);
atexit(SDL_Quit);
SDL_CDClose(cdrom);
See Also
SDL_CD, SDL_CDtrack, SDL_CDClose
If the drive has a CD in it, the table of contents of the CD and current play
position of the CD will be stored in the SDL_CD structure.
The macro CD_INDRIVE is provided for convenience, and given a status returns
true if there's a disk in the drive.
if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) {
/* clamp to the actual number of tracks on the CD */
if (track >= cdrom->numtracks) {
track = cdrom->numtracks-1;
}
if ( SDL_CDPlayTracks(cdrom, track, 0, 1, 0) == 0 ) {
playing = 1;
}
}
return playing;
}
See Also
SDL_CD
A frame is the base data unit of a CD. CD_FPS frames is equal to 1 second of
music. SDL provides two macros for converting between time and frames:
FRAMES_TO_MSF(f, M,S,F) and MSF_TO_FRAMES.
Examples
int min, sec, frame;
int frame_offset;
SDL provides functions for creating threads, mutexes, semphores and condition
variables.
In general, you must be very aware of concurrency and data integrity issues
when writing multi-threaded programs. Some good guidelines include:
Never terminate threads, always set a flag and wait for them to quit
Think very carefully about all possible ways your code may interact
Uint32 SDL_ThreadID(void);
Description
Get the 32-bit thread identifier for the current thread.
SDL_mutex *SDL_CreateMutex(void);
Description
Create a new, unlocked mutex.
Examples
SDL_mutex *mut;
mut=SDL_CreateMutex();
.
.
if(SDL_mutexP(mut)==-1){
fprintf(stderr, "Couldn't lock mutex\n");
exit(-1);
}
.
/* Do stuff while mutex is locked */
.
.
if(SDL_mutexV(mut)==-1){
fprintf(stderr, "Couldn't unlock mutex\n");
exit(-1);
}
SDL_DestroyMutex(mut);
See Also
SDL_mutexP, SDL_mutexV, SDL_DestroyMutex
my_sem = SDL_CreateSemaphore(INITIAL_SEM_VALUE);
if (my_sem == NULL) {
return CREATE_SEM_FAILED;
}
See Also
SDL_DestroySemaphore, SDL_SemWait, SDL_SemTryWait, SDL_SemWaitTimeout,
SDL_SemPost, SDL_SemValue
After SDL_SemWait() is successful, the semaphore can be released and its count
atomically incremented by a successful call to SDL_SemPost.
Return Value
Returns 0 if successful or -1 if there was an error (leaving the semaphore
unchanged).
Examples
if (SDL_SemWait(my_sem) == -1) {
return WAIT_FAILED;
}
...
SDL_SemPost(my_sem);
See Also
SDL_CreateSemaphore, SDL_DestroySemaphore, SDL_SemTryWait,
SDL_SemWaitTimeout, SDL_SemPost, SDL_SemValue
After SDL_SemTryWait is successful, the semaphore can be released and its count
atomically incremented by a successful call to SDL_SemPost.
Return Value
Returns 0 if the semaphore was successfully locked or either
SDL_MUTEX_TIMEOUT or -1 if the thread would have suspended or there
was an error, respectivly.
If the semaphore was not successfully locked, the semaphore will be unchanged.
Examples
res = SDL_SemTryWait(my_sem);
if (res == SDL_MUTEX_TIMEOUT) {
return TRY_AGAIN;
}
if (res == -1) {
return WAIT_ERROR;
}
...
SDL_SemPost(my_sem);
See Also
SDL_CreateSemaphore, SDL_DestroySemaphore, SDL_SemWait,
SDL_SemWaitTimeout, SDL_SemPost, SDL_SemValue
If the semaphore was not successfully locked, the semaphore will be unchanged.
Examples
res = SDL_SemWaitTimeout(my_sem, WAIT_TIMEOUT_MILLISEC);
if (res == SDL_MUTEX_TIMEOUT) {
return TRY_AGAIN;
}
if (res == -1) {
return WAIT_ERROR;
}
...
SDL_SemPost(my_sem);
See Also
SDL_CreateSemaphore, SDL_DestroySemaphore, SDL_SemWait, SDL_SemTryWait,
SDL_SemPost, SDL_SemValue
SDL_cond *SDL_CreateCond(void);
Description
Creates a condition variable.
Examples
SDL_cond *cond;
cond=SDL_CreateCond();
.
.
/* Do stuff */
.
.
SDL_DestroyCond(cond);
See Also
SDL_DestroyCond, SDL_CondWait, SDL_CondSignal
SDL provides several cross-platform functions for dealing with time. It provides
a way to get the current time, a way to wait a little while, and a simple timer
mechanism. These functions give you two ways of moving an object every x
milliseconds:
Use a timer callback function. This may have the bad effect that it runs in a
seperate thread or uses alarm signals, but it's easier to implement.
Or you can get the number of milliseconds passed, and move the object if,
for example, 30 ms passed.
Uint32 SDL_GetTicks(void);
Description
Get the number of milliseconds since the SDL library initialization. Note that
this value wraps if the program runs for more than ~49 days.
See Also
SDL_Delay
The timer callback function may run in a different thread than your main
program, and so shouldn't call any functions from within itself. You may always
call SDL_PushEvent, however.
The timer callback function may run in a different thread than your main
constant, and so shouldn't call any functions from within itself.
The maximum resolution of this timer is 10 ms, which means that if you request
a 16 ms timer, your callback will run approximately 20 ms later on an unloaded
system. If you wanted to set a flag signaling a frame update at 30 frames per
second (every 33 ms), you might set a timer for 30 ms (see example below).
Note: This function is kept for compatibility but has been superseded by the
new timer functions SDL_AddTimer and SDL_RemoveTimer which
support multiple timers.
Examples
SDL_SetTimer((33/10)*10, my_callback);
See Also
SDL_AddTimer
Prev Home
SDL_RemoveTimer Up