Files
MiniGUI/src/ial/auto.c
T

325 lines
8.4 KiB
C

///////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT NOTICE
//
// The following open source license statement does not apply to any
// entity in the Exception List published by FMSoft.
//
// For more information, please visit:
//
// https://www.fmsoft.cn/exception-list
//
//////////////////////////////////////////////////////////////////////////////
/*
* This file is part of MiniGUI, a mature cross-platform windowing
* and Graphics User Interface (GUI) support system for embedded systems
* and smart IoT devices.
*
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
* Copyright (C) 1998~2002, WEI Yongming
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Or,
*
* As this program is a library, any link to this program must follow
* GNU General Public License version 3 (GPLv3). If you cannot accept
* GPLv3, you need to be licensed from FMSoft.
*
* If you have got a commercial license of this program, please use it
* under the terms and conditions of the commercial license.
*
* For more information about the commercial license, please refer to
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
/*
** auto.c: Automatic Input Engine
**
** Created by Wei Yongming, 2004/01/29
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#ifdef _MGIAL_AUTO
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "minigui.h"
#include "misc.h"
#include "ial.h"
#include "auto-protocol.h"
static AUTO_IAL_INPUT_EVENT event, *last_event=NULL, *mouse_event=&event, *key_event=&event;
static long long int time_started = 0;
static int fd_script = -1;
static const unsigned char *s_scripts = NULL;
static int s_scripts_len = 0;
static long long int getcurtime(void)
{
struct timeval tv;
gettimeofday( &tv, NULL );
return (long long int)tv.tv_sec * 1000 + (long long int)tv.tv_usec / 1000;
}
/************************ Low Level Input Operations **********************/
/*
* Mouse operations -- Event
*/
static int mouse_update (void)
{
if (last_event && last_event->type == 1)
{
mouse_event = last_event;
last_event = NULL;
return 1;
}
else
{
return -1;
}
}
static void mouse_getxy (int *x, int* y)
{
*x = mouse_event->u.mouse_event.x;
*y = mouse_event->u.mouse_event.y;
}
static int mouse_getbutton (void)
{
return mouse_event->u.mouse_event.buttons;
}
static unsigned char kbd_state [NR_KEYS];
static int keyboard_update (void)
{
if (last_event && last_event->type == 0)
{
key_event = last_event;
last_event = NULL;
kbd_state[key_event->u.key_event.scancode] = key_event->u.key_event.type;
return key_event->u.key_event.scancode + 1;
}
else
{
return -1;
}
}
static const char* keyboard_getstate (void)
{
return ( const char*) kbd_state;
}
static int get_auto_event(void)
{
if (s_scripts)
{
if (s_scripts_len >= sizeof(event))
{
memcpy(&event, s_scripts, sizeof(event));
s_scripts += sizeof(event);
s_scripts_len -= sizeof(event);
goto got;
}
else
{
return -1;
}
}
else
{
int n_read = read (fd_script, &event, sizeof (event));
if (n_read != sizeof (event)) {
if (errno != EAGAIN) {
/* reach EOF */
char* loop = getenv ("MG_ENV_IAL_AUTO_REPLAY");
if (loop) { /* try to replay */
time_started = 0; /* reset time_started */
lseek (fd_script, 0, SEEK_SET);
n_read = read (fd_script, &event, sizeof(event));
if (n_read == sizeof (event) ) {
goto got;
}
}
}
if (errno != EAGAIN)
{
close(fd_script);
fd_script = -1;
}
return -1;
}
else
{
goto got;
}
}
got:
event.timestamp = ArchSwapLE64(event.timestamp);
event.type = ArchSwapLE32(event.type);
if (event.type == 0)
{
event.u.key_event.scancode = ArchSwapLE32(event.u.key_event.scancode);
event.u.key_event.type = ArchSwapLE32(event.u.key_event.type);
}
else
{
event.u.mouse_event.x = ArchSwapLE32(event.u.mouse_event.x);
event.u.mouse_event.y = ArchSwapLE32(event.u.mouse_event.y);
event.u.mouse_event.buttons = ArchSwapLE32(event.u.mouse_event.buttons);
}
return 1;
}
static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
struct timeval *timeout)
{
long long int curtime;
long long int steptime;
struct timeval mytimeout = { 0, 0 };
int e;
curtime = getcurtime();
/* get last event */
if (! last_event && (fd_script >= 0 || s_scripts)) {
/* get next event */
if (get_auto_event() > 0) {
last_event = &event;
if (time_started == 0) {
time_started = curtime - last_event->timestamp;
}
}
}
if (last_event) {
steptime = last_event->timestamp - (curtime - time_started);
/* calculate steptime value */
if (steptime < 0)
steptime = 0;
if (timeout == NULL) {
/* modify timeout value */
mytimeout.tv_sec = (time_t)(steptime / 1000);
mytimeout.tv_usec =
#ifdef HAVE_SYS_TIME_H
(suseconds_t)
#endif
((steptime % 1000) * 1000);
timeout = &mytimeout;
} else {
if (steptime < (timeout->tv_sec * 1000 + timeout->tv_usec / 1000)) {
/* modify timeout value */
timeout->tv_sec = (time_t)(steptime / 1000);
timeout->tv_usec =
#ifdef HAVE_SYS_TIME_H
(suseconds_t)
#endif
((steptime % 1000) * 1000);
}
} /* end if */
e = select (maxfd + 1, in, out, except, timeout);
if (e < 0) {
/* zero all fd sets */
if (in) FD_ZERO (in);
if (out) FD_ZERO (out);
if (except) FD_ZERO (except);
}
curtime = getcurtime();
if (last_event->timestamp > (curtime - time_started)) {
return 0;
} else {
return (last_event->type == 0) ? IAL_KEYEVENT : IAL_MOUSEEVENT;
}
} else {
e = select (maxfd + 1, in, out, except, timeout);
if (e < 0) {
/* zero all fd sets */
if (in) FD_ZERO (in);
if (out) FD_ZERO (out);
if (except) FD_ZERO (except);
return -1;
} else {
return 0;
}
}
}
BOOL ial_InitAutoInput (INPUT* input, const char* mdev, const char* mtype)
{
input->update_mouse = mouse_update;
input->get_mouse_xy = mouse_getxy;
input->set_mouse_xy = NULL;
input->get_mouse_button = mouse_getbutton;
input->set_mouse_range = NULL;
input->suspend_mouse= NULL;
input->resume_mouse = NULL;
input->update_keyboard = keyboard_update;
input->get_keyboard_state = keyboard_getstate;
input->suspend_keyboard = NULL;
input->resume_keyboard = NULL;
input->set_leds = NULL;
input->wait_event = wait_event;
if (! s_scripts)
{
char *path;
path = getenv("MG_ENV_RECORD_IAL");
if (! path)
{
path = "ial_scripts.dat";
}
fd_script = open(path, O_RDONLY, 0);
}
return TRUE;
}
void TermAutoInput (void)
{
}
void IALSetAutoScripts(const unsigned char *scripts, int scripts_len)
{
s_scripts = scripts;
s_scripts_len = scripts_len;
}
#endif /* _MGIAL_AUTO */