~shiny/tools

df0dfd8cceac9afc5b63ea7ec878278574f29ff5 — Thomas Spurden 9 years ago
Converts joystick input to fake keyboard input
1 files changed, 164 insertions(+), 0 deletions(-)

A joykey.c
A  => joykey.c +164 -0
@@ 1,164 @@
#if 0
# Copyright (c) 2011, Thomas Spurden <thomas@spurden.name>
# 
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
# 
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Generate key press/release events from joystick button press/release events.

# This file can be read by either GNU Make or a C99 compiler.
# Easy way to compile is: make -f thisfile output
# Which will produce a binary called output.

# Dependencies: X11 with XTest extension and SDL.

! := $(lastword $(MAKEFILE_LIST))
%: $!
	$(CC) -pedantic -Wall -O2 -std=c99 -lX11 -lXtst -lSDL -o $@ -xc $!

define program
#endif

// If set, print each joystick button event to stdout.
#define VERBOSE (1)

// Choose your joystick index.
#define JoyIndex 0

// List the buttons in order (see jstest output) and the X11 keysym you want to
// be generated by it (or zero for no keysym).  To work out your buttons just
// compile with verbose on; each button press will be printed to stdout.
#define KEYS \
	KEY(Select, XK_a), \
	KEY(LClick, 0), \
	KEY(RClick, 0), \
	KEY(Start, XK_Escape), \
	KEY(Up, XK_Up), \
	KEY(Right, XK_Right), \
	KEY(Down, XK_Down), \
	KEY(Left, XK_Left), \
	KEY(L2, 0), \
	KEY(R2, 0), \
	KEY(L1, 0), \
	KEY(R1, 0), \
	KEY(Triangle, 0), \
	KEY(Circle, 0), \
	KEY(Cross, XK_space), \
	KEY(Square, XK_Shift_L), \
	KEY(PS, 0)

// Actual program now
#include <SDL/SDL.h>
#include <SDL/SDL_joystick.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
#include <X11/extensions/XTest.h>

#define KEY(k,x) Key_ ## k
enum Key {
	KEYS,
	Keys_Num
};
#undef KEY

#define KEY(k,x) [Key_ ## k] = x
static int const buttonMap[Keys_Num] = {
	KEYS
};
#undef KEY

#if VERBOSE
#define KEY(k,x) { .button = #k, .key = #x }
struct {
	char const* button;
	char const* key;
} mapNames[Keys_Num] = {
	KEYS
};
#undef KEY
#endif

Display* dpy = NULL;
SDL_Joystick* input = NULL;

void die(char const* str) {
	fprintf(stderr, "Exited: %s: %s\n", str, SDL_GetError());
	exit(1);
}

void cleanup() {
	if(dpy) XCloseDisplay(dpy);
	if(input) SDL_JoystickClose(input);
	SDL_Quit();
}

int main()
{
	SDL_Event ev;

	if(SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_VIDEO) < 0) die("SDL_Init failed");
	atexit(cleanup);

	if(SDL_JoystickEventState(SDL_ENABLE) == -1)
		die("Could not set joystick events to be queued");

	if((dpy = XOpenDisplay(0)) == NULL)
		die("Could not open X display");

	if((input = SDL_JoystickOpen(JoyIndex)) == NULL)
		die("Could not open joystick");
#if VERBOSE
	printf(
		"Joystick %i: %s; %i axes, %i buttons, %i hats, %i balls\n",
		JoyIndex,
		SDL_JoystickName(JoyIndex),
		SDL_JoystickNumAxes(input),
		SDL_JoystickNumButtons(input),
		SDL_JoystickNumHats(input),
		SDL_JoystickNumBalls(input)
	);
#endif

	while(SDL_WaitEvent(&ev)) {
		if(ev.type == SDL_QUIT) die("Quit");

		if(ev.type == SDL_JOYBUTTONDOWN || ev.type == SDL_JOYBUTTONUP) {
			int const n = ev.jbutton.button;
			if(n < Keys_Num && buttonMap[n]) {
#if VERBOSE
				printf(
					"%s %s => %s\n",
					mapNames[n].button,
					ev.type == SDL_JOYBUTTONDOWN? "down" : "up",
					mapNames[n].key
				);
#endif
				XTestFakeKeyEvent(
					dpy,
					XKeysymToKeycode(dpy, buttonMap[n]),
					ev.type == SDL_JOYBUTTONDOWN,
					CurrentTime
				);
				XFlush(dpy);
				XSync(dpy, False);
			}
#if VERBOSE
			printf("Unmapped button %i pressed\n", n);
#endif
		}
	}
}

#if 0
endef
#endif