Adding new features: joystick.

Not sure if this help any more, but here is a short hack I used to query the joystick on Windows. The small extension uses winmm (comes with PlatformSDK for Windows XP). Oh, and LGPL license of course. Tell me if you need binaries for Pytrhon 2.4 or Python 2.5.

enn0x

2007/07/07 EDIT: fixed a problem in method getButton. Now you can use getButton( 0 ) to getButton( n-1 ) where n is the number of buttons.

/*
    Copyright (c) 2007 Ralf Pfrogner (ralf.pfrogner@gmx.net)

    This file is part of "Joystick Python Extension".

    This software is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation; either version 2.1 of the
    License, or (at your option) any later version. The text of the
    GNU Lesser General Public License is included with this library in
    the file license.txt.

    This software 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 file
    license.txt for more details.
*/

// Python headers
//
#include <Python.h>
#include "structmember.h"

// Windows MMS headers
//
#include <Windows.h>



// ____________________________________________________________________________
// JOYSTICK TYPE

typedef struct {
    PyObject_HEAD

    int joyID;
    JOYINFOEX info;
    JOYCAPS caps;

} PyJoystickObject;

extern PyTypeObject PyJoystickType;

// _____UTILS_____

static float parametric( int x0 )
{
    int x;

    // integer range is asymetic around zero,
    // so we have to cheat a little to get float ranges from -1.0 to 1.0

    if ( x0 < 32767 ) x = x0 - 32768;
    else              x = x0 - 32767;

    return (float)x / 32768.0f;
}

// _____METHOD : UPDATE_____

static PyObject* PyJoystickObject_update( PyJoystickObject *self, PyObject *args )
{
    int success;

    success = joyGetPosEx( self->joyID, &(self->info) );

    return Py_BuildValue( "O", ( success == JOYERR_NOERROR ) ? Py_True : Py_False );
}

// _____METHOD : GET X_____

static PyObject* PyJoystickObject_getX( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwXpos ) );
}

// _____METHOD : GET Y_____

static PyObject* PyJoystickObject_getY( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwYpos ) );
}

// _____METHOD : GET Z_____

static PyObject* PyJoystickObject_getZ( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwZpos ) );
}

// _____METHOD : GET R_____

static PyObject* PyJoystickObject_getR( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwRpos ) );
}

// _____METHOD : GET U_____

static PyObject* PyJoystickObject_getU( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwUpos ) );
}

// _____METHOD : GET V_____

static PyObject* PyJoystickObject_getV( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "f", parametric( self->info.dwVpos ) );
}

// _____METHOD : NUM AXES_____

static PyObject* PyJoystickObject_numAxes( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "i", self->caps.wNumAxes );
}

// _____METHOD : NUM BUTTONS_____

static PyObject* PyJoystickObject_numButtons( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "i", self->caps.wNumButtons );
}

// _____METHOD : NAME_____

static PyObject* PyJoystickObject_name( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "s", self->caps.szPname );
}

// _____METHOD : GET BUTTON_____

static PyObject* PyJoystickObject_getButton( PyJoystickObject *self, PyObject *args )
{
    int btn;
    bool state;

    if ( ! PyArg_ParseTuple( args, "i", &btn ) )
        return NULL;

    state = self->info.dwButtons & ( 1 << btn );

    return Py_BuildValue( "O", state ? Py_True : Py_False );
}

// _____METHOD : GET POV_____

static PyObject* PyJoystickObject_getPOV( PyJoystickObject *self, PyObject *args )
{
    return Py_BuildValue( "i", self->info.dwPOV / 100 );
}




// _____METHODS_____

static PyMethodDef PyJoystickObject_methods[ ] = {
    { "numAxes", ( PyCFunction ) PyJoystickObject_numAxes, METH_VARARGS, "" },
    { "numButtons", ( PyCFunction ) PyJoystickObject_numButtons, METH_VARARGS, "" },
    { "name", ( PyCFunction ) PyJoystickObject_name, METH_VARARGS, "" },
    { "update", ( PyCFunction ) PyJoystickObject_update, METH_VARARGS, "" },
    { "getButton", ( PyCFunction ) PyJoystickObject_getButton, METH_VARARGS, "" },
    { "getPOV", ( PyCFunction ) PyJoystickObject_getPOV, METH_VARARGS, "" },
    { "getX", ( PyCFunction ) PyJoystickObject_getX, METH_VARARGS, "" },
    { "getY", ( PyCFunction ) PyJoystickObject_getY, METH_VARARGS, "" },
    { "getZ", ( PyCFunction ) PyJoystickObject_getZ, METH_VARARGS, "" },
    { "getR", ( PyCFunction ) PyJoystickObject_getR, METH_VARARGS, "" },
    { "getU", ( PyCFunction ) PyJoystickObject_getU, METH_VARARGS, "" },
    { "getV", ( PyCFunction ) PyJoystickObject_getV, METH_VARARGS, "" },

    { NULL }
};

