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
+541 -352

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") SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
aux_source_directory(./src SRC_LIST) aux_source_directory(./src SRC_LIST)
aux_source_directory(./src/input SRC_LIST)
list(APPEND SRC_LIST ./src/video/fake.c) 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) 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(ALSA REQUIRED)
find_package(Opus REQUIRED) find_package(Opus REQUIRED)
find_package(Broadcom) find_package(Broadcom)
@@ -25,18 +17,12 @@ find_package(CEC)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(EVDEV REQUIRED libevdev) pkg_check_modules(EVDEV REQUIRED libevdev)
pkg_check_modules(AVAHI REQUIRED avahi-client)
pkg_check_modules(UDEV REQUIRED libudev) pkg_check_modules(UDEV REQUIRED libudev)
pkg_check_modules(SDL sdl2) pkg_check_modules(SDL sdl2)
pkg_check_modules(AVCODEC libavcodec) pkg_check_modules(AVCODEC libavcodec)
pkg_check_modules(AVUTIL libavutil) pkg_check_modules(AVUTIL libavutil)
pkg_check_modules(SWSCALE libswscale) pkg_check_modules(SWSCALE libswscale)
if(CEC_FOUND)
include_directories(./third_party/libcec)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
endif()
if(BROADCOM_FOUND) if(BROADCOM_FOUND)
aux_source_directory(./third_party/ilclient SRC_LIST) aux_source_directory(./third_party/ilclient SRC_LIST)
aux_source_directory(./third_party/h264bitstream 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) list(APPEND MOONLIGHT_DEFINITIONS HAVE_SDL)
endif() endif()
add_subdirectory(libgamestream)
add_executable(moonlight ${SRC_LIST}) add_executable(moonlight ${SRC_LIST})
target_link_libraries(moonlight PUBLIC gamestream)
set_property(TARGET moonlight PROPERTY C_STANDARD 11) 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) 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}) target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS}) list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif() endif()
if(FREESCALE_FOUND) if(FREESCALE_FOUND)
include_directories(${FREESCALE_INCLUDE_DIRS}) target_include_directories(moonlight PRIVATE ${FREESCALE_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${FREESCALE_LIBRARIES}) target_link_libraries (moonlight PUBLIC ${FREESCALE_LIBRARIES})
endif() endif()
if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND AND SDL_FOUND) 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}) target_link_libraries(moonlight PUBLIC ${SDL_LIBRARIES} ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${SWSCALE_LIBRARIES})
endif() endif()
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS}) 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_include_directories(moonlight PRIVATE ./libgamestream ./third_party/moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${UDEV_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_link_libraries (moonlight PUBLIC ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY} ${UDEV_LIBRARIES} ${CMAKE_DL_LIBS})
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake) include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
install(TARGETS moonlight DESTINATION ${CMAKE_INSTALL_BINDIR}) 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();
+104 -321
View File
@@ -17,6 +17,8 @@
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>. * along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../loop.h"
#include "keyboard.h" #include "keyboard.h"
#include "mapping.h" #include "mapping.h"
#include "global.h" #include "global.h"
@@ -24,20 +26,13 @@
#include "libevdev/libevdev.h" #include "libevdev/libevdev.h"
#include "limelight-common/Limelight.h" #include "limelight-common/Limelight.h"
#ifdef HAVE_LIBCEC
#include <ceccloader.h>
#endif
#include <libudev.h> #include <libudev.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <signal.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <sys/signalfd.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <limits.h> #include <limits.h>
@@ -55,7 +50,6 @@ struct input_device {
struct libevdev *dev; struct libevdev *dev;
struct mapping map; struct mapping map;
int fd; int fd;
int fdindex;
char modifiers; char modifiers;
__s32 mouseDeltaX, mouseDeltaY, mouseScroll; __s32 mouseDeltaX, mouseDeltaY, mouseScroll;
short controllerId; short controllerId;
@@ -68,107 +62,17 @@ struct input_device {
struct input_abs_parms dpadxParms, dpadyParms; struct input_abs_parms dpadxParms, dpadyParms;
}; };
static struct pollfd* fds = NULL;
static struct input_device* devices = NULL; static struct input_device* devices = NULL;
static int numDevices = 0, numFds = 0; static int numDevices = 0;
static int assignedControllerIds = 0; static int assignedControllerIds = 0;
static short* currentKey; static short* currentKey;
static short* currentAbs; static short* currentAbs;
static bool* currentReverse; static bool* currentReverse;
static bool autoadd; static bool (*handler) (struct input_event*, struct input_device*);
static char* defaultMapfile;
static struct udev *udev;
static struct udev_monitor *udev_mon;
static int udev_fdindex;
static int sig_fdindex; static void evdev_init_parms(struct input_device *dev, struct input_abs_parms *parms, int code) {
#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) {
parms->flat = libevdev_get_abs_flat(dev->dev, code); parms->flat = libevdev_get_abs_flat(dev->dev, code);
parms->min = libevdev_get_abs_minimum(dev->dev, code); parms->min = libevdev_get_abs_minimum(dev->dev, code);
parms->max = libevdev_get_abs_maximum(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; parms->diff = parms->max - parms->min;
} }
void input_create(const char* device, char* mapFile) { static void evdev_remove(int devindex) {
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) {
numDevices--; numDevices--;
numFds--;
if (devices[devindex].controllerId >= 0) if (devices[devindex].controllerId >= 0)
assignedControllerIds &= ~(1 << devices[devindex].controllerId); 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) if (devindex != numDevices && numDevices > 0)
memcpy(&devices[devindex], &devices[numDevices], sizeof(struct input_device)); memcpy(&devices[devindex], &devices[numDevices], sizeof(struct input_device));
fprintf(stderr, "Removed input device\n"); fprintf(stderr, "Removed input device\n");
} }
void input_init(char* mapfile) { static short evdev_convert_value(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms, bool reverse) {
#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) {
if (abs(ev->value - parms->avg) < parms->flat) if (abs(ev->value - parms->avg) < parms->flat)
return 0; return 0;
else if (ev->value > parms->max) 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; 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) if (abs(ev->value-parms->min)<parms->flat)
return 0; return 0;
else if (ev->value>parms->max) 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)) if (ev->value > (parms->avg+parms->range/4))
return reverse?-1:1; return reverse?-1:1;
else if (ev->value < (parms->avg-parms->range/4)) 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; 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; bool gamepadModified = false;
switch (ev->type) { switch (ev->type) {
@@ -495,19 +264,19 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
case EV_ABS: case EV_ABS:
gamepadModified = true; gamepadModified = true;
if (ev->code == dev->map.abs_x) 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) 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) 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) 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) 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) 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) { 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) { if (dir == 1) {
dev->buttonFlags |= RIGHT_FLAG; dev->buttonFlags |= RIGHT_FLAG;
dev->buttonFlags &= ~LEFT_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; dev->buttonFlags |= LEFT_FLAG;
} }
} else if (ev->code == dev->map.abs_dpad_y) { } 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) { if (dir == 1) {
dev->buttonFlags |= DOWN_FLAG; dev->buttonFlags |= DOWN_FLAG;
dev->buttonFlags &= ~UP_FLAG; dev->buttonFlags &= ~UP_FLAG;
@@ -540,7 +309,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
return true; 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) { switch (ev->type) {
case EV_KEY: case EV_KEY:
if (currentKey != NULL) { if (currentKey != NULL) {
@@ -553,7 +322,7 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
case EV_ABS: case EV_ABS:
if (currentAbs != NULL) { if (currentAbs != NULL) {
struct input_abs_parms parms; 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) { if (ev->value > parms.avg + parms.range/2) {
*currentAbs = ev->code; *currentAbs = ev->code;
@@ -569,42 +338,16 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
return true; return true;
} }
static void input_drain(void) { static void evdev_drain(void) {
for (int i = 0; i < numDevices; i++) { for (int i = 0; i < numDevices; i++) {
struct input_event ev; struct input_event ev;
while (libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev) >= 0); 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*)) { static int evdev_handle(int fd) {
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);
}
}
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++) { for (int i=0;i<numDevices;i++) {
if (fds[devices[i].fdindex].revents > 0) { if (devices[i].fd = fd) {
int rc; int rc;
struct input_event ev; struct input_event ev;
while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) { while ((rc = libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) >= 0) {
@@ -612,48 +355,87 @@ static bool input_poll(bool (*handler) (struct input_event*, struct input_device
fprintf(stderr, "Error: cannot keep up\n"); fprintf(stderr, "Error: cannot keep up\n");
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
if (!handler(&ev, &devices[i])) if (!handler(&ev, &devices[i]))
return true; return LOOP_RETURN;
} }
} }
if (rc == -ENODEV) { if (rc == -ENODEV) {
input_remove(i); evdev_remove(i);
} else if (rc != -EAGAIN && rc < 0) { } else if (rc != -EAGAIN && rc < 0) {
fprintf(stderr, "Error: %s\n", strerror(-rc)); fprintf(stderr, "Error: %s\n", strerror(-rc));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
} }
} return LOOP_OK;
return false;
} }
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); printf("Press %s\n", keyName);
currentKey = key; currentKey = key;
currentAbs = NULL; currentAbs = NULL;
*key = -1; *key = -1;
if (!input_poll(input_handle_mapping_event)) loop_main();
exit(1);
usleep(250000); 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); printf("Move %s\n", keyName);
currentKey = NULL; currentKey = NULL;
currentAbs = abs; currentAbs = abs;
currentReverse = reverse; currentReverse = reverse;
*abs = -1; *abs = -1;
if (!input_poll(input_handle_mapping_event)) loop_main();
exit(1);
usleep(250000); 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); printf("Press %s\n", keyName);
currentKey = key; currentKey = key;
currentAbs = abs; currentAbs = abs;
@@ -661,53 +443,54 @@ static void input_map_abskey(char* keyName, short* key, short* abs, bool* revers
*key = -1; *key = -1;
*abs = -1; *abs = -1;
*currentReverse = false; *currentReverse = false;
if (!input_poll(input_handle_mapping_event)) loop_main();
exit(1);
usleep(250000); usleep(250000);
input_drain(); evdev_drain();
} }
void input_map(char* fileName) { void evdev_map(char* fileName) {
struct mapping map; struct mapping map;
input_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x)); handler = evdev_handle_mapping_event;
input_map_abs("Left Stick Up", &(map.abs_y), &(map.reverse_y));
input_map_key("Left Stick Button", &(map.btn_thumbl));
input_map_abs("Right Stick Right", &(map.abs_rx), &(map.reverse_rx)); evdev_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x));
input_map_abs("Right Stick Up", &(map.abs_ry), &(map.reverse_ry)); evdev_map_abs("Left Stick Up", &(map.abs_y), &(map.reverse_y));
input_map_key("Right Stick Button", &(map.btn_thumbr)); 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) 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 else
map.btn_dpad_left = -1; 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) 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 else
map.btn_dpad_up = -1; map.btn_dpad_up = -1;
input_map_key("Button X (1)", &(map.btn_west)); evdev_map_key("Button X (1)", &(map.btn_west));
input_map_key("Button A (2)", &(map.btn_south)); evdev_map_key("Button A (2)", &(map.btn_south));
input_map_key("Button B (3)", &(map.btn_east)); evdev_map_key("Button B (3)", &(map.btn_east));
input_map_key("Button Y (4)", &(map.btn_north)); evdev_map_key("Button Y (4)", &(map.btn_north));
input_map_key("Back Button", &(map.btn_select)); evdev_map_key("Back Button", &(map.btn_select));
input_map_key("Start Button", &(map.btn_start)); evdev_map_key("Start Button", &(map.btn_start));
input_map_key("Special Button", &(map.btn_mode)); evdev_map_key("Special Button", &(map.btn_mode));
bool ignored; bool ignored;
input_map_abskey("Left Trigger", &(map.btn_tl2), &(map.abs_z), &ignored); evdev_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("Right Trigger", &(map.btn_tr2), &(map.abs_rz), &ignored);
input_map_key("Left Bumper", &(map.btn_tl)); evdev_map_key("Left Bumper", &(map.btn_tl));
input_map_key("Right Bumper", &(map.btn_tr)); evdev_map_key("Right Bumper", &(map.btn_tr));
mapping_save(fileName, &map); mapping_save(fileName, &map);
} }
void input_loop() { void evdev_init() {
input_poll(input_handle_event); handler = evdev_handle_event;
} }
+4 -5
View File
@@ -17,9 +17,8 @@
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>. * along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/ */
void input_init(char* mapfile); void evdev_create(const char* device, char* mapFile);
void input_create(char* device, char* mapFile); void evdev_loop();
void input_loop(); void evdev_map(char* fileName);
void input_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/>. * along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include "loop.h"
#include "client.h" #include "client.h"
#include "connection.h" #include "connection.h"
#include "video.h" #include "video.h"
#include "audio.h" #include "audio.h"
#include "input.h"
#include "discover.h" #include "discover.h"
#include "input/evdev.h"
#include "input/udev.h"
#include "input/cec.h"
#include "limelight-common/Limelight.h" #include "limelight-common/Limelight.h"
#include <stdio.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); client_start_app(config, address, appId, sops, localaudio);
video_init(); 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()); LiStartConnection(address, config, &connection_callbacks, decoder_callbacks, &audio_callbacks, NULL, NULL, 0, client_get_server_version());
input_loop(); loop_main();
LiStopConnection(); LiStopConnection();
} }
@@ -172,6 +180,7 @@ int main(int argc, char* argv[]) {
int option_index = 0; int option_index = 0;
bool sops = true; bool sops = true;
bool localaudio = false; bool localaudio = false;
bool autoadd = true;
int c; int c;
while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:n", long_options, &option_index)) != -1) { while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:n", long_options, &option_index)) != -1) {
switch (c) { switch (c) {
@@ -205,7 +214,8 @@ int main(int argc, char* argv[]) {
app = optarg; app = optarg;
break; break;
case 'j': case 'j':
input_create(optarg, mapping); evdev_create(optarg, mapping);
autoadd = false;
break; break;
case 'k': case 'k':
mapping = get_path(optarg); mapping = get_path(optarg);
@@ -238,8 +248,8 @@ int main(int argc, char* argv[]) {
perror("No filename for mapping"); perror("No filename for mapping");
exit(-1); exit(-1);
} }
input_init(mapping); udev_init(autoadd, mapping);
input_map(address); evdev_map(address);
exit(0); exit(0);
} }
@@ -263,7 +273,7 @@ int main(int argc, char* argv[]) {
pair_check(); pair_check();
applist(address); applist(address);
} else if (strcmp("stream", action) == 0) { } else if (strcmp("stream", action) == 0) {
input_init(mapping); udev_init(autoadd, mapping);
pair_check(); pair_check();
stream(&config, address, app, sops, localaudio); stream(&config, address, app, sops, localaudio);
} else if (strcmp("pair", action) == 0) } else if (strcmp("pair", action) == 0)