Merge branch 'master' into pc

This commit is contained in:
Iwan Timmer 2015-06-27 12:53:14 +02:00
commit e1ae9f4874
43 changed files with 834 additions and 187 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "common"]
path = common
path = third_party/moonlight-common-c
url = https://github.com/irtimmer/moonlight-common-c.git

View File

@ -6,10 +6,10 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
aux_source_directory(./src SRC_LIST)
list(APPEND SRC_LIST ./src/video/fake.c)
aux_source_directory(./common/limelight-common SRC_LIST)
aux_source_directory(./common/limelight-common/OpenAES SRC_LIST)
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(./common)
include_directories(./third_party/moonlight-common-c)
set(MOONLIGHT_DEFINITIONS)
@ -21,6 +21,7 @@ find_package(ALSA REQUIRED)
find_package(Opus REQUIRED)
find_package(Broadcom)
find_package(Freescale)
find_package(CEC)
find_package(PkgConfig REQUIRED)
pkg_check_modules(EVDEV REQUIRED libevdev)
@ -31,9 +32,14 @@ pkg_check_modules(AVCODEC libavcodec)
pkg_check_modules(AVUTIL libavutil)
pkg_check_modules(SWSCALE libswscale)
if(CEC_FOUND)
include_directories(./third_party/libcec)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
endif()
if(BROADCOM_FOUND)
aux_source_directory(./ilclient SRC_LIST)
aux_source_directory(./h264bitstream SRC_LIST)
aux_source_directory(./third_party/ilclient SRC_LIST)
aux_source_directory(./third_party/h264bitstream SRC_LIST)
list(APPEND SRC_LIST ./src/video/omx.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX)
endif()
@ -52,7 +58,7 @@ add_executable(moonlight ${SRC_LIST})
set_property(TARGET moonlight PROPERTY C_STANDARD 11)
if(BROADCOM_FOUND)
include_directories(./ilclient ./h264bitstream ${BROADCOM_INCLUDE_DIRS})
include_directories(./third_party/ilclient ./third_party/h264bitstream ${BROADCOM_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif()
@ -68,8 +74,8 @@ if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND AND SDL_FOUND)
endif()
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS})
include_directories(./moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${AVAHI_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})
include_directories(./third_party/moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${AVAHI_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS} ${CEC_INCLUDE_DIRS})
target_link_libraries (moonlight PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY} ${AVAHI_LIBRARIES} ${UDEV_LIBRARIES} ${CMAKE_DL_LIBS} ${CEC_LIBRARIES})
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
install(TARGETS moonlight DESTINATION ${CMAKE_INSTALL_BINDIR})

129
README.md
View File

