Fixed minor errors, added motion events
[xf86-input-tuio.git] / src / tuio.c
blobe24786660d1e77597a2cfb64141dabf2558b2a84
1 /*
2 * Copyright (c) 2009 Ryan Huffman
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
22 * Authors:
23 * Ryan Huffman (ryanhuffman@gmail.com)
26 #include <unistd.h>
28 #include <xf86Xinput.h>
29 #include <X11/extensions/XIproto.h>
30 #include <X11/extensions/XInput2.h>
31 #include <xf86_OSlib.h>
33 #include "tuio.h"
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 /* Module Functions */
40 static pointer
41 TuioPlug(pointer, pointer, int *, int *);
43 static void
44 TuioUnplug(pointer);
46 /* Driver Functions */
47 static InputInfoPtr
48 TuioPreInit(InputDriverPtr, IDevPtr, int);
50 static void
51 TuioUnInit(InputDriverPtr, InputInfoPtr, int);
53 static void
54 TuioReadInput(InputInfoPtr);
56 static int
57 TuioControl(DeviceIntPtr, int);
59 /* Internal Functions */
60 static int
61 _tuio_lo_cur2d_handle(const char *path,
62 const char *types,
63 lo_arg **argv,
64 int argc,
65 void *data,
66 void *user_data);
68 static ObjectPtr
69 _object_get(ObjectList list, int id);
71 static ObjectPtr
72 _object_insert(ObjectList list);
74 static void
75 _object_remove(ObjectList list, ObjectPtr obj);
77 static int
78 _tuio_init_buttons(DeviceIntPtr device);
80 static int
81 _tuio_init_axes(DeviceIntPtr device);
83 static void
84 lo_error(int num,
85 const char *msg,
86 const char *path);
89 static XF86ModuleVersionInfo TuioVersionRec =
91 "tuio",
92 MODULEVENDORSTRING,
93 MODINFOSTRING1,
94 MODINFOSTRING2,
95 XORG_VERSION_CURRENT,
96 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
97 ABI_CLASS_XINPUT,
98 ABI_XINPUT_VERSION,
99 MOD_CLASS_XINPUT,
100 {0, 0, 0, 0}
103 _X_EXPORT InputDriverRec TUIO =
106 "tuio",
107 NULL,
108 TuioPreInit,
109 TuioUnInit,
110 NULL,
114 _X_EXPORT XF86ModuleData tuioModuleData =
116 &TuioVersionRec,
117 TuioPlug,
118 TuioUnplug
121 static pointer
122 TuioPlug(pointer module,
123 pointer options,
124 int *errmaj,
125 int *errmin)
127 xf86AddInputDriver(&TUIO, module, 0);
128 return module;
131 static void
132 TuioUnplug(pointer p)
137 * Pre-initialization of new device
139 * TODO:
140 * - Parse configuration options
141 * - Setup internal data
143 static InputInfoPtr
144 TuioPreInit(InputDriverPtr drv,
145 IDevPtr dev,
146 int flags)
148 InputInfoPtr pInfo;
149 TuioDevicePtr pTuio;
150 const char *device;
152 if (!(pInfo = xf86AllocateInput(drv, 0)))
153 return NULL;
155 pTuio = xcalloc(1, sizeof(TuioDeviceRec));
156 if (!pTuio) {
157 pInfo->private = NULL;
158 xf86DeleteInput(pInfo, 0);
159 return NULL;
162 pInfo->private = pTuio;
164 pInfo->name = xstrdup(dev->identifier);
165 pInfo->flags = 0;
166 pInfo->type_name = XI_TOUCHSCREEN; /* FIXME: Correct type? */
167 pInfo->conf_idev = dev;
168 pInfo->read_input = TuioReadInput; /* Set callback */
169 pInfo->switch_mode = NULL;
170 pInfo->device_control = TuioControl; /* Set callback */
172 /* Process common device options */
173 xf86CollectInputOptions(pInfo, NULL, NULL);
174 xf86ProcessCommonOptions(pInfo, pInfo->options);
176 pInfo->flags |= XI86_OPEN_ON_INIT;
177 pInfo->flags |= XI86_CONFIGURED;
179 return pInfo;
182 static void
183 TuioUnInit(InputDriverPtr drv,
184 InputInfoPtr pInfo,
185 int flags)
187 TuioDevicePtr pTuio = pInfo->private;
189 xfree(pTuio);
190 xf86DeleteInput(pInfo, 0);
194 * Handle new data on the socket
196 static void
197 TuioReadInput(InputInfoPtr pInfo)
199 TuioDevicePtr pTuio = pInfo->private;
200 char data;
202 while(xf86WaitForInput(pInfo->fd, 0) > 0)
204 lo_server_recv_noblock(pTuio->server, 0);
209 * Handle device state changes
211 static int
212 TuioControl(DeviceIntPtr device,
213 int what)
215 InputInfoPtr pInfo = device->public.devicePrivate;
216 TuioDevicePtr pTuio = pInfo->private;
218 switch (what)
220 case DEVICE_INIT:
221 xf86Msg(X_INFO, "%s: Init\n", pInfo->name);
222 _tuio_init_buttons(device);
223 _tuio_init_axes(device);
224 break;
226 case DEVICE_ON: /* Open device socket and start listening! */
227 xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
228 if (device->public.on) /* already on! */
229 break;
231 pTuio->server = lo_server_new_with_proto("3333", LO_UDP, lo_error);
232 if (pTuio->server == NULL) {
233 xf86Msg(X_ERROR, "%s: Error allocating new lo_server\n",
234 pInfo->name);
235 return BadAlloc;
237 pTuio->list = xcalloc(1, sizeof(ObjectPtr));
238 *pTuio->list = NULL;
240 /* Register to receive all /tuio/2Dcur messages */
241 lo_server_add_method(pTuio->server, "/tuio/2Dcur", NULL,
242 _tuio_lo_cur2d_handle, pInfo);
244 pInfo->fd = lo_server_get_socket_fd(pTuio->server);
245 xf86Msg(X_INFO, "%s: Socket = %i\n", pInfo->name, pInfo->fd);
247 //xf86FlushInput(pInfo->fd);
248 xf86AddEnabledDevice(pInfo);
249 device->public.on = TRUE;
250 break;
252 case DEVICE_OFF:
253 xf86Msg(X_INFO, "%s: Off\n", pInfo->name);
254 if (!device->public.on)
255 break;
257 xf86RemoveEnabledDevice(pInfo);
259 lo_server_free(pTuio->server);
261 pInfo->fd = -1;
262 device->public.on = FALSE;
263 break;
265 case DEVICE_CLOSE:
266 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
268 lo_server_free(pTuio->server);
269 pInfo->fd = -1;
270 device->public.on = FALSE;
271 break;
274 return Success;
277 static int
278 _tuio_create_master() {
279 //XICreateMasterInfo ci;
280 //unsigned int blobid;
281 //char cur_name[21]; /* Max len: 20 char + \0 */
283 //sprintf(cur_name, "tuio_blob_%u", blobid);
285 //c.type = XICreateMaster;
286 //c.name = cur_name;
290 * Handles OSC messages in the /tuio/2Dcur address space
292 static int
293 _tuio_lo_cur2d_handle(const char *path,
294 const char *types,
295 lo_arg **argv,
296 int argc,
297 void *data,
298 void *user_data)
300 InputInfoPtr pInfo = user_data;
301 TuioDevicePtr pTuio = pInfo->private;
302 ObjectList list = pTuio->list;
303 ObjectPtr obj, objtemp;
304 int valuators[2];
305 int i;
307 if (argc < 1) {
308 xf86Msg(X_ERROR, "%s: \n", pInfo->name);
309 return 1;
312 /* Parse message type */
313 if (!strcmp(argv[0], "set")) {
314 obj = _object_get(list, argv[1]->i);
315 if(obj == NULL) {
316 obj = _object_insert(list);
317 obj->id = argv[1]->i;
319 obj->x = argv[2]->f;
320 obj->y = argv[3]->f;
321 valuators[0] = obj->x * 1400;
322 valuators[1] = obj->y * 1050;
323 xf86PostMotionEventP(pInfo->dev,
324 TRUE, /* is_absolute */
325 0, /* first_valuator */
326 2, /* num_valuators */
327 valuators);
329 } else if (!strcmp(argv[0], "alive")) {
330 obj = *list;
331 while (obj != NULL) {
332 obj->alive = 0;
333 for (i=1; i<argc; i++) {
334 if (argv[i]->i == obj->id) {
335 obj->alive = 1;
336 break;
339 if (!obj->alive) {
340 objtemp = obj->next;
341 _object_remove(list, obj);
342 obj = objtemp;
343 } else {
344 obj = obj->next;
349 } else if (!strcmp(argv[0], "fseq")) {
352 return 0;
356 * liblo error handler
358 static void
359 lo_error(int num,
360 const char *msg,
361 const char *path)
363 xf86Msg(X_ERROR, "liblo: %s\n", msg);
366 static ObjectPtr
367 _object_get(ObjectList list, int id) {
368 ObjectPtr obj = *list;
370 while (obj != NULL && obj->id != id) {
371 obj = obj->next;
374 return obj;
377 static ObjectPtr
378 _object_insert(ObjectList list) {
379 ObjectPtr obj = xcalloc(1, sizeof(ObjectRec));
380 obj->previous = NULL;
381 obj->next = *list;
382 if (*list != NULL)
383 (*list)->previous = obj;
384 *list = obj;
385 return obj;
388 static void
389 _object_remove(ObjectList list, ObjectPtr obj) {
390 if (obj->next != NULL)
391 obj->next->previous = obj->previous;
393 if (obj->previous != NULL)
394 obj->previous->next = obj->next;
395 else
396 *list = obj->next;
397 free(obj);
401 * Init the button map for the random device.
402 * @return Success or X error code on failure.
404 static int
405 _tuio_init_buttons(DeviceIntPtr device)
407 InputInfoPtr pInfo = device->public.devicePrivate;
408 CARD8 *map;
409 int i;
410 const int num_buttons = 2;
411 int ret = Success;
413 map = xcalloc(num_buttons, sizeof(CARD8));
415 for (i = 0; i < num_buttons; i++)
416 map[i] = i;
418 if (!InitButtonClassDeviceStruct(device, num_buttons, map)) {
419 xf86Msg(X_ERROR, "%s: Failed to register buttons.\n", pInfo->name);
420 ret = BadAlloc;
423 xfree(map);
424 return ret;
429 * Init the valuators for the random device.
430 * Only absolute mode is supported.
431 * @return Success or X error code on failure.
433 static int
434 _tuio_init_axes(DeviceIntPtr device)
436 InputInfoPtr pInfo = device->public.devicePrivate;
437 int i;
438 const int num_axes = 2;
440 if (!InitValuatorClassDeviceStruct(device,
441 num_axes,
442 GetMotionHistorySize(),
444 return BadAlloc;
446 pInfo->dev->valuator->mode = Absolute;
447 if (!InitAbsoluteClassDeviceStruct(device))
448 return BadAlloc;
450 for (i = 0; i < num_axes; i++)
452 xf86InitValuatorAxisStruct(device, i, -1, -1, 1, 1, 1);
453 xf86InitValuatorDefaults(device, i);
455 return Success;