use only one process for emu input event emulation

Seems that SDL is not thread-safe, so forking leads to some
strange bugs. Thus I switch back to one process implementaion.
pull/2/merge
Qingping Hou 12 years ago
parent 9fca67b6cb
commit 02d48dee3d

@ -86,14 +86,14 @@ int findFreeFdSlot() {
}
static int openInputDevice(lua_State *L) {
const char* inputdevice = luaL_checkstring(L, 1);
#ifndef EMULATE_READER
int fd;
int childpid;
const char* inputdevice = luaL_checkstring(L, 1);
fd = findFreeFdSlot();
if(fd == -1) {
return luaL_error(L, "no free slot for new input device <%s>", inputdevice);
}
#ifndef EMULATE_READER
if(!strcmp("fake_events", inputdevice)) {
/* special case: the power slider */
int pipefd[2];
@ -179,60 +179,6 @@ static int openInputDevice(lua_State *L) {
inputfds[fd] = pipefd[0];
slider_pid = childpid;
}
#else
int keep_waiting = 1;
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
return luaL_error(L, "cannot initialize SDL.");
}
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
if((childpid = fork()) == -1) {
return luaL_error(L, "cannot fork() emu event generator");
}
if(childpid == 0) {
struct input_event ev;
SDL_Event event;
/*close(pipefd[0]);*/
inputfds[fd] = open(inputdevice, O_RDWR | O_NONBLOCK);
while(keep_waiting) {
SDL_WaitEvent(&event);
switch(event.type) {
case SDL_KEYDOWN:
genEmuEvent(L, inputfds[fd], EV_KEY, event.key.keysym.scancode, 1);
break;
case SDL_KEYUP:
genEmuEvent(L, inputfds[fd], EV_KEY, event.key.keysym.scancode, 0);
break;
case SDL_MOUSEMOTION:
/* ignore move motion here, we might use it for other
* gesture in future. */
/*printf("Mouse moved by %d,%d to (%d,%d)\n", */
/*event.motion.xrel, event.motion.yrel,*/
/*event.motion.x, event.motion.y);*/
break;
case SDL_MOUSEBUTTONDOWN:
/* use mouse click to simulate single tap */
genEmuEvent(L, inputfds[fd], EV_ABS, ABS_MT_TRACKING_ID, 0);
genEmuEvent(L, inputfds[fd], EV_ABS, ABS_MT_POSITION_X, event.button.x);
genEmuEvent(L, inputfds[fd], EV_ABS, ABS_MT_POSITION_Y, event.button.y);
genEmuEvent(L, inputfds[fd], EV_SYN, SYN_REPORT, 0);
genEmuEvent(L, inputfds[fd], EV_ABS, ABS_MT_TRACKING_ID, -1);
genEmuEvent(L, inputfds[fd], EV_SYN, SYN_REPORT, 0);
/*printf("Mouse button %d pressed at (%d,%d)\n",*/
/*event.button.button, event.button.x, event.button.y);*/
break;
case SDL_QUIT:
/* 3 byte is enough to signal waitForInput */
write(inputfds[fd], "application forced to quit", 3);
keep_waiting = 0;
}
}
close(inputfds[fd]);
// We're done, go away :).
_exit(EXIT_SUCCESS);
#endif
} else {
inputfds[fd] = open(inputdevice, O_RDONLY | O_NONBLOCK, 0);
if(inputfds[fd] != -1) {
@ -242,6 +188,18 @@ static int openInputDevice(lua_State *L) {
return luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno);
}
}
#else
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
return luaL_error(L, "cannot initialize SDL.");
}
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
/* we only use inputfds[0] in emu mode, because we only have one
* fake device so far. */
inputfds[0] = open(inputdevice, O_RDWR | O_NONBLOCK);
if (inputfds < 0) {
return luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno);
}
#endif
return 0;
}
@ -261,22 +219,20 @@ static int closeInputDevices(lua_State *L) {
}
return 0;
#else
if(emu_event_pid != -1) {
/* kill and wait for child process */
kill(emu_event_pid, SIGTERM);
waitpid(-1, NULL, 0);
}
close(inputfds[0]);
SDL_Quit();
return 0;
#endif
}
static int waitForInput(lua_State *L) {
struct input_event input;
int n;
#ifndef EMULATE_READER
int usecs = luaL_optint(L, 1, -1); // we check for <0 later
fd_set fds;
struct timeval timeout;
int i, n, num, nfds;
struct input_event input;
int i, num, nfds;
timeout.tv_sec = (usecs/1000000);
timeout.tv_usec = (usecs%1000000);
@ -315,14 +271,60 @@ static int waitForInput(lua_State *L) {
lua_pushinteger(L, (int) input.value);
lua_settable(L, -3);
return 1;
} else {
if (*((char *)&input) == 'a') {
return luaL_error(L, "application forced to quit");
}
}
}
}
#else
SDL_Event event;
while(1) {
/* so far we only use inputfds[0] in emu mode */
n = read(inputfds[0], &input, sizeof(struct input_event));
if(n == sizeof(struct input_event)) {
lua_newtable(L);
lua_pushstring(L, "type");
lua_pushinteger(L, (int) input.type);
lua_settable(L, -3);
lua_pushstring(L, "code");
lua_pushinteger(L, (int) input.code);
lua_settable(L, -3);
lua_pushstring(L, "value");
lua_pushinteger(L, (int) input.value);
lua_settable(L, -3);
return 1;
}
SDL_WaitEvent(&event);
switch(event.type) {
case SDL_KEYDOWN:
genEmuEvent(L, inputfds[0], EV_KEY, event.key.keysym.scancode, 1);
break;
case SDL_KEYUP:
genEmuEvent(L, inputfds[0], EV_KEY, event.key.keysym.scancode, 0);
break;
case SDL_MOUSEMOTION:
/* ignore move motion here, we might use it for other
* gesture in future. */
/*printf("Mouse moved by %d,%d to (%d,%d)\n", */
/*event.motion.xrel, event.motion.yrel,*/
/*event.motion.x, event.motion.y);*/
break;
case SDL_MOUSEBUTTONDOWN:
/* use mouse click to simulate single tap */
genEmuEvent(L, inputfds[0], EV_ABS, ABS_MT_TRACKING_ID, 0);
genEmuEvent(L, inputfds[0], EV_ABS, ABS_MT_POSITION_X, event.button.x);
genEmuEvent(L, inputfds[0], EV_ABS, ABS_MT_POSITION_Y, event.button.y);
genEmuEvent(L, inputfds[0], EV_SYN, SYN_REPORT, 0);
genEmuEvent(L, inputfds[0], EV_ABS, ABS_MT_TRACKING_ID, -1);
genEmuEvent(L, inputfds[0], EV_SYN, SYN_REPORT, 0);
/*printf("Mouse button %d pressed at (%d,%d)\n",*/
/*event.button.button, event.button.x, event.button.y);*/
break;
case SDL_QUIT:
return luaL_error(L, "application forced to quit");
}
}
#endif
return 0;
}

Loading…
Cancel
Save