Merge tag 'v2.4.5' into raspbian/jessie

This commit is contained in:
Iwan Timmer
2018-01-13 15:10:49 +00:00
17 changed files with 274 additions and 103 deletions

View File

@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.1)
project(moonlight-embedded VERSION 2.4.3 LANGUAGES C)
project(moonlight-embedded VERSION 2.4.5 LANGUAGES C)
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
SET(CMAKE_C_STANDARD 99)
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
aux_source_directory(./src SRC_LIST)
@@ -25,7 +26,7 @@ pkg_check_modules(VDPAU vdpau)
pkg_check_modules(LIBVA libva)
pkg_check_modules(LIBVA_X11 libva-x11)
pkg_check_modules(PULSE libpulse-simple)
pkg_check_modules(CEC libcec>=3.0.0)
pkg_check_modules(CEC libcec>=4)
pkg_check_modules(EGL egl)
pkg_check_modules(GLES glesv2)
@@ -51,66 +52,17 @@ endif()
SET(MOONLIGHT_COMMON_INCLUDE_DIR ./third_party/moonlight-common-c/src)
SET(GAMESTREAM_INCLUDE_DIR ./libgamestream)
if(NOT AMLOGIC_FOUND AND NOT BROADCOM_FOUND AND NOT FREESCALE_FOUND AND NOT SOFTWARE_FOUND)
message(FATAL_ERROR "No video output available")
endif()
if (SOFTWARE_FOUND)
list(APPEND SRC_LIST ./src/video/ffmpeg.c)
if (SDL_FOUND)
list(APPEND SRC_LIST ./src/video/sdl.c ./src/audio/sdl.c ./src/input/sdl.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_SDL)
list(APPEND MOONLIGHT_OPTIONS SDL)
endif()
if (X11_FOUND)
list(APPEND SRC_LIST ./src/video/x11.c ./src/video/egl.c ./src/input/x11.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_X11)
list(APPEND MOONLIGHT_OPTIONS X11)
endif()
if(VDPAU_ACCEL_FOUND)
list(APPEND SRC_LIST ./src/video/ffmpeg_vdpau.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VDPAU)
list(APPEND MOONLIGHT_OPTIONS VDPAU)
endif()
if(VA_ACCEL_FOUND)
list(APPEND SRC_LIST ./src/video/ffmpeg_vaapi.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VAAPI)
list(APPEND MOONLIGHT_OPTIONS VAAPI)
endif()
endif()
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_EMBEDDED)
list(APPEND MOONLIGHT_OPTIONS EMBEDDED)
endif()
if (ALSA_FOUND)
list(APPEND SRC_LIST ./src/audio/alsa.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_ALSA)
list(APPEND MOONLIGHT_OPTIONS ALSA)
endif()
if (PULSE_FOUND)
list(APPEND SRC_LIST ./src/audio/pulse.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_PULSE)
list(APPEND MOONLIGHT_OPTIONS PULSE)
endif()
if (CEC_FOUND)
list(APPEND SRC_LIST ./src/input/cec.c)
endif()
include_directories("${PROJECT_BINARY_DIR}")
add_subdirectory(libgamestream)
add_executable(moonlight ${SRC_LIST})
target_link_libraries(moonlight gamestream)
set_property(TARGET moonlight PROPERTY C_STANDARD 99)
if (CEC_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
list(APPEND MOONLIGHT_OPTIONS CEC)
target_sources(moonlight PRIVATE ./src/input/cec.c)
target_include_directories(moonlight PRIVATE ./third_party/libcec ${CEC_INCLUDE_DIRS})
target_link_libraries(moonlight ${CEC_LIBRARIES})
endif()
@@ -145,39 +97,65 @@ if(FREESCALE_FOUND)
install(TARGETS moonlight-imx DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(SDL_FOUND)
target_include_directories(moonlight PRIVATE ${SDL_INCLUDE_DIRS})
target_link_libraries(moonlight ${SDL_LIBRARIES})
endif()
if(X11_FOUND)
target_include_directories(moonlight PRIVATE ${XLIB_INCLUDE_DIRS} ${EGL_INCLUDE_DIRS} ${GLES_INCLUDE_DIRS})
target_link_libraries(moonlight ${XLIB_LIBRARIES} ${EGL_LIBRARIES} ${GLES_LIBRARIES})
endif()
if (SOFTWARE_FOUND)
target_sources(moonlight PRIVATE ./src/video/ffmpeg.c)
target_include_directories(moonlight PRIVATE ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS})
target_link_libraries(moonlight ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES})
if(SDL_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_SDL)
list(APPEND MOONLIGHT_OPTIONS SDL)
target_sources(moonlight PRIVATE ./src/video/sdl.c ./src/audio/sdl.c ./src/input/sdl.c)
target_include_directories(moonlight PRIVATE ${SDL_INCLUDE_DIRS})
target_link_libraries(moonlight ${SDL_LIBRARIES})
endif()
if(X11_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_X11)
list(APPEND MOONLIGHT_OPTIONS X11)
target_sources(moonlight PRIVATE ./src/video/x11.c ./src/video/egl.c ./src/input/x11.c)
target_include_directories(moonlight PRIVATE ${XLIB_INCLUDE_DIRS} ${EGL_INCLUDE_DIRS} ${GLES_INCLUDE_DIRS})
target_link_libraries(moonlight ${XLIB_LIBRARIES} ${EGL_LIBRARIES} ${GLES_LIBRARIES})
endif()
if(VDPAU_ACCEL_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VDPAU)
list(APPEND MOONLIGHT_OPTIONS VDPAU)
target_sources(moonlight PRIVATE ./src/video/ffmpeg_vdpau.c)
target_include_directories(moonlight PRIVATE ${VDPAU_INCLUDE_DIRS})
target_link_libraries(moonlight ${VDPAU_LIBRARIES})
endif()
if(VA_ACCEL_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_VAAPI)
list(APPEND MOONLIGHT_OPTIONS VAAPI)
target_sources(moonlight PRIVATE ./src/video/ffmpeg_vaapi.c)
target_include_directories(moonlight PRIVATE ${LIBVA_INCLUDE_DIRS} ${LIBVA_X11_INCLUDE_DIRS})
target_link_libraries(moonlight ${LIBVA_LIBRARIES} ${LIBVA_X11_LIBRARIES})
endif()
endif()
if (ALSA_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_ALSA)
list(APPEND MOONLIGHT_OPTIONS ALSA)
target_sources(moonlight PRIVATE ./src/audio/alsa.c)
target_include_directories(moonlight PRIVATE ${ALSA_INCLUDE_DIR})
target_link_libraries(moonlight ${ALSA_LIBRARY})
endif()
if (PULSE_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_PULSE)
list(APPEND MOONLIGHT_OPTIONS PULSE)
target_sources(moonlight PRIVATE ./src/audio/pulse.c)
target_include_directories(moonlight PRIVATE ${PULSE_INCLUDE_DIRS})
target_link_libraries(moonlight ${PULSE_LIBRARIES})
endif()
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_EMBEDDED)
list(APPEND MOONLIGHT_OPTIONS EMBEDDED)
endif()
if(NOT AMLOGIC_FOUND AND NOT BROADCOM_FOUND AND NOT FREESCALE_FOUND AND NOT SOFTWARE_FOUND)
message(FATAL_ERROR "No video output available")
endif()
configure_file("./src/configuration.h.in" "${PROJECT_BINARY_DIR}/configuration.h")
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS})

