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"] [submodule "common"]
path = common path = third_party/moonlight-common-c
url = https://github.com/irtimmer/moonlight-common-c.git 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) aux_source_directory(./src SRC_LIST)
list(APPEND SRC_LIST ./src/video/fake.c) list(APPEND SRC_LIST ./src/video/fake.c)
aux_source_directory(./common/limelight-common SRC_LIST) aux_source_directory(./third_party/moonlight-common-c/limelight-common SRC_LIST)
aux_source_directory(./common/limelight-common/OpenAES 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) set(MOONLIGHT_DEFINITIONS)
@ -21,6 +21,7 @@ find_package(ALSA REQUIRED)
find_package(Opus REQUIRED) find_package(Opus REQUIRED)
find_package(Broadcom) find_package(Broadcom)
find_package(Freescale) find_package(Freescale)
find_package(CEC)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(EVDEV REQUIRED libevdev) pkg_check_modules(EVDEV REQUIRED libevdev)
@ -31,9 +32,14 @@ pkg_check_modules(AVCODEC libavcodec)
pkg_check_modules(AVUTIL libavutil) pkg_check_modules(AVUTIL libavutil)
pkg_check_modules(SWSCALE libswscale) pkg_check_modules(SWSCALE libswscale)
if(CEC_FOUND)
include_directories(./third_party/libcec)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_LIBCEC)
endif()
if(BROADCOM_FOUND) if(BROADCOM_FOUND)
aux_source_directory(./ilclient SRC_LIST) aux_source_directory(./third_party/ilclient SRC_LIST)
aux_source_directory(./h264bitstream SRC_LIST) aux_source_directory(./third_party/h264bitstream SRC_LIST)
list(APPEND SRC_LIST ./src/video/omx.c) list(APPEND SRC_LIST ./src/video/omx.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX) list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX)
endif() endif()
@ -52,7 +58,7 @@ add_executable(moonlight ${SRC_LIST})
set_property(TARGET moonlight PROPERTY C_STANDARD 11) set_property(TARGET moonlight PROPERTY C_STANDARD 11)
if(BROADCOM_FOUND) 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}) target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS}) list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif() endif()
@ -68,8 +74,8 @@ if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND AND SDL_FOUND)
endif() endif()
set_property(TARGET moonlight PROPERTY COMPILE_DEFINITIONS ${MOONLIGHT_DEFINITIONS}) 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}) 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}) 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) include(${CMAKE_ROOT}/Modules/GNUInstallDirs.cmake)
install(TARGETS moonlight DESTINATION ${CMAKE_INSTALL_BINDIR}) 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). 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 ##Features
* Streams Steam and all of your games from your PC to your embedded system. * Streams Steam and all of your games from your PC to your embedded system.
* Use mDNS to scan for compatible GeForce Experience (GFE) machines on the network.
##Installation * Qwerty Keyboard, Mouse and Gamepad support
* Support Raspberry Pi and i.MX 6 devices
* 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)
##Requirements ##Requirements
@ -50,10 +31,12 @@ implementation.
* Play games! * Play games!
##Usage ##Usage
Usage: moonlight [options] host Usage: moonlight [options] host
Actions: Actions:
map Create mapping file for gamepad
pair Pair device with computer pair Pair device with computer
stream Stream computer to device stream Stream computer to device
list List available games and applications list List available games and applications
@ -71,23 +54,117 @@ implementation.
-bitrate <bitrate> Specify the bitrate in Kbps -bitrate <bitrate> Specify the bitrate in Kbps
-packetsize <size> Specify the maximum packetsize in bytes -packetsize <size> Specify the maximum packetsize in bytes
-app <app> Name of app to stream -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 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 package using the following commands
* 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) 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`` * Initialize the git submodules ``git submodule update --init``
* Build and install using the following commands
``` ```
mkdir build mkdir build
cd build/ cd build/
cmake ../ cmake ../
make 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 ## Discussion
[XDA](http://forum.xda-developers.com/showthread.php?t=2505510) [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 short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
static void audio_renderer_init() { static void audio_renderer_init() {
printf("audio_renderer_init\n");
int rc; int rc;
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &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)); CHECK_RETURN(snd_pcm_prepare(handle));
} }
static void audio_renderer_release() { static void audio_renderer_cleanup() {
printf("audio_renderer_release\n");
if (decoder != NULL) if (decoder != NULL)
opus_decoder_destroy(decoder); 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 = { AUDIO_RENDERER_CALLBACKS audio_callbacks = {
.init = audio_renderer_init, .init = audio_renderer_init,
.start = NULL, .cleanup = audio_renderer_cleanup,
.stop = NULL,
.release = audio_renderer_release,
.decodeAndPlaySample = audio_renderer_decode_and_play_sample, .decodeAndPlaySample = audio_renderer_decode_and_play_sample,
}; };

View File

@ -72,8 +72,9 @@ static void client_load_unique_id() {
static void client_load_cert() { static void client_load_cert() {
FILE *fd = fopen(certificateFileName, "r"); FILE *fd = fopen(certificateFileName, "r");
if (fd == NULL) { if (fd == NULL) {
printf("Generating certificate\n"); printf("Generating certificate...");
struct CertKeyPair cert = generateCertKeyPair(); struct CertKeyPair cert = generateCertKeyPair();
printf("done\n");
saveCertKeyPair(certificateFileName, p12FileName, keyFileName, cert); saveCertKeyPair(certificateFileName, p12FileName, keyFileName, cert);
freeCertKeyPair(cert); freeCertKeyPair(cert);
fd = fopen(certificateFileName, "r"); fd = fopen(certificateFileName, "r");
@ -85,7 +86,7 @@ static void client_load_cert() {
} }
if (!(cert = PEM_read_X509(fd, NULL, NULL, NULL))) { 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); exit(-1);
} }
@ -123,7 +124,10 @@ static void client_load_server_status(const char *address) {
paired = pairedText != NULL && strcmp(pairedText, "1") == 0; paired = pairedText != NULL && strcmp(pairedText, "1") == 0;
currentGame = currentGameText == NULL ? 0 : atoi(currentGameText); currentGame = currentGameText == NULL ? 0 : atoi(currentGameText);
strstr(versionText, ".")[0] = 0; char *versionSep = strstr(versionText, ".");
if (versionSep != NULL) {
*versionSep = 0;
}
serverMajorVersion = atoi(versionText); serverMajorVersion = atoi(versionText);
free(pairedText); 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(); EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (ctx == NULL) { 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; return -1;
} }
const EVP_MD *md = EVP_get_digestbyname("SHA256"); const EVP_MD *md = EVP_get_digestbyname("SHA256");
if (md == NULL) { 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; goto cleanup;
} }
int rc = EVP_DigestInit_ex(ctx, md, NULL); int rc = EVP_DigestInit_ex(ctx, md, NULL);
if (rc != 1) { 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; goto cleanup;
} }
rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey); rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
if (rc != 1) { 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; goto cleanup;
} }
rc = EVP_DigestSignUpdate(ctx, msg, mlen); rc = EVP_DigestSignUpdate(ctx, msg, mlen);
if (rc != 1) { 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; goto cleanup;
} }
size_t req = 0; size_t req = 0;
rc = EVP_DigestSignFinal(ctx, NULL, &req); rc = EVP_DigestSignFinal(ctx, NULL, &req);
if (rc != 1) { 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; goto cleanup;
} }
if (!(req > 0)) { 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; goto cleanup;
} }
*sig = OPENSSL_malloc(req); *sig = OPENSSL_malloc(req);
if (*sig == NULL) { 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; goto cleanup;
} }
*slen = req; *slen = req;
rc = EVP_DigestSignFinal(ctx, *sig, slen); rc = EVP_DigestSignFinal(ctx, *sig, slen);
if (rc != 1) { 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()); ERR_get_error());
goto cleanup; goto cleanup;
} }
if (req != *slen) { 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); req, *slen);
goto cleanup; goto cleanup;
} }
@ -223,6 +227,11 @@ void client_pair(const char *address) {
return; 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]; char pin[5];
sprintf(pin, "%d%d%d%d", (int)random() % 10, (int)random() % 10, (int)random() % 10, (int)random() % 10); 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); 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); 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); 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_request(url, data);
http_free_data(data); http_free_data(data);

