mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2026-02-16 10:30:47 +00:00
Merge branch 'master' into pc
This commit is contained in:
@@ -36,7 +36,6 @@ static OpusDecoder* decoder;
|
||||
static short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
|
||||
|
||||
static void audio_renderer_init() {
|
||||
printf("audio_renderer_init\n");
|
||||
int rc;
|
||||
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);
|
||||
|
||||
@@ -72,8 +71,7 @@ static void audio_renderer_init() {
|
||||
CHECK_RETURN(snd_pcm_prepare(handle));
|
||||
}
|
||||
|
||||
static void audio_renderer_release() {
|
||||
printf("audio_renderer_release\n");
|
||||
static void audio_renderer_cleanup() {
|
||||
if (decoder != NULL)
|
||||
opus_decoder_destroy(decoder);
|
||||
|
||||
@@ -101,8 +99,6 @@ static void audio_renderer_decode_and_play_sample(char* data, int length) {
|
||||
|
||||
AUDIO_RENDERER_CALLBACKS audio_callbacks = {
|
||||
.init = audio_renderer_init,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = audio_renderer_release,
|
||||
.cleanup = audio_renderer_cleanup,
|
||||
.decodeAndPlaySample = audio_renderer_decode_and_play_sample,
|
||||
};
|
||||
|
||||
37
src/client.c
37
src/client.c
@@ -72,8 +72,9 @@ static void client_load_unique_id() {
|
||||
static void client_load_cert() {
|
||||
FILE *fd = fopen(certificateFileName, "r");
|
||||
if (fd == NULL) {
|
||||
printf("Generating certificate\n");
|
||||
printf("Generating certificate...");
|
||||
struct CertKeyPair cert = generateCertKeyPair();
|
||||
printf("done\n");
|
||||
saveCertKeyPair(certificateFileName, p12FileName, keyFileName, cert);
|
||||
freeCertKeyPair(cert);
|
||||
fd = fopen(certificateFileName, "r");
|
||||
@@ -85,7 +86,7 @@ static void client_load_cert() {
|
||||
}
|
||||
|
||||
if (!(cert = PEM_read_X509(fd, NULL, NULL, NULL))) {
|
||||
printf("Error loading cert into memory.\n");
|
||||
fprintf(stderr, "Error loading cert into memory.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -123,7 +124,10 @@ static void client_load_server_status(const char *address) {
|
||||
|
||||
paired = pairedText != NULL && strcmp(pairedText, "1") == 0;
|
||||
currentGame = currentGameText == NULL ? 0 : atoi(currentGameText);
|
||||
strstr(versionText, ".")[0] = 0;
|
||||
char *versionSep = strstr(versionText, ".");
|
||||
if (versionSep != NULL) {
|
||||
*versionSep = 0;
|
||||
}
|
||||
serverMajorVersion = atoi(versionText);
|
||||
|
||||
free(pairedText);
|
||||
@@ -146,62 +150,62 @@ static int sign_it(const char *msg, size_t mlen, unsigned char **sig, size_t *sl
|
||||
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
if (ctx == NULL) {
|
||||
printf("EVP_MD_CTX_create failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_MD_CTX_create failed, error 0x%lx\n", ERR_get_error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
const EVP_MD *md = EVP_get_digestbyname("SHA256");
|
||||
if (md == NULL) {
|
||||
printf("EVP_get_digestbyname failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_get_digestbyname failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
int rc = EVP_DigestInit_ex(ctx, md, NULL);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestInit_ex failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestInit_ex failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignInit failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignInit failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = EVP_DigestSignUpdate(ctx, msg, mlen);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignUpdate failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignUpdate failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
size_t req = 0;
|
||||
rc = EVP_DigestSignFinal(ctx, NULL, &req);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignFinal failed (1), error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (1), error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(req > 0)) {
|
||||
printf("EVP_DigestSignFinal failed (2), error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (2), error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*sig = OPENSSL_malloc(req);
|
||||
if (*sig == NULL) {
|
||||
printf("OPENSSL_malloc failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "OPENSSL_malloc failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*slen = req;
|
||||
rc = EVP_DigestSignFinal(ctx, *sig, slen);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignFinal failed (3), return code %d, error 0x%lx\n", rc,
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (3), return code %d, error 0x%lx\n", rc,
|
||||
ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req != *slen) {
|
||||
printf("EVP_DigestSignFinal failed, mismatched signature sizes %ld, %ld\n",
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed, mismatched signature sizes %ld, %ld\n",
|
||||
req, *slen);
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -223,6 +227,11 @@ void client_pair(const char *address) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentGame != 0) {
|
||||
fprintf(stderr, "The computer is currently in a game. You must close the game before pairing.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char pin[5];
|
||||
sprintf(pin, "%d%d%d%d", (int)random() % 10, (int)random() % 10, (int)random() % 10, (int)random() % 10);
|
||||
printf("Please enter the following PIN on the target PC: %s\n", pin);
|
||||
@@ -305,7 +314,7 @@ void client_pair(const char *address) {
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", address, unique_id, client_pairing_secret_hex);
|
||||
http_request(url, data);
|
||||
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, unique_id, challenge_response_hex);
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, unique_id);
|
||||
http_request(url, data);
|
||||
http_free_data(data);
|
||||
|
||||
|
||||
@@ -18,49 +18,30 @@
|
||||
*/
|
||||
|
||||
#include "connection.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void connection_stage_starting(int stage)
|
||||
{
|
||||
printf("connection_stage_starting %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_stage_complete(int stage)
|
||||
{
|
||||
printf("connection_stage_complete %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_stage_failed(int stage, long iets)
|
||||
{
|
||||
printf("connection_stage_failed %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_connection_started()
|
||||
{
|
||||
printf("connection_connection_started\n");
|
||||
}
|
||||
|
||||
void connection_connection_terminated()
|
||||
{
|
||||
printf("connection_connection_terminated\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
void connection_display_message(char *msg)
|
||||
{
|
||||
printf("connection_display_message: %s\n", msg);
|
||||
printf("%s\n", msg);
|
||||
}
|
||||
|
||||
void connection_display_transient_message(char *msg)
|
||||
{
|
||||
printf("connection_display_transient_message: %s\n", msg);
|
||||
printf("%s\n", msg);
|
||||
}
|
||||
|
||||
CONNECTION_LISTENER_CALLBACKS connection_callbacks = {
|
||||
.stageStarting = connection_stage_starting,
|
||||
.stageComplete = connection_stage_complete,
|
||||
.stageFailed = connection_stage_failed,
|
||||
.connectionStarted = connection_connection_started,
|
||||
.stageStarting = NULL,
|
||||
.stageComplete = NULL,
|
||||
.stageFailed = NULL,
|
||||
.connectionStarted = NULL,
|
||||
.connectionTerminated = connection_connection_terminated,
|
||||
.displayMessage = connection_display_message,
|
||||
.displayTransientMessage = connection_display_transient_message,
|
||||
|
||||
27
src/global.c
Normal file
27
src/global.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_t main_thread_id;
|
||||
|
||||
void quit() {
|
||||
pthread_kill(main_thread_id, SIGTERM);
|
||||
}
|
||||
24
src/global.h
Normal file
24
src/global.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 <pthread.h>
|
||||
|
||||
extern pthread_t main_thread_id;
|
||||
|
||||
void quit();
|
||||
@@ -56,6 +56,7 @@ void http_init() {
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyFile);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _write_curl);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
||||
}
|
||||
|
||||
int http_request(char* url, struct http_data* data) {
|
||||
|
||||
215
src/input.c
215
src/input.c
@@ -19,21 +19,30 @@
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "mapping.h"
|
||||
#include "global.h"
|
||||
|
||||
#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>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
struct input_abs_parms {
|
||||
int min, max;
|
||||
@@ -51,7 +60,7 @@ struct input_device {
|
||||
__s32 mouseDeltaX, mouseDeltaY, mouseScroll;
|
||||
short controllerId;
|
||||
int buttonFlags;
|
||||
short leftTrigger, rightTrigger;
|
||||
char leftTrigger, rightTrigger;
|
||||
short leftStickX, leftStickY;
|
||||
short rightStickX, rightStickY;
|
||||
bool gamepadModified;
|
||||
@@ -74,6 +83,91 @@ static struct udev *udev;
|
||||
static struct udev_monitor *udev_mon;
|
||||
static int udev_fdindex;
|
||||
|
||||
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) {
|
||||
parms->flat = libevdev_get_abs_flat(dev->dev, code);
|
||||
parms->min = libevdev_get_abs_minimum(dev->dev, code);
|
||||
@@ -109,6 +203,7 @@ void input_create(const char* device, char* mapFile) {
|
||||
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);
|
||||
@@ -141,11 +236,15 @@ static void input_remove(int devindex) {
|
||||
if (fdindex != numFds && numFds > 0) {
|
||||
memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd));
|
||||
if (numFds == udev_fdindex)
|
||||
udev_fdindex = numFds;
|
||||
udev_fdindex = fdindex;
|
||||
else if (numFds == sig_fdindex)
|
||||
sig_fdindex = fdindex;
|
||||
else {
|
||||
for (int i=0;i<numDevices;i++) {
|
||||
if (devices[i].fdindex == numFds)
|
||||
if (devices[i].fdindex == numFds) {
|
||||
devices[i].fdindex = fdindex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,13 +255,18 @@ static void input_remove(int devindex) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (autoadd = numDevices == 0) {
|
||||
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);
|
||||
@@ -187,11 +291,11 @@ void input_init(char* mapfile) {
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
|
||||
udev_monitor_enable_receiving(udev_mon);
|
||||
|
||||
int udev_fdindex = numFds;
|
||||
numFds++;
|
||||
udev_fdindex = numFds++;
|
||||
sig_fdindex = numFds++;
|
||||
|
||||
if (fds == NULL)
|
||||
fds = malloc(sizeof(struct pollfd));
|
||||
fds = malloc(sizeof(struct pollfd)*numFds);
|
||||
else
|
||||
fds = realloc(fds, sizeof(struct pollfd)*numFds);
|
||||
|
||||
@@ -203,6 +307,17 @@ void input_init(char* mapfile) {
|
||||
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() {
|
||||
@@ -216,10 +331,10 @@ static short input_convert_value(struct input_event *ev, struct input_device *de
|
||||
return reverse?SHRT_MIN:SHRT_MAX;
|
||||
else if (ev->value < parms->min)
|
||||
return reverse?SHRT_MAX:SHRT_MIN;
|
||||
else {
|
||||
int value = ev->value + (ev->value<parms->avg?parms->flat:-parms->flat);
|
||||
return (value-parms->avg) * SHRT_MAX / ((reverse?-parms->range-1:parms->range) - parms->flat);
|
||||
}
|
||||
else if (reverse)
|
||||
return (parms->max - (ev->value<parms->avg?parms->flat*2:0) - ev->value) * (SHRT_MAX-SHRT_MIN) / (parms->max-parms->min-parms->flat*2) - SHRT_MIN;
|
||||
else
|
||||
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) {
|
||||
@@ -228,7 +343,7 @@ static char input_convert_value_byte(struct input_event *ev, struct input_device
|
||||
else if (ev->value>parms->max)
|
||||
return UCHAR_MAX;
|
||||
else {
|
||||
int value = ev->value + parms->flat;
|
||||
int value = ev->value - parms->flat;
|
||||
return (value-parms->min) * UCHAR_MAX / (parms->diff-parms->flat);
|
||||
}
|
||||
}
|
||||
@@ -345,20 +460,20 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
gamepadCode = SPECIAL_FLAG;
|
||||
}
|
||||
|
||||
if (mouseCode > 0) {
|
||||
if (mouseCode != 0) {
|
||||
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
|
||||
} else {
|
||||
gamepadModified = true;
|
||||
|
||||
if (gamepadCode > 0) {
|
||||
if (gamepadCode != 0) {
|
||||
if (ev->value)
|
||||
dev->buttonFlags |= gamepadCode;
|
||||
else
|
||||
dev->buttonFlags &= ~gamepadCode;
|
||||
} else if (ev->code == dev->map.btn_tl2)
|
||||
dev->leftTrigger = ev->value?USHRT_MAX:0;
|
||||
dev->leftTrigger = ev->value?UCHAR_MAX:0;
|
||||
else if (ev->code == dev->map.btn_tr2)
|
||||
dev->rightTrigger = ev->value?USHRT_MAX:0;
|
||||
dev->rightTrigger = ev->value?UCHAR_MAX:0;
|
||||
else
|
||||
gamepadModified = false;
|
||||
}
|
||||
@@ -372,7 +487,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
case REL_Y:
|
||||
dev->mouseDeltaY = ev->value;
|
||||
break;
|
||||
case REL_Z:
|
||||
case REL_WHEEL:
|
||||
dev->mouseScroll = ev->value;
|
||||
break;
|
||||
}
|
||||
@@ -396,7 +511,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else if (dir == -1) {
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else {
|
||||
@@ -406,11 +521,11 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
} else if (ev->code == dev->map.abs_dpad_y) {
|
||||
int dir = input_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_dpad_y);
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= UP_FLAG;
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
} else if (dir == -1) {
|
||||
dev->buttonFlags |= DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags |= UP_FLAG;
|
||||
@@ -454,7 +569,14 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
|
||||
return true;
|
||||
}
|
||||
|
||||
static void input_poll(bool (*handler) (struct input_event*, struct input_device*)) {
|
||||
static void input_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);
|
||||
@@ -469,6 +591,17 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
}
|
||||
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) {
|
||||
@@ -479,7 +612,7 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
fprintf(stderr, "Error: cannot keep up\n");
|
||||
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||
if (!handler(&ev, &devices[i]))
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (rc == -ENODEV) {
|
||||
@@ -491,6 +624,8 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void input_map_key(char* keyName, short* key) {
|
||||
@@ -498,38 +633,50 @@ static void input_map_key(char* keyName, short* key) {
|
||||
currentKey = key;
|
||||
currentAbs = NULL;
|
||||
*key = -1;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
static void input_map_abs(char* keyName, short* abs, bool* reverse) {
|
||||
printf("%s\n", keyName);
|
||||
printf("Move %s\n", keyName);
|
||||
currentKey = NULL;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*abs = -1;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
static void input_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
|
||||
printf("%s\n", keyName);
|
||||
printf("Press %s\n", keyName);
|
||||
currentKey = key;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*key = -1;
|
||||
*abs = -1;
|
||||
*currentReverse = false;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
void input_map(char* fileName) {
|
||||
struct mapping map;
|
||||
|
||||
input_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x));
|
||||
input_map_abs("Left Stick Down", &(map.abs_y), &(map.reverse_y));
|
||||
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));
|
||||
input_map_abs("Right Stick Down", &(map.abs_ry), &(map.reverse_ry));
|
||||
input_map_abs("Right Stick Up", &(map.abs_ry), &(map.reverse_ry));
|
||||
input_map_key("Right Stick Button", &(map.btn_thumbr));
|
||||
|
||||
input_map_abskey("D-Pad Right", &(map.btn_dpad_right), &(map.abs_dpad_x), &(map.reverse_dpad_x));
|
||||
@@ -553,11 +700,11 @@ void input_map(char* fileName) {
|
||||
input_map_key("Special Button", &(map.btn_mode));
|
||||
|
||||
bool ignored;
|
||||
input_map_abskey("Left Trigger", &(map.btn_tl), &(map.abs_z), &ignored);
|
||||
input_map_abskey("Right Trigger", &(map.btn_tr), &(map.abs_rz), &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);
|
||||
|
||||
input_map_key("Left Bumper", &(map.btn_tl2));
|
||||
input_map_key("Right Bumper", &(map.btn_tr2));
|
||||
input_map_key("Left Bumper", &(map.btn_tl));
|
||||
input_map_key("Right Bumper", &(map.btn_tr));
|
||||
mapping_save(fileName, &map);
|
||||
}
|
||||
|
||||
|
||||
21
src/main.c
21
src/main.c
@@ -53,7 +53,7 @@ static void applist(const char* address) {
|
||||
static void stream(STREAM_CONFIGURATION* config, const char* address, const char* app, bool sops, bool localaudio) {
|
||||
int appId = client_get_app_id(address, app);
|
||||
if (appId<0) {
|
||||
printf("Can't find app %s\n", app);
|
||||
fprintf(stderr, "Can't find app %s\n", app);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -61,20 +61,7 @@ static void stream(STREAM_CONFIGURATION* config, const char* address, const char
|
||||
|
||||
video_init();
|
||||
|
||||
struct addrinfo hints, *res;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int err = getaddrinfo(address, NULL, &hints, &res);
|
||||
if (err<0 || res == NULL) {
|
||||
printf("Can't resolve host: %s\n", address);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct sockaddr_in *addr = (struct sockaddr_in*)res->ai_addr;
|
||||
LiStartConnection(addr->sin_addr.s_addr, config, NULL, decoder_callbacks,
|
||||
&audio_callbacks, NULL, NULL, 0, client_get_server_version());
|
||||
freeaddrinfo(res);
|
||||
LiStartConnection(address, config, &connection_callbacks, decoder_callbacks, &audio_callbacks, NULL, NULL, 0, client_get_server_version());
|
||||
|
||||
input_loop();
|
||||
|
||||
@@ -147,7 +134,7 @@ char* get_path(char* name) {
|
||||
|
||||
static void pair_check(void) {
|
||||
if (!client_is_paired(NULL)) {
|
||||
printf("You must pair with the PC first\n");
|
||||
fprintf(stderr, "You must pair with the PC first\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@@ -265,7 +252,7 @@ int main(int argc, char* argv[]) {
|
||||
address[0] = 0;
|
||||
discover_server(address);
|
||||
if (address[0] == 0) {
|
||||
perror("Can't find server");
|
||||
fprintf(stderr, "Autodiscovery failed. Specify an IP address next time.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +100,11 @@ void mapping_load(char* fileName, struct mapping* map) {
|
||||
else if (strcmp("reverse_ry", key) == 0)
|
||||
map->reverse_ry = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_x", key) == 0)
|
||||
map->reverse_x = strcmp("true", value) == 0;
|
||||
map->reverse_dpad_x = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_y", key) == 0)
|
||||
map->reverse_y = strcmp("true", value) == 0;
|
||||
map->reverse_dpad_y = strcmp("true", value) == 0;
|
||||
else
|
||||
printf("Can't map (%s)\n", key);
|
||||
fprintf(stderr, "Can't map (%s)\n", key);
|
||||
}
|
||||
if (key != NULL)
|
||||
free(key);
|
||||
|
||||
@@ -49,7 +49,7 @@ struct CertKeyPair generateCertKeyPair() {
|
||||
|
||||
p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0);
|
||||
if (p12 == NULL) {
|
||||
printf("Error generating a valid PKCS12 certificate.\n");
|
||||
fprintf(stderr, "Error generating a valid PKCS12 certificate.\n");
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
|
||||
19
src/video.c
19
src/video.c
@@ -27,7 +27,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
DECODER_RENDERER_CALLBACKS *decoder_callbacks;
|
||||
char* decoder_output_name;
|
||||
|
||||
static int decoder_level;
|
||||
|
||||
@@ -37,22 +36,14 @@ void video_init() {
|
||||
#else
|
||||
decoder_callbacks = &decoder_callbacks_fake;
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
if (dlsym(RTLD_DEFAULT, "vpu_Init") != NULL && video_imx_init()) {
|
||||
decoder_callbacks = &decoder_callbacks_imx;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OMX
|
||||
if (dlsym(RTLD_DEFAULT, "bcm_host_init") != NULL) {
|
||||
decoder_callbacks = &decoder_callbacks_omx;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
if (dlsym(RTLD_DEFAULT, "vpu_Init") != NULL) {
|
||||
decoder_callbacks = &decoder_callbacks_imx;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int video_add_output(int level, char* name, DECODER_RENDERER_CALLBACKS *callbacks) {
|
||||
if (level > decoder_level) {
|
||||
decoder_output_name = name;
|
||||
decoder_level = level;
|
||||
decoder_callbacks = callbacks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "limelight-common/Limelight.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern DECODER_RENDERER_CALLBACKS *decoder_callbacks;
|
||||
|
||||
void video_init();
|
||||
@@ -31,5 +33,6 @@ extern DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl;
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx;
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx;
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_imx;
|
||||
bool video_imx_init();
|
||||
#endif
|
||||
|
||||
@@ -25,12 +25,10 @@ static FILE* fd;
|
||||
static const char* fileName = "fake.h264";
|
||||
|
||||
void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
printf("decoder_renderer_setup %dx%d %dfps\n", width, height, redrawRate);
|
||||
fd = fopen(fileName, "w");
|
||||
}
|
||||
|
||||
void decoder_renderer_release() {
|
||||
printf("decoder_renderer_release\n");
|
||||
void decoder_renderer_cleanup() {
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
@@ -45,8 +43,6 @@ int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_fake = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#include "../video.h"
|
||||
|
||||
#include "vpu_io.h"
|
||||
#include "vpu_lib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -43,6 +40,9 @@
|
||||
#include <linux/v4l2-controls.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <vpu_io.h>
|
||||
#include <vpu_lib.h>
|
||||
|
||||
#define STREAM_BUF_SIZE 0x200000
|
||||
#define PS_SAVE_SIZE 0x080000
|
||||
|
||||
@@ -72,6 +72,10 @@ static int disp_clr_index = 0;
|
||||
static FrameBuffer *fb;
|
||||
static struct v4l2_buffer dbuf;
|
||||
|
||||
bool video_imx_init() {
|
||||
return vpu_Init(NULL) == RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
struct mxcfb_gbl_alpha alpha;
|
||||
|
||||
@@ -94,11 +98,6 @@ static void decoder_renderer_setup(int width, int height, int redrawRate, void*
|
||||
|
||||
close(fd_fb);
|
||||
|
||||
if (vpu_Init(NULL) != RETCODE_SUCCESS){
|
||||
fprintf(stderr, "Can't intialize VPU\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mem_desc.size = STREAM_BUF_SIZE;
|
||||
if (IOGetPhyMem(&mem_desc)){
|
||||
fprintf(stderr, "Can't get physical memory address\n");
|
||||
@@ -413,7 +412,7 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
return DR_OK;
|
||||
}
|
||||
|
||||
static void decoder_renderer_release() {
|
||||
static void decoder_renderer_cleanup() {
|
||||
IOFreePhyMem(&ps_mem_desc);
|
||||
IOFreePhyMem(&slice_mem_desc);
|
||||
|
||||
@@ -424,8 +423,6 @@ static void decoder_renderer_release() {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_imx = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
||||
@@ -30,14 +30,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../video.h"
|
||||
|
||||
#include "bcm_host.h"
|
||||
#include "ilclient.h"
|
||||
#include "h264_stream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ilclient.h>
|
||||
#include <bcm_host.h>
|
||||
|
||||
static TUNNEL_T tunnel[2];
|
||||
static COMPONENT_T *list[3];
|
||||
static ILCLIENT_T *client;
|
||||
@@ -129,7 +130,7 @@ static void decoder_renderer_setup(int width, int height, int redrawRate, void*
|
||||
}
|
||||
}
|
||||
|
||||
static void decoder_renderer_stop() {
|
||||
static void decoder_renderer_cleanup() {
|
||||
int status = 0;
|
||||
|
||||
buf->nFilledLen = 0;
|
||||
@@ -144,9 +145,7 @@ static void decoder_renderer_stop() {
|
||||
ilclient_flush_tunnels(tunnel, 0);
|
||||
|
||||
ilclient_disable_port_buffers(list[0], 130, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void decoder_renderer_release() {
|
||||
ilclient_disable_tunnel(tunnel);
|
||||
ilclient_teardown_tunnels(tunnel);
|
||||
|
||||
@@ -227,8 +226,6 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_omx = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = decoder_renderer_stop,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ static void sdl_setup(int width, int height, int redrawRate, void* context, int
|
||||
screen_height = height;
|
||||
}
|
||||
|
||||
static void sdl_release() {
|
||||
static void sdl_cleanup() {
|
||||
ffmpeg_destroy();
|
||||
}
|
||||
|
||||
@@ -109,8 +109,6 @@ static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl = {
|
||||
.setup = sdl_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = sdl_release,
|
||||
.cleanup = sdl_cleanup,
|
||||
.submitDecodeUnit = sdl_submit_decode_unit,
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
struct xml_query search;
|
||||
search.data = node;
|
||||
search.start = 0;
|
||||
search.memory = malloc(1);
|
||||
search.memory = calloc(1, 1);
|
||||
search.size = 0;
|
||||
XML_Parser parser = XML_ParserCreate("UTF-8");
|
||||
XML_SetUserData(parser, &search);
|
||||
@@ -100,7 +100,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
XML_SetCharacterDataHandler(parser, _xml_write_data);
|
||||
if (! XML_Parse(parser, data, len, 1)) {
|
||||
int code = XML_GetErrorCode(parser);
|
||||
printf("%s\n", XML_ErrorString(code));
|
||||
fprintf(stderr, "XML Error: %s\n", XML_ErrorString(code));
|
||||
return 1;
|
||||
}
|
||||
*result = search.memory;
|
||||
@@ -110,7 +110,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
|
||||
struct app_list* xml_applist(char* data, size_t len) {
|
||||
struct xml_query query;
|
||||
query.memory = malloc(1);
|
||||
query.memory = calloc(1, 1);
|
||||
query.size = 0;
|
||||
query.start = 0;
|
||||
query.data = NULL;
|
||||
@@ -120,7 +120,7 @@ struct app_list* xml_applist(char* data, size_t len) {
|
||||
XML_SetCharacterDataHandler(parser, _xml_write_data);
|
||||
if (! XML_Parse(parser, data, len, 1)) {
|
||||
int code = XML_GetErrorCode(parser);
|
||||
printf("%s\n", XML_ErrorString(code));
|
||||
fprintf(stderr, "XML Error %s\n", XML_ErrorString(code));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user