View File

@@ -7,7 +7,7 @@ mark_as_advanced(BROADCOM_INCLUDE_DIR)
find_path(KERNEL_INCLUDE_DIR
NAMES linux/mxc_v4l2.h
DOC "Kernel include directory"
PATHS /lib/modules/${CMAKE_SYSTEM_VERSION}/build)
PATHS /lib/modules/${CMAKE_SYSTEM_VERSION}/build/include)
mark_as_advanced(KERNEL_INCLUDE_DIR)
find_library(VPU_LIBRARY

View File

@@ -31,6 +31,10 @@ List all available games and application on host.
Quit the current running game or application on host.
=item B<map>
Create a mapping for the specified I<INPUT> device.
=item B<help>
Show help for all available commands.

View File

@@ -16,10 +16,8 @@ aux_source_directory(../third_party/moonlight-common-c/src MOONLIGHT_COMMON_SRC_
aux_source_directory(../third_party/moonlight-common-c/reedsolomon MOONLIGHT_COMMON_SRC_LIST)
add_library(moonlight-common SHARED ${MOONLIGHT_COMMON_SRC_LIST})
set_property(TARGET moonlight-common PROPERTY C_STANDARD 99)
add_library(gamestream SHARED ${GAMESTREAM_SRC_LIST})
set_property(TARGET gamestream PROPERTY C_STANDARD 99)
target_link_libraries(gamestream moonlight-common)
set_target_properties(gamestream PROPERTIES SOVERSION ${SO_VERSION} VERSION ${PROJECT_VERSION})

View File

@@ -22,6 +22,7 @@
#include "mkcert.h"
#include "client.h"
#include "errors.h"
#include "limits.h"
#include <Limelight.h>
@@ -58,12 +59,13 @@ static EVP_PKEY *privateKey;
const char* gs_error;
static int mkdirtree(const char* directory) {
char buffer[1024];
char buffer[PATH_MAX];
char* p = buffer;
// The passed in string could be a string literal
// so we must copy it first
strcpy(p, directory);
strncpy(p, directory, PATH_MAX - 1);
buffer[PATH_MAX - 1] = '\0';
while (*p != 0) {
// Find the end of the path element
@@ -86,8 +88,8 @@ static int mkdirtree(const char* directory) {
}
static int load_unique_id(const char* keyDirectory) {
char uniqueFilePath[4096];
sprintf(uniqueFilePath, "%s/%s", keyDirectory, UNIQUE_FILE_NAME);
char uniqueFilePath[PATH_MAX];
snprintf(uniqueFilePath, PATH_MAX, "%s/%s", keyDirectory, UNIQUE_FILE_NAME);
FILE *fd = fopen(uniqueFilePath, "r");
if (fd == NULL) {
@@ -111,11 +113,11 @@ static int load_unique_id(const char* keyDirectory) {
}
static int load_cert(const char* keyDirectory) {
char certificateFilePath[4096];
sprintf(certificateFilePath, "%s/%s", keyDirectory, CERTIFICATE_FILE_NAME);
char certificateFilePath[PATH_MAX];
snprintf(certificateFilePath, PATH_MAX, "%s/%s", keyDirectory, CERTIFICATE_FILE_NAME);
char keyFilePath[4096];
sprintf(&keyFilePath[0], "%s/%s", keyDirectory, KEY_FILE_NAME);
char keyFilePath[PATH_MAX];
snprintf(&keyFilePath[0], PATH_MAX, "%s/%s", keyDirectory, KEY_FILE_NAME);
FILE *fd = fopen(certificateFilePath, "r");
if (fd == NULL) {
@@ -123,8 +125,8 @@ static int load_cert(const char* keyDirectory) {
CERT_KEY_PAIR cert = mkcert_generate();
printf("done\n");
char p12FilePath[4096];
sprintf(p12FilePath, "%s/%s", keyDirectory, P12_FILE_NAME);
char p12FilePath[PATH_MAX];
snprintf(p12FilePath, PATH_MAX, "%s/%s", keyDirectory, P12_FILE_NAME);
mkcert_save(certificateFilePath, p12FilePath, keyFilePath, cert);
mkcert_free(cert);
@@ -190,7 +192,7 @@ static int load_server_status(PSERVER_DATA server) {
// is not already paired. Since we can't pair without knowing the server version, we
// make another request over HTTP if the HTTPS request fails. We can't just use HTTP
// for everything because it doesn't accurately tell us if we're paired.
sprintf(url, "%s://%s:%d/serverinfo?uniqueid=%s&uuid=%s",
snprintf(url, sizeof(url), "%s://%s:%d/serverinfo?uniqueid=%s&uuid=%s",
i == 0 ? "https" : "http", server->serverInfo.address, i == 0 ? 47984 : 47989, unique_id, uuid_str);
PHTTP_DATA data = http_create_data();
@@ -245,7 +247,7 @@ static int load_server_status(PSERVER_DATA server) {
server->supports4K = serverCodecModeSupportText != NULL;
server->serverMajorVersion = atoi(server->serverInfo.serverInfoAppVersion);
if (strstr(stateText, "_SERVER_AVAILABLE")) {
if (strstr(stateText, "_SERVER_BUSY") == NULL) {
// After GFE 2.8, current game remains set even after streaming
// has ended. We emulate the old behavior by forcing it to zero
// if streaming is not active.
@@ -375,7 +377,7 @@ int gs_unpair(PSERVER_DATA server) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "http://%s:47989/unpair?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
snprintf(url, sizeof(url), "http://%s:47989/unpair?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
ret = http_request(url, data);
http_free_data(data);
@@ -406,7 +408,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->serverInfo.address, unique_id, uuid_str, salt_hex, cert_hex);
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->serverInfo.address, unique_id, uuid_str, salt_hex, cert_hex);
PHTTP_DATA data = http_create_data();
if (data == NULL)
return GS_OUT_OF_MEMORY;
@@ -465,7 +467,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->serverInfo.address, unique_id, uuid_str, challenge_hex);
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->serverInfo.address, unique_id, uuid_str, challenge_hex);
if ((ret = http_request(url, data)) != GS_OK)
goto cleanup;
@@ -524,7 +526,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->serverInfo.address, unique_id, uuid_str, challenge_response_hex);
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->serverInfo.address, unique_id, uuid_str, challenge_response_hex);
if ((ret = http_request(url, data)) != GS_OK)
goto cleanup;
@@ -575,7 +577,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->serverInfo.address, unique_id, uuid_str, client_pairing_secret_hex);
snprintf(url, sizeof(url), "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->serverInfo.address, unique_id, uuid_str, client_pairing_secret_hex);
if ((ret = http_request(url, data)) != GS_OK)
goto cleanup;
@@ -594,7 +596,7 @@ int gs_pair(PSERVER_DATA server, char* pin) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->serverInfo.address, unique_id, uuid_str);
snprintf(url, sizeof(url), "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->serverInfo.address, unique_id, uuid_str);
if ((ret = http_request(url, data)) != GS_OK)
goto cleanup;
@@ -636,7 +638,7 @@ int gs_applist(PSERVER_DATA server, PAPP_LIST *list) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "https://%s:47984/applist?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
snprintf(url, sizeof(url), "https://%s:47984/applist?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
if (http_request(url, data) != GS_OK)
ret = GS_IO_ERROR;
else if (xml_status(data->memory, data->size) == GS_ERROR)
@@ -687,9 +689,9 @@ int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, b
if (server->currentGame == 0) {
int channelCounnt = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_COUNT_STEREO : CHANNEL_COUNT_51_SURROUND;
int mask = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_MASK_STEREO : CHANNEL_MASK_51_SURROUND;
sprintf(url, "https://%s:47984/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d", server->serverInfo.address, unique_id, uuid_str, appId, config->width, config->height, config->fps, sops, rikey_hex, rikeyid, localaudio, (mask << 16) + channelCounnt);
snprintf(url, sizeof(url), "https://%s:47984/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d", server->serverInfo.address, unique_id, uuid_str, appId, config->width, config->height, config->fps, sops, rikey_hex, rikeyid, localaudio, (mask << 16) + channelCounnt);
} else
sprintf(url, "https://%s:47984/resume?uniqueid=%s&uuid=%s&rikey=%s&rikeyid=%d", server->serverInfo.address, unique_id, uuid_str, rikey_hex, rikeyid);
snprintf(url, sizeof(url), "https://%s:47984/resume?uniqueid=%s&uuid=%s&rikey=%s&rikeyid=%d", server->serverInfo.address, unique_id, uuid_str, rikey_hex, rikeyid);
if ((ret = http_request(url, data)) == GS_OK)
server->currentGame = appId;
@@ -726,7 +728,7 @@ int gs_quit_app(PSERVER_DATA server) {
uuid_generate_random(uuid);
uuid_unparse(uuid, uuid_str);
sprintf(url, "https://%s:47984/cancel?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
snprintf(url, sizeof(url), "https://%s:47984/cancel?uniqueid=%s&uuid=%s", server->serverInfo.address, unique_id, uuid_str);
if ((ret = http_request(url, data)) != GS_OK)
goto cleanup;

View File

@@ -27,6 +27,8 @@
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <pwd.h>
#include <sys/types.h>
#define MOONLIGHT_PATH "/moonlight"
#define USER_PATHS "."
@@ -76,6 +78,11 @@ char* get_path(char* name, char* extra_data_dirs) {
return name;
}
if (!home_dir) {
struct passwd *pw = getpwuid(getuid());
home_dir = pw->pw_dir;
}
if (!extra_data_dirs)
extra_data_dirs = "/usr/share:/usr/local/share";
if (!xdg_config_dir)
@@ -335,13 +342,14 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
config_save(config->config_file, config);
if (config->key_dir[0] == 0x0) {
const char *xdg_cache_dir = getenv("XDG_CACHE_DIR");
if (xdg_cache_dir != NULL)
sprintf(config->key_dir, "%s" MOONLIGHT_PATH, xdg_cache_dir);
else {
const char *home_dir = getenv("HOME");
sprintf(config->key_dir, "%s" DEFAULT_CACHE_DIR MOONLIGHT_PATH, home_dir);
}
struct passwd *pw = getpwuid(getuid());
const char *dir;
if ((dir = getenv("XDG_CACHE_DIR")) != NULL)
sprintf(config->key_dir, "%s" MOONLIGHT_PATH, dir);
else if ((dir = getenv("HOME")) != NULL)
sprintf(config->key_dir, "%s" DEFAULT_CACHE_DIR MOONLIGHT_PATH, dir);
else
sprintf(config->key_dir, "%s" DEFAULT_CACHE_DIR MOONLIGHT_PATH, pw->pw_dir);
}
if (config->stream.fps == -1)

View File

@@ -84,6 +84,8 @@ static int numDevices = 0;
static int assignedControllerIds = 0;
static short* currentKey;
static short* currentHat;
static short* currentHatDir;
static short* currentAbs;
static bool* currentReverse;
@@ -243,6 +245,7 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
mouseCode = BUTTON_RIGHT;
break;
default:
gamepadModified = true;
if (dev->map == NULL)
break;
else if (index == dev->map->btn_a)
@@ -279,9 +282,8 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
if (mouseCode != 0) {
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
gamepadModified = false;
} else if (gamepadCode != 0) {
gamepadModified = true;
if (ev->value)
dev->buttonFlags |= gamepadCode;
else
@@ -366,28 +368,41 @@ static bool evdev_handle_event(struct input_event *ev, struct input_device *dev)
}
static bool evdev_handle_mapping_event(struct input_event *ev, struct input_device *dev) {
int index, hat_index;
switch (ev->type) {
case EV_KEY:
index = ev->code > BTN_MISC && ev->code < (BTN_MISC + KEY_MAX) ? dev->key_map[ev->code - BTN_MISC] : -1;
if (currentKey != NULL) {
if (ev->value)
*currentKey = ev->code;
else if (ev->code == *currentKey)
*currentKey = index;
else if (*currentKey != -1 && index == *currentKey)
return false;
}
break;
case EV_ABS:
hat_index = (ev->code - ABS_HAT0X) / 2;
if (hat_index >= 0 && hat_index < 4) {
int hat_dir_index = (ev->code - ABS_HAT0X) % 2;
dev->hats_state[hat_index][hat_dir_index] = ev->value < 0 ? -1 : (ev->value == 0 ? 0 : 1);
}
if (currentAbs != NULL) {
struct input_abs_parms parms;
evdev_init_parms(dev, &parms, ev->code);
if (ev->value > parms.avg + parms.range/2) {
*currentAbs = ev->code;
*currentAbs = dev->abs_map[ev->code];
*currentReverse = false;
} else if (ev->value < parms.avg - parms.range/2) {
*currentAbs = ev->code;
*currentAbs = dev->abs_map[ev->code];
*currentReverse = true;
} else if (ev->code == *currentAbs)
return false;
} else if (currentHat != NULL) {
if (hat_index >= 0 && hat_index < 4) {
*currentHat = hat_index;
*currentHatDir = hat_constants[dev->hats_state[hat_index][1] + 1][dev->hats_state[hat_index][0] + 1];
return false;
}
}
break;
}
@@ -403,7 +418,7 @@ static void evdev_drain(void) {
static int evdev_handle(int fd) {
for (int i=0;i<numDevices;i++) {
if (devices[i].fd = fd) {
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) {
@@ -537,6 +552,117 @@ void evdev_create(const char* device, struct mapping* mappings, bool verbose) {
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;
currentHat = NULL;
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;
currentHat = NULL;
currentAbs = abs;
currentReverse = reverse;
*abs = -1;
loop_main();
usleep(250000);
evdev_drain();
}
static void evdev_map_hatkey(char* keyName, short* hat, short* hat_dir, short* key) {
printf("Press %s\n", keyName);
currentKey = key;
currentHat = hat;
currentHatDir = hat_dir;
currentAbs = NULL;
*key = -1;
*hat = -1;
*hat_dir = -1;
*currentReverse = false;
loop_main();
usleep(250000);
evdev_drain();
}
static void evdev_map_abskey(char* keyName, short* abs, short* key, bool* reverse) {
printf("Press %s\n", keyName);
currentKey = key;
currentHat = NULL;
currentAbs = abs;
currentReverse = reverse;
*key = -1;
*abs = -1;
*currentReverse = false;
loop_main();
usleep(250000);
evdev_drain();
}
void evdev_map(char* device) {
int fd = open(device, O_RDONLY|O_NONBLOCK);
struct libevdev *evdev = libevdev_new();
libevdev_set_fd(evdev, fd);
const char* name = libevdev_get_name(evdev);
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]);
struct mapping map;
strncpy(map.name, libevdev_get_name(evdev), sizeof(map.name));
strncpy(map.guid, str_guid, sizeof(map.name));
libevdev_free(evdev);
close(fd);
handler = evdev_handle_mapping_event;
evdev_map_abs("Left Stick Right", &(map.abs_leftx), &(map.reverse_leftx));
evdev_map_abs("Left Stick Up", &(map.abs_lefty), &(map.reverse_lefty));
evdev_map_key("Left Stick Button", &(map.btn_leftstick));
evdev_map_abs("Right Stick Right", &(map.abs_rightx), &(map.reverse_rightx));
evdev_map_abs("Right Stick Up", &(map.abs_righty), &(map.reverse_righty));
evdev_map_key("Right Stick Button", &(map.btn_rightstick));
evdev_map_hatkey("D-Pad Right", &(map.hat_dpright), &(map.hat_dir_dpright), &(map.btn_dpright));
evdev_map_hatkey("D-Pad Left", &(map.hat_dpleft), &(map.hat_dir_dpleft), &(map.btn_dpleft));
evdev_map_hatkey("D-Pad Up", &(map.hat_dpup), &(map.hat_dir_dpup), &(map.btn_dpup));
evdev_map_hatkey("D-Pad Down", &(map.hat_dpdown), &(map.hat_dir_dpdown), &(map.btn_dpdown));
evdev_map_key("Button X (1)", &(map.btn_x));
evdev_map_key("Button A (2)", &(map.btn_a));
evdev_map_key("Button B (3)", &(map.btn_b));
evdev_map_key("Button Y (4)", &(map.btn_y));
evdev_map_key("Back Button", &(map.btn_back));
evdev_map_key("Start Button", &(map.btn_start));
evdev_map_key("Special Button", &(map.btn_guide));
bool ignored;
evdev_map_abskey("Left Trigger", &(map.abs_lefttrigger), &(map.btn_lefttrigger), &ignored);
evdev_map_abskey("Right Trigger", &(map.abs_righttrigger), &(map.btn_righttrigger), &ignored);
evdev_map_key("Left Bumper", &(map.btn_leftshoulder));
evdev_map_key("Right Bumper", &(map.btn_rightshoulder));
mapping_print(&map);
}
void evdev_start() {
// After grabbing, the only way to quit via the keyboard
// is via the special key combo that the input handling

View File

@@ -25,3 +25,4 @@ void evdev_loop();
void evdev_init();
void evdev_start();
void evdev_stop();
void evdev_map(char* device);

View File

@@ -155,3 +155,39 @@ struct mapping* mapping_load(char* fileName, bool verbose) {
return mappings;
}
#define print_btn(btn, code) if (code > -1) printf("%s:b%d,", btn, code)
#define print_abs(abs, code) if (code > -1) printf("%s:a%d,", abs, code)
#define print_hat(hat, code, dir) if (code > -1) printf("%s:h%d.%d,", hat, code, dir)
void mapping_print(struct mapping* map) {
printf("%s,%s,", map->guid, map->name);
print_btn("a", map->btn_a);
print_btn("b", map->btn_b);
print_btn("x", map->btn_x);
print_btn("y", map->btn_y);
print_btn("start", map->btn_start);
print_btn("guide", map->btn_guide);
print_btn("back", map->btn_back);
print_btn("leftstick", map->btn_leftstick);
print_btn("rightstick", map->btn_rightstick);
print_btn("leftshoulder", map->btn_leftshoulder);
print_btn("rightshoulder", map->btn_rightshoulder);
print_btn("dpup", map->btn_dpup);
print_btn("dpleft", map->btn_dpleft);
print_btn("dpdown", map->btn_dpdown);
print_btn("dpright", map->btn_dpright);
print_hat("dpup", map->hat_dpup, map->hat_dir_dpup);
print_hat("dpleft", map->hat_dpleft, map->hat_dir_dpleft);
print_hat("dpdown", map->hat_dpdown, map->hat_dir_dpdown);
print_hat("dpright", map->hat_dpright, map->hat_dir_dpright);
print_abs("leftx", map->abs_leftx);
print_abs("lefty", map->abs_lefty);
print_abs("rightx", map->abs_rightx);
print_abs("righty", map->abs_righty);
print_abs("lefttrigger", map->abs_lefttrigger);
print_abs("righttrigger", map->abs_righttrigger);
print_btn("lefttrigger", map->btn_lefttrigger);
print_btn("righttrigger", map->btn_righttrigger);
printf("platform:Linux\n");
}

View File

@@ -49,3 +49,4 @@ struct mapping {
struct mapping* mapping_parse(char* mapping);
struct mapping* mapping_load(char* fileName, bool verbose);
void mapping_print(struct mapping*);

View File

@@ -139,6 +139,7 @@ static void help() {
printf("\tstream\t\t\tStream computer to device\n");
printf("\tlist\t\t\tList available games and applications\n");
printf("\tquit\t\t\tQuit the application or game being streamed\n");
printf("\tmap\t\t\tCreate mapping for gamepad\n");
printf("\thelp\t\t\tShow this help\n");
printf("\n Global Options\n\n");
printf("\t-config <config>\tLoad configuration file\n");
@@ -194,6 +195,17 @@ int main(int argc, char* argv[]) {
if (config.debug_level > 0)
printf("Moonlight Embedded %d.%d.%d (%s)\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, COMPILE_OPTIONS);
if (strcmp("map", config.action) == 0) {
if (config.inputsCount != 1) {
printf("You need to specify one input device using -input.\n");
exit(-1);
}
evdev_create(config.inputs[0], NULL, config.debug_level > 0);
evdev_map(config.inputs[0]);
exit(0);
}
if (config.address == NULL) {
config.address = malloc(MAX_ADDRESS_SIZE);
if (config.address == NULL) {

View File

@@ -27,6 +27,7 @@
#endif
#include <Limelight.h>
#include <libavcodec/avcodec.h>
#include <stdlib.h>
#include <pthread.h>

View File

@@ -18,6 +18,7 @@
*/
#include <va/va.h>
#include <X11/Xlib.h>
int vaapi_init_lib();
int vaapi_init(AVCodecContext* decoder_ctx);

View File

@@ -22,7 +22,7 @@
#include "ffmpeg_vdpau.h"
#include <vdpau/vdpau.h>
#include <vdpau/vdpau_x11.h>
#include <libavutil/pixfmt.h>
#include <libavutil/imgutils.h>
#include <libavcodec/vdpau.h>

View File

@@ -34,6 +34,7 @@
#include <libv4l2.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/mxc_v4l2.h>
#include <linux/mxcfb.h>

View File

@@ -34,6 +34,8 @@
#include <X11/Xutil.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>