View File

@ -18,49 +18,30 @@
*/ */
#include "connection.h" #include "connection.h"
#include "global.h"
#include <stdio.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() void connection_connection_terminated()
{ {
printf("connection_connection_terminated\n"); quit();
} }
void connection_display_message(char *msg) void connection_display_message(char *msg)
{ {
printf("connection_display_message: %s\n", msg); printf("%s\n", msg);
} }
void connection_display_transient_message(char *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 = { CONNECTION_LISTENER_CALLBACKS connection_callbacks = {
.stageStarting = connection_stage_starting, .stageStarting = NULL,
.stageComplete = connection_stage_complete, .stageComplete = NULL,
.stageFailed = connection_stage_failed, .stageFailed = NULL,
.connectionStarted = connection_connection_started, .connectionStarted = NULL,
.connectionTerminated = connection_connection_terminated, .connectionTerminated = connection_connection_terminated,
.displayMessage = connection_display_message, .displayMessage = connection_display_message,
.displayTransientMessage = connection_display_transient_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_SSLKEY, pKeyFile);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _write_curl); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _write_curl);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
} }
int http_request(char* url, struct http_data* data) { int http_request(char* url, struct http_data* data) {

View File

@ -19,21 +19,30 @@
#include "keyboard.h" #include "keyboard.h"
#include "mapping.h" #include "mapping.h"
#include "global.h"
#include "libevdev/libevdev.h" #include "libevdev/libevdev.h"
#include "limelight-common/Limelight.h" #include "limelight-common/Limelight.h"
#ifdef HAVE_LIBCEC
#include <ceccloader.h>
#endif
#include <libudev.h> #include <libudev.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <signal.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/signalfd.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <limits.h> #include <limits.h>
#include <unistd.h>
#include <pthread.h>
struct input_abs_parms { struct input_abs_parms {
int min, max; int min, max;
@ -51,7 +60,7 @@ struct input_device {
__s32 mouseDeltaX, mouseDeltaY, mouseScroll; __s32 mouseDeltaX, mouseDeltaY, mouseScroll;
short controllerId; short controllerId;
int buttonFlags; int buttonFlags;
short leftTrigger, rightTrigger; char leftTrigger, rightTrigger;
short leftStickX, leftStickY; short leftStickX, leftStickY;
short rightStickX, rightStickY; short rightStickX, rightStickY;
bool gamepadModified; bool gamepadModified;
@ -74,6 +83,91 @@ static struct udev *udev;
static struct udev_monitor *udev_mon; static struct udev_monitor *udev_mon;
static int udev_fdindex; 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) { static void input_init_parms(struct input_device *dev, struct input_abs_parms *parms, int code) {
parms->flat = libevdev_get_abs_flat(dev->dev, code); parms->flat = libevdev_get_abs_flat(dev->dev, code);
parms->min = libevdev_get_abs_minimum(dev->dev, code); parms->min = libevdev_get_abs_minimum(dev->dev, code);
@ -109,6 +203,7 @@ void input_create(const char* device, char* mapFile) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
memset(&devices[dev], 0, sizeof(devices[0]));
devices[dev].fd = fd; devices[dev].fd = fd;
devices[dev].dev = libevdev_new(); devices[dev].dev = libevdev_new();
libevdev_set_fd(devices[dev].dev, devices[dev].fd); libevdev_set_fd(devices[dev].dev, devices[dev].fd);
@ -141,11 +236,15 @@ static void input_remove(int devindex) {
if (fdindex != numFds && numFds > 0) { if (fdindex != numFds && numFds > 0) {
memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd)); memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd));
if (numFds == udev_fdindex) if (numFds == udev_fdindex)
udev_fdindex = numFds; udev_fdindex = fdindex;
else if (numFds == sig_fdindex)
sig_fdindex = fdindex;
else { else {
for (int i=0;i<numDevices;i++) { for (int i=0;i<numDevices;i++) {
if (devices[i].fdindex == numFds) if (devices[i].fdindex == numFds) {
devices[i].fdindex = fdindex; devices[i].fdindex = fdindex;
break;
}
} }
} }
} }
@ -156,13 +255,18 @@ static void input_remove(int devindex) {
} }
void input_init(char* mapfile) { void input_init(char* mapfile) {
#ifdef HAVE_LIBCEC
init_cec();
#endif
udev = udev_new(); udev = udev_new();
if (!udev) { if (!udev) {
fprintf(stderr, "Can't create udev\n"); fprintf(stderr, "Can't create udev\n");
exit(1); exit(1);
} }
if (autoadd = numDevices == 0) { autoadd = (numDevices == 0);
if (autoadd) {
struct udev_enumerate *enumerate = udev_enumerate_new(udev); struct udev_enumerate *enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "input"); udev_enumerate_add_match_subsystem(enumerate, "input");
udev_enumerate_scan_devices(enumerate); 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_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
udev_monitor_enable_receiving(udev_mon); udev_monitor_enable_receiving(udev_mon);
int udev_fdindex = numFds; udev_fdindex = numFds++;
numFds++; sig_fdindex = numFds++;
if (fds == NULL) if (fds == NULL)
fds = malloc(sizeof(struct pollfd)); fds = malloc(sizeof(struct pollfd)*numFds);
else else
fds = realloc(fds, sizeof(struct pollfd)*numFds); fds = realloc(fds, sizeof(struct pollfd)*numFds);
@ -203,6 +307,17 @@ void input_init(char* mapfile) {
defaultMapfile = mapfile; defaultMapfile = mapfile;
fds[udev_fdindex].fd = udev_monitor_get_fd(udev_mon); fds[udev_fdindex].fd = udev_monitor_get_fd(udev_mon);
fds[udev_fdindex].events = POLLIN; 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() { 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; return reverse?SHRT_MIN:SHRT_MAX;
else if (ev->value < parms->min) else if (ev->value < parms->min)
return reverse?SHRT_MAX:SHRT_MIN; return reverse?SHRT_MAX:SHRT_MIN;
else { else if (reverse)
int value = ev->value + (ev->value<parms->avg?parms->flat:-parms->flat); 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;
return (value-parms->avg) * SHRT_MAX / ((reverse?-parms->range-1:parms->range) - parms->flat); 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) { 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) else if (ev->value>parms->max)
return UCHAR_MAX; return UCHAR_MAX;
else { else {
int value = ev->value + parms->flat; int value = ev->value - parms->flat;
return (value-parms->min) * UCHAR_MAX / (parms->diff-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; gamepadCode = SPECIAL_FLAG;
} }
if (mouseCode > 0) { if (mouseCode != 0) {
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode); LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
} else { } else {
gamepadModified = true; gamepadModified = true;
if (gamepadCode > 0) { if (gamepadCode != 0) {
if (ev->value) if (ev->value)
dev->buttonFlags |= gamepadCode; dev->buttonFlags |= gamepadCode;
else else
dev->buttonFlags &= ~gamepadCode; dev->buttonFlags &= ~gamepadCode;
} else if (ev->code == dev->map.btn_tl2) } 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) else if (ev->code == dev->map.btn_tr2)
dev->rightTrigger = ev->value?USHRT_MAX:0; dev->rightTrigger = ev->value?UCHAR_MAX:0;
else else
gamepadModified = false; gamepadModified = false;
} }
@ -372,7 +487,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
case REL_Y: case REL_Y:
dev->mouseDeltaY = ev->value; dev->mouseDeltaY = ev->value;
break; break;
case REL_Z: case REL_WHEEL:
dev->mouseScroll = ev->value; dev->mouseScroll = ev->value;
break; break;
} }
@ -396,7 +511,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
if (dir == 1) { if (dir == 1) {
dev->buttonFlags |= RIGHT_FLAG; dev->buttonFlags |= RIGHT_FLAG;
dev->buttonFlags &= ~LEFT_FLAG; dev->buttonFlags &= ~LEFT_FLAG;
} else if (dir == -1) { } else if (dir == 0) {
dev->buttonFlags &= ~RIGHT_FLAG; dev->buttonFlags &= ~RIGHT_FLAG;
dev->buttonFlags &= ~LEFT_FLAG; dev->buttonFlags &= ~LEFT_FLAG;
} else { } 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) { } else if (ev->code == dev->map.abs_dpad_y) {
int dir = input_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_dpad_y); int dir = input_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_dpad_y);
if (dir == 1) { if (dir == 1) {
dev->buttonFlags |= UP_FLAG; dev->buttonFlags |= DOWN_FLAG;
dev->buttonFlags &= ~DOWN_FLAG;
} else if (dir == -1) {
dev->buttonFlags &= ~UP_FLAG; dev->buttonFlags &= ~UP_FLAG;
} else if (dir == 0) {
dev->buttonFlags &= ~DOWN_FLAG; dev->buttonFlags &= ~DOWN_FLAG;
dev->buttonFlags &= ~UP_FLAG;
} else { } else {
dev->buttonFlags &= ~DOWN_FLAG; dev->buttonFlags &= ~DOWN_FLAG;
dev->buttonFlags |= UP_FLAG; dev->buttonFlags |= UP_FLAG;
@ -454,7 +569,14 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
return true; 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)) { while (poll(fds, numFds, -1)) {
if (fds[udev_fdindex].revents > 0) { if (fds[udev_fdindex].revents > 0) {
struct udev_device *dev = udev_monitor_receive_device(udev_mon); 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); udev_device_unref(dev);
} }
} else if (fds[sig_fdindex].revents > 0) {
struct signalfd_siginfo info;
read(fds[sig_fdindex].fd, &info, sizeof(info));
switch (info.ssi_signo) {
case SIGINT:
case SIGTERM:
case SIGQUIT:
case SIGHUP:
return false;
}
} }
for (int i=0;i<numDevices;i++) { for (int i=0;i<numDevices;i++) {
if (fds[devices[i].fdindex].revents > 0) { if (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"); fprintf(stderr, "Error: cannot keep up\n");
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
if (!handler(&ev, &devices[i])) if (!handler(&ev, &devices[i]))
return; return true;
} }
} }
if (rc == -ENODEV) { 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) { static void input_map_key(char* keyName, short* key) {
@ -498,38 +633,50 @@ static void input_map_key(char* keyName, short* key) {
currentKey = key; currentKey = key;
currentAbs = NULL; currentAbs = NULL;
*key = -1; *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) { static void input_map_abs(char* keyName, short* abs, bool* reverse) {
printf("%s\n", keyName); printf("Move %s\n", keyName);
currentKey = NULL; currentKey = NULL;
currentAbs = abs; currentAbs = abs;
currentReverse = reverse; currentReverse = reverse;
*abs = -1; *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) { static void input_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
printf("%s\n", keyName); printf("Press %s\n", keyName);
currentKey = key; currentKey = key;
currentAbs = abs; currentAbs = abs;
currentReverse = reverse; currentReverse = reverse;
*key = -1; *key = -1;
*abs = -1; *abs = -1;
*currentReverse = false; *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) { void input_map(char* fileName) {
struct mapping map; struct mapping map;
input_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x)); 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_key("Left Stick Button", &(map.btn_thumbl));
input_map_abs("Right Stick Right", &(map.abs_rx), &(map.reverse_rx)); 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_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)); 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)); input_map_key("Special Button", &(map.btn_mode));
bool ignored; bool ignored;
input_map_abskey("Left Trigger", &(map.btn_tl), &(map.abs_z), &ignored); input_map_abskey("Left Trigger", &(map.btn_tl2), &(map.abs_z), &ignored);
input_map_abskey("Right Trigger", &(map.btn_tr), &(map.abs_rz), &ignored); input_map_abskey("Right Trigger", &(map.btn_tr2), &(map.abs_rz), &ignored);
input_map_key("Left Bumper", &(map.btn_tl2)); input_map_key("Left Bumper", &(map.btn_tl));
input_map_key("Right Bumper", &(map.btn_tr2)); input_map_key("Right Bumper", &(map.btn_tr));
mapping_save(fileName, &map); 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) { static void stream(STREAM_CONFIGURATION* config, const char* address, const char* app, bool sops, bool localaudio) {
int appId = client_get_app_id(address, app); int appId = client_get_app_id(address, app);
if (appId<0) { if (appId<0) {
printf("Can't find app %s\n", app); fprintf(stderr, "Can't find app %s\n", app);
exit(-1); exit(-1);
} }
@ -61,20 +61,7 @@ static void stream(STREAM_CONFIGURATION* config, const char* address, const char
video_init(); video_init();
struct addrinfo hints, *res; LiStartConnection(address, config, &connection_callbacks, decoder_callbacks, &audio_callbacks, NULL, NULL, 0, client_get_server_version());
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);
input_loop(); input_loop();
@ -147,7 +134,7 @@ char* get_path(char* name) {
static void pair_check(void) { static void pair_check(void) {
if (!client_is_paired(NULL)) { 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); exit(-1);
} }
} }
@ -265,7 +252,7 @@ int main(int argc, char* argv[]) {
address[0] = 0; address[0] = 0;
discover_server(address); discover_server(address);
if (address[0] == 0) { if (address[0] == 0) {
perror("Can't find server"); fprintf(stderr, "Autodiscovery failed. Specify an IP address next time.\n");
exit(-1); exit(-1);
} }
} }

