SHARE
TWEET

RSDL Joystick

a guest Aug 11th, 2010 141 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. '''
  2. Joystick RSDL Extension, by Brett
  3. goatman.py@gmail.com
  4. license BSD
  5.  
  6. Interfacing RPython with C
  7. The documentation on how to interface RPython with C is rather limited, the extending doc mentions that `MixedModules` using rffi is the most advanced method available.  The rffi document only provides a quick glance at how to use rffi.llexternal.  The best place to get started is looking at the source code in rlib/rsdl/RSDL.py which binds RPython to SDL.  What should be clear after reading RSDL.py is that PyPy provides a very direct and easy to understand interface for C; that should also provide the highest possible performance.  
  8.  
  9. The source code in rffi_platform.py (found in pypy/rpython/tool) is very interesting, it generates dynamic C code that it compiles to get information about the C code we are trying to wrap, for example if you had used the wrong name in a struct it will generate an error.  Using rffi_platform different C types can be defined, such as structs, constant integers; these are then put into a special container class called CConfig, which is then parsed by rffi_platform.configure(CConfig) and wrappers returned.  After we have the wrappers we must tell any pointers we had previously used in the CConfig that they `become` those objects, MyPointer.TO.become(MyStruct).
  10.  
  11. RSDL that is included in PyPy is incomplete and lacks wrappers for Joystick, the code below wraps SDL Joystick.
  12. '''
  13. PATH2PYPY = 'pypy'
  14.  
  15. import sys, math, time
  16. sys.path.append(PATH2PYPY)
  17. from pypy.rlib.objectmodel import specialize
  18. from pypy.rpython.lltypesystem import lltype, rffi
  19. from pypy.rpython.tool import rffi_platform as platform
  20. from pypy.rlib.rsdl import RSDL, RSDL_helper
  21. from pypy.rlib.rsdl.eci import get_rsdl_compilation_info
  22.  
  23. eci = get_rsdl_compilation_info()
  24. ## wrapper for rffi.llexternal just to shorten the call
  25. def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci)
  26.  
  27. JoystickPtr = lltype.Ptr(lltype.ForwardReference())
  28. JoyAxisEventPtr = lltype.Ptr(lltype.ForwardReference())
  29. JoyBallEventPtr = lltype.Ptr(lltype.ForwardReference())
  30. JoyButtonEventPtr = lltype.Ptr(lltype.ForwardReference())
  31. JoyHatEventPtr = lltype.Ptr(lltype.ForwardReference())
  32.  
  33.  
  34. class CConfig:
  35.         _compilation_info_ = eci
  36.         Joystick = platform.Struct('SDL_JoyAxisEvent', [])              # just and ID, struct contains nothing
  37.         # rsdl/constants.py already defines SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, etc..
  38.         JoyAxisEvent = platform.Struct('SDL_JoyAxisEvent',
  39.                         [('type', rffi.INT),
  40.                         ('which', rffi.INT),
  41.                         ('axis', rffi.INT),
  42.                         ('value', rffi.INT)])
  43.         JoyBallEvent = platform.Struct('SDL_JoyBallEvent',
  44.                         [('type', rffi.INT),
  45.                         ('which', rffi.INT),
  46.                         ('ball', rffi.INT),
  47.                         ('xrel', rffi.INT), ('yrel', rffi.INT)])
  48.         JoyButtonEvent = platform.Struct('SDL_JoyButtonEvent',
  49.                         [('type', rffi.INT),
  50.                         ('which', rffi.INT),
  51.                         ('button', rffi.INT),
  52.                         ('state', rffi.INT)])           # SDL_PRESSED or SDL_RELEASED
  53.         JoyHatEvent = platform.Struct('SDL_JoyHatEvent',
  54.                         [('type', rffi.INT),
  55.                         ('which', rffi.INT),
  56.                         ('hat', rffi.INT),
  57.                         ('value', rffi.INT)])           # SDL_HAT_*
  58.  
  59. CONSTS = 'INIT_JOYSTICK QUERY ENABLE IGNORE PRESSED RELEASED'
  60. #hat already in rsdl/constants.py#HAT_CENTERED HAT_UP HAT_RIGHT HAT_DOWN HAT_LEFT HAT_RIGHTUP HAT_RIGHTDOWN HAT_LEFTUP HAT_LEFTDOWN'
  61. for name in CONSTS.split():
  62.         name = name.strip()
  63.         if name:
  64.                 ci = platform.ConstantInteger('SDL_%s' %name)
  65.                 setattr( CConfig, name, ci )
  66. globals().update(platform.configure(CConfig))
  67.  
  68. JoystickPtr.TO.become(Joystick)
  69. JoyAxisEventPtr.TO.become(JoyAxisEvent)
  70. JoyBallEventPtr.TO.become(JoyBallEvent)
  71. JoyButtonEventPtr.TO.become(JoyButtonEvent)
  72. JoyHatEventPtr.TO.become(JoyHatEvent)
  73.  
  74. #Updates the state(position, buttons, etc.) of all open joysticks.
  75. #If joystick events have been enabled with SDL_JoystickEventState then this is called automatically in the event loop.
  76. JoystickUpdate = external('SDL_JoystickUpdate', [], lltype.Void)
  77. NumJoysticks = external('SDL_NumJoysticks', [], rffi.INT)
  78. ## CCHARP seems to stand for C char pointer ##
  79. JoystickName = external('SDL_JoystickName', [rffi.INT], rffi.CCHARP)
  80. JoystickOpen = external('SDL_JoystickOpen', [rffi.INT], JoystickPtr)
  81. JoystickOpened = external('SDL_JoystickOpened', [rffi.INT], rffi.INT)
  82. JoystickIndex = external('SDL_JoystickIndex', [JoystickPtr], rffi.INT)
  83. JoystickNumAxes = external('SDL_JoystickNumAxes', [JoystickPtr], rffi.INT)
  84. JoystickNumBalls = external('SDL_JoystickNumBalls', [JoystickPtr], rffi.INT)
  85. JoystickNumHats = external('SDL_JoystickNumHats', [JoystickPtr], rffi.INT)
  86. JoystickNumButtons = external('SDL_JoystickNumButtons', [JoystickPtr], rffi.INT)
  87. JoystickGetAxis = external('SDL_JoystickGetAxis', [JoystickPtr,rffi.INT], rffi.INT)             # 16bit signed integer (-32768 to 32768)
  88. JoystickGetHat = external('SDL_JoystickGetHat', [JoystickPtr,rffi.INT], rffi.INT)               # Uint8
  89. JoystickGetButton = external('SDL_JoystickGetButton', [JoystickPtr,rffi.INT], rffi.INT)         # Uint8
  90. # is this correct?
  91. #JoystickBallXPtr = lltype.Ptr(lltype.ForwardReference())
  92. #JoystickBallYPtr = lltype.Ptr(lltype.ForwardReference())
  93. #int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy);
  94. #JoystickGetBall = external('SDL_JoystickGetBall', [JoystickPtr,rffi.INT, JoystickBallXPtr, JoystickBallYPtr], rffi.INT)                # Uint8
  95. JoystickClose = external('SDL_JoystickClose', [JoystickPtr], lltype.Void)               # Uint8
  96. #This function is used to enable or disable joystick event processing. With joystick event processing disabled you will have to update joystick states with SDL_JoystickUpdate and read the joystick information manually. state is either SDL_QUERY, SDL_ENABLE or SDL_IGNORE.
  97. JoystickEventState = external('SDL_JoystickEventState', [rffi.INT], rffi.INT)
  98.  
  99. def handle_event( etype, event ):
  100.         if etype == RSDL.JOYAXISMOTION:
  101.                 p = rffi.cast( JoyAxisEventPtr, event )
  102.                 axis = rffi.getintfield(p, 'c_axis')
  103.                 value = rffi.getintfield(p, 'c_value')
  104.                 print 'axis: %s value: %s' %(axis, value)
  105.  
  106.         elif etype == RSDL.JOYBALLMOTION:
  107.                 p = rffi.cast( JoyBallEventPtr, event )
  108.                 ball = rffi.getintfield(p, 'c_ball')
  109.                 x = rffi.getintfield(p, 'c_xrel')
  110.                 y = rffi.getintfield(p, 'c_yrel')
  111.                 print 'ball: %s x: %s y: %s' %(ball, x,y)
  112.  
  113.         elif etype == RSDL.JOYHATMOTION:
  114.                 p = rffi.cast( JoyHatEventPtr, event )
  115.                 hat = rffi.getintfield(p, 'c_hat')
  116.                 value = rffi.getintfield(p, 'c_value')
  117.                 print 'hat: %s value: %s' %(hat, value)
  118.  
  119.         elif etype in ( RSDL.JOYBUTTONDOWN, RSDL.JOYBUTTONUP ):
  120.                 p = rffi.cast( JoyButtonEventPtr, event )
  121.                 but = rffi.getintfield(p, 'c_button')
  122.                 state = rffi.getintfield(p, 'c_state')
  123.                 print 'button: %s state: %s' %(but, state)
  124.  
  125.  
  126. def poll(loops=1000):
  127.         event = lltype.malloc(RSDL.Event, flavor='raw')
  128.         try:
  129.                 i = 1
  130.                 while i < loops:
  131.                         ok = RSDL.PollEvent(event); ok = rffi.cast(lltype.Signed, ok)
  132.                         assert ok >= 0
  133.                         if ok > 0: c_type = rffi.getintfield(event, 'c_type'); handle_event( c_type, event )
  134.                         time.sleep(0.01)
  135.                         i += 1
  136.         finally: lltype.free(event, flavor='raw')
  137.  
  138. def test():
  139.         assert RSDL.Init(INIT_JOYSTICK | RSDL.INIT_VIDEO ) >= 0
  140.         num = NumJoysticks(); print 'number of joysticks/gamepads: %s' %num
  141.         JoystickEventState( RSDL.ENABLE )
  142.         if num:
  143.                 joy = JoystickOpen( 0 )
  144.                 numaxes = JoystickNumAxes( joy ); print 'number of axes: %s' %numaxes
  145.                 numbut = JoystickNumButtons( joy ); print 'number of buttons: %s' %numbut
  146.                 poll()
  147.  
  148. if __name__ == '__main__':
  149.         from pypy.translator.interactive import Translation
  150.         t = Translation( test )
  151.         t.annotate(); t.rtype()
  152.         entrypoint = t.compile_c()
  153.         entrypoint()
RAW Paste Data
Want to get better at Python?
Learn to code Python in 2017
Pastebin PRO Summer Special!
Get 40% OFF on Pastebin PRO accounts!
Top