PDA

View Full Version : SDL_Events not catching any events



masonwheeler
26-02-2008, 07:52 PM
I'm trying to make my program work in Delphi using a translated version of Bob Pendelton's FastEvents library, which is basically a wrapper around SDL_Events that has some beneficial features I'm interested in. Problem is, I can't get it to return any events.

This routine never returns:
procedure FE_WaitEvent(event: PSDL_Event);
begin
SDL_LockMutex(eventLock);
while SDL_PollEvent(event) <= 0 do
SDL_CondWait(eventWait, eventLock);
SDL_UnlockMutex(eventLock);
SDL_CondSignal(eventWait);
end;

I've initialized SDL and the FastEvents unit before calling this, and both initialized successfully.
assert(SDL_Init(SDL_INIT_AUDIO or SDL_INIT_TIMER) = 0);
assert(FE_Init = 0);

The routine is running in a dedicated input-management thread. I was told how to do this on the SDL development list (see this thread for details (http://lists.libsdl.org/pipermail/sdl-libsdl.org/2008-February/064334.html)) and have followed the instructions I was given. I also removed the applicable form's OnKeyDown event handler, just to see if that would make a difference. It didn't. So does anyone know what I'm doing wrong?

Mason

technomage
26-02-2008, 08:08 PM
SDL_PollEvent will return 0 if there are no events, so in this case it will enter the while loop and stay there until an event is recieved.

This is correct behaviour for the FE_WaitEvent was what you are asking is for the app to wait for an event before continuing.

If you are running your rendering and input on the main app thread then you should FE_PollEvent or SDL_PollEvent. Here is an example


while not Done do
begin

while SDL_PollEvent(@event) > 0 do
begin
if event.type_ = SDL_QUITEV then Done := True;
end;
// Render stuff
SDL_Flip(screen);
end;


This will poll the event system and return if not events are present. If I remember correctly Fast Events has a FE_PollEvent which you can plug in there.

masonwheeler
26-02-2008, 08:26 PM
Two things.

First, I'm not doing input on the same thread as video rendering. That's a really bad idea, since they can get in each other's way. (Especially because, in my program, certain input-handling routines contain calls to the Sleep() routine.)

Second:

SDL_PollEvent will return 0 if there are no events, so in this case it will enter the while loop and stay there until an event is recieved.

This is correct behaviour for the FE_WaitEvent was what you are asking is for the app to wait for an event before continuing.
I suppose I should have mentioned this, but I guess it seemed too obvious to me. The procedure never returns, no matter how many keys I hit. For some reason, it's not catching the events.

savage
26-02-2008, 11:19 PM
Having looked at the orginal C code, think the code should be...


procedure FE_WaitEvent(event: PSDL_Event);
begin
SDL_LockMutex(eventLock);
while SDL_PollEvent(event) >= 0 do
SDL_CondWait(eventWait, eventLock);
SDL_UnlockMutex(eventLock);
SDL_CondSignal(eventWait);
end;


I agree with Dean, because SDL_PollEvent return 0 or 1. 0 for no event and 1 if there is an event. It seems pointless to be notified of "no event", but I suppose there may in occasions when you may want to take advantage of that idle time.

The thing I don't quite understand is how I can use FE_WaitEvents to actually be notified of something.

masonwheeler
26-02-2008, 11:39 PM
No, the comparison is definitely written the right way in my translation. Here's what's happening. (I had to dig around in the SDL code a bit, but it sorta makes sense now.)

It locks the mutex for thread safety, then checks SDL_PollEvent(). SDL_PollEvent scans for new events from the OS. If it finds nothing, it returns 0, and SDL_CondWait() gets called, which temporarily unlocks the mutex in case any other threads want to push locally-created events onto the event queue, then loops back up to SDL_PollEvent again.

Repeat, repeat, and keep on repeating until it finds something, either from the OS or the application, in which case SDL_PollEvent returns 1, the comparison evaluates false, the mutex unlocks, and the routine exits, with a description of the event in the event parameter, which, being a pointer, doesn't need to be passed in as a var.

That's what it's supposed to be doing. But it's not actually catching my keystrokes. And with the base library written in C and made available to Delphi as a precompiled DLL, I set breakpoints in the debugger and find out why. :(

(If this seems like a strange way to handle things, it's because this unit was originally written to handle incoming network traffic, which can generate enough events to flood the SDL_Events queue under ordinary circumstances. The whole FastEvents library is heavily optimized for speed, so as to not miss any packets.)

savage
26-02-2008, 11:58 PM
Ah ok I get it then. Well then for me, on Windows, it executes as you describe if I do the following...

while ( not Done ) do
begin
FE_WaitEvent( @event );

case event.type_ of
SDL_QUITEV :
begin
Done := true;
end;

SDL_KEYDOWN :
begin
// handle key presses
HandleKeyPress( @event.key.keysym );
end;

SDL_VIDEORESIZE :
begin
surface := SDL_SetVideoMode( event.resize.w, event.resize.h, SCREEN_BPP, videoflags );
if ( surface = nil ) then
begin
Log.LogError( Format( 'Could not get a surface after resize : %s', [SDL_GetError] ),
'Main' );
TerminateApplication;
end;
InitGL;
ResizeWindow( event.resize.w, event.resize.h );
end;
end;
// draw the scene
DrawGLScene;
end;

Which will only Draw the scene if I either press a key or move the mouse etc. So it seems to be working fine for me.

masonwheeler
27-02-2008, 12:01 AM
Works fine for you, huh? Go figure.

What's your initialization like? It looks to me like the only thing this routine requires is the timer, which FE_Init will take care of if it's not already initialized, but maybe there's something I'm missing.

savage
27-02-2008, 09:15 AM
I'm calling FE_Init, straight after SDL_Init and then the code as I posted it. Nothing fancy. Maybe the difference is that this is all in one thread.