Compare commits

...

2 commits

Author SHA1 Message Date
Tobias Boege
3b166c7f9b gb.joystick: Remove the concept of sticks
[GB.JOYSTICK]
* BUG: Joystick.{Stick,Direction} are not well-defined. Stick to axes as the Linux API does.
2019-02-24 22:37:06 +01:00
Tobias Boege
4a22fb7522 Add gb.joystick for Linux' legacy Joystick API
[CONFIGURATION]
* NEW: Add gb.joystick

[GB.JOYSTICK]
* NEW: New component to interface with Linux' legacy Joystick API
2019-02-24 22:24:01 +01:00
8 changed files with 419 additions and 1 deletions

View file

@ -94,6 +94,15 @@ GB_COMPONENT(
[GB_FIND(, /usr/local /usr, lib)],
[$GB_INOTIFY_LIB])
dnl ---- Check for the Linux joystick headers
dnl TODO: Should also check if JS_VERSION >= 0x010000
GB_COMPONENT(
joystick, JOYSTICK, gb.joystick, [joystick],
[GB_FIND(linux/joystick.h, /usr/local/lib /usr/local /usr/lib /usr, include)],
[GB_FIND(, /usr/local /usr, lib)],
[$C_LIB])
dnl ---- We do not use libtool to load shared libraries anymore!
AC_DEFINE(DONT_USE_LTDL, 1, [Do not use libtool to load shared libraries])
@ -140,6 +149,7 @@ lib/data/Makefile \
lib/clipper/Makefile \
lib/inotify/Makefile \
lib/jit/Makefile \
lib/joystick/Makefile \
])
AC_OUTPUT

View file

@ -1,2 +1,2 @@
SUBDIRS = debug eval db compress vb option geom draw image gui gui.opengl gui.qt gui.qt.webkit gui.qt.opengl image.effect signal term complex data clipper gui.trayicon @INOTIFY_DIR@ jit
SUBDIRS = debug eval db compress vb option geom draw image gui gui.opengl gui.qt gui.qt.webkit gui.qt.opengl image.effect signal term complex data clipper gui.trayicon @INOTIFY_DIR@ jit joystick
EXTRA_DIST = gb.component

View file

@ -0,0 +1,10 @@
COMPONENT = gb.joystick
include $(top_srcdir)/component.am
gblib_LTLIBRARIES = gb.joystick.la
gb_joystick_la_LIBADD = @JOYSTICK_LIB@
gb_joystick_la_LDFLAGS = -module @LD_FLAGS@ @JOYSTICK_LDFLAGS@
gb_joystick_la_CPPFLAGS = @JOYSTICK_INC@ -I$(top_srcdir)/share
gb_joystick_la_SOURCES = \
main.c main.h \
c_joystick.c c_joystick.h

View file