// _____MEMBERS_____

static PyMemberDef PyJoystickObject_members[ ] = {
    { NULL }
};

// _____NEW_____

static PyObject* PyJoystickObject_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
{
    PyJoystickObject *self;

    self = ( PyJoystickObject* ) type->tp_alloc( type, 0 );
    if ( self != NULL ) { }

    return (PyObject *) self;
}

// _____INIT_____

static int PyJoystickObject_init( PyJoystickObject* self, PyObject *args, PyObject *kwds )
{
    if ( ! PyArg_ParseTuple( args, "i", &(self->joyID) ) )
        return NULL;

    self->info.dwFlags = JOY_RETURNALL;
    self->info.dwSize = sizeof( self->info );

    joyGetDevCaps( self->joyID, &(self->caps), sizeof( self->caps ) );
    joyGetPosEx( self->joyID, &(self->info) );

    return 0;
}

// _____DEALLOC_____

static void PyJoystickObject_dealloc( PyJoystickObject *self )
{
    //delete self->m_ptr;

    self->ob_type->tp_free( (PyObject *) self );
}

// ______TYPE_____

extern PyTypeObject PyJoystickType = {
    PyObject_HEAD_INIT( NULL )
    0,                                         /* ob_size */
    "Joystick.Joystick",                       /* tp_name */
    sizeof( PyJoystickObject ),                /* tp_basicsize */
    0,                                         /* tp_itemsize */
    ( destructor ) PyJoystickObject_dealloc,   /* tp_dealloc */
    0,                                         /* tp_print */
    0,                                         /* tp_getattr */
    0,                                         /* tp_setattr */
    0,                                         /* tp_compare */
    0,                                         /* tp_repr */
    0,                                         /* tp_as_number */
    0,                                         /* tp_as_sequence */
    0,                                         /* tp_as_mapping */
    0,                                         /* tp_hash */
    0,                                         /* tp_call */
    0,                                         /* tp_str */
    0,                                         /* tp_getattro */
    0,                                         /* tp_setattro */
    0,                                         /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT,                        /* tp_flags */
    0,                                         /* tp_doc */
    0,                                         /* tp_traverse */
    0,                                         /* tp_clear */
    0,                                         /* tp_richcompare */
    0,                                         /* tp_weaklistoffset */
    0,                                         /* tp_iter */
    0,                                         /* tp_iternext */
    PyJoystickObject_methods,                  /* tp_methods */
    PyJoystickObject_members,                  /* tp_members */
    0,                                         /* tp_getset */
    0,                                         /* tp_base */
    0,                                         /* tp_dict */
    0,                                         /* tp_descr_get */
    0,                                         /* tp_descr_set */
    0,                                         /* tp_dictoffset */
    ( initproc ) PyJoystickObject_init,        /* tp_init */
    0,                                         /* tp_alloc */
    PyJoystickObject_new,                      /* tp_new */
};



// ____________________________________________________________________________
// MODULE

// _____METHOD : NUM JOYSTICKS _____

static PyObject* Joystick_NumJoysticks( PyObject *self, PyObject *args )
{
    unsigned int i, n, nmax;
    JOYINFO info;

    nmax = joyGetNumDevs( );

    n = 0;

    for ( i=0; i < nmax; i++ ) {
        if ( joyGetPos( i, &info ) == JOYERR_NOERROR ) n++;
    }

    return Py_BuildValue( "i", n );
}

// _____METHODS_____

static PyMethodDef Pymethods[ ] = {
    { "NumJoysticks", ( PyCFunction ) Joystick_NumJoysticks, METH_VARARGS, "" },

    { NULL }
};

// ____INIT MODULE_____

PyMODINIT_FUNC initJoystick( void )
{
    PyObject* m;

    m = Py_InitModule3( "Joystick", Pymethods, "" );

    // Constants
    PyObject_SetAttrString( m, "__version__", Py_BuildValue( "s", "0.1" ) );

    //PyObject_SetAttrString( m, "ID1", PyInt_FromLong( JOYSTICKID1 ) );

    // Joystick
    if ( PyType_Ready( &PyJoystickType ) < 0 )
        return;

    Py_INCREF( &PyJoystickType );
    PyModule_AddObject( m, "Joystick", (PyObject*) &PyJoystickType );
}