updated method definitions - all functions now accept tuples/keywords
[PyX52.git] / PyX52.c
blobeb4cb14843b3be2ef0fc1119c608580c3e84ca2a
1 #include <Python.h>
2 #include "structmember.h"
3 #include "datetime.h"
5 #include <time.h>
7 #include <x52pro.h>
9 typedef struct
11 PyObject_HEAD
12 struct x52 *handle;
13 } PyX52_X52_object;
15 static PyTypeObject PyX52_X52_type;
16 static PyMethodDef PyX52_methods[];
17 static PyMethodDef PyX52_X52_methods[];
19 static PyObject *PyX52_X52_new(PyTypeObject *);
20 static int PyX52_X52_init(PyX52_X52_object *);
21 static void PyX52_X52_dealloc(PyX52_X52_object *);
23 static PyObject *PyX52_X52_gettype(PyX52_X52_object *);
24 static PyObject *PyX52_X52_settext(PyX52_X52_object *, PyObject *, PyObject *);
25 static PyObject *PyX52_X52_setbri(PyX52_X52_object *, PyObject *, PyObject *);
26 static PyObject *PyX52_X52_setled(PyX52_X52_object *, PyObject *, PyObject *);
27 static PyObject *PyX52_X52_settime(PyX52_X52_object *, PyObject *, PyObject *);
28 static PyObject *PyX52_X52_setoffs(PyX52_X52_object *, PyObject *, PyObject *);
29 static PyObject *PyX52_X52_setsecond(PyX52_X52_object *, PyObject *, PyObject *);
30 static PyObject *PyX52_X52_setdate(PyX52_X52_object *, PyObject *, PyObject *);
34 static PyObject *
35 PyX52_X52_new(PyTypeObject *type)
38 PyX52_X52_object *self;
39 self = (PyX52_X52_object *)type->tp_alloc(type, 0);
40 if (self != NULL)
42 self->handle = NULL;
44 return (PyObject *)self;
47 static int
48 PyX52_X52_init(PyX52_X52_object *self)
51 self->handle = x52_init();
52 if (self->handle == NULL)
54 PyErr_SetString(PyExc_RuntimeError, "No compatible joysticks found.");
55 return -1;
57 x52_debug(self->handle, 0);
58 return 0;
61 static void
62 PyX52_X52_dealloc(PyX52_X52_object *self)
65 if (self->handle != NULL)
67 x52_close(self->handle);
69 self->handle = NULL;
70 self->ob_type->tp_free((PyObject *)self);
73 static PyObject *
74 PyX52_X52_gettype(PyX52_X52_object *self)
76 enum x52_type type = x52_gettype(self->handle);
77 return Py_BuildValue("i", type);
80 static PyObject *
81 PyX52_X52_settext(PyX52_X52_object *self, PyObject *args, PyObject *kws)
83 if (x52_gettype(self->handle) == DEV_YOKE)
85 PyErr_SetString(PyExc_RuntimeError, "Cannot call settext on this device.");
86 return NULL;
89 static char *kwlist = {NULL}'
90 if (!PyArg_ParseTupleAndKeywords(args, kws, "", kwlist))
91 return NULL;
93 Py_INCREF(Py_None);
94 return Py_None;
97 static PyObject *
98 PyX52_X52_setbri(PyX52_X52_object *self, PyObject *args, PyObject *kws)
100 if (x52_gettype(self->handle) == DEV_YOKE)
102 PyErr_SetString(PyExc_RuntimeError, "Cannot call setbri on this device.");
103 return NULL;
106 int mode = 0;
107 int bri = 0;
109 static char *kwlist[] = {"mode", "bri", NULL};
110 if (!PyArg_ParseTupleAndKeywords(args, kws, "ii", kwlist, &mode, &bri))
111 return NULL;
113 if (mode != 0 && mode != 1)
115 PyErr_SetString(PyExc_AttributeError, "Invalid mode.");
116 return NULL;
119 if (mode == 0 && x52_gettype(self->handle) != DEV_X52PRO)
121 PyErr_SetString(PyExc_AttributeError, "Cannot set LED brightness on this device.");
122 return NULL;
125 if (bri < 0 || bri > 127)
127 PyErr_SetString(PyExc_AttributeError, "Invalid brightness value.");
128 return NULL;
131 if (x52_setbri(self->handle, mode, bri) != 0)
133 PyErr_SetString(PyExc_RuntimeError, "Could not set brightness.");
134 return NULL;
137 Py_INCREF(Py_None);
138 return Py_None;
141 static PyObject *
142 PyX52_X52_setled(PyX52_X52_object *self, PyObject *args, PyObject *kws)
144 if (x52_gettype(self->handle) != DEV_X52PRO)
146 PyErr_SetString(PyExc_RuntimeError, "Cannot call setled on this device.");
147 return NULL;
151 * TODO: Allow passing of a dict with LEDs/states
152 * TODO: Allow abstraction to button colour (i.e. PyX52.X52.buttons["coolie"].orange())
154 int led = 0;
155 int state = 0;
157 static char *kwlist[] = {"led", "state", NULL};
158 if (!PyArg_ParseTupleAndKeywords(args, kws, "ii", kwlist, &led, &state))
159 return NULL;
161 if (state != 0 && state != 1)
163 PyErr_SetString(PyExc_AttributeError, "Invalid LED state.");
164 return NULL;
167 if (led < X52PRO_LED_FIRE || led > X52PRO_LED_IGREEN)
169 PyErr_SetString(PyExc_AttributeError, "Invalid LED ID.");
170 return NULL;
173 if (!x52_setled(self->handle, led, state))
175 PyErr_SetString(PyExc_RuntimeError, "Could not set LED status.");
176 return NULL;
179 Py_INCREF(Py_None);
180 return Py_None;
183 static PyObject *
184 PyX52_X52_settime(PyX52_X52_object *self, PyObject *args, PyObject *kws)
186 int h24 = 1;
188 struct tm *ltime = NULL;
189 time_t t = time(NULL);
190 ltime = gmtime(&t);
192 int hour = ltime->tm_hour;
193 int minute = ltime->tm_min;
195 static char *kwlist[] = {"hour", "minute", "h24", NULL};
196 if (!PyArg_ParseTupleAndKeywords(args, kws, "|iii", kwlist, &hour, &minute, &h24))
197 return NULL;
199 if (x52_settime(self->handle, h24, hour, minute) != 0)
201 PyErr_SetString(PyExc_RuntimeError, "Could not set time.");
202 return NULL;
205 Py_INCREF(Py_None);
206 return Py_None;
209 static PyObject *
210 PyX52_X52_setoffs(PyX52_X52_object *self, PyObject *args, PyObject *kws)
213 * TODO: default to local timezones
215 if (x52_gettype(self->handle) == DEV_YOKE)
217 PyErr_SetString(PyExc_RuntimeError, "Cannot call setoffs on this device.");
218 return NULL;
221 int offs2 = 0;
222 int offs3 = 0;
224 static char *kwlist[] = {"offs2", "offs3", NULL};
225 if (!PyArg_ParseTupleAndKeywords(args, kws, "|ii", kwlist, &offs2, &offs3))
226 return NULL;
228 Py_INCREF(Py_None);
229 return Py_None;
232 static PyObject *
233 PyX52_X52_setsecond(PyX52_X52_object *self, PyObject *args, PyObject *kws)
235 if (x52_gettype(self->handle) != DEV_YOKE)
237 PyErr_SetString(PyExc_RuntimeError, "Cannot call setsecond on this device.");
238 return NULL;
241 struct tm *ltime;
242 time_t t = time(NULL);
243 gmtime_r(&t, ltime);
245 int second = ltime->tm_sec;
247 static char *kwlist[] = {"second", NULL};
248 if (!PyArg_ParseTupleAndKeywords(args, kws, "|iii", kwlist, &second))
249 return NULL;
251 x52_setsecond(self->handle, second);
253 Py_INCREF(Py_None);
254 return Py_None;
257 static PyObject *
258 PyX52_X52_setdate(PyX52_X52_object *self, PyObject *args, PyObject *kws)
260 if (x52_gettype(self->handle) == DEV_YOKE)
262 PyErr_SetString(PyExc_RuntimeError, "Cannot call setdate on this device.");
263 return NULL;
266 struct tm *ltime;
267 time_t *t;
268 time(t);
269 ltime = gmtime(t);
271 int year = ltime->tm_year - 100;
272 int month = ltime->tm_mon + 1;
273 int day = ltime->tm_mday;
275 static char *kwlist[] = {"year", "month", "day", NULL};
276 if (!PyArg_ParseTupleAndKeywords(args, kws, "|iii", kwlist, &year, &month, &day))
277 return NULL;
279 if (x52_setdate(self->handle, year, month, day) != 0)
281 PyErr_SetString(PyExc_RuntimeError, "Could not set date.");
282 return NULL;
285 Py_INCREF(Py_None);
286 return Py_None;
289 static PyMethodDef PyX52_X52_methods[] = {
290 {"gettype", (PyCFunction)PyX52_X52_gettype, METH_NOARGS, "Get the type of X52 device."},
291 {"settext", (PyCFunction)PyX52_X52_settext, METH_VARARGS | METH_KEYWORDS, "Set the text on the MFD. (X52 and X52 Pro only.)"},
292 {"setbri", (PyCFunction)PyX52_X52_setbri, METH_VARARGS | METH_KEYWORDS, "Set the brightness of either the LEDs or the MFD. (X52 and X52 Pro only.)"},
293 {"setled", (PyCFunction)PyX52_X52_setled, METH_VARARGS | METH_KEYWORDS, "Set an LED's state. (X52 Pro only.)"},
294 {"settime", (PyCFunction)PyX52_X52_settime, METH_VARARGS | METH_KEYWORDS, "Set the MFD display time. If arguments are not supplied, sets the current time in 24 hour format. (X52, X52 Pro and Yoke.)"},
295 {"setoffs", (PyCFunction)PyX52_X52_setoffs, METH_VARARGS | METH_KEYWORDS, "Set the time offset. (X52, X52 Pro.)"},
296 {"setsecond", (PyCFunction)PyX52_X52_setsecond, METH_VARARGS | METH_KEYWORDS, "Set the second. If no arguments are supplied, current second is used. (Yoke only.)"},
297 {"setdate", (PyCFunction)PyX52_X52_setdate, METH_VARARGS | METH_KEYWORDS, "Set the date. If no arguments are supplied, current date is used. (X52, X52 Pro.)"},
298 {NULL, NULL, 0, NULL}
301 static PyTypeObject PyX52_X52_type = {
302 PyObject_HEAD_INIT(NULL)
303 0, /*ob_size*/
304 "PyX52.X52", /*tp_name*/
305 sizeof(PyX52_X52_object), /*tp_basicsize*/
306 0, /*tp_itemsize*/
307 (destructor)PyX52_X52_dealloc, /*tp_dealloc*/
308 0, /*tp_print*/
309 0, /*tp_getattr*/
310 0, /*tp_setattr*/
311 0, /*tp_compare*/
312 0, /*tp_repr*/
313 0, /*tp_as_number*/
314 0, /*tp_as_sequence*/
315 0, /*tp_as_mapping*/
316 0, /*tp_hash */
317 0, /*tp_call*/
318 0, /*tp_str*/
319 0, /*tp_getattro*/
320 0, /*tp_setattro*/
321 0, /*tp_as_buffer*/
322 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
323 "X52 joystick object", /* tp_doc */
324 0, /*tp_traverse*/
325 0, /* tp_clear */
326 0, /* tp_richcompare */
327 0, /* tp_weaklistoffset */
328 0, /* tp_iter */
329 0, /* tp_iternext */
330 PyX52_X52_methods, /* tp_methods */
331 0, /* tp_members */
332 0, /* tp_getset */
333 0, /* tp_base */
334 0, /* tp_dict */
335 0, /* tp_descr_get */
336 0, /* tp_descr_set */
337 0, /* tp_dictoffset */
338 (initproc)PyX52_X52_init, /* tp_init */
339 0, /* tp_alloc */
340 (newfunc)PyX52_X52_new, /* tp_new */
343 static PyMethodDef PyX52_methods[] = {
344 {NULL}
347 #ifndef PyMODINIT_FUNC
348 #define PyMODINIT_FUNC void
349 #endif
350 PyMODINIT_FUNC
351 initPyX52(void)
353 PyObject *m;
355 if (PyType_Ready(&PyX52_X52_type) < 0)
356 return;
358 m = Py_InitModule3("PyX52", PyX52_methods, "Provides functions for handling Saitek X52, X52 Pro and Yoke joystick devices.");
359 if (m == NULL)
360 return;
362 Py_INCREF(&PyX52_X52_type);
363 PyModule_AddObject(m, "X52", (PyObject *) &PyX52_X52_type);
366 * Fire
371 * T1
372 * T2
373 * T3
374 * CO
378 PyModule_AddIntConstant(m, "LED_FIRE", X52PRO_LED_FIRE);
379 PyModule_AddIntConstant(m, "LED_ARED", X52PRO_LED_ARED);
380 PyModule_AddIntConstant(m, "LED_AGREEN", X52PRO_LED_AGREEN);
381 PyModule_AddIntConstant(m, "LED_BRED", X52PRO_LED_BRED);
382 PyModule_AddIntConstant(m, "LED_BGREEN", X52PRO_LED_BGREEN);
383 PyModule_AddIntConstant(m, "LED_DRED", X52PRO_LED_DRED);
384 PyModule_AddIntConstant(m, "LED_DGREEN", X52PRO_LED_DGREEN);
385 PyModule_AddIntConstant(m, "LED_ERED", X52PRO_LED_ERED);
386 PyModule_AddIntConstant(m, "LED_EGREEN", X52PRO_LED_EGREEN);
387 PyModule_AddIntConstant(m, "LED_T1RED", X52PRO_LED_T1RED);
388 PyModule_AddIntConstant(m, "LED_T1GREEN", X52PRO_LED_T1GREEN);
389 PyModule_AddIntConstant(m, "LED_T2RED", X52PRO_LED_T2RED);
390 PyModule_AddIntConstant(m, "LED_T2GREEN", X52PRO_LED_T2GREEN);
391 PyModule_AddIntConstant(m, "LED_T3RED", X52PRO_LED_T3RED);
392 PyModule_AddIntConstant(m, "LED_T3GREEN", X52PRO_LED_T3GREEN);
393 PyModule_AddIntConstant(m, "LED_CORED", X52PRO_LED_CORED);
394 PyModule_AddIntConstant(m, "LED_COGREEN", X52PRO_LED_COGREEN);
395 PyModule_AddIntConstant(m, "LED_IRED", X52PRO_LED_IRED);
396 PyModule_AddIntConstant(m, "LED_IGREEN", X52PRO_LED_IGREEN);
398 PyModule_AddIntConstant(m, "TYPE_X52", DEV_X52);
399 PyModule_AddIntConstant(m, "TYPE_X52PRO", DEV_X52PRO);
400 PyModule_AddIntConstant(m, "TYPE_YOKE", DEV_YOKE);