Good morning. I’m writing my first SDL application (combining parts
from various examples and test apps), which is intended (eventually)
to be a slide-show-to-music program. I’ve set up two threads, one
which will handle video, the other of which will handle audio.
There’s also the main thread, which currently isn’t doing anything
important.
This application works – for a while. As soon as the video thread
ends, the application exits even though the audio thread should still
be running. Furthermore, it seems to exit non-gracefully (although
without a core dump) in that if I run it full-screen, it does not
restore the screen resolution back to its original (under X on
Linux).
There does not appear to be a function that a thread should call to
exit itself gracefully; it seems that it is just supposed to return to
its caller. Is this incorrect? Is there a proper way to do it?
Why does the application exit when the video thread completes?
Application follows…
Thanks!
Derrell----------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include “SDL.h”
#include “SDL_thread.h”
#include “SDL_image.h”
#include “smpeg/smpeg.h”
#ifndef TRUE
define TRUE 1
define FALSE 0
#endif
#if 0
#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768
#else
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#endif
#define P puts
#define SLIDE “/winstuff/cap/mmcs/Slide Shows/Slides/199901-01/0022.jpg”
#define SOUND “/var/tmp/moon_landing.mp3”
static int
videoThread(void * pData)
{
int depth;
SDL_Surface * pScreen;
SDL_Surface * pImage;
/* Create a display for the image */
depth = SDL_VideoModeOK(IMAGE_WIDTH, IMAGE_HEIGHT, 32, SDL_SWSURFACE);
if ((pScreen = SDL_SetVideoMode(IMAGE_WIDTH,
IMAGE_HEIGHT,
depth,
(SDL_DOUBLEBUF |
#if 0
SDL_FULLSCREEN |
#endif
SDL_HWPALETTE |
SDL_HWSURFACE))) == NULL)
{
fprintf(stderr,“Couldn’t set %dx%dx%d video mode: %s\n”,
IMAGE_WIDTH, IMAGE_HEIGHT, depth, SDL_GetError());
SDL_Quit();
exit(1);
}
/* No cursor */
SDL_ShowCursor(0);
/* Open the image file */
if ((pImage = IMG_Load(SLIDE)) == NULL)
{
fprintf(stderr,"Couldn't load %s: %s\n", SLIDE, SDL_GetError());
SDL_Quit();
exit(1);
}
/* Set the palette, if one exists */
if (pImage->format->palette)
{
SDL_SetColors(pScreen, pImage->format->palette->colors,
0, pImage->format->palette->ncolors);
}
/* Display the image */
SDL_BlitSurface(pImage, NULL, pScreen, NULL);
SDL_Flip(pScreen);
SDL_Delay(5000);
#if 0 /* See if this is causing it to exit… Nope. Still exits. /
/ We’re done! */
SDL_FreeSurface(pImage);
#endif
P("videoThread leaving");
return 0;
}
static int
audioThread(void * pData)
{
SMPEG * hMpeg;
SMPEG_Info info;
if (SMPEG_error(hMpeg = SMPEG_new(SOUND, &info, TRUE)))
{
fprintf(stderr, "%s\n", SMPEG_error(hMpeg));
SMPEG_delete(hMpeg);
}
SMPEG_enableaudio(hMpeg, TRUE);
SMPEG_setvolume(hMpeg, 100);
/* Play it, and wait for playback to complete */
SMPEG_play(hMpeg);
while (SMPEG_status(hMpeg) == SMPEG_PLAYING)
{
SDL_Delay(1000/2);
}
SMPEG_delete(hMpeg);
return 0;
}
int main(int argc,
char *argv[])
{
int i;
#if 1 /* Do we need this? It’s function is not documented /
/ Initialize the SDL library for event thread */
if (SDL_Init(SDL_INIT_EVENTTHREAD) < 0)
{
fprintf(stderr,
“Couldn’t initialize SDL event thread: %s\n”,
SDL_GetError());
return 1;
}
#endif
/* Initialize the SDL library for audio */
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{
fprintf(stderr,
"Couldn't initialize SDL audio: %s\n",
SDL_GetError());
return 1;
}
/* Initialize the SDL library for video */
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr,
"Couldn't initialize SDL video: %s\n",
SDL_GetError());
return 1;
}
if ((SDL_CreateThread(videoThread, NULL)) == NULL)
{
fprintf(stderr, "Couldn't create video thread: %s\n", SDL_GetError());
return 1;
}
if ((SDL_CreateThread(audioThread, NULL)) == NULL)
{
fprintf(stderr, "Couldn't create audio thread: %s\n", SDL_GetError());
return 1;
}
P("About to delay");
SDL_Delay(3000);
P("Delay finished.");
/* Wait for any keyboard or mouse input */
for (i=SDL_NOEVENT; i<SDL_NUMEVENTS; ++i)
{
switch (i)
{
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONDOWN:
case SDL_QUIT:
/* Valid event, keep it */
break;
default:
/* We don't want this event */
SDL_EventState((Uint8)i, SDL_IGNORE);
break;
}
}
for (;;)
{
SDL_WaitEvent(NULL);
}
P("About to SDL_Quit() -- never gets here for some reason");
SDL_Quit();
P("See ya!");
return 0;
}