Merge branch 'library' into pc

This commit is contained in:
Iwan Timmer committed 2015-06-28 21:39:13 +02:00
commit 2dd653d22b
26 files changed
+553 -364

No files matched your search

+15 -20
View File
@@ -4,19 +4,11 @@ cmake_minimum_required(VERSION 3.1)
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
aux_source_directory(./src SRC_LIST)
aux_source_directory(./src/input SRC_LIST)
list(APPEND SRC_LIST ./src/video/fake.c)
aux_source_directory(./third_party/moonlight-common-c/limelight-common SRC_LIST)
aux_source_directory(./third_party/moonlight-common-c/limelight-common/OpenAES SRC_LIST)
include_directories(./third_party/moonlight-common-c)
set(MOONLIGHT_DEFINITIONS)
find_package(Threads REQUIRED)
find_package(CURL REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(EXPAT REQUIRED)
find_package(ALSA REQUIRED)
find_package(Opus REQUIRED)
find_package(Broadcom)
@@ -25,18 +17,12 @@ find_package(CEC)
find_package(PkgConfig REQUIRED)
pkg_check_modules(EVDEV REQUIRED libevdev)
pkg_check_modules(AVAHI REQUIRED avahi-client)
pkg_check_modules(UDEV REQUIRED libudev)
pkg_check_modules(SDL sdl2)
pkg_check_modules(AVCODEC libavcodec)
pkg_check_modules(AVUTIL libavutil)
pkg_check_modules(SWSCALE libswscale)
if(CEC_FOUND)
include_directories(./third_party/libcec)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
endif()
if(BROADCOM_FOUND)
aux_source_directory(./third_party/ilclient SRC_LIST)
aux_source_directory(./third_party/h264bitstream SRC_LIST)
@@ -54,28 +40,37 @@ if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND AND SDL_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_SDL)
endif()
add_subdirectory(libgamestream)
add_executable(moonlight ${SRC_LIST})
target_link_libraries(moonlight PUBLIC gamestream)
set_property(TARGET moonlight PROPERTY C_STANDARD 11)
if (CEC_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
target_include_directories(moonlight PRIVATE ./third_party/libcec ${CEC_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${CEC_LIBRARIES})
endif()
if(BROADCOM_FOUND)
include_directories(./third_party/ilclient ./third_party/h264bitstream ${BROADCOM_INCLUDE_DIRS})
target_include_directories(moonlight PRIVATE ./third_party/ilclient ./third_party/h264bitstream ${BROADCOM_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif()
if(FREESCALE_FOUND)
include_directories(${FREESCALE_INCLUDE_DIRS})
target_include_directories(moonlight PRIVATE ${FREESCALE_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${FREESCALE_LIBRARIES})
endif()
if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND AND SDL_FOUND)
include_directories(${SDL_INCLUDE_DIRS} ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS} ${SWSCALE_INCLUDE_DIRS})
target_include_directories(moonlight PRIVATE ${SDL_INCLUDE_DIRS} ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS} ${SWSCALE_INCLUDE_DIRS})
target_link_libraries(moonlight PUBLIC ${SDL_LIBRARIES} ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${SWSCALE_LIBRARIES})
endif()
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS})
include_directories(./third_party/moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${AVAHI_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS} ${CEC_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY} ${AVAHI_LIBRARIES} ${UDEV_LIBRARIES} ${CMAKE_DL_LIBS} ${CEC_LIBRARIES})
target_include_directories(moonlight PRIVATE ./libgamestream ./third_party/moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY} ${UDEV_LIBRARIES} ${CMAKE_DL_LIBS})
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
install(TARGETS moonlight DESTINATION ${CMAKE_INSTALL_BINDIR})
+20
View File
@@ -0,0 +1,20 @@
find_package(Threads REQUIRED)
find_package(CURL REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(EXPAT REQUIRED)
pkg_check_modules(AVAHI REQUIRED avahi-client)
aux_source_directory(./ GAMESTREAM_SRC_LIST)
aux_source_directory(../third_party/moonlight-common-c/limelight-common GAMESTREAM_SRC_LIST)
aux_source_directory(../third_party/moonlight-common-c/limelight-common/OpenAES GAMESTREAM_SRC_LIST)
add_library(gamestream SHARED ${GAMESTREAM_SRC_LIST})
set_property(TARGET gamestream PROPERTY C_STANDARD 11)
set_target_properties(gamestream PROPERTIES SOVERSION 0 VERSION 2.1.0)
target_include_directories(gamestream PRIVATE ../third_party/moonlight-common-c ${AVAHI_INCLUDE_DIRS})
target_link_libraries (gamestream PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${AVAHI_LIBRARIES} ${CMAKE_DL_LIBS})
#install(TARGETS gamestream DESTINATION ${CMAKE_INSTALL_LIBDIR})
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+103
View File
@@ -0,0 +1,103 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LIBCEC
#include <ceccloader.h>
static libcec_configuration g_config;
static char g_strPort[50] = { 0 };
static libcec_interface_t g_iface;
static ICECCallbacks g_callbacks;
static int on_cec_keypress(void* userdata, const cec_keypress key) {
char value;
switch (key.keycode) {
case CEC_USER_CONTROL_CODE_UP:
value = KEY_UP;
break;
case CEC_USER_CONTROL_CODE_DOWN:
value = KEY_DOWN;
break;
case CEC_USER_CONTROL_CODE_LEFT:
value = KEY_LEFT;
break;
case CEC_USER_CONTROL_CODE_RIGHT:
value = KEY_RIGHT;
break;
case CEC_USER_CONTROL_CODE_ENTER:
case CEC_USER_CONTROL_CODE_SELECT:
value = KEY_ENTER;
break;
case CEC_USER_CONTROL_CODE_ROOT_MENU:
value = KEY_TAB;
break;
case CEC_USER_CONTROL_CODE_AN_RETURN:
case CEC_USER_CONTROL_CODE_EXIT:
value = KEY_ESC;
break;
default:
value = 0;
break;
}
if (value != 0) {
short code = 0x80 << 8 | keyCodes[value];
LiSendKeyboardEvent(code, (key.duration > 0)?KEY_ACTION_DOWN:KEY_ACTION_UP, 0);
}
}
void init_cec() {
libcecc_reset_configuration(&g_config);
g_config.clientVersion = LIBCEC_VERSION_CURRENT;
g_config.bActivateSource = 0;
g_callbacks.CBCecKeyPress = &on_cec_keypress;
g_config.callbacks = &g_callbacks;
snprintf(g_config.strDeviceName, sizeof(g_config.strDeviceName), "Moonlight");
g_config.callbacks = &g_callbacks;
g_config.deviceTypes.types[0] = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
if (libcecc_initialise(&g_config, &g_iface, NULL) != 1) {
fprintf(stderr, "Failed to initialize libcec interface\n");
fflush(stderr);
return;
}
g_iface.init_video_standalone(g_iface.connection);
cec_adapter devices[10];
int8_t iDevicesFound = g_iface.find_adapters(g_iface.connection, devices, sizeof(devices) / sizeof(devices), NULL);
if (iDevicesFound <= 0) {
fprintf(stderr, "No CEC devices found\n");
fflush(stderr);
libcecc_destroy(&g_iface);
return;
}
strcpy(g_strPort, devices[0].comm);
if (!g_iface.open(g_iface.connection, g_strPort, 5000)) {
fprintf(stderr, "Unable to open the device on port %s\n", g_strPort);
fflush(stderr);
libcecc_destroy(&g_iface);
return;
}
g_iface.set_active_source(g_iface.connection, g_config.deviceTypes.types[0]);
}
#endif /* HAVE_LIBCEC */
+20
View File
@@ -0,0 +1,20 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
void init_cec();
+116 -333
View File
@@ -17,6 +17,8 @@
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#include "../loop.h"
#include "keyboard.h"
#include "mapping.h"
#include "global.h"
@@ -24,20 +26,13 @@
#include "libevdev/libevdev.h"
#include "limelight-common/Limelight.h"
#ifdef HAVE_LIBCEC
#include <ceccloader.h>
#endif
#include <libudev.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signalfd.h>
#include <fcntl.h>
#include <poll.h>
#include <limits.h>
@@ -55,7 +50,6 @@ struct input_device {
struct libevdev *dev;
struct mapping map;
int fd;
int fdindex;
char modifiers;
__s32 mouseDeltaX, mouseDeltaY, mouseScroll;
short controllerId;
@@ -68,107 +62,17 @@ struct input_device {
struct input_abs_parms dpadxParms, dpadyParms;
};
static struct pollfd* fds = NULL;
static struct input_device* devices = NULL;
static int numDevices = 0, numFds = 0;
static int numDevices = 0;
static int assignedControllerIds = 0;
static short* currentKey;
static short* currentAbs;
static bool* currentReverse;
static bool autoadd;
static char* defaultMapfile;
static struct udev *udev;
static struct udev_monitor *udev_mon;
static int udev_fdindex;
static bool (*handler) (struct input_event*, struct input_device*);
static int sig_fdindex;
#ifdef HAVE_LIBCEC
static libcec_configuration g_config;
static char g_strPort[50] = { 0 };
static libcec_interface_t g_iface;
static ICECCallbacks g_callbacks;
static int on_cec_keypress(void* userdata, const cec_keypress key) {
char value;
switch (key.keycode) {
case CEC_USER_CONTROL_CODE_UP:
value = KEY_UP;
break;
case CEC_USER_CONTROL_CODE_DOWN:
value = KEY_DOWN;
break;
case CEC_USER_CONTROL_CODE_LEFT:
value = KEY_LEFT;
break;
case CEC_USER_CONTROL_CODE_RIGHT:
value = KEY_RIGHT;
break;
case CEC_USER_CONTROL_CODE_ENTER:
case CEC_USER_CONTROL_CODE_SELECT:
value = KEY_ENTER;
break;
case CEC_USER_CONTROL_CODE_ROOT_MENU:
value = KEY_TAB;
break;
case CEC_USER_CONTROL_CODE_AN_RETURN:
case CEC_USER_CONTROL_CODE_EXIT:
value = KEY_ESC;
break;
default:
value = 0;
break;
}
if (value != 0) {
short code = 0x80 << 8 | keyCodes[value];
LiSendKeyboardEvent(code, (key.duration > 0)?KEY_ACTION_DOWN:KEY_ACTION_UP, 0);
}
}
static void init_cec() {
libcecc_reset_configuration(&g_config);
g_config.clientVersion = LIBCEC_VERSION_CURRENT;
g_config.bActivateSource = 0;
g_callbacks.CBCecKeyPress = &on_cec_keypress;
g_config.callbacks = &g_callbacks;
snprintf(g_config.strDeviceName, sizeof(g_config.strDeviceName), "Moonlight");
g_config.callbacks = &g_callbacks;
g_config.deviceTypes.types[0] = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
if (libcecc_initialise(&g_config, &g_iface, NULL) != 1) {
fprintf(stderr, "Failed to initialize libcec interface\n");
fflush(stderr);
return;
}
g_iface.init_video_standalone(g_iface.connection);
cec_adapter devices[10];
int8_t iDevicesFound = g_iface.find_adapters(g_iface.connection, devices, sizeof(devices) / sizeof(devices), NULL);
if (iDevicesFound <= 0) {
fprintf(stderr, "No CEC devices found\n");
fflush(stderr);
libcecc_destroy(&g_iface);
return;
}
strcpy(g_strPort, devices[0].comm);
if (!g_iface.open(g_iface.connection, g_strPort, 5000)) {
fprintf(stderr, "Unable to open the device on port %s\n", g_strPort);
fflush(stderr);
libcecc_destroy(&g_iface);
return;
}
g_iface.set_active_source(g_iface.connection, g_config.deviceTypes.types[0]);
}
#endif
static void input_init_parms(struct input_device *dev, struct input_abs_parms *parms, int code) {
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);
@@ -177,154 +81,19 @@ static void input_init_parms(struct input_device *dev, struct input_abs_parms *p
parms->diff = parms->max - parms->min;
}
void input_create(const char* device, char* mapFile) {
int fd = open(device, O_RDONLY|O_NONBLOCK);
if (fd <= 0) {
fprintf(stderr, "Failed to open device %s\n", device);
fflush(stderr);
return;
}
int dev = numDevices;
int fdindex = numFds;
numDevices++;
numFds++;
if (fds == NULL) {
fds = malloc(sizeof(struct pollfd));
devices = malloc(sizeof(struct input_device));
} else {
fds = realloc(fds, sizeof(struct pollfd)*numFds);
devices = realloc(devices, sizeof(struct input_device)*numDevices);
}
if (fds == NULL || devices == NULL) {
fprintf(stderr, "Not enough memory\n");
exit(EXIT_FAILURE);
}
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].fdindex = fdindex;
fds[fdindex].fd = devices[dev].fd;
fds[fdindex].events = POLLIN;
if (mapFile != NULL)
mapping_load(mapFile, &(devices[dev].map));
devices[dev].controllerId = -1;
input_init_parms(&devices[dev], &(devices[dev].xParms), devices[dev].map.abs_x);
input_init_parms(&devices[dev], &(devices[dev].yParms), devices[dev].map.abs_y);
input_init_parms(&devices[dev], &(devices[dev].zParms), devices[dev].map.abs_z);
input_init_parms(&devices[dev], &(devices[dev].rxParms), devices[dev].map.abs_rx);
input_init_parms(&devices[dev], &(devices[dev].ryParms), devices[dev].map.abs_ry);
input_init_parms(&devices[dev], &(devices[dev].rzParms), devices[dev].map.abs_rz);
input_init_parms(&devices[dev], &(devices[dev].dpadxParms), devices[dev].map.abs_dpad_x);
input_init_parms(&devices[dev], &(devices[dev].dpadyParms), devices[dev].map.abs_dpad_y);
}
static void input_remove(int devindex) {
static void evdev_remove(int devindex) {
numDevices--;
numFds--;
if (devices[devindex].controllerId >= 0)
assignedControllerIds &= ~(1 << devices[devindex].controllerId);
int fdindex = devices[devindex].fdindex;
if (fdindex != numFds && numFds > 0) {
memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd));
if (numFds == udev_fdindex)
udev_fdindex = fdindex;
else if (numFds == sig_fdindex)
sig_fdindex = fdindex;
else {
for (int i=0;i<numDevices;i++) {
if (devices[i].fdindex == numFds) {
devices[i].fdindex = fdindex;
break;
}
}
}
}
if (devindex != numDevices && numDevices > 0)
memcpy(&devices[devindex], &devices[numDevices], sizeof(struct input_device));
fprintf(stderr, "Removed input device\n");
}
void input_init(char* mapfile) {
#ifdef HAVE_LIBCEC
init_cec();
#endif
udev = udev_new();
if (!udev) {
fprintf(stderr, "Can't create udev\n");
exit(1);
}
autoadd = (numDevices == 0);
if (autoadd) {
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "input");
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *dev_list_entry;
udev_list_entry_foreach(dev_list_entry, devices) {
const char *path = udev_list_entry_get_name(dev_list_entry);
struct udev_device *dev = udev_device_new_from_syspath(udev, path);
const char *devnode = udev_device_get_devnode(dev);
int id;
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
input_create(devnode, mapfile);
}
udev_device_unref(dev);
}
udev_enumerate_unref(enumerate);
}
udev_mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
udev_monitor_enable_receiving(udev_mon);
udev_fdindex = numFds++;
sig_fdindex = numFds++;
if (fds == NULL)
fds = malloc(sizeof(struct pollfd)*numFds);
else
fds = realloc(fds, sizeof(struct pollfd)*numFds);
if (fds == NULL) {
fprintf(stderr, "Not enough memory\n");
exit(EXIT_FAILURE);
}
defaultMapfile = mapfile;
fds[udev_fdindex].fd = udev_monitor_get_fd(udev_mon);
fds[udev_fdindex].events = POLLIN;
main_thread_id = pthread_self();
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGHUP);
sigaddset(&sigset, SIGTERM);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGQUIT);
sigprocmask(SIG_BLOCK, &sigset, NULL);
fds[sig_fdindex].fd = signalfd(-1, &sigset, 0);
fds[sig_fdindex].events = POLLIN | POLLERR | POLLHUP;
}
void input_destroy() {
udev_unref(udev);
}
static short input_convert_value(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms, bool reverse) {
static short evdev_convert_value(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms, bool reverse) {
if (abs(ev->value - parms->avg) < parms->flat)
return 0;
else if (ev->value > parms->max)
@@ -337,7 +106,7 @@ static short input_convert_value(struct input_event *ev, struct input_device *de
return (ev->value - (ev->value>parms->avg?parms->flat*2:0) - parms->min) * (SHRT_MAX-SHRT_MIN) / (parms->max-parms->min-parms->flat*2) - SHRT_MIN;
}
static char input_convert_value_byte(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms) {
static char evdev_convert_value_byte(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms) {
if (abs(ev->value-parms->min)<parms->flat)
return 0;
else if (ev->value>parms->max)
@@ -348,7 +117,7 @@ static char input_convert_value_byte(struct input_event *ev, struct input_device
}
}
static int input_convert_value_direction(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms, bool reverse) {
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))
@@ -357,7 +126,7 @@ static int input_convert_value_direction(struct input_event *ev, struct input_de
return 0;
}
static bool input_handle_event(struct input_event *ev, struct input_device *dev) {
static bool evdev_handle_event(struct input_event *ev, struct input_device *dev) {
bool gamepadModified = false;
switch (ev->type) {
@@ -495,19 +264,19 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
case EV_ABS:
gamepadModified = true;
if (ev->code == dev->map.abs_x)
dev->leftStickX = input_convert_value(ev, dev, &dev->xParms, dev->map.reverse_x);
dev->leftStickX = evdev_convert_value(ev, dev, &dev->xParms, dev->map.reverse_x);
else if (ev->code == dev->map.abs_y)
dev->leftStickY = input_convert_value(ev, dev, &dev->yParms, dev->map.reverse_y);
dev->leftStickY = evdev_convert_value(ev, dev, &dev->yParms, dev->map.reverse_y);
else if (ev->code == dev->map.abs_rx)
dev->rightStickX = input_convert_value(ev, dev, &dev->rxParms, dev->map.reverse_rx);
dev->rightStickX = evdev_convert_value(ev, dev, &dev->rxParms, dev->map.reverse_rx);
else if (ev->code == dev->map.abs_ry)
dev->rightStickY = input_convert_value(ev, dev, &dev->ryParms, dev->map.reverse_ry);
dev->rightStickY = evdev_convert_value(ev, dev, &dev->ryParms, dev->map.reverse_ry);
else if (ev->code == dev->map.abs_z)
dev->leftTrigger = input_convert_value_byte(ev, dev, &dev->zParms);
dev->leftTrigger = evdev_convert_value_byte(ev, dev, &dev->zParms);
else if (ev->code == dev->map.abs_rz)
dev->rightTrigger = input_convert_value_byte(ev, dev, &dev->rzParms);
dev->rightTrigger = evdev_convert_value_byte(ev, dev, &dev->rzParms);
else if (ev->code == dev->map.abs_dpad_x) {
int dir = input_convert_value_direction(ev, dev, &dev->dpadxParms, dev->map.reverse_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;
@@ -519,7 +288,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
dev->buttonFlags |= LEFT_FLAG;
}
} else if (ev->code == dev->map.abs_dpad_y) {
int dir = input_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_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;
@@ -540,7 +309,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
return true;
}
static bool input_handle_mapping_event(struct input_event *ev, struct input_device *dev) {
static bool evdev_handle_mapping_event(struct input_event *ev, struct input_device *dev) {
switch (ev->type) {
case EV_KEY:
if (currentKey != NULL) {
@@ -553,7 +322,7 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
case EV_ABS:
if (currentAbs != NULL) {
struct input_abs_parms parms;
input_init_parms(dev, &parms, ev->code);
evdev_init_parms(dev, &parms, ev->code);
if (ev->value > parms.avg + parms.range/2) {
*currentAbs = ev->code;
@@ -569,91 +338,104 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
return true;
}
static void input_drain(void) {
static void evdev_drain(void) {
for (int i = 0; i < numDevices; i++) {
struct input_event ev;
while (libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev) >= 0);
}
}
static bool input_poll(bool (*handler) (struct input_event*, struct input_device*)) {
while (poll(fds, numFds, -1)) {
if (fds[udev_fdindex].revents > 0) {
struct udev_device *dev = udev_monitor_receive_device(udev_mon);
const char *action = udev_device_get_action(dev);
if (action != NULL) {
if (autoadd && strcmp("add", action) == 0) {
const char *devnode = udev_device_get_devnode(dev);
int id;
if (devnode != NULL && sscanf(devnode, "/dev/input/event%d", &id) == 1) {
input_create(devnode, defaultMapfile);
}
static int evdev_handle(int fd) {
for (int i=0;i<numDevices;i++) {
if (devices[i].fd = fd) {
int rc;
struct input_event ev;
while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) {
if (rc == LIBEVDEV_READ_STATUS_SYNC)
fprintf(stderr, "Error: cannot keep up\n");
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
if (!handler(&ev, &devices[i]))
return LOOP_RETURN;
}
udev_device_unref(dev);
}
} else if (fds[sig_fdindex].revents > 0) {
struct signalfd_siginfo info;
read(fds[sig_fdindex].fd, &info, sizeof(info));
switch (info.ssi_signo) {
case SIGINT:
case SIGTERM:
case SIGQUIT:
case SIGHUP:
return false;
}
}
for (int i=0;i<numDevices;i++) {
if (fds[devices[i].fdindex].revents > 0) {
int rc;
struct input_event ev;
while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) {
if (rc == LIBEVDEV_READ_STATUS_SYNC)
fprintf(stderr, "Error: cannot keep up\n");
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
if (!handler(&ev, &devices[i]))
return true;
}
}
if (rc == -ENODEV) {
input_remove(i);
} else if (rc != -EAGAIN && rc < 0) {
fprintf(stderr, "Error: %s\n", strerror(-rc));
exit(EXIT_FAILURE);
}
if (rc == -ENODEV) {
evdev_remove(i);
} else if (rc != -EAGAIN && rc < 0) {
fprintf(stderr, "Error: %s\n", strerror(-rc));
exit(EXIT_FAILURE);
}
}
}
return false;
return LOOP_OK;
}
static void input_map_key(char* keyName, short* key) {
void evdev_create(const char* device, char* mapFile) {
int fd = open(device, O_RDONLY|O_NONBLOCK);
if (fd <= 0) {
fprintf(stderr, "Failed to open device %s\n", device);
fflush(stderr);
return;
}
int dev = numDevices;
numDevices++;
if (devices == NULL) {
devices = malloc(sizeof(struct input_device));
} else {
devices = realloc(devices, sizeof(struct input_device)*numDevices);
}
if (devices == NULL) {
fprintf(stderr, "Not enough memory\n");
exit(EXIT_FAILURE);
}
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);
if (mapFile != NULL)
mapping_load(mapFile, &(devices[dev].map));
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);
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;
if (!input_poll(input_handle_mapping_event))
exit(1);
loop_main();
usleep(250000);
input_drain();
evdev_drain();
}
static void input_map_abs(char* keyName, short* abs, bool* reverse) {
static void evdev_map_abs(char* keyName, short* abs, bool* reverse) {
printf("Move %s\n", keyName);
currentKey = NULL;
currentAbs = abs;
currentReverse = reverse;
*abs = -1;
if (!input_poll(input_handle_mapping_event))
exit(1);
loop_main();
usleep(250000);
input_drain();
evdev_drain();
}
static void input_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
static void evdev_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
printf("Press %s\n", keyName);
currentKey = key;
currentAbs = abs;
@@ -661,53 +443,54 @@ static void input_map_abskey(char* keyName, short* key, short* abs, bool* revers
*key = -1;
*abs = -1;
*currentReverse = false;
if (!input_poll(input_handle_mapping_event))
exit(1);
loop_main();
usleep(250000);
input_drain();
evdev_drain();
}
void input_map(char* fileName) {
void evdev_map(char* fileName) {
struct mapping map;
input_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x));
input_map_abs("Left Stick Up", &(map.abs_y), &(map.reverse_y));
input_map_key("Left Stick Button", &(map.btn_thumbl));
handler = evdev_handle_mapping_event;
input_map_abs("Right Stick Right", &(map.abs_rx), &(map.reverse_rx));
input_map_abs("Right Stick Up", &(map.abs_ry), &(map.reverse_ry));
input_map_key("Right Stick Button", &(map.btn_thumbr));
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));
input_map_abskey("D-Pad Right", &(map.btn_dpad_right), &(map.abs_dpad_x), &(map.reverse_dpad_x));
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)
input_map_key("D-Pad Left", &(map.btn_dpad_left));
evdev_map_key("D-Pad Left", &(map.btn_dpad_left));
else
map.btn_dpad_left = -1;
input_map_abskey("D-Pad Down", &(map.btn_dpad_down), &(map.abs_dpad_y), &(map.reverse_dpad_y));
evdev_map_abskey("D-Pad Down", &(map.btn_dpad_down), &(map.abs_dpad_y), &(map.reverse_dpad_y));
if (map.btn_dpad_down >= 0)
input_map_key("D-Pad Up", &(map.btn_dpad_up));
evdev_map_key("D-Pad Up", &(map.btn_dpad_up));
else
map.btn_dpad_up = -1;
input_map_key("Button X (1)", &(map.btn_west));
input_map_key("Button A (2)", &(map.btn_south));
input_map_key("Button B (3)", &(map.btn_east));
input_map_key("Button Y (4)", &(map.btn_north));
input_map_key("Back Button", &(map.btn_select));
input_map_key("Start Button", &(map.btn_start));
input_map_key("Special Button", &(map.btn_mode));
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;
input_map_abskey("Left Trigger", &(map.btn_tl2), &(map.abs_z), &ignored);
input_map_abskey("Right Trigger", &(map.btn_tr2), &(map.abs_rz), &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);
input_map_key("Left Bumper", &(map.btn_tl));
input_map_key("Right Bumper", &(map.btn_tr));
evdev_map_key("Left Bumper", &(map.btn_tl));
evdev_map_key("Right Bumper", &(map.btn_tr));
mapping_save(fileName, &map);
}
void input_loop() {
input_poll(input_handle_event);
void evdev_init() {
handler = evdev_handle_event;
}
+4 -5
View File
@@ -17,9 +17,8 @@
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
void input_init(char* mapfile);
void input_create(char* device, char* mapFile);
void input_loop();
void input_map(char* fileName);
void evdev_create(const char* device, char* mapFile);
void evdev_loop();
void evdev_map(char* fileName);
void input_destroy();
void evdev_init();
File renamed without changes.
File renamed without changes.
File renamed without changes.
+97
View File
@@ -0,0 +1,97 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#include "../loop.h"
#include "evdev.h"
#include <libudev.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
static bool autoadd;
static char* defaultMapfile;
static struct udev *udev;
static struct udev_monitor *udev_mon;
static int udev_fd;
static int udev_handle(int fd) {
struct udev_device *dev = udev_monitor_receive_device(udev_mon);
const char *action = udev_device_get_action(dev);
if (action != NULL) {
if (autoadd && strcmp("add", action) == 0) {
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);
}
}
udev_device_unref(dev);
}
return LOOP_OK;
}
void udev_init(bool autoload, char* mapfile) {
udev = udev_new();
if (!udev) {
fprintf(stderr, "Can't create udev\n");
exit(1);
}
autoadd = autoload;
if (autoload) {
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "input");
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *dev_list_entry;
udev_list_entry_foreach(dev_list_entry, devices) {
const char *path = udev_list_entry_get_name(dev_list_entry);
struct udev_device *dev = udev_device_new_from_syspath(udev, path);
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);
}
udev_device_unref(dev);
}
udev_enumerate_unref(enumerate);
}
udev_mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
udev_monitor_enable_receiving(udev_mon);
defaultMapfile = mapfile;
int udev_fd = udev_monitor_get_fd(udev_mon);
loop_add_fd(udev_fd, &udev_handle, POLLIN);
}
void evdev_destroy() {
udev_unref(udev);
}
+21
View File
@@ -0,0 +1,21 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
void udev_init(bool autoload, char* mapfile);
void evdev_destroy();
+113
View File
@@ -0,0 +1,113 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#include "loop.h"
#include "global.h"
#include <sys/stat.h>
#include <sys/signalfd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <string.h>
static struct pollfd* fds = NULL;
static FdHandler* fdHandlers = NULL;
static int numFds = 0;
static int sigFd;
static int loop_sig_handler(int fd) {
struct signalfd_siginfo info;
read(fd, &info, sizeof(info));
switch (info.ssi_signo) {
case SIGINT:
case SIGTERM:
case SIGQUIT:
case SIGHUP:
return LOOP_RETURN;
}
return LOOP_OK;
}
void loop_add_fd(int fd, FdHandler handler, int events) {
int fdindex = numFds;
numFds++;
if (fds == NULL) {
fds = malloc(sizeof(struct pollfd));
fdHandlers = malloc(sizeof(FdHandler*));
} else {
fds = realloc(fds, sizeof(struct pollfd)*numFds);
fdHandlers = realloc(fdHandlers, sizeof(FdHandler*)*numFds);
}
if (fds == NULL || fdHandlers == NULL) {
fprintf(stderr, "Not enough memory\n");
exit(EXIT_FAILURE);
}
fds[fdindex].fd = fd;
fds[fdindex].events = events;
}
void loop_remove_fd(int fd) {
numFds--;
int fdindex;
for (int i=0;i<numFds;i++) {
if (fds[i].fd = fd)
fdindex = i;
break;
}
if (fdindex != numFds && numFds > 0) {
memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd));
memcpy(&fdHandlers[fdindex], &fdHandlers[numFds], sizeof(FdHandler*));
}
}
void loop_main() {
main_thread_id = pthread_self();
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGHUP);
sigaddset(&sigset, SIGTERM);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGQUIT);
sigprocmask(SIG_BLOCK, &sigset, NULL);
sigFd = signalfd(-1, &sigset, 0);
loop_add_fd(sigFd, loop_sig_handler, POLLIN | POLLERR | POLLHUP);
//static bool evdev_poll(bool (*handler) (struct input_event*, struct input_device*)) {
while (poll(fds, numFds, -1)) {
for (int i=0;i<numFds;i++) {
if (fds[i].revents > 0) {
int ret = fdHandlers[i](fds[i].fd);
if (ret == LOOP_RETURN) {
return;
}
break;
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Moonlight 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 Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#define LOOP_RETURN 1
#define LOOP_OK 0
typedef int(*FdHandler)(int fd);
void loop_add_fd(int fd, FdHandler handler, int events);
void loop_remove_fd(int fd);
void loop_main();
+16 -6
View File
@@ -17,13 +17,17 @@
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/
#include "loop.h"
#include "client.h"
#include "connection.h"
#include "video.h"
#include "audio.h"
#include "input.h"
#include "discover.h"
#include "input/evdev.h"
#include "input/udev.h"
#include "input/cec.h"
#include "limelight-common/Limelight.h"
#include <stdio.h>
@@ -60,10 +64,14 @@ static void stream(STREAM_CONFIGURATION* config, const char* address, const char
client_start_app(config, address, appId, sops, localaudio);
video_init();
evdev_init();
#ifdef HAVE_LIBCEC
cec_init();
#endif /* HAVE_LIBCEC */
LiStartConnection(address, config, &connection_callbacks, decoder_callbacks, &audio_callbacks, NULL, NULL, 0, client_get_server_version());
input_loop();
loop_main();
LiStopConnection();
}
@@ -172,6 +180,7 @@ int main(int argc, char* argv[]) {
int option_index = 0;
bool sops = true;
bool localaudio = false;
bool autoadd = true;
int c;
while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:n", long_options, &option_index)) != -1) {
switch (c) {
@@ -205,7 +214,8 @@ int main(int argc, char* argv[]) {
app = optarg;
break;
case 'j':
input_create(optarg, mapping);
evdev_create(optarg, mapping);
autoadd = false;
break;
case 'k':
mapping = get_path(optarg);
@@ -238,8 +248,8 @@ int main(int argc, char* argv[]) {
perror("No filename for mapping");
exit(-1);
}
input_init(mapping);
input_map(address);
udev_init(autoadd, mapping);
evdev_map(address);
exit(0);
}
@@ -263,7 +273,7 @@ int main(int argc, char* argv[]) {
pair_check();
applist(address);
} else if (strcmp("stream", action) == 0) {
input_init(mapping);
udev_init(autoadd, mapping);
pair_check();
stream(&config, address, app, sops, localaudio);
} else if (strcmp("pair", action) == 0)