Changeset 114 for branches/cwiidpy

Show
Ignore:
Timestamp:
05/15/07 19:32:43 (2 years ago)
Author:
dsmith
Message:

cwiidpy: split into multiple files

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/cwiidpy/Makefile

    r104 r114  
    22 
    33NAME = cwiidmodule 
    4 SOURCES = cwiidmodule.c 
     4SOURCES = cwiidmodule.c Wiimote.c 
    55 
    66SO_NAME = $(NAME).so 
  • branches/cwiidpy/cwiidmodule.c

    r111 r114  
    2020 * 
    2121 * ChangeLog: 
     22 * 2007-05-14 L. Donnie Smith <cwiid@abstrakraft.org> 
     23 * * moved Wiimote class to separate files 
     24 * 
    2225 * 2007-05-12 L. Donnie Smith <cwiid@abstrakraft.org> 
    2326 * * added keywords to read 
     
    5558 */ 
    5659 
    57 /* Apparently this has to be first for every python interpreter extension */ 
    5860#include "Python.h" 
    5961 
    60 /* Standard Includes */ 
    61 #include <errno.h> 
    6262#include <stdlib.h> 
    6363 
    64 /* Interesting includes */ 
    6564#include "cwiid.h" 
    6665#include "structmember.h" 
    6766 
    68 /* Python Function declarations */ 
     67/* externally defined types */ 
     68extern PyTypeObject Wiimote_Type; 
     69 
     70/* cwiid module initializer */ 
    6971PyMODINIT_FUNC initcwiid(void); 
    7072 
    71 /* Types */ 
    72 typedef struct { 
    73         PyObject_HEAD 
    74         cwiid_wiimote_t *wiimote; 
    75         PyObject *callback; 
    76 } Wiimote; 
    77  
    78 static int Wiimote_init(Wiimote *self, PyObject *args, PyObject *kwds); 
    79 static PyObject *Wiimote_read(Wiimote *self, PyObject *args, PyObject *kwds); 
    80 static PyObject *Wiimote_write(Wiimote *self, PyObject *args, PyObject *kwds); 
    81 static PyObject *Wiimote_command(Wiimote *self, PyObject *args); 
    82 static PyObject *Wiimote_disconnect(Wiimote *self); 
    83 static PyObject * 
    84         Wiimote_enable(Wiimote *self, PyObject *args, PyObject *kwds); 
    85 static PyObject * 
    86         Wiimote_disable(Wiimote *self, PyObject *args, PyObject *kwds); 
    87 static PyObject *Wiimote_get_mesg(Wiimote *self, PyObject *args); 
    88 static PyObject *Wiimote_set_callback(Wiimote *self, PyObject *args); 
    89 static PyObject *Wiimote_get_state(Wiimote *self, void *closure); 
    90  
     73/* CWiid constants, enumerations */ 
    9174#define CONST_MACRO(a) {#a, CWIID_##a} 
    92 struct cwiid_constant { 
     75static struct { 
    9376        char *name; 
    9477        int value; 
    95 }; 
    96  
    97 static struct cwiid_constant cwiid_constants[] = { 
     78} cwiid_constants[] = { 
    9879        CONST_MACRO(FLAG_MESG_IFC), 
    9980        CONST_MACRO(FLAG_CONTINUOUS), 
     
    174155}; 
    175156 
    176 /* Type private functions */ 
    177 static PyObject * 
    178         Wiimote_new(PyTypeObject *type, PyObject *args, PyObject *kwds); 
    179 static void Wiimote_dealloc(Wiimote *self); 
    180  
    181 /* Helper functions */ 
    182 static void 
    183         callbackBridge(cwiid_wiimote_t *wiimote, int mesg_count, 
    184                        union cwiid_mesg mesg[]); 
    185 static PyObject *processMesgs(int mesg_count, union cwiid_mesg mesg[]); 
    186 static int cwiid_start(Wiimote *self, int flags); 
    187  
    188157/* Associates cwiid functions with python ones */ 
    189158static PyMethodDef modMethods[] =  
     
    192161}; 
    193162 
    194 /* Our type methods */ 
    195 static PyMethodDef Wiimote_Methods[] = 
    196 { 
    197         /* {"__init__", constructorwii, METH_VARARGS, "cwiid(function)"}, */ 
    198         {"read", (PyCFunction)Wiimote_read, METH_VARARGS | METH_KEYWORDS, 
    199          "read from wiimote"}, 
    200         {"write", (PyCFunction)Wiimote_write, METH_VARARGS | METH_KEYWORDS, 
    201          "write to wiimote"}, 
    202         {"command", (PyCFunction)Wiimote_command, METH_VARARGS, 
    203          "send wiimote command"}, 
    204         {"enable", (PyCFunction)Wiimote_enable, METH_VARARGS | METH_KEYWORDS, 
    205          "enable flags on wiimote"}, 
    206         {"disable", (PyCFunction)Wiimote_disable, METH_VARARGS | METH_KEYWORDS, 
    207          "disable flags on wiimote"}, 
    208         {"get_mesg", (PyCFunction)Wiimote_get_mesg, METH_VARARGS, 
    209          "blocking call to get messages"}, 
    210         {"set_callback", (PyCFunction)Wiimote_set_callback, METH_VARARGS, 
    211          "setup a mesg processing callback"}, 
    212         {"disconnect", (PyCFunction)Wiimote_disconnect, METH_NOARGS, 
    213          "disconnect wiimote"}, 
    214         {NULL, NULL} 
    215 }; 
    216  
    217 static PyMemberDef Wiimote_Members[] = { 
    218         {"_wiimote", T_OBJECT_EX, offsetof(Wiimote, wiimote), 0, "wiimote"}, 
    219         {"_callback", T_OBJECT_EX,offsetof(Wiimote, callback),0,"callback"}, 
    220         {NULL} 
    221 }; 
    222  
    223 static PyGetSetDef Wiimote_GetSet[] = { 
    224         {"state", (getter)Wiimote_get_state, NULL, "Wiimote state", NULL}, 
    225         {NULL} 
    226 }; 
    227  
    228 /* Defines a new type in python */ 
    229 static PyTypeObject Wiimote_Type = { 
    230         PyObject_HEAD_INIT(NULL) 
    231         0,                                              /* ob_size */ 
    232         "cwiid.Wiimote",                /* tp_name */ 
    233         sizeof(Wiimote),                /* tp_basicsize */ 
    234         0,                                              /* tp_itemsize */ 
    235         (destructor)Wiimote_dealloc,    /* tp_dealloc */ 
    236         0,                                              /* tp_print */ 
    237         0,                                              /* tp_getattr */ 
    238         0,                                              /* tp_setattr */ 
    239         0,                                              /* tp_compare */ 
    240         0,                                              /* tp_repr */ 
    241         0,                                              /* tp_as_number */ 
    242         0,                                              /* tp_as_sequence */ 
    243         0,                                              /* tp_as_mapping */ 
    244         0,                                              /* tp_hash */ 
    245         0,                                              /* tp_call */ 
    246         0,                                              /* tp_str */ 
    247         0,                                              /* tp_getattro */ 
    248         0,                                              /* tp_setattro */ 
    249         0,                                              /* tp_as_buffer */ 
    250         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,       /* tp_flags */ 
    251         "cwiid c-python interface",     /* tp_doc */ 
    252         0,                                              /* tp_traverse */ 
    253         0,                                              /* tp_clear */ 
    254         0,                                              /* tp_richcompare */ 
    255         0,                                              /* tp_weaklistoffset */ 
    256         0,                                              /* tp_iter */ 
    257         0,                                              /* tp_iternext */ 
    258         Wiimote_Methods,                /* tp_methods */ 
    259         Wiimote_Members,                /* tp_members */ 
    260         Wiimote_GetSet,                 /* tp_getset */ 
    261         0,                                              /* tp_base */ 
    262         0,                                              /* tp_dict */ 
    263         0,                                              /* tp_descr_get */ 
    264         0,                                              /* tp_descr_set */ 
    265         0,                                              /* tp_dictoffset */ 
    266         (initproc)Wiimote_init, /* tp_init */ 
    267         0,                                              /* tp_alloc */ 
    268         Wiimote_new,                    /* tp_new */ 
    269 }; 
    270  
    271163PyMODINIT_FUNC initcwiid(void) 
    272164{ 
    273         PyObject *m, *value
    274         struct cwiid_constant *constant
     165        PyObject *m
     166        int i
    275167 
    276168        PyEval_InitThreads(); 
     
    288180        PyModule_AddObject(m, "Wiimote", (PyObject*)&Wiimote_Type); 
    289181 
    290         for (constant = cwiid_constants; constant->name; constant++) { 
     182        for (i = 0; cwiid_constants[i].name; i++) { 
    291183                /* No way to report errors from here, so just ignore them and hope 
    292184                 * for segfault */ 
    293                 value = Py_BuildValue("i", constant->value); 
    294                 PyModule_AddObject(m, constant->name, value); 
     185                PyModule_AddIntConstant(m, cwiid_constants[i].name, cwiid_constants[i].value); 
    295186        } 
    296187} 
    297188 
    298 /* Allocate and deallocate functions */ 
    299 static PyObject * 
    300         Wiimote_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 
    301 { 
    302         Wiimote* self; 
    303  
    304         if (!(self = (Wiimote *) type->tp_alloc(type, 0))) { 
    305                 return NULL; 
    306         } 
    307  
    308         self->wiimote = NULL; 
    309         Py_INCREF(self->callback = Py_None); 
    310  
    311         return (PyObject*) self; 
    312 } 
    313  
    314 static void Wiimote_dealloc(Wiimote *self) 
    315 { 
    316         if (self->wiimote) { 
    317                 cwiid_disconnect(self->wiimote); 
    318         } 
    319         Py_XDECREF(self->callback); 
    320         self->ob_type->tp_free((PyObject *)self); 
    321 } 
    322  
    323 static int cwiid_start(Wiimote *self, int flags) 
    324 { 
    325         cwiid_wiimote_t *theMote; 
    326         bdaddr_t bdaddr = *BDADDR_ANY; 
    327  
    328         /* Set up wiimote */ 
    329         if(!(theMote = cwiid_connect(&bdaddr, flags))) { 
    330                 PyErr_SetString(PyExc_IOError, "Could not connect to wiimote"); 
    331                 return -1; 
    332         } 
    333         cwiid_set_data(theMote,self); /* keep pyobject with wiimote */ 
    334         self->wiimote = theMote; /* keep wiimote with pyobject */ 
    335         return 0; 
    336 } 
    337  
    338 static int Wiimote_init(Wiimote* self, PyObject* args, PyObject *kwds) 
    339 { 
    340         static char *kwlist[] = { "flags", NULL }; 
    341         int flags = 0; 
    342  
    343         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &flags)) { 
    344                 return -1; 
    345         } 
    346  
    347         if (cwiid_start(self, flags)) { 
    348                 return -1; 
    349         } 
    350  
    351         return 0; 
    352 } 
    353  
    354 static PyObject *Wiimote_read(Wiimote *self, PyObject *args, PyObject *kwds) 
    355 { 
    356         static char *kwlist[] = { "flags", "offset", "len", NULL }; 
    357         unsigned char flags; 
    358         unsigned int offset; 
    359         unsigned int len; 
    360         void *buf; 
    361         PyObject *pyRetBuf; 
    362  
    363         if (!PyArg_ParseTupleAndKeywords(args, kwds, "BII", kwlist, &flags, 
    364                                          &offset, &len)) { 
    365                 return NULL; 
    366         } 
    367  
    368         if (!(pyRetBuf = PyBuffer_New(len))) { 
    369                 return NULL; 
    370         } 
    371         if (PyObject_AsWriteBuffer(pyRetBuf, &buf, (int *)&len)) { 
    372                 Py_DECREF(pyRetBuf); 
    373                 return NULL; 
    374         } 
    375         if (cwiid_read(self->wiimote,flags,offset,len,buf)) { 
    376                 PyErr_SetString(PyExc_IOError, "Wiimote read error"); 
    377                 Py_DECREF(pyRetBuf); 
    378                 return NULL; 
    379         } 
    380  
    381         return pyRetBuf; 
    382 } 
    383  
    384 static PyObject *Wiimote_write(Wiimote *self, PyObject *args, PyObject *kwds) 
    385 { 
    386         static char *kwlist[] = { "flags", "offset", "buffer", NULL }; 
    387         unsigned char flags; 
    388         unsigned int offset; 
    389         void *buf; 
    390         int len; 
    391  
    392         if (!PyArg_ParseTupleAndKeywords(args, kwds, "BIt#", kwlist, &flags, 
    393                                          &offset, &buf, &len)) { 
    394                 return NULL; 
    395         } 
    396  
    397         if (cwiid_write(self->wiimote, flags, offset, len, buf)) { 
    398                 PyErr_SetString(PyExc_IOError, "Wiimote write error"); 
    399                 return NULL; 
    400         } 
    401  
    402         Py_RETURN_NONE; 
    403 } 
    404  
    405 static PyObject *Wiimote_command(Wiimote *self, PyObject *args) 
    406 { 
    407         /* Python types */ 
    408         PyObject *pycommand; 
    409         PyObject *pyflags; 
    410  
    411         /* C types */ 
    412         enum cwiid_command command; 
    413         uint8_t flags; 
    414  
    415         PyArg_UnpackTuple(args, "command", 2, 2, &pycommand, &pyflags); 
    416         if(!(PyInt_Check(pycommand) && PyInt_Check(pyflags))) { 
    417                 PyErr_SetString(PyExc_TypeError, "command and flags must be ints"); 
    418         } 
    419  
    420         /* marshal everything over */ 
    421         command = (enum cwiid_command) PyInt_AsLong(pycommand); 
    422         flags = (uint8_t) PyInt_AsLong(pyflags); 
    423  
    424         /* finally, send the command to the wiimote */ 
    425         cwiid_command(self->wiimote, command, flags); 
    426         /* PyGILState_Release(gstate); */ 
    427  
    428         Py_RETURN_NONE; 
    429 } 
    430  
    431 static PyObject *Wiimote_disconnect(Wiimote *self) 
    432 { 
    433         if (cwiid_disconnect(self->wiimote)) { 
    434                 PyErr_SetString(PyExc_IOError, "Wiimote disconnect error"); 
    435                 self->wiimote = NULL; 
    436                 return NULL; 
    437         } 
    438         self->wiimote = NULL; 
    439  
    440         Py_RETURN_NONE; 
    441 } 
    442  
    443 static PyObject *Wiimote_enable(Wiimote *self, PyObject *args, PyObject *kwds) 
    444 { 
    445         static char *kwlist[] = { "flags", NULL }; 
    446         int flags; 
    447  
    448         if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &flags)) { 
    449                 return NULL; 
    450         } 
    451  
    452         if (cwiid_enable(self->wiimote, flags)) { 
    453                 PyErr_SetString(PyExc_IOError, "cwiid_enable error"); 
    454                 return NULL; 
    455         } 
    456  
    457         Py_RETURN_NONE; 
    458 } 
    459  
    460 static PyObject * 
    461         Wiimote_disable(Wiimote *self, PyObject *args, PyObject *kwds) 
    462 { 
    463         static char *kwlist[] = { "flags", NULL }; 
    464         int flags; 
    465  
    466         if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &flags)) { 
    467                 return NULL; 
    468         } 
    469  
    470         if (cwiid_disable(self->wiimote, flags)) { 
    471                 PyErr_SetString(PyExc_IOError, "cwiid_disable error"); 
    472                 return NULL; 
    473         } 
    474  
    475         Py_RETURN_NONE; 
    476 } 
    477  
    478 static PyObject *Wiimote_get_mesg(Wiimote *self, PyObject *args) 
    479 { 
    480         union cwiid_mesg *mesg; 
    481         int mesg_count; 
    482  
    483         /* get the messages from Mr. Wiimote */ 
    484         if (cwiid_get_mesg(self->wiimote, &mesg_count, &mesg)) { 
    485                 if (errno == EAGAIN) { 
    486                         Py_RETURN_NONE; 
    487                 } 
    488                 else { 
    489                         PyErr_SetString(PyExc_IOError, "get_mesg error"); 
    490                         return NULL; 
    491                 } 
    492         } 
    493  
    494         return processMesgs(mesg_count, mesg); 
    495 } 
    496  
    497 static PyObject *Wiimote_set_callback(Wiimote *self, PyObject *args) 
    498 { 
    499         PyObject *pyCallback; 
    500  
    501         PyArg_UnpackTuple(args, "set_callback", 1, 1, &pyCallback); 
    502         if (!PyCallable_Check(pyCallback)) { 
    503                 PyErr_SetString(PyExc_TypeError, "callback must be callable!"); 
    504         } 
    505         Py_XINCREF(pyCallback); 
    506  
    507         /* Set this callback as an attribute in the class */ 
    508         /* wasn't a callback before */  
    509         if (self->callback== Py_None) { 
    510                 cwiid_set_mesg_callback(self->wiimote,  
    511                                         (cwiid_mesg_callback_t *) callbackBridge); 
    512         } 
    513         self->callback = pyCallback; 
    514  
    515         Py_RETURN_NONE; 
    516 } 
    517  
    518 static PyObject *Wiimote_get_state(Wiimote* self, void *closure) 
    519 { 
    520         struct cwiid_state state; 
    521         PyObject *PyState; 
    522  
    523         if (cwiid_get_state(self->wiimote, &state)) { 
    524                 PyErr_SetString(PyExc_IOError, "get state error"); 
    525                 return NULL; 
    526         } 
    527  
    528         PyState = Py_BuildValue("{s:B,s:B,s:B,s:B,s:i,s:i}", 
    529                                 "rpt_mode", state.rpt_mode, 
    530                                 "led", state.led, 
    531                                 "rumble", state.rumble, 
    532                                 "battery", state.battery, 
    533                                 "ext_type", state.ext_type, 
    534                                 "error", state.error); 
    535  
    536         if (state.rpt_mode & CWIID_RPT_BTN) { 
    537                 PyObject *PyBtn = Py_BuildValue("I", state.buttons); 
    538                 if (!PyBtn) { 
    539                         Py_DECREF(PyState); 
    540                         return NULL; 
    541                 } 
    542                 if (PyDict_SetItemString(PyState, "buttons", PyBtn)) { 
    543                         Py_DECREF(PyState); 
    544                         Py_DECREF(PyBtn); 
    545                         return NULL; 
    546                 } 
    547                 Py_DECREF(PyBtn); 
    548         } 
    549  
    550         if (state.rpt_mode & CWIID_RPT_ACC) { 
    551                 PyObject *PyAcc = Py_BuildValue("{s:B,s:B,s:B}", 
    552                                                                     "x", state.acc[CWIID_X], 
    553                                             "y", state.acc[CWIID_Y], 
    554                                             "z", state.acc[CWIID_Z]); 
    555                 if (!PyAcc) { 
    556                         Py_DECREF(PyState); 
    557                         return NULL; 
    558                 } 
    559                 if (PyDict_SetItemString(PyState, "acc", PyAcc)) { 
    560                         Py_DECREF(PyState); 
    561                         Py_DECREF(PyAcc); 
    562                         return NULL; 
    563                 } 
    564                 Py_DECREF(PyAcc); 
    565         } 
    566  
    567         if (state.rpt_mode & CWIID_RPT_IR) { 
    568                 int i; 
    569                 PyObject *PyIr = PyList_New(CWIID_IR_SRC_COUNT); 
    570  
    571                 if (!PyIr) { 
    572                         Py_DECREF(PyState); 
    573                         return NULL; 
    574                 } 
    575  
    576                 if (PyDict_SetItemString(PyState, "ir_src", PyIr)) { 
    577                         Py_DECREF(PyState); 
    578                         Py_DECREF(PyIr); 
    579                         return NULL; 
    580                 } 
    581  
    582                 Py_DECREF(PyIr); 
    583  
    584                 for (i=0; i < CWIID_IR_SRC_COUNT; i++) { 
    585                         PyObject *PyIrSrc; 
    586                         PyObject *PySize; 
    587  
    588                         if (state.ir_src[i].valid) { 
    589                                 PyIrSrc = Py_BuildValue("{s:{s:I,s:I}}", 
    590                                                         "pos", 
    591                                                           "x", state.ir_src[i].pos[CWIID_X], 
    592                                                           "y", state.ir_src[i].pos[CWIID_Y]); 
    593                                 if (!PyIrSrc) { 
    594                                         Py_DECREF(PyState); 
    595                                         return NULL; 
    596                                 } 
    597  
    598                                 if (state.ir_src[i].size != -1) { 
    599                                         if (!(PySize = PyInt_FromLong( 
    600                                           (long)state.ir_src[i].size))) { 
    601                                                 Py_DECREF(PyState); 
    602                                                 Py_DECREF(PyIrSrc); 
    603                                                 return NULL; 
    604                                         } 
    605                                         if (PyDict_SetItemString(PyIrSrc, "size", PySize)) { 
    606                                                 Py_DECREF(PyState); 
    607                                                 Py_DECREF(PyIrSrc); 
    608                                                 Py_DECREF(PySize); 
    609                                                 return NULL; 
    610                                         } 
    611  
    612                                         Py_DECREF(PySize); 
    613                                 } 
    614                         } 
    615                         else { 
    616                                 Py_INCREF(PyIrSrc = Py_None); 
    617                         } 
    618  
    619                         PyList_SET_ITEM(PyIr, i, PyIrSrc); 
    620                 } 
    621         } 
    622  
    623         switch (state.ext_type) { 
    624                 PyObject *PyExt; 
    625         case CWIID_EXT_NUNCHUK: 
    626                 if (state.rpt_mode & CWIID_RPT_NUNCHUK) { 
    627                         PyExt = Py_BuildValue("{s:{s:B,s:B},s:{s:B,s:B,s:B},s:I}", 
    628                                               "stick", 
    629                                                 "x", state.ext.nunchuk.stick[CWIID_X], 
    630                                                 "y", state.ext.nunchuk.stick[CWIID_Y], 
    631                                               "acc", 
    632                                                 "x", state.ext.nunchuk.acc[CWIID_X], 
    633                                                 "y", state.ext.nunchuk.acc[CWIID_Y], 
    634                                                 "z", state.ext.nunchuk.acc[CWIID_Z], 
    635                                               "buttons", state.ext.nunchuk.buttons); 
    636  
    637                         if (!PyExt) { 
    638                                 Py_DECREF(PyState); 
    639                                 return NULL; 
    640                         } 
    641  
    642                         if (PyDict_SetItemString(PyState, "nunchuk", PyExt)) { 
    643                                 Py_DECREF(PyState); 
    644                                 Py_DECREF(PyExt); 
    645                                 return NULL; 
    646                         } 
    647  
    648                         Py_DECREF(PyExt); 
    649                 } 
    650                 break; 
    651         case CWIID_EXT_CLASSIC: 
    652                 if (state.rpt_mode & CWIID_RPT_CLASSIC) { 
    653                         PyExt = Py_BuildValue("{s:{s:B,s:B},s:{s:B,s:B},s:B,s:B,s:I}", 
    654                                               "l_stick", 
    655                                                 "x", state.ext.classic.l_stick[CWIID_X], 
    656                                                 "y", state.ext.classic.l_stick[CWIID_Y], 
    657                                               "r_stick", 
    658                                                 "x", state.ext.classic.r_stick[CWIID_X], 
    659                                                 "y", state.ext.classic.r_stick[CWIID_Y], 
    660                                               "l", state.ext.classic.l, 
    661                                               "r", state.ext.classic.r, 
    662                                               "buttons", state.ext.classic.buttons); 
    663  
    664                         if (!PyExt) { 
    665                                 Py_DECREF(PyState); 
    666                                 return NULL; 
    667                         } 
    668  
    669                         if (PyDict_SetItemString(PyState, "classic", PyExt)) { 
    670                                 Py_DECREF(PyState); 
    671                                 Py_DECREF(PyExt); 
    672                                 return NULL; 
    673                         } 
    674  
    675                         Py_DECREF(PyExt); 
    676                 } 
    677                 break; 
    678         default: 
    679                 break; 
    680         } 
    681  
    682         return PyState; 
    683 } 
    684  
    685 static void  
    686         callbackBridge(cwiid_wiimote_t *wiimote, int mesg_count, 
    687                        union cwiid_mesg mesg[]) 
    688 { 
    689         PyObject *argTuple; 
    690         PyObject *pyself; 
    691         /* PyObject *pyCallback; */ 
    692         PyGILState_STATE gstate; 
    693  
    694         gstate = PyGILState_Ensure(); 
    695  
    696         argTuple = processMesgs(mesg_count, mesg); 
    697  
    698         /* Put id and the list of messages as the arguments to the callback */ 
    699         pyself = (PyObject *) cwiid_get_data(wiimote); 
    700         if (PyMethod_Check(((Wiimote *)pyself)->callback)) { 
    701                 /* Sorry for the ugliness here. 
    702                  * After determining that the callback is a method in a class, 
    703                  * this line calls that function object with self and the argtuple 
    704                  * as arguments. */ 
    705                 PyObject_CallFunction( 
    706                   PyMethod_Function(((Wiimote *)pyself)->callback),"(OO)", 
    707                   PyMethod_Class(((Wiimote *)pyself)->callback), argTuple 
    708                   ); 
    709         } 
    710         else { 
    711                 PyObject_CallFunction(((Wiimote *)pyself)->callback, 
    712                   "(O)",argTuple); 
    713         } 
    714  
    715         Py_XDECREF(argTuple); /* actually need to decref the entire structure */ 
    716         PyGILState_Release(gstate); 
    717 } 
    718  
    719 /* This is the function responsible for marshaling the cwiid messages from 
    720  * C to python. It's rather complicated since it uses a complex C union 
    721  * to store the data and multiple enumerations to figure out what data is 
    722  * actually being sent. Neither of these common C types really translate 
    723  * well into Python. I've done my best to translate it to python as follows: 
    724  * 
    725  * Python callback takes arg (mesgs). The mesgs is a list of 
    726  * mesg tuples which contain the mesg type and a dict of the arguments. 
    727  *  
    728  * Ex: 
    729  * mesgs =>[(CWIID_BTN_MESG,{"buttons":btnMask}),  
    730  *          (CWIID_ACC_MESG,{"x":xVal, "y":yVal, "z":zVal})] 
    731  */ 
    732 static PyObject *processMesgs(int mesg_count, union cwiid_mesg mesg[]) 
    733 { 
    734         PyObject *mesglist; /* List of message tuples */ 
    735         PyObject *amesg; /* A single message (type, [arguments]) */ 
    736         PyObject *mesgVal; /* Dictionary of arguments for a message */ 
    737         PyObject *PyIrList; 
    738         int i, j; 
    739  
    740         if (!(mesglist = PyList_New(mesg_count))) { 
    741                 return NULL; 
    742         } 
    743  
    744         for (i = 0; i < mesg_count; i++) { 
    745                 switch (mesg[i].type) { 
    746                 case CWIID_MESG_STATUS: 
    747                         mesgVal = Py_BuildValue("{s:B,s:i}", 
    748                                                 "battery", mesg[i].status_mesg.battery, 
    749                                                 "ext_type", mesg[i].status_mesg.ext_type); 
    750                         break; 
    751                 case CWIID_MESG_BTN: 
    752                         mesgVal = Py_BuildValue("{s:I}", 
    753                                                 "buttons", mesg[i].btn_mesg.buttons); 
    754                         break; 
    755                 case CWIID_MESG_ACC: 
    756                         mesgVal = Py_BuildValue("{s:{s:B,s:B,s:B}}", 
    757                                                 "acc", 
    758                                                   "x", mesg[i].acc_mesg.acc[CWIID_X], 
    759                                                   "y", mesg[i].acc_mesg.acc[CWIID_Y], 
    760                                                   "z", mesg[i].acc_mesg.acc[CWIID_Z]); 
    761                         break; 
    762                 case CWIID_MESG_IR: 
    763                         mesgVal = NULL; 
    764  
    765                         if (!(PyIrList = PyList_New(CWIID_IR_SRC_COUNT))) { 
    766                                 break; 
    767                         } 
    768  
    769                         for (j=0; j < CWIID_IR_SRC_COUNT; j++) { 
    770                                 PyObject *PyIrSrc; 
    771                                 PyObject *PySize; 
    772  
    773                                 if (mesg[i].ir_mesg.src[j].valid) { 
    774                                         PyIrSrc = Py_BuildValue("{s:{s:I,s:I}}", 
    775                                                      "pos", 
    776                                                        "x", mesg[i].ir_mesg.src[j].pos[CWIID_X], 
    777                                                        "y", mesg[i].ir_mesg.src[j].pos[CWIID_Y]); 
    778  
    779                                         if (!PyIrSrc) { 
    780                                                 Py_DECREF(PyIrList); 
    781                                                 PyIrList = NULL; 
    782                                                 break; 
    783                                         } 
    784  
    785                                         if (mesg[i].ir_mesg.src[j].size != -1) { 
    786                                                 if (!(PySize = PyInt_FromLong( 
    787                                                   (long)mesg[i].ir_mesg.src[j].size))) { 
    788                                                         Py_DECREF(PyIrList); 
    789                                                         Py_DECREF(PyIrSrc); 
    790                                                         PyIrList = NULL; 
    791                                                         break; 
    792                                                 } 
    793                                                 if (PyDict_SetItemString(PyIrSrc, "size", PySize)) { 
    794                                                         Py_DECREF(PyIrList); 
    795                                                         Py_DECREF(PyIrSrc); 
    796                                                         Py_DECREF(PySize); 
    797                                                         PyIrList = NULL; 
    798                                                         break; 
    799                                                 } 
    800  
    801                                                 Py_DECREF(PySize); 
    802                                         } 
    803                                 } 
    804                                 else { 
    805                                         Py_INCREF(PyIrSrc = Py_None); 
    806                                 } 
    807                                 PyList_SET_ITEM(PyIrList, j, PyIrSrc); 
    808                         } 
    809  
    810                         if (!PyIrList) { 
    811                                 break; 
    812                         } 
    813  
    814                         mesgVal = Py_BuildValue("{s:O}", "src", PyIrList); 
    815                         Py_DECREF(PyIrList); 
    816                         break; 
    817                 case CWIID_MESG_NUNCHUK: 
    818                         mesgVal = Py_BuildValue("{s:{s:B,s:B},s:{s:B,s:B,s:B},s:I}", 
    819                                                 "stick", 
    820                                                   "x", mesg[i].nunchuk_mesg.stick[CWIID_X], 
    821                                                   "y", mesg[i].nunchuk_mesg.stick[CWIID_Y], 
    822                                                 "acc", 
    823                                                   "x", mesg[i].nunchuk_mesg.acc[CWIID_X], 
    824                                                   "y", mesg[i].nunchuk_mesg.acc[CWIID_Y], 
    825                                                   "z", mesg[i].nunchuk_mesg.acc[CWIID_Z], 
    826                                                 "buttons", mesg[i].nunchuk_mesg.buttons); 
    827                         break; 
    828                 case CWIID_MESG_CLASSIC: 
    829                         mesgVal = Py_BuildValue("{s:{s:B,s:B},s:{s:B,s:B},s:B,s:B,s:I}", 
    830                                      "l_stick", 
    831                                        "x", mesg[i].classic_mesg.l_stick[CWIID_X], 
    832                                        "y", mesg[i].classic_mesg.l_stick[CWIID_Y], 
    833                                      "r_stick", 
    834                                        "x", mesg[i].classic_mesg.r_stick[CWIID_X], 
    835                                        "y", mesg[i].classic_mesg.r_stick[CWIID_Y], 
    836                                      "l", mesg[i].classic_mesg.l, 
    837                                      "r", mesg[i].classic_mesg.r, 
    838                                      "buttons", mesg[i].classic_mesg.buttons); 
    839                         break; 
    840                 case CWIID_MESG_ERROR: 
    841                         mesgVal = Py_BuildValue("{s:i}", 
    842                                                 "error",mesg[i].error_mesg.error); 
    843                         break; 
    844                 default: 
    845                         Py_INCREF(mesgVal = Py_None); 
    846                         break; 
    847                 } 
    848  
    849                 if (!mesgVal) { 
    850                         return NULL; 
    851                 } 
    852  
    853                 /* Finally Put the type next to the message in a tuple and 
    854                  * append them to the list of messages */ 
    855                 if (!(amesg = Py_BuildValue("(iO)", mesg[i].type, mesgVal))) { 
    856                         Py_DECREF(mesgVal); 
    857                         return NULL; 
    858                 } 
    859                 Py_DECREF(mesgVal); 
    860                 PyList_SET_ITEM(mesglist, i, amesg); 
    861         } 
    862  
    863         return mesglist; 
    864 }