@ -0,0 +1,278 @@
/***************************************************************************
c_joystick.c
(C) 2015-2019 Tobias Boege <tobias@gambas-buch.de>
with bits from Cedron Dawg
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 1, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __C_JOYSTICK_C
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <linux/joystick.h>
#include "c_joystick.h"
#define GB_ErrorErrno() GB.Error(strerror(errno))
typedef struct {
GB_BASE ob;
int fd;
struct js_event e;
int e_init; /* last event had JS_EVENT_INIT bit set? */
} CJOYSTICK;
DECLARE_EVENT(EVENT_Axis);
DECLARE_EVENT(EVENT_Button);
static void read_cb(int fd, int flags, CJOYSTICK *joy)
{
again:
if (read(fd, &joy->e, sizeof(joy->e)) != sizeof(joy->e)) {
if (errno == EINTR)
goto again;
GB_ErrorErrno();
return;
}
joy->e_init = !!(joy->e.type & JS_EVENT_INIT);
switch (joy->e.type & ~JS_EVENT_INIT) {
case JS_EVENT_AXIS:
GB.Raise(joy, EVENT_Axis, 0);
break;
case JS_EVENT_BUTTON:
GB.Raise(joy, EVENT_Button, 0);
break;
default:
fprintf(stderr, "[gb.joystick] Unknown event type '%d'. "
"Please report this as a bug.\n", joy->e.type);
break;
}
}
#define THIS ((CJOYSTICK *) _object)
/**G
* Create a new joystick object. The ~Path~ should point to the special
* character device for the joystick, usually something like
* `/dev/input/js0`.
**/
BEGIN_METHOD(Joystick_new, GB_STRING path)
/* Need a NUL-terminated string */
char *path = GB.TempString(STRING(path), LENGTH(path));
int fd;
fd = open(path, O_RDONLY);
if (fd == -1) {
GB_ErrorErrno();
return;
}
THIS->fd = fd;
GB.Watch(fd, GB_WATCH_READ, (void *) read_cb, (intptr_t) THIS);
END_METHOD
BEGIN_METHOD_VOID(Joystick_free)
GB.Watch(THIS->fd, GB_WATCH_NONE, NULL, 0);
close(THIS->fd);
END_METHOD
/**G
* Return the number of axes of the joystick.
**/
BEGIN_PROPERTY(Joystick_Axes)
unsigned char axes;
if (ioctl(THIS->fd, JSIOCGAXES, &axes) == -1) {
GB_ErrorErrno();
return;
}
GB.ReturnInteger(axes);
END_PROPERTY
/**G
* Return the number of buttons of the joystick.
**/
BEGIN_PROPERTY(Joystick_Buttons)
unsigned char buttons;
if (ioctl(THIS->fd, JSIOCGBUTTONS, &buttons) == -1) {
GB_ErrorErrno();
return;
}
GB.ReturnInteger(buttons);
END_PROPERTY
/**G
* Return the device ID of the joystick.
**/
BEGIN_PROPERTY(Joystick_Name)
char name[128];
memset(name, 0, sizeof(name));
if (ioctl(THIS->fd, JSIOCGNAME(128), name) == -1) {
GB_ErrorErrno();
return;
}
GB.ReturnNewZeroString(name);
END_PROPERTY
/**G
* When a joystick is opened, it issues a series of synthetic events
* for you to determine the initial state of axes and buttons.
*
* This property indicates if the latest event was such an initialisation
* event.
**/
BEGIN_PROPERTY(Joystick_Init)
GB.ReturnBoolean(THIS->e_init);
END_PROPERTY
/**G
* Returns the index of the button that caused the most recent
* [Button](../.button) event.
**/
BEGIN_PROPERTY(Joystick_Button)
GB.ReturnInteger(THIS->e.number);
END_PROPERTY
/**G
* Returns the index of the axis that caused the most recent
* [Axis](../.axis) event.
**/
BEGIN_PROPERTY(Joystick_Axis)
GB.ReturnInteger(THIS->e.number);
END_PROPERTY
/**G
* In a Button event, this value is 0 or 1, according to whether the
* [button](../button) was pressed or released.
*
* In an Axis event, the value gives the position of the [axis](../axis)
* on a scale of -32767 to +32767, the range of a [Short](/lang/type/short).
*
* [[ warning
* The actual range of values seen in this property might be smaller
* than the full Short range **if the joystick calibration is off**.
* There exist external tools to recalibrate it but you may want to
* use *thresholds* when determining the intensity of the stick tilt,
* to make your program more robust to uncalibrated devices.
* ]]
**/
BEGIN_PROPERTY(Joystick_Value)
GB.ReturnInteger(THIS->e.value);
END_PROPERTY
/**G
* A timestamp for the event in milliseconds. You can use this to detect
* whether buttons were pressed or sticks were moved "almost" simultaneously,
* independently of how fast you process them in your program.
*
* [[ warning
* The timestamp comes out of the kernel as an unsigned 32-bit integer,
* but Gambas has only signed integers. As such, timestamps will overflow
* and change sign around every 25 days and reset to zero every 50 days.
* ]]
**/
BEGIN_PROPERTY(Joystick_Time)
GB.ReturnInteger(THIS->e.time);
END_PROPERTY
/**G
* This class represents a joystick/gamepad handled by the legacy
* [Linux Joystick API]. Once created it raises its [Button](.button)
* and [Axis](.axis) events to indicate input from the device.
*
* An analog control stick on a gamepad usually has two axes: one
* is vertical the other horizontal. However, there exist sticks with
* only a single axis and the numbering of axes is not always
* consistent with respect to being horizontal or vertical.
* Usually, you will want to let the user configure which buttons
* and axes should cause which actions in your program.
*
* Some properties of this class describe the device itself, while
* others describe the latest event that occurred. You should use
* them during event handlers only.
*
* [Linux Joystick API]: https://www.kernel.org/doc/html/latest/input/joydev/joystick-api.html
**/
GB_DESC CJoystick[] = {
GB_DECLARE("Joystick", sizeof(CJOYSTICK)),
GB_PROPERTY_READ("Axes", "i", Joystick_Axes),
GB_PROPERTY_READ("Buttons", "i", Joystick_Buttons),
GB_PROPERTY_READ("Name", "s", Joystick_Name),
//GB_PROPERTY_READ("DriverVersion", "i", Joystick_DriverVersion),
//GB_PROPERTY("Correction", ".Joystick.Correction", Joystick_Correction),
// There are a few more ioctls in my <linux/joystick.h>
// which I found no documentation for...
/**G
* Raised when a joystick stick changes position.
* The axis on which the stick changed in is stored in the
* [Axis](../axis) property and the new position is the
* [Value](../value) property.
**/
GB_EVENT("Axis", NULL, NULL, &EVENT_Axis),
/**G
* Raised when a joystick button was pressed or released.
* The index of the button is stored in the [Button](../button)
* property. Its new state can be found in the [Value](../value)
* property.
**/
GB_EVENT("Button", NULL, NULL, &EVENT_Button),
GB_METHOD("_new", NULL, Joystick_new, "(Path)s"),
GB_METHOD("_free", NULL, Joystick_free, NULL),
/* Event data */
GB_PROPERTY_READ("Init", "b", Joystick_Init),
GB_PROPERTY_READ("Axis", "i", Joystick_Axis),
GB_PROPERTY_READ("Button", "i", Joystick_Button),
GB_PROPERTY_READ("Value", "i", Joystick_Value),
GB_PROPERTY_READ("Time", "i", Joystick_Time),
GB_END_DECLARE
};