View File

@ -100,11 +100,11 @@ void mapping_load(char* fileName, struct mapping* map) {
else if (strcmp("reverse_ry", key) == 0) else if (strcmp("reverse_ry", key) == 0)
map->reverse_ry = strcmp("true", value) == 0; map->reverse_ry = strcmp("true", value) == 0;
else if (strcmp("reverse_dpad_x", key) == 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) else if (strcmp("reverse_dpad_y", key) == 0)
map->reverse_y = strcmp("true", value) == 0; map->reverse_dpad_y = strcmp("true", value) == 0;
else else
printf("Can't map (%s)\n", key); fprintf(stderr, "Can't map (%s)\n", key);
} }
if (key != NULL) if (key != NULL)
free(key); free(key);

View File

@ -49,7 +49,7 @@ struct CertKeyPair generateCertKeyPair() {
p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0); p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0);
if (p12 == NULL) { if (p12 == NULL) {
printf("Error generating a valid PKCS12 certificate.\n"); fprintf(stderr, "Error generating a valid PKCS12 certificate.\n");
} }
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE

View File

@ -27,7 +27,6 @@
#include <stdlib.h> #include <stdlib.h>
DECODER_RENDERER_CALLBACKS *decoder_callbacks; DECODER_RENDERER_CALLBACKS *decoder_callbacks;
char* decoder_output_name;
static int decoder_level; static int decoder_level;
@ -37,22 +36,14 @@ void video_init() {
#else #else
decoder_callbacks = &decoder_callbacks_fake; decoder_callbacks = &decoder_callbacks_fake;
#endif #endif
#ifdef HAVE_IMX
if (dlsym(RTLD_DEFAULT, "vpu_Init") != NULL && video_imx_init()) {
decoder_callbacks = &decoder_callbacks_imx;
}
#endif
#ifdef HAVE_OMX #ifdef HAVE_OMX
if (dlsym(RTLD_DEFAULT, "bcm_host_init") != NULL) { if (dlsym(RTLD_DEFAULT, "bcm_host_init") != NULL) {
decoder_callbacks = &decoder_callbacks_omx; decoder_callbacks = &decoder_callbacks_omx;
} }
#endif #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 "limelight-common/Limelight.h"
#include <stdbool.h>
extern DECODER_RENDERER_CALLBACKS *decoder_callbacks; extern DECODER_RENDERER_CALLBACKS *decoder_callbacks;
void video_init(); void video_init();
@ -31,5 +33,6 @@ extern DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl;
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx; extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx;
#endif #endif
#ifdef HAVE_IMX #ifdef HAVE_IMX
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx; extern DECODER_RENDERER_CALLBACKS decoder_callbacks_imx;
bool video_imx_init();
#endif #endif

View File

@ -25,12 +25,10 @@ static FILE* fd;
static const char* fileName = "fake.h264"; static const char* fileName = "fake.h264";
void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) { 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"); fd = fopen(fileName, "w");
} }
void decoder_renderer_release() { void decoder_renderer_cleanup() {
printf("decoder_renderer_release\n");
fclose(fd); fclose(fd);
} }
@ -45,8 +43,6 @@ int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
DECODER_RENDERER_CALLBACKS decoder_callbacks_fake = { DECODER_RENDERER_CALLBACKS decoder_callbacks_fake = {
.setup = decoder_renderer_setup, .setup = decoder_renderer_setup,
.start = NULL, .cleanup = decoder_renderer_cleanup,
.stop = NULL,
.release = decoder_renderer_release,
.submitDecodeUnit = decoder_renderer_submit_decode_unit, .submitDecodeUnit = decoder_renderer_submit_decode_unit,
}; };

View File

@ -19,9 +19,6 @@
#include "../video.h" #include "../video.h"
#include "vpu_io.h"
#include "vpu_lib.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -43,6 +40,9 @@
#include <linux/v4l2-controls.h> #include <linux/v4l2-controls.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <vpu_io.h>
#include <vpu_lib.h>
#define STREAM_BUF_SIZE 0x200000 #define STREAM_BUF_SIZE 0x200000
#define PS_SAVE_SIZE 0x080000 #define PS_SAVE_SIZE 0x080000
@ -72,6 +72,10 @@ static int disp_clr_index = 0;
static FrameBuffer *fb; static FrameBuffer *fb;
static struct v4l2_buffer dbuf; 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) { static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
struct mxcfb_gbl_alpha alpha; struct mxcfb_gbl_alpha alpha;
@ -94,11 +98,6 @@ static void decoder_renderer_setup(int width, int height, int redrawRate, void*
close(fd_fb); 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; mem_desc.size = STREAM_BUF_SIZE;
if (IOGetPhyMem(&mem_desc)){ if (IOGetPhyMem(&mem_desc)){
fprintf(stderr, "Can't get physical memory address\n"); 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; return DR_OK;
} }
static void decoder_renderer_release() { static void decoder_renderer_cleanup() {
IOFreePhyMem(&ps_mem_desc); IOFreePhyMem(&ps_mem_desc);
IOFreePhyMem(&slice_mem_desc); IOFreePhyMem(&slice_mem_desc);
@ -424,8 +423,6 @@ static void decoder_renderer_release() {
DECODER_RENDERER_CALLBACKS decoder_callbacks_imx = { DECODER_RENDERER_CALLBACKS decoder_callbacks_imx = {
.setup = decoder_renderer_setup, .setup = decoder_renderer_setup,
.start = NULL, .cleanup = decoder_renderer_cleanup,
.stop = NULL,
.release = decoder_renderer_release,
.submitDecodeUnit = decoder_renderer_submit_decode_unit, .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 "../video.h"
#include "bcm_host.h"
#include "ilclient.h"
#include "h264_stream.h" #include "h264_stream.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ilclient.h>
#include <bcm_host.h>
static TUNNEL_T tunnel[2]; static TUNNEL_T tunnel[2];
static COMPONENT_T *list[3]; static COMPONENT_T *list[3];
static ILCLIENT_T *client; 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; int status = 0;
buf->nFilledLen = 0; buf->nFilledLen = 0;
@ -144,9 +145,7 @@ static void decoder_renderer_stop() {
ilclient_flush_tunnels(tunnel, 0); ilclient_flush_tunnels(tunnel, 0);
ilclient_disable_port_buffers(list[0], 130, NULL, NULL, NULL); ilclient_disable_port_buffers(list[0], 130, NULL, NULL, NULL);
}
static void decoder_renderer_release() {
ilclient_disable_tunnel(tunnel); ilclient_disable_tunnel(tunnel);
ilclient_teardown_tunnels(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 = { DECODER_RENDERER_CALLBACKS decoder_callbacks_omx = {
.setup = decoder_renderer_setup, .setup = decoder_renderer_setup,
.start = NULL, .cleanup = decoder_renderer_cleanup,
.stop = decoder_renderer_stop,
.release = decoder_renderer_release,
.submitDecodeUnit = decoder_renderer_submit_decode_unit, .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; screen_height = height;
} }
static void sdl_release() { static void sdl_cleanup() {
ffmpeg_destroy(); ffmpeg_destroy();
} }
@ -109,8 +109,6 @@ static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) {
DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl = { DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl = {
.setup = sdl_setup, .setup = sdl_setup,
.start = NULL, .cleanup = sdl_cleanup,
.stop = NULL,
.release = sdl_release,
.submitDecodeUnit = sdl_submit_decode_unit, .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; struct xml_query search;
search.data = node; search.data = node;
search.start = 0; search.start = 0;
search.memory = malloc(1); search.memory = calloc(1, 1);
search.size = 0; search.size = 0;
XML_Parser parser = XML_ParserCreate("UTF-8"); XML_Parser parser = XML_ParserCreate("UTF-8");
XML_SetUserData(parser, &search); 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); XML_SetCharacterDataHandler(parser, _xml_write_data);
if (! XML_Parse(parser, data, len, 1)) { if (! XML_Parse(parser, data, len, 1)) {
int code = XML_GetErrorCode(parser); int code = XML_GetErrorCode(parser);
printf("%s\n", XML_ErrorString(code)); fprintf(stderr, "XML Error: %s\n", XML_ErrorString(code));
return 1; return 1;
} }
*result = search.memory; *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 app_list* xml_applist(char* data, size_t len) {
struct xml_query query; struct xml_query query;
query.memory = malloc(1); query.memory = calloc(1, 1);
query.size = 0; query.size = 0;
query.start = 0; query.start = 0;
query.data = NULL; query.data = NULL;
@ -120,7 +120,7 @@ struct app_list* xml_applist(char* data, size_t len) {
XML_SetCharacterDataHandler(parser, _xml_write_data); XML_SetCharacterDataHandler(parser, _xml_write_data);
if (! XML_Parse(parser, data, len, 1)) { if (! XML_Parse(parser, data, len, 1)) {
int code = XML_GetErrorCode(parser); int code = XML_GetErrorCode(parser);
printf("%s\n", XML_ErrorString(code)); fprintf(stderr, "XML Error %s\n", XML_ErrorString(code));
exit(-1); 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