Advertisement
Guest User

RSDL Joystick

a guest
Aug 11th, 2010
785
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.45 KB | None | 0 0
  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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement