root/branches/cwiidpy/Wiimote.c

Revision 117, 20.6 kB (checked in by dsmith, 2 years ago)

more cwiidpy

Line 
1 /*
2  * Copyright (C) 2007 Justin M. Tulloss <jmtulloss@gmail.com>
3  *
4  * Interface from Python to libcwiid
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  *
21  * ChangeLog:
22  * 2007-05-22 L. Donnie Smith <cwiid@abstrakraft.org>
23  * * changed disconnect to close
24  * * replaced command with attributes for rpt_mode, rumble, led,
25  *   added request_status method
26  * * fixed memory leak in get_mesg
27  * * added function names to argument parsing errors
28  *
29  * 2007-05-15 L. Donnie Smith <cwiid@abstrakraft.org>
30  * * revised message types
31  * * revised argument/keylist parsing
32  *
33  * 2007-05-14 L. Donnie Smith <cwiid@abstrakraft.org>
34  * * moved Wiimote class to separate file
35  */
36
37 #include "Python.h"
38 #include "structmember.h"
39 #include <errno.h>
40 #include "cwiid.h"
41
42 typedef struct {
43         PyObject_HEAD
44         cwiid_wiimote_t *wiimote;
45         PyObject *callback;
46 } Wiimote;
47
48 /* method prototypes */
49 static PyObject *
50         Wiimote_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
51 static void Wiimote_dealloc(Wiimote *self);
52 static int Wiimote_init(Wiimote *self, PyObject *args, PyObject *kwds);
53 static PyObject *Wiimote_close(Wiimote *self);
54
55 static PyObject *Wiimote_enable(Wiimote *self, PyObject *args, PyObject *kwds);
56 static PyObject *
57         Wiimote_disable(Wiimote *self, PyObject *args, PyObject *kwds);
58
59 static int
60         Wiimote_set_mesg_callback(Wiimote *self, PyObject *args, void *closure);
61 static PyObject *Wiimote_get_mesg(Wiimote *self);
62 static PyObject *Wiimote_get_state(Wiimote *self, void *closure);
63
64 static PyObject *Wiimote_request_status(Wiimote *self);
65 static int Wiimote_set_led(Wiimote *self, PyObject *PyLed, void *closure);
66 static int
67         Wiimote_set_rumble(Wiimote *self, PyObject *PyRumble, void *closure);
68 static int
69         Wiimote_set_rpt_mode(Wiimote *self, PyObject *PyRptMode, void *closure);
70
71 static PyObject *Wiimote_read(Wiimote *self, PyObject *args, PyObject *kwds);
72 static PyObject *Wiimote_write(Wiimote *self, PyObject *args, PyObject *kwds);
73
74 /* helper prototypes */
75 static cwiid_mesg_callback_t callbackBridge;
76 static PyObject *processMesgs(int mesg_count, union cwiid_mesg mesg[]);
77 static int cwiid_start(Wiimote *self, int flags);
78
79 static PyMethodDef Wiimote_Methods[] =
80 {
81         {"close", (PyCFunction)Wiimote_close, METH_NOARGS,
82          "close wiimote connection"},
83         {"enable", (PyCFunction)Wiimote_enable, METH_VARARGS | METH_KEYWORDS,
84          "enable flags on wiimote"},
85         {"disable", (PyCFunction)Wiimote_disable, METH_VARARGS | METH_KEYWORDS,
86          "disable flags on wiimote"},
87         {"set_mesg_callback", (PyCFunction)Wiimote_set_mesg_callback,
88          METH_VARARGS | METH_KEYWORDS, "setup a mesg processing callback"},
89         {"get_mesg", (PyCFunction)Wiimote_get_mesg, METH_NOARGS,
90          "blocking call to get messages"},
91         {"request_status", (PyCFunction)Wiimote_request_status, METH_NOARGS,
92          "request status message"},
93         {"read", (PyCFunction)Wiimote_read, METH_VARARGS | METH_KEYWORDS,
94          "read from wiimote"},
95         {"write", (PyCFunction)Wiimote_write, METH_VARARGS | METH_KEYWORDS,
96          "write to wiimote"},
97         {NULL, NULL, 0, NULL}
98 };
99
100 static PyGetSetDef Wiimote_GetSet[] = {
101         {"state", (getter)Wiimote_get_state, NULL, "Wiimote state", NULL},
102         {"mesg_callback", NULL, (setter)Wiimote_set_mesg_callback,
103          "Wiimote message callback", NULL},
104         {"led", NULL, (setter)Wiimote_set_led, "Wiimote led state", NULL},
105         {"rumble", NULL, (setter)Wiimote_set_rumble, "Wiimote rumble state", NULL},
106         {"rpt_mode", NULL, (setter)Wiimote_set_rpt_mode, "Wiimote report mode",
107          NULL},
108         {NULL, NULL, NULL, NULL, NULL}
109 };
110
111 PyTypeObject Wiimote_Type = {
112         PyObject_HEAD_INIT(NULL)
113         0,                                              /* ob_size */
114         "cwiid.Wiimote",                /* tp_name */
115         sizeof(Wiimote),                /* tp_basicsize */
116         0,                                              /* tp_itemsize */
117         (destructor)Wiimote_dealloc,    /* tp_dealloc */
118         0,                                              /* tp_print */
119         0,                                              /* tp_getattr */
120         0,                                              /* tp_setattr */
121         0,                                              /* tp_compare */
122         0,                                              /* tp_repr */
123         0,                                              /* tp_as_number */
124         0,                                              /* tp_as_sequence */
125         0,                                              /* tp_as_mapping */
126         0,                                              /* tp_hash */
127         0,                                              /* tp_call */
128         0,                                              /* tp_str */
129         0,                                              /* tp_getattro */
130         0,                                              /* tp_setattro */
131         0,                                              /* tp_as_buffer */
132         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,       /* tp_flags */
133         "cwiid c-python interface",     /* tp_doc */
134         0,                                              /* tp_traverse */
135         0,                                              /* tp_clear */
136         0,                                              /* tp_richcompare */
137         0,                                              /* tp_weaklistoffset */
138         0,                                              /* tp_iter */
139         0,                                              /* tp_iternext */
140         Wiimote_Methods,                /* tp_methods */
141         0,                                              /* tp_members */
142         Wiimote_GetSet,                 /* tp_getset */
143         0,                                              /* tp_base */
144         0,                                              /* tp_dict */
145         0,                                              /* tp_descr_get */
146         0,                                              /* tp_descr_set */
147         0,                                              /* tp_dictoffset */
148         (initproc)Wiimote_init, /* tp_init */
149         0,                                              /* tp_alloc */
150         Wiimote_new,                    /* tp_new */
151 };
152
153 /* Allocate and deallocate functions */
154 static PyObject *
155         Wiimote_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
156 {
157         Wiimote* self;
158
159         if (!(self = (Wiimote *) type->tp_alloc(type, 0))) {
160                 return NULL;
161         }
162
163         self->wiimote = NULL;
164         Py_INCREF(self->callback = Py_None);
165
166         return (PyObject*) self;
167 }
168
169 static void Wiimote_dealloc(Wiimote *self)
170 {
171         if (self->wiimote) {
172                 cwiid_close(self->wiimote);
173         }
174         Py_XDECREF(self->callback);
175         self->ob_type->tp_free((PyObject *)self);
176 }
177
178 static int cwiid_start(Wiimote *self, int flags)
179 {
180         cwiid_wiimote_t *wiimote;
181         bdaddr_t bdaddr = *BDADDR_ANY;
182
183         /* Set up wiimote */
184         if(!(wiimote = cwiid_open(&bdaddr, flags))) {
185                 PyErr_SetString(PyExc_IOError, "Could not open wiimote");
186                 return -1;
187         }
188
189         /* keep pyobject with wiimote */
190         cwiid_set_data(wiimote,self);
191         /* keep wiimote with pyobject */
192         self->wiimote = wiimote;
193         return 0;
194 }
195
196 static int Wiimote_init(Wiimote* self, PyObject* args, PyObject *kwds)
197 {
198         static char *kwlist[] = {"flags", NULL};
199         int flags = 0;
200
201         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:cwiid.Wiimote.init",
202                                          kwlist, &flags)) {
203                 return -1;
204         }
205
206         if (cwiid_start(self, flags)) {
207                 return -1;
208         }
209
210         return 0;
211 }
212
213 static PyObject *Wiimote_close(Wiimote *self)
214 {
215         if (cwiid_close(self->wiimote)) {
216                 PyErr_SetString(PyExc_IOError, "Wiimote close error");
217                 self->wiimote = NULL;
218                 return NULL;
219         }
220         self->wiimote = NULL;
221
222         Py_RETURN_NONE;
223 }
224
225 static PyObject *Wiimote_enable(Wiimote *self, PyObject *args, PyObject *kwds)
226 {
227         static char *kwlist[] = {"flags", NULL};
228         int flags;
229
230         if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:cwiid.Wiimote.enable",
231                                          kwlist, &flags)) {
232                 return NULL;
233         }
234
235         if (cwiid_enable(self->wiimote, flags)) {
236                 PyErr_SetString(PyExc_IOError, "cwiid_enable error");
237                 return NULL;
238         }
239
240         Py_RETURN_NONE;
241 }
242
243 static PyObject *Wiimote_disable(Wiimote *self, PyObject *args, PyObject *kwds)
244 {
245         static char *kwlist[] = {"flags", NULL};
246         int flags;
247
248         if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:cwiid.Wiimote.disable",
249                                          kwlist, &flags)) {
250                 return NULL;
251         }
252
253         if (cwiid_disable(self->wiimote, flags)) {
254                 PyErr_SetString(PyExc_IOError, "cwiid_disable error");
255                 return NULL;
256         }
257
258         Py_RETURN_NONE;
259 }
260
261 static int
262         Wiimote_set_mesg_callback(Wiimote *self, PyObject *NewCallback,
263                                   void *closure)
264 {
265         PyObject *OldCallback;
266
267         if (!PyCallable_Check(NewCallback)) {
268                 PyErr_SetString(PyExc_TypeError, "callback must be callable!");
269         }
270         OldCallback = self->callback;
271
272         if ((OldCallback == Py_None) && (NewCallback != Py_None)) {
273                 if (cwiid_set_mesg_callback(self->wiimote, callbackBridge)) {
274                         PyErr_SetString(PyExc_IOError, "set callback error");
275                         return -1;
276                 }
277         }
278         else if ((OldCallback != Py_None) && (NewCallback == Py_None)) {
279                 if (cwiid_set_mesg_callback(self->wiimote, NULL)) {
280                         PyErr_SetString(PyExc_IOError, "set callback error");
281                         return -1;
282                 }
283         }
284
285         Py_INCREF(NewCallback);
286         Py_DECREF(OldCallback);
287         self->callback = NewCallback;
288
289         return 0;
290 }
291
292 static PyObject *Wiimote_get_mesg(Wiimote *self)
293 {
294         union cwiid_mesg *mesg;
295         int mesg_count;
296         struct timespec t;
297         PyObject *PyMesg;
298
299         if (cwiid_get_mesg(self->wiimote, &mesg_count, &mesg, &t)) {
300                 if (errno == EAGAIN) {
301                         Py_RETURN_NONE;
302                 }
303                 else {
304                         PyErr_SetString(PyExc_IOError, "get_mesg error");
305                         return NULL;
306                 }
307         }
308
309         PyMesg = processMesgs(mesg_count, mesg);
310
311         free(mesg);
312
313         return PyMesg;
314 }
315
316 static PyObject *Wiimote_get_state(Wiimote* self, void *closure)
317 {
318         struct cwiid_state state;
319         PyObject *PyState;
320
321         if (cwiid_get_state(self->wiimote, &state)) {
322                 PyErr_SetString(PyExc_IOError, "get state error");
323                 return NULL;
324         }
325
326         PyState = Py_BuildValue("{s:B,s:B,s:B,s:B,s:i,s:i}",
327                                 "rpt_mode", state.rpt_mode,
328                                 "led", state.led,
329                                 "rumble", state.rumble,
330                                 "battery", state.battery,
331                                 "ext_type", state.ext_type,
332                                 "error", state.error);
333
334         if (state.rpt_mode & CWIID_RPT_BTN) {
335                 PyObject *PyBtn = Py_BuildValue("I", state.buttons);
336                 if (!PyBtn) {
337                         Py_DECREF(PyState);
338                         return NULL;
339                 }
340                 if (PyDict_SetItemString(PyState, "buttons", PyBtn)) {
341                         Py_DECREF(PyState);
342                         Py_DECREF(PyBtn);
343                         return NULL;
344                 }
345                 Py_DECREF(PyBtn);
346         }
347
348         if (state.rpt_mode & CWIID_RPT_ACC) {
349                 PyObject *PyAcc = Py_BuildValue("(B,B,B)",
350                                                                     state.acc[CWIID_X],
351                                             state.acc[CWIID_Y],
352                                             state.acc[CWIID_Z]);
353                 if (!PyAcc) {
354                         Py_DECREF(PyState);
355                         return NULL;
356                 }
357                 if (PyDict_SetItemString(PyState, "acc", PyAcc)) {
358                         Py_DECREF(PyState);
359                         Py_DECREF(PyAcc);
360                         return NULL;
361                 }
362                 Py_DECREF(PyAcc);
363         }
364
365         if (state.rpt_mode & CWIID_RPT_IR) {
366                 int i;
367                 PyObject *PyIr = PyList_New(CWIID_IR_SRC_COUNT);
368
369                 if (!PyIr) {
370                         Py_DECREF(PyState);
371                         return NULL;
372                 }
373
374                 if (PyDict_SetItemString(PyState, "ir_src", PyIr)) {
375                         Py_DECREF(PyState);
376                         Py_DECREF(PyIr);
377                         return NULL;
378                 }
379
380                 Py_DECREF(PyIr);
381
382                 for (i=0; i < CWIID_IR_SRC_COUNT; i++) {
383                         PyObject *PyIrSrc;
384                         PyObject *PySize;
385
386                         if (state.ir_src[i].valid) {
387                                 PyIrSrc = Py_BuildValue("{s:(I,I)}",
388                                                         "pos",
389                                                           state.ir_src[i].pos[CWIID_X],
390                                                           state.ir_src[i].pos[CWIID_Y]);
391                                 if (!PyIrSrc) {
392                                         Py_DECREF(PyState);
393                                         return NULL;
394                                 }
395
396                                 if (state.ir_src[i].size != -1) {
397                                         if (!(PySize = PyInt_FromLong(
398                                           (long)state.ir_src[i].size))) {
399                                                 Py_DECREF(PyState);
400                                                 Py_DECREF(PyIrSrc);
401                                                 return NULL;
402                                         }
403                                         if (PyDict_SetItemString(PyIrSrc, "size", PySize)) {
404                                                 Py_DECREF(PyState);
405                                                 Py_DECREF(PyIrSrc);
406                                                 Py_DECREF(PySize);
407                                                 return NULL;
408                                         }
409
410                                         Py_DECREF(PySize);
411                                 }
412                         }
413                         else {
414                                 Py_INCREF(PyIrSrc = Py_None);
415                         }
416
417                         PyList_SET_ITEM(PyIr, i, PyIrSrc);
418                 }
419         }
420
421         switch (state.ext_type) {
422                 PyObject *PyExt;
423         case CWIID_EXT_NUNCHUK:
424                 if (state.rpt_mode & CWIID_RPT_NUNCHUK) {
425                         PyExt = Py_BuildValue("{s:(B,B),s:(B,B,B),s:I}",
426                                               "stick",
427                                                 state.ext.nunchuk.stick[CWIID_X],
428                                                 state.ext.nunchuk.stick[CWIID_Y],
429                                               "acc",
430                                                 state.ext.nunchuk.acc[CWIID_X],
431                                                 state.ext.nunchuk.acc[CWIID_Y],
432                                                 state.ext.nunchuk.acc[CWIID_Z],
433                                               "buttons", state.ext.nunchuk.buttons);
434
435                         if (!PyExt) {
436                                 Py_DECREF(PyState);
437                                 return NULL;
438                         }
439
440                         if (PyDict_SetItemString(PyState, "nunchuk", PyExt)) {
441                                 Py_DECREF(PyState);
442                                 Py_DECREF(PyExt);
443                                 return NULL;
444                         }
445
446                         Py_DECREF(PyExt);
447                 }
448                 break;
449         case CWIID_EXT_CLASSIC:
450                 if (state.rpt_mode & CWIID_RPT_CLASSIC) {
451                         PyExt = Py_BuildValue("{s:(B,B),s:(B,B),s:B,s:B,s:I}",
452                                               "l_stick",
453                                                 state.ext.classic.l_stick[CWIID_X],
454                                                 state.ext.classic.l_stick[CWIID_Y],
455                                               "r_stick",
456                                                 state.ext.classic.r_stick[CWIID_X],
457                                                 state.ext.classic.r_stick[CWIID_Y],
458                                               "l", state.ext.classic.l,
459                                               "r", state.ext.classic.r,
460                                               "buttons", state.ext.classic.buttons);
461
462                         if (!PyExt) {
463                                 Py_DECREF(PyState);
464                                 return NULL;
465                         }
466
467                         if (PyDict_SetItemString(PyState, "classic", PyExt)) {
468                                 Py_DECREF(PyState);
469                                 Py_DECREF(PyExt);
470                                 return NULL;
471                         }
472
473                         Py_DECREF(PyExt);
474                 }
475                 break;
476         default:
477                 break;
478         }
479
480         return PyState;
481 }
482
483 static PyObject *Wiimote_request_status(Wiimote *self)
484 {
485         if (cwiid_request_status(self->wiimote)) {
486                 PyErr_SetString(PyExc_IOError, "Wiimote request status error");
487                 return NULL;
488         }
489
490         Py_RETURN_NONE;
491 }
492
493 static int Wiimote_set_led(Wiimote *self, PyObject *PyLed, void *closure)
494 {
495         long led;
496
497         if (((led = PyInt_AsLong(PyLed)) == -1) && PyErr_Occurred()) {
498                 return -1;
499         }
500
501         if (cwiid_set_led(self->wiimote, (uint8_t)led)) {
502                 PyErr_SetString(PyExc_IOError, "Wiimote set led error");
503                 return -1;
504         }
505
506         return 0;
507 }
508
509 static int
510         Wiimote_set_rumble(Wiimote *self, PyObject *PyRumble, void *closure)
511 {
512         long rumble;
513
514         if (((rumble = PyInt_AsLong(PyRumble)) == -1) && PyErr_Occurred()) {
515                 return -1;
516         }
517
518         if (cwiid_set_rumble(self->wiimote, (uint8_t)rumble)) {
519                 PyErr_SetString(PyExc_IOError, "Wiimote set rumble error");
520                 return -1;
521         }
522
523         return 0;
524 }
525
526 static int
527         Wiimote_set_rpt_mode(Wiimote *self, PyObject *PyRptMode, void *closure)
528 {
529         long rpt_mode;
530
531         if (((rpt_mode = PyInt_AsLong(PyRptMode)) == -1) && PyErr_Occurred()) {
532                 return -1;
533         }
534
535         if (cwiid_set_rpt_mode(self->wiimote, (uint8_t)rpt_mode)) {
536                 PyErr_SetString(PyExc_IOError, "Wiimote set rpt_mode error");
537                 return -1;
538         }
539
540         return 0;
541 }
542
543 /* static PyObject *Wiimote_command(Wiimote *self, PyObject *args, PyObject *kwds)
544 {
545         static char *kwlist[] = { "command", "flags", NULL };
546         int command, flags;
547
548         if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &command,
549                                          &flags)) {
550                 return NULL;
551         }
552
553         cwiid_command(self->wiimote, (enum cwiid_command)command, (uint8_t)flags);
554
555         Py_RETURN_NONE;
556 }
557 */
558
559 static PyObject *Wiimote_read(Wiimote *self, PyObject *args, PyObject *kwds)
560 {
561         static char *kwlist[] = { "flags", "offset", "len", NULL };
562         unsigned char flags;
563         unsigned int offset;
564         unsigned int len;
565         void *buf;
566         PyObject *pyRetBuf;
567
568         if (!PyArg_ParseTupleAndKeywords(args, kwds, "BII:cwiid.Wiimote.read",
569                                          kwlist, &flags, &offset, &len)) {
570                 return NULL;
571         }
572
573         if (!(pyRetBuf = PyBuffer_New(len))) {
574                 return NULL;
575         }
576         if (PyObject_AsWriteBuffer(pyRetBuf, &buf, (int *)&len)) {
577                 Py_DECREF(pyRetBuf);
578                 return NULL;
579         }
580         if (cwiid_read(self->wiimote,flags,offset,len,buf)) {
581                 PyErr_SetString(PyExc_IOError, "Wiimote read error");
582                 Py_DECREF(pyRetBuf);
583                 return NULL;
584         }
585
586         return pyRetBuf;
587 }
588
589 static PyObject *Wiimote_write(Wiimote *self, PyObject *args, PyObject *kwds)
590 {
591         static char *kwlist[] = { "flags", "offset", "buffer", NULL };
592         unsigned char flags;
593         unsigned int offset;
594         void *buf;
595         int len;
596
597         if (!PyArg_ParseTupleAndKeywords(args, kwds, "BIt#:cwiid.Wiimote.write",
598                                          kwlist, &flags, &offset, &buf, &len)) {
599                 return NULL;
600         }
601
602         if (cwiid_write(self->wiimote, flags, offset, len, buf)) {
603                 PyErr_SetString(PyExc_IOError, "Wiimote write error");
604                 return NULL;
605         }
606
607         Py_RETURN_NONE;
608 }
609
610 static void
611         callbackBridge(cwiid_wiimote_t *wiimote, int mesg_count,
612                        union cwiid_mesg mesg[], struct timespec *t)
613 {
614         PyObject *ArgTuple;
615         PyObject *PySelf;
616         PyGILState_STATE gstate;
617
618         gstate = PyGILState_Ensure();
619
620         ArgTuple = processMesgs(mesg_count, mesg);
621
622         /* Put id and the list of messages as the arguments to the callback */
623         PySelf = (PyObject *) cwiid_get_data(wiimote);
624         PyObject_CallFunction(((Wiimote *)PySelf)->callback, "(O)", ArgTuple);
625
626         Py_XDECREF(ArgTuple);
627         PyGILState_Release(gstate);
628 }
629
630 /* This is the function responsible for marshaling the cwiid messages from
631  * C to python. It's rather complicated since it uses a complex C union
632  * to store the data and multiple enumerations to figure out what data is
633  * actually being sent. Neither of these common C types really translate
634  * well into Python. I've done my best to translate it to python as follows:
635  *
636  * Python callback takes arg (mesgs). The mesgs is a list of
637  * mesg tuples which contain the mesg type and a dict of the arguments.
638  *
639  * Ex:
640  * mesgs =>[(CWIID_STATUS_MESG,{"battery":battery,"ext_type":ext_type}),
641  *          (CWIID_BTN_MESG,buttons),
642  *          (CWIID_ACC_MESG,(x,y,z)),
643  *          (CWIID_IR_MESG,[{"pos":(x,y),"size":size}, ...]),
644  *          (CWIID_NUNCHUK_MESG,{"stick":(x,y),"acc":(x,y,z),
645  *                               "buttons":buttons},
646  *          (CWIID_CLASSIC_MESG,{"l_stick":(x,y),"r_stick":(x,y),"l":l,"r":r,
647  *                               "buttons":buttons},
648  *          (CWIID_ERROR_MESG,error)]
649  */
650 static PyObject *processMesgs(int mesg_count, union cwiid_mesg mesg[])
651 {
652         PyObject *mesglist; /* List of message tuples */
653         PyObject *amesg; /* A single message (type, [arguments]) */
654         PyObject *mesgVal; /* Dictionary of arguments for a message */
655         PyObject *PyIrList;
656         int i, j;
657
658         if (!(mesglist = PyList_New(mesg_count))) {
659                 return NULL;
660         }
661
662         for (i = 0; i < mesg_count; i++) {
663                 switch (mesg[i].type) {
664                 case CWIID_MESG_STATUS:
665                         mesgVal = Py_BuildValue("{s:B,s:i}",
666                                                 "battery", mesg[i].status_mesg.battery,
667                                                 "ext_type", mesg[i].status_mesg.ext_type);
668                         break;
669                 case CWIID_MESG_BTN:
670                         mesgVal = Py_BuildValue("I", mesg[i].btn_mesg.buttons);
671                         break;
672                 case CWIID_MESG_ACC:
673                         mesgVal = Py_BuildValue("(B,B,B)", mesg[i].acc_mesg.acc[CWIID_X],
674                                                            mesg[i].acc_mesg.acc[CWIID_Y],
675                                                            mesg[i].acc_mesg.acc[CWIID_Z]);
676                         break;
677                 case CWIID_MESG_IR:
678                         mesgVal = NULL;
679
680                         if (!(PyIrList = PyList_New(CWIID_IR_SRC_COUNT))) {
681                                 break;
682                         }
683
684                         for (j=0; j < CWIID_IR_SRC_COUNT; j++) {
685                                 PyObject *PyIrSrc;
686                                 PyObject *PySize;
687
688                                 if (mesg[i].ir_mesg.src[j].valid) {
689                                         PyIrSrc = Py_BuildValue("{s:(I,I)}",
690                                                      "pos",
691                                                        mesg[i].ir_mesg.src[j].pos[CWIID_X],
692                                                        mesg[i].ir_mesg.src[j].pos[CWIID_Y]);
693
694                                         if (!PyIrSrc) {
695                                                 Py_DECREF(PyIrList);
696                                                 PyIrList = NULL;
697                                                 break;
698                                         }
699
700                                         if (mesg[i].ir_mesg.src[j].size != -1) {
701                                                 if (!(PySize = PyInt_FromLong(
702                                                   (long)mesg[i].ir_mesg.src[j].size))) {
703                                                         Py_DECREF(PyIrList);
704                                                         Py_DECREF(PyIrSrc);
705                                                         PyIrList = NULL;
706                                                         break;
707                                                 }
708                                                 if (PyDict_SetItemString(PyIrSrc, "size", PySize)) {
709                                                         Py_DECREF(PyIrList);
710                                                         Py_DECREF(PyIrSrc);
711                                                         Py_DECREF(PySize);
712                                                         PyIrList = NULL;
713                                                         break;
714                                                 }
715
716                                                 Py_DECREF(PySize);
717                                         }
718                                 }
719                                 else {
720                                         Py_INCREF(PyIrSrc = Py_None);
721                                 }
722                                 PyList_SET_ITEM(PyIrList, j, PyIrSrc);
723                         }
724
725                         if (!PyIrList) {
726                                 break;
727                         }
728
729                         mesgVal = PyIrList;
730                         break;
731                 case CWIID_MESG_NUNCHUK:
732                         mesgVal = Py_BuildValue("{s:(B,B),s:(B,B,B),s:I}",
733                                                 "stick",
734                                                   mesg[i].nunchuk_mesg.stick[CWIID_X],
735                                                   mesg[i].nunchuk_mesg.stick[CWIID_Y],
736                                                 "acc",
737                                                   mesg[i].nunchuk_mesg.acc[CWIID_X],
738                                                   mesg[i].nunchuk_mesg.acc[CWIID_Y],
739                                                   mesg[i].nunchuk_mesg.acc[CWIID_Z],
740                                                 "buttons", mesg[i].nunchuk_mesg.buttons);
741                         break;
742                 case CWIID_MESG_CLASSIC:
743                         mesgVal = Py_BuildValue("{s:(B,B),s:(B,B),s:B,s:B,s:I}",
744                                      "l_stick",
745                                        mesg[i].classic_mesg.l_stick[CWIID_X],
746                                        mesg[i].classic_mesg.l_stick[CWIID_Y],
747                                      "r_stick",
748                                        mesg[i].classic_mesg.r_stick[CWIID_X],
749                                        mesg[i].classic_mesg.r_stick[CWIID_Y],
750                                      "l", mesg[i].classic_mesg.l,
751                                      "r", mesg[i].classic_mesg.r,
752                                      "buttons", mesg[i].classic_mesg.buttons);
753                         break;
754                 case CWIID_MESG_ERROR:
755                         mesgVal = Py_BuildValue("i", mesg[i].error_mesg.error);
756                         break;
757                 default:
758                         Py_INCREF(mesgVal = Py_None);
759                         break;
760                 }
761
762                 if (!mesgVal) {
763                         return NULL;
764                 }
765
766                 /* Finally Put the type next to the message in a tuple and
767                  * append them to the list of messages */
768                 if (!(amesg = Py_BuildValue("(iO)", mesg[i].type, mesgVal))) {
769                         Py_DECREF(mesgVal);
770                         return NULL;
771                 }
772                 Py_DECREF(mesgVal);
773                 PyList_SET_ITEM(mesglist, i, amesg);
774         }
775
776         return mesglist;
777 }
Note: See TracBrowser for help on using the browser.