@ -8,31 +8,12 @@ your powerful Windows desktop to your embedded system, like Raspberry Pi, CuBox-
For a demo see this [video](https://www.youtube.com/watch?v=XRW6O0bSHNw).
[Moonlight-common-c](https://github.com/moonlight-stream/moonlight-common-c) is the shared codebase between
different C implementations of Moonlight
[Moonlight](https://github.com/moonlight-stream/moonlight-android) also has an Android
implementation.
[Moonlight-pc](https://github.com/moonlight-stream/moonlight-pc) also has an Linux/OSX/Windows
implementation.
[Moonlight iOS](https://github.com/moonlight-stream/moonlight-ios) also has an iOS
implementation.
[Moonlight Windows](https://github.com/moonlight-stream/moonlight-windows) also has an Windows and Windows Phone
implementation.
##Features
* Streams Steam and all of your games from your PC to your embedded system.
##Installation
* Download [GeForce Experience](http://www.geforce.com/geforce-experience) and install on your Windows PC
* Download the compiled version from the [GitHub releases page](https://github.com/irtimmer/moonlight-embedded/releases)
* Install libopus0 (Debian/Raspbian) or opus (Arch Linux/Fedora/Pidora)
* [Configure sound](http://elinux.org/R-Pi_Troubleshooting#Sound)
* Use mDNS to scan for compatible GeForce Experience (GFE) machines on the network.
* Qwerty Keyboard, Mouse and Gamepad support
* Support Raspberry Pi and i.MX 6 devices
##Requirements
@ -50,10 +31,12 @@ implementation.
* Play games!
##Usage
Usage: moonlight [options] host
Actions:
map Create mapping file for gamepad
pair Pair device with computer
stream Stream computer to device
list List available games and applications
@ -71,23 +54,117 @@ implementation.
-bitrate <bitrate> Specify the bitrate in Kbps
-packetsize <size> Specify the maximum packetsize in bytes
-app <app> Name of app to stream
-nosops Don't allow GFE to modify game settings
-input <device> Use <device> as input. Can be used multiple times
-mapping <file> Use <file> as gamepad mapping configuration file (use before -input)
-audio <device> Use <device> as ALSA audio output device (default sysdefault)
-localaudio Play audio locally
Use ctrl-c to exit application
##Compile
## Packages
Prebuilt binary packages for Raspbian Wheezy are available, add this line to your */etc/apt/sources.list*
```
deb http://archive.itimmer.nl/raspbian/moonlight wheezy main
```
* Install cmake
* Install cryptographics libraries libssl-dev (Debian/Raspbian) or openssl-devel (Fedora/Pidora) or openssl (Arch Linux)
* Install audio libraries libopus-dev and libasound2-dev (Debian/Raspbian) or opus-devel and alsa-lib-devel (Fedora/Pidora) or opus and alsa-lib (Arch Linux)
Install package using the following commands
```
apt-get update
apt-get install moonlight-embedded
```
Source package for ArchLinux is available in [AUR](https://aur.archlinux.org/packages/moonlight-embedded/)
Prebuilt binary packages for ArchLinux ARM are available, add those lines to you */etc/pacman.conf*
```
[moonlight]
Server = http://archive.itimmer.nl/archlinux/$repo/os/$arch
SigLevel = Optional
```
Install package using the following command
```
pacman -Sy moonlight-embedded
```
##Compile and install
* Download and extract Moonlight Embedded from release or git clone
* Install development dependencies (see Dependencies)
* Initialize the git submodules ``git submodule update --init``
* Build and install using the following commands
```
mkdir build
cd build/
cmake ../
make
make install
```
## Dependencies
### ArchLinux
Install with
```
pacman -S (package list)
```
* opus
* expat
* openssl
* alsa-lib
* avahi
* libevdev
For compilation and development you also need:
* cmake
### Debian (Raspbian)
Install with
```
apt-get install (package list)
```
* libopus0
* libexpat1
* libasound2
* libudev0
* libavahi-client3
* libcurl3
* libevdev2
For compilation and development you also need:
* libssl-dev
* libopus-dev
* libasound2-dev
* libudev-dev
* libavahi-client-dev
* libcurl4-openssl-dev
* libevdev-dev
* cmake
## See also
[Moonlight-common-c](https://github.com/moonlight-stream/moonlight-common-c) is the shared codebase between
different C implementations of Moonlight
[Moonlight-common-c](https://github.com/irtimmer/moonlight-common-c) is the used fork used by Moonlight Embedded
[Moonlight-common](https://github.com/moonlight-stream/moonlight-common) is the shared codebase between
different Java implementations of Moonlight
[Moonlight](https://github.com/moonlight-stream/moonlight-android) also has an Android
implementation.
[Moonlight-pc](https://github.com/moonlight-stream/moonlight-pc) also has an Linux/OSX/Windows
implementation.
[Moonlight iOS](https://github.com/moonlight-stream/moonlight-ios) also has an iOS
implementation.
[Moonlight Windows](https://github.com/moonlight-stream/moonlight-windows) also has an Windows and Windows Phone
implementation.
## Discussion
[XDA](http://forum.xda-developers.com/showthread.php?t=2505510)

19
cmake/FindCEC.cmake Normal file
View File

@ -0,0 +1,19 @@
# - Try to find CEC
# Once done this will define
#
# CEC_FOUND - system has libcec
# CEC_INCLUDE_DIRS - the libcec include directory
# CEC_LIBRARIES - The libcec libraries
if(PKG_CONFIG_FOUND)
pkg_check_modules (CEC libcec>=3.0.0)
else()
find_path(CEC_INCLUDE_DIRS libcec/cec.h)
find_library(CEC_LIBRARIES cec)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CEC DEFAULT_MSG CEC_INCLUDE_DIRS CEC_LIBRARIES)
list(APPEND CEC_DEFINITIONS -DHAVE_LIBCEC=1)
mark_as_advanced(CEC_INCLUDE_DIRS CEC_LIBRARIES CEC_DEFINITIONS)

1
common

@ -1 +0,0 @@
Subproject commit fcd2a20e01c202558fc0b9b923a6612d3fce8d50

6
debian/changelog vendored Normal file
View File

@ -0,0 +1,6 @@
moonlight-embedded (2.0.1-1) UNRELEASED; urgency=low
* Initial release
* This is my first Debian package
-- Iwan Timmer <irtimmer@gmail.com> Sat, 20 Jun 2015 11:58:32 +0000

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

14
debian/control vendored Normal file
View File

@ -0,0 +1,14 @@
Source: moonlight-embedded
Section: games
Priority: extra
Maintainer: Iwan Timmer <irtimmer@gmail.com>
Build-Depends: debhelper (>= 8.0.0), cmake, libopus-dev, libexpat1-dev, libasound2-dev, libudev-dev, libavahi-client-dev, libcurl4-openssl-dev, libevdev-dev, libraspberrypi-dev
Standards-Version: 3.9.3
Homepage: https://github.com/irtimmer/moonlight-embedded
Package: moonlight-embedded
Architecture: armhf
Depends: libopus0, libexpat1, libssl1.0.0, libasound2, libudev0, libavahi-client3, libcurl3, libevdev2, libraspberrypi0, ${shlibs:Depends}, ${misc:Depends}
Description: GameStream client for Linux
Game streaming client for Nvidia's GameStream.
Stream games from your Windows computer with Nvidia graphic card to your linux box.

22
debian/copyright vendored Normal file
View File

@ -0,0 +1,22 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: moonlight-embedded
Source: https://github.com/irtimmer/moonlight-embedded
Files: *
Copyright: 2014, 2015 Iwan Timmer <irtimmer@gmail.com>
License: GPL-3+
This package 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.
.
This package 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 this program. If not, see <http://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".

32
debian/patches/install.patch vendored Normal file
View File

@ -0,0 +1,32 @@
Compile using older version (2.8) of CMake
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
project(moonlight-embedded C)
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 2.8)
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -44,18 +44,18 @@
if(BROADCOM_FOUND)
include_directories(./third_party/ilclient ./third_party/h264bitstream ${BROADCOM_INCLUDE_DIRS})
- target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
+ target_link_libraries (moonlight ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif()
if(FREESCALE_FOUND)
include_directories(${FREESCALE_INCLUDE_DIRS})
- target_link_libraries (moonlight PUBLIC ${FREESCALE_LIBRARIES})
+ target_link_libraries (moonlight ${FREESCALE_LIBRARIES})
endif()
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS})
include_directories(./third_party/moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS} ${AVAHI_INCLUDE_DIRS} ${UDEV_INCLUDE_DIRS})
-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})
+target_link_libraries (moonlight ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY} ${AVAHI_LIBRARIES} ${UDEV_LIBRARIES} ${CMAKE_DL_LIBS})
include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
install(TARGETS moonlight DESTINATION ${CMAKE_INSTALL_BINDIR})

1
debian/patches/series vendored Normal file
View File

@ -0,0 +1 @@
install.patch

8
debian/rules vendored Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
export DEB_CFLAGS_MAINT_APPEND = -std=gnu99
%:
dh $@ --with quilt

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

View File

@ -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,
};

View File

@ -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);

View File

@ -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
View 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
View 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();

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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);
}

306
third_party/libcec/ceccloader.h vendored Normal file
View File

@ -0,0 +1,306 @@
#pragma once
/*
* This file is part of the libCEC(R) library.
*
* libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved.
* libCEC(R) is an original work, containing original code.
*
* libCEC(R) is a trademark of Pulse-Eight Limited.
*
* This program is dual-licensed; 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
* Alternatively, you can license this library under a commercial license,
* please contact Pulse-Eight Licensing for more information.
*
* For more information contact:
* Pulse-Eight Licensing <license@pulse-eight.com>
* http://www.pulse-eight.com/
* http://www.pulse-eight.net/
*/
#include "cecc.h"
#include <stdio.h>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <conio.h>
typedef HINSTANCE libcecc_lib_instance_t;
#else
#include <dlfcn.h>
typedef void* libcecc_lib_instance_t;
#ifndef CDECL
#define CDECL
#endif
#endif
static libcecc_lib_instance_t libcecc_load_library(const char* strLib);
static void libcecc_close_library(libcecc_lib_instance_t lib);
static void* libcecc_resolve(void* lib, const char* name);
#define _libcecc_resolve(lib, tar, name, method) \
do { \
tar = (method) libcecc_resolve(lib, name); \
if (tar == NULL) \
{ \
libcecc_close_library(lib); \
return -1; \
} \
} while(0)
typedef struct {
libcec_connection_t connection;
libcecc_lib_instance_t lib_instance;
void (CDECL *destroy)(libcec_connection_t connection);
int (CDECL *open)(libcec_connection_t connection, const char* strPort, uint32_t iTimeout);
void (CDECL *close)(libcec_connection_t connection);
void (CDECL *clear_configuration)(CEC_NAMESPACE libcec_configuration* configuration);
int (CDECL *enable_callbacks)(libcec_connection_t connection, void* cbParam, CEC_NAMESPACE ICECCallbacks* callbacks);
int8_t (CDECL *find_adapters)(libcec_connection_t connection, CEC_NAMESPACE cec_adapter* deviceList, uint8_t iBufSize, const char* strDevicePath);
int (CDECL *ping_adapters)(libcec_connection_t connection);
int (CDECL *start_bootloader)(libcec_connection_t connection);
int (CDECL *power_on_devices)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
int (CDECL *standby_devices)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
int (CDECL *set_active_source)(libcec_connection_t connection, CEC_NAMESPACE cec_device_type type);
int (CDECL *set_deck_control_mode)(libcec_connection_t connection, CEC_NAMESPACE cec_deck_control_mode mode, int bSendUpdate);
int (CDECL *set_deck_info)(libcec_connection_t connection, CEC_NAMESPACE cec_deck_info info, int bSendUpdate);
int (CDECL *set_inactive_view)(libcec_connection_t connection);
int (CDECL *set_menu_state)(libcec_connection_t connection, CEC_NAMESPACE cec_menu_state state, int bSendUpdate);
int (CDECL *transmit)(libcec_connection_t connection, const CEC_NAMESPACE cec_command* data);
int (CDECL *set_logical_address)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
int (CDECL *set_physical_address)(libcec_connection_t connection, uint16_t iPhysicalAddress);
int (CDECL *set_osd_string)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_display_control duration, const char* strMessage);
int (CDECL *switch_monitoring)(libcec_connection_t connection, int bEnable);
CEC_NAMESPACE cec_version (CDECL *get_device_cec_version)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
int (CDECL *get_device_menu_language)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_menu_language* language);
uint64_t (CDECL *get_device_vendor_id)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
uint16_t (CDECL *get_device_physical_address)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
CEC_NAMESPACE cec_logical_address (CDECL *get_active_source)(libcec_connection_t connection);
int (CDECL *is_active_source)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress);
CEC_NAMESPACE cec_power_status (CDECL *get_device_power_status)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
int (CDECL *poll_device)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
CEC_NAMESPACE cec_logical_addresses (CDECL *get_active_devices)(libcec_connection_t connection);
int (CDECL *is_active_device)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address address);
int (CDECL *is_active_device_type)(libcec_connection_t connection, CEC_NAMESPACE cec_device_type type);
int (CDECL *set_hdmi_port)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address baseDevice, uint8_t iPort);
int (CDECL *volume_up)(libcec_connection_t connection, int bSendRelease);
int (CDECL *volume_down)(libcec_connection_t connection, int bSendRelease);
int (CDECL *mute_audio)(libcec_connection_t connection, int bSendRelease);
int (CDECL *send_keypress)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, CEC_NAMESPACE cec_user_control_code key, int bWait);
int (CDECL *send_key_release)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, int bWait);
CEC_NAMESPACE cec_osd_name (CDECL *get_device_osd_name)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress);
int (CDECL *set_stream_path_logical)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress);
int (CDECL *set_stream_path_physical)(libcec_connection_t connection, uint16_t iPhysicalAddress);
CEC_NAMESPACE cec_logical_addresses (CDECL *get_logical_addresses)(libcec_connection_t connection);
int (CDECL *get_current_configuration)(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration);
int (CDECL *can_persist_configuration)(libcec_connection_t connection);
int (CDECL *persist_configuration)(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration);
int (CDECL *set_configuration)(libcec_connection_t connection, const CEC_NAMESPACE libcec_configuration* configuration);
void (CDECL *rescan_devices)(libcec_connection_t connection);
int (CDECL *is_libcec_active_source)(libcec_connection_t connection);
int (CDECL *get_device_information)(libcec_connection_t connection, const char* strPort, CEC_NAMESPACE libcec_configuration* config, uint32_t iTimeoutMs);
const char* (CDECL *get_lib_info)(libcec_connection_t connection);
void (CDECL *init_video_standalone)(libcec_connection_t connection);
uint16_t (CDECL *get_adapter_vendor_id)(libcec_connection_t connection);
uint16_t (CDECL *get_adapter_product_id)(libcec_connection_t connection);
uint8_t (CDECL *audio_toggle_mute)(libcec_connection_t connection);
uint8_t (CDECL *audio_mute)(libcec_connection_t connection);
uint8_t (CDECL *audio_unmute)(libcec_connection_t connection);
uint8_t (CDECL *audio_get_status)(libcec_connection_t connection);
int8_t (CDECL *detect_adapters)(libcec_connection_t connection, CEC_NAMESPACE cec_adapter_descriptor* deviceList, uint8_t iBufSize, const char* strDevicePath, int bQuickScan);
void (CDECL *menu_state_to_string)(const CEC_NAMESPACE cec_menu_state state, char* buf, size_t bufsize);
void (CDECL *cec_version_to_string)(const CEC_NAMESPACE cec_version version, char* buf, size_t bufsize);
void (CDECL *power_status_to_string)(const CEC_NAMESPACE cec_power_status status, char* buf, size_t bufsize);
void (CDECL *logical_address_to_string)(const CEC_NAMESPACE cec_logical_address address, char* buf, size_t bufsize);
void (CDECL *deck_control_mode_to_string)(const CEC_NAMESPACE cec_deck_control_mode mode, char* buf, size_t bufsize);
void (CDECL *deck_status_to_string)(const CEC_NAMESPACE cec_deck_info status, char* buf, size_t bufsize);
void (CDECL *opcode_to_string)(const CEC_NAMESPACE cec_opcode opcode, char* buf, size_t bufsize);
void (CDECL *system_audio_status_to_string)(const CEC_NAMESPACE cec_system_audio_status mode, char* buf, size_t bufsize);
void (CDECL *audio_status_to_string)(const CEC_NAMESPACE cec_audio_status status, char* buf, size_t bufsize);
void (CDECL *vendor_id_to_string)(const CEC_NAMESPACE cec_vendor_id vendor, char* buf, size_t bufsize);
void (CDECL *user_control_key_to_string)(const CEC_NAMESPACE cec_user_control_code key, char* buf, size_t bufsize);
void (CDECL *adapter_type_to_string)(const CEC_NAMESPACE cec_adapter_type type, char* buf, size_t bufsize);
void (CDECL *version_to_string)(uint32_t version, char* buf, size_t bufsize);
} libcec_interface_t;
static int libcecc_resolve_all(void* lib, libcec_interface_t* iface)
{
if (!lib || !iface)
return -1;
_libcecc_resolve(lib, iface->destroy, "libcec_destroy", void(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->open, "libcec_open", int(CDECL *)(libcec_connection_t, const char*, uint32_t));
_libcecc_resolve(lib, iface->close, "libcec_close", void(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->clear_configuration, "libcec_clear_configuration", void(CDECL *)(CEC_NAMESPACE libcec_configuration*));
_libcecc_resolve(lib, iface->enable_callbacks, "libcec_enable_callbacks", int(CDECL *)(libcec_connection_t, void*, CEC_NAMESPACE ICECCallbacks*));
_libcecc_resolve(lib, iface->find_adapters, "libcec_find_adapters", int8_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_adapter*, uint8_t, const char*));
_libcecc_resolve(lib, iface->ping_adapters, "libcec_ping_adapters", int(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->start_bootloader, "libcec_start_bootloader", int(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->power_on_devices, "libcec_power_on_devices", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->standby_devices, "libcec_standby_devices", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->set_active_source, "libcec_set_active_source", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_device_type));
_libcecc_resolve(lib, iface->set_deck_control_mode, "libcec_set_deck_control_mode", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_deck_control_mode, int));
_libcecc_resolve(lib, iface->set_deck_info, "libcec_set_deck_info", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_deck_info, int));
_libcecc_resolve(lib, iface->set_inactive_view, "libcec_set_inactive_view", int(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->set_menu_state, "libcec_set_menu_state", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_menu_state, int));
_libcecc_resolve(lib, iface->transmit, "libcec_transmit", int(CDECL *)(libcec_connection_t, const CEC_NAMESPACE cec_command*));
_libcecc_resolve(lib, iface->set_logical_address, "libcec_set_logical_address", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->set_physical_address, "libcec_set_physical_address", int(CDECL *)(libcec_connection_t, uint16_t));
_libcecc_resolve(lib, iface->set_osd_string, "libcec_set_osd_string", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_display_control, const char*));
_libcecc_resolve(lib, iface->switch_monitoring, "libcec_switch_monitoring", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->get_device_cec_version, "libcec_get_device_cec_version", CEC_NAMESPACE cec_version(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_device_menu_language, "libcec_get_device_menu_language", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_menu_language*));
_libcecc_resolve(lib, iface->get_device_vendor_id, "libcec_get_device_vendor_id", uint64_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_device_physical_address, "libcec_get_device_physical_address", uint16_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_active_source, "libcec_get_active_source", CEC_NAMESPACE cec_logical_address(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->is_active_source, "libcec_is_active_source", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_device_power_status, "libcec_get_device_power_status", CEC_NAMESPACE cec_power_status(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->poll_device, "libcec_poll_device", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_active_devices, "libcec_get_active_devices", CEC_NAMESPACE cec_logical_addresses(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->is_active_device, "libcec_is_active_device", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->is_active_device_type, "libcec_is_active_device_type", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_device_type));
_libcecc_resolve(lib, iface->set_hdmi_port, "libcec_set_hdmi_port", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, uint8_t));
_libcecc_resolve(lib, iface->volume_up, "libcec_volume_up", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->volume_down, "libcec_volume_down", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->mute_audio, "libcec_mute_audio", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->send_keypress, "libcec_send_keypress", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_user_control_code, int));
_libcecc_resolve(lib, iface->send_key_release, "libcec_send_key_release", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, int));
_libcecc_resolve(lib, iface->get_device_osd_name, "libcec_get_device_osd_name", CEC_NAMESPACE cec_osd_name(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->set_stream_path_logical, "libcec_set_stream_path_logical", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->set_stream_path_physical, "libcec_set_stream_path_physical", int(CDECL *)(libcec_connection_t, uint16_t));
_libcecc_resolve(lib, iface->get_logical_addresses, "libcec_get_logical_addresses", CEC_NAMESPACE cec_logical_addresses(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->get_current_configuration, "libcec_get_current_configuration", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE libcec_configuration*));
_libcecc_resolve(lib, iface->can_persist_configuration, "libcec_can_persist_configuration", int(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->persist_configuration, "libcec_persist_configuration", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE libcec_configuration*));
_libcecc_resolve(lib, iface->set_configuration, "libcec_set_configuration", int(CDECL *)(libcec_connection_t, const CEC_NAMESPACE libcec_configuration*));
_libcecc_resolve(lib, iface->rescan_devices, "libcec_rescan_devices", void(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->is_libcec_active_source, "libcec_is_libcec_active_source", int(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->get_device_information, "libcec_get_device_information", int(CDECL *)(libcec_connection_t, const char*, CEC_NAMESPACE libcec_configuration*, uint32_t));
_libcecc_resolve(lib, iface->get_lib_info, "libcec_get_lib_info", const char*(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->init_video_standalone, "libcec_init_video_standalone", void(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->get_adapter_vendor_id, "libcec_get_adapter_vendor_id", uint16_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->get_adapter_product_id, "libcec_get_adapter_product_id", uint16_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->audio_toggle_mute, "libcec_audio_toggle_mute", uint8_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->audio_mute, "libcec_audio_mute", uint8_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->audio_unmute, "libcec_audio_unmute", uint8_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->audio_get_status, "libcec_audio_get_status", uint8_t(CDECL *)(libcec_connection_t));
_libcecc_resolve(lib, iface->detect_adapters, "libcec_detect_adapters", int8_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_adapter_descriptor*, uint8_t, const char*, int));
_libcecc_resolve(lib, iface->menu_state_to_string, "libcec_menu_state_to_string", void(CDECL *)(const CEC_NAMESPACE cec_menu_state, char*, size_t));
_libcecc_resolve(lib, iface->cec_version_to_string, "libcec_cec_version_to_string", void(CDECL *)(const CEC_NAMESPACE cec_version, char*, size_t));
_libcecc_resolve(lib, iface->power_status_to_string, "libcec_power_status_to_string", void(CDECL *)(const CEC_NAMESPACE cec_power_status, char*, size_t));
_libcecc_resolve(lib, iface->logical_address_to_string, "libcec_logical_address_to_string", void(CDECL *)(const CEC_NAMESPACE cec_logical_address, char*, size_t));
_libcecc_resolve(lib, iface->deck_control_mode_to_string, "libcec_deck_control_mode_to_string", void(CDECL *)(const CEC_NAMESPACE cec_deck_control_mode, char*, size_t));
_libcecc_resolve(lib, iface->deck_status_to_string, "libcec_deck_status_to_string", void(CDECL *)(const CEC_NAMESPACE cec_deck_info, char*, size_t));
_libcecc_resolve(lib, iface->opcode_to_string, "libcec_opcode_to_string", void(CDECL *)(const CEC_NAMESPACE cec_opcode, char*, size_t));
_libcecc_resolve(lib, iface->system_audio_status_to_string, "libcec_system_audio_status_to_string", void(CDECL *)(const CEC_NAMESPACE cec_system_audio_status, char*, size_t));
_libcecc_resolve(lib, iface->audio_status_to_string, "libcec_audio_status_to_string", void(CDECL *)(const CEC_NAMESPACE cec_audio_status, char*, size_t));
_libcecc_resolve(lib, iface->vendor_id_to_string, "libcec_vendor_id_to_string", void(CDECL *)(const CEC_NAMESPACE cec_vendor_id, char*, size_t));
_libcecc_resolve(lib, iface->user_control_key_to_string, "libcec_user_control_key_to_string", void(CDECL *)(const CEC_NAMESPACE cec_user_control_code, char*, size_t));
_libcecc_resolve(lib, iface->adapter_type_to_string, "libcec_adapter_type_to_string", void(CDECL *)(const CEC_NAMESPACE cec_adapter_type, char*, size_t));
_libcecc_resolve(lib, iface->version_to_string, "libcec_version_to_string", void(CDECL *)(uint32_t, char*, size_t));
return 1;
}
static libcecc_lib_instance_t libcecc_load_library(const char* strLib)
{
libcecc_lib_instance_t lib;
#if defined(_WIN32) || defined(_WIN64)
lib = LoadLibrary(strLib ? strLib : "cec.dll");
if (lib == NULL)
printf("failed to load cec.dll\n");
#else
#if defined(__APPLE__)
lib = dlopen(strLib ? strLib : "libcec." CEC_LIB_VERSION_MAJOR_STR ".dylib", RTLD_LAZY);
#else
lib = dlopen(strLib ? strLib : "libcec.so." CEC_LIB_VERSION_MAJOR_STR ".0", RTLD_LAZY);
#endif
if (lib == NULL)
printf("%s\n", dlerror());
#endif
return lib;
}
static void libcecc_close_library(libcecc_lib_instance_t lib)
{
#if defined(_WIN32) || defined(_WIN64)
FreeLibrary(lib);
#else
dlclose(lib);
#endif
}
static void* libcecc_resolve(void* lib, const char* name)
{
#if defined(_WIN32) || defined(_WIN64)
return GetProcAddress(lib, name);
#else
return dlsym(lib, name);
#endif
}
void libcecc_reset_configuration(CEC_NAMESPACE libcec_configuration* configuration)
{
void(CDECL * _clear_configuration)(CEC_NAMESPACE libcec_configuration*);
libcecc_lib_instance_t lib;
memset(configuration, 0, sizeof(CEC_NAMESPACE libcec_configuration));
lib = libcecc_load_library(NULL);
if (lib == NULL)
return;
_clear_configuration = (void(CDECL *)(CEC_NAMESPACE libcec_configuration*)) libcecc_resolve(lib, "libcec_clear_configuration");
if (_clear_configuration)
_clear_configuration(configuration);
libcecc_close_library(lib);
}
/*!
* @brief Create a new libCEC instance.
* @param configuration The configuration to pass to libCEC
* @param strLib The name of and/or path to libCEC
* @return 1 when loaded, 0 if libCEC failed to initialise, -1 if methods failed to be resolved
*/
int libcecc_initialise(CEC_NAMESPACE libcec_configuration* configuration, libcec_interface_t* iface, const char* strLib)
{
void* (CDECL *_cec_initialise)(CEC_NAMESPACE libcec_configuration*);
libcecc_lib_instance_t lib;
lib = libcecc_load_library(strLib);
if (lib == NULL)
return -1;
_libcecc_resolve(lib, _cec_initialise, "libcec_initialise", void* (CDECL *)(CEC_NAMESPACE libcec_configuration*));
iface->lib_instance = lib;
iface->connection = _cec_initialise(configuration);
return iface->connection ?
libcecc_resolve_all(lib, iface) :
0;
}
/*!
* @brief Destroy an instance of libCEC.
* @param device The instance to destroy.
*/
void libcecc_destroy(libcec_interface_t* iface)
{
if (iface->destroy)
iface->destroy(iface->connection);
libcecc_close_library(iface->lib_instance);
memset(iface, 0, sizeof(libcec_interface_t));
}

1
third_party/moonlight-common-c vendored Submodule

@ -0,0 +1 @@
Subproject commit 678afd9c300ae4591aa53e3bbf0e14783803671e