mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-03 16:25:31 +00:00
Merge branch 'master' into pc
This commit is contained in:
commit
e1ae9f4874
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "common"]
|
||||
path = common
|
||||
path = third_party/moonlight-common-c
|
||||
url = https://github.com/irtimmer/moonlight-common-c.git
|
||||
|
@ -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
129
README.md
@ -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
19
cmake/FindCEC.cmake
Normal 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
common
@ -1 +0,0 @@
|
||||
Subproject commit fcd2a20e01c202558fc0b9b923a6612d3fce8d50
|
6
debian/changelog
vendored
Normal file
6
debian/changelog
vendored
Normal 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
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
||||
9
|
14
debian/control
vendored
Normal file
14
debian/control
vendored
Normal 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
22
debian/copyright
vendored
Normal 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
32
debian/patches/install.patch
vendored
Normal 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
1
debian/patches/series
vendored
Normal file
@ -0,0 +1 @@
|
||||
install.patch
|
8
debian/rules
vendored
Executable file
8
debian/rules
vendored
Executable 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
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
@ -36,7 +36,6 @@ static OpusDecoder* decoder;
|
||||
static short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
|
||||
|
||||
static void audio_renderer_init() {
|
||||
printf("audio_renderer_init\n");
|
||||
int rc;
|
||||
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);
|
||||
|
||||
@ -72,8 +71,7 @@ static void audio_renderer_init() {
|
||||
CHECK_RETURN(snd_pcm_prepare(handle));
|
||||
}
|
||||
|
||||
static void audio_renderer_release() {
|
||||
printf("audio_renderer_release\n");
|
||||
static void audio_renderer_cleanup() {
|
||||
if (decoder != NULL)
|
||||
opus_decoder_destroy(decoder);
|
||||
|
||||
@ -101,8 +99,6 @@ static void audio_renderer_decode_and_play_sample(char* data, int length) {
|
||||
|
||||
AUDIO_RENDERER_CALLBACKS audio_callbacks = {
|
||||
.init = audio_renderer_init,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = audio_renderer_release,
|
||||
.cleanup = audio_renderer_cleanup,
|
||||
.decodeAndPlaySample = audio_renderer_decode_and_play_sample,
|
||||
};
|
||||
|
37
src/client.c
37
src/client.c
@ -72,8 +72,9 @@ static void client_load_unique_id() {
|
||||
static void client_load_cert() {
|
||||
FILE *fd = fopen(certificateFileName, "r");
|
||||
if (fd == NULL) {
|
||||
printf("Generating certificate\n");
|
||||
printf("Generating certificate...");
|
||||
struct CertKeyPair cert = generateCertKeyPair();
|
||||
printf("done\n");
|
||||
saveCertKeyPair(certificateFileName, p12FileName, keyFileName, cert);
|
||||
freeCertKeyPair(cert);
|
||||
fd = fopen(certificateFileName, "r");
|
||||
@ -85,7 +86,7 @@ static void client_load_cert() {
|
||||
}
|
||||
|
||||
if (!(cert = PEM_read_X509(fd, NULL, NULL, NULL))) {
|
||||
printf("Error loading cert into memory.\n");
|
||||
fprintf(stderr, "Error loading cert into memory.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -123,7 +124,10 @@ static void client_load_server_status(const char *address) {
|
||||
|
||||
paired = pairedText != NULL && strcmp(pairedText, "1") == 0;
|
||||
currentGame = currentGameText == NULL ? 0 : atoi(currentGameText);
|
||||
strstr(versionText, ".")[0] = 0;
|
||||
char *versionSep = strstr(versionText, ".");
|
||||
if (versionSep != NULL) {
|
||||
*versionSep = 0;
|
||||
}
|
||||
serverMajorVersion = atoi(versionText);
|
||||
|
||||
free(pairedText);
|
||||
@ -146,62 +150,62 @@ static int sign_it(const char *msg, size_t mlen, unsigned char **sig, size_t *sl
|
||||
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
if (ctx == NULL) {
|
||||
printf("EVP_MD_CTX_create failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_MD_CTX_create failed, error 0x%lx\n", ERR_get_error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
const EVP_MD *md = EVP_get_digestbyname("SHA256");
|
||||
if (md == NULL) {
|
||||
printf("EVP_get_digestbyname failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_get_digestbyname failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
int rc = EVP_DigestInit_ex(ctx, md, NULL);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestInit_ex failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestInit_ex failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignInit failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignInit failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = EVP_DigestSignUpdate(ctx, msg, mlen);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignUpdate failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignUpdate failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
size_t req = 0;
|
||||
rc = EVP_DigestSignFinal(ctx, NULL, &req);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignFinal failed (1), error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (1), error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(req > 0)) {
|
||||
printf("EVP_DigestSignFinal failed (2), error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (2), error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*sig = OPENSSL_malloc(req);
|
||||
if (*sig == NULL) {
|
||||
printf("OPENSSL_malloc failed, error 0x%lx\n", ERR_get_error());
|
||||
fprintf(stderr, "OPENSSL_malloc failed, error 0x%lx\n", ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*slen = req;
|
||||
rc = EVP_DigestSignFinal(ctx, *sig, slen);
|
||||
if (rc != 1) {
|
||||
printf("EVP_DigestSignFinal failed (3), return code %d, error 0x%lx\n", rc,
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed (3), return code %d, error 0x%lx\n", rc,
|
||||
ERR_get_error());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req != *slen) {
|
||||
printf("EVP_DigestSignFinal failed, mismatched signature sizes %ld, %ld\n",
|
||||
fprintf(stderr, "EVP_DigestSignFinal failed, mismatched signature sizes %ld, %ld\n",
|
||||
req, *slen);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -223,6 +227,11 @@ void client_pair(const char *address) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentGame != 0) {
|
||||
fprintf(stderr, "The computer is currently in a game. You must close the game before pairing.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char pin[5];
|
||||
sprintf(pin, "%d%d%d%d", (int)random() % 10, (int)random() % 10, (int)random() % 10, (int)random() % 10);
|
||||
printf("Please enter the following PIN on the target PC: %s\n", pin);
|
||||
@ -305,7 +314,7 @@ void client_pair(const char *address) {
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", address, unique_id, client_pairing_secret_hex);
|
||||
http_request(url, data);
|
||||
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, unique_id, challenge_response_hex);
|
||||
sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, unique_id);
|
||||
http_request(url, data);
|
||||
http_free_data(data);
|
||||
|
||||
|
@ -18,49 +18,30 @@
|
||||
*/
|
||||
|
||||
#include "connection.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void connection_stage_starting(int stage)
|
||||
{
|
||||
printf("connection_stage_starting %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_stage_complete(int stage)
|
||||
{
|
||||
printf("connection_stage_complete %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_stage_failed(int stage, long iets)
|
||||
{
|
||||
printf("connection_stage_failed %d\n", stage);
|
||||
}
|
||||
|
||||
void connection_connection_started()
|
||||
{
|
||||
printf("connection_connection_started\n");
|
||||
}
|
||||
|
||||
void connection_connection_terminated()
|
||||
{
|
||||
printf("connection_connection_terminated\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
void connection_display_message(char *msg)
|
||||
{
|
||||
printf("connection_display_message: %s\n", msg);
|
||||
printf("%s\n", msg);
|
||||
}
|
||||
|
||||
void connection_display_transient_message(char *msg)
|
||||
{
|
||||
printf("connection_display_transient_message: %s\n", msg);
|
||||
printf("%s\n", msg);
|
||||
}
|
||||
|
||||
CONNECTION_LISTENER_CALLBACKS connection_callbacks = {
|
||||
.stageStarting = connection_stage_starting,
|
||||
.stageComplete = connection_stage_complete,
|
||||
.stageFailed = connection_stage_failed,
|
||||
.connectionStarted = connection_connection_started,
|
||||
.stageStarting = NULL,
|
||||
.stageComplete = NULL,
|
||||
.stageFailed = NULL,
|
||||
.connectionStarted = NULL,
|
||||
.connectionTerminated = connection_connection_terminated,
|
||||
.displayMessage = connection_display_message,
|
||||
.displayTransientMessage = connection_display_transient_message,
|
||||
|
27
src/global.c
Normal file
27
src/global.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_t main_thread_id;
|
||||
|
||||
void quit() {
|
||||
pthread_kill(main_thread_id, SIGTERM);
|
||||
}
|
24
src/global.h
Normal file
24
src/global.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
extern pthread_t main_thread_id;
|
||||
|
||||
void quit();
|
@ -56,6 +56,7 @@ void http_init() {
|
||||
curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyFile);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _write_curl);
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
||||
}
|
||||
|
||||
int http_request(char* url, struct http_data* data) {
|
||||
|
215
src/input.c
215
src/input.c
@ -19,21 +19,30 @@
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "mapping.h"
|
||||
#include "global.h"
|
||||
|
||||
#include "libevdev/libevdev.h"
|
||||
#include "limelight-common/Limelight.h"
|
||||
|
||||
#ifdef HAVE_LIBCEC
|
||||
#include <ceccloader.h>
|
||||
#endif
|
||||
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
struct input_abs_parms {
|
||||
int min, max;
|
||||
@ -51,7 +60,7 @@ struct input_device {
|
||||
__s32 mouseDeltaX, mouseDeltaY, mouseScroll;
|
||||
short controllerId;
|
||||
int buttonFlags;
|
||||
short leftTrigger, rightTrigger;
|
||||
char leftTrigger, rightTrigger;
|
||||
short leftStickX, leftStickY;
|
||||
short rightStickX, rightStickY;
|
||||
bool gamepadModified;
|
||||
@ -74,6 +83,91 @@ static struct udev *udev;
|
||||
static struct udev_monitor *udev_mon;
|
||||
static int udev_fdindex;
|
||||
|
||||
static int sig_fdindex;
|
||||
|
||||
#ifdef HAVE_LIBCEC
|
||||
static libcec_configuration g_config;
|
||||
static char g_strPort[50] = { 0 };
|
||||
static libcec_interface_t g_iface;
|
||||
static ICECCallbacks g_callbacks;
|
||||
|
||||
static int on_cec_keypress(void* userdata, const cec_keypress key) {
|
||||
char value;
|
||||
switch (key.keycode) {
|
||||
case CEC_USER_CONTROL_CODE_UP:
|
||||
value = KEY_UP;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_DOWN:
|
||||
value = KEY_DOWN;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_LEFT:
|
||||
value = KEY_LEFT;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_RIGHT:
|
||||
value = KEY_RIGHT;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_ENTER:
|
||||
case CEC_USER_CONTROL_CODE_SELECT:
|
||||
value = KEY_ENTER;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_ROOT_MENU:
|
||||
value = KEY_TAB;
|
||||
break;
|
||||
case CEC_USER_CONTROL_CODE_AN_RETURN:
|
||||
case CEC_USER_CONTROL_CODE_EXIT:
|
||||
value = KEY_ESC;
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value != 0) {
|
||||
short code = 0x80 << 8 | keyCodes[value];
|
||||
LiSendKeyboardEvent(code, (key.duration > 0)?KEY_ACTION_DOWN:KEY_ACTION_UP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_cec() {
|
||||
libcecc_reset_configuration(&g_config);
|
||||
g_config.clientVersion = LIBCEC_VERSION_CURRENT;
|
||||
g_config.bActivateSource = 0;
|
||||
g_callbacks.CBCecKeyPress = &on_cec_keypress;
|
||||
g_config.callbacks = &g_callbacks;
|
||||
snprintf(g_config.strDeviceName, sizeof(g_config.strDeviceName), "Moonlight");
|
||||
g_config.callbacks = &g_callbacks;
|
||||
g_config.deviceTypes.types[0] = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
|
||||
|
||||
if (libcecc_initialise(&g_config, &g_iface, NULL) != 1) {
|
||||
fprintf(stderr, "Failed to initialize libcec interface\n");
|
||||
fflush(stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
g_iface.init_video_standalone(g_iface.connection);
|
||||
|
||||
cec_adapter devices[10];
|
||||
int8_t iDevicesFound = g_iface.find_adapters(g_iface.connection, devices, sizeof(devices) / sizeof(devices), NULL);
|
||||
|
||||
if (iDevicesFound <= 0) {
|
||||
fprintf(stderr, "No CEC devices found\n");
|
||||
fflush(stderr);
|
||||
libcecc_destroy(&g_iface);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(g_strPort, devices[0].comm);
|
||||
if (!g_iface.open(g_iface.connection, g_strPort, 5000)) {
|
||||
fprintf(stderr, "Unable to open the device on port %s\n", g_strPort);
|
||||
fflush(stderr);
|
||||
libcecc_destroy(&g_iface);
|
||||
return;
|
||||
}
|
||||
|
||||
g_iface.set_active_source(g_iface.connection, g_config.deviceTypes.types[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void input_init_parms(struct input_device *dev, struct input_abs_parms *parms, int code) {
|
||||
parms->flat = libevdev_get_abs_flat(dev->dev, code);
|
||||
parms->min = libevdev_get_abs_minimum(dev->dev, code);
|
||||
@ -109,6 +203,7 @@ void input_create(const char* device, char* mapFile) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&devices[dev], 0, sizeof(devices[0]));
|
||||
devices[dev].fd = fd;
|
||||
devices[dev].dev = libevdev_new();
|
||||
libevdev_set_fd(devices[dev].dev, devices[dev].fd);
|
||||
@ -141,11 +236,15 @@ static void input_remove(int devindex) {
|
||||
if (fdindex != numFds && numFds > 0) {
|
||||
memcpy(&fds[fdindex], &fds[numFds], sizeof(struct pollfd));
|
||||
if (numFds == udev_fdindex)
|
||||
udev_fdindex = numFds;
|
||||
udev_fdindex = fdindex;
|
||||
else if (numFds == sig_fdindex)
|
||||
sig_fdindex = fdindex;
|
||||
else {
|
||||
for (int i=0;i<numDevices;i++) {
|
||||
if (devices[i].fdindex == numFds)
|
||||
if (devices[i].fdindex == numFds) {
|
||||
devices[i].fdindex = fdindex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,13 +255,18 @@ static void input_remove(int devindex) {
|
||||
}
|
||||
|
||||
void input_init(char* mapfile) {
|
||||
#ifdef HAVE_LIBCEC
|
||||
init_cec();
|
||||
#endif
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev) {
|
||||
fprintf(stderr, "Can't create udev\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (autoadd = numDevices == 0) {
|
||||
autoadd = (numDevices == 0);
|
||||
if (autoadd) {
|
||||
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
|
||||
udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
@ -187,11 +291,11 @@ void input_init(char* mapfile) {
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "input", NULL);
|
||||
udev_monitor_enable_receiving(udev_mon);
|
||||
|
||||
int udev_fdindex = numFds;
|
||||
numFds++;
|
||||
udev_fdindex = numFds++;
|
||||
sig_fdindex = numFds++;
|
||||
|
||||
if (fds == NULL)
|
||||
fds = malloc(sizeof(struct pollfd));
|
||||
fds = malloc(sizeof(struct pollfd)*numFds);
|
||||
else
|
||||
fds = realloc(fds, sizeof(struct pollfd)*numFds);
|
||||
|
||||
@ -203,6 +307,17 @@ void input_init(char* mapfile) {
|
||||
defaultMapfile = mapfile;
|
||||
fds[udev_fdindex].fd = udev_monitor_get_fd(udev_mon);
|
||||
fds[udev_fdindex].events = POLLIN;
|
||||
|
||||
main_thread_id = pthread_self();
|
||||
sigset_t sigset;
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGHUP);
|
||||
sigaddset(&sigset, SIGTERM);
|
||||
sigaddset(&sigset, SIGINT);
|
||||
sigaddset(&sigset, SIGQUIT);
|
||||
sigprocmask(SIG_BLOCK, &sigset, NULL);
|
||||
fds[sig_fdindex].fd = signalfd(-1, &sigset, 0);
|
||||
fds[sig_fdindex].events = POLLIN | POLLERR | POLLHUP;
|
||||
}
|
||||
|
||||
void input_destroy() {
|
||||
@ -216,10 +331,10 @@ static short input_convert_value(struct input_event *ev, struct input_device *de
|
||||
return reverse?SHRT_MIN:SHRT_MAX;
|
||||
else if (ev->value < parms->min)
|
||||
return reverse?SHRT_MAX:SHRT_MIN;
|
||||
else {
|
||||
int value = ev->value + (ev->value<parms->avg?parms->flat:-parms->flat);
|
||||
return (value-parms->avg) * SHRT_MAX / ((reverse?-parms->range-1:parms->range) - parms->flat);
|
||||
}
|
||||
else if (reverse)
|
||||
return (parms->max - (ev->value<parms->avg?parms->flat*2:0) - ev->value) * (SHRT_MAX-SHRT_MIN) / (parms->max-parms->min-parms->flat*2) - SHRT_MIN;
|
||||
else
|
||||
return (ev->value - (ev->value>parms->avg?parms->flat*2:0) - parms->min) * (SHRT_MAX-SHRT_MIN) / (parms->max-parms->min-parms->flat*2) - SHRT_MIN;
|
||||
}
|
||||
|
||||
static char input_convert_value_byte(struct input_event *ev, struct input_device *dev, struct input_abs_parms *parms) {
|
||||
@ -228,7 +343,7 @@ static char input_convert_value_byte(struct input_event *ev, struct input_device
|
||||
else if (ev->value>parms->max)
|
||||
return UCHAR_MAX;
|
||||
else {
|
||||
int value = ev->value + parms->flat;
|
||||
int value = ev->value - parms->flat;
|
||||
return (value-parms->min) * UCHAR_MAX / (parms->diff-parms->flat);
|
||||
}
|
||||
}
|
||||
@ -345,20 +460,20 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
gamepadCode = SPECIAL_FLAG;
|
||||
}
|
||||
|
||||
if (mouseCode > 0) {
|
||||
if (mouseCode != 0) {
|
||||
LiSendMouseButtonEvent(ev->value?BUTTON_ACTION_PRESS:BUTTON_ACTION_RELEASE, mouseCode);
|
||||
} else {
|
||||
gamepadModified = true;
|
||||
|
||||
if (gamepadCode > 0) {
|
||||
if (gamepadCode != 0) {
|
||||
if (ev->value)
|
||||
dev->buttonFlags |= gamepadCode;
|
||||
else
|
||||
dev->buttonFlags &= ~gamepadCode;
|
||||
} else if (ev->code == dev->map.btn_tl2)
|
||||
dev->leftTrigger = ev->value?USHRT_MAX:0;
|
||||
dev->leftTrigger = ev->value?UCHAR_MAX:0;
|
||||
else if (ev->code == dev->map.btn_tr2)
|
||||
dev->rightTrigger = ev->value?USHRT_MAX:0;
|
||||
dev->rightTrigger = ev->value?UCHAR_MAX:0;
|
||||
else
|
||||
gamepadModified = false;
|
||||
}
|
||||
@ -372,7 +487,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
case REL_Y:
|
||||
dev->mouseDeltaY = ev->value;
|
||||
break;
|
||||
case REL_Z:
|
||||
case REL_WHEEL:
|
||||
dev->mouseScroll = ev->value;
|
||||
break;
|
||||
}
|
||||
@ -396,7 +511,7 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else if (dir == -1) {
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~RIGHT_FLAG;
|
||||
dev->buttonFlags &= ~LEFT_FLAG;
|
||||
} else {
|
||||
@ -406,11 +521,11 @@ static bool input_handle_event(struct input_event *ev, struct input_device *dev)
|
||||
} else if (ev->code == dev->map.abs_dpad_y) {
|
||||
int dir = input_convert_value_direction(ev, dev, &dev->dpadyParms, dev->map.reverse_dpad_y);
|
||||
if (dir == 1) {
|
||||
dev->buttonFlags |= UP_FLAG;
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
} else if (dir == -1) {
|
||||
dev->buttonFlags |= DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else if (dir == 0) {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags &= ~UP_FLAG;
|
||||
} else {
|
||||
dev->buttonFlags &= ~DOWN_FLAG;
|
||||
dev->buttonFlags |= UP_FLAG;
|
||||
@ -454,7 +569,14 @@ static bool input_handle_mapping_event(struct input_event *ev, struct input_devi
|
||||
return true;
|
||||
}
|
||||
|
||||
static void input_poll(bool (*handler) (struct input_event*, struct input_device*)) {
|
||||
static void input_drain(void) {
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
struct input_event ev;
|
||||
while (libevdev_next_event(devices[i].dev, LIBEVDEV_READ_FLAG_NORMAL, &ev) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool input_poll(bool (*handler) (struct input_event*, struct input_device*)) {
|
||||
while (poll(fds, numFds, -1)) {
|
||||
if (fds[udev_fdindex].revents > 0) {
|
||||
struct udev_device *dev = udev_monitor_receive_device(udev_mon);
|
||||
@ -469,6 +591,17 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
} else if (fds[sig_fdindex].revents > 0) {
|
||||
struct signalfd_siginfo info;
|
||||
read(fds[sig_fdindex].fd, &info, sizeof(info));
|
||||
|
||||
switch (info.ssi_signo) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
case SIGQUIT:
|
||||
case SIGHUP:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i=0;i<numDevices;i++) {
|
||||
if (fds[devices[i].fdindex].revents > 0) {
|
||||
@ -479,7 +612,7 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
fprintf(stderr, "Error: cannot keep up\n");
|
||||
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||
if (!handler(&ev, &devices[i]))
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (rc == -ENODEV) {
|
||||
@ -491,6 +624,8 @@ static void input_poll(bool (*handler) (struct input_event*, struct input_device
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void input_map_key(char* keyName, short* key) {
|
||||
@ -498,38 +633,50 @@ static void input_map_key(char* keyName, short* key) {
|
||||
currentKey = key;
|
||||
currentAbs = NULL;
|
||||
*key = -1;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
static void input_map_abs(char* keyName, short* abs, bool* reverse) {
|
||||
printf("%s\n", keyName);
|
||||
printf("Move %s\n", keyName);
|
||||
currentKey = NULL;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*abs = -1;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
static void input_map_abskey(char* keyName, short* key, short* abs, bool* reverse) {
|
||||
printf("%s\n", keyName);
|
||||
printf("Press %s\n", keyName);
|
||||
currentKey = key;
|
||||
currentAbs = abs;
|
||||
currentReverse = reverse;
|
||||
*key = -1;
|
||||
*abs = -1;
|
||||
*currentReverse = false;
|
||||
input_poll(input_handle_mapping_event);
|
||||
if (!input_poll(input_handle_mapping_event))
|
||||
exit(1);
|
||||
|
||||
usleep(250000);
|
||||
input_drain();
|
||||
}
|
||||
|
||||
void input_map(char* fileName) {
|
||||
struct mapping map;
|
||||
|
||||
input_map_abs("Left Stick Right", &(map.abs_x), &(map.reverse_x));
|
||||
input_map_abs("Left Stick Down", &(map.abs_y), &(map.reverse_y));
|
||||
input_map_abs("Left Stick Up", &(map.abs_y), &(map.reverse_y));
|
||||
input_map_key("Left Stick Button", &(map.btn_thumbl));
|
||||
|
||||
input_map_abs("Right Stick Right", &(map.abs_rx), &(map.reverse_rx));
|
||||
input_map_abs("Right Stick Down", &(map.abs_ry), &(map.reverse_ry));
|
||||
input_map_abs("Right Stick Up", &(map.abs_ry), &(map.reverse_ry));
|
||||
input_map_key("Right Stick Button", &(map.btn_thumbr));
|
||||
|
||||
input_map_abskey("D-Pad Right", &(map.btn_dpad_right), &(map.abs_dpad_x), &(map.reverse_dpad_x));
|
||||
@ -553,11 +700,11 @@ void input_map(char* fileName) {
|
||||
input_map_key("Special Button", &(map.btn_mode));
|
||||
|
||||
bool ignored;
|
||||
input_map_abskey("Left Trigger", &(map.btn_tl), &(map.abs_z), &ignored);
|
||||
input_map_abskey("Right Trigger", &(map.btn_tr), &(map.abs_rz), &ignored);
|
||||
input_map_abskey("Left Trigger", &(map.btn_tl2), &(map.abs_z), &ignored);
|
||||
input_map_abskey("Right Trigger", &(map.btn_tr2), &(map.abs_rz), &ignored);
|
||||
|
||||
input_map_key("Left Bumper", &(map.btn_tl2));
|
||||
input_map_key("Right Bumper", &(map.btn_tr2));
|
||||
input_map_key("Left Bumper", &(map.btn_tl));
|
||||
input_map_key("Right Bumper", &(map.btn_tr));
|
||||
mapping_save(fileName, &map);
|
||||
}
|
||||
|
||||
|
21
src/main.c
21
src/main.c
@ -53,7 +53,7 @@ static void applist(const char* address) {
|
||||
static void stream(STREAM_CONFIGURATION* config, const char* address, const char* app, bool sops, bool localaudio) {
|
||||
int appId = client_get_app_id(address, app);
|
||||
if (appId<0) {
|
||||
printf("Can't find app %s\n", app);
|
||||
fprintf(stderr, "Can't find app %s\n", app);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -61,20 +61,7 @@ static void stream(STREAM_CONFIGURATION* config, const char* address, const char
|
||||
|
||||
video_init();
|
||||
|
||||
struct addrinfo hints, *res;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int err = getaddrinfo(address, NULL, &hints, &res);
|
||||
if (err<0 || res == NULL) {
|
||||
printf("Can't resolve host: %s\n", address);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct sockaddr_in *addr = (struct sockaddr_in*)res->ai_addr;
|
||||
LiStartConnection(addr->sin_addr.s_addr, config, NULL, decoder_callbacks,
|
||||
&audio_callbacks, NULL, NULL, 0, client_get_server_version());
|
||||
freeaddrinfo(res);
|
||||
LiStartConnection(address, config, &connection_callbacks, decoder_callbacks, &audio_callbacks, NULL, NULL, 0, client_get_server_version());
|
||||
|
||||
input_loop();
|
||||
|
||||
@ -147,7 +134,7 @@ char* get_path(char* name) {
|
||||
|
||||
static void pair_check(void) {
|
||||
if (!client_is_paired(NULL)) {
|
||||
printf("You must pair with the PC first\n");
|
||||
fprintf(stderr, "You must pair with the PC first\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@ -265,7 +252,7 @@ int main(int argc, char* argv[]) {
|
||||
address[0] = 0;
|
||||
discover_server(address);
|
||||
if (address[0] == 0) {
|
||||
perror("Can't find server");
|
||||
fprintf(stderr, "Autodiscovery failed. Specify an IP address next time.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
@ -100,11 +100,11 @@ void mapping_load(char* fileName, struct mapping* map) {
|
||||
else if (strcmp("reverse_ry", key) == 0)
|
||||
map->reverse_ry = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_x", key) == 0)
|
||||
map->reverse_x = strcmp("true", value) == 0;
|
||||
map->reverse_dpad_x = strcmp("true", value) == 0;
|
||||
else if (strcmp("reverse_dpad_y", key) == 0)
|
||||
map->reverse_y = strcmp("true", value) == 0;
|
||||
map->reverse_dpad_y = strcmp("true", value) == 0;
|
||||
else
|
||||
printf("Can't map (%s)\n", key);
|
||||
fprintf(stderr, "Can't map (%s)\n", key);
|
||||
}
|
||||
if (key != NULL)
|
||||
free(key);
|
||||
|
@ -49,7 +49,7 @@ struct CertKeyPair generateCertKeyPair() {
|
||||
|
||||
p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0);
|
||||
if (p12 == NULL) {
|
||||
printf("Error generating a valid PKCS12 certificate.\n");
|
||||
fprintf(stderr, "Error generating a valid PKCS12 certificate.\n");
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
|
19
src/video.c
19
src/video.c
@ -27,7 +27,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
DECODER_RENDERER_CALLBACKS *decoder_callbacks;
|
||||
char* decoder_output_name;
|
||||
|
||||
static int decoder_level;
|
||||
|
||||
@ -37,22 +36,14 @@ void video_init() {
|
||||
#else
|
||||
decoder_callbacks = &decoder_callbacks_fake;
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
if (dlsym(RTLD_DEFAULT, "vpu_Init") != NULL && video_imx_init()) {
|
||||
decoder_callbacks = &decoder_callbacks_imx;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OMX
|
||||
if (dlsym(RTLD_DEFAULT, "bcm_host_init") != NULL) {
|
||||
decoder_callbacks = &decoder_callbacks_omx;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
if (dlsym(RTLD_DEFAULT, "vpu_Init") != NULL) {
|
||||
decoder_callbacks = &decoder_callbacks_imx;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int video_add_output(int level, char* name, DECODER_RENDERER_CALLBACKS *callbacks) {
|
||||
if (level > decoder_level) {
|
||||
decoder_output_name = name;
|
||||
decoder_level = level;
|
||||
decoder_callbacks = callbacks;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "limelight-common/Limelight.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern DECODER_RENDERER_CALLBACKS *decoder_callbacks;
|
||||
|
||||
void video_init();
|
||||
@ -31,5 +33,6 @@ extern DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl;
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx;
|
||||
#endif
|
||||
#ifdef HAVE_IMX
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_omx;
|
||||
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_imx;
|
||||
bool video_imx_init();
|
||||
#endif
|
||||
|
@ -25,12 +25,10 @@ static FILE* fd;
|
||||
static const char* fileName = "fake.h264";
|
||||
|
||||
void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
printf("decoder_renderer_setup %dx%d %dfps\n", width, height, redrawRate);
|
||||
fd = fopen(fileName, "w");
|
||||
}
|
||||
|
||||
void decoder_renderer_release() {
|
||||
printf("decoder_renderer_release\n");
|
||||
void decoder_renderer_cleanup() {
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
@ -45,8 +43,6 @@ int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_fake = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
@ -19,9 +19,6 @@
|
||||
|
||||
#include "../video.h"
|
||||
|
||||
#include "vpu_io.h"
|
||||
#include "vpu_lib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@ -43,6 +40,9 @@
|
||||
#include <linux/v4l2-controls.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <vpu_io.h>
|
||||
#include <vpu_lib.h>
|
||||
|
||||
#define STREAM_BUF_SIZE 0x200000
|
||||
#define PS_SAVE_SIZE 0x080000
|
||||
|
||||
@ -72,6 +72,10 @@ static int disp_clr_index = 0;
|
||||
static FrameBuffer *fb;
|
||||
static struct v4l2_buffer dbuf;
|
||||
|
||||
bool video_imx_init() {
|
||||
return vpu_Init(NULL) == RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
struct mxcfb_gbl_alpha alpha;
|
||||
|
||||
@ -94,11 +98,6 @@ static void decoder_renderer_setup(int width, int height, int redrawRate, void*
|
||||
|
||||
close(fd_fb);
|
||||
|
||||
if (vpu_Init(NULL) != RETCODE_SUCCESS){
|
||||
fprintf(stderr, "Can't intialize VPU\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mem_desc.size = STREAM_BUF_SIZE;
|
||||
if (IOGetPhyMem(&mem_desc)){
|
||||
fprintf(stderr, "Can't get physical memory address\n");
|
||||
@ -413,7 +412,7 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
return DR_OK;
|
||||
}
|
||||
|
||||
static void decoder_renderer_release() {
|
||||
static void decoder_renderer_cleanup() {
|
||||
IOFreePhyMem(&ps_mem_desc);
|
||||
IOFreePhyMem(&slice_mem_desc);
|
||||
|
||||
@ -424,8 +423,6 @@ static void decoder_renderer_release() {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_imx = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
@ -30,14 +30,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../video.h"
|
||||
|
||||
#include "bcm_host.h"
|
||||
#include "ilclient.h"
|
||||
#include "h264_stream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ilclient.h>
|
||||
#include <bcm_host.h>
|
||||
|
||||
static TUNNEL_T tunnel[2];
|
||||
static COMPONENT_T *list[3];
|
||||
static ILCLIENT_T *client;
|
||||
@ -129,7 +130,7 @@ static void decoder_renderer_setup(int width, int height, int redrawRate, void*
|
||||
}
|
||||
}
|
||||
|
||||
static void decoder_renderer_stop() {
|
||||
static void decoder_renderer_cleanup() {
|
||||
int status = 0;
|
||||
|
||||
buf->nFilledLen = 0;
|
||||
@ -144,9 +145,7 @@ static void decoder_renderer_stop() {
|
||||
ilclient_flush_tunnels(tunnel, 0);
|
||||
|
||||
ilclient_disable_port_buffers(list[0], 130, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void decoder_renderer_release() {
|
||||
ilclient_disable_tunnel(tunnel);
|
||||
ilclient_teardown_tunnels(tunnel);
|
||||
|
||||
@ -227,8 +226,6 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_omx = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.start = NULL,
|
||||
.stop = decoder_renderer_stop,
|
||||
.release = decoder_renderer_release,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ static void sdl_setup(int width, int height, int redrawRate, void* context, int
|
||||
screen_height = height;
|
||||
}
|
||||
|
||||
static void sdl_release() {
|
||||
static void sdl_cleanup() {
|
||||
ffmpeg_destroy();
|
||||
}
|
||||
|
||||
@ -109,8 +109,6 @@ static int sdl_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_sdl = {
|
||||
.setup = sdl_setup,
|
||||
.start = NULL,
|
||||
.stop = NULL,
|
||||
.release = sdl_release,
|
||||
.cleanup = sdl_cleanup,
|
||||
.submitDecodeUnit = sdl_submit_decode_unit,
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
struct xml_query search;
|
||||
search.data = node;
|
||||
search.start = 0;
|
||||
search.memory = malloc(1);
|
||||
search.memory = calloc(1, 1);
|
||||
search.size = 0;
|
||||
XML_Parser parser = XML_ParserCreate("UTF-8");
|
||||
XML_SetUserData(parser, &search);
|
||||
@ -100,7 +100,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
XML_SetCharacterDataHandler(parser, _xml_write_data);
|
||||
if (! XML_Parse(parser, data, len, 1)) {
|
||||
int code = XML_GetErrorCode(parser);
|
||||
printf("%s\n", XML_ErrorString(code));
|
||||
fprintf(stderr, "XML Error: %s\n", XML_ErrorString(code));
|
||||
return 1;
|
||||
}
|
||||
*result = search.memory;
|
||||
@ -110,7 +110,7 @@ int xml_search(char* data, size_t len, char* node, char** result) {
|
||||
|
||||
struct app_list* xml_applist(char* data, size_t len) {
|
||||
struct xml_query query;
|
||||
query.memory = malloc(1);
|
||||
query.memory = calloc(1, 1);
|
||||
query.size = 0;
|
||||
query.start = 0;
|
||||
query.data = NULL;
|
||||
@ -120,7 +120,7 @@ struct app_list* xml_applist(char* data, size_t len) {
|
||||
XML_SetCharacterDataHandler(parser, _xml_write_data);
|
||||
if (! XML_Parse(parser, data, len, 1)) {
|
||||
int code = XML_GetErrorCode(parser);
|
||||
printf("%s\n", XML_ErrorString(code));
|
||||
fprintf(stderr, "XML Error %s\n", XML_ErrorString(code));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
306
third_party/libcec/ceccloader.h
vendored
Normal file
306
third_party/libcec/ceccloader.h
vendored
Normal 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
1
third_party/moonlight-common-c
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 678afd9c300ae4591aa53e3bbf0e14783803671e
|
Loading…
x
Reference in New Issue
Block a user