Commits

aholkner  committed 9e87430

Initial import from previous repository.

  • Participants
  • Branches ctypes-soc

Comments (0)

Files changed (31)

+SDL-ctypes 0.03
+---------------
+ - Set func_name instead of __name__ in `SDL.dll.function`; this should
+   fix an error about __name__ being unwriteable in OS X (untested).
+ - Provide access to unpythonified functions via _SDL_PeepEvents etc,
+   rather  than SDL.dll._dll.SDL_PeepEvents.  This is cleaner, and sets
+   things up for a unified compatibility mechanism.
+ - `since` argument added to `SDL.dll.function` to specify minimum version
+   of loaded library.
+ - support/prep_doc.py now ignores private functions marked with "_"
+ - version support for 1.2.1 to 1.2.10
+        since 1.2.7:
+            SDL_RWFromConstMem added
+        since 1.2.10:
+            SDL_WM_SetCaption unicode arguments
+            SDL_VideoInfo window size attributes
+            SDL_GetKeyRepeat added
+ - SDL.array module added
+ - SDL.video functions modified to accept and return SDL.array.SDL_array,
+   numpy arrays or any other sequence.
+ - Implemented SDL_CreateRGSurfaceFrom
+ - added test programs test/testpalette.py and test/testgamma.py
+ - __copy__ and __deepcopy__ methods added to SDL_Colour and SDL_Rect
+ - Constants and enums in keysym.py moved into constants.py
+ - SDL_keysym.unicode is now a unicode string type, not integer
+include test/sample.bmp
+include test/*.py
+include unit/*.py
+include support/*.py
+include support/*.txt
+include doc/**
+include CHANGELOG

File SDL/__init__.py

+#!/usr/bin/env python
+
+'''Main module for importing SDL-ctypes.
+
+This module defines the intialization and cleanup functions:
+    - `SDL_Init`
+    - `SDL_InitSubSystem`
+    - `SDL_WasInit`
+    - `SDL_QuitSubSystem`
+    - `SDL_Quit`
+
+It also imports all functions, constants and classes from the package
+submodules.  Typical usage, then, is to just import this module directly
+into your namespace::
+
+    from SDL import *
+
+This gives you access to all SDL names exactly as they appear in the C
+header files.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+import ctypes
+
+import SDL.dll
+from SDL.active import *
+from SDL.cdrom import *
+from SDL.constants import *
+from SDL.error import *
+from SDL.events import *
+from SDL.keyboard import *
+from SDL.keysym import *
+from SDL.mouse import *
+from SDL.quit import *
+from SDL.rwops import *
+from SDL.timer import *
+from SDL.version import *
+from SDL.video import *
+
+# SDL.h
+
+SDL_Init = SDL.dll.function('SDL_Init',
+    '''Initialise the SDL library.
+
+    This function loads the SDL dynamically linked library and initializes 
+    the subsystems specified by `flags` (and those satisfying dependencies)
+    Unless the `SDL_INIT_NOPARACHUTE` flag is set, it will install cleanup
+    signal handlers for some commonly ignored fatal signals (like SIGSEGV).
+
+    The following flags are recognised:
+
+        - `SDL_INIT_TIMER`
+        - `SDL_INIT_AUDIO`
+        - `SDL_INIT_VIDEO`
+        - `SDL_INIT_CDROM`
+        - `SDL_INIT_JOYSTICK`
+        - `SDL_INIT_NOPARACHUTE`
+        - `SDL_INIT_EVENTTHREAD`
+        - `SDL_INIT_EVERYTHING`
+
+    :Parameters:
+     - `flags`: int
+
+    :rtype: int
+    :return: undocumented (FIXME)
+    :see: `SDL_Quit`
+    ''',
+    args=['flags'],
+    arg_types=[ctypes.c_uint],
+    return_type=ctypes.c_int)
+
+SDL_InitSubSystem = SDL.dll.function('SDL_InitSubSystem',
+    '''Initialize specific SDL subsystems.
+
+    :Parameters:
+     - `flags`: int
+
+    :rtype: int
+    :return: undocumented (FIXME)
+    :see: `SDL_Init`, `SDL_QuitSubSystem`
+    ''',
+    args=['flags'],
+    arg_types=[ctypes.c_uint],
+    return_type=ctypes.c_int)
+
+SDL_QuitSubSystem = SDL.dll.function('SDL_QuitSubSystem',
+    '''Clean up specific SDL subsystems.
+
+    :Parameters:
+     - `flags`: int
+
+    :see: `SDL_InitSubSystem`
+    ''',
+    args=['flags'],
+    arg_types=[ctypes.c_uint],
+    return_type=None)
+
+SDL_WasInit = SDL.dll.function('SDL_WasInit',
+    '''Return a mask of the specified subsystems which have been
+    initialized.
+
+    If `flags` is 0, return a mask of all initialized subsystems.
+
+    :Parameters:
+     - `flags`: int
+
+    :rtype: int
+    :return: undocumented (FIXME)
+    :see: `SDL_Init`
+    ''',
+    args=['flags'],
+    arg_types=[ctypes.c_uint],
+    return_type=ctypes.c_int)
+
+SDL_Quit = SDL.dll.function('SDL_Quit',
+    '''Clean up all initialized subsystems.
+
+    You should call this function upon all exit conditions.
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=None)

File SDL/active.py

+#!/usr/bin/env python
+
+'''SDL application focus event handling.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+
+SDL_GetAppState = SDL.dll.function('SDL_GetAppState',
+    '''Return the current state of the application.
+
+    The return value is a bitwise combination of `SDL_APPMOUSEFOCUS`,
+    `SDL_APPINPUTFOCUS`, and `SDL_APPACTIVE`.  The meanings are as follows:
+    
+        `SDL_APPMOUSEFOCUS`
+            The application has mouse coverage.
+        `SDL_APPINPUTFOCUS`
+            The application has input focus.
+        `SDL_APPACTIVATE` 
+            The user is able to see your application, otherwise it has been
+            iconified or disabled
+    
+    :rtype: int
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=c_int)

File SDL/array.py

+#!/usr/bin/env python
+
+'''
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+# numpy
+try:
+    import numpy
+    _numpy_typemap = {
+        c_ubyte: numpy.UInt8,
+        c_ushort: numpy.UInt16,
+        c_uint: numpy.UInt32
+    }
+    _have_numpy = True
+except ImportError:
+    _have_numpy = False
+
+class SDL_array:
+    def __init__(self, ptr, count, ctype):
+        '''Construct an array at memory location `ptr` with `count` elements
+        of type `ctype`.
+
+        :Parameters:
+            `ptr` : ctypes.Array, POINTER(ctype) or POINTER(ctypes.Array)
+                Starting point of the array space.  Don't use c_void_p; this
+                will not cast correctly.  If `ptr` is None, the array
+                will be created (filled with random data).
+            `count` : int
+                Number of elements in the array.
+            `ctype` : type
+                ctypes type if each element, e.g., c_ubyte, c_int, etc.
+
+        '''
+        if not ptr:
+            ptr = (ctype * count)()
+        self.ptr = ptr
+        self.count = count
+        self.ctype = ctype
+        self._ctypes_array = None
+
+    def as_bytes(self):
+        '''Access the array as raw bytes, regardless of the underlying
+        data type.
+
+        This can be useful, for example, in accessing a 32-bit colour
+        buffer by individual components rather than the encoded pixel.
+
+        :rtype: SDL_array
+        '''
+        return SDL_array(self.ptr, (self.count * sizeof(self.ctype)), c_ubyte)
+
+    def as_ctypes(self):
+        '''Access the array as a ctypes array.
+
+        :rtype: ctypes.Array
+        '''
+        if not self._ctypes_array:
+            self._ctypes_array = \
+                cast(self.ptr, POINTER(self.ctype * self.count)).contents
+        return self._ctypes_array
+
+    def as_numpy(self):
+        '''Access the array as a numpy array.  
+        
+        The numpy array shares the same underlying memory buffer, so
+        changes are immediate, and you can use the numpy array as you would
+        normally.  To set the entire contents of the array at once, use a
+        ``[:]`` slice.
+
+        If numpy is not installed, an ImportError will be raised.
+
+        :rtype: numpy.ndarray
+        '''
+        if not _have_numpy:
+            raise ImportError, 'numpy could not be imported'
+        if self.ctype not in _numpy_typemap:
+            raise TypeError, '%s has no numpy compatible type' % self.ctype
+        return numpy.frombuffer(self.as_ctypes(), _numpy_typemap[self.ctype])
+
+    def __repr__(self):
+        return 'SDL_array(ctype=%s, count=%r)' % (self.ctype, self.count)
+
+    def __len__(self):
+        return self.count
+
+    def __getitem__(self, key):
+        if type(key) is slice:
+            if key.step:
+                raise TypeError, 'slice step not supported'
+            return self.as_ctypes()[key.start:key.stop]
+        else:
+            return self.as_ctypes()[key]
+
+    def __setitem__(self, key, value):
+        if type(key) is slice:
+            if key.step:
+                raise TypeError, 'slice step not supported'
+            self.as_ctypes()[key.start:key.stop] = value
+        else:
+            self.as_ctypes()[key] = value
+
+def to_ctypes(values, count, ctype):
+    '''Create a ctypes array of the given count and type, with the contents
+    of sequence `values`.
+
+    :Parameters:
+     - `values`: sequence of length `count`, or SDL_array instance, or
+       ctypes.Array, or POINTER(ctypes.Array)
+     - `count`: int
+     - `ctype`: type
+
+    '''
+
+    # Convert SDL_array instances to ctypes array
+    if isinstance(values, SDL_array):
+        values = values.as_ctypes()
+
+    # Cast ctypes array to correct type if necessary
+    if isinstance(values, Array):
+        if values._type_ is ctype:
+            return values
+        else:
+            return cast(values, POINTER(ctype * count)).contents
+
+    # Otherwise assume sequence
+    return (ctype * count)(*values)

File SDL/cdrom.py

+#!/usr/bin/env python
+
+'''CD-audio control.
+
+In order to use these functions, `SDL_Init` must have been called with the
+`SDL_INIT_CDROM` flag.  This causes SDL to scan the system for CD-ROM
+drives, and load appropriate drivers.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.constants
+import SDL.dll
+
+class SDL_CDtrack(Structure):
+    _fields_ = [('id', c_ubyte),
+                ('type', c_ubyte),
+                ('_unused', c_ushort),
+                ('length', c_uint),
+                ('offset', c_uint)]
+
+class SDL_CD(Structure):
+    _fields_ = [('id', c_uint),
+                ('status', c_int),
+                ('numtracks', c_int),
+                ('cur_track', c_int),
+                ('cur_frame', c_int),
+                ('track', SDL_CDtrack * (SDL.constants.SDL_MAX_TRACKS + 1))]
+
+def CD_INDRIVE(status):
+    '''Given a status, returns True if there's a disk in the drive.
+
+    :Parameters:
+     - `status`: int
+
+    :rtype: bool
+    '''
+    return status > 0
+
+def FRAMES_TO_MSF(frames):
+    '''Convert from frames to minute/second/frame
+
+    :Parameters:
+     - `frames`: int
+
+    :rtype: (int, int, int)
+    :return: tuple of (minutes, seconds, frames)
+    '''
+    F = frames % SDL.constants.CD_FPS
+    frames /= SDL.constants.CD_FPS
+    S = frames % 60
+    frames /= 60
+    M = frames
+    return (M, S, F)
+
+def MSF_TO_FRAMES(minutes, seconds, frames):
+    '''Convert from minute/second/frame to frames
+
+    :Parameters:
+     - `minutes`: int
+     - `seconds`: int
+     - `frames`: int
+
+    :rtype: int
+    '''
+    return SDL.constants.CD_FPS(minutes * 60 + seconds) + frames
+
+SDL_CDNumDrives = SDL.dll.function('SDL_CDNumDrives',
+    '''Return the number of CD-ROM drives on the system.
+
+    :rtype: int
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDName = SDL.dll.function('SDL_CDName',
+    '''Return a human-readable, system-dependent identifier for the
+    CD-ROM.
+
+    Example::
+
+        '/dev/cdrom'
+        'E:'
+        '/dev/disk/ide/1/master'
+
+    :Parameters:
+        `drive` : int
+            Drive number, starting with 0.  Drive 0 is the system default
+            CD-ROM.
+
+    :rtype: string
+    ''',
+    args=['drive'],
+    arg_types=[c_int],
+    return_type=c_char_p,
+    require_return=True)
+
+SDL_CDOpen = SDL.dll.function('SDL_CDOpen',
+    '''Open a CD-ROM drive for access.
+
+    It returns a drive handle on success, or raises an exception if the
+    drive was invalid or busy.  This newly opened CD-ROM becomes the
+    default CD used when other CD functions are passed None as the CD-ROM
+    handle.
+
+    Drives are numbered starting with 0.  Drive 0 is the system default
+    CD-ROM.
+
+    :Parameters:
+     - `drive`: int
+
+    :rtype: `SDL_CD`
+    ''',
+    args=['drive'],
+    arg_types=[c_int],
+    return_type=POINTER(SDL_CD),
+    dereference_return=True,
+    require_return=True)
+
+SDL_CDStatus = SDL.dll.function('SDL_CDStatus',
+    '''Return the current status of the given drive.
+
+    If the drive has a CD in it, the table of contents of the CD and
+    current play position of the CD will be updated in the SDL_CD
+    instance.
+
+    Possible return values are
+     - `CD_TRAYEMPTY`
+     - `CD_STOPPED`
+     - `CD_PLAYING`
+     - `CD_PAUSED`
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    :rtype: int
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=int,
+    error_return=-1)
+
+SDL_CDPlayTracks = SDL.dll.function('SDL_CDPlayTracks',
+    '''Play the given CD.
+
+    Plays the given CD starting at `start_track` and `start_frame` for
+    `ntracks` tracks and `nframes` frames.  If both `ntracks` and `nframes`
+    are 0, play until the end of the CD.  This function will skip data
+    tracks.  This function should only be called after calling
+    `SDL_CDStatus` to get track information about the CD.
+
+    For example::
+
+    	# Play entire CD:
+        if CD_INDRIVE(SDL_CDStatus(cdrom)):
+            SDL_CDPlayTracks(cdrom, 0, 0, 0, 0)
+
+        # Play last track:
+        if CD_INDRIVE(SDL_CDStatus(cdrom)):
+            SDL_CDPlayTracks(cdrom, cdrom.numtracks-1, 0, 0, 0)
+
+        #Play first and second track and 10 seconds of third track:
+        if CD_INDRIVE(SDL_CDStatus(cdrom)):
+            SDL_CDPlayTracks(cdrom, 0, 0, 2, 10)
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+     - `start_track`: int
+     - `start_frame`: int
+     - `ntracks`: int
+     - `nframes`: int
+
+    ''',
+    args=['cdrom', 'start_track', 'start_frame', 'ntracks', 'nframes'],
+    arg_types=[POINTER(SDL_CD), c_int, c_int, c_int, c_int],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDPlay = SDL.dll.function('SDL_CDPlay',
+    '''Play the given CD.
+
+    Plays the given CD starting at `start` frame for `length` frames.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+     - `start`: int
+     - `length`: int
+
+    ''',
+    args=['cdrom', 'start', 'length'],
+    arg_types=[POINTER(SDL_CD), c_int, c_int],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDPause = SDL.dll.function('SDL_CDPause',
+    '''Pause play.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDResume = SDL.dll.function('SDL_CDResume',
+    '''Resume play.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDStop = SDL.dll.function('SDL_CDStop',
+    '''Stop play.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDEject = SDL.dll.function('SDL_CDEject',
+    '''Eject CD-ROM.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=c_int,
+    error_return=-1)
+
+SDL_CDClose = SDL.dll.function('SDL_CDClose',
+    '''Close the handle for the CD-ROM drive.
+
+    :Parameters:
+     - `cdrom`: `SDL_CD`
+
+    ''',
+    args=['cdrom'],
+    arg_types=[POINTER(SDL_CD)],
+    return_type=c_int,
+    error_return=-1)

File SDL/constants.py

+#!/usr/bin/env python
+
+'''Constants and enums for all SDL submodules.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+# TODO enums
+
+# enum SDLKey {
+
+#  The keyboard syms have been cleverly chosen to map to ASCII 
+SDLK_UNKNOWN            = 0
+SDLK_FIRST              = 0
+SDLK_BACKSPACE          = 8
+SDLK_TAB                = 9
+SDLK_CLEAR              = 12
+SDLK_RETURN             = 13
+SDLK_PAUSE              = 19
+SDLK_ESCAPE             = 27
+SDLK_SPACE              = 32
+SDLK_EXCLAIM            = 33
+SDLK_QUOTEDBL           = 34
+SDLK_HASH               = 35
+SDLK_DOLLAR             = 36
+SDLK_AMPERSAND          = 38
+SDLK_QUOTE              = 39
+SDLK_LEFTPAREN          = 40
+SDLK_RIGHTPAREN         = 41
+SDLK_ASTERISK           = 42
+SDLK_PLUS               = 43
+SDLK_COMMA              = 44
+SDLK_MINUS              = 45
+SDLK_PERIOD             = 46
+SDLK_SLASH              = 47
+SDLK_0                  = 48
+SDLK_1                  = 49
+SDLK_2                  = 50
+SDLK_3                  = 51
+SDLK_4                  = 52
+SDLK_5                  = 53
+SDLK_6                  = 54
+SDLK_7                  = 55
+SDLK_8                  = 56
+SDLK_9                  = 57
+SDLK_COLON              = 58
+SDLK_SEMICOLON          = 59
+SDLK_LESS               = 60
+SDLK_EQUALS             = 61
+SDLK_GREATER            = 62
+SDLK_QUESTION           = 63
+SDLK_AT                 = 64
+
+#  Skip uppercase letters
+
+SDLK_LEFTBRACKET        = 91
+SDLK_BACKSLASH          = 92
+SDLK_RIGHTBRACKET       = 93
+SDLK_CARET              = 94
+SDLK_UNDERSCORE         = 95
+SDLK_BACKQUOTE          = 96
+SDLK_a                  = 97
+SDLK_b                  = 98
+SDLK_c                  = 99
+SDLK_d                  = 100
+SDLK_e                  = 101
+SDLK_f                  = 102
+SDLK_g                  = 103
+SDLK_h                  = 104
+SDLK_i                  = 105
+SDLK_j                  = 106
+SDLK_k                  = 107
+SDLK_l                  = 108
+SDLK_m                  = 109
+SDLK_n                  = 110
+SDLK_o                  = 111
+SDLK_p                  = 112
+SDLK_q                  = 113
+SDLK_r                  = 114
+SDLK_s                  = 115
+SDLK_t                  = 116
+SDLK_u                  = 117
+SDLK_v                  = 118
+SDLK_w                  = 119
+SDLK_x                  = 120
+SDLK_y                  = 121
+SDLK_z                  = 122
+SDLK_DELETE             = 127
+#  End of ASCII mapped keysyms 
+
+#  International keyboard syms 
+SDLK_WORLD_0            = 160          #  0xA0 
+SDLK_WORLD_1            = 161
+SDLK_WORLD_2            = 162
+SDLK_WORLD_3            = 163
+SDLK_WORLD_4            = 164
+SDLK_WORLD_5            = 165
+SDLK_WORLD_6            = 166
+SDLK_WORLD_7            = 167
+SDLK_WORLD_8            = 168
+SDLK_WORLD_9            = 169
+SDLK_WORLD_10           = 170
+SDLK_WORLD_11           = 171
+SDLK_WORLD_12           = 172
+SDLK_WORLD_13           = 173
+SDLK_WORLD_14           = 174
+SDLK_WORLD_15           = 175
+SDLK_WORLD_16           = 176
+SDLK_WORLD_17           = 177
+SDLK_WORLD_18           = 178
+SDLK_WORLD_19           = 179
+SDLK_WORLD_20           = 180
+SDLK_WORLD_21           = 181
+SDLK_WORLD_22           = 182
+SDLK_WORLD_23           = 183
+SDLK_WORLD_24           = 184
+SDLK_WORLD_25           = 185
+SDLK_WORLD_26           = 186
+SDLK_WORLD_27           = 187
+SDLK_WORLD_28           = 188
+SDLK_WORLD_29           = 189
+SDLK_WORLD_30           = 190
+SDLK_WORLD_31           = 191
+SDLK_WORLD_32           = 192
+SDLK_WORLD_33           = 193
+SDLK_WORLD_34           = 194
+SDLK_WORLD_35           = 195
+SDLK_WORLD_36           = 196
+SDLK_WORLD_37           = 197
+SDLK_WORLD_38           = 198
+SDLK_WORLD_39           = 199
+SDLK_WORLD_40           = 200
+SDLK_WORLD_41           = 201
+SDLK_WORLD_42           = 202
+SDLK_WORLD_43           = 203
+SDLK_WORLD_44           = 204
+SDLK_WORLD_45           = 205
+SDLK_WORLD_46           = 206
+SDLK_WORLD_47           = 207
+SDLK_WORLD_48           = 208
+SDLK_WORLD_49           = 209
+SDLK_WORLD_50           = 210
+SDLK_WORLD_51           = 211
+SDLK_WORLD_52           = 212
+SDLK_WORLD_53           = 213
+SDLK_WORLD_54           = 214
+SDLK_WORLD_55           = 215
+SDLK_WORLD_56           = 216
+SDLK_WORLD_57           = 217
+SDLK_WORLD_58           = 218
+SDLK_WORLD_59           = 219
+SDLK_WORLD_60           = 220
+SDLK_WORLD_61           = 221
+SDLK_WORLD_62           = 222
+SDLK_WORLD_63           = 223
+SDLK_WORLD_64           = 224
+SDLK_WORLD_65           = 225
+SDLK_WORLD_66           = 226
+SDLK_WORLD_67           = 227
+SDLK_WORLD_68           = 228
+SDLK_WORLD_69           = 229
+SDLK_WORLD_70           = 230
+SDLK_WORLD_71           = 231
+SDLK_WORLD_72           = 232
+SDLK_WORLD_73           = 233
+SDLK_WORLD_74           = 234
+SDLK_WORLD_75           = 235
+SDLK_WORLD_76           = 236
+SDLK_WORLD_77           = 237
+SDLK_WORLD_78           = 238
+SDLK_WORLD_79           = 239
+SDLK_WORLD_80           = 240
+SDLK_WORLD_81           = 241
+SDLK_WORLD_82           = 242
+SDLK_WORLD_83           = 243
+SDLK_WORLD_84           = 244
+SDLK_WORLD_85           = 245
+SDLK_WORLD_86           = 246
+SDLK_WORLD_87           = 247
+SDLK_WORLD_88           = 248
+SDLK_WORLD_89           = 249
+SDLK_WORLD_90           = 250
+SDLK_WORLD_91           = 251
+SDLK_WORLD_92           = 252
+SDLK_WORLD_93           = 253
+SDLK_WORLD_94           = 254
+SDLK_WORLD_95           = 255          #  0xFF 
+
+#  Numeric keypad 
+SDLK_KP0                = 256
+SDLK_KP1                = 257
+SDLK_KP2                = 258
+SDLK_KP3                = 259
+SDLK_KP4                = 260
+SDLK_KP5                = 261
+SDLK_KP6                = 262
+SDLK_KP7                = 263
+SDLK_KP8                = 264
+SDLK_KP9                = 265
+SDLK_KP_PERIOD          = 266
+SDLK_KP_DIVIDE          = 267
+SDLK_KP_MULTIPLY        = 268
+SDLK_KP_MINUS           = 269
+SDLK_KP_PLUS            = 270
+SDLK_KP_ENTER           = 271
+SDLK_KP_EQUALS          = 272
+
+#  Arrows + Home/End pad 
+SDLK_UP                 = 273
+SDLK_DOWN               = 274
+SDLK_RIGHT              = 275
+SDLK_LEFT               = 276
+SDLK_INSERT             = 277
+SDLK_HOME               = 278
+SDLK_END                = 279
+SDLK_PAGEUP             = 280
+SDLK_PAGEDOWN           = 281
+
+#  Function keys 
+SDLK_F1                 = 282
+SDLK_F2                 = 283
+SDLK_F3                 = 284
+SDLK_F4                 = 285
+SDLK_F5                 = 286
+SDLK_F6                 = 287
+SDLK_F7                 = 288
+SDLK_F8                 = 289
+SDLK_F9                 = 290
+SDLK_F10                = 291
+SDLK_F11                = 292
+SDLK_F12                = 293
+SDLK_F13                = 294
+SDLK_F14                = 295
+SDLK_F15                = 296
+
+#  Key state modifier keys 
+SDLK_NUMLOCK            = 300
+SDLK_CAPSLOCK           = 301
+SDLK_SCROLLOCK          = 302
+SDLK_RSHIFT             = 303
+SDLK_LSHIFT             = 304
+SDLK_RCTRL              = 305
+SDLK_LCTRL              = 306
+SDLK_RALT               = 307
+SDLK_LALT               = 308
+SDLK_RMETA              = 309
+SDLK_LMETA              = 310
+SDLK_LSUPER             = 311          #  Left "Windows" key 
+SDLK_RSUPER             = 312          #  Right "Windows" key 
+SDLK_MODE               = 313          #  "Alt Gr" key 
+SDLK_COMPOSE            = 314          #  Multi-key compose key 
+
+#  Miscellaneous function keys 
+SDLK_HELP               = 315
+SDLK_PRINT              = 316
+SDLK_SYSREQ             = 317
+SDLK_BREAK              = 318
+SDLK_MENU               = 319
+SDLK_POWER              = 320          #  Power Macintosh power key 
+SDLK_EURO               = 321          #  Some european keyboards 
+SDLK_UNDO               = 322          #  Atari keyboard has Undo 
+
+SDLK_LAST               = 323          #  Keep me updated please.
+
+# end of enum SDLKey
+
+# enum SDLMod
+
+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
+KMOD_RESERVED   = 0x8000
+
+# end of enum SDLMod
+
+KMOD_CTRL   = KMOD_LCTRL    | KMOD_RCTRL
+KMOD_SHIFT  = KMOD_LSHIFT   | KMOD_RSHIFT
+KMOD_ALT    = KMOD_LALT     | KMOD_RALT
+KMOD_META   = KMOD_LMETA    | KMOD_RMETA
+
+#BEGIN GENERATED CONSTANTS; see support/make_constants.py
+
+#Constants from SDL_mouse.h:
+SDL_BUTTON_LEFT = 0x00000001
+SDL_BUTTON_MIDDLE = 0x00000002
+SDL_BUTTON_RIGHT = 0x00000003
+SDL_BUTTON_WHEELUP = 0x00000004
+SDL_BUTTON_WHEELDOWN = 0x00000005
+
+#Constants from SDL_version.h:
+SDL_MAJOR_VERSION = 0x00000001
+SDL_MINOR_VERSION = 0x00000002
+SDL_PATCHLEVEL = 0x0000000a
+
+#Constants from SDL.h:
+SDL_INIT_TIMER = 0x00000001
+SDL_INIT_AUDIO = 0x00000010
+SDL_INIT_VIDEO = 0x00000020
+SDL_INIT_CDROM = 0x00000100
+SDL_INIT_JOYSTICK = 0x00000200
+SDL_INIT_NOPARACHUTE = 0x00100000
+SDL_INIT_EVENTTHREAD = 0x01000000
+SDL_INIT_EVERYTHING = 0x0000ffff
+
+#Constants from SDL_mutex.h:
+SDL_MUTEX_TIMEDOUT = 0x00000001
+
+#Constants from SDL_ttf.h:
+SDL_TTF_MAJOR_VERSION = 0x00000002
+SDL_TTF_MINOR_VERSION = 0x00000000
+SDL_TTF_PATCHLEVEL = 0x00000007
+UNICODE_BOM_NATIVE = 0x0000feff
+UNICODE_BOM_SWAPPED = 0x0000fffe
+TTF_STYLE_NORMAL = 0x00000000
+TTF_STYLE_BOLD = 0x00000001
+TTF_STYLE_ITALIC = 0x00000002
+TTF_STYLE_UNDERLINE = 0x00000004
+
+#Constants from SDL_video.h:
+SDL_ALPHA_OPAQUE = 0x000000ff
+SDL_ALPHA_TRANSPARENT = 0x00000000
+SDL_SWSURFACE = 0x00000000
+SDL_HWSURFACE = 0x00000001
+SDL_ASYNCBLIT = 0x00000004
+SDL_ANYFORMAT = 0x10000000
+SDL_HWPALETTE = 0x20000000
+SDL_DOUBLEBUF = 0x40000000
+SDL_FULLSCREEN = 0x80000000
+SDL_OPENGL = 0x00000002
+SDL_OPENGLBLIT = 0x0000000a
+SDL_RESIZABLE = 0x00000010
+SDL_NOFRAME = 0x00000020
+SDL_HWACCEL = 0x00000100
+SDL_SRCCOLORKEY = 0x00001000
+SDL_RLEACCELOK = 0x00002000
+SDL_RLEACCEL = 0x00004000
+SDL_SRCALPHA = 0x00010000
+SDL_PREALLOC = 0x01000000
+SDL_YV12_OVERLAY = 0x32315659
+SDL_IYUV_OVERLAY = 0x56555949
+SDL_YUY2_OVERLAY = 0x32595559
+SDL_UYVY_OVERLAY = 0x59565955
+SDL_YVYU_OVERLAY = 0x55595659
+SDL_LOGPAL = 0x00000001
+SDL_PHYSPAL = 0x00000002
+
+#Constants from SDL_name.h:
+NeedFunctionPrototypes = 0x00000001
+
+#Constants from SDL_endian.h:
+SDL_LIL_ENDIAN = 0x000004d2
+SDL_BIG_ENDIAN = 0x000010e1
+
+#Constants from SDL_audio.h:
+AUDIO_U8 = 0x00000008
+AUDIO_S8 = 0x00008008
+AUDIO_U16LSB = 0x00000010
+AUDIO_S16LSB = 0x00008010
+AUDIO_U16MSB = 0x00001010
+AUDIO_S16MSB = 0x00009010
+SDL_MIX_MAXVOLUME = 0x00000080
+
+#Constants from begin_code.h:
+NULL = 0x00000000
+
+#Constants from SDL_cdrom.h:
+SDL_MAX_TRACKS = 0x00000063
+SDL_AUDIO_TRACK = 0x00000000
+SDL_DATA_TRACK = 0x00000004
+CD_FPS = 0x0000004b
+
+#Constants from SDL_events.h:
+SDL_RELEASED = 0x00000000
+SDL_PRESSED = 0x00000001
+SDL_ALLEVENTS = 0xffffffff
+SDL_IGNORE = 0x00000000
+SDL_DISABLE = 0x00000000
+SDL_ENABLE = 0x00000001
+
+#Constants from SDL_active.h:
+SDL_APPMOUSEFOCUS = 0x00000001
+SDL_APPINPUTFOCUS = 0x00000002
+SDL_APPACTIVE = 0x00000004
+
+#Constants from SDL_opengl.h:
+WIN32_LEAN_AND_MEAN = 0x00000001
+
+#Constants from SDL_joystick.h:
+SDL_HAT_CENTERED = 0x00000000
+SDL_HAT_UP = 0x00000001
+SDL_HAT_RIGHT = 0x00000002
+SDL_HAT_DOWN = 0x00000004
+SDL_HAT_LEFT = 0x00000008
+
+#Constants from SDL_keyboard.h:
+SDL_ALL_HOTKEYS = 0xffffffff
+SDL_DEFAULT_REPEAT_DELAY = 0x000001f4
+SDL_DEFAULT_REPEAT_INTERVAL = 0x0000001e
+
+#Constants from SDL_rwops.h:
+RW_SEEK_SET = 0x00000000
+RW_SEEK_CUR = 0x00000001
+RW_SEEK_END = 0x00000002
+
+#Constants from SDL_sound.h:
+SOUND_VER_MAJOR = 0x00000001
+SOUND_VER_MINOR = 0x00000000
+SOUND_VER_PATCH = 0x00000001
+
+#Constants from SDL_mixer.h:
+SDL_MIXER_MAJOR_VERSION = 0x00000001
+SDL_MIXER_MINOR_VERSION = 0x00000002
+SDL_MIXER_PATCHLEVEL = 0x00000006
+MIX_CHANNELS = 0x00000008
+MIX_DEFAULT_FREQUENCY = 0x00005622
+MIX_DEFAULT_CHANNELS = 0x00000002
+MIX_MAX_VOLUME = 0x00000080
+
+#Constants from SDL_timer.h:
+SDL_TIMESLICE = 0x0000000a
+TIMER_RESOLUTION = 0x0000000a
+#END GENERATED CONSTANTS
+#!/usr/bin/env python
+
+'''
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+_dll = cdll.SDL
+
+# Private version checking declared before SDL.version can be
+# imported.
+class _SDL_version(Structure):
+    _fields_ = [('major', c_ubyte),
+                ('minor', c_ubyte),
+                ('patch', c_ubyte)]
+
+    def __repr__(self):
+        return '%d.%d.%d' % \
+            (self.major, self.minor, self.patch)
+
+def _version_parts(v):
+    '''Return a tuple (major, minor, patch) for `v`, which can be
+    an _SDL_version, string or tuple.'''
+    if type(v) == _SDL_version:
+        return v.major, v.minor, v.patch
+    elif type(v) == tuple:
+        return v
+    elif type(v) == string:
+        return tuple([int(i) for i in v.split('.')])
+    else:
+        raise TypeError
+
+def version_compatible(v):
+    '''Returns True iff `v` is equal to or later than the loaded library
+    version.'''
+    v = _version_parts(v) 
+    for i in range(3):
+        if _version[i] < v[i]:
+            return False
+    return True
+
+def assert_version_compatible(name, since):
+    '''Raises an exception if `since` is later than the loaded library.'''
+    if not version_compatible(version):
+        import SDL.error
+        raise SDL.error.SDL_NotImplementedError, \
+            '%s requires SDL version %s; currently using version %s' % \
+            (name, _version_string(since), _version_string(_version))
+
+def _version_string(v):
+    return '%d.%d.%d' % _version_parts(v)
+
+# Get the version of the DLL we're using
+_dll.SDL_Linked_Version.restype = POINTER(_SDL_version)
+_version = _version_parts(_dll.SDL_Linked_Version().contents)
+
+def private_function(name, **kwargs):
+    '''Construct a wrapper function for ctypes with internal documentation
+    and no argument names.'''
+    kwargs['doc'] = 'Private wrapper for %s' % name
+    kwargs['args'] = []
+    return function(name, **kwargs)
+
+def function(name, doc, args=[], arg_types=[], 
+             return_type=None, 
+             dereference_return=False, 
+             require_return=False,
+             success_return=None,
+             error_return=None,
+             since=None):
+    '''Construct a wrapper function for ctypes.
+
+    :Parameters:
+        `name`
+            The name of the function as it appears in the shared library.
+        `doc`
+            Docstring to associate with the wrapper function.
+        `args`
+            List of strings giving the argument names.
+        `arg_types`
+            List of ctypes classes giving the argument types.
+        `return_type`
+            The ctypes class giving the wrapped function's native return
+            type.
+        `dereference_return`
+            If True, the return value is assumed to be a pointer and
+            will be dereferenced via ``.contents`` before being returned
+            to the user application.
+        `require_return`
+            Used in conjunction with `dereference_return`; if True, an
+            exception will be raised if the result is NULL; if False
+            None will be returned when the result is NULL.
+        `success_return`
+            If not None, the expected result of the wrapped function.  If
+            the return value does not equal success_return, an exception
+            will be raised.
+        `error_return`
+            If not None, the error result of the wrapped function.  If the
+            return value equals error_return, an exception will be raised.
+            Cannot be used in conjunction with `success_return`.
+        `since`
+            Tuple (major, minor, patch) or string 'x.y.z' of the first version
+            of SDL in which this function appears.  If the loaded version
+            predates it, a placeholder function that raises
+            `SDL_NotImplementedError` will be returned instead.  Set to None
+            if the function is in all versions of SDL.
+    '''
+    # Check for version compatibility first
+    if since and not version_compatible(since):
+        def _f(*args, **kwargs):
+            import SDL.error
+            raise SDL.error.SDL_NotImplementedError, \
+                  '%s requires SDL version %s; currently using version %s' % \
+                  (name, _version_string(since), _version_string(_version))
+        if args:
+            _f._args = args
+        _f.__doc__ = doc
+        _f.func_name = name
+        return _f
+
+    # Ok, get function from ctypes
+    func = getattr(_dll, name)
+    func.argtypes = arg_types
+    func.restype = return_type
+    if dereference_return:
+        if require_return:
+            # Construct a function which dereferences the pointer result,
+            # or raises an exception if NULL is returned.
+            def _f(*args, **kwargs):
+                result = func(*args, **kwargs)
+                if result:
+                    return result.contents
+                import SDL.error
+                raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+        else:
+            # Construct a function which dereferences the pointer result,
+            # or returns None if NULL is returned.
+            def _f(*args, **kwargs):
+                result = func(*args, **kwargs)
+                if result:
+                    return result.contents
+                return None
+    elif success_return is not None:
+        # Construct a function which returns None, but raises an exception
+        # if the C function returns a failure code.
+        def _f(*args, **kwargs):
+            result = func(*args, **kwargs)
+            if result != success_return:
+                import SDL.error
+                raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+            return result
+    elif error_return is not None:
+        # Construct a function which returns None, but raises an exception
+        # if the C function returns a failure code.
+        def _f(*args, **kwargs):
+            result = func(*args, **kwargs)
+            if result == error_return:
+                import SDL.error
+                raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+            return result
+    elif require_return:
+        # Construct a function which returns the usual result, or returns
+        # None if NULL is returned.
+        def _f(*args, **kwargs):
+            result = func(*args, **kwargs)
+            if not result: 
+                import SDL.error
+                raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+            return result
+    else:
+        # Construct a function which returns the C function's return
+        # value.
+        def _f(*args, **kwargs):
+            return func(*args, **kwargs)
+    if args:
+        _f._args = args
+    _f.__doc__ = doc
+    _f.func_name = name
+    return _f
+

File SDL/error.py

+#!/usr/bin/env python
+
+'''Error detection and error handling functions.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+
+class SDL_Exception(Exception):
+    '''Exception raised for all SDL errors.  
+    
+    The message is as returned by `SDL_GetError`.
+    '''
+    def __init__(self, message):
+        self.message = message
+
+    def __str__(self):
+        return self.message
+
+class SDL_NotImplementedError(NotImplementedError):
+    '''Exception raised when the available SDL library predates the
+    requested function.'''
+    pass
+
+SDL_SetError = SDL.dll.function('SDL_SetError',
+    '''Set the static error string.
+
+    :Parameters:
+        `fmt`
+            format string; subsequent integer and string arguments are
+            interpreted as in printf().
+    ''',
+    args=['fmt'],
+    arg_types=[c_char_p],
+    return_type=None)
+
+SDL_GetError = SDL.dll.function('SDL_GetError',
+    '''Return the last error string set.
+
+    :rtype: string
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=c_char_p)
+
+SDL_ClearError = SDL.dll.function('SDL_ClearError',
+    '''Clear any error string set.
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=None)
+
+# SDL_Error not implemented (marked private in SDL_error.h)

File SDL/events.py

+#!/usr/bin/env python
+
+'''Event handling.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+import SDL.keyboard
+
+# enum SDL_EventType
+(SDL_NOEVENT,
+    SDL_ACTIVEEVENT,
+    SDL_KEYDOWN,
+    SDL_KEYUP,
+    SDL_MOUSEMOTION,
+    SDL_MOUSEBUTTONDOWN,
+    SDL_MOUSEBUTTONUP,
+    SDL_JOYAXISMOTION,
+    SDL_JOYBALLMOTION,
+    SDL_JOYHATMOTION,
+    SDL_JOYBUTTONDOWN,
+    SDL_JOYBUTTONUP,
+    SDL_QUIT,
+    SDL_SYSWMEVENT,
+    SDL_EVENT_RESERVEDA,
+    SDL_EVENT_RESERVEDB,
+    SDL_VIDEORESIZE,
+    SDL_VIDEOEXPOSE,
+    SDL_EVENT_RESERVED2,
+    SDL_EVENT_RESERVED3,
+    SDL_EVENT_RESERVED4,
+    SDL_EVENT_RESERVED5,
+    SDL_EVENT_RESERVED6,
+    SDL_EVENT_RESERVED7) = range(24)
+SDL_USEREVENT = 24
+SDL_NUMEVENTS = 32
+
+def SDL_EVENTMASK(x):
+    '''Used for predefining event masks.'''
+    return 1 << x
+
+# enum SDL_EventMask
+SDL_ACTIVEEVENTMASK     = SDL_EVENTMASK(SDL_ACTIVEEVENT)
+SDL_KEYDOWNMASK         = SDL_EVENTMASK(SDL_KEYDOWN)
+SDL_KEYUPMASK           = SDL_EVENTMASK(SDL_KEYUP)
+SDL_KEYEVENTMASK        = SDL_KEYUPMASK | \
+                          SDL_KEYDOWNMASK
+SDL_MOUSEMOTIONMASK     = SDL_EVENTMASK(SDL_MOUSEMOTION)
+SDL_MOUSEBUTTONDOWNMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)
+SDL_MOUSEBUTTONUPMASK   = SDL_EVENTMASK(SDL_MOUSEBUTTONUP)
+SDL_MOUSEEVENTMASK      = SDL_MOUSEMOTIONMASK | \
+                          SDL_MOUSEBUTTONDOWNMASK | \
+                          SDL_MOUSEBUTTONUPMASK
+SDL_JOYAXISMOTIONMASK   = SDL_EVENTMASK(SDL_JOYAXISMOTION)
+SDL_JOYBALLMOTIONMASK   = SDL_EVENTMASK(SDL_JOYBALLMOTION)
+SDL_JOYHATMOTIONMASK    = SDL_EVENTMASK(SDL_JOYHATMOTION)
+SDL_JOYBUTTONDOWNMASK   = SDL_EVENTMASK(SDL_JOYBUTTONDOWN)
+SDL_JOYBUTTONUPMASK     = SDL_EVENTMASK(SDL_JOYBUTTONUP)
+SDL_JOYEVENTMASK        = SDL_JOYAXISMOTIONMASK | \
+                          SDL_JOYBALLMOTIONMASK | \
+                          SDL_JOYHATMOTIONMASK | \
+                          SDL_JOYBUTTONDOWNMASK | \
+                          SDL_JOYBUTTONUPMASK
+SDL_QUITMASK            = SDL_EVENTMASK(SDL_QUIT)
+SDL_SYSWMEVENTMASK      = SDL_EVENTMASK(SDL_SYSWMEVENT)
+SDL_VIDEORESIZEMASK     = SDL_EVENTMASK(SDL_VIDEORESIZE)
+SDL_VIDEOEXPOSEMASK     = SDL_EVENTMASK(SDL_VIDEOEXPOSE)
+
+# enum SDL_eventaction
+(SDL_ADDEVENT,
+    SDL_PEEKEVENT,
+    SDL_GETEVENT) = range(3)
+
+class SDL_ActiveEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('gain', c_ubyte),
+                ('state', c_ubyte)]
+
+class SDL_KeyboardEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('state', c_ubyte),
+                ('keysym', SDL.keyboard.SDL_keysym)]
+
+class SDL_MouseMotionEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('state', c_ubyte),
+                ('x', c_ushort),
+                ('y', c_ushort),
+                ('xrel', c_short),
+                ('yrel', c_short)]
+
+class SDL_MouseButtonEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('button', c_ubyte),
+                ('state', c_ubyte),
+                ('x', c_ushort),
+                ('y', c_ushort)]
+
+class SDL_JoyAxisEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('axis', c_ubyte),
+                ('value', c_short)]
+
+class SDL_JoyBallEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('ball', c_ubyte),
+                ('xrel', c_short),
+                ('yrel', c_short)]
+
+class SDL_JoyHatEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('hat', c_ubyte),
+                ('value', c_ubyte)]
+
+class SDL_JoyButtonEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('which', c_ubyte),
+                ('button', c_ubyte),
+                ('state', c_ubyte)]
+
+class SDL_ResizeEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('w', c_int),
+                ('h', c_int)]
+
+class SDL_ExposeEvent(Structure):
+    _fields_ = [('type', c_ubyte)]
+
+class SDL_QuitEvent(Structure):
+    _fields_ = [('type', c_ubyte)]
+
+class SDL_UserEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('code', c_int),
+                ('data1', c_void_p),
+                ('data2', c_void_p)]
+
+class SDL_SysWMEvent(Structure):
+    _fields_ = [('type', c_ubyte),
+                ('msg', c_void_p)]  # TODO with SDL_syswm.h
+
+class SDL_Event(Union):
+    _fields_ = [('type', c_ubyte),
+                ('active', SDL_ActiveEvent),
+                ('key', SDL_KeyboardEvent),
+                ('motion', SDL_MouseMotionEvent),
+                ('button', SDL_MouseButtonEvent),
+                ('jaxis', SDL_JoyAxisEvent),
+                ('jball', SDL_JoyBallEvent),
+                ('jhat', SDL_JoyHatEvent),
+                ('jbutton', SDL_JoyButtonEvent),
+                ('resize', SDL_ResizeEvent),
+                ('expose', SDL_ExposeEvent),
+                ('quit', SDL_QuitEvent),
+                ('user', SDL_UserEvent),
+                ('syswm', SDL_SysWMEvent)]
+
+    types = {
+        SDL_ACTIVEEVENT: (SDL_ActiveEvent, 'active'),
+        SDL_KEYDOWN: (SDL_KeyboardEvent, 'key'),
+        SDL_KEYUP: (SDL_KeyboardEvent, 'key'),
+        SDL_MOUSEMOTION: (SDL_MouseMotionEvent, 'motion'),
+        SDL_MOUSEBUTTONDOWN: (SDL_MouseButtonEvent, 'button'),
+        SDL_MOUSEBUTTONUP: (SDL_MouseButtonEvent, 'button'),
+        SDL_JOYAXISMOTION: (SDL_JoyAxisEvent, 'jaxis'),
+        SDL_JOYBALLMOTION: (SDL_JoyBallEvent, 'jball'),
+        SDL_JOYHATMOTION: (SDL_JoyHatEvent, 'jhat'),
+        SDL_JOYBUTTONDOWN: (SDL_JoyButtonEvent, 'jbutton'),
+        SDL_JOYBUTTONUP: (SDL_JoyButtonEvent, 'jbutton'),
+        SDL_VIDEORESIZE: (SDL_ResizeEvent, 'resize'),
+        SDL_VIDEOEXPOSE: (SDL_ExposeEvent, 'expose'),
+        SDL_QUIT: (SDL_QuitEvent, 'quit'),
+        SDL_SYSWMEVENT: (SDL_SysWMEvent, 'syswm')
+    }
+
+    def __repr__(self):
+        if self.type in self.types:
+            return self.types[self.type][0].__repr__(self)
+        elif self.type >= SDL_USEREVENT:    # SDL_MAXEVENTS not defined
+            return SDL_UserEvent.__repr__(self)
+        return 'SDLEvent(type=%d)' % self.type
+
+    def specialize(self):
+        if self.type in self.types:
+            return getattr(self, self.types[self.type][1])
+        elif self.type >= SDL_USEREVENT:    # SDL_MAXEVENTS not defined
+            return self.user
+        return self
+
+SDL_PumpEvents = SDL.dll.function('SDL_PumpEvents',
+    '''Pumps the event loop, gathering events from the input devices.
+
+    This function updates the event queue and internal input device state.
+    This should only be run in the thread that sets the video mode.
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=None)
+
+_SDL_PeepEvents = SDL.dll.private_function('SDL_PeepEvents',
+    arg_types=[POINTER(SDL_Event), c_int, c_int, c_uint],
+    return_type=c_int)
+
+def SDL_PeepEvents(numevents, action, mask):
+    '''Check the event queue for messages and optionally return them.
+
+    The behaviour depends on `action`:
+
+        `SDL_ADDEVENT`
+            Not implemented; will raise an exception.  See `SDL_PushEvent`.
+        `SDL_PEEKEVENT`
+            Up to `numevents` events at the front of the event queue,
+            matching `mask`, will be returned and will not be removed
+            from the queue.
+        `SDL_GETEVENT`
+            Up to `numevents` events at the front of the event queue,
+            matching `mask`, will be returned and will be removed from the
+            queue.
+
+    :Parameters:
+        `numevents` : int
+            Maximum number of events to return
+        `action` : int
+            Either `SDL_PEEKEVENT` or `SDL_GETEVENT`
+        `mask` : int
+            Mask to match type of returned events with.
+
+    :rtype: list
+    :return: list of SDL_Event (or subclass)
+    :see: `SDL_PushEvent`, `SDL_HaveEvents`
+    '''
+    if action == SDL_ADDEVENT:
+        raise NotImplementedError, 'Use SDL_PushEvent to add events'
+    ar = (SDL_Event * numevents)()
+    num = _SDL_PeepEvents(ar, numevents, action, mask)
+    if num == -1:
+        raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+    return list([e.specialize() for e in ar[:num]])
+
+def SDL_HaveEvents(mask):
+    '''Check the event queue for events matching the given mask.
+
+    :note: This function replaces the C function 
+        SDL_PeepEvents(NULL, ...), which had undocumented behaviour.
+
+    :Parameters:
+        `mask` : int
+            Mask to match type of returned events with.
+
+    :rtype: bool
+    :return: True if at least one event matches the mask in the event
+        queue.
+    '''
+    num = _SDL_PeepEvents(None, 1, SDL_PEEKEVENT, mask)
+    return num > 0
+
+_SDL_PollEvent = SDL.dll.private_function('SDL_PollEvent',
+    arg_types=[POINTER(SDL_Event)],
+    return_type=c_int)
+
+def SDL_PollEvent():
+    '''Poll for currently pending events.
+
+    Returns True if there are any pending events, or False if there are none
+    available.
+
+    :see: `SDL_PollEventAndReturn`
+    :rtype: bool
+    '''
+    return _SDL_PollEvent(None) == 1
+    
+def SDL_PollEventAndReturn():
+    '''Poll for currently pending events, and return one off the queue
+    if possible.
+
+    :see: `SDL_PollEvent`
+    :rtype: `SDL_Event` or subclass
+    '''
+    # Need to make this global to workaround refcounting error with cast
+    e = SDL_Event()
+    result = _SDL_PollEvent(byref(e))
+    if result == 1:
+        return e.specialize()
+    return None
+
+_SDL_WaitEvent = SDL.dll.private_function('SDL_WaitEvent',
+    arg_types=[POINTER(SDL_Event)],
+    return_type=c_int)
+
+def SDL_WaitEvent():
+    '''Wait indefinitely for an event.
+
+    Returns when an event is available on the queue, or raises an exception
+    if an error occurs while waiting.
+
+    :see: `SDL_WaitEventAndReturn`
+    '''
+    if _SDL_WaitEvent(None) == 0:
+        raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+    
+def SDL_WaitEventAndReturn():
+    '''Wait indefinitely for the next event and return it.
+
+    :see: `SDL_WaitEvent`
+    :rtype: `SDL_Event` or subclass
+    '''
+    ev = SDL_Event()
+    result = _SDL_WaitEvent(byref(ev))
+    if result == 1:
+        return ev.specialize()
+    else:
+        raise SDL.error.SDL_Exception, SDL.error.SDL_GetError()
+
+SDL_PushEvent = SDL.dll.function('SDL_PushEvent',
+    '''Add an event to the event queue.
+
+    :Parameters:
+     - `event`: `SDL_Event`
+
+    ''',
+    args=['event'],
+    arg_types=[POINTER(SDL_Event)],
+    return_type=c_int,
+    error_return=-1)
+
+
+_SDL_EventFilter = CFUNCTYPE(c_int, POINTER(SDL_Event))
+_SDL_SetEventFilter = SDL.dll.private_function('SDL_SetEventFilter',
+    arg_types=[_SDL_EventFilter],
+    return_type=None)
+
+def SDL_SetEventFilter(filter):
+    '''Set up a filter to process all events before they change internal
+    state and are posted to the internal event queue.
+
+    :warning:  Be very careful of what you do in the event filter function,
+        as it may run in a different thread.
+
+    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.
+
+    :Parameters:
+        `filter` : function
+            a function that takes an `SDL_Event` as a single argument.  If
+            the function returns 1 the event will be added to the internal
+            queue.  If it returns 0, the event will be dropped from the
+            queue, but the internal state will still be updated.  The event
+            instance must not be modified.
+
+    '''
+    _SDL_SetEventFilter(_SDL_EventFilter(filter))
+
+_SDL_GetEventFilter = SDL.dll.private_function('SDL_GetEventFilter',
+    arg_types=[],
+    return_type=_SDL_EventFilter)
+
+# XXX this doesn't need to be wrapped specially
+def SDL_GetEventFilter():
+    '''Return the current event filter.
+
+    This can be used to "chain" filters.  If there is no event filter set,
+    this function returns None.
+
+    :rtype: function
+    '''
+    return _SDL_GetEventFilter()
+
+SDL_EventState = SDL.dll.function('SDL_EventState',
+    '''Ignore or enable the processing of certain events.
+
+    The behaviour of this function depends on `state`
+
+        `SDL_IGNORE`
+            the event will be automatically dropped from the event queue
+            and will not be event filtered.
+        `SDL_ENABLE`
+            the event will be processed normally.
+        `SDL_QUERY`
+            return the current processing state of the event.
+
+    :Parameters:
+        `type` : int
+            Type of event, e.g. `SDL_KEYDOWN`, `SDL_MOUSEMOTION`, etc.
+            (TODO: documented list of these?)
+        `state` : int
+            One of `SDL_IGNORE`, `SDL_ENABLE` or `SDL_QUERY`
+
+    :rtype: int
+    :return: the event processing state: either `SDL_IGNORE or
+        `SDL_ENABLE`.
+    ''',
+    args=['type', 'state'],
+    arg_types=[c_ubyte, c_int],
+    return_type=c_int)

File SDL/keyboard.py

+#!/usr/bin/env python
+
+'''Keyboard event handling.
+
+You should call `SDL_Init` with `SDL_INIT_VIDEO` before using these functions.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+
+class SDL_keysym(Structure):
+    '''Keysym structure
+
+        * The scancode is hardware dependent, and should not be used by
+          general applications.  If no hardware scancode is available, it will
+          be 0
+        * The `unicode` translated character is only available when character
+          translation is enabled by `SDL_EnableUNICODE`.  If non-empty, this is
+          unicode string of unit length.
+    '''
+    _fields_ = [('scancode', c_ubyte),
+                ('sym', c_int),
+                ('mod', c_int),
+                ('_unicode', c_ushort)]
+
+    def __getattr__(self, name):
+        if name == 'unicode':
+            return unichr(self._unicode)
+        raise AttributeError
+
+SDL_EnableUNICODE = SDL.dll.function('SDL_EnableUNICODE',
+    '''Enable or disable Unicode translation of keyboard input.
+
+    This translation has some overhead, so translation defaults off.
+
+    :Parameters:
+        `enable` : int
+            * if 1, translation is enabled
+            * if 0, translation is disabled.  
+            * if -1, the translation is not changed.
+
+    :rtype: int
+    :return: the previous state of keyboard translation
+    ''',
+    args=['enable'],
+    arg_types=[c_int],
+    return_type=c_int)
+
+SDL_EnableKeyRepeat = SDL.dll.function('SDL_EnableKeyRepeat',
+    '''Enable keyboard repeat.
+
+    Keyboard repeat defaults to off.
+
+    :Parameters:
+        `delay` : int
+            the initial delay in milliseconds between the time when a key is
+            pressed, and keyboard repeat begins.  If 0, keyboard repeat is
+            disabled.
+        `interval` : int
+            the time in milliseconds between keyboard repeat events.
+
+    :rtype: int
+    :return: undocumented (FIXME)
+    ''',
+    args=['delay', 'interval'],
+    arg_types=[c_int, c_int],
+    return_type=c_int)
+
+_SDL_GetKeyRepeat = SDL.dll.private_function('SDL_GetKeyRepeat',
+    arg_types=[POINTER(c_int), POINTER(c_int)],
+    return_type=None,
+    since=(1,2,10))
+
+def SDL_GetKeyRepeat():
+    '''Get the keyboard repeat parameters.
+
+    :see: `SDL_EnableKeyRepeat`
+    :rtype: (int, int)
+    :return: tuple (delay, interval), as defined in `SDL_EnableKeyRepeat`
+    :since: 1.2.10
+    '''
+    delay, interval = c_int(), c_int()
+    _SDL_GetKeyRepeat(byref(delay), byref(interval))
+    return delay.value, interval.value
+
+_SDL_GetKeyState = SDL.dll.private_function('SDL_GetKeyRepeat',
+    arg_types=[POINTER(c_int)],
+    return_type=POINTER(c_ubyte))
+
+def SDL_GetKeyState():
+    '''Get a snapshot of the current state of the keyboard.
+
+    Example::
+        
+        keystate = SDL_GetKeyState()
+        if keystate[SDLK_RETURN]:
+            print '<RETURN> is pressed'
+    
+    :rtype: list
+    :return: a list of integers indexed by the SDLK_* symbols
+    '''
+    numkeys = c_int()
+    keystate = _SDL_GetKeyState(byref(numkeys))
+    keystate_ar = cast(keystate, POINTER(c_ubyte * numkeys.value)).contents
+    return list(keystate_ar)
+
+SDL_GetModState = SDL.dll.function('SDL_GetModState',
+    '''Get the current key modifier state.
+
+    :rtype: int
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=c_int)
+
+SDL_SetModState = SDL.dll.function('SDL_SetModState',
+    '''Set the current key modifier state.
+
+    This does not change the keyboard state, only the key modifier flags.
+
+    :Parameters:
+     - `modstate`: int
+    
+    ''',
+    args=['modstate'],
+    arg_types=[c_int],
+    return_type=None)
+
+_SDL_GetKeyName = SDL.dll.private_function('SDL_GetKeyName',
+    arg_types=[c_int],
+    return_type=c_char_p)
+
+def SDL_GetKeyName(key):
+    '''Get the name of an SDL virtual keysym.
+
+    :Parameters:
+     - `key`: int
+
+    :rtype: string
+    '''
+    return _SDL_GetKeyName(key)
+

File SDL/mouse.py

+#!/usr/bin/env python
+
+'''Mouse event handling.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+import SDL.video
+
+class SDL_Cursor(Structure):
+    _fields_ = [('area', SDL.video.SDL_Rect),
+                ('hot_x', c_short),
+                ('hot_y', c_short),
+                ('data', POINTER(c_ubyte)),
+                ('mask', POINTER(c_ubyte)),
+                ('save', POINTER(c_ubyte) * 2),
+                ('wm_cursor', c_void_p)]
+
+_SDL_GetMouseState = SDL.dll.private_function('SDL_GetMouseState',
+    arg_types=[POINTER(c_int), POINTER(c_int)],
+    return_type=c_ubyte)
+
+def SDL_GetMouseState():
+    '''Retrieve the current state of the mouse.
+
+    Example::
+
+        state, x, y = SDL_GetMouseState()
+        if state & SDL_BUTTON_LMASK:
+            print 'Left button pressed.'
+
+    :rtype: (int, int, int)
+    :return: (state, x, y), where
+        * state is a button bitmask, which can be tested using `SDL_BUTTON`
+        * x and y are the current mouse cursor position.
+
+    '''
+    x, y = c_int(), c_int()
+    state = _SDL_GetMouseState(byref(x), byref(y))
+    return state, x.value, y.value
+
+_SDL_GetRelativeMouseState = \
+    SDL.dll.private_function('SDL_GetRelativeMouseState',
+    arg_types=[POINTER(c_int), POINTER(c_int)],
+    return_type=c_ubyte)
+
+def SDL_GetRelativeMouseState():
+    '''Retrieve the current state of the mouse.
+
+    :rtype: (int, int, int)
+    :return: (state, dx, dy), 
+        where state is a button bitmask, which can be tested using
+        `SDL_BUTTON`; dx and dy are the mouse deltas since the last call to
+        `SDL_GetRelativeMouseState`
+
+    '''
+    dx, dy = c_int(), c_int()
+    state = _SDL_GetRelativeMouseState(byref(dx), byref(dy))
+    return state, dx.value, dy.value
+
+SDL_WarpMouse = SDL.dll.function('SDL_WarpMouse',
+    '''Set the position of the mouse cursor.
+
+    Generates a mouse motion event.
+
+    :Parameters:
+     - `x`: int
+     - `y`: int
+
+    ''',
+    args=['x', 'y'],
+    arg_types=[c_ushort, c_ushort],
+    return_type=None)
+
+# TODO: SDL_CreateCursor
+
+SDL_SetCursor = SDL.dll.function('SDL_SetCursor',
+    '''Set the currently active cursor to the specified one.
+
+    If the cursor is currently visible, the change will be immediately
+    represented on the display.
+
+    :Parameters:
+     - `cursor`: `SDL_Cursor`
+
+    ''',
+    args=['cursor'],
+    arg_types=[POINTER(SDL_Cursor)],
+    return_type=None)
+
+SDL_GetCursor = SDL.dll.function('SDL_GetCursor',
+    '''Return the currently active cursor.
+
+    :rtype: `SDL_Cursor`
+    ''',
+    args=[],
+    arg_types=[],
+    return_type=POINTER(SDL_Cursor),
+    dereference_return=True)
+
+SDL_FreeCursor = SDL.dll.function('SDL_FreeCursor',
+    '''Deallocate a cursor created with `SDL_CreateCursor`
+
+    :Parameters:
+     - `cursor`: `SDL_Cursor`
+    ''',
+    args=['cursor'],
+    arg_types=[POINTER(SDL_Cursor)],
+    return_type=None)
+
+SDL_ShowCursor = SDL.dll.function('SDL_ShowCursor',
+    '''Toggle whether or not the curosr is shown on the screen.
+
+    The cursor starts off displayed, but can be turned off.
+
+    :Parameters:
+        `toggle` : int
+            if 1, shows the cursor; if 0, hides the cursor, if -1, returns
+            the current state of the cursor.
+
+    :rtype: int
+    :return: 1 if the cursor was being displayed before the call, otherwise
+        0.
+    ''',
+    args=['toggle'],
+    arg_types=[c_int],
+    return_type=c_int)
+
+def SDL_BUTTON(X):
+    '''Used to create a mask for a mouse button.
+    '''
+    return 1 << (X-1)
+
+SDL_BUTTON_LMASK    = SDL_BUTTON(SDL.constants.SDL_BUTTON_LEFT)
+SDL_BUTTON_MMASK    = SDL_BUTTON(SDL.constants.SDL_BUTTON_MIDDLE)
+SDL_BUTTON_RMASK    = SDL_BUTTON(SDL.constants.SDL_BUTTON_RIGHT)
+#!/usr/bin/env python
+
+'''Quit event handling.
+
+An `SDL_QUITEVENT` is generated when the user tries to close the application
+window.  If it is ignored or filtered out, the window will remain open.
+If it is not ignored or filtered, it is queued normally and the window
+is allowed to close.  When the window is closed, screen updates will 
+complete, but have no effect.
+
+`SDL_Init` installs signal handlers for SIGINT (keyboard interrupt)
+and SIGTERM (system termination request), if handlers do not already
+exist, that generate `SDL_QUITEVENT` events as well.  There is no way
+to determine the cause of an `SDL_QUITEVENT`, but setting a signal
+handler in your application will override the default generation of
+quit events for that signal.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+import SDL.events
+
+def SDL_QuitRequested():
+    '''Return True if there is a quit event in the event queue.
+
+    :rtype: bool
+    '''
+    SDL.events.SDL_PumpEvents()
+    return SDL.events.SDL_HaveEvents(SDL.events.SDL_QUITMASK)

File SDL/rwops.py

+#!/usr/bin/env python
+
+'''General interface for SDL to read and write data sources.
+
+For files, use `SDL_RWFromFile`.  Other Python file-type objects can be
+used with `SDL_RWFromObject`.  If another library provides a constant void
+pointer to a contiguous region of memory, `SDL_RWFromMem` and
+`SDL_RWFromConstMem` can be used.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+import SDL.constants
+
+_rwops_p = POINTER('SDL_RWops')
+_seek_fn = CFUNCTYPE(c_int, _rwops_p, c_int, c_int)
+_read_fn = CFUNCTYPE(c_int, _rwops_p, c_void_p, c_int, c_int)
+_write_fn = CFUNCTYPE(c_int, _rwops_p, c_void_p, c_int, c_int)
+_close_fn = CFUNCTYPE(c_int, _rwops_p)
+
+class _hidden_mem_t(Structure):
+    _fields_ = [('base', c_void_p),
+                ('here', c_void_p),
+                ('stop', c_void_p)]
+
+class SDL_RWops(Structure):
+    _fields_ = [('seek', _seek_fn),
+                ('read', _read_fn),
+                ('write', _write_fn),
+                ('close', _close_fn),
+                ('type', c_uint),
+                ('_hidden_mem', _hidden_mem_t)]
+SetPointerType(_rwops_p, SDL_RWops)
+
+SDL_RWFromFile = SDL.dll.function('SDL_RWFromFile',
+    '''Create an SDL_RWops structure from a file on disk.
+
+    :Parameters:
+        `file` : string
+            Filename
+        `mode` : string
+            Mode to open the file with; as with the built-in function ``open``.
+
+    :rtype: `SDL_RWops`
+    ''',
+    args=['file', 'mode'],
+    arg_types=[c_char_p, c_char_p],
+    return_type=POINTER(SDL_RWops),
+    dereference_return=True,
+    require_return=True)
+
+SDL_RWFromMem = SDL.dll.function('SDL_RWFromMem',
+    '''Create an SDL_RWops structure from a contiguous region of memory.
+
+    :Parameters:
+     - `mem`: ``c_void_p``
+     - `size`: int
+
+    :rtype: `SDL_RWops`
+    ''',
+    args=['mem', 'size'],
+    arg_types=[c_void_p, c_int],
+    return_type=POINTER(SDL_RWops),
+    dereference_return=True,
+    require_return=True)
+
+SDL_RWFromConstMem = SDL.dll.function('SDL_RWFromConstMem',
+    '''Create an SDL_RWops structure from a contiguous region of memory.
+
+    :Parameters:
+     - `mem`: ``c_void_p``
+     - `size`: int
+
+    :rtype: `SDL_RWops`
+    :since: 1.2.7
+    ''',
+    args=['mem', 'size'],
+    arg_types=[c_void_p, c_int],
+    return_type=POINTER(SDL_RWops),
+    dereference_return=True,
+    require_return=True,
+    since=(1,2,7))
+
+""" These functions shouldn't be useful to Pythoners.
+SDL_AllocRW = SDL.dll.function('SDL_AllocRW',
+    '''Allocate a blank SDL_Rwops structure.
+
+    :rtype: `SDL_RWops`
+    '''
+    args=[],
+    arg_types=[],
+    return_type=POINTER(SDL_RWops),
+    dereference_return=True,
+    require_return=True)
+
+SDL_FreeRW = SDL.dll.function('SDL_FreeRW',
+    '''Free a SDL_RWops structure.
+
+    :param area: `SDL_RWops`
+    '''
+    args=['area'],
+    arg_types=[POINTER(SDL_RWops)],
+    return_type=None)
+"""
+
+# XXX Tested read from open() only so far
+def SDL_RWFromObject(obj):
+    '''Construct an SDL_RWops structure from a Python file-like object.
+
+    The object must support the following methods in the same fashion as
+    the builtin file object: 
+
+        - ``read(len) -> data``
+        - ``write(data)``
+        - ``seek(offset, whence)``
+        - ``close()``
+
+    :Parameters:
+     - `obj`: Python file-like object to wrap
+
+    :rtype: `SDL_RWops`
+    '''
+
+    ctx = SDL_RWops()
+
+    def _seek(context, offset, whence):
+        obj.seek(offset, whence)
+        return obj.tell()
+    ctx.seek = _seek_fn(_seek)
+
+    def _read(context, ptr, size, maximum):
+        try:
+            r = obj.read(maximum * size)
+            memmove(ptr, r, len(r))
+            return len(r) / size
+        except:
+            return -1
+    ctx.read = _read_fn(_read)
+
+    def _write(context, ptr, size, num):
+        try:
+            obj.write(string_at(ptr, size*num))
+            return num
+        except:
+            return -1
+    ctx.write = _write_fn(_write)
+
+    def _close(context):
+        obj.close()
+    ctx.close = _close_fn(_close)
+    return ctx
+
+"""
+# XXX Usefulness of the following using raw pointers?
+
+def SDL_RWseek(ctx, offset, whence):
+    return ctx.seek(ctx, offset, whence)
+
+def SDL_RWtell(ctx):
+    return ctx.seek(ctx, 0, SDL.constants.RW_SEEK_CUR)
+
+def SDL_RWread(ctx, ptr, size, n):
+    return ctx.read(ctx, ptr, size, n)
+
+def SDL_RWwrite(ctx, ptr, size, n):
+    return ctx.write(ctx, ptr, size, n)
+
+def SDL_RWclose(ctx):
+    return ctx.close(ctx)
+"""
+
+# XXX not implemented: SDL_Read{BL}E* and SDL_Write{BL}E*

File SDL/timer.py

+#!/usr/bin/env python
+
+'''Time management routines.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id: $'
+
+from ctypes import *
+
+import SDL.dll
+
+SDL_GetTicks = SDL.dll.function('SDL_GetTicks',
+    '''Get the number of milliseconds since the SDL library initialization.