mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2026-04-13 03:16:12 +00:00
Merge branch 'sdl'
This commit is contained in:
15
src/config.c
15
src/config.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015, 2016 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -37,7 +37,6 @@
|
||||
#define write_config_bool(fd, key, value) fprintf(fd, "%s = %s\n", key, value?"true":"false");
|
||||
|
||||
bool inputAdded = false;
|
||||
static bool mapped = true;
|
||||
const char* audio_device = NULL;
|
||||
|
||||
static struct option long_options[] = {
|
||||
@@ -152,11 +151,9 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) {
|
||||
perror("Too many inputs specified");
|
||||
exit(-1);
|
||||
}
|
||||
config->inputs[config->inputsCount].path = value;
|
||||
config->inputs[config->inputsCount].mapping = config->mapping;
|
||||
config->inputs[config->inputsCount] = value;
|
||||
config->inputsCount++;
|
||||
inputAdded = true;
|
||||
mapped = true;
|
||||
break;
|
||||
case 'k':
|
||||
config->mapping = get_path(value, getenv("XDG_DATA_DIRS"));
|
||||
@@ -164,7 +161,6 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) {
|
||||
fprintf(stderr, "Unable to open custom mapping file: %s\n", value);
|
||||
exit(-1);
|
||||
}
|
||||
mapped = false;
|
||||
break;
|
||||
case 'l':
|
||||
config->sops = false;
|
||||
@@ -309,7 +305,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
|
||||
config->codec = CODEC_UNSPECIFIED;
|
||||
|
||||
config->inputsCount = 0;
|
||||
config->mapping = get_path("mappings/default.conf", getenv("XDG_DATA_DIRS"));
|
||||
config->mapping = get_path("gamecontrollerdb.txt", getenv("XDG_DATA_DIRS"));
|
||||
config->key_dir[0] = 0;
|
||||
|
||||
char* config_file = get_path("moonlight.conf", "/etc");
|
||||
@@ -352,10 +348,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
|
||||
}
|
||||
|
||||
if (inputAdded) {
|
||||
if (!mapped) {
|
||||
fprintf(stderr, "Mapping option should be followed by the input to be mapped.\n");
|
||||
exit(-1);
|
||||
} else if (config->mapping == NULL) {
|
||||
if (config->mapping == NULL) {
|
||||
fprintf(stderr, "Please specify mapping file as default mapping could not be found.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015, 2016 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,11 +25,6 @@
|
||||
|
||||
enum codecs { CODEC_UNSPECIFIED, CODEC_H264, CODEC_HEVC };
|
||||
|
||||
struct input_config {
|
||||
char* path;
|
||||
char* mapping;
|
||||
};
|
||||
|
||||
typedef struct _CONFIGURATION {
|
||||
STREAM_CONFIGURATION stream;
|
||||
char* app;
|
||||
@@ -44,7 +39,7 @@ typedef struct _CONFIGURATION {
|
||||
bool fullscreen;
|
||||
bool forcehw;
|
||||
bool unsupported_version;
|
||||
struct input_config inputs[MAX_INPUTS];
|
||||
char* inputs[MAX_INPUTS];
|
||||
int inputsCount;
|
||||
enum codecs codec;
|
||||
} CONFIGURATION, *PCONFIGURATION;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,13 @@
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <endian.h>
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define int16_to_le(val) val
|
||||
#else
|
||||
#define int16_to_le(val) ((((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00))
|
||||
#endif
|
||||
|
||||
struct input_abs_parms {
|
||||
int min, max;
|
||||
@@ -48,7 +55,10 @@ struct input_abs_parms {
|
||||
|
||||
struct input_device {
|
||||
struct libevdev *dev;
|
||||
struct mapping map;
|
||||
struct mapping* map;
|
||||
int key_map[KEY_MAX];
|
||||
int abs_map[ABS_MAX];
|
||||
int hats_state[3][2];
|
||||
int fd;
|
||||
char modifiers;
|
||||
__s32 mouseDeltaX, mouseDeltaY, mouseScroll;
|
||||
@@ -59,9 +69,16 @@ struct input_device {
|
||||
short rightStickX, rightStickY;
|
||||
bool gamepadModified;
|
||||
struct input_abs_parms xParms, yParms, rxParms, ryParms, zParms, rzParms;
|
||||
struct input_abs_parms dpadxParms, dpadyParms;
|
||||
};
|
||||
|
||||
#define HAT_UP 1
|
||||
#define HAT_RIGHT 2
|
||||
#define HAT_DOWN 4
|
||||
#define HAT_LEFT 8
|
||||
static const int hat_constants[3][3] = {{HAT_UP | HAT_LEFT, HAT_UP, HAT_UP | HAT_RIGHT}, {HAT_LEFT, 0, HAT_RIGHT}, {HAT_LEFT | HAT_DOWN, HAT_DOWN, HAT_RIGHT}};
|
||||
|
||||
#define set_hat(flags, flag, hat, hat_flag) flags = (-((hat & hat_flag) > 0) ^ flags) & flag
|
||||
|
||||
static struct input_device* devices = NULL;
|
||||
static int numDevices = 0;
|
||||
static int assignedControllerIds = 0;
|
||||
@@ -78,9 +95,9 @@ static bool grabbingDevices;
|
||||
static bool (*handler) (struct input_event*, struct input_device*);
|
||||
|
||||
static void evdev_init_parms(struct input_device *dev, struct input_abs_parms *parms, int code) {
|
||||
parms->flat = libevdev_get_abs_flat(dev->dev, code);
|
||||
parms->min = libevdev_get_abs_minimum(dev->dev, code);
|
||||
parms->max = libevdev_get_abs_maximum(dev->dev, code);
|
||||
parms->flat = libevdev_get_abs_flat(dev->dev, dev->abs_map[code]);
|
||||
parms->min = libevdev_get_abs_minimum(dev->dev, dev->abs_map[code]);
|
||||
parms->max = libevdev_get_abs_maximum(dev->dev, dev->abs_map[code]);
|
||||
parms->avg = (parms->min+parms->max)/2;
|
||||
parms->range = parms->max - parms->avg;
|
||||
parms->diff = parms->max - parms->min;
|
||||
@@ -120,15 +137,6 @@ static char evdev_convert_value_byte(struct input_event *ev, struct input_device
|
||||
return (ev->value - parms->flat - parms->min) * UCHAR_MAX / (parms->diff - parms->flat);
|
||||
}
|
||||
|
||||
static int evdev_convert_value_direction(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms, bool reverse) {
|
||||
if (ev->value > (parms->avg+parms->range/4))
|
||||
return reverse?-1:1;
|
||||
else if (ev->value < (parms->avg-parms->range/4))
|
||||
return reverse?1:-1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool evdev_handle_event(struct input_event *ev, struct input_device *dev) {
|
||||
bool gamepadModified = false;
|
||||
|
||||
@@ -195,6 +203,8 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
} else {
|
||||
int mouseCode = 0;
|
||||
short gamepadCode = 0;
|
||||
int index = dev->key_map[ev->code - BTN_MISC];
|
||||
|
||||
switch (ev->code) {
|
||||
case BTN_LEFT:
|
||||
mouseCode = BUTTON_LEFT;
|
||||
@@ -206,35 +216,35 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
mouseCode = BUTTON_RIGHT;
|
||||
break;
|
||||
default:
|
||||
if (ev->code == dev->map.btn_south)
|
||||
if (index == dev->map->btn_a)
|
||||
gamepadCode = A_FLAG;
|
||||
else if (ev->code == dev->map.btn_west)
|
||||
else if (index == dev->map->btn_x)
|
||||
gamepadCode = X_FLAG;
|
||||
else if (ev->code == dev->map.btn_north)
|
||||
else if (index == dev->map->btn_y)
|
||||
gamepadCode = Y_FLAG;
|
||||
else if (ev->code == dev->map.btn_east)
|
||||
else if (index == dev->map->btn_b)
|
||||
gamepadCode = B_FLAG;
|
||||
else if (ev->code == dev->map.btn_dpad_up)
|
||||
else if (index == dev->map->btn_dpup)
|
||||
gamepadCode = UP_FLAG;
|
||||
else if (ev->code == dev->map.btn_dpad_down)
|
||||
else if (index == dev->map->btn_dpdown)
|
||||
gamepadCode = DOWN_FLAG;
|
||||
else if (ev->code == dev->map.btn_dpad_right)
|
||||
else if (index == dev->map->btn_dpright)
|
||||
gamepadCode = RIGHT_FLAG;
|
||||
else if (ev->code == dev->map.btn_dpad_left)
|
||||
else if (index == dev->map->btn_dpleft)
|
||||
gamepadCode = LEFT_FLAG;
|
||||
else if (ev->code == dev->map.btn_thumbl)
|
||||
else if (index == dev->map->btn_leftstick)
|
||||
gamepadCode = LS_CLK_FLAG;
|
||||
else if (ev->code == dev->map.btn_thumbr)
|
||||
else if (index == dev->map->btn_rightstick)
|
||||
gamepadCode = RS_CLK_FLAG;
|
||||
else if (ev->code == dev->map.btn_tl)
|
||||
else if (index == dev->map->btn_leftshoulder)
|
||||
gamepadCode = LB_FLAG;
|
||||
else if (ev->code == dev->map.btn_tr)
|
||||
else if (index == dev->map->btn_rightshoulder)
|
||||
gamepadCode = RB_FLAG;
|
||||
else if (ev->code == dev->map.btn_start)
|
||||
else if (index == dev->map->btn_start)
|
||||
gamepadCode = PLAY_FLAG;
|
||||
else if (ev->code == dev->map.btn_select)
|
||||
else if (index == dev->map->btn_back)
|
||||
gamepadCode = BACK_FLAG;
|
||||
else if (ev->code == dev->map.btn_mode)
|
||||
else if (index == dev->map->btn_guide)
|
||||
gamepadCode = SPECIAL_FLAG;
|
||||
}
|
||||
|
||||
@@ -248,9 +258,9 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
dev->buttonFlags |= gamepadCode;
|
||||
else
|
||||
dev->buttonFlags &= ~gamepadCode;
|
||||
} else if (ev->code == dev->map.btn_tl2)
|
||||
} else if (index == dev->map->btn_lefttrigger)
|
||||
dev->leftTrigger = ev->value?UCHAR_MAX:0;
|
||||
else if (ev->code == dev->map.btn_tr2)
|
||||
else if (index == dev->map->btn_righttrigger)
|
||||
dev->rightTrigger = ev->value?UCHAR_MAX:0;
|
||||
else {
|
||||
fprintf(stderr, "Unmapped button: %d\n", ev->code);
|
||||
@@ -274,46 +284,46 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
break;
|
||||
case EV_ABS:
|
||||
gamepadModified = true;
|
||||
if (ev->code == dev->map.abs_x)
|
||||
dev->leftStickX = evdev_convert_value(ev, dev, &dev->xParms, dev->map.reverse_x);
|
||||
else if (ev->code == dev->map.abs_y)
|
||||
dev->leftStickY = evdev_convert_value(ev, dev, &dev->yParms, dev->map.reverse_y);
|
||||
else if (ev->code == dev->map.abs_rx)
|
||||
dev->rightStickX = evdev_convert_value(ev, dev, &dev->rxParms, dev->map.reverse_rx);
|
||||
else if (ev->code == dev->map.abs_ry)
|
||||
dev->rightStickY = evdev_convert_value(ev, dev, &dev->ryParms, dev->map.reverse_ry);
|
||||
else if (ev->code == dev->map.abs_z)
|
||||
dev->leftTrigger = evdev_convert_value_byte(ev, dev, &dev->zParms);
|
||||
else if (ev->code == dev->map.abs_rz)
|
||||
dev->rightTrigger = evdev_convert_value_byte(ev, dev, &dev->rzParms);
|
||||
else if (ev->code == dev->map.abs_dpad_x) {
|
||||
int dir = evdev_convert_value_direction(ev, dev, &dev->dpadxParms, dev->map.reverse_dpad_x);
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else {
|
||||
dev->buttonFlags &= ~RIGHT_FLAG;
|
||||
dev->buttonFlags |= LEFT_FLAG;
|
||||
}
|
||||
} else if (ev->code == dev->map.abs_dpad_y) {
|
||||
int dir = evdev_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_dpad_y);
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags |= UP_FLAG;
|
||||
}
|
||||
} else
|
||||
gamepadModified = false;
|
||||
int index = dev->abs_map[ev->code];
|
||||
int hat_index = (ev->code - ABS_HAT0X) / 2;
|
||||
int har_dir_index = (ev->code - ABS_HAT0X) % 2;
|
||||
|
||||
break;
|
||||
switch (ev->code) {
|
||||
case ABS_HAT0X:
|
||||
case ABS_HAT0Y:
|
||||
case ABS_HAT1X:
|
||||
case ABS_HAT1Y:
|
||||
case ABS_HAT2X:
|
||||
case ABS_HAT2Y:
|
||||
case ABS_HAT3X:
|
||||
case ABS_HAT3Y:
|
||||
dev->hats_state[hat_index][har_dir_index] = ev->value < 0 ? 0 : (ev->value == 0 ? 1 : 2);
|
||||
int hat_state = hat_constants[dev->hats_state[hat_index][0]][dev->hats_state[hat_index][1]];
|
||||
if (hat_index == dev->map->hat_dpup)
|
||||
set_hat(dev->buttonFlags, UP_FLAG, hat_state, dev->map->hat_dir_dpup);
|
||||
if (hat_index == dev->map->hat_dpdown)
|
||||
set_hat(dev->buttonFlags, DOWN_FLAG, hat_state, dev->map->hat_dir_dpdown);
|
||||
if (hat_index == dev->map->hat_dpright)
|
||||
set_hat(dev->buttonFlags, HAT_RIGHT, hat_state, dev->map->hat_dir_dpright);
|
||||
if (hat_index == dev->map->hat_dpleft)
|
||||
set_hat(dev->buttonFlags, HAT_LEFT, hat_state, dev->map->hat_dir_dpleft);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (index == dev->map->abs_leftx)
|
||||
dev->leftStickX = evdev_convert_value(ev, dev, &dev->xParms, dev->map->reverse_leftx);
|
||||
else if (index == dev->map->abs_lefty)
|
||||
dev->leftStickY = evdev_convert_value(ev, dev, &dev->yParms, !dev->map->reverse_lefty);
|
||||
else if (index == dev->map->abs_rightx)
|
||||
dev->rightStickX = evdev_convert_value(ev, dev, &dev->rxParms, dev->map->reverse_rightx);
|
||||
else if (index == dev->map->abs_righty)
|
||||
dev->rightStickY = evdev_convert_value(ev, dev, &dev->ryParms, !dev->map->reverse_righty);
|
||||
else if (index == dev->map->abs_lefttrigger)
|
||||
dev->leftTrigger = evdev_convert_value_byte(ev, dev, &dev->zParms);
|
||||
else if (index == dev->map->abs_righttrigger)
|
||||
dev->rightTrigger = evdev_convert_value_byte(ev, dev, &dev->rzParms);
|
||||
else
|
||||
gamepadModified = false;
|
||||
}
|
||||
|
||||
dev->gamepadModified |= gamepadModified;
|
||||
@@ -380,7 +390,7 @@ static int evdev_handle(int fd) {
|
||||
return LOOP_OK;
|
||||
}
|
||||
|
||||
void evdev_create(const char* device, char* mapFile) {
|
||||
void evdev_create(const char* device, struct mapping* mappings) {
|
||||
int fd = open(device, O_RDONLY|O_NONBLOCK);
|
||||
if (fd <= 0) {
|
||||
fprintf(stderr, "Failed to open device %s\n", device);
|
||||
@@ -388,6 +398,31 @@ void evdev_create(const char* device, char* mapFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct libevdev *evdev = libevdev_new();
|
||||
libevdev_set_fd(evdev, fd);
|
||||
|
||||
int16_t guid[8] = {0};
|
||||
guid[0] = int16_to_le(libevdev_get_id_bustype(evdev));
|
||||
guid[2] = int16_to_le(libevdev_get_id_vendor(evdev));
|
||||
guid[4] = int16_to_le(libevdev_get_id_product(evdev));
|
||||
guid[6] = int16_to_le(libevdev_get_id_version(evdev));
|
||||
|
||||
char str_guid[33];
|
||||
char* buf = str_guid;
|
||||
for (int i = 0; i < 16; i++)
|
||||
buf += sprintf(buf, "%02x", ((unsigned char*) guid)[i]);
|
||||
|
||||
while (mappings != NULL && strncmp(str_guid, mappings->guid, 32) != 0)
|
||||
mappings = mappings->next;
|
||||
|
||||
if (mappings == NULL) {
|
||||
fprintf(stderr, "No mapping available for %s\n", device);
|
||||
fflush(stderr);
|
||||
close(fd);
|
||||
libevdev_free(evdev);
|
||||
return;
|
||||
}
|
||||
|
||||
int dev = numDevices;
|
||||
numDevices++;
|
||||
|
||||
@@ -404,21 +439,35 @@ void evdev_create(const char* device, char* mapFile) {
|
||||
|
||||
memset(&devices[dev], 0, sizeof(devices[0]));
|
||||
devices[dev].fd = fd;
|
||||
devices[dev].dev = libevdev_new();
|
||||
libevdev_set_fd(devices[dev].dev, devices[dev].fd);
|
||||
devices[dev].dev = evdev;
|
||||
devices[dev].map = mappings;
|
||||
|
||||
if (mapFile != NULL)
|
||||
mapping_load(mapFile, &(devices[dev].map));
|
||||
int nbuttons = 0;
|
||||
for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
|
||||
if (libevdev_has_event_code(devices[dev].dev, EV_KEY, i))
|
||||
devices[dev].key_map[i - BTN_MISC] = nbuttons++;
|
||||
}
|
||||
for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
|
||||
if (libevdev_has_event_code(devices[dev].dev, EV_KEY, i))
|
||||
devices[dev].key_map[i - BTN_MISC] = nbuttons++;
|
||||
}
|
||||
|
||||
int naxes = 0;
|
||||
for (int i = 0; i < ABS_MAX; ++i) {
|
||||
/* Skip hats */
|
||||
if (i == ABS_HAT0X)
|
||||
i = ABS_HAT3Y;
|
||||
else if (libevdev_has_event_code(devices[dev].dev, EV_ABS, i))
|
||||
devices[dev].abs_map[i] = naxes++;
|
||||
}
|
||||
|
||||
devices[dev].controllerId = -1;
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].xParms), devices[dev].map.abs_x);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].yParms), devices[dev].map.abs_y);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].zParms), devices[dev].map.abs_z);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].rxParms), devices[dev].map.abs_rx);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].ryParms), devices[dev].map.abs_ry);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].rzParms), devices[dev].map.abs_rz);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].dpadxParms), devices[dev].map.abs_dpad_x);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].dpadyParms), devices[dev].map.abs_dpad_y);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].xParms), devices[dev].map->abs_leftx);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].yParms), devices[dev].map->abs_lefty);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].zParms), devices[dev].map->abs_lefttrigger);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].rxParms), devices[dev].map->abs_rightx);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].ryParms), devices[dev].map->abs_righty);
|
||||
evdev_init_parms(&devices[dev], &(devices[dev].rzParms), devices[dev].map->abs_righttrigger);
|
||||
|
||||
if (grabbingDevices) {
|
||||
if (ioctl(fd, EVIOCGRAB, 1) < 0) {
|
||||
@@ -429,85 +478,6 @@ void evdev_create(const char* device, char* mapFile) {
|
||||
loop_add_fd(devices[dev].fd, &evdev_handle, POLLIN);
|
||||
}
|
||||
|
||||
static void evdev_map_key(char* keyName, short* key) {
|
||||
printf("Press %s\n", keyName);
|
||||
currentKey = key;
|
||||
currentAbs = NULL;
|
||||
*key = -1;
|
||||
loop_main();
|
||||
|
||||
usleep(250000);
|
||||
evdev_drain();
|
||||
}
|
||||
|
||||
static void evdev_map_abs(char* keyName, short* abs, bool* reverse) {
|
||||
printf("Move %s\n", keyName);
|
||||
currentKey = NULL;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*abs = -1;
|
||||
loop_main();
|
||||
|
||||
usleep(250000);
|
||||
evdev_drain();
|
||||
}
|
||||
|
||||
static void evdev_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
|
||||
printf("Press %s\n", keyName);
|
||||
currentKey = key;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*key = -1;
|
||||
*abs = -1;
|
||||
*currentReverse = false;
|
||||
loop_main();
|
||||
|
||||
usleep(250000);
|
||||
evdev_drain();
|
||||
}
|
||||
|
||||
void evdev_map(char* fileName) {
|
||||
struct mapping map;
|
||||
|
||||
handler = evdev_handle_mapping_event;
|
||||
|
||||
evdev_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x));
|
||||
evdev_map_abs("Left Stick Up", &(map.abs_y), &(map.reverse_y));
|
||||
evdev_map_key("Left Stick Button", &(map.btn_thumbl));
|
||||
|
||||
evdev_map_abs("Right Stick Right", &(map.abs_rx), &(map.reverse_rx));
|
||||
evdev_map_abs("Right Stick Up", &(map.abs_ry), &(map.reverse_ry));
|
||||
evdev_map_key("Right Stick Button", &(map.btn_thumbr));
|
||||
|
||||
evdev_map_abskey("D-Pad Right", &(map.btn_dpad_right), &(map.abs_dpad_x), &(map.reverse_dpad_x));
|
||||
if (map.btn_dpad_right >= 0)
|
||||
evdev_map_key("D-Pad Left", &(map.btn_dpad_left));
|
||||
else
|
||||
map.btn_dpad_left = -1;
|
||||
|
||||
evdev_map_abskey("D-Pad Down", &(map.btn_dpad_down), &(map.abs_dpad_y), &(map.reverse_dpad_y));
|
||||
if (map.btn_dpad_down >= 0)
|
||||
evdev_map_key("D-Pad Up", &(map.btn_dpad_up));
|
||||
else
|
||||
map.btn_dpad_up = -1;
|
||||
|
||||
evdev_map_key("Button X (1)", &(map.btn_west));
|
||||
evdev_map_key("Button A (2)", &(map.btn_south));
|
||||
evdev_map_key("Button B (3)", &(map.btn_east));
|
||||
evdev_map_key("Button Y (4)", &(map.btn_north));
|
||||
evdev_map_key("Back Button", &(map.btn_select));
|
||||
evdev_map_key("Start Button", &(map.btn_start));
|
||||
evdev_map_key("Special Button", &(map.btn_mode));
|
||||
|
||||
bool ignored;
|
||||
evdev_map_abskey("Left Trigger", &(map.btn_tl2), &(map.abs_z), &ignored);
|
||||
evdev_map_abskey("Right Trigger", &(map.btn_tr2), &(map.abs_rz), &ignored);
|
||||
|
||||
evdev_map_key("Left Bumper", &(map.btn_tl));
|
||||
evdev_map_key("Right Bumper", &(map.btn_tr));
|
||||
mapping_save(fileName, &map);
|
||||
}
|
||||
|
||||
void evdev_start() {
|
||||
// After grabbing, the only way to quit via the keyboard
|
||||
// is via the special key combo that the input handling
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,9 +17,8 @@
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
void evdev_create(const char* device, char* mapFile);
|
||||
void evdev_create(const char* device, struct mapping* mappings);
|
||||
void evdev_loop();
|
||||
void evdev_map(char* fileName);
|
||||
|
||||
void evdev_init();
|
||||
void evdev_start();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,10 +23,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define write_config(fd, key, value) fprintf(fd, "%s = %hd\n", key, value)
|
||||
#define write_config_bool(fd, key, value) fprintf(fd, "%s = %s\n", key, value?"true":"false");
|
||||
|
||||
void mapping_load(char* fileName, struct mapping* map) {
|
||||
struct mapping* mapping_load(char* fileName) {
|
||||
struct mapping* mappings = NULL;
|
||||
struct mapping* map = NULL;
|
||||
FILE* fd = fopen(fileName, "r");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "Can't open mapping file: %s\n", fileName);
|
||||
@@ -36,135 +35,117 @@ void mapping_load(char* fileName, struct mapping* map) {
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
while (getline(&line, &len, fd) != -1) {
|
||||
char *key = NULL, *value = NULL;
|
||||
if (sscanf(line, "%ms = %ms", &key, &value) == 2) {
|
||||
long int_value = strtol(value, NULL, 10);
|
||||
if (strcmp("abs_x", key) == 0)
|
||||
map->abs_x = int_value;
|
||||
else if (strcmp("abs_y", key) == 0)
|
||||
map->abs_y = int_value;
|
||||
else if (strcmp("abs_z", key) == 0)
|
||||
map->abs_z = int_value;
|
||||
else if (strcmp("abs_rx", key) == 0)
|
||||
map->abs_rx = int_value;
|
||||
else if (strcmp("abs_ry", key) == 0)
|
||||
map->abs_ry = int_value;
|
||||
else if (strcmp("abs_rz", key) == 0)
|
||||
map->abs_rz = int_value;
|
||||
else if (strcmp("abs_deadzone", key) == 0)
|
||||
map->abs_deadzone = int_value;
|
||||
else if (strcmp("abs_dpad_x", key) == 0)
|
||||
map->abs_dpad_x = int_value;
|
||||
else if (strcmp("abs_dpad_y", key) == 0)
|
||||
map->abs_dpad_y = int_value;
|
||||
else if (strcmp("btn_south", key) == 0)
|
||||
map->btn_south = int_value;
|
||||
else if (strcmp("btn_north", key) == 0)
|
||||
map->btn_north = int_value;
|
||||
else if (strcmp("btn_east", key) == 0)
|
||||
map->btn_east = int_value;
|
||||
else if (strcmp("btn_west", key) == 0)
|
||||
map->btn_west = int_value;
|
||||
else if (strcmp("btn_select", key) == 0)
|
||||
map->btn_select = int_value;
|
||||
else if (strcmp("btn_start", key) == 0)
|
||||
map->btn_start = int_value;
|
||||
else if (strcmp("btn_mode", key) == 0)
|
||||
map->btn_mode = int_value;
|
||||
else if (strcmp("btn_thumbl", key) == 0)
|
||||
map->btn_thumbl = int_value;
|
||||
else if (strcmp("btn_thumbr", key) == 0)
|
||||
map->btn_thumbr = int_value;
|
||||
else if (strcmp("btn_tl", key) == 0)
|
||||
map->btn_tl = int_value;
|
||||
else if (strcmp("btn_tr", key) == 0)
|
||||
map->btn_tr = int_value;
|
||||
else if (strcmp("btn_tl2", key) == 0)
|
||||
map->btn_tl2 = int_value;
|
||||
else if (strcmp("btn_tr2", key) == 0)
|
||||
map->btn_tr2 = int_value;
|
||||
else if (strcmp("btn_dpad_up", key) == 0)
|
||||
map->btn_dpad_up = int_value;
|
||||
else if (strcmp("btn_dpad_down", key) == 0)
|
||||
map->btn_dpad_down = int_value;
|
||||
else if (strcmp("btn_dpad_left", key) == 0)
|
||||
map->btn_dpad_left = int_value;
|
||||
else if (strcmp("btn_dpad_right", key) == 0)
|
||||
map->btn_dpad_right = int_value;
|
||||
else if (strcmp("reverse_x", key) == 0)
|
||||
map->reverse_x = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_y", key) == 0)
|
||||
map->reverse_y = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_rx", key) == 0)
|
||||
map->reverse_rx = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_ry", key) == 0)
|
||||
map->reverse_ry = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_x", key) == 0)
|
||||
map->reverse_dpad_x = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_y", key) == 0)
|
||||
map->reverse_dpad_y = strcmp("true", value) == 0;
|
||||
else
|
||||
fprintf(stderr, "Can't map (%s)\n", key);
|
||||
}
|
||||
if (key != NULL)
|
||||
free(key);
|
||||
char* strpoint;
|
||||
char* guid = strtok_r(line, ",", &strpoint);
|
||||
char* name = strtok_r(NULL, ",", &strpoint);
|
||||
if (guid == NULL || name == NULL)
|
||||
continue;
|
||||
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
struct mapping* newmap = malloc(sizeof(struct mapping));
|
||||
if (newmap == NULL) {
|
||||
fprintf(stderr, "Not enough memory");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (mappings == NULL)
|
||||
mappings = newmap;
|
||||
else
|
||||
map->next = newmap;
|
||||
|
||||
map = newmap;
|
||||
|
||||
strncpy(map->guid, guid, sizeof(map->guid));
|
||||
strncpy(map->name, name, sizeof(map->name));
|
||||
|
||||
char* option;
|
||||
while ((option = strtok_r(NULL, ",", &strpoint)) != NULL) {
|
||||
char *key = NULL, *value = NULL;
|
||||
int ret;
|
||||
if ((ret = sscanf(option, "%m[^:]:%ms", &key, &value)) == 2) {
|
||||
int int_value, direction_value;
|
||||
char flag = NULL;
|
||||
if (strcmp("platform", key) == 0)
|
||||
strncpy(map->platform, value, sizeof(map->platform));
|
||||
else if (sscanf(value, "b%d", &int_value) == 1) {
|
||||
if (strcmp("a", key) == 0)
|
||||
map->btn_a = int_value;
|
||||
else if (strcmp("y", key) == 0)
|
||||
map->btn_y = int_value;
|
||||
else if (strcmp("x", key) == 0)
|
||||
map->btn_x = int_value;
|
||||
else if (strcmp("b", key) == 0)
|
||||
map->btn_b = int_value;
|
||||
else if (strcmp("back", key) == 0)
|
||||
map->btn_back = int_value;
|
||||
else if (strcmp("start", key) == 0)
|
||||
map->btn_start = int_value;
|
||||
else if (strcmp("guide", key) == 0)
|
||||
map->btn_guide = int_value;
|
||||
else if (strcmp("dpup", key) == 0)
|
||||
map->btn_dpup = int_value;
|
||||
else if (strcmp("dpdown", key) == 0)
|
||||
map->btn_dpdown = int_value;
|
||||
else if (strcmp("dpleft", key) == 0)
|
||||
map->btn_dpleft = int_value;
|
||||
else if (strcmp("dpright", key) == 0)
|
||||
map->btn_dpright = int_value;
|
||||
else if (strcmp("leftstick", key) == 0)
|
||||
map->btn_leftstick = int_value;
|
||||
else if (strcmp("rightstick", key) == 0)
|
||||
map->btn_rightstick = int_value;
|
||||
else if (strcmp("leftshoulder", key) == 0)
|
||||
map->btn_leftshoulder = int_value;
|
||||
else if (strcmp("rightshoulder", key) == 0)
|
||||
map->btn_rightshoulder = int_value;
|
||||
else if (strcmp("lefttrigger", key) == 0)
|
||||
map->btn_lefttrigger = int_value;
|
||||
else if (strcmp("righttrigger", key) == 0)
|
||||
map->btn_righttrigger = int_value;
|
||||
} else if (sscanf(value, "a%d%c", &int_value, &flag) >= 1) {
|
||||
if (strcmp("leftx", key) == 0) {
|
||||
map->abs_leftx = int_value;
|
||||
map->reverse_leftx = flag == '~';
|
||||
} else if (strcmp("lefty", key) == 0) {
|
||||
map->abs_lefty = int_value;
|
||||
map->reverse_lefty = flag == '~';
|
||||
} else if (strcmp("rightx", key) == 0) {
|
||||
map->abs_rightx = int_value;
|
||||
map->reverse_rightx = flag == '~';
|
||||
} else if (strcmp("righty", key) == 0) {
|
||||
map->abs_righty = int_value;
|
||||
map->reverse_righty = flag == '~';
|
||||
} else if (strcmp("lefttrigger", key) == 0)
|
||||
map->abs_lefttrigger = int_value;
|
||||
else if (strcmp("righttrigger", key) == 0)
|
||||
map->abs_righttrigger = int_value;
|
||||
} else if (sscanf(value, "h%d.%d", &int_value, &direction_value) == 2) {
|
||||
if (strcmp("dpright", key) == 0) {
|
||||
map->hat_dpright = int_value;
|
||||
map->hat_dir_dpright = direction_value;
|
||||
} else if (strcmp("dpleft", key) == 0) {
|
||||
map->hat_dpleft = int_value;
|
||||
map->hat_dir_dpleft = direction_value;
|
||||
} else if (strcmp("dpup", key) == 0) {
|
||||
map->hat_dpup = int_value;
|
||||
map->hat_dir_dpup = direction_value;
|
||||
} else if (strcmp("dpdown", key) == 0) {
|
||||
map->hat_dpdown = int_value;
|
||||
map->hat_dir_dpdown = direction_value;
|
||||
}
|
||||
} else
|
||||
fprintf(stderr, "Can't map (%s)\n", option);
|
||||
} else if (ret == 0 && option[0] != '\n')
|
||||
fprintf(stderr, "Can't map (%s)\n", option);
|
||||
|
||||
if (key != NULL)
|
||||
free(key);
|
||||
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
}
|
||||
map->guid[32] = '\0';
|
||||
map->name[256] = '\0';
|
||||
map->platform[32] = '\0';
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
void mapping_save(char* fileName, struct mapping* map) {
|
||||
FILE* fd = fopen(fileName, "w");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "Can't open mapping file: %s\n", fileName);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
write_config(fd, "abs_x", map->abs_x);
|
||||
write_config(fd, "abs_y", map->abs_y);
|
||||
write_config(fd, "abs_z", map->abs_z);
|
||||
|
||||
write_config_bool(fd, "reverse_x", map->reverse_x);
|
||||
write_config_bool(fd, "reverse_y", map->reverse_y);
|
||||
|
||||
write_config(fd, "abs_rx", map->abs_rx);
|
||||
write_config(fd, "abs_ry", map->abs_ry);
|
||||
write_config(fd, "abs_rz", map->abs_rz);
|
||||
|
||||
write_config_bool(fd, "reverse_rx", map->reverse_rx);
|
||||
write_config_bool(fd, "reverse_ry", map->reverse_ry);
|
||||
|
||||
write_config(fd, "abs_deadzone", map->abs_deadzone);
|
||||
|
||||
write_config(fd, "abs_dpad_x", map->abs_dpad_x);
|
||||
write_config(fd, "abs_dpad_y", map->abs_dpad_y);
|
||||
|
||||
write_config_bool(fd, "reverse_dpad_x", map->reverse_dpad_x);
|
||||
write_config_bool(fd, "reverse_dpad_y", map->reverse_dpad_y);
|
||||
|
||||
write_config(fd, "btn_north", map->btn_north);
|
||||
write_config(fd, "btn_east", map->btn_east);
|
||||
write_config(fd, "btn_south", map->btn_south);
|
||||
write_config(fd, "btn_west", map->btn_west);
|
||||
|
||||
write_config(fd, "btn_select", map->btn_select);
|
||||
write_config(fd, "btn_start", map->btn_start);
|
||||
write_config(fd, "btn_mode", map->btn_mode);
|
||||
|
||||
write_config(fd, "btn_thumbl", map->btn_thumbl);
|
||||
write_config(fd, "btn_thumbr", map->btn_thumbr);
|
||||
|
||||
write_config(fd, "btn_tl", map->btn_tl);
|
||||
write_config(fd, "btn_tr", map->btn_tr);
|
||||
write_config(fd, "btn_tl2", map->btn_tl2);
|
||||
write_config(fd, "btn_tr2", map->btn_tr2);
|
||||
|
||||
write_config(fd, "btn_dpad_up", map->btn_dpad_up);
|
||||
write_config(fd, "btn_dpad_down", map->btn_dpad_down);
|
||||
write_config(fd, "btn_dpad_left", map->btn_dpad_left);
|
||||
write_config(fd, "btn_dpad_right", map->btn_dpad_right);
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,27 +17,34 @@
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct mapping {
|
||||
short abs_x, abs_y, abs_z;
|
||||
short abs_rx, abs_ry, abs_rz;
|
||||
char guid[33];
|
||||
char platform[33];
|
||||
char name[257];
|
||||
|
||||
bool reverse_x, reverse_y;
|
||||
bool reverse_rx, reverse_ry;
|
||||
bool reverse_leftx, reverse_lefty;
|
||||
bool reverse_rightx, reverse_righty;
|
||||
|
||||
short abs_leftx, abs_lefty;
|
||||
short abs_rightx, abs_righty;
|
||||
|
||||
short abs_deadzone;
|
||||
short hat_dpright, hat_dpleft, hat_dpup, hat_dpdown;
|
||||
short hat_dir_dpright, hat_dir_dpleft, hat_dir_dpup, hat_dir_dpdown;
|
||||
short btn_dpup, btn_dpdown, btn_dpleft, btn_dpright;
|
||||
|
||||
short btn_a, btn_x, btn_y, btn_b;
|
||||
short btn_back, btn_start, btn_guide;
|
||||
short btn_leftstick, btn_rightstick;
|
||||
short btn_leftshoulder, btn_rightshoulder;
|
||||
|
||||
short abs_lefttrigger, abs_righttrigger;
|
||||
short btn_lefttrigger, btn_righttrigger;
|
||||
|
||||
short abs_dpad_x, abs_dpad_y;
|
||||
bool reverse_dpad_x, reverse_dpad_y;
|
||||
|
||||
short btn_south, btn_east, btn_north, btn_west;
|
||||
short btn_select, btn_start, btn_mode;
|
||||
short btn_thumbl, btn_thumbr;
|
||||
short btn_tl, btn_tr, btn_tl2, btn_tr2;
|
||||
|
||||
short btn_dpad_up, btn_dpad_down, btn_dpad_left, btn_dpad_right;
|
||||
struct mapping* next;
|
||||
};
|
||||
|
||||
void mapping_load(char* fileName, struct mapping* map);
|
||||
void mapping_save(char* fileName, struct mapping* map);
|
||||
struct mapping* mapping_load(char* fileName);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -43,11 +43,11 @@ static GAMEPAD_STATE gamepads[4];
|
||||
static int keyboard_modifiers;
|
||||
static int activeGamepadMask = 0;
|
||||
|
||||
void sdlinput_init() {
|
||||
void sdlinput_init(char* mappings) {
|
||||
memset(gamepads, 0, sizeof(gamepads));
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
|
||||
SDL_GameControllerAddMappingsFromFile(mappings);
|
||||
|
||||
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
@@ -103,10 +103,20 @@ int sdlinput_handle_event(SDL_Event* event) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
button = event->key.keysym.sym;
|
||||
if (button >= (0x40000000 + 0x39) && button < (0x40000000 + 0x39 + sizeof(keyCodes)))
|
||||
button = keyCodes[button - 0x40000039];
|
||||
else if (button >= 0x61)
|
||||
if (button >= 0x21 && button <= 0x2f)
|
||||
button = keyCodes1[button - 0x21];
|
||||
else if (button >= 0x3a && button <= 0x40)
|
||||
button = keyCodes2[button - 0x3a];
|
||||
else if (button >= 0x5b && button <= 0x60)
|
||||
button = keyCodes3[button - 0x5b];
|
||||
else if (button >= 0x40000039 && button < 0x40000039 + sizeof(keyCodes4))
|
||||
button = keyCodes4[button - 0x40000039];
|
||||
else if (button >= 0x400000E0 && button <= 0x400000E7)
|
||||
button = keyCodes5[button - 0x400000E0];
|
||||
else if (button >= 0x61 && button <= 0x7a)
|
||||
button -= 0x20;
|
||||
else if (button == 0x7f)
|
||||
button = 0x2e;
|
||||
|
||||
int modifier = 0;
|
||||
switch (event->key.keysym.sym) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,7 +22,44 @@
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
|
||||
static const short keyCodes[] = {
|
||||
static const short keyCodes1[] = {
|
||||
0, //SDLK_EXCLAIM
|
||||
0, //SDLK_QUOTEDBL
|
||||
0, //SDLK_HASH
|
||||
0, //SDLK_DOLLAR
|
||||
0, //SDLK_PERCENT
|
||||
0, //SDLK_AMPERSAND
|
||||
0xDE, //SDLK_QUOTE
|
||||
0, //SDLK_LEFTPAREN
|
||||
0, //SDLK_RIGHTPAREN
|
||||
0, //SDLK_ASTERISK
|
||||
0, //SDLK_PLUS
|
||||
0xBC, //SDLK_COMMA
|
||||
0xBD, //SDLK_MINUS
|
||||
0xBE, //SDLK_PERIOD
|
||||
0xBF, //SDLK_SLASH
|
||||
};
|
||||
|
||||
static const short keyCodes2[] = {
|
||||
0, //SDLK_COLON
|
||||
0xBA, //SDLK_SEMICOLON
|
||||
0, //SDLK_LESS
|
||||
0xBB, //SDLK_EQUALS
|
||||
0, //SDLK_GREATER
|
||||
0, //SDLK_QUESTION
|
||||
0, //SDLK_AT
|
||||
};
|
||||
|
||||
static const short keyCodes3[] = {
|
||||
0xDB, //SDLK_LEFTBRACKET
|
||||
0xDC, //SDLK_BACKSLASH
|
||||
0xDD, //SDLK_RIGHTBRACKET
|
||||
0, //SDLK_CARET
|
||||
0, //SDLK_UNDERSCORE
|
||||
0xC0, //SDLK_BACKQUOTE
|
||||
};
|
||||
|
||||
static const short keyCodes4[] = {
|
||||
0x14, //SDLK_CAPSLOCK
|
||||
0x70, //SDLK_F1
|
||||
0x71, //SDLK_F2
|
||||
@@ -51,7 +88,18 @@ static const short keyCodes[] = {
|
||||
0x26, //SDLK_UP
|
||||
};
|
||||
|
||||
void sdlinput_init();
|
||||
static const short keyCodes5[] = {
|
||||
0x11, //SDLK_LCTRL
|
||||
0x10, //SDLK_LSHIFT
|
||||
0x12, //SDLK_LALT
|
||||
0x5B, //SDLK_LGUI
|
||||
0x11, //SDLK_LRCTRL
|
||||
0x10, //SDLK_RSHIFT
|
||||
0x12, //SDLK_RALT
|
||||
0x5C, //SDLK_RGUI
|
||||
};
|
||||
|
||||
void sdlinput_init(char* mappings);
|
||||
int sdlinput_handle_event(SDL_Event* event);
|
||||
|
||||
#endif /* HAVE_SDL */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "../loop.h"
|
||||
|
||||
#include "udev.h"
|
||||
#include "evdev.h"
|
||||
|
||||
#include <libudev.h>
|
||||
@@ -31,7 +32,7 @@
|
||||
#include <poll.h>
|
||||
|
||||
static bool autoadd;
|
||||
static char* defaultMapfile;
|
||||
static struct mapping* defaultMappings;
|
||||
|
||||
static struct udev *udev;
|
||||
static struct udev_monitor *udev_mon;
|
||||
@@ -45,7 +46,7 @@ static int udev_handle(int fd) {
|
||||
const char *devnode = udev_device_get_devnode(dev);
|
||||
int id;
|
||||
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
||||
evdev_create(devnode, defaultMapfile);
|
||||
evdev_create(devnode, defaultMappings);
|
||||
}
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
@@ -53,7 +54,7 @@ static int udev_handle(int fd) {
|
||||
return LOOP_OK;
|
||||
}
|
||||
|
||||
void udev_init(bool autoload, char* mapfile) {
|
||||
void udev_init(bool autoload, struct mapping* mappings) {
|
||||
udev = udev_new();
|
||||
if (!udev) {
|
||||
fprintf(stderr, "Can't create udev\n");
|
||||
@@ -74,7 +75,7 @@ void udev_init(bool autoload, char* mapfile) {
|
||||
const char *devnode = udev_device_get_devnode(dev);
|
||||
int id;
|
||||
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
|
||||
evdev_create(devnode, mapfile);
|
||||
evdev_create(devnode, mappings);
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
@@ -86,7 +87,7 @@ void udev_init(bool autoload, char* mapfile) {
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
|
||||
udev_monitor_enable_receiving(udev_mon);
|
||||
|
||||
defaultMapfile = mapfile;
|
||||
defaultMappings = mappings;
|
||||
|
||||
int udev_fd = udev_monitor_get_fd(udev_mon);
|
||||
loop_add_fd(udev_fd, &udev_handle, POLLIN);
|
||||
|
||||
@@ -17,5 +17,7 @@
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
void udev_init(bool autoload, char* mapfile);
|
||||
#include "mapping.h"
|
||||
|
||||
void udev_init(bool autoload, struct mapping* mappings);
|
||||
void evdev_destroy();
|
||||
|
||||
39
src/main.c
39
src/main.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015, 2016 Iwan Timmer
|
||||
* Copyright (C) 2015-2017 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "platform.h"
|
||||
#include "sdl.h"
|
||||
|
||||
#include "input/mapping.h"
|
||||
#include "input/evdev.h"
|
||||
#include "input/udev.h"
|
||||
#include "input/cec.h"
|
||||
@@ -119,7 +120,6 @@ static void help() {
|
||||
printf("Usage: moonlight [action] (options) [host]\n");
|
||||
printf(" moonlight [configfile]\n");
|
||||
printf("\n Actions\n\n");
|
||||
printf("\tmap\t\t\tCreate mapping file for gamepad\n");
|
||||
printf("\tpair\t\t\tPair device with computer\n");
|
||||
printf("\tunpair\t\t\tUnpair device with computer\n");
|
||||
printf("\tstream\t\t\tStream computer to device\n");
|
||||
@@ -146,13 +146,13 @@ static void help() {
|
||||
printf("\t-localaudio\t\tPlay audio locally\n");
|
||||
printf("\t-surround\t\tStream 5.1 surround sound (requires GFE 2.7)\n");
|
||||
printf("\t-keydir <directory>\tLoad encryption keys from directory\n");
|
||||
printf("\t-mapping <file>\t\tUse <file> as gamepad mappings configuration file\n");
|
||||
#ifdef HAVE_SDL
|
||||
printf("\n Video options (SDL Only)\n\n");
|
||||
printf("\t-windowed\t\tDisplay screen in a window\n");
|
||||
#endif
|
||||
#ifdef HAVE_EMBEDDED
|
||||
printf("\n I/O options\n\n");
|
||||
printf("\t-mapping <file>\t\tUse <file> as gamepad mapping configuration file (use before -input)\n");
|
||||
printf("\t-input <device>\t\tUse <device> as input. Can be used multiple times\n");
|
||||
printf("\t-audio <device>\t\tUse <device> as audio output device\n");
|
||||
printf("\t-forcehw \t\tTry to use video hardware acceleration\n");
|
||||
@@ -181,21 +181,11 @@ int main(int argc, char* argv[]) {
|
||||
if (system == 0) {
|
||||
fprintf(stderr, "Platform '%s' not found\n", config.platform);
|
||||
exit(-1);
|
||||
} else if (system == SDL && audio_device != NULL) {
|
||||
fprintf(stderr, "You can't select a audio device for SDL\n");
|
||||
exit(-1);
|
||||
}
|
||||
config.stream.supportsHevc = config.codec != CODEC_H264 && (config.codec == CODEC_HEVC || platform_supports_hevc(system));
|
||||
|
||||
if (strcmp("map", config.action) == 0) {
|
||||
if (config.address == NULL) {
|
||||
perror("No filename for mapping");
|
||||
exit(-1);
|
||||
}
|
||||
udev_init(!inputAdded, config.mapping);
|
||||
for (int i=0;i<config.inputsCount;i++)
|
||||
evdev_create(config.inputs[i].path, config.inputs[i].mapping);
|
||||
|
||||
evdev_map(config.address);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (config.address == NULL) {
|
||||
config.address = malloc(MAX_ADDRESS_SIZE);
|
||||
@@ -245,20 +235,29 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp("stream", config.action) == 0) {
|
||||
pair_check(&server);
|
||||
if (IS_EMBEDDED(system)) {
|
||||
struct mapping* mappings = mapping_load(config.mapping);
|
||||
|
||||
for (int i=0;i<config.inputsCount;i++) {
|
||||
printf("Add input %s (mapping %s)...\n", config.inputs[i].path, config.inputs[i].mapping);
|
||||
evdev_create(config.inputs[i].path, config.inputs[i].mapping);
|
||||
printf("Add input %s...\n", config.inputs[i]);
|
||||
evdev_create(config.inputs[i], mappings);
|
||||
}
|
||||
|
||||
udev_init(!inputAdded, config.mapping);
|
||||
udev_init(!inputAdded, mappings);
|
||||
evdev_init();
|
||||
#ifdef HAVE_LIBCEC
|
||||
cec_init();
|
||||
#endif /* HAVE_LIBCEC */
|
||||
}
|
||||
#ifdef HAVE_SDL
|
||||
else if (system == SDL)
|
||||
else if (system == SDL) {
|
||||
if (config.inputsCount > 0) {
|
||||
fprintf(stderr, "You can't select input devices as SDL will automatically use all available controllers\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sdl_init(config.stream.width, config.stream.height, config.fullscreen);
|
||||
sdlinput_init(config.mapping);
|
||||
}
|
||||
#endif
|
||||
|
||||
stream(&server, &config, system);
|
||||
|
||||
@@ -68,8 +68,6 @@ void sdl_init(int width, int height, bool fullscreen) {
|
||||
fprintf(stderr, "Couldn't create mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sdlinput_init();
|
||||
}
|
||||
|
||||
void sdl_loop() {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DECODER_BUFFER_SIZE 92*1024
|
||||
@@ -37,7 +38,7 @@ static void sdl_setup(int videoFormat, int width, int height, int redrawRate, vo
|
||||
if (drFlags & FORCE_HARDWARE_ACCELERATION)
|
||||
avc_flags |= HARDWARE_ACCELERATION;
|
||||
|
||||
if (ffmpeg_init(videoFormat, width, height, avc_flags, SDL_BUFFER_FRAMES, 2) < 0) {
|
||||
if (ffmpeg_init(videoFormat, width, height, avc_flags, SDL_BUFFER_FRAMES, sysconf(_SC_NPROCESSORS_ONLN)) < 0) {
|
||||
fprintf(stderr, "Couldn't initialize video decoding\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -92,5 +93,5 @@ DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl = {
|
||||
.setup = sdl_setup,
|
||||
.cleanup = sdl_cleanup,
|
||||
.submitDecodeUnit = sdl_submit_decode_unit,
|
||||
.capabilities = CAPABILITY_SLICES_PER_FRAME(2) | CAPABILITY_REFERENCE_FRAME_INVALIDATION | CAPABILITY_DIRECT_SUBMIT,
|
||||
.capabilities = CAPABILITY_SLICES_PER_FRAME(4) | CAPABILITY_REFERENCE_FRAME_INVALIDATION | CAPABILITY_DIRECT_SUBMIT,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user