/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * mod_multimouse.c: Simple module for accessing /dev/input/mouse* devices */ /** * This module provides a simple way to access the Linux /dev/input/mouse* * devices. It has been written for multiplayer games where every player has * his own mouse. */ #define MOUSE_COUNT 64 #include #include #include #include #include #include #include #include "spl.h" #include "compat.h" extern void SPL_ABI(spl_mod_multimouse_init)(struct spl_vm *vm, struct spl_module *mod, int restore); extern void SPL_ABI(spl_mod_multimouse_done)(struct spl_vm *vm, struct spl_module *mod); struct mm_hnode_data { int fd, error; int direction; int x, y, b1, b2; int ox, oy, ob1, ob2; int mx, my, dx, dy; }; #define DIR_BOTTOM 0 #define DIR_LEFT 1 #define DIR_TOP 2 #define DIR_RIGHT 3 static struct mm_hnode_data *handler_multimouse_init() { struct mm_hnode_data *d = calloc(MOUSE_COUNT, sizeof(struct mm_hnode_data)); for (int i=0; ihnode_data) node->hnode_data = handler_multimouse_init(); struct mm_hnode_data *d = node->hnode_data; for (int i=0; i= 0) { signed char buffer[3]; d[i].ob1 = d[i].b1; d[i].ob2 = d[i].b2; d[i].ox = d[i].x; d[i].oy = d[i].y; if (read(d[i].fd, buffer, 3) == 3) { d[i].b1 = buffer[0]&1; d[i].b2 = buffer[0]&2; switch (d[i].direction) { case DIR_BOTTOM: d[i].dx = +buffer[1]; d[i].dy = -buffer[2]; break; case DIR_LEFT: d[i].dx = +buffer[2]; d[i].dy = +buffer[1]; break; case DIR_TOP: d[i].dx = -buffer[1]; d[i].dy = +buffer[2]; break; case DIR_RIGHT: d[i].dx = -buffer[2]; d[i].dy = -buffer[1]; break; } d[i].x += d[i].dx; d[i].y += d[i].dy; if (d[i].x < 0) d[i].x = 0; if (d[i].y < 0) d[i].y = 0; if (d[i].x > d[i].mx) d[i].x = d[i].mx; if (d[i].y > d[i].my) d[i].y = d[i].my; } else { d[i].dx = 0; d[i].dy = 0; } } } return 0; } /** * This namespace holds the status information of all mice. It is an array * of hashes with one array elements per mouse and one hash entry per property. * * E.g. the variable 'multimouse[3].b1' has the value '1' if the left (first) * mouse button of the 4th mouse (the array starts with index 0) is pressed. * * The following properies are implemented: * * b1, b2 * Left and right mouse button * * dx, dy * X- and Y-delta for all mousemovement between the last * call to [[multimouse_update()]] and the call before the * last one. * * x, y * X- and Y-coordinates of the current mouse position. * * mx, my * The maximum X- and Y-coordinates. This variables must * be set before the variables x and y can be used. * * ob1, ob2, ox, oy * The old values of b1, b2, x and y before the last call to * [[multimouse_update()]]. * * direction * The view-point of the player. Possible values are 'bottom', * 'top', 'left' and 'right'. The default value is 'bottom'. * * error * This variable is defined when an error occured while opening * the mouse device and is set to the error string. * * The 'error' variable is read-only. All the other variables are read- and * writeable. * */ // namespace multimouse static void handler_multimouse_node(struct spl_task UNUSED(*task), struct spl_vm UNUSED(*vm), struct spl_node *node, struct spl_hnode_args *args, void UNUSED(*data)) { if ( args->action == SPL_HNODE_ACTION_PUT ) { struct mm_hnode_data *d = node->hnode_data; if (d) { for (int i=0; i= 0) close(d[i].fd); free(d); } return; } if (!node->hnode_data) node->hnode_data = handler_multimouse_init(); struct mm_hnode_data *d = node->hnode_data; if (args->action == SPL_HNODE_ACTION_LOOKUP || args->action == SPL_HNODE_ACTION_CREATE) { char *key_dup = strdup(args->key); char *strtokptr = 0; char *idx = strtok_r(key_dup, ".", &strtokptr); char *var = strtok_r(0, ".", &strtokptr); if (idx && *idx == '?') idx++; if (var && *var == '?') var++; int i = idx ? atoi(idx) : -1; if (!var || i < 0 || i >= MOUSE_COUNT) { free(key_dup); return; } if (args->action == SPL_HNODE_ACTION_LOOKUP && !strcmp(var, "error")) { if (d[i].fd < 0) args->value = SPL_NEW_STRING_DUP(strerror(d[i].error)); free(key_dup); return; } if (!strcmp(var, "direction")) { if (args->action == SPL_HNODE_ACTION_LOOKUP) { if (d[i].direction == DIR_BOTTOM) args->value = SPL_NEW_STRING_DUP("bottom"); if (d[i].direction == DIR_LEFT) args->value = SPL_NEW_STRING_DUP("left"); if (d[i].direction == DIR_TOP) args->value = SPL_NEW_STRING_DUP("top"); if (d[i].direction == DIR_RIGHT) args->value = SPL_NEW_STRING_DUP("right"); } if (args->action == SPL_HNODE_ACTION_CREATE) { char *val = spl_get_string(args->value); if (!strcmp(val, "bottom")) d[i].direction = DIR_BOTTOM; if (!strcmp(val, "left")) d[i].direction = DIR_LEFT; if (!strcmp(val, "top")) d[i].direction = DIR_TOP; if (!strcmp(val, "right")) d[i].direction = DIR_RIGHT; } } struct { char *name; int *valp; } tab[] = { { "x", &d[i].x }, { "y", &d[i].y }, { "b1", &d[i].b1 }, { "b2", &d[i].b2 }, { "ox", &d[i].ox }, { "oy", &d[i].oy }, { "ob1", &d[i].ob1 }, { "ob2", &d[i].ob2 }, { "mx", &d[i].mx }, { "my", &d[i].my }, { "dx", &d[i].dx }, { "dy", &d[i].dy }, { 0, 0 } }; for (int j=0; tab[j].name; j++) { if (!strcmp(var, tab[j].name)) { if (args->action == SPL_HNODE_ACTION_LOOKUP) args->value = SPL_NEW_INT(*tab[j].valp); else *tab[j].valp = spl_get_int(args->value); } } free(key_dup); } } void SPL_ABI(spl_mod_multimouse_init)(struct spl_vm *vm, struct spl_module *mod, int restore) { spl_clib_reg(vm, "__multiouse_update", handler_multimouse_update, 0); spl_hnode_reg(vm, "multimouse_node", handler_multimouse_node, 0); if (!restore) { spl_hnode(vm, vm->root, "multimouse", "multimouse_node", mod); spl_eval(vm, 0, strdup(mod->name), "function multimouse_update() { " "__multiouse_update(multimouse); }"); } } void SPL_ABI(spl_mod_multimouse_done)(struct spl_vm UNUSED(*vm), struct spl_module UNUSED(*mod)) { return; }