/* pygame - Python Game Library Copyright (C) 2000-2001 Pete Shinners This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Pete Shinners pete@shinners.org */ /* * pygame fastevent module */ #define PYGAMEAPI_FASTEVENT_INTERNAL #include "pygame.h" #include "fastevents.h" static int FE_WasInit = 0; #define FE_INIT_CHECK() \ do { \ if (!FE_WasInit) { \ return RAISE(PyExc_SDLError, "fastevent system not initialized"); \ } \ } while (0) static void fastevent_cleanup(void) { if (FE_WasInit) { FE_Quit(); FE_WasInit = 0; } } /* fastevent module functions */ /*DOC*/ static char doc_init[] = /*DOC*/ "pygame.fastevent.init() -> None\n" /*DOC*/ "initialize pygame.fastevent.\n" /*DOC*/ ; static PyObject* fastevent_init(PyObject* self, PyObject* args) { if(!PyArg_ParseTuple(args, "")) return NULL; VIDEO_INIT_CHECK(); #ifndef WITH_THREAD return RAISE(PyExc_SDLError, "pygame.fastevent requires a threaded Python"); #else if (!FE_WasInit) { if(FE_Init() == -1) return RAISE(PyExc_SDLError, FE_GetError()); PyGame_RegisterQuit(fastevent_cleanup); FE_WasInit = 1; } RETURN_NONE #endif /* WITH_THREAD */ } /*DOC*/ static char doc_pump[] = /*DOC*/ "pygame.fastevent.pump() -> None\n" /*DOC*/ "update the internal messages\n" /*DOC*/ "\n" /*DOC*/ "For each frame of your game, you will need to make some sort\n" /*DOC*/ "of call to the event queue. This ensures your program can internally\n" /*DOC*/ "interact with the rest of the operating system. If you are not using\n" /*DOC*/ "other event functions in your game, you should call pump() to allow\n" /*DOC*/ "pygame to handle internal actions.\n" /*DOC*/ "\n" /*DOC*/ "There are important things that must be dealt with internally in the\n" /*DOC*/ "event queue. The main window may need to be repainted. Certain joysticks\n" /*DOC*/ "must be polled for their values. If you fail to make a call to the event\n" /*DOC*/ "queue for too long, the system may decide your program has locked up.\n" /*DOC*/ ; static PyObject* fastevent_pump(PyObject* self, PyObject* args) { if(!PyArg_ParseTuple(args, "")) return NULL; FE_INIT_CHECK(); FE_PumpEvents(); RETURN_NONE } /*DOC*/ static char doc_wait[] = /*DOC*/ "pygame.fastevent.wait() -> Event\n" /*DOC*/ "wait for an event\n" /*DOC*/ "\n" /*DOC*/ "Returns the current event on the queue. If there are no messages\n" /*DOC*/ "waiting on the queue, this will not return until one is\n" /*DOC*/ "available. Sometimes it is important to use this wait to get\n" /*DOC*/ "events from the queue, it will allow your application to idle\n" /*DOC*/ "when the user isn't doing anything with it.\n" /*DOC*/ ; static PyObject* fastevent_wait(PyObject* self, PyObject* args) { SDL_Event event; int status; if(!PyArg_ParseTuple(args, "")) return NULL; FE_INIT_CHECK(); Py_BEGIN_ALLOW_THREADS status = FE_WaitEvent(&event); Py_END_ALLOW_THREADS /* FE_WaitEvent will block forever on error */ if(!status) return RAISE(PyExc_SDLError, "unexpected error in FE_WaitEvent!"); return PyEvent_New(&event); } /*DOC*/ static char doc_poll[] = /*DOC*/ "pygame.fastevent.poll() -> Event\n" /*DOC*/ "get an available event\n" /*DOC*/ "\n" /*DOC*/ "Returns next event on queue. If there is no event waiting on the\n" /*DOC*/ "queue, this will return an event with type NOEVENT.\n" /*DOC*/ ; static PyObject* fastevent_poll(PyObject* self, PyObject* args) { SDL_Event event; int status; if(!PyArg_ParseTuple(args, "")) return NULL; FE_INIT_CHECK(); status = FE_PollEvent(&event); if (status == 1) { return PyEvent_New(&event); } else { /* Check for -1 */ return PyEvent_New(NULL); } } /*DOC*/ static char doc_get[] = /*DOC*/ "pygame.fastevent.get() -> list of Events\n" /*DOC*/ "get all events from the queue\n" /*DOC*/ ; static PyObject* fastevent_get(PyObject* self, PyObject* args) { SDL_Event event; PyObject *list, *e; int status; if(!PyArg_ParseTuple(args, "")) return NULL; FE_INIT_CHECK(); list = PyList_New(0); if(!list) return NULL; FE_PumpEvents(); while (1) { status = FE_PollEvent(&event); if (status != 1) { break; } e = PyEvent_New(&event); if(!e) { Py_DECREF(list); return NULL; } PyList_Append(list, e); Py_DECREF(e); } return list; } /*DOC*/ static char doc_post[] = /*DOC*/ "pygame.fastevent.post(Event) -> None\n" /*DOC*/ "place an event on the queue\n" /*DOC*/ "\n" /*DOC*/ "This will post your own event objects onto the event queue.\n" /*DOC*/ "You can past any event type you want, but some care must be\n" /*DOC*/ "taken. For example, if you post a MOUSEBUTTONDOWN event to the\n" /*DOC*/ "queue, it is likely any code receiving the event will expect\n" /*DOC*/ "the standard MOUSEBUTTONDOWN attributes to be available, like\n" /*DOC*/ "'pos' and 'button'.\n" /*DOC*/ "\n" /*DOC*/ "Because pygame.fastevent.post() may have to wait for the queue\n" /*DOC*/ "to empty, you can get into a dead lock if you try to append an\n" /*DOC*/ "event on to a full queue from the thread that processes events.\n" /*DOC*/ "For that reason I do not recommend using this function in the\n" /*DOC*/ "main thread of an SDL program.\n" /*DOC*/ ; static PyObject* fastevent_post(PyObject* self, PyObject* args) { PyEventObject* e; SDL_Event event; int status; if(!PyArg_ParseTuple(args, "O!", &PyEvent_Type, &e)) return NULL; FE_INIT_CHECK(); if (PyEvent_FillUserEvent(e, &event)) return NULL; Py_BEGIN_ALLOW_THREADS status = FE_PushEvent(&event); Py_END_ALLOW_THREADS if (status != 1) return RAISE(PyExc_SDLError, "Unexpected error in FE_PushEvent"); RETURN_NONE } static PyMethodDef fastevent_builtins[] = { { "init", fastevent_init, 1, doc_init }, { "get", fastevent_get, 1, doc_get }, { "pump", fastevent_pump, 1, doc_pump }, { "wait", fastevent_wait, 1, doc_wait }, { "poll", fastevent_poll, 1, doc_poll }, { "post", fastevent_post, 1, doc_post }, { NULL, NULL } }; /*DOC*/ static char doc_fastevent_MODULE[] = /*DOC*/ "pygame.fastevent is a wrapper for Bob Pendleton's fastevent\n" /*DOC*/ "library. It provides fast events for use in multithreaded\n" /*DOC*/ "environments. When using pygame.fastevent, you can not use\n" /*DOC*/ "any of the pump, wait, poll, post, get, peek, etc. functions\n" /*DOC*/ "from pygame.event, but you should use the Event objects.\n" /*DOC*/ ; PYGAME_EXPORT void initfastevent(void) { PyObject *module, *eventmodule, *dict; /* create the module */ module = Py_InitModule3("fastevent", fastevent_builtins, doc_fastevent_MODULE); dict = PyModule_GetDict(module); /*imported needed apis*/ import_pygame_base(); import_pygame_event(); eventmodule = PyImport_ImportModule("pygame.event"); if (eventmodule) { char *NAMES[] = {"Event", "event_name", NULL}; int i; for (i = 0; NAMES[i]; i++) { PyObject *ref = PyObject_GetAttrString(eventmodule, NAMES[i]); if (ref) { PyDict_SetItemString(dict, NAMES[i], ref); } else { PyErr_Clear(); } } } }