View file

@ -0,0 +1,35 @@
/***************************************************************************
c_joystick.h
(C) 2015-2019 Tobias Boege <tobias@gambas-buch.de>
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 1, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#ifndef __C_JOYSTICK_H
#define __C_JOYSTICK_H
#include "gambas.h"
extern GB_INTERFACE GB;
#ifndef __C_JOYSTICK_C
extern GB_DESC CJoystick[];
#endif
#endif /* __C_JOYSTICK_H */

View file

@ -0,0 +1,4 @@
[Component]
Name=Linux Joystick API component
Author=Tobias Boege
State=Experimental

46
main/lib/joystick/main.c Normal file
View file

@ -0,0 +1,46 @@
/***************************************************************************
main.c
gb.joystick component
(C) 2015-2019 Tobias Boege <tobias@gambas-buch.de>
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 1, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __MAIN_C
#include "c_joystick.h"
#include "main.h"
GB_INTERFACE GB EXPORT;
GB_DESC *GB_CLASSES[] EXPORT = {
CJoystick,
NULL
};
int EXPORT GB_INIT()
{
return 0;
}
void EXPORT GB_EXIT()
{
}

35
main/lib/joystick/main.h Normal file
View file

@ -0,0 +1,35 @@
/***************************************************************************
main.h
gb.joystick component
(C) 2015-2019 Tobias Boege <tobias@gambas-buch.de>
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 1, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#ifndef __MAIN_H
#define __MAIN_H
#include "gambas.h"
#ifndef __MAIN_C
extern GB_INTERFACE GB;
#endif
#endif /* __MAIN_H */