Added X52 button mapping file to tracking
[PyX52.git] / PyX52.c
bloba6f7526f2645ca7f4fe3c5922e613d659e7190d2
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 int ok = PyArg_ParseTuple(args, "");
91 Py_INCREF(Py_None);
92 return Py_None;
95 static PyObject *
96 PyX52_X52_setbri(PyX52_X52_object *self, PyObject *args, PyObject *kws)
98 if (x52_gettype(self->handle) == DEV_YOKE)
100 PyErr_SetString(PyExc_RuntimeError, "Cannot call setbri on this device.");
101 return NULL;
104 int mode = 0;
105 int bri = 0;
107 static char *kwlist[] = {"mode", "bri", NULL};
108 if (!PyArg_ParseTupleAndKeywords(args, kws, "ii", kwlist, &mode, &bri))
109 return NULL;
111 if (mode != 0 && mode != 1)
113 PyErr_SetString(PyExc_AttributeError, "Invalid mode.");
114 return NULL;
117 if (mode == 0 && x52_gettype(self->handle) != DEV_X52PRO)
119 PyErr_SetString(PyExc_AttributeError, "Cannot set LED brightness on this device.");
120 return NULL;
123 if (bri < 0 || bri > 127)
125 PyErr_SetString(PyExc_AttributeError, "Invalid brightness value.");
126 return NULL;
129 if (x52_setbri(self->handle, mode, bri) != 0)
131 PyErr_SetString(PyExc_RuntimeError, "Could not set brightness.");
132 return NULL;
135 Py_INCREF(Py_None);
136 return Py_None;
139 static PyObject *
140 PyX52_X52_setled(PyX52_X52_object *self, PyObject *args, PyObject *kws)
142 if (x52_gettype(self->handle) != DEV_X52PRO)
144 PyErr_SetString(PyExc_RuntimeError, "Cannot call setled on this device.");
145 return NULL;
149 * TODO: Allow passing of a dict with LEDs/states
150 * TODO: Allow abstraction to button colour (i.e. PyX52.X52.buttons["coolie"].orange())
152 int led = 0;
153 int state = 0;
155 static char *kwlist[] = {"led", "state", NULL};
156 if (!PyArg_ParseTupleAndKeywords(args, kws, "ii", kwlist, &led, &state))
157 return NULL;
159 if (state != 0 && state != 1)
161 PyErr_SetString(PyExc_AttributeError, "Invalid LED state.");
162 return NULL;
165 if (led < X52PRO_LED_FIRE || led > X52PRO_LED_IGREEN)
167 PyErr_SetString(PyExc_AttributeError, "Invalid LED ID.");
168 return NULL;
171 if (!x52_setled(self->handle, led, state))
173 PyErr_SetString(PyExc_RuntimeError, "Could not set LED status.");
174 return NULL;
177 Py_INCREF(Py_None);
178 return Py_None;
181 static PyObject *
182 PyX52_X52_settime(PyX52_X52_object *self, PyObject *args, PyObject *kws)
184 int h24 = 1;
186 struct tm *ltime = NULL;
187 time_t t = time(NULL);
188 ltime = gmtime(&t);
190 int hour = ltime->tm_hour;
191 int minute = ltime->tm_min;
194 static char *kwlist[] = {"hour", "minute", "h24", NULL};
195 if (!PyArg_ParseTupleAndKeywords(args, kws, "|iii", kwlist, &hour, &minute, &h24))
196 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)
261 if (x52_gettype(self->handle) == DEV_YOKE)
263 PyErr_SetString(PyExc_RuntimeError, "Cannot call setdate on this device.");
264 return NULL;
267 struct tm *ltime;
268 time_t *t;
269 time(t);
270 ltime = gmtime(t);
272 int year = ltime->tm_year - 100;
273 int month = ltime->tm_mon + 1;
274 int day = ltime->tm_mday;
276 static char *kwlist[] = {"year", "month", "day", NULL};
277 if (!PyArg_ParseTupleAndKeywords(args, kws, "|iii", kwlist, &year, &month, &day))
278 return NULL;
280 if (x52_setdate(self->handle, year, month, day) != 0)
282 PyErr_SetString(PyExc_RuntimeError, "Could not set date.");
283 return NULL;
286 Py_INCREF(Py_None);
287 return Py_None;
290 static PyMethodDef PyX52_X52_methods[] = {
291 {"gettype", (PyCFunction)PyX52_X52_gettype, METH_NOARGS, "Get the type of X52 device."},
292 {"settext", (PyCFunction)PyX52_X52_settext, METH_VARARGS, "Set the text on the MFD. (X52 and X52 Pro only.)"},
293 {"setbri", (PyCFunction)PyX52_X52_setbri, METH_VARARGS | METH_KEYWORDS, "Set the brightness of either the LEDs or the MFD. (X52 and X52 Pro only.)"},
294 {"setled", (PyCFunction)PyX52_X52_setled, METH_VARARGS, "Set an LED's state. (X52 Pro only.)"},
295 {"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.)"},
296 {"setoffs", (PyCFunction)PyX52_X52_setoffs, METH_VARARGS, "Set the time offset. (X52, X52 Pro.)"},
297 {"setsecond", (PyCFunction)PyX52_X52_setsecond, METH_VARARGS | METH_KEYWORDS, "Set the second. If no arguments are supplied, current second is used. (Yoke only.)"},
298 {"setdate", (PyCFunction)PyX52_X52_setdate, METH_VARARGS | METH_KEYWORDS, "Set the date. If no arguments are supplied, current date is used. (X52, X52 Pro.)"},
299 {NULL, NULL, 0, NULL}
302 static PyTypeObject PyX52_X52_type = {
303 PyObject_HEAD_INIT(NULL)
304 0, /*ob_size*/
305 "PyX52.X52", /*tp_name*/
306 sizeof(PyX52_X52_object), /*tp_basicsize*/
307 0, /*tp_itemsize*/
308 (destructor)PyX52_X52_dealloc, /*tp_dealloc*/
309 0, /*tp_print*/
310 0, /*tp_getattr*/
311 0, /*tp_setattr*/
312 0, /*tp_compare*/
313 0, /*tp_repr*/
314 0, /*tp_as_number*/
315 0, /*tp_as_sequence*/
316 0, /*tp_as_mapping*/
317 0, /*tp_hash */
318 0, /*tp_call*/
319 0, /*tp_str*/
320 0, /*tp_getattro*/
321 0, /*tp_setattro*/
322 0, /*tp_as_buffer*/
323 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
324 "X52 joystick object", /* tp_doc */
325 0, /*tp_traverse*/
326 0, /* tp_clear */
327 0, /* tp_richcompare */
328 0, /* tp_weaklistoffset */
329 0, /* tp_iter */
330 0, /* tp_iternext */
331 PyX52_X52_methods, /* tp_methods */
332 0, /* tp_members */
333 0, /* tp_getset */
334 0, /* tp_base */
335 0, /* tp_dict */
336 0, /* tp_descr_get */
337 0, /* tp_descr_set */
338 0, /* tp_dictoffset */
339 (initproc)PyX52_X52_init, /* tp_init */
340 0, /* tp_alloc */
341 (newfunc)PyX52_X52_new, /* tp_new */
344 static PyMethodDef PyX52_methods[] = {
345 {NULL}
348 #ifndef PyMODINIT_FUNC
349 #define PyMODINIT_FUNC void
350 #endif
351 PyMODINIT_FUNC
352 initPyX52(void)
354 PyObject *m;
356 if (PyType_Ready(&PyX52_X52_type) < 0)
357 return;
359 m = Py_InitModule3("PyX52", PyX52_methods, "Provides functions for handling Saitek X52, X52 Pro and Yoke joystick devices.");
360 if (m == NULL)
361 return;
363 Py_INCREF(&PyX52_X52_type);
364 PyModule_AddObject(m, "X52", (PyObject *) &PyX52_X52_type);
367 * Fire
372 * T1
373 * T2
374 * T3
375 * CO
379 PyModule_AddIntConstant(m, "LED_FIRE", X52PRO_LED_FIRE);
380 PyModule_AddIntConstant(m, "LED_ARED", X52PRO_LED_ARED);
381 PyModule_AddIntConstant(m, "LED_AGREEN", X52PRO_LED_AGREEN);
382 PyModule_AddIntConstant(m, "LED_BRED", X52PRO_LED_BRED);
383 PyModule_AddIntConstant(m, "LED_BGREEN", X52PRO_LED_BGREEN);
384 PyModule_AddIntConstant(m, "LED_DRED", X52PRO_LED_DRED);
385 PyModule_AddIntConstant(m, "LED_DGREEN", X52PRO_LED_DGREEN);
386 PyModule_AddIntConstant(m, "LED_ERED", X52PRO_LED_ERED);
387 PyModule_AddIntConstant(m, "LED_EGREEN", X52PRO_LED_EGREEN);
388 PyModule_AddIntConstant(m, "LED_T1RED", X52PRO_LED_T1RED);
389 PyModule_AddIntConstant(m, "LED_T1GREEN", X52PRO_LED_T1GREEN);
390 PyModule_AddIntConstant(m, "LED_T2RED", X52PRO_LED_T2RED);
391 PyModule_AddIntConstant(m, "LED_T2GREEN", X52PRO_LED_T2GREEN);
392 PyModule_AddIntConstant(m, "LED_T3RED", X52PRO_LED_T3RED);
393 PyModule_AddIntConstant(m, "LED_T3GREEN", X52PRO_LED_T3GREEN);
394 PyModule_AddIntConstant(m, "LED_CORED", X52PRO_LED_CORED);
395 PyModule_AddIntConstant(m, "LED_COGREEN", X52PRO_LED_COGREEN);
396 PyModule_AddIntConstant(m, "LED_IRED", X52PRO_LED_IRED);
397 PyModule_AddIntConstant(m, "LED_IGREEN", X52PRO_LED_IGREEN);
399 PyModule_AddIntConstant(m, "TYPE_X52", DEV_X52);
400 PyModule_AddIntConstant(m, "TYPE_X52PRO", DEV_X52PRO);
401 PyModule_AddIntConstant(m, "TYPE_YOKE", DEV_YOKE);