Compare commits

...

39 commits

Author SHA1 Message Date
Florian Märkl
a1fd418685 Update Ubuntu for AppImage to 24.04 2025-06-25 16:56:44 +02:00
Florian Märkl
bb5a79f234 Update dependencies in BSDs CI 2025-06-22 11:57:41 +02:00
Florian Märkl
4eb90a7a65 Refresh switch to build again 2025-06-09 12:20:27 +02:00
Florian Märkl
94fcdc3c61 Add reference to chiaki-ng 2024-07-31 15:54:39 +02:00
Florian Märkl
8911a44766 Remove Play Store from README.md 2023-08-20 12:53:52 +02:00
Florian Märkl
89368f63c9 Add script for local macOS distribution 2023-08-20 11:42:20 +02:00
Florian Märkl
d4a0603bf2 Fix switch host_addr regex for more arbitrary strings 2023-08-20 11:17:05 +02:00
Florian Märkl
666238ba9f Bump version to 2.2.0 2023-08-20 11:12:11 +02:00
Florian Märkl
bcdd0dd7fd Update CI images 2023-08-20 09:45:15 +02:00
Florian Märkl
6096de8c13 Do not handle server shutdown as error
When the console is powered off or put into sleep mode during streaming,
the remote will disconnect and report the string "Server shutting down".
This is expected by the user and thus should not be shown as an error
message.
2023-02-08 14:08:47 +01:00
Florian Märkl
582ec7aa54 Allow specifying command in switch podman script 2023-02-08 14:08:17 +01:00
Florian Märkl
e14083c87c Update android target SDK to 33 and dependencies 2023-02-05 19:46:34 +01:00
Johannes Baiter
c2f0932670 gui: Support for DualSense haptics and trigger effects
Haptics with PulseAudio does not seem to be working properly, so using
Pipewire as a backend is recommended (and picked by default, if
available via an SDL hint).
2023-02-01 18:05:59 +01:00
Johannes Baiter
7a490b5aae Fix feedback state position 0x1b when DualSense is connected.
The previous value of `0` caused the PS5 to expect a set of 'trigger status'
values in the 0x19 and 0x1a position, which would have required reading
raw values from the DualSense HID device, since these values are not
reported by the SDL DualSense driver (code that does so can be checked
out from the `trigger-feedback` branch on https://git.sr.ht/~jbaiter/chiaki).

Fortunately this is not neccessary, simply setting the value to `1`
seems to make the PS5 to rely on fallback logic (presumably based on the
L2/R2 value) and games that would otherwise have relied on the trigger
status (Astro's Playroom climbing levels) now work without any problems.
2023-01-29 13:39:30 +01:00
Johannes Baiter
4c8209762c Add support for touchpad and sensor handling via SDL
This should enable support for more controllers besides the DS4 and
DualSense, basically any controller supported by SDL that has at least
one touchpad, an accelerometer and a gyroscope.

Older SDL versions have been tested down to 2.0.9. Versions older than
2.0.14 won't have sensors and touchpad support, though.

Setsu is deprecated and remains in-tree for now, but defaults to being
disabled if SDL2 is found and >= 2.0.14. If Setsu is enabled explicitly,
touchpad and sensors are not handled by SDL.
2022-12-14 20:22:40 +01:00
Florian Märkl
76690a319c Fix testing on AppVeyor and make appveyor-win.sh more portable
test/chiaki-unit.exe failed to load some OpenSSL dlls somehow, which
broke the build. Moving them next to the executable fixes that.
The APPVEYOR_BUILD_FOLDER env var is also not needed anymore now.
2022-12-14 19:27:15 +01:00
Street Pea
36816db7ac Add quit (Ctrl+Q) shortcut to GUI 2022-12-10 15:13:22 +01:00
Street Pea
801f902bea Add transform/scaling modes to GUI
Added zoom and stretch modes to GUI to mirror the transform modes
available on Android. They are reachable through a context menu or
shortcuts (Ctrl+S/Ctrl+Z).
CLI options --stretch and --zoom have been added as well.

Co-authored-by: Florian Märkl <info@florianmaerkl.de>
2022-12-10 15:13:03 +01:00
Johannes Baiter
74d39e6314 lib: Add support for trigger effects and controller haptics
By default, no trigger effects and haptics are requested from the
console, lib users have to explicitly enable them for a session by
setting the new `enable_dualsense` flag on the session's
`ChiakiConnectInfo` struct.

Trigger Effects are simply a new Takion message type `11`  and
include the type of each effect and the effect data (10 bytes) for
each of the triggers. They are exposed as a new Chiaki event type
`CHIAKI_EVENT_TRIGGER_EFFECTS`.

Haptic effects are implemented in the protocol as a separate audio
stream, for which packets are only sent when there are actually
effects being played, i.e. silence is not explicitly encoded.
Audio data is 3kHz little endian 16 bit stereo sent in frames of
10 samples every 100ms. Note that the Takion AV header has the
codec field set to Opus, however this is not true.
Users can provide a new `ChiakiAudioSink` dedicated to haptics
via the new `chiaki_session_set_haptics_sink` API, which behaves
identical to the regular audio sink, except that it has a lower
frequency.
2022-11-01 18:29:05 +01:00
Florian Märkl
40a9dee4ed Fix some EINTR handling 2022-10-23 13:42:12 +02:00
Florian Märkl
6bfbcfc456 Update chiaki-build-switch image in build script 2022-09-25 14:24:43 +02:00
Florian Märkl
e00f5fae9d Update macOS icon in Big Sur style 2022-09-25 10:29:17 +02:00
Florian Märkl
4164255ef9 Update dependencies and fix CI
* nanopb 0.4.6.4 with PB_C99_STATIC_ASSERT to avoid depending on C11
* OpenSSL 1.1.1q on windows
* Switched from docker to podman in CI
* Appdir in appimage build container is now in /build/appdir to fix
  "Invalid cross-device link" errors in linuxdeploy when appdir is in
  mount
* Use python protobuf==3.19.5 in bionic image, which still supports
  python 3.6, and on windows where nanopb otherwise has issues
* Purge nanopb_pb2.py to force regeneration of it for possibly different
  python protobuf versions in subsequent builds
* FreeBSD needs py39 packages now
2022-09-24 15:18:53 +02:00
Florian Märkl
b790fb3fb5 Set PATH to find protoc for nanopb generator 2022-06-02 18:26:42 +02:00
Florian Märkl
b4f051395f Reduce targets in fetched mbedtls and show progress 2022-06-02 17:58:57 +02:00
Florian Märkl
420809b24e Add option to fetch mbedtls with cmake 2022-06-02 17:10:19 +02:00
Florian Märkl
7d820bd4ab Update and fix CI
* appimage: switched to bionic
* android: updated container for nanopb changes
* switch: updated devkitpro and simpler cmake scripts
2022-03-26 18:33:15 +01:00
Florian Märkl
aa3a3b8bbc Update Windows Dependencies in CI 2022-03-26 11:33:50 +01:00
MiniMeOSc
ccecc67d74 Fix stream command not working for second or later host in configuration 2022-03-22 11:38:47 +01:00
Florian Märkl
dcd2e6af4a Update nanopb to fix unaligned pointers on arm64 2021-12-03 11:47:32 +01:00
Florian Märkl
7a01ac0d41 Update BSD CI 2021-12-03 11:46:47 +01:00
Florian Märkl
796a128456 Fix fec.c extension 2021-04-11 18:19:46 +02:00
Florian Märkl
695da18473 Make CLI Wakeup work for PS5 2021-04-11 18:11:35 +02:00
Florian Märkl
7870a28cdd Fix Discovery in CLI 2021-04-11 18:11:35 +02:00
Florian Märkl
a44000ea2b Enable CLI in CI 2021-04-11 18:11:35 +02:00
Florian Märkl
2b4a7426ff Install CLI 2021-04-11 18:11:35 +02:00
Florian Märkl
f50b060795 Fix AppVeyor 2021-04-11 18:11:35 +02:00
Florian Märkl
a049ed43ec
Force-disable Lib Decoders on Android 2021-02-02 10:59:26 +01:00
Florian Märkl
ae3ca1ac7a
Update Flatpak to v2.1.1 2021-01-24 14:02:17 +01:00
89 changed files with 1793 additions and 377 deletions

View file

@ -5,6 +5,7 @@ image:
branches:
only:
- master
- develop
- /^v\d.*$/
- /^deploy-test(-.*)?$/
@ -36,14 +37,14 @@ for:
install:
- git submodule update --init --recursive
- sudo pip3 install protobuf
- brew install qt opus openssl@1.1 nasm sdl2 protobuf
- HOMEBREW_NO_AUTO_UPDATE=1 brew install qt@5 opus openssl@1.1 nasm sdl2 protobuf
- scripts/build-ffmpeg.sh
build_script:
- export CMAKE_PREFIX_PATH="`pwd`/ffmpeg-prefix;/usr/local/opt/openssl@1.1;/usr/local/opt/qt"
- export CMAKE_PREFIX_PATH="`pwd`/ffmpeg-prefix;/usr/local/opt/openssl@1.1;/usr/local/opt/qt@5"
- scripts/build-common.sh
- cp -a build/gui/chiaki.app Chiaki.app
- /usr/local/opt/qt/bin/macdeployqt Chiaki.app -dmg
- /usr/local/opt/qt@5/bin/macdeployqt Chiaki.app -dmg
artifacts:
- path: Chiaki.dmg

View file

@ -22,7 +22,7 @@ tasks:
sudo docker run \
-v /home/build:/home/build \
-u $(id -u):$(id -g) \
thestr4ng3r/android:f064ea6 \
thestr4ng3r/android:90d826e \
/bin/bash -c "cd /home/build/chiaki/android && ./gradlew assembleRelease bundleRelease"
cp chiaki/android/app/build/outputs/apk/release/app-release*.apk Chiaki.apk
cp chiaki/android/app/build/outputs/bundle/release/app-release*.aab Chiaki.aab

View file

@ -9,37 +9,47 @@ packages:
- ninja
- protoc
- py3-protobuf
- py3-setuptools
- opus-dev
- qt5-qtbase-dev
- qt5-qtsvg-dev
- qt5-qtmultimedia-dev
- ffmpeg-dev
- sdl2-dev
- docker
- podman
- fuse
- udev
- argp-standalone
artifacts:
- chiaki.nro
- Chiaki.AppImage
tasks:
- start_docker: |
sudo service docker start
sudo chmod +s /usr/bin/docker # Yes, I know what I am doing
sudo service fuse start # Fuse for AppImages
- setup_podman: |
sudo rc-service udev start
sudo rc-service cgroups start
sudo rc-service fuse start # Fuse for AppImages
echo build:100000:65536 | sudo tee /etc/subuid
echo build:100000:65536 | sudo tee /etc/subgid
# https://www.kernel.org/doc/Documentation/networking/tuntap.txt
# for slirp4netns
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 0666 /dev/net/tun
- local_build_and_test: |
cd chiaki
cmake -Bbuild -GNinja
cmake -Bbuild -GNinja -DCHIAKI_ENABLE_CLI=ON -DCHIAKI_ENABLE_GUI=ON -DCHIAKI_CLI_ARGP_STANDALONE=ON
ninja -C build
build/test/chiaki-unit
- appimage: |
cd chiaki
scripts/run-docker-build-appimage.sh
scripts/run-podman-build-appimage.sh
cp appimage/Chiaki.AppImage ../Chiaki.AppImage
- switch: |
cd chiaki
scripts/switch/run-docker-build-chiaki.sh
scripts/switch/run-podman-build-chiaki.sh
cp build_switch/switch/chiaki.nro ../chiaki.nro
- bullseye: |
cd chiaki
scripts/run-docker-build-bullseye.sh
scripts/run-podman-build-bullseye.sh

View file

@ -1,5 +1,5 @@
image: freebsd/latest
image: freebsd/14.x
sources:
- https://git.sr.ht/~thestr4ng3r/chiaki
@ -7,7 +7,8 @@ sources:
packages:
- cmake
- protobuf
- py37-protobuf
- py311-setuptools # should not be needed with nanopb >= 0.4.9
- py311-protobuf
- opus
- qt5-core
- qt5-qmake

View file

@ -1,5 +1,5 @@
image: openbsd/6.7
image: openbsd/latest
sources:
- https://git.sr.ht/~thestr4ng3r/chiaki
@ -7,6 +7,7 @@ sources:
packages:
- cmake
- protobuf
- py3-setuptools # should not be needed with nanopb >= 0.4.9
- py3-protobuf
- opus
- qtbase

2
.gitignore vendored
View file

@ -29,3 +29,5 @@ compile_commands.json
chiaki.conf
/appimage
.cache/
/*.app
/*.dmg

2
.gitmodules vendored
View file

@ -15,4 +15,4 @@
url = https://github.com/google/oboe
[submodule "switch/borealis"]
path = switch/borealis
url = https://github.com/natinusala/borealis.git
url = https://git.sr.ht/~thestr4ng3r/borealis

View file

@ -24,6 +24,7 @@ endif()
tri_option(CHIAKI_ENABLE_FFMPEG_DECODER "Enable FFMPEG video decoder" ${CHIAKI_FFMPEG_DEFAULT})
tri_option(CHIAKI_ENABLE_PI_DECODER "Enable Raspberry Pi-specific video decoder (requires libraspberrypi0 and libraspberrypi-doc)" AUTO)
option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
option(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT "Fetch Mbed TLS instead of using system-provided libs" OFF)
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON)
option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
@ -31,8 +32,8 @@ tri_option(CHIAKI_USE_SYSTEM_JERASURE "Use system-provided jerasure instead of s
tri_option(CHIAKI_USE_SYSTEM_NANOPB "Use system-provided nanopb instead of submodule" AUTO)
set(CHIAKI_VERSION_MAJOR 2)
set(CHIAKI_VERSION_MINOR 1)
set(CHIAKI_VERSION_PATCH 1)
set(CHIAKI_VERSION_MINOR 2)
set(CHIAKI_VERSION_PATCH 0)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
set(CPACK_PACKAGE_NAME "chiaki")
@ -89,6 +90,20 @@ endif()
if(CHIAKI_LIB_ENABLE_MBEDTLS)
add_definitions(-DCHIAKI_LIB_ENABLE_MBEDTLS)
if(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT)
set(FETCHCONTENT_QUIET CACHE BOOL FALSE)
include(FetchContent)
set(ENABLE_TESTING CACHE INTERNAL OFF)
set(ENABLE_PROGRAMS CACHE INTERNAL OFF)
set(USE_SHARED_MBEDTLS_LIBRARY CACHE INTERNAL OFF)
FetchContent_Declare(
mbedtls
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
GIT_TAG 8b3f26a5ac38d4fdccbc5c5366229f3e01dafcc0 # v2.28.0
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(mbedtls)
endif()
endif()
if(CHIAKI_ENABLE_FFMPEG_DECODER)
@ -135,21 +150,30 @@ if(CHIAKI_ENABLE_CLI)
add_subdirectory(cli)
endif()
if(CHIAKI_ENABLE_GUI AND CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
find_package(SDL2 MODULE REQUIRED)
endif()
if(CHIAKI_ENABLE_SETSU)
find_package(Udev QUIET)
find_package(Evdev QUIET)
if(Udev_FOUND AND Evdev_FOUND)
set(CHIAKI_ENABLE_SETSU ON)
else()
if(NOT CHIAKI_ENABLE_SETSU STREQUAL AUTO)
message(FATAL_ERROR "
CHIAKI_ENABLE_SETSU is set to ON, but its dependencies (udev and evdev) could not be resolved.
Keep in mind that setsu is only supported on Linux!")
endif()
if(CHIAKI_ENABLE_SETSU STREQUAL AUTO AND SDL2_FOUND AND (SDL2_VERSION_MINOR GREATER 0 OR SDL2_VERSION_PATCH GREATER_EQUAL 14))
message(STATUS "SDL version ${SDL2_VERSION} is >= 2.0.14, disabling Setsu")
set(CHIAKI_ENABLE_SETSU OFF)
endif()
if(CHIAKI_ENABLE_SETSU)
add_subdirectory(setsu)
else()
find_package(Udev QUIET)
find_package(Evdev QUIET)
if(Udev_FOUND AND Evdev_FOUND)
set(CHIAKI_ENABLE_SETSU ON)
else()
if(NOT CHIAKI_ENABLE_SETSU STREQUAL AUTO)
message(FATAL_ERROR "
CHIAKI_ENABLE_SETSU is set to ON, but its dependencies (udev and evdev) could not be resolved.
Keep in mind that setsu is only supported on Linux!")
endif()
set(CHIAKI_ENABLE_SETSU OFF)
endif()
if(CHIAKI_ENABLE_SETSU)
add_subdirectory(setsu)
endif()
endif()
endif()
@ -160,7 +184,6 @@ else()
endif()
if(CHIAKI_ENABLE_GUI)
#add_subdirectory(setsu)
add_subdirectory(gui)
endif()

View file

@ -8,14 +8,19 @@
[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/c81ogebvsmo43dd3?svg=true)](https://ci.appveyor.com/project/thestr4ng3r/chiaki) [![builds.sr.ht Status](https://builds.sr.ht/~thestr4ng3r/chiaki.svg)](https://builds.sr.ht/~thestr4ng3r/chiaki?)
Chiaki is a Free and Open Source Software Client for PlayStation 4 and PlayStation 5 Remote Play
for Linux, FreeBSD, OpenBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
for Linux, FreeBSD, OpenBSD, NetBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
![Screenshot](assets/screenshot.png)
## Project Status
## Project Status and Contributing
As all relevant features are implemented, this project is considered to be finished and in maintenance mode only.
No major updates are planned and contributions are only accepted in special cases.
No major updates are planned and contributions are only accepted in special cases such as security issues.
The objective is to keep a stable base and not break existing support for less mainstream platforms such as BSDs.
**For a more active, fast moving and community-oriented project, refer
to [chiaki-ng](https://streetpea.github.io/chiaki-ng/) ("next generation").
If you would like to contribute, this will likely also be the best place to do so.**
![Screenshot](assets/screenshot.png)
## Installing
@ -28,7 +33,7 @@ Builds are provided for Linux, Android, macOS, Nintendo Switch and Windows.
You can download them [here](https://git.sr.ht/~thestr4ng3r/chiaki/refs).
* **Linux**: The provided file is an [AppImage](https://appimage.org/). Simply make it executable (`chmod +x <file>.AppImage`) and run it.
* **Android**: Install from [Google Play](https://play.google.com/store/apps/details?id=com.metallic.chiaki), [F-Droid](https://f-droid.org/packages/com.metallic.chiaki/) or download the APK from Sourcehut.
* **Android**: Install from [F-Droid](https://f-droid.org/packages/com.metallic.chiaki/) or download the APK from Sourcehut.
* **macOS**: Drag the application from the `.dmg` into your Applications folder.
* **Windows**: Extract the `.zip` file and execute `chiaki.exe`.
* **Switch**: Download the `.nro` file and copy it into the `switch/` directory on your SD card.

View file

@ -18,13 +18,12 @@ def chiakiVersion = "$chiakiVersionMajor.$chiakiVersionMinor.$chiakiVersionPatch
println("Determined Chiaki Version: $chiakiVersion")
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
compileSdkVersion 33
defaultConfig {
applicationId "com.metallic.chiaki"
minSdkVersion 21
targetSdkVersion 30
versionCode 11
targetSdkVersion 33
versionCode 12
versionName chiakiVersion
externalNativeBuild {
cmake {
@ -33,6 +32,8 @@ android {
"-DCHIAKI_ENABLE_GUI=OFF",
"-DCHIAKI_ENABLE_SETSU=OFF",
"-DCHIAKI_ENABLE_ANDROID=ON",
"-DCHIAKI_ENABLE_FFMPEG_DECODER=OFF",
"-DCHIAKI_ENABLE_PI_DECODER=OFF",
"-DCHIAKI_LIB_ENABLE_OPUS=OFF",
"-DCHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT=ON"
}
@ -50,7 +51,7 @@ android {
}
externalNativeBuild {
cmake {
version "3.10.2+"
version "3.22.1"
path rootCMakeLists
}
}
@ -93,23 +94,23 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.5.1'
implementation "io.reactivex.rxjava2:rxjava:2.2.20"
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
def room_version = "2.2.6"
def room_version = "2.5.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-rxjava2:$room_version"
implementation "com.squareup.moshi:moshi:1.9.2"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.9.2"
implementation "com.squareup.moshi:moshi:1.14.0"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.14.0"
}

View file

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
<application
android:allowBackup="true"
@ -28,7 +29,8 @@
</provider>
<activity android:name=".main.MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View file

@ -110,9 +110,9 @@ JNIEXPORT jstring JNICALL JNI_FCN(quitReasonToString)(JNIEnv *env, jobject obj,
return E->NewStringUTF(env, chiaki_quit_reason_string((ChiakiQuitReason)value));
}
JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsStopped)(JNIEnv *env, jobject obj, jint value)
JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsError)(JNIEnv *env, jobject obj, jint value)
{
return value == CHIAKI_QUIT_REASON_STOPPED;
return chiaki_quit_reason_is_error(value);
}
JNIEXPORT jobject JNICALL JNI_FCN(videoProfilePreset)(JNIEnv *env, jobject obj, jint resolution_preset, jint fps_preset, jobject codec)

@ -1 +1 @@
Subproject commit 0ab5b12a5bc3630a3d6c83b20eed2a669ebf7a24
Subproject commit 8740d0fc321a55489dbbf6067298201b7d2e106d

View file

@ -3,7 +3,7 @@
package com.metallic.chiaki.common
import androidx.room.*
import androidx.room.ForeignKey.SET_NULL
import androidx.room.ForeignKey.Companion.SET_NULL
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Single

View file

@ -3,7 +3,7 @@
package com.metallic.chiaki.common
import androidx.room.*
import androidx.room.ColumnInfo.BLOB
import androidx.room.ColumnInfo.Companion.BLOB
import com.metallic.chiaki.lib.RegistHost
import com.metallic.chiaki.lib.Target
import io.reactivex.Completable

View file

@ -25,6 +25,8 @@ import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import okio.Buffer
import okio.Okio
import okio.buffer
import okio.source
import java.io.File
import java.io.IOException
@ -164,7 +166,7 @@ fun importSettingsFromUri(activity: Activity, uri: Uri, disposable: CompositeDis
try
{
val inputStream = activity.contentResolver.openInputStream(uri) ?: throw IOException()
val buffer = Okio.buffer(Okio.source(inputStream))
val buffer = inputStream.source().buffer()
val reader = JsonReader.of(buffer)
val adapter = moshi().serializedSettingsAdapter()

View file

@ -83,7 +83,7 @@ private class ChiakiNative
}
@JvmStatic external fun errorCodeToString(value: Int): String
@JvmStatic external fun quitReasonToString(value: Int): String
@JvmStatic external fun quitReasonIsStopped(value: Int): Boolean
@JvmStatic external fun quitReasonIsError(value: Int): Boolean
@JvmStatic external fun videoProfilePreset(resolutionPreset: Int, fpsPreset: Int, codec: Codec): ConnectVideoProfile
@JvmStatic external fun sessionCreate(result: CreateResult, connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean, javaSession: Session)
@JvmStatic external fun sessionFree(ptr: Long)
@ -309,10 +309,7 @@ class QuitReason(val value: Int)
{
override fun toString() = ChiakiNative.quitReasonToString(value)
/**
* whether the reason is CHIAKI_QUIT_REASON_STOPPED
*/
val isStopped = ChiakiNative.quitReasonIsStopped(value)
val isError = ChiakiNative.quitReasonIsError(value)
}
sealed class Event

View file

@ -174,7 +174,7 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
.alpha(1.0f)
.setListener(object: AnimatorListenerAdapter()
{
override fun onAnimationEnd(animation: Animator?)
override fun onAnimationEnd(animation: Animator)
{
binding.overlay.alpha = 1.0f
}
@ -189,7 +189,7 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
.alpha(0.0f)
.setListener(object: AnimatorListenerAdapter()
{
override fun onAnimationEnd(animation: Animator?)
override fun onAnimationEnd(animation: Animator)
{
binding.overlay.isGone = true
}
@ -230,28 +230,33 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
{
is StreamStateQuit ->
{
if(!state.reason.isStopped && dialogContents != StreamQuitDialog)
if(dialogContents != StreamQuitDialog)
{
dialog?.dismiss()
val reasonStr = state.reasonString
val dialog = MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.alert_message_session_quit, state.reason.toString())
+ (if(reasonStr != null) "\n$reasonStr" else ""))
.setPositiveButton(R.string.action_reconnect) { _, _ ->
dialog = null
reconnect()
}
.setOnCancelListener {
dialog = null
finish()
}
.setNegativeButton(R.string.action_quit_session) { _, _ ->
dialog = null
finish()
}
.create()
dialogContents = StreamQuitDialog
dialog.show()
if(state.reason.isError)
{
dialog?.dismiss()
val reasonStr = state.reasonString
val dialog = MaterialAlertDialogBuilder(this)
.setMessage(getString(R.string.alert_message_session_quit, state.reason.toString())
+ (if(reasonStr != null) "\n$reasonStr" else ""))
.setPositiveButton(R.string.action_reconnect) { _, _ ->
dialog = null
reconnect()
}
.setOnCancelListener {
dialog = null
finish()
}
.setNegativeButton(R.string.action_quit_session) { _, _ ->
dialog = null
finish()
}
.create()
dialogContents = StreamQuitDialog
dialog.show()
}
else
finish()
}
}
@ -306,6 +311,8 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
dialog.show()
}
}
else -> {}
}
}

View file

@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.4.21'
ext.kotlin_version = '1.8.0'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.android.tools.build:gradle:7.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View file

@ -1,6 +1,6 @@
#Fri Jan 15 11:37:05 CET 2021
#Sun Feb 05 16:25:19 CET 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
zipStoreBase=GRADLE_USER_HOME

266
assets/chiaki_macos.svg Normal file
View file

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1024"
height="1024"
viewBox="0 0 270.93332 270.93334"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)"
sodipodi:docname="chiaki_macos.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.5946522"
inkscape:cx="616.32665"
inkscape:cy="519.63148"
inkscape:window-width="1920"
inkscape:window-height="978"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showguides="true"><sodipodi:guide
position="26.458333,219.96511"
orientation="-1,0"
id="guide1357"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="50.653599,244.475"
orientation="0,1"
id="guide1359"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="244.475,210.52655"
orientation="-1,0"
id="guide1361"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="67.733332,26.458333"
orientation="0,1"
id="guide1363"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="135.46666,253.78662"
orientation="-1,0"
id="guide4345"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient4465"><stop
style="stop-color:#f1ff7f;stop-opacity:1;"
offset="0"
id="stop4461" /><stop
style="stop-color:#b2d400;stop-opacity:1;"
offset="1"
id="stop4463" /></linearGradient><filter
x="-0.014563107"
y="-0.014563107"
width="1.0291262"
height="1.0412621"
filterUnits="objectBoundingBox"
id="filter-80aygx4sbj-3"><feOffset
dx="0"
dy="5"
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset424" /><feGaussianBlur
stdDeviation="2.5"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur426" /><feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
type="matrix"
in="shadowBlurOuter1"
id="feColorMatrix428" /></filter><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath869"><path
d="m -143.73827,56.831818 a 79.375,79.375 0 0 1 102.042535,2e-6 l -51.021268,60.80478 z"
sodipodi:end="5.4105207"
sodipodi:start="4.0142573"
sodipodi:ry="79.375"
sodipodi:rx="79.375"
sodipodi:cy="117.6366"
sodipodi:cx="-92.717003"
sodipodi:type="arc"
id="path871"
style="fill:#008080;fill-opacity:1;stroke:none;stroke-width:11.1206;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:arc-type="slice" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath964"><circle
style="display:inline;fill:#ff9955;fill-opacity:1;stroke:none;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle966"
cx="-135.46669"
cy="161.49431"
r="135.46667"
inkscape:label="circle"
transform="scale(-1,1)" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4387"><path
d="m 270.31599,96.939968 c 0,-3.20165 0,-6.403627 -0.0173,-9.605605 -0.0174,-2.697285 -0.0473,-5.393909 -0.12049,-8.089885 -0.15834,-5.876017 -0.50503,-11.802446 -1.55009,-17.613009 -1.05975,-5.894353 -2.79053,-11.380228 -5.51791,-16.735846 -2.68122,-5.26397 -6.18365,-10.080848 -10.3626,-14.256872 -4.17798,-4.176024 -8.99614,-7.676173 -14.26207,-10.355782 -5.36116,-2.728048 -10.85292,-4.458156 -16.75377,-5.517628 -5.81122,-1.043433 -11.73926,-1.38939 -17.61526,-1.54813 -2.69792,-0.07299 -5.39585,-0.103764 -8.09443,-0.120439 -3.2036,-0.01955 -6.40721,-0.01806 -9.61081,-0.01806 L 149.2133,12.945506 h -27.8204 l -36.538684,0.133205 c -3.209827,0 -6.419646,-0.0016 -9.629466,0.01806 -2.704145,0.01657 -5.406981,0.04745 -8.110144,0.120439 -5.889745,0.158737 -11.831203,0.505024 -17.656149,1.549765 -5.908728,1.059145 -11.408663,2.788599 -16.777022,5.514685 -5.277041,2.679934 -10.105685,6.18041 -14.292493,10.35709 -4.186156,4.175697 -7.695131,8.991593 -10.3812753,14.254581 -2.734911,5.35823 -4.4689412,10.84739 -5.5313527,16.74501 -1.0460477,5.808273 -1.3926574,11.732737 -1.55205319,17.606136 -0.0726642,2.696304 -0.10408515,5.392927 -0.12043909,8.089885 -0.0195464,3.202305 -0.18427009,7.179987 -0.18427009,10.381964 v 36.032494 28.11836 l 0.16625869,36.79805 c 0,3.20624 -0.001309,6.41247 0.0180605,9.6187 0.0163323,2.70089 0.0477729,5.40111 0.12078473,8.10101 0.15905935,5.88356 0.50633015,11.81849 1.55336045,17.63691 1.0620848,5.90221 2.7957884,11.39593 5.5284083,16.75842 2.6864707,5.27149 6.1960987,10.09461 10.3825837,14.27651 4.186482,4.18193 9.013815,7.68665 14.289876,10.3702 5.37163,2.73164 10.874184,4.46402 16.786519,5.52481 5.82232,1.04508 11.761815,1.39168 17.649275,1.55042 2.703163,0.073 5.406326,0.10416 8.110465,0.12049 3.20982,0.0198 6.419318,0.0198 9.629138,0.0198 h 36.868929 27.88948 36.79758 c 3.2036,0 6.40721,0 9.61081,-0.0198 2.69858,-0.0174 5.39651,-0.0475 8.09444,-0.12049 5.87828,-0.15908 11.8083,-0.506 17.62211,-1.55173 5.89727,-1.06076 11.38641,-2.79253 16.74462,-5.52253 5.26689,-2.68321 10.08605,-6.18859 14.26436,-10.37117 4.17829,-4.18126 7.68039,-9.00371 10.36162,-14.27421 2.72902,-5.36511 4.45979,-10.86145 5.52024,-16.7676 1.04409,-5.81612 1.39036,-11.74877 1.5491,-17.63003 0.073,-2.70023 0.10416,-5.40045 0.11999,-8.10101 0.0173,-3.20623 0.0173,-6.41246 0.0173,-9.6187 0,0 0,-36.14835 0,-36.79805 v -28.14782 c 0,-0.47982 0,-36.779393 0,-36.779393"
id="path4389"
style="fill:#cfff0d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.654602"
inkscape:label="clip" /></clipPath><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4465"
id="linearGradient4467"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.0000001,0,0,2.0000001,5.0529028e-6,-2.9497097e-5)" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4465"
id="linearGradient1573"
gradientUnits="userSpaceOnUse"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientTransform="matrix(1.9999999,0,0,1.9999999,-8.9032287e-4,7.677083e-6)" /></defs><g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"><path
d="m 417,128.31353 c 0,-4.89098 0,-9.78246 -0.0281,-14.67394 -0.0245,-4.12049 -0.072,-8.23997 -0.184,-12.35846 -0.242,-8.976466 -0.77149,-18.029933 -2.36798,-26.906401 C 412.80098,65.370262 410.157,56.989792 405.99053,48.808322 401.89456,40.766852 396.5441,33.408378 390.16015,27.028902 383.7777,20.649425 376.41725,15.302444 368.37281,11.208959 360.18287,7.0414744 351.79343,4.398484 342.779,2.7799899 333.90156,1.1859957 324.84563,0.65749761 315.8692,0.41499849 311.74773,0.3034989 307.62626,0.25649907 303.50379,0.23099916 298.60983,0.20099927 293.71586,0.20349926 288.8219,0.20349926 L 231.99832,0 h -42.49969 l -55.81808,0.20349926 c -4.90347,0 -9.80693,-0.0025 -14.71039,0.0274999 -4.13097,0.0254999 -8.25994,0.0724997 -12.38941,0.18399933 C 97.583315,0.65749761 88.506882,1.1864957 79.608448,2.7824899 70.582015,4.400484 62.180077,7.0424744 53.979137,11.206959 45.917697,15.300944 38.541252,20.648425 32.145299,27.028902 25.750346,33.407878 20.389886,40.764852 16.286417,48.804822 12.108447,56.990293 9.459467,65.375762 7.836479,74.385229 6.2384908,83.258197 5.7089948,92.308664 5.4654965,101.28113 5.3544974,105.40012 5.3064977,109.5196 5.2814979,113.63959 5.2514981,118.53157 5,124.60805 5,129.49953 v 55.0448 42.95484 l 0.2539981,56.2143 c 0,4.89798 -0.002,9.79596 0.0275,14.69394 0.025,4.12599 0.072999,8.25097 0.1844986,12.37546 0.2429983,8.98797 0.7734943,18.05443 2.3729825,26.9429 1.622488,9.01647 4.2709678,17.40894 8.4454378,25.60091 4.103969,8.05297 9.465429,15.42094 15.860882,21.80942 6.395453,6.38848 13.769898,11.74245 21.829839,15.84194 8.205939,4.17298 16.611876,6.81947 25.64381,8.43997 8.894434,1.59649 17.967867,2.12599 26.961802,2.36849 4.12947,0.1115 8.25894,0.159 12.38991,0.184 C 123.87412,412 128.77708,412 133.68055,412 h 56.32258 42.60518 56.21359 c 4.89396,0 9.78793,0 14.68189,-0.0295 4.12247,-0.025 8.24394,-0.0725 12.36541,-0.184 8.97993,-0.243 18.03887,-0.773 26.9203,-2.37049 9.00893,-1.62049 17.39437,-4.26598 25.57981,-8.43647 8.04594,-4.09898 15.40789,-9.45397 21.79084,-15.84344 6.38295,-6.38748 11.73291,-13.75445 15.82888,-21.80592 4.16897,-8.19597 6.81295,-16.59244 8.43294,-25.61491 1.59499,-8.88497 2.12398,-17.94793 2.36648,-26.9324 0.1115,-4.12499 0.159,-8.24997 0.1835,-12.37546 C 417,293.50943 417,288.61145 417,283.71347 c 0,0 0,-55.2218 0,-56.2143 v -42.99984 c 0,-0.733 0,-56.1858 0,-56.1858"
id="use436"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;filter:url(#filter-80aygx4sbj-3)"
transform="matrix(0.52916669,0,0,0.52916669,23.8125,26.458334)" /><path
d="m 244.475,94.357609 c 0,-2.588144 0,-5.176552 -0.014,-7.76496 -0.014,-2.180426 -0.0382,-4.360318 -0.0974,-6.539686 -0.128,-4.750046 -0.40826,-9.540837 -1.25306,-14.237969 -0.85668,-4.764864 -2.2558,-9.199528 -4.46056,-13.52889 -2.16744,-4.255278 -4.99872,-8.149136 -8.3769,-11.524941 -3.37738,-3.375806 -7.27228,-6.20525 -11.52914,-8.371386 -4.33384,-2.205294 -8.77326,-3.603876 -13.54338,-4.46033 -4.69766,-0.843488 -9.48976,-1.123152 -14.23978,-1.251474 -2.18094,-0.059 -4.3619,-0.08388 -6.54336,-0.09736 -2.58972,-0.0158 -5.17946,-0.0146 -7.76918,-0.0146 l -30.06997,-0.10768 h -22.48942 l -29.537067,0.10768 c -2.594752,0 -5.1895,-0.0013 -7.784248,0.0146 -2.185972,0.0134 -4.370884,0.03836 -6.556062,0.09736 -4.761142,0.12832 -9.564087,0.40825 -14.272841,1.252796 -4.776488,0.85619 -9.222514,2.254242 -13.562178,4.45795 -4.265844,2.1664 -8.169214,4.996108 -11.553737,8.372444 -3.383996,3.375541 -6.220574,7.268605 -8.391994,11.523089 -2.210842,4.331478 -3.612594,8.76879 -4.471424,13.536298 -0.845602,4.69528 -1.125794,9.484485 -1.254646,14.232413 -0.05874,2.179634 -0.08414,4.359524 -0.09736,6.539686 -0.0158,2.588674 -0.14896,5.804144 -0.14896,8.392552 v 29.127869 22.73027 l 0.1344,29.74674 c 0,2.59184 -0.0011,5.18368 0.0146,7.77554 0.0132,2.18334 0.03862,4.36614 0.09764,6.54868 0.12858,4.75614 0.409306,9.5538 1.255702,14.25728 0.858566,4.77122 2.260054,9.21222 4.469044,13.54714 2.171684,4.26136 5.00879,8.16026 8.393052,11.54082 3.384259,3.38058 7.286569,6.21372 11.551621,8.38304 4.34231,2.2082 8.790452,3.60862 13.56985,4.46614 4.706638,0.84482 9.507995,1.125 14.267285,1.25332 2.185178,0.059 4.370356,0.0842 6.556326,0.0974 2.594748,0.016 5.189232,0.016 7.783984,0.016 h 29.804033 22.54524 29.74635 c 2.58972,0 5.17944,0 7.76916,-0.016 2.18148,-0.014 4.36242,-0.0384 6.54338,-0.0974 4.75188,-0.1286 9.54556,-0.40904 14.24532,-1.25438 4.76722,-0.8575 9.20452,-2.25742 13.53598,-4.4643 4.25764,-2.16904 8.15334,-5.00272 11.531,-8.38382 3.37764,-3.38004 6.20866,-7.2784 8.3761,-11.53896 2.20608,-4.33704 3.6052,-8.78016 4.46244,-13.55456 0.84402,-4.70162 1.12394,-9.49744 1.25226,-14.25172 0.059,-2.18282 0.0842,-4.36562 0.097,-6.54868 0.014,-2.59186 0.014,-5.1837 0.014,-7.77554 0,0 0,-29.22154 0,-29.74674 v -22.75408 c 0,-0.38788 0,-29.731651 0,-29.731651"
id="use438"
style="display:inline;fill:url(#linearGradient1573);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.529166" /><path
id="path1446"
style="display:none;fill:url(#linearGradient4467);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.529166"
inkscape:label="bg_cut"
d="m 124.0896,26.458306 -29.537222,0.10748 c -2.59475,0 -5.188758,-0.0015 -7.783504,0.0144 -2.18597,0.0134 -4.37153,0.03918 -6.556706,0.09818 -4.761139,0.12832 -9.564283,0.408092 -14.273031,1.252638 -4.776484,0.856188 -9.222305,2.253902 -13.561965,4.457609 -4.26584,2.166398 -8.169296,4.996284 -11.553817,8.372616 -3.383992,3.375538 -6.219802,7.268332 -8.39122,11.522813 -2.210838,4.331472 -3.613248,8.76862 -4.472078,13.536124 -0.8456,4.695277 -1.125852,9.484801 -1.254704,14.232723 -0.05874,2.179632 -0.08394,4.358977 -0.09716,6.539137 -0.0158,2.588672 -0.14882,5.804882 -0.14882,8.393286 V 108.73021 H 244.47502 V 94.35796 h 0.001 c 0,-2.58814 -4.8e-4,-5.177528 -0.014,-7.765934 -0.014,-2.180424 -0.038,-4.359771 -0.0972,-6.539137 -0.128,-4.75004 -0.40784,-9.540762 -1.25264,-14.237891 -0.85668,-4.76486 -2.25596,-9.199532 -4.46072,-13.52889 -2.16744,-4.255275 -4.99856,-8.149077 -8.37674,-11.524879 -3.37738,-3.375802 -7.27216,-6.205448 -11.52902,-8.371582 -4.33384,-2.205293 -8.77324,-3.604257 -13.54336,-4.460711 -4.69766,-0.843486 -9.48993,-1.122248 -14.23996,-1.25057 -2.18094,-0.059 -4.36179,-0.0847 -6.54327,-0.09818 -2.58971,-0.0158 -5.18035,-0.0144 -7.77006,-0.0144 l -30.06949,-0.10748 z m -97.498969,149.491654 0.0032,0.63976 c 0,2.59184 -0.0012,5.18442 0.0144,7.77627 0.0132,2.18333 0.03916,4.36589 0.09818,6.54843 0.12858,4.75613 0.408308,9.55406 1.254704,14.25754 0.858566,4.7712 2.261024,9.21154 4.470012,13.54646 2.171682,4.26134 5.007994,8.16086 8.392252,11.5414 3.384257,3.38058 7.286703,6.21364 11.551751,8.38296 4.342306,2.2082 8.790839,3.60836 13.570231,4.46588 4.706634,0.84482 9.507544,1.12534 14.266831,1.25366 2.185176,0.059 4.370738,0.084 6.556706,0.0972 2.594746,0.016 5.188754,0.016 7.783504,0.016 h 29.804898 22.54437 29.74702 c 2.58972,0 5.17932,5e-4 7.76903,-0.016 2.18148,-0.014 4.36233,-0.0382 6.54327,-0.0972 4.75188,-0.1286 9.54537,-0.40936 14.24513,-1.2547 4.76722,-0.8575 9.20466,-2.25694 13.53612,-4.4638 4.25764,-2.16904 8.15342,-5.0029 11.53108,-8.384 3.37764,-3.38002 6.20828,-7.27878 8.37572,-11.53934 2.20608,-4.33704 3.60554,-8.78034 4.46278,-13.55472 0.84402,-4.70162 1.12432,-9.49706 1.25264,-14.25134 0.059,-2.1828 0.0834,-4.36536 0.0962,-6.54843 0.014,-2.59185 0.014,-5.18443 0.014,-7.77627 v -0.63976 z" /><g
id="g1005"
inkscape:label="main icon"
clip-path="url(#clipPath4387)"
style="display:inline"
transform="matrix(0.80837807,0,0,0.80837807,25.958398,15.993434)"><rect
inkscape:label="bg"
ry="1.0565645"
y="20.8298"
x="-4.0937502e-07"
height="270.93335"
width="270.93335"
id="rect873"
style="display:none;fill:#cfff0d;fill-opacity:1;stroke:none;stroke-width:8.46431;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><g
id="g1033"
inkscape:label="right (original)"
transform="matrix(-1,0,0,1,262.28035,14.266743)"
style="display:none;stroke:none"><path
inkscape:connector-curvature="0"
id="path1019"
d="M -8.6529992,183.6071 H 107.72321 l 19.09046,28.9079 V 100.45235 H -8.6529992 Z"
style="display:inline;fill:#162d50;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="cccccc"
inkscape:label="face" /><rect
style="fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.185662;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1021"
width="15.497028"
height="31.75"
x="92.382744"
y="131.06844"
inkscape:label="eye" /><path
sodipodi:type="star"
style="fill:#162d50;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
id="path1023"
sodipodi:sides="3"
sodipodi:cx="75.635689"
sodipodi:cy="87.601158"
sodipodi:r1="33.042126"
sodipodi:r2="16.521063"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 104.25101,104.12222 -28.615321,0 -28.615321,0 14.30766,-24.781593 14.307661,-24.781595 14.30766,24.781594 z"
inkscape:transform-center-y="-7.0654063"
transform="matrix(0.70280031,0,0,0.85532099,32.495272,20.355967)"
inkscape:label="ear" /><flowRoot
xml:space="preserve"
id="flowRoot1031"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
transform="matrix(0.26458333,0,0,0.26458333,-8.6529992,15.861276)"
inkscape:label="flowRoot4545"><flowRegion
id="flowRegion1027"
style="stroke:none"><rect
id="rect1025"
width="104.28571"
height="78.571426"
x="-374.28571"
y="54"
style="stroke:none" /></flowRegion><flowPara
id="flowPara1029" /></flowRoot></g><use
style="display:none"
inkscape:label="left"
transform="matrix(-1,0,0,1,270.93336,-5.3256301e-6)"
height="100%"
width="100%"
id="use4535"
xlink:href="#g4527"
y="0"
x="0" /><g
style="display:inline;stroke:none"
transform="matrix(-1,0,0,1,262.28035,14.266743)"
inkscape:label="face"
id="g4527"><path
style="display:inline;fill:#162d50;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 356.42773,228.50391 -38.0039,80.11132 -21.9375,46.24219 H -619.27414 V 669.14258 H 439.84766 L 512,778.40039 584.15234,669.14258 H 1613.2487 V 354.85742 H 727.51367 l -21.9375,-46.24219 -38.0039,-80.11132 -38.00586,80.11132 -21.9375,46.24219 H 512 416.37109 l -21.9375,-46.24219 z"
id="path4518"
inkscape:connector-curvature="0"
inkscape:label="shape"
transform="matrix(-0.26458333,0,0,0.26458333,262.28035,6.563066)"
sodipodi:nodetypes="ccccccccccccccccccc" /><rect
inkscape:label="eye right"
y="131.18182"
x="92.153267"
height="31.75"
width="15.875"
id="rect1043"
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.187912;stroke-miterlimit:4;stroke-dasharray:none" /><rect
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.187912;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1047"
width="15.875"
height="31.75"
x="145.59911"
y="131.18182"
inkscape:label="eye left" /></g><g
inkscape:label="dangerous_microwaves"
clip-path="url(#clipPath869)"
style="fill:none"
transform="translate(187.02207,-8.675551)"
id="g844"><circle
inkscape:label="path830"
r="58.208332"
style="fill:none;fill-opacity:1;stroke:#162d50;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path830"
cx="-92.71701"
cy="117.6366" /><circle
r="41.241978"
cy="117.6366"
cx="-92.71701"
id="circle840"
style="fill:none;fill-opacity:1;stroke:#162d50;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1024"
height="1024"
viewBox="0 0 270.93332 270.93334"
version="1.1"
id="svg5"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2"><linearGradient
id="linearGradient4465"><stop
style="stop-color:#f6ffbc;stop-opacity:1;"
offset="0"
id="stop4461" /><stop
style="stop-color:#b4d700;stop-opacity:1;"
offset="1"
id="stop4463" /></linearGradient><filter
x="-0.014563107"
y="-0.014563107"
width="1.0291262"
height="1.0412621"
filterUnits="objectBoundingBox"
id="filter-80aygx4sbj-3"><feOffset
dx="0"
dy="5"
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset424" /><feGaussianBlur
stdDeviation="2.5"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur426" /><feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
type="matrix"
in="shadowBlurOuter1"
id="feColorMatrix428" /></filter><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath964"><circle
style="display:inline;fill:#ff9955;fill-opacity:1;stroke:none;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle966"
cx="-135.46669"
cy="161.49431"
r="135.46667"
transform="scale(-1,1)" /></clipPath><linearGradient
xlink:href="#linearGradient4465"
id="linearGradient4467"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientUnits="userSpaceOnUse" /><linearGradient
xlink:href="#linearGradient4465-9"
id="linearGradient4467-7"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-7.288516e-4,6.5027792e-5)" /><linearGradient
id="linearGradient4465-9"><stop
style="stop-color:#f1ff7f;stop-opacity:1;"
offset="0"
id="stop4461-3" /><stop
style="stop-color:#b2d400;stop-opacity:1;"
offset="1"
id="stop4463-8" /></linearGradient></defs><g
id="layer1"
transform="matrix(2.0000001,0,0,2.0000001,4.2905177e-6,-3.0059484e-5)"><path
d="m 417,128.31353 c 0,-4.89098 0,-9.78246 -0.0281,-14.67394 -0.0245,-4.12049 -0.072,-8.23997 -0.184,-12.35846 -0.242,-8.976466 -0.77149,-18.029933 -2.36798,-26.906401 C 412.80098,65.370262 410.157,56.989792 405.99053,48.808322 401.89456,40.766852 396.5441,33.408378 390.16015,27.028902 383.7777,20.649425 376.41725,15.302444 368.37281,11.208959 360.18287,7.0414744 351.79343,4.398484 342.779,2.7799899 333.90156,1.1859957 324.84563,0.65749761 315.8692,0.41499849 311.74773,0.3034989 307.62626,0.25649907 303.50379,0.23099916 298.60983,0.20099927 293.71586,0.20349926 288.8219,0.20349926 L 231.99832,0 h -42.49969 l -55.81808,0.20349926 c -4.90347,0 -9.80693,-0.0025 -14.71039,0.0274999 -4.13097,0.0254999 -8.25994,0.0724997 -12.38941,0.18399933 C 97.583315,0.65749761 88.506882,1.1864957 79.608448,2.7824899 70.582015,4.400484 62.180077,7.0424744 53.979137,11.206959 45.917697,15.300944 38.541252,20.648425 32.145299,27.028902 25.750346,33.407878 20.389886,40.764852 16.286417,48.804822 12.108447,56.990293 9.459467,65.375762 7.836479,74.385229 6.2384908,83.258197 5.7089948,92.308664 5.4654965,101.28113 5.3544974,105.40012 5.3064977,109.5196 5.2814979,113.63959 5.2514981,118.53157 5,124.60805 5,129.49953 v 55.0448 42.95484 l 0.2539981,56.2143 c 0,4.89798 -0.002,9.79596 0.0275,14.69394 0.025,4.12599 0.072999,8.25097 0.1844986,12.37546 0.2429983,8.98797 0.7734943,18.05443 2.3729825,26.9429 1.622488,9.01647 4.2709678,17.40894 8.4454378,25.60091 4.103969,8.05297 9.465429,15.42094 15.860882,21.80942 6.395453,6.38848 13.769898,11.74245 21.829839,15.84194 8.205939,4.17298 16.611876,6.81947 25.64381,8.43997 8.894434,1.59649 17.967867,2.12599 26.961802,2.36849 4.12947,0.1115 8.25894,0.159 12.38991,0.184 C 123.87412,412 128.77708,412 133.68055,412 h 56.32258 42.60518 56.21359 c 4.89396,0 9.78793,0 14.68189,-0.0295 4.12247,-0.025 8.24394,-0.0725 12.36541,-0.184 8.97993,-0.243 18.03887,-0.773 26.9203,-2.37049 9.00893,-1.62049 17.39437,-4.26598 25.57981,-8.43647 8.04594,-4.09898 15.40789,-9.45397 21.79084,-15.84344 6.38295,-6.38748 11.73291,-13.75445 15.82888,-21.80592 4.16897,-8.19597 6.81295,-16.59244 8.43294,-25.61491 1.59499,-8.88497 2.12398,-17.94793 2.36648,-26.9324 0.1115,-4.12499 0.159,-8.24997 0.1835,-12.37546 C 417,293.50943 417,288.61145 417,283.71347 c 0,0 0,-55.2218 0,-56.2143 v -42.99984 c 0,-0.733 0,-56.1858 0,-56.1858"
id="use436"
style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;filter:url(#filter-80aygx4sbj-3)"
transform="matrix(0.26458333,0,0,0.26458333,11.906247,13.229181)" /><path
id="path1446-0"
style="display:inline;fill:url(#linearGradient4467-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264583"
d="m 62.044061,13.229232 -14.7686,0.05374 c -1.29738,0 -2.59438,-7.27e-4 -3.89175,0.0072 -1.09299,0.0067 -2.18577,0.01959 -3.27836,0.04909 -2.38057,0.06416 -4.78214,0.204046 -7.13651,0.626319 -2.38824,0.428094 -4.61115,1.126951 -6.78098,2.228804 -2.13292,1.083199 -4.08465,2.498142 -5.77691,4.186308 -1.692,1.687769 -3.1099,3.634166 -4.19561,5.761406 -1.10542,2.165736 -1.80663,4.38431 -2.23604,6.768062 -0.4228,2.347638 -0.56293,4.7424 -0.62735,7.116361 -0.0294,1.089816 -0.042,2.179488 -0.0486,3.269568 -0.008,1.294336 -0.0744,2.902441 -0.0744,4.196643 v 6.872449 H 122.23676 v -7.186125 h 5.2e-4 c 0,-1.29407 -2.4e-4,-2.588764 -0.007,-3.882967 -0.007,-1.090212 -0.019,-2.179885 -0.0486,-3.269568 -0.064,-2.37502 -0.20392,-4.770381 -0.62632,-7.118945 -0.42834,-2.38243 -1.12798,-4.599766 -2.23036,-6.764445 -1.08372,-2.127637 -2.49928,-4.074538 -4.18837,-5.762439 -1.68869,-1.687901 -3.63608,-3.102724 -5.76451,-4.185791 -2.16692,-1.102646 -4.38662,-1.802128 -6.77168,-2.230355 -2.34883,-0.421743 -4.744969,-0.561124 -7.119979,-0.625285 -1.09047,-0.0295 -2.1809,-0.04235 -3.27163,-0.04909 -1.29486,-0.0079 -2.59018,-0.0072 -3.88504,-0.0072 l -15.03474,-0.05374 z m -48.74947,74.745825 0.002,0.319877 c 0,1.295923 -6e-4,2.592212 0.007,3.888135 0.007,1.091667 0.0196,2.182948 0.0491,3.274218 0.0643,2.378065 0.20415,4.777033 0.62735,7.128773 0.42928,2.3856 1.13051,4.60577 2.235,6.77323 1.08584,2.13067 2.504,4.08043 4.19613,5.7707 1.69213,1.69029 3.64335,3.10682 5.77587,4.19148 2.17116,1.1041 4.39542,1.80418 6.78512,2.23294 2.35332,0.42241 4.75377,0.56267 7.13341,0.62683 1.09259,0.0295 2.18537,0.042 3.27836,0.0486 1.29737,0.008 2.59437,0.008 3.89175,0.008 h 14.90244 11.27219 14.87351 c 1.29485,0 2.58965,2.5e-4 3.88451,-0.008 1.09074,-0.007 2.18117,-0.0191 3.27164,-0.0486 2.37594,-0.0643 4.772679,-0.20468 7.122559,-0.62735 2.38361,-0.42875 4.60233,-1.12847 6.76806,-2.2319 2.12882,-1.08452 4.07671,-2.50145 5.76554,-4.192 1.68882,-1.69001 3.10414,-3.63939 4.18786,-5.76967 1.10304,-2.16852 1.80277,-4.39017 2.23139,-6.77736 0.42201,-2.35081 0.56216,-4.748534 0.62632,-7.125673 0.0295,-1.091402 0.0417,-2.182683 0.0481,-3.274218 0.007,-1.295923 0.007,-2.592212 0.007,-3.888135 v -0.319877 z" /><path
id="path4518"
style="display:inline;fill:#162d50;stroke:none;stroke-width:0.106942px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 51.096105,40.852287 -4.064351,8.567436 -2.345593,4.945434 H 13.229682 v 7.69152 11.365198 l 0.06563,14.553117 H 60.017007 L 67.733332,99.65955 75.449657,87.974992 H 122.2375 V 73.421875 62.044791 54.365157 H 90.780505 l -2.345594,-4.945434 -4.064351,-8.567436 -4.064351,8.567436 -2.346111,4.945434 H 67.733332 57.506567 l -2.34611,-4.945434 z" /><rect
y="66.785446"
x="-81.742691"
height="12.833001"
width="6.4165006"
id="rect1043"
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
transform="scale(-1,1)" /><rect
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1047"
width="6.4165006"
height="12.833001"
x="-60.140472"
y="66.785446"
transform="scale(-1,1)" /><path
id="path830"
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
d="m 51.095589,26.798881 c -6.169023,0 -11.826367,2.225125 -16.215031,5.913334 l 2.185913,2.605009 c 3.790164,-3.181711 8.681211,-5.09633 14.029118,-5.09633 5.348221,0 10.239895,1.9148 14.030152,5.096847 l 2.185913,-2.605009 C 62.922884,29.024147 57.264963,26.798881 51.095589,26.798881 Z" /><path
id="circle840"
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
d="m 51.095589,33.656344 c -4.49058,0 -8.610793,1.621713 -11.807548,4.308781 l 2.18643,2.605525 c 2.597877,-2.180752 5.951484,-3.492293 9.621118,-3.492293 3.669777,0 7.024322,1.311388 9.622669,3.492293 l 2.185913,-2.605009 C 59.707311,35.278198 55.58652,33.656344 51.095589,33.656344 Z" /></g></svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -15,3 +15,4 @@ endif()
add_executable(chiaki-cli src/main.c)
target_link_libraries(chiaki-cli chiaki-cli-lib)
install(TARGETS chiaki-cli)

View file

@ -142,13 +142,19 @@ CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[]
return 1;
}
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4); // TODO: IPv6, PS5, should probably use the service
ChiakiDiscoveryPacket packet;
memset(&packet, 0, sizeof(packet));
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS4;
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4);
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
if(err != CHIAKI_ERR_SUCCESS)
CHIAKI_LOGE(log, "Failed to send discovery packet for PS4: %s", chiaki_error_string(err));
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS5;
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS5);
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
if(err != CHIAKI_ERR_SUCCESS)
CHIAKI_LOGE(log, "Failed to send discovery packet for PS5: %s", chiaki_error_string(err));
while(1)
sleep(1); // TODO: wtf

View file

@ -11,10 +11,14 @@ static char doc[] = "Send a PS4 wakeup packet.";
#define ARG_KEY_HOST 'h'
#define ARG_KEY_REGISTKEY 'r'
#define ARG_KEY_PS4 '4'
#define ARG_KEY_PS5 '5'
static struct argp_option options[] = {
{ "host", ARG_KEY_HOST, "Host", 0, "Host to send wakeup packet to", 0 },
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "PS4 registration key", 0 },
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "Remote Play registration key (plaintext)", 0 },
{ "ps4", ARG_KEY_PS4, NULL, 0, "PlayStation 4", 0 },
{ "ps5", ARG_KEY_PS5, NULL, 0, "PlayStation 5 (default)", 0 },
{ 0 }
};
@ -22,6 +26,7 @@ typedef struct arguments
{
const char *host;
const char *registkey;
bool ps5;
} Arguments;
static int parse_opt(int key, char *arg, struct argp_state *state)
@ -39,6 +44,12 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
case ARGP_KEY_ARG:
argp_usage(state);
break;
case ARG_KEY_PS4:
arguments->ps5 = false;
break;
case ARG_KEY_PS5:
arguments->ps5 = true;
break;
default:
return ARGP_ERR_UNKNOWN;
}
@ -51,6 +62,7 @@ static struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
CHIAKI_EXPORT int chiaki_cli_cmd_wakeup(ChiakiLog *log, int argc, char *argv[])
{
Arguments arguments = { 0 };
arguments.ps5 = true;
error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
if(argp_r != 0)
return 1;
@ -73,5 +85,5 @@ CHIAKI_EXPORT int chiaki_cli_cmd_wakeup(ChiakiLog *log, int argc, char *argv[])
uint64_t credential = (uint64_t)strtoull(arguments.registkey, NULL, 16);
return chiaki_discovery_wakeup(log, NULL, arguments.host, credential, false);
return chiaki_discovery_wakeup(log, NULL, arguments.host, credential, arguments.ps5);
}

View file

@ -1,6 +1,26 @@
find_package(SDL2 NO_MODULE QUIET)
# Adapted from libsdl-org/SDL_ttf: https://github.com/libsdl-org/SDL_ttf/blob/main/cmake/FindPrivateSDL2.cmake#L19-L31
# Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
# Licensed under the zlib license (https://github.com/libsdl-org/SDL_ttf/blob/main/LICENSE.txt)
set(SDL2_VERSION_MAJOR)
set(SDL2_VERSION_MINOR)
set(SDL2_VERSION_PATCH)
set(SDL2_VERSION)
if(SDL2_INCLUDE_DIR)
file(READ "${SDL2_INCLUDE_DIR}/SDL_version.h" _sdl_version_h)
string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl2_major_re "${_sdl_version_h}")
set(SDL2_VERSION_MAJOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl2_minor_re "${_sdl_version_h}")
set(SDL2_VERSION_MINOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl2_patch_re "${_sdl_version_h}")
set(SDL2_VERSION_PATCH "${CMAKE_MATCH_1}")
if(_sdl2_major_re AND _sdl2_minor_re AND _sdl2_patch_re)
set(SDL2_VERSION "${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}")
endif()
endif()
if(SDL2_FOUND AND (NOT TARGET SDL2::SDL2))
add_library(SDL2::SDL2 UNKNOWN IMPORTED GLOBAL)
if(NOT SDL2_LIBDIR)

View file

@ -33,8 +33,8 @@ endif()
find_program(MAKE_EXE NAMES gmake make)
ExternalProject_Add(OpenSSL-ExternalProject
URL https://www.openssl.org/source/openssl-1.1.1d.tar.gz
URL_HASH SHA256=1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
URL https://www.openssl.org/source/openssl-1.1.1s.tar.gz
URL_HASH SHA256=c5ac01e760ee6ff0dab61d6b2bbd30146724d063eb322180c6f18a6f74e4b6aa
INSTALL_DIR "${OPENSSL_INSTALL_DIR}"
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ${OPENSSL_BUILD_ENV}
"<SOURCE_DIR>/Configure" "--prefix=<INSTALL_DIR>" no-shared ${OPENSSL_CONFIG_EXTRA_ARGS} "${OPENSSL_OS_COMPILER}"

View file

@ -1,34 +1,15 @@
# Find DEVKITPRO
set(DEVKITPRO "$ENV{DEVKITPRO}" CACHE PATH "Path to DevKitPro")
set(PORTLIBS_PREFIX "$ENV{PORTLIBS_PREFIX}" CACHE PATH "Path to portlibs inside DevKitPro")
if(NOT DEVKITPRO OR NOT PORTLIBS_PREFIX)
message(FATAL_ERROR "Please set DEVKITPRO & PORTLIBS_PREFIX env before calling cmake. https://devkitpro.org/wiki/Getting_Started")
if(NOT DEVKITPRO)
message(FATAL_ERROR "Please set DEVKITPRO env before calling cmake. https://devkitpro.org/wiki/Getting_Started")
endif()
# include devkitpro toolchain
include("${DEVKITPRO}/switch.cmake")
include("${DEVKITPRO}/cmake/Switch.cmake")
set(NSWITCH TRUE)
# Enable gcc -g, to use
# /opt/devkitpro/devkitA64/bin/aarch64-none-elf-addr2line -e build_switch/switch/chiaki -f -p -C -a 0xCCB5C
# set(CMAKE_BUILD_TYPE Debug)
# set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Shared libs not available" )
# FIXME rework this file to use the toolchain only
# https://github.com/diasurgical/devilutionX/pull/764
set(ARCH "-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -ftls-model=local-exec")
# set(CMAKE_C_FLAGS "-O2 -ffunction-sections ${ARCH}")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
# workaroud force -fPIE to avoid
# aarch64-none-elf/bin/ld: read-only segment has dynamic relocations
set(CMAKE_EXE_LINKER_FLAGS "-specs=${DEVKITPRO}/libnx/switch.specs ${ARCH} -fPIE -Wl,-Map,Output.map")
# add portlibs to the list of include dir
include_directories("${PORTLIBS_PREFIX}/include")
# troubleshoot
message(STATUS "CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
message(STATUS "PKG_CONFIG_EXECUTABLE = ${PKG_CONFIG_EXECUTABLE}")
@ -79,4 +60,3 @@ function(add_nro_target output_name target title author version icon romfs)
endfunction()
set(CMAKE_USE_SYSTEM_ENVIRONMENT_PATH OFF)
set(CMAKE_PREFIX_PATH "/")

View file

@ -6,9 +6,6 @@ find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Concurrent Multimedia Open
if(APPLE)
find_package(Qt5 REQUIRED COMPONENTS MacExtras)
endif()
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
find_package(SDL2 MODULE REQUIRED)
endif()
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
@ -70,12 +67,12 @@ if(CHIAKI_ENABLE_CLI)
endif()
target_link_libraries(chiaki Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Concurrent Qt5::Multimedia Qt5::OpenGL Qt5::Svg)
target_link_libraries(chiaki SDL2::SDL2)
if(APPLE)
target_link_libraries(chiaki Qt5::MacExtras)
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_QT_MACEXTRAS)
endif()
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
target_link_libraries(chiaki SDL2::SDL2)
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
endif()
if(CHIAKI_ENABLE_SETSU)

Binary file not shown.

View file

@ -3,6 +3,8 @@
#ifndef CHIAKI_AVOPENGLWIDGET_H
#define CHIAKI_AVOPENGLWIDGET_H
#include "transformmode.h"
#include <chiaki/log.h>
#include <QOpenGLWidget>
@ -74,21 +76,24 @@ class AVOpenGLWidget: public QOpenGLWidget
public:
static QSurfaceFormat CreateSurfaceFormat();
explicit AVOpenGLWidget(StreamSession *session, QWidget *parent = nullptr);
explicit AVOpenGLWidget(StreamSession *session, QWidget *parent = nullptr, TransformMode transform_mode = TransformMode::Fit);
~AVOpenGLWidget() override;
void SwapFrames();
AVOpenGLFrame *GetBackgroundFrame() { return &frames[1 - frame_fg]; }
void SetTransformMode(TransformMode mode) { transform_mode = mode; }
TransformMode GetTransformMode() const { return transform_mode; }
protected:
TransformMode transform_mode;
void mouseMoveEvent(QMouseEvent *event) override;
void initializeGL() override;
void paintGL() override;
private slots:
void ResetMouseTimeout();
public slots:
void ResetMouseTimeout();
void HideMouse();
};

View file

@ -12,8 +12,12 @@
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
#include <SDL.h>
#include <chiaki/orientation.h>
#endif
#define PS_TOUCHPAD_MAX_X 1920
#define PS_TOUCHPAD_MAX_Y 1079
class Controller;
class ControllerManager : public QObject
@ -33,7 +37,9 @@ class ControllerManager : public QObject
private slots:
void UpdateAvailableControllers();
void HandleEvents();
void ControllerEvent(int device_id);
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
void ControllerEvent(SDL_Event evt);
#endif
public:
static ControllerManager *GetInstance();
@ -57,12 +63,24 @@ class Controller : public QObject
private:
Controller(int device_id, ControllerManager *manager);
void UpdateState();
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
void UpdateState(SDL_Event event);
bool HandleButtonEvent(SDL_ControllerButtonEvent event);
bool HandleAxisEvent(SDL_ControllerAxisEvent event);
#if SDL_VERSION_ATLEAST(2, 0, 14)
bool HandleSensorEvent(SDL_ControllerSensorEvent event);
bool HandleTouchpadEvent(SDL_ControllerTouchpadEvent event);
#endif
#endif
ControllerManager *manager;
int id;
ChiakiOrientationTracker orientation_tracker;
ChiakiControllerState state;
bool is_dualsense;
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
QMap<QPair<Sint64, Sint64>, uint8_t> touch_ids;
SDL_GameController *controller;
#endif
@ -74,9 +92,43 @@ class Controller : public QObject
QString GetName();
ChiakiControllerState GetState();
void SetRumble(uint8_t left, uint8_t right);
void SetTriggerEffects(uint8_t type_left, const uint8_t *data_left, uint8_t type_right, const uint8_t *data_right);
bool IsDualSense();
signals:
void StateChanged();
};
/* PS5 trigger effect documentation:
https://controllers.fandom.com/wiki/Sony_DualSense#FFB_Trigger_Modes
Taken from SDL2, licensed under the zlib license,
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
https://github.com/libsdl-org/SDL/blob/release-2.24.1/test/testgamecontroller.c#L263-L289
*/
typedef struct
{
Uint8 ucEnableBits1; /* 0 */
Uint8 ucEnableBits2; /* 1 */
Uint8 ucRumbleRight; /* 2 */
Uint8 ucRumbleLeft; /* 3 */
Uint8 ucHeadphoneVolume; /* 4 */
Uint8 ucSpeakerVolume; /* 5 */
Uint8 ucMicrophoneVolume; /* 6 */
Uint8 ucAudioEnableBits; /* 7 */
Uint8 ucMicLightMode; /* 8 */
Uint8 ucAudioMuteBits; /* 9 */
Uint8 rgucRightTriggerEffect[11]; /* 10 */
Uint8 rgucLeftTriggerEffect[11]; /* 21 */
Uint8 rgucUnknown1[6]; /* 32 */
Uint8 ucLedFlags; /* 38 */
Uint8 rgucUnknown2[2]; /* 39 */
Uint8 ucLedAnim; /* 41 */
Uint8 ucLedBrightness; /* 42 */
Uint8 ucPadLights; /* 43 */
Uint8 ucLedRed; /* 44 */
Uint8 ucLedGreen; /* 45 */
Uint8 ucLedBlue; /* 46 */
} DS5EffectsState_t;
#endif // CHIAKI_CONTROLLERMANAGER_H

View file

@ -55,6 +55,7 @@ class MainWindow : public QMainWindow
void UpdateDiscoveryEnabled();
void ShowSettings();
void Quit();
void UpdateDisplayServers();
void UpdateServerWidgets();

View file

@ -63,6 +63,9 @@ class Settings : public QObject
void SetLogVerbose(bool enabled) { settings.setValue("settings/log_verbose", enabled); }
uint32_t GetLogLevelMask();
bool GetDualSenseEnabled() const { return settings.value("settings/dualsense_enabled", false).toBool(); }
void SetDualSenseEnabled(bool enabled) { settings.setValue("settings/dualsense_enabled", enabled); }
ChiakiVideoResolutionPreset GetResolution() const;
void SetResolution(ChiakiVideoResolutionPreset resolution);

View file

@ -20,6 +20,7 @@ class SettingsDialog : public QDialog
QCheckBox *log_verbose_check_box;
QComboBox *disconnect_action_combo_box;
QCheckBox *dualsense_check_box;
QComboBox *resolution_combo_box;
QComboBox *fps_combo_box;
@ -37,6 +38,7 @@ class SettingsDialog : public QDialog
private slots:
void LogVerboseChanged();
void DualSenseChanged();
void DisconnectActionSelected();
void ResolutionSelected();

View file

@ -20,6 +20,7 @@
#include "sessionlog.h"
#include "controllermanager.h"
#include "settings.h"
#include "transformmode.h"
#include <QObject>
#include <QImage>
@ -53,9 +54,18 @@ struct StreamSessionConnectInfo
ChiakiConnectVideoProfile video_profile;
unsigned int audio_buffer_size;
bool fullscreen;
TransformMode transform_mode;
bool enable_keyboard;
bool enable_dualsense;
StreamSessionConnectInfo(Settings *settings, ChiakiTarget target, QString host, QByteArray regist_key, QByteArray morning, bool fullscreen);
StreamSessionConnectInfo(
Settings *settings,
ChiakiTarget target,
QString host,
QByteArray regist_key,
QByteArray morning,
bool fullscreen,
TransformMode transform_mode);
};
class StreamSession : public QObject
@ -92,17 +102,23 @@ class StreamSession : public QObject
unsigned int audio_buffer_size;
QAudioOutput *audio_output;
QIODevice *audio_io;
SDL_AudioDeviceID haptics_output;
uint8_t *haptics_resampler_buf;
QMap<Qt::Key, int> key_map;
void PushAudioFrame(int16_t *buf, size_t samples_count);
void PushHapticsFrame(uint8_t *buf, size_t buf_size);
#if CHIAKI_GUI_ENABLE_SETSU
void HandleSetsuEvent(SetsuEvent *event);
#endif
private slots:
void InitAudio(unsigned int channels, unsigned int rate);
void InitHaptics();
void Event(ChiakiEvent *event);
void DisconnectHaptics();
void ConnectHaptics();
public:
explicit StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent = nullptr);
@ -124,7 +140,7 @@ class StreamSession : public QObject
#endif
void HandleKeyboardEvent(QKeyEvent *event);
void HandleMouseEvent(QMouseEvent *event);
bool HandleMouseEvent(QMouseEvent *event);
signals:
void FfmpegFrameAvailable();

View file

@ -22,10 +22,14 @@ class StreamWindow: public QMainWindow
const StreamSessionConnectInfo connect_info;
StreamSession *session;
QAction *fullscreen_action;
QAction *stretch_action;
QAction *zoom_action;
AVOpenGLWidget *av_widget;
void Init();
void UpdateVideoTransform();
void UpdateTransformModeActions();
protected:
void keyPressEvent(QKeyEvent *event) override;
@ -42,6 +46,9 @@ class StreamWindow: public QMainWindow
void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
void LoginPINRequested(bool incorrect);
void ToggleFullscreen();
void ToggleStretch();
void ToggleZoom();
void Quit();
};
#endif // CHIAKI_GUI_STREAMWINDOW_H

View file

@ -0,0 +1,12 @@
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
#ifndef CHIAKI_TRANSFORMMODE_H
#define CHIAKI_TRANSFORMMODE_H
enum class TransformMode {
Fit,
Zoom,
Stretch
};
#endif

102
gui/res/chiaki_macos.svg Normal file
View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1024"
height="1024"
viewBox="0 0 270.93332 270.93334"
version="1.1"
id="svg5"
xml:space="preserve"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2"><linearGradient
id="linearGradient4465"><stop
style="stop-color:#f6ffbc;stop-opacity:1;"
offset="0"
id="stop4461" /><stop
style="stop-color:#b4d700;stop-opacity:1;"
offset="1"
id="stop4463" /></linearGradient><filter
x="-0.014563107"
y="-0.014563107"
width="1.0291262"
height="1.0412621"
filterUnits="objectBoundingBox"
id="filter-80aygx4sbj-3"><feOffset
dx="0"
dy="5"
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset424" /><feGaussianBlur
stdDeviation="2.5"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur426" /><feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"
type="matrix"
in="shadowBlurOuter1"
id="feColorMatrix428" /></filter><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath964"><circle
style="display:inline;fill:#ff9955;fill-opacity:1;stroke:none;stroke-width:8.46667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle966"
cx="-135.46669"
cy="161.49431"
r="135.46667"
transform="scale(-1,1)" /></clipPath><linearGradient
xlink:href="#linearGradient4465"
id="linearGradient4467"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientUnits="userSpaceOnUse" /><linearGradient
xlink:href="#linearGradient4465-9"
id="linearGradient4467-7"
x1="67.73333"
y1="13.229165"
x2="67.73333"
y2="122.2375"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-7.288516e-4,6.5027792e-5)" /><linearGradient
id="linearGradient4465-9"><stop
style="stop-color:#f1ff7f;stop-opacity:1;"
offset="0"
id="stop4461-3" /><stop
style="stop-color:#b2d400;stop-opacity:1;"
offset="1"
id="stop4463-8" /></linearGradient></defs><g
id="layer1"
transform="matrix(2.0000001,0,0,2.0000001,4.2905177e-6,-3.0059484e-5)"><path
d="m 417,128.31353 c 0,-4.89098 0,-9.78246 -0.0281,-14.67394 -0.0245,-4.12049 -0.072,-8.23997 -0.184,-12.35846 -0.242,-8.976466 -0.77149,-18.029933 -2.36798,-26.906401 C 412.80098,65.370262 410.157,56.989792 405.99053,48.808322 401.89456,40.766852 396.5441,33.408378 390.16015,27.028902 383.7777,20.649425 376.41725,15.302444 368.37281,11.208959 360.18287,7.0414744 351.79343,4.398484 342.779,2.7799899 333.90156,1.1859957 324.84563,0.65749761 315.8692,0.41499849 311.74773,0.3034989 307.62626,0.25649907 303.50379,0.23099916 298.60983,0.20099927 293.71586,0.20349926 288.8219,0.20349926 L 231.99832,0 h -42.49969 l -55.81808,0.20349926 c -4.90347,0 -9.80693,-0.0025 -14.71039,0.0274999 -4.13097,0.0254999 -8.25994,0.0724997 -12.38941,0.18399933 C 97.583315,0.65749761 88.506882,1.1864957 79.608448,2.7824899 70.582015,4.400484 62.180077,7.0424744 53.979137,11.206959 45.917697,15.300944 38.541252,20.648425 32.145299,27.028902 25.750346,33.407878 20.389886,40.764852 16.286417,48.804822 12.108447,56.990293 9.459467,65.375762 7.836479,74.385229 6.2384908,83.258197 5.7089948,92.308664 5.4654965,101.28113 5.3544974,105.40012 5.3064977,109.5196 5.2814979,113.63959 5.2514981,118.53157 5,124.60805 5,129.49953 v 55.0448 42.95484 l 0.2539981,56.2143 c 0,4.89798 -0.002,9.79596 0.0275,14.69394 0.025,4.12599 0.072999,8.25097 0.1844986,12.37546 0.2429983,8.98797 0.7734943,18.05443 2.3729825,26.9429 1.622488,9.01647 4.2709678,17.40894 8.4454378,25.60091 4.103969,8.05297 9.465429,15.42094 15.860882,21.80942 6.395453,6.38848 13.769898,11.74245 21.829839,15.84194 8.205939,4.17298 16.611876,6.81947 25.64381,8.43997 8.894434,1.59649 17.967867,2.12599 26.961802,2.36849 4.12947,0.1115 8.25894,0.159 12.38991,0.184 C 123.87412,412 128.77708,412 133.68055,412 h 56.32258 42.60518 56.21359 c 4.89396,0 9.78793,0 14.68189,-0.0295 4.12247,-0.025 8.24394,-0.0725 12.36541,-0.184 8.97993,-0.243 18.03887,-0.773 26.9203,-2.37049 9.00893,-1.62049 17.39437,-4.26598 25.57981,-8.43647 8.04594,-4.09898 15.40789,-9.45397 21.79084,-15.84344 6.38295,-6.38748 11.73291,-13.75445 15.82888,-21.80592 4.16897,-8.19597 6.81295,-16.59244 8.43294,-25.61491 1.59499,-8.88497 2.12398,-17.94793 2.36648,-26.9324 0.1115,-4.12499 0.159,-8.24997 0.1835,-12.37546 C 417,293.50943 417,288.61145 417,283.71347 c 0,0 0,-55.2218 0,-56.2143 v -42.99984 c 0,-0.733 0,-56.1858 0,-56.1858"
id="use436"
style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;filter:url(#filter-80aygx4sbj-3)"
transform="matrix(0.26458333,0,0,0.26458333,11.906247,13.229181)" /><path
id="path1446-0"
style="display:inline;fill:url(#linearGradient4467-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264583"
d="m 62.044061,13.229232 -14.7686,0.05374 c -1.29738,0 -2.59438,-7.27e-4 -3.89175,0.0072 -1.09299,0.0067 -2.18577,0.01959 -3.27836,0.04909 -2.38057,0.06416 -4.78214,0.204046 -7.13651,0.626319 -2.38824,0.428094 -4.61115,1.126951 -6.78098,2.228804 -2.13292,1.083199 -4.08465,2.498142 -5.77691,4.186308 -1.692,1.687769 -3.1099,3.634166 -4.19561,5.761406 -1.10542,2.165736 -1.80663,4.38431 -2.23604,6.768062 -0.4228,2.347638 -0.56293,4.7424 -0.62735,7.116361 -0.0294,1.089816 -0.042,2.179488 -0.0486,3.269568 -0.008,1.294336 -0.0744,2.902441 -0.0744,4.196643 v 6.872449 H 122.23676 v -7.186125 h 5.2e-4 c 0,-1.29407 -2.4e-4,-2.588764 -0.007,-3.882967 -0.007,-1.090212 -0.019,-2.179885 -0.0486,-3.269568 -0.064,-2.37502 -0.20392,-4.770381 -0.62632,-7.118945 -0.42834,-2.38243 -1.12798,-4.599766 -2.23036,-6.764445 -1.08372,-2.127637 -2.49928,-4.074538 -4.18837,-5.762439 -1.68869,-1.687901 -3.63608,-3.102724 -5.76451,-4.185791 -2.16692,-1.102646 -4.38662,-1.802128 -6.77168,-2.230355 -2.34883,-0.421743 -4.744969,-0.561124 -7.119979,-0.625285 -1.09047,-0.0295 -2.1809,-0.04235 -3.27163,-0.04909 -1.29486,-0.0079 -2.59018,-0.0072 -3.88504,-0.0072 l -15.03474,-0.05374 z m -48.74947,74.745825 0.002,0.319877 c 0,1.295923 -6e-4,2.592212 0.007,3.888135 0.007,1.091667 0.0196,2.182948 0.0491,3.274218 0.0643,2.378065 0.20415,4.777033 0.62735,7.128773 0.42928,2.3856 1.13051,4.60577 2.235,6.77323 1.08584,2.13067 2.504,4.08043 4.19613,5.7707 1.69213,1.69029 3.64335,3.10682 5.77587,4.19148 2.17116,1.1041 4.39542,1.80418 6.78512,2.23294 2.35332,0.42241 4.75377,0.56267 7.13341,0.62683 1.09259,0.0295 2.18537,0.042 3.27836,0.0486 1.29737,0.008 2.59437,0.008 3.89175,0.008 h 14.90244 11.27219 14.87351 c 1.29485,0 2.58965,2.5e-4 3.88451,-0.008 1.09074,-0.007 2.18117,-0.0191 3.27164,-0.0486 2.37594,-0.0643 4.772679,-0.20468 7.122559,-0.62735 2.38361,-0.42875 4.60233,-1.12847 6.76806,-2.2319 2.12882,-1.08452 4.07671,-2.50145 5.76554,-4.192 1.68882,-1.69001 3.10414,-3.63939 4.18786,-5.76967 1.10304,-2.16852 1.80277,-4.39017 2.23139,-6.77736 0.42201,-2.35081 0.56216,-4.748534 0.62632,-7.125673 0.0295,-1.091402 0.0417,-2.182683 0.0481,-3.274218 0.007,-1.295923 0.007,-2.592212 0.007,-3.888135 v -0.319877 z" /><path
id="path4518"
style="display:inline;fill:#162d50;stroke:none;stroke-width:0.106942px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 51.096105,40.852287 -4.064351,8.567436 -2.345593,4.945434 H 13.229682 v 7.69152 11.365198 l 0.06563,14.553117 H 60.017007 L 67.733332,99.65955 75.449657,87.974992 H 122.2375 V 73.421875 62.044791 54.365157 H 90.780505 l -2.345594,-4.945434 -4.064351,-8.567436 -4.064351,8.567436 -2.346111,4.945434 H 67.733332 57.506567 l -2.34611,-4.945434 z" /><rect
y="66.785446"
x="-81.742691"
height="12.833001"
width="6.4165006"
id="rect1043"
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
transform="scale(-1,1)" /><rect
style="display:inline;fill:#ffaaee;fill-opacity:1;stroke:none;stroke-width:0.075952;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1047"
width="6.4165006"
height="12.833001"
x="-60.140472"
y="66.785446"
transform="scale(-1,1)" /><path
id="path830"
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
d="m 51.095589,26.798881 c -6.169023,0 -11.826367,2.225125 -16.215031,5.913334 l 2.185913,2.605009 c 3.790164,-3.181711 8.681211,-5.09633 14.029118,-5.09633 5.348221,0 10.239895,1.9148 14.030152,5.096847 l 2.185913,-2.605009 C 62.922884,29.024147 57.264963,26.798881 51.095589,26.798881 Z" /><path
id="circle840"
style="color:#000000;fill:#162d50;-inkscape-stroke:none"
d="m 51.095589,33.656344 c -4.49058,0 -8.610793,1.621713 -11.807548,4.308781 l 2.18643,2.605525 c 2.597877,-2.180752 5.951484,-3.492293 9.621118,-3.492293 3.669777,0 7.024322,1.311388 9.622669,3.492293 l 2.185913,-2.605009 C 59.707311,35.278198 55.58652,33.656344 51.095589,33.656344 Z" /></g></svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -5,6 +5,7 @@
<file>discover-24px.svg</file>
<file>discover-off-24px.svg</file>
<file>chiaki.svg</file>
<file>chiaki_macos.svg</file>
<file>console-ps4.svg</file>
<file>console-ps5.svg</file>
</qresource>

View file

@ -122,9 +122,9 @@ QSurfaceFormat AVOpenGLWidget::CreateSurfaceFormat()
return format;
}
AVOpenGLWidget::AVOpenGLWidget(StreamSession *session, QWidget *parent)
AVOpenGLWidget::AVOpenGLWidget(StreamSession *session, QWidget *parent, TransformMode transform_mode)
: QOpenGLWidget(parent),
session(session)
session(session), transform_mode(transform_mode)
{
enum AVPixelFormat pixel_format = chiaki_ffmpeg_decoder_get_pixel_format(session->GetFfmpegDecoder());
conversion_config = nullptr;
@ -381,10 +381,10 @@ void AVOpenGLWidget::paintGL()
vp_width = widget_width;
vp_height = widget_height;
}
else
else if(transform_mode == TransformMode::Fit)
{
float aspect = (float)frame->width / (float)frame->height;
if(aspect < (float)widget_width / (float)widget_height)
if(widget_height && aspect < (float)widget_width / (float)widget_height)
{
vp_height = widget_height;
vp_width = (GLsizei)(vp_height * aspect);
@ -395,6 +395,34 @@ void AVOpenGLWidget::paintGL()
vp_height = (GLsizei)(vp_width / aspect);
}
}
else if(transform_mode == TransformMode::Zoom)
{
float aspect = (float)frame->width / (float)frame->height;
if(widget_height && aspect < (float)widget_width / (float)widget_height)
{
vp_width = widget_width;
vp_height = (GLsizei)(vp_width / aspect);
}
else
{
vp_height = widget_height;
vp_width = (GLsizei)(vp_height * aspect);
}
}
else // transform_mode == TransformMode::Stretch
{
float aspect = (float)frame->width / (float)frame->height;
if(widget_height && aspect < (float)widget_width / (float)widget_height)
{
vp_height = widget_height;
vp_width = widget_width;
}
else
{
vp_width = widget_width;
vp_height = widget_height;
}
}
f->glViewport((widget_width - vp_width) / 2, (widget_height - vp_height) / 2, vp_width, vp_height);

View file

@ -68,6 +68,12 @@ static QSet<QString> chiaki_motion_controller_guids({
"030000008f0e00001431000000000000",
});
static QSet<QPair<int16_t, int16_t>> chiaki_dualsense_controller_ids({
// in format (vendor id, product id)
QPair<int16_t, int16_t>(0x054c, 0x0ce6), // DualSense controller
QPair<int16_t, int16_t>(0x054c, 0x0df2), // DualSense Edge controller
});
static ControllerManager *instance = nullptr;
#define UPDATE_INTERVAL_MS 4
@ -84,6 +90,15 @@ ControllerManager::ControllerManager(QObject *parent)
{
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
SDL_SetMainReady();
#ifdef SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
#endif
#ifdef SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
#endif
#ifdef SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
#endif
if(SDL_Init(SDL_INIT_GAMECONTROLLER) < 0)
{
const char *err = SDL_GetError();
@ -156,22 +171,51 @@ void ControllerManager::HandleEvents()
break;
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERBUTTONDOWN:
ControllerEvent(event.cbutton.which);
break;
case SDL_CONTROLLERAXISMOTION:
ControllerEvent(event.caxis.which);
#if not defined(CHIAKI_ENABLE_SETSU) and SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLERSENSORUPDATE:
case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP:
#endif
ControllerEvent(event);
break;
}
}
#endif
}
void ControllerManager::ControllerEvent(int device_id)
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
void ControllerManager::ControllerEvent(SDL_Event event)
{
int device_id;
switch(event.type)
{
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
device_id = event.cbutton.which;
break;
case SDL_CONTROLLERAXISMOTION:
device_id = event.caxis.which;
break;
#if SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLERSENSORUPDATE:
device_id = event.csensor.which;
break;
case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP:
device_id = event.ctouchpad.which;
break;
#endif
default:
return;
}
if(!open_controllers.contains(device_id))
return;
open_controllers[device_id]->UpdateState();
open_controllers[device_id]->UpdateState(event);
}
#endif
QSet<int> ControllerManager::GetAvailableControllers()
{
@ -196,10 +240,13 @@ void ControllerManager::ControllerClosed(Controller *controller)
open_controllers.remove(controller->GetDeviceID());
}
Controller::Controller(int device_id, ControllerManager *manager) : QObject(manager)
Controller::Controller(int device_id, ControllerManager *manager)
: QObject(manager), is_dualsense(false)
{
this->id = device_id;
this->manager = manager;
chiaki_orientation_tracker_init(&this->orientation_tracker);
chiaki_controller_state_set_idle(&this->state);
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
controller = nullptr;
@ -208,6 +255,14 @@ Controller::Controller(int device_id, ControllerManager *manager) : QObject(mana
if(SDL_JoystickGetDeviceInstanceID(i) == device_id)
{
controller = SDL_GameControllerOpen(i);
#if SDL_VERSION_ATLEAST(2, 0, 14)
if(SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL))
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
if(SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO))
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
#endif
auto controller_id = QPair<int16_t, int16_t>(SDL_GameControllerGetVendor(controller), SDL_GameControllerGetProduct(controller));
is_dualsense = chiaki_dualsense_controller_ids.contains(controller_id);
break;
}
}
@ -218,16 +273,197 @@ Controller::~Controller()
{
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(controller)
{
// Clear trigger effects, SDL doesn't do it automatically
const uint8_t clear_effect[10] = { 0 };
this->SetTriggerEffects(0x05, clear_effect, 0x05, clear_effect);
SDL_GameControllerClose(controller);
}
#endif
manager->ControllerClosed(this);
}
void Controller::UpdateState()
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
void Controller::UpdateState(SDL_Event event)
{
switch(event.type)
{
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
if(!HandleButtonEvent(event.cbutton))
return;
break;
case SDL_CONTROLLERAXISMOTION:
if(!HandleAxisEvent(event.caxis))
return;
break;
#if SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLERSENSORUPDATE:
if(!HandleSensorEvent(event.csensor))
return;
break;
case SDL_CONTROLLERTOUCHPADDOWN:
case SDL_CONTROLLERTOUCHPADMOTION:
case SDL_CONTROLLERTOUCHPADUP:
if(!HandleTouchpadEvent(event.ctouchpad))
return;
break;
#endif
default:
return;
}
emit StateChanged();
}
inline bool Controller::HandleButtonEvent(SDL_ControllerButtonEvent event) {
ChiakiControllerButton ps_btn;
switch(event.button)
{
case SDL_CONTROLLER_BUTTON_A:
ps_btn = CHIAKI_CONTROLLER_BUTTON_CROSS;
break;
case SDL_CONTROLLER_BUTTON_B:
ps_btn = CHIAKI_CONTROLLER_BUTTON_MOON;
break;
case SDL_CONTROLLER_BUTTON_X:
ps_btn = CHIAKI_CONTROLLER_BUTTON_BOX;
break;
case SDL_CONTROLLER_BUTTON_Y:
ps_btn = CHIAKI_CONTROLLER_BUTTON_PYRAMID;
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
ps_btn = CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT;
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
ps_btn = CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT;
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
ps_btn = CHIAKI_CONTROLLER_BUTTON_DPAD_UP;
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
ps_btn = CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN;
break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
ps_btn = CHIAKI_CONTROLLER_BUTTON_L1;
break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
ps_btn = CHIAKI_CONTROLLER_BUTTON_R1;
break;
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
ps_btn = CHIAKI_CONTROLLER_BUTTON_L3;
break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
ps_btn = CHIAKI_CONTROLLER_BUTTON_R3;
break;
case SDL_CONTROLLER_BUTTON_START:
ps_btn = CHIAKI_CONTROLLER_BUTTON_OPTIONS;
break;
case SDL_CONTROLLER_BUTTON_BACK:
ps_btn = CHIAKI_CONTROLLER_BUTTON_SHARE;
break;
case SDL_CONTROLLER_BUTTON_GUIDE:
ps_btn = CHIAKI_CONTROLLER_BUTTON_PS;
break;
#if SDL_VERSION_ATLEAST(2, 0, 14)
case SDL_CONTROLLER_BUTTON_TOUCHPAD:
ps_btn = CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
break;
#endif
default:
return false;
}
if(event.type == SDL_CONTROLLERBUTTONDOWN)
state.buttons |= ps_btn;
else
state.buttons &= ~ps_btn;
return true;
}
inline bool Controller::HandleAxisEvent(SDL_ControllerAxisEvent event) {
switch(event.axis)
{
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
state.l2_state = (uint8_t)(event.value >> 7);
break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
state.r2_state = (uint8_t)(event.value >> 7);
break;
case SDL_CONTROLLER_AXIS_LEFTX:
state.left_x = event.value;
break;
case SDL_CONTROLLER_AXIS_LEFTY:
state.left_y = event.value;
break;
case SDL_CONTROLLER_AXIS_RIGHTX:
state.right_x = event.value;
break;
case SDL_CONTROLLER_AXIS_RIGHTY:
state.right_y = event.value;
break;
default:
return false;
}
return true;
}
#if SDL_VERSION_ATLEAST(2, 0, 14)
inline bool Controller::HandleSensorEvent(SDL_ControllerSensorEvent event)
{
switch(event.sensor)
{
case SDL_SENSOR_ACCEL:
state.accel_x = event.data[0] / SDL_STANDARD_GRAVITY;
state.accel_y = event.data[1] / SDL_STANDARD_GRAVITY;
state.accel_z = event.data[2] / SDL_STANDARD_GRAVITY;
break;
case SDL_SENSOR_GYRO:
state.gyro_x = event.data[0];
state.gyro_y = event.data[1];
state.gyro_z = event.data[2];
break;
default:
return false;
}
chiaki_orientation_tracker_update(
&orientation_tracker, state.gyro_x, state.gyro_y, state.gyro_z,
state.accel_x, state.accel_y, state.accel_z, event.timestamp * 1000);
chiaki_orientation_tracker_apply_to_controller_state(&orientation_tracker, &state);
return true;
}
inline bool Controller::HandleTouchpadEvent(SDL_ControllerTouchpadEvent event)
{
auto key = qMakePair(event.touchpad, event.finger);
bool exists = touch_ids.contains(key);
uint8_t chiaki_id;
switch(event.type)
{
case SDL_CONTROLLERTOUCHPADDOWN:
if(touch_ids.size() >= CHIAKI_CONTROLLER_TOUCHES_MAX)
return false;
chiaki_id = chiaki_controller_state_start_touch(&state, event.x * PS_TOUCHPAD_MAX_X, event.y * PS_TOUCHPAD_MAX_Y);
touch_ids.insert(key, chiaki_id);
break;
case SDL_CONTROLLERTOUCHPADMOTION:
if(!exists)
return false;
chiaki_controller_state_set_touch_pos(&state, touch_ids[key], event.x * PS_TOUCHPAD_MAX_X, event.y * PS_TOUCHPAD_MAX_Y);
break;
case SDL_CONTROLLERTOUCHPADUP:
if(!exists)
return false;
chiaki_controller_state_stop_touch(&state, touch_ids[key]);
touch_ids.remove(key);
break;
default:
return false;
}
return true;
}
#endif
#endif
bool Controller::IsConnected()
{
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
@ -263,35 +499,6 @@ QString Controller::GetName()
ChiakiControllerState Controller::GetState()
{
ChiakiControllerState state;
chiaki_controller_state_set_idle(&state);
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(!controller)
return state;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_A) ? CHIAKI_CONTROLLER_BUTTON_CROSS : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_B) ? CHIAKI_CONTROLLER_BUTTON_MOON : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X) ? CHIAKI_CONTROLLER_BUTTON_BOX : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_Y) ? CHIAKI_CONTROLLER_BUTTON_PYRAMID : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT) ? CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) ? CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_UP) ? CHIAKI_CONTROLLER_BUTTON_DPAD_UP : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN) ? CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSHOULDER) ? CHIAKI_CONTROLLER_BUTTON_L1 : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) ? CHIAKI_CONTROLLER_BUTTON_R1 : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_LEFTSTICK) ? CHIAKI_CONTROLLER_BUTTON_L3 : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_RIGHTSTICK) ? CHIAKI_CONTROLLER_BUTTON_R3 : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_START) ? CHIAKI_CONTROLLER_BUTTON_OPTIONS : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_BACK) ? CHIAKI_CONTROLLER_BUTTON_SHARE : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_GUIDE) ? CHIAKI_CONTROLLER_BUTTON_PS : 0;
state.l2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7);
state.r2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7);
state.left_x = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
state.left_y = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
state.right_x = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
state.right_y = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
#endif
return state;
}
@ -303,3 +510,28 @@ void Controller::SetRumble(uint8_t left, uint8_t right)
SDL_GameControllerRumble(controller, (uint16_t)left << 8, (uint16_t)right << 8, 5000);
#endif
}
void Controller::SetTriggerEffects(uint8_t type_left, const uint8_t *data_left, uint8_t type_right, const uint8_t *data_right)
{
#if defined(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER) && SDL_VERSION_ATLEAST(2, 0, 16)
if(!is_dualsense || !controller)
return;
DS5EffectsState_t state;
SDL_zero(state);
state.ucEnableBits1 |= (0x04 /* left trigger */ | 0x08 /* right trigger */);
state.rgucLeftTriggerEffect[0] = type_left;
SDL_memcpy(state.rgucLeftTriggerEffect + 1, data_left, 10);
state.rgucRightTriggerEffect[0] = type_right;
SDL_memcpy(state.rgucRightTriggerEffect + 1, data_right, 10);
SDL_GameControllerSendEffect(controller, &state, sizeof(state));
#endif
}
bool Controller::IsDualSense()
{
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(!controller)
return false;
return is_dualsense;
#endif
}

View file

@ -71,7 +71,11 @@ int real_main(int argc, char *argv[])
QApplication app(argc, argv);
#ifdef Q_OS_MACOS
QApplication::setWindowIcon(QIcon(":/icons/chiaki_macos.svg"));
#else
QApplication::setWindowIcon(QIcon(":/icons/chiaki.svg"));
#endif
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
@ -99,9 +103,15 @@ int real_main(int argc, char *argv[])
QCommandLineOption morning_option("morning", "", "morning");
parser.addOption(morning_option);
QCommandLineOption fullscreen_option("fullscreen", "Start window in fullscreen (only for use with stream command)");
QCommandLineOption fullscreen_option("fullscreen", "Start window in fullscreen mode [maintains aspect ratio, adds black bars to fill unsused parts of screen if applicable] (only for use with stream command)");
parser.addOption(fullscreen_option);
QCommandLineOption zoom_option("zoom", "Start window in fullscreen zoomed in to fit screen [maintains aspect ratio, cutting off edges of image to fill screen] (only for use with stream command)");
parser.addOption(zoom_option);
QCommandLineOption stretch_option("stretch", "Start window in fullscreen stretched to fit screen [distorts aspect ratio to fill screen] (only for use with stream command)");
parser.addOption(stretch_option);
parser.process(app);
QStringList args = parser.positionalArguments();
@ -129,15 +139,21 @@ int real_main(int argc, char *argv[])
{
if(args.length() < 3)
parser.showHelp(1);
bool found = false;
for(const auto &temphost : settings.GetRegisteredHosts())
{
if(temphost.GetServerNickname() == args[1])
{
found = true;
morning = temphost.GetRPKey();
regist_key = temphost.GetRPRegistKey();
target = temphost.GetTarget();
break;
}
}
if(!found)
{
printf("No configuration found for '%s'\n", args[1].toLocal8Bit().constData());
return 1;
}
@ -164,7 +180,21 @@ int real_main(int argc, char *argv[])
return 1;
}
}
StreamSessionConnectInfo connect_info(&settings, target, host, regist_key, morning, parser.isSet(fullscreen_option));
if ((parser.isSet(stretch_option) && (parser.isSet(zoom_option) || parser.isSet(fullscreen_option))) || (parser.isSet(zoom_option) && parser.isSet(fullscreen_option)))
{
printf("Must choose between fullscreen, zoom or stretch option.");
return 1;
}
StreamSessionConnectInfo connect_info(
&settings,
target,
host,
regist_key,
morning,
parser.isSet(fullscreen_option),
parser.isSet(zoom_option) ? TransformMode::Zoom : parser.isSet(stretch_option) ? TransformMode::Stretch : TransformMode::Fit);
return RunStream(app, connect_info);
}
#ifdef CHIAKI_ENABLE_CLI

View file

@ -146,6 +146,11 @@ MainWindow::MainWindow(Settings *settings, QWidget *parent)
AddToolBarAction(settings_action);
connect(settings_action, &QAction::triggered, this, &MainWindow::ShowSettings);
auto quit_action = new QAction(tr("Quit"), this);
quit_action->setShortcut(Qt::CTRL + Qt::Key_Q);
addAction(quit_action);
connect(quit_action, &QAction::triggered, this, &MainWindow::Quit);
auto scroll_area = new QScrollArea(this);
scroll_area->setWidgetResizable(true);
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -249,7 +254,14 @@ void MainWindow::ServerItemWidgetTriggered()
}
QString host = server.GetHostAddr();
StreamSessionConnectInfo info(settings, server.registered_host.GetTarget(), host, server.registered_host.GetRPRegistKey(), server.registered_host.GetRPKey(), false);
StreamSessionConnectInfo info(
settings,
server.registered_host.GetTarget(),
host,
server.registered_host.GetRPRegistKey(),
server.registered_host.GetRPKey(),
false,
TransformMode::Fit);
new StreamWindow(info);
}
else
@ -298,6 +310,11 @@ void MainWindow::ShowSettings()
dialog.exec();
}
void MainWindow::Quit()
{
qApp->exit();
}
void MainWindow::UpdateDisplayServers()
{
display_servers.clear();

View file

@ -69,6 +69,11 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
log_verbose_check_box->setChecked(settings->GetLogVerbose());
connect(log_verbose_check_box, &QCheckBox::stateChanged, this, &SettingsDialog::LogVerboseChanged);
dualsense_check_box = new QCheckBox(this);
general_layout->addRow(tr("Extended DualSense Support:\nEnable haptics and adaptive triggers\nfor attached DualSense controllers.\nThis is currently experimental."), dualsense_check_box);
dualsense_check_box->setChecked(settings->GetDualSenseEnabled());
connect(dualsense_check_box, &QCheckBox::stateChanged, this, &SettingsDialog::DualSenseChanged);
auto log_directory_label = new QLineEdit(GetLogBaseDir(), this);
log_directory_label->setReadOnly(true);
general_layout->addRow(tr("Log Directory:"), log_directory_label);
@ -322,6 +327,11 @@ void SettingsDialog::LogVerboseChanged()
settings->SetLogVerbose(log_verbose_check_box->isChecked());
}
void SettingsDialog::DualSenseChanged()
{
settings->SetDualSenseEnabled(dualsense_check_box->isChecked());
}
void SettingsDialog::FPSSelected()
{
settings->SetFPS((ChiakiVideoFPSPreset)fps_combo_box->currentData().toInt());

View file

@ -14,7 +14,20 @@
#define SETSU_UPDATE_INTERVAL_MS 4
StreamSessionConnectInfo::StreamSessionConnectInfo(Settings *settings, ChiakiTarget target, QString host, QByteArray regist_key, QByteArray morning, bool fullscreen)
#ifdef Q_OS_LINUX
#define DUALSENSE_AUDIO_DEVICE_NEEDLE "DualSense"
#else
#define DUALSENSE_AUDIO_DEVICE_NEEDLE "Wireless Controller"
#endif
StreamSessionConnectInfo::StreamSessionConnectInfo(
Settings *settings,
ChiakiTarget target,
QString host,
QByteArray regist_key,
QByteArray morning,
bool fullscreen,
TransformMode transform_mode)
: settings(settings)
{
key_map = settings->GetControllerMappingForDecoding();
@ -30,11 +43,14 @@ StreamSessionConnectInfo::StreamSessionConnectInfo(Settings *settings, ChiakiTar
this->morning = morning;
audio_buffer_size = settings->GetAudioBufferSize();
this->fullscreen = fullscreen;
this->transform_mode = transform_mode;
this->enable_keyboard = false; // TODO: from settings
this->enable_dualsense = settings->GetDualSenseEnabled();
}
static void AudioSettingsCb(uint32_t channels, uint32_t rate, void *user);
static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user);
static void HapticsFrameCb(uint8_t *buf, size_t buf_size, void *user);
static void EventCb(ChiakiEvent *event, void *user);
#if CHIAKI_GUI_ENABLE_SETSU
static void SessionSetsuCb(SetsuEvent *event, void *user);
@ -49,7 +65,9 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
pi_decoder(nullptr),
#endif
audio_output(nullptr),
audio_io(nullptr)
audio_io(nullptr),
haptics_output(0),
haptics_resampler_buf(nullptr)
{
connected = false;
ChiakiErrorCode err;
@ -108,6 +126,7 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
chiaki_connect_info.video_profile = connect_info.video_profile;
chiaki_connect_info.video_profile_auto_downgrade = true;
chiaki_connect_info.enable_keyboard = false;
chiaki_connect_info.enable_dualsense = connect_info.enable_dualsense;
#if CHIAKI_LIB_ENABLE_PI_DECODER
if(connect_info.decoder == Decoder::Pi && chiaki_connect_info.video_profile.codec != CHIAKI_CODEC_H264)
@ -136,6 +155,14 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
chiaki_opus_decoder_get_sink(&opus_decoder, &audio_sink);
chiaki_session_set_audio_sink(&session, &audio_sink);
if(connect_info.enable_dualsense)
{
ChiakiAudioSink haptics_sink;
haptics_sink.user = this;
haptics_sink.frame_cb = HapticsFrameCb;
chiaki_session_set_haptics_sink(&session, &haptics_sink);
}
#if CHIAKI_LIB_ENABLE_PI_DECODER
if(pi_decoder)
chiaki_session_set_video_sample_cb(&session, chiaki_pi_decoder_video_sample_cb, pi_decoder);
@ -173,6 +200,10 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
#endif
key_map = connect_info.key_map;
if(connect_info.enable_dualsense)
{
InitHaptics();
}
UpdateGamepads();
}
@ -200,6 +231,16 @@ StreamSession::~StreamSession()
chiaki_ffmpeg_decoder_fini(ffmpeg_decoder);
delete ffmpeg_decoder;
}
if(haptics_output > 0)
{
SDL_CloseAudioDevice(haptics_output);
haptics_output = 0;
}
if(haptics_resampler_buf)
{
free(haptics_resampler_buf);
haptics_resampler_buf = nullptr;
}
}
void StreamSession::Start()
@ -228,13 +269,16 @@ void StreamSession::SetLoginPIN(const QString &pin)
chiaki_session_set_login_pin(&session, (const uint8_t *)data.constData(), data.size());
}
void StreamSession::HandleMouseEvent(QMouseEvent *event)
bool StreamSession::HandleMouseEvent(QMouseEvent *event)
{
if(event->button() != Qt::MouseButton::LeftButton)
return false;
if(event->type() == QEvent::MouseButtonPress)
keyboard_state.buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
else
keyboard_state.buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
SendFeedbackState();
return true;
}
void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
@ -301,6 +345,8 @@ void StreamSession::UpdateGamepads()
{
CHIAKI_LOGI(log.GetChiakiLog(), "Controller %d disconnected", controller->GetDeviceID());
controllers.remove(controller_id);
if(controller->IsDualSense())
DisconnectHaptics();
delete controller;
}
}
@ -319,6 +365,11 @@ void StreamSession::UpdateGamepads()
CHIAKI_LOGI(log.GetChiakiLog(), "Controller %d opened: \"%s\"", controller_id, controller->GetName().toLocal8Bit().constData());
connect(controller, &Controller::StateChanged, this, &StreamSession::SendFeedbackState);
controllers[controller_id] = controller;
if(controller->IsDualSense())
{
// Connect haptics audio device with a delay to give the sound system time to set up
QTimer::singleShot(1000, this, &StreamSession::ConnectHaptics);
}
}
}
@ -377,6 +428,82 @@ void StreamSession::InitAudio(unsigned int channels, unsigned int rate)
channels, rate, audio_output->bufferSize());
}
void StreamSession::InitHaptics()
{
haptics_output = 0;
haptics_resampler_buf = nullptr;
#ifdef Q_OS_LINUX
// Haptics work most reliably with Pipewire, so try to use that if available
SDL_SetHint("SDL_AUDIODRIVER", "pipewire");
#endif
if(SDL_Init(SDL_INIT_AUDIO) < 0)
{
CHIAKI_LOGE(log.GetChiakiLog(), "Could not initialize SDL Audio for haptics output: %s", SDL_GetError());
return;
}
#ifdef Q_OS_LINUX
if(!strstr(SDL_GetCurrentAudioDriver(), "pipewire"))
{
CHIAKI_LOGW(
log.GetChiakiLog(),
"Haptics output is not using Pipewire, this may not work reliably. (was: '%s')",
SDL_GetCurrentAudioDriver());
}
#endif
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16LSB, 4, 3000, AUDIO_S16LSB, 4, 48000);
cvt.len = 240; // 10 16bit stereo samples
haptics_resampler_buf = (uint8_t*) calloc(cvt.len * cvt.len_mult, sizeof(uint8_t));
}
void StreamSession::DisconnectHaptics()
{
if(this->haptics_output > 0)
{
SDL_CloseAudioDevice(haptics_output);
this->haptics_output = 0;
}
}
void StreamSession::ConnectHaptics()
{
if(this->haptics_output > 0)
{
CHIAKI_LOGW(this->log.GetChiakiLog(), "Haptics already connected to an attached DualSense controller, ignoring additional controllers.");
return;
}
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 48000;
want.format = AUDIO_S16LSB;
want.channels = 4;
want.samples = 480; // 10ms buffer
want.callback = NULL;
const char *device_name = nullptr;
for(int i=0; i < SDL_GetNumAudioDevices(0); i++)
{
device_name = SDL_GetAudioDeviceName(i, 0);
if(!device_name || !strstr(device_name, DUALSENSE_AUDIO_DEVICE_NEEDLE))
continue;
haptics_output = SDL_OpenAudioDevice(device_name, 0, &want, &have, 0);
if(haptics_output == 0)
{
CHIAKI_LOGE(log.GetChiakiLog(), "Could not open SDL Audio Device %s for haptics output: %s", device_name, SDL_GetError());
continue;
}
SDL_PauseAudioDevice(haptics_output, 0);
CHIAKI_LOGI(log.GetChiakiLog(), "Haptics Audio Device '%s' opened with %d channels @ %d Hz, buffer size %u (driver=%s)", device_name, have.channels, have.freq, have.size, SDL_GetCurrentAudioDriver());
return;
}
CHIAKI_LOGW(log.GetChiakiLog(), "DualSense features were enabled and a DualSense is connected, but could not find the DualSense audio device!");
return;
}
void StreamSession::PushAudioFrame(int16_t *buf, size_t samples_count)
{
if(!audio_io)
@ -384,6 +511,35 @@ void StreamSession::PushAudioFrame(int16_t *buf, size_t samples_count)
audio_io->write((const char *)buf, static_cast<qint64>(samples_count * 2 * 2));
}
void StreamSession::PushHapticsFrame(uint8_t *buf, size_t buf_size)
{
if(haptics_output == 0)
return;
SDL_AudioCVT cvt;
// Haptics samples are coming in at 3KHZ, but the DualSense expects 48KHZ
SDL_BuildAudioCVT(&cvt, AUDIO_S16LSB, 4, 3000, AUDIO_S16LSB, 4, 48000);
cvt.len = buf_size * 2;
cvt.buf = haptics_resampler_buf;
// Remix to 4 channels
for (int i=0; i < buf_size; i+=4)
{
SDL_memset(haptics_resampler_buf + i * 2, 0, 4);
SDL_memcpy(haptics_resampler_buf + (i * 2) + 4, buf + i, 4);
}
// Resample to 48kHZ
if(SDL_ConvertAudio(&cvt) != 0)
{
CHIAKI_LOGE(log.GetChiakiLog(), "Failed to resample haptics audio: %s", SDL_GetError());
return;
}
if(SDL_QueueAudio(haptics_output, cvt.buf, cvt.len_cvt) < 0)
{
CHIAKI_LOGE(log.GetChiakiLog(), "Failed to submit haptics audio to device: %s", SDL_GetError());
return;
}
}
void StreamSession::Event(ChiakiEvent *event)
{
switch(event->type)
@ -407,6 +563,19 @@ void StreamSession::Event(ChiakiEvent *event)
});
break;
}
case CHIAKI_EVENT_TRIGGER_EFFECTS: {
uint8_t type_left = event->trigger_effects.type_left;
uint8_t data_left[10];
memcpy(data_left, event->trigger_effects.left, 10);
uint8_t data_right[10];
memcpy(data_right, event->trigger_effects.right, 10);
uint8_t type_right = event->trigger_effects.type_right;
QMetaObject::invokeMethod(this, [this, type_left, data_left, type_right, data_right]() {
for(auto controller : controllers)
controller->SetTriggerEffects(type_left, data_left, type_right, data_right);
});
break;
}
default:
break;
}
@ -533,6 +702,7 @@ class StreamSessionPrivate
}
static void PushAudioFrame(StreamSession *session, int16_t *buf, size_t samples_count) { session->PushAudioFrame(buf, samples_count); }
static void PushHapticsFrame(StreamSession *session, uint8_t *buf, size_t buf_size) { session->PushHapticsFrame(buf, buf_size); }
static void Event(StreamSession *session, ChiakiEvent *event) { session->Event(event); }
#if CHIAKI_GUI_ENABLE_SETSU
static void HandleSetsuEvent(StreamSession *session, SetsuEvent *event) { session->HandleSetsuEvent(event); }
@ -552,6 +722,12 @@ static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user)
StreamSessionPrivate::PushAudioFrame(session, buf, samples_count);
}
static void HapticsFrameCb(uint8_t *buf, size_t buf_size, void *user)
{
auto session = reinterpret_cast<StreamSession *>(user);
StreamSessionPrivate::PushHapticsFrame(session, buf, buf_size);
}
static void EventCb(ChiakiEvent *event, void *user)
{
auto session = reinterpret_cast<StreamSession *>(user);

View file

@ -10,6 +10,7 @@
#include <QMessageBox>
#include <QCoreApplication>
#include <QAction>
#include <QMenu>
StreamWindow::StreamWindow(const StreamSessionConnectInfo &connect_info, QWidget *parent)
: QMainWindow(parent),
@ -23,8 +24,6 @@ StreamWindow::StreamWindow(const StreamSessionConnectInfo &connect_info, QWidget
try
{
if(connect_info.fullscreen)
showFullScreen();
Init();
}
catch(const Exception &e)
@ -40,6 +39,8 @@ StreamWindow::~StreamWindow()
delete av_widget;
}
#include <QGuiApplication>
void StreamWindow::Init()
{
session = new StreamSession(connect_info, this);
@ -47,10 +48,36 @@ void StreamWindow::Init()
connect(session, &StreamSession::SessionQuit, this, &StreamWindow::SessionQuit);
connect(session, &StreamSession::LoginPINRequested, this, &StreamWindow::LoginPINRequested);
const QKeySequence fullscreen_shortcut = Qt::Key_F11;
const QKeySequence stretch_shortcut = Qt::CTRL + Qt::Key_S;
const QKeySequence zoom_shortcut = Qt::CTRL + Qt::Key_Z;
fullscreen_action = new QAction(tr("Fullscreen"), this);
fullscreen_action->setCheckable(true);
fullscreen_action->setShortcut(fullscreen_shortcut);
addAction(fullscreen_action);
connect(fullscreen_action, &QAction::triggered, this, &StreamWindow::ToggleFullscreen);
if(session->GetFfmpegDecoder())
{
av_widget = new AVOpenGLWidget(session, this);
av_widget = new AVOpenGLWidget(session, this, connect_info.transform_mode);
setCentralWidget(av_widget);
av_widget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(av_widget, &QWidget::customContextMenuRequested, this, [this](const QPoint &pos) {
av_widget->ResetMouseTimeout();
QMenu menu(av_widget);
menu.addAction(fullscreen_action);
menu.addSeparator();
menu.addAction(stretch_action);
menu.addAction(zoom_action);
releaseKeyboard();
connect(&menu, &QMenu::aboutToHide, this, [this] {
grabKeyboard();
});
menu.exec(av_widget->mapToGlobal(pos));
});
}
else
{
@ -63,13 +90,34 @@ void StreamWindow::Init()
session->Start();
auto fullscreen_action = new QAction(tr("Fullscreen"), this);
fullscreen_action->setShortcut(Qt::Key_F11);
addAction(fullscreen_action);
connect(fullscreen_action, &QAction::triggered, this, &StreamWindow::ToggleFullscreen);
stretch_action = new QAction(tr("Stretch"), this);
stretch_action->setCheckable(true);
stretch_action->setShortcut(stretch_shortcut);
addAction(stretch_action);
connect(stretch_action, &QAction::triggered, this, &StreamWindow::ToggleStretch);
zoom_action = new QAction(tr("Zoom"), this);
zoom_action->setCheckable(true);
zoom_action->setShortcut(zoom_shortcut);
addAction(zoom_action);
connect(zoom_action, &QAction::triggered, this, &StreamWindow::ToggleZoom);
auto quit_action = new QAction(tr("Quit"), this);
quit_action->setShortcut(Qt::CTRL + Qt::Key_Q);
addAction(quit_action);
connect(quit_action, &QAction::triggered, this, &StreamWindow::Quit);
resize(connect_info.video_profile.width, connect_info.video_profile.height);
show();
if(connect_info.fullscreen)
{
showFullScreen();
fullscreen_action->setChecked(true);
}
else
show();
UpdateTransformModeActions();
}
void StreamWindow::keyPressEvent(QKeyEvent *event)
@ -84,22 +132,32 @@ void StreamWindow::keyReleaseEvent(QKeyEvent *event)
session->HandleKeyboardEvent(event);
}
void StreamWindow::Quit()
{
close();
}
void StreamWindow::mousePressEvent(QMouseEvent *event)
{
if(session)
session->HandleMouseEvent(event);
if(session && session->HandleMouseEvent(event))
return;
QMainWindow::mousePressEvent(event);
}
void StreamWindow::mouseReleaseEvent(QMouseEvent *event)
{
if(session)
session->HandleMouseEvent(event);
if(session && session->HandleMouseEvent(event))
return;
QMainWindow::mouseReleaseEvent(event);
}
void StreamWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
ToggleFullscreen();
if(event->button() == Qt::MouseButton::LeftButton)
{
ToggleFullscreen();
return;
}
QMainWindow::mouseDoubleClickEvent(event);
}
@ -143,7 +201,7 @@ void StreamWindow::closeEvent(QCloseEvent *event)
void StreamWindow::SessionQuit(ChiakiQuitReason reason, const QString &reason_str)
{
if(reason != CHIAKI_QUIT_REASON_STOPPED)
if(chiaki_quit_reason_is_error(reason))
{
QString m = tr("Chiaki Session has quit") + ":\n" + chiaki_quit_reason_string(reason);
if(!reason_str.isEmpty())
@ -175,15 +233,48 @@ void StreamWindow::LoginPINRequested(bool incorrect)
void StreamWindow::ToggleFullscreen()
{
if(isFullScreen())
{
showNormal();
fullscreen_action->setChecked(false);
}
else
{
showFullScreen();
if(av_widget)
av_widget->HideMouse();
fullscreen_action->setChecked(true);
}
}
void StreamWindow::UpdateTransformModeActions()
{
TransformMode tm = av_widget ? av_widget->GetTransformMode() : TransformMode::Fit;
stretch_action->setChecked(tm == TransformMode::Stretch);
zoom_action->setChecked(tm == TransformMode::Zoom);
}
void StreamWindow::ToggleStretch()
{
if(!av_widget)
return;
av_widget->SetTransformMode(
av_widget->GetTransformMode() == TransformMode::Stretch
? TransformMode::Fit
: TransformMode::Stretch);
UpdateTransformModeActions();
}
void StreamWindow::ToggleZoom()
{
if(!av_widget)
return;
av_widget->SetTransformMode(
av_widget->GetTransformMode() == TransformMode::Zoom
? TransformMode::Fit
: TransformMode::Zoom);
UpdateTransformModeActions();
}
void StreamWindow::resizeEvent(QResizeEvent *event)
{
UpdateVideoTransform();

View file

@ -72,7 +72,7 @@ set(SOURCE_FILES
src/controller.c
src/takionsendbuffer.c
src/time.c
src/fec
src/fec.c
src/regist.c
src/opusdecoder.c
src/orientation.c)
@ -119,11 +119,15 @@ find_package(Threads REQUIRED)
target_link_libraries(chiaki-lib Threads::Threads)
if(CHIAKI_LIB_ENABLE_MBEDTLS)
# provided by mbedtls-static (mbedtls-devel)
find_library(MBEDTLS mbedtls)
find_library(MBEDX509 mbedx509)
find_library(MBEDCRYPTO mbedcrypto)
target_link_libraries(chiaki-lib ${MBEDTLS} ${MBEDX509} ${MBEDCRYPTO})
if(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT)
target_link_libraries(chiaki-lib mbedtls mbedx509 mbedcrypto)
else()
# provided by mbedtls-static (mbedtls-devel)
find_library(MBEDTLS mbedtls)
find_library(MBEDX509 mbedx509)
find_library(MBEDCRYPTO mbedcrypto)
target_link_libraries(chiaki-lib ${MBEDTLS} ${MBEDX509} ${MBEDCRYPTO})
endif()
elseif(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT)
target_link_libraries(chiaki-lib OpenSSL_Crypto)
else()

View file

@ -78,6 +78,7 @@ typedef struct chiaki_connect_info_t
ChiakiConnectVideoProfile video_profile;
bool video_profile_auto_downgrade; // Downgrade video_profile if server does not seem to support it.
bool enable_keyboard;
bool enable_dualsense;
} ChiakiConnectInfo;
@ -93,11 +94,17 @@ typedef enum {
CHIAKI_QUIT_REASON_CTRL_CONNECT_FAILED,
CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED,
CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN,
CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED
CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED,
CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_SHUTDOWN, // like REMOTE_DISCONNECTED, but because the server shut down
} ChiakiQuitReason;
CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason);
static inline bool chiaki_quit_reason_is_error(ChiakiQuitReason reason)
{
return reason != CHIAKI_QUIT_REASON_STOPPED && reason != CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_SHUTDOWN;
}
typedef struct chiaki_quit_event_t
{
ChiakiQuitReason reason;
@ -121,6 +128,14 @@ typedef struct chiaki_rumble_event_t
uint8_t right; // high-frequency
} ChiakiRumbleEvent;
typedef struct chiaki_trigger_effects_event_t
{
uint8_t type_left;
uint8_t type_right;
uint8_t left[10];
uint8_t right[10];
} ChiakiTriggerEffectsEvent;
typedef enum {
CHIAKI_EVENT_CONNECTED,
CHIAKI_EVENT_LOGIN_PIN_REQUEST,
@ -129,6 +144,7 @@ typedef enum {
CHIAKI_EVENT_KEYBOARD_REMOTE_CLOSE,
CHIAKI_EVENT_RUMBLE,
CHIAKI_EVENT_QUIT,
CHIAKI_EVENT_TRIGGER_EFFECTS,
} ChiakiEventType;
typedef struct chiaki_event_t
@ -139,6 +155,7 @@ typedef struct chiaki_event_t
ChiakiQuitEvent quit;
ChiakiKeyboardEvent keyboard;
ChiakiRumbleEvent rumble;
ChiakiTriggerEffectsEvent trigger_effects;
struct
{
bool pin_incorrect; // false on first request, true if the pin entered before was incorrect
@ -170,6 +187,7 @@ typedef struct chiaki_session_t
ChiakiConnectVideoProfile video_profile;
bool video_profile_auto_downgrade;
bool enable_keyboard;
bool enable_dualsense;
} connect_info;
ChiakiTarget target;
@ -191,6 +209,7 @@ typedef struct chiaki_session_t
ChiakiVideoSampleCallback video_sample_cb;
void *video_sample_cb_user;
ChiakiAudioSink audio_sink;
ChiakiAudioSink haptics_sink;
ChiakiThread session_thread;
@ -246,6 +265,14 @@ static inline void chiaki_session_set_audio_sink(ChiakiSession *session, ChiakiA
session->audio_sink = *sink;
}
/**
* @param sink contents are copied
*/
static inline void chiaki_session_set_haptics_sink(ChiakiSession *session, ChiakiAudioSink *sink)
{
session->haptics_sink = *sink;
}
#ifdef __cplusplus
}
#endif

View file

@ -32,6 +32,7 @@ typedef struct chiaki_stream_connection_t
ChiakiPacketStats packet_stats;
ChiakiAudioReceiver *audio_receiver;
ChiakiVideoReceiver *video_receiver;
ChiakiAudioReceiver *haptics_receiver;
ChiakiFeedbackSender feedback_sender;
/**

View file

@ -27,7 +27,8 @@ extern "C" {
typedef enum chiaki_takion_message_data_type_t {
CHIAKI_TAKION_MESSAGE_DATA_TYPE_PROTOBUF = 0,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_RUMBLE = 7,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_9 = 9
CHIAKI_TAKION_MESSAGE_DATA_TYPE_9 = 9,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_TRIGGER_EFFECTS = 11,
} ChiakiTakionMessageDataType;
typedef struct chiaki_takion_av_packet_t
@ -36,6 +37,7 @@ typedef struct chiaki_takion_av_packet_t
ChiakiSeqNum16 frame_index;
bool uses_nalu_info_structs;
bool is_video;
bool is_haptics;
ChiakiSeqNum16 unit_index;
uint16_t units_in_frame_total; // source + units_in_frame_fec
uint16_t units_in_frame_fec;
@ -46,8 +48,6 @@ typedef struct chiaki_takion_av_packet_t
uint64_t key_pos;
uint8_t byte_before_audio_data;
uint8_t *data; // not owned
size_t data_size;
} ChiakiTakionAVPacket;
@ -106,6 +106,7 @@ typedef struct chiaki_takion_connect_info_t
ChiakiTakionCallback cb;
void *cb_user;
bool enable_crypt;
bool enable_dualsense;
uint8_t protocol_version;
} ChiakiTakionConnectInfo;
@ -162,6 +163,8 @@ typedef struct chiaki_takion_t
ChiakiTakionAVPacketParse av_packet_parse;
ChiakiKeyState key_state;
bool enable_dualsense;
} ChiakiTakion;

View file

@ -11,8 +11,16 @@ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/takion.pb"
set(SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/takion.pb.c")
set(HEADER_FILES "${CMAKE_CURRENT_BINARY_DIR}/takion.pb.h")
if(UNIX AND IS_ABSOLUTE "${PROTOC}")
# make sure protoc is in PATH when invoking the generator below, which needs it.
get_filename_component(PROTOC_PATH "${PROTOC}" DIRECTORY)
set(GEN_PREFIX "${CMAKE_COMMAND}" -E env "PATH=${PROTOC_PATH}:$ENV{PATH}")
else()
set(GEN_PREFIX "")
endif()
add_custom_command(OUTPUT ${SOURCE_FILES} ${HEADER_FILES}
COMMAND "${PYTHON_EXECUTABLE}" "${NANOPB_GENERATOR_PY}" "${CMAKE_CURRENT_BINARY_DIR}/takion.pb"
COMMAND ${GEN_PREFIX} "${PYTHON_EXECUTABLE}" "${NANOPB_GENERATOR_PY}" "${CMAKE_CURRENT_BINARY_DIR}/takion.pb"
MAIN_DEPENDENCY "${CMAKE_CURRENT_BINARY_DIR}/takion.pb")
set(CHIAKI_LIB_PROTO_SOURCE_FILES "${SOURCE_FILES}" PARENT_SCOPE)

View file

@ -312,7 +312,8 @@ message ControllerConnectionPayload {
VITA = 3;
XINPUT = 4;
MOBILE = 5;
BOND = 6;
DUALSENSE = 6;
VR2SENSE = 7;
}
}

View file

@ -5,7 +5,7 @@
#include <string.h>
static void chiaki_audio_receiver_frame(ChiakiAudioReceiver *audio_receiver, ChiakiSeqNum16 frame_index, uint8_t *buf, size_t buf_size);
static void chiaki_audio_receiver_frame(ChiakiAudioReceiver *audio_receiver, ChiakiSeqNum16 frame_index, bool is_haptics, uint8_t *buf, size_t buf_size);
CHIAKI_EXPORT ChiakiErrorCode chiaki_audio_receiver_init(ChiakiAudioReceiver *audio_receiver, ChiakiSession *session, ChiakiPacketStats *packet_stats)
{
@ -102,14 +102,14 @@ CHIAKI_EXPORT void chiaki_audio_receiver_av_packet(ChiakiAudioReceiver *audio_re
frame_index = packet->frame_index - fec_units_count + fec_index;
}
chiaki_audio_receiver_frame(audio_receiver, frame_index, packet->data + unit_size * i, unit_size);
chiaki_audio_receiver_frame(audio_receiver, frame_index, packet->is_haptics, packet->data + unit_size * i, unit_size);
}
if(audio_receiver->packet_stats)
chiaki_packet_stats_push_seq(audio_receiver->packet_stats, packet->frame_index);
}
static void chiaki_audio_receiver_frame(ChiakiAudioReceiver *audio_receiver, ChiakiSeqNum16 frame_index, uint8_t *buf, size_t buf_size)
static void chiaki_audio_receiver_frame(ChiakiAudioReceiver *audio_receiver, ChiakiSeqNum16 frame_index, bool is_haptics, uint8_t *buf, size_t buf_size)
{
chiaki_mutex_lock(&audio_receiver->mutex);
@ -117,7 +117,9 @@ static void chiaki_audio_receiver_frame(ChiakiAudioReceiver *audio_receiver, Chi
goto beach;
audio_receiver->frame_index_prev = frame_index;
if(audio_receiver->session->audio_sink.frame_cb)
if(is_haptics && audio_receiver->session->haptics_sink.frame_cb)
audio_receiver->session->haptics_sink.frame_cb(buf, buf_size, audio_receiver->session->haptics_sink.user);
else if(!is_haptics && audio_receiver->session->audio_sink.frame_cb)
audio_receiver->session->audio_sink.frame_cb(buf, buf_size, audio_receiver->session->audio_sink.user);
beach:

View file

@ -121,6 +121,19 @@ CHIAKI_EXPORT void chiaki_controller_state_or(ChiakiControllerState *out, Chiaki
out->right_x = MAX_ABS(a->right_x, b->right_x);
out->right_y = MAX_ABS(a->right_y, b->right_y);
#define ORF(n, idle_val) if(a->n == idle_val) out->n = b->n; else out->n = a->n
ORF(accel_x, 0.0f);
ORF(accel_y, 1.0f);
ORF(accel_z, 0.0f);
ORF(gyro_x, 0.0f);
ORF(gyro_y, 0.0f);
ORF(gyro_z, 0.0f);
ORF(orient_x, 0.0f);
ORF(orient_y, 0.0f);
ORF(orient_z, 0.0f);
ORF(orient_w, 1.0f);
#undef ORF
out->touch_id_next = 0;
for(size_t i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
{

View file

@ -488,17 +488,25 @@ static void ctrl_message_received(ChiakiCtrl *ctrl, uint16_t msg_type, uint8_t *
static void ctrl_enable_optional_features(ChiakiCtrl *ctrl)
{
if(!ctrl->session->connect_info.enable_keyboard)
return;
// TODO: Last byte of pre_enable request is random (?)
// TODO: Signature ?!
uint8_t enable = 1;
uint8_t pre_enable[4] = { 0x00, 0x01, 0x01, 0x80 };
uint8_t signature[0x10] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ctrl_message_send(ctrl, 0xD, signature, 0x10);
ctrl_message_send(ctrl, 0x36, pre_enable, 4);
ctrl_message_send(ctrl, CTRL_MESSAGE_TYPE_KEYBOARD_ENABLE_TOGGLE, &enable, 1);
ctrl_message_send(ctrl, 0x36, pre_enable, 4);
if(ctrl->session->connect_info.enable_dualsense)
{
CHIAKI_LOGI(ctrl->session->log, "Enabling DualSense features");
const uint8_t enable[3] = { 0x00, 0x40, 0x00 };
ctrl_message_send(ctrl, 0x13, enable, 3);
}
if(ctrl->session->connect_info.enable_keyboard)
{
CHIAKI_LOGI(ctrl->session->log, "Enabling Keyboard");
// TODO: Last byte of pre_enable request is random (?)
// TODO: Signature ?!
uint8_t enable = 1;
uint8_t pre_enable[4] = { 0x00, 0x01, 0x01, 0x80 };
uint8_t signature[0x10] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ctrl_message_send(ctrl, 0xD, signature, 0x10);
ctrl_message_send(ctrl, 0x36, pre_enable, 4);
ctrl_message_send(ctrl, CTRL_MESSAGE_TYPE_KEYBOARD_ENABLE_TOGGLE, &enable, 1);
ctrl_message_send(ctrl, 0x36, pre_enable, 4);
}
}
static void ctrl_message_received_session_id(ChiakiCtrl *ctrl, uint8_t *payload, size_t payload_size)

View file

@ -81,7 +81,11 @@ CHIAKI_EXPORT void chiaki_feedback_state_format_v12(uint8_t *buf, ChiakiFeedback
chiaki_feedback_state_format_v9(buf, state);
buf[0x19] = 0x0;
buf[0x1a] = 0x0;
buf[0x1b] = 0x1; // 1 for Shock, 0 for Sense
// 1 is classic DualShock, 0 is DualSense, but using 0 requires setting [0x19] and [0x1a] to
// values taken from raw HID, which is generally not available. But setting 1 for both seems
// to always work fine.
buf[0x1b] = 0x1;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFeedbackHistoryEvent *event, uint64_t button, uint8_t state)

View file

@ -146,7 +146,15 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_recv_http_header(int sock, char *buf, size_
return err;
}
int received = (int)recv(sock, buf, (int)buf_size, 0);
int received;
do
{
received = (int)recv(sock, buf, (int)buf_size, 0);
#if _WIN32
} while(false);
#else
} while(received < 0 && errno == EINTR);
#endif
if(received <= 0)
return received == 0 ? CHIAKI_ERR_DISCONNECTED : CHIAKI_ERR_NETWORK;

View file

@ -158,6 +158,8 @@ CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason)
return "Unknown Error in Stream Connection";
case CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED:
return "Remote has disconnected from Stream Connection";
case CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_SHUTDOWN:
return "Remote has disconnected from Stream Connection the because Server shut down";
case CHIAKI_QUIT_REASON_NONE:
default:
return "Unknown";
@ -227,6 +229,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, Chiaki
session->connect_info.video_profile = connect_info->video_profile;
session->connect_info.video_profile_auto_downgrade = connect_info->video_profile_auto_downgrade;
session->connect_info.enable_keyboard = connect_info->enable_keyboard;
session->connect_info.enable_dualsense = connect_info->enable_dualsense;
return CHIAKI_ERR_SUCCESS;
error_stop_pipe:
@ -504,7 +507,10 @@ ctrl_failed:
if(err == CHIAKI_ERR_DISCONNECTED)
{
CHIAKI_LOGE(session->log, "Remote disconnected from StreamConnection");
session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED;
if(!strcmp(session->stream_connection.remote_disconnect_reason, "Server shutting down"))
session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_SHUTDOWN;
else
session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED;
session->quit_reason_str = strdup(session->stream_connection.remote_disconnect_reason);
}
else if(err != CHIAKI_ERR_SUCCESS && err != CHIAKI_ERR_CANCELED)

View file

@ -147,7 +147,11 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
timeout = &timeout_s;
}
int r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout);
int r;
do
{
r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout);
} while(r < 0 && errno == EINTR);
if(r < 0)
return CHIAKI_ERR_UNKNOWN;

View file

@ -47,7 +47,9 @@ static void stream_connection_takion_cb(ChiakiTakionEvent *event, void *user);
static void stream_connection_takion_data(ChiakiStreamConnection *stream_connection, ChiakiTakionMessageDataType data_type, uint8_t *buf, size_t buf_size);
static void stream_connection_takion_data_protobuf(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size);
static void stream_connection_takion_data_rumble(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size);
static void stream_connection_takion_data_trigger_effects(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size);
static ChiakiErrorCode stream_connection_send_big(ChiakiStreamConnection *stream_connection);
static ChiakiErrorCode stream_connection_send_controller_connection(ChiakiStreamConnection *stream_connection);
static ChiakiErrorCode stream_connection_send_disconnect(ChiakiStreamConnection *stream_connection);
static void stream_connection_takion_data_idle(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size);
static void stream_connection_takion_data_expect_bang(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size);
@ -79,6 +81,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_init(ChiakiStreamConnecti
stream_connection->video_receiver = NULL;
stream_connection->audio_receiver = NULL;
stream_connection->haptics_receiver = NULL;
err = chiaki_mutex_init(&stream_connection->feedback_sender_mutex, false);
if(err != CHIAKI_ERR_SUCCESS)
@ -143,6 +146,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnectio
takion_info.ip_dontfrag = false;
takion_info.enable_crypt = true;
takion_info.enable_dualsense = session->connect_info.enable_dualsense;
takion_info.protocol_version = chiaki_target_is_ps5(session->target) ? 12 : 9;
takion_info.cb = stream_connection_takion_cb;
@ -164,12 +168,20 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnectio
return CHIAKI_ERR_UNKNOWN;
}
stream_connection->haptics_receiver = chiaki_audio_receiver_new(session, NULL);
if(!stream_connection->haptics_receiver)
{
CHIAKI_LOGE(session->log, "StreamConnection failed to initialize Haptics Receiver");
err = CHIAKI_ERR_UNKNOWN;
goto err_audio_receiver;
}
stream_connection->video_receiver = chiaki_video_receiver_new(session, &stream_connection->packet_stats);
if(!stream_connection->video_receiver)
{
CHIAKI_LOGE(session->log, "StreamConnection failed to initialize Video Receiver");
err = CHIAKI_ERR_UNKNOWN;
goto err_audio_receiver;
goto err_haptics_receiver;
}
stream_connection->state = STATE_TAKION_CONNECT;
@ -321,6 +333,10 @@ err_video_receiver:
chiaki_video_receiver_free(stream_connection->video_receiver);
stream_connection->video_receiver = NULL;
err_haptics_receiver:
chiaki_audio_receiver_free(stream_connection->haptics_receiver);
stream_connection->haptics_receiver = NULL;
err_audio_receiver:
chiaki_audio_receiver_free(stream_connection->audio_receiver);
stream_connection->audio_receiver = NULL;
@ -376,6 +392,9 @@ static void stream_connection_takion_data(ChiakiStreamConnection *stream_connect
case CHIAKI_TAKION_MESSAGE_DATA_TYPE_RUMBLE:
stream_connection_takion_data_rumble(stream_connection, buf, buf_size);
break;
case CHIAKI_TAKION_MESSAGE_DATA_TYPE_TRIGGER_EFFECTS:
stream_connection_takion_data_trigger_effects(stream_connection, buf, buf_size);
break;
default:
break;
}
@ -415,6 +434,24 @@ static void stream_connection_takion_data_rumble(ChiakiStreamConnection *stream_
chiaki_session_send_event(stream_connection->session, &event);
}
static void stream_connection_takion_data_trigger_effects(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size)
{
if(buf_size < 25)
{
CHIAKI_LOGE(stream_connection->log, "StreamConnection got trigger effects packet with size %#llx < 25",
(unsigned long long)buf_size);
return;
}
ChiakiEvent event = { 0 };
event.type = CHIAKI_EVENT_TRIGGER_EFFECTS;
event.trigger_effects.type_left = buf[1];
event.trigger_effects.type_right = buf[2];
memcpy(&event.trigger_effects.left, buf + 5, 10);
memcpy(&event.trigger_effects.right, buf + 15, 10);
chiaki_session_send_event(stream_connection->session, &event);
}
static void stream_connection_takion_data_handle_disconnect(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size)
{
tkproto_TakionMessage msg;
@ -460,7 +497,7 @@ static void stream_connection_takion_data_idle(ChiakiStreamConnection *stream_co
return;
}
CHIAKI_LOGV(stream_connection->log, "StreamConnection received data");
CHIAKI_LOGV(stream_connection->log, "StreamConnection received data with msg.type == %d", msg.type);
chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_VERBOSE, buf, buf_size);
if(msg.type == tkproto_TakionMessage_PayloadType_DISCONNECT)
@ -522,7 +559,8 @@ static void stream_connection_takion_data_expect_bang(ChiakiStreamConnection *st
return;
}
CHIAKI_LOGE(stream_connection->log, "StreamConnection expected bang payload but received something else");
CHIAKI_LOGE(stream_connection->log, "StreamConnection expected bang payload but received something else: %d", msg.type);
chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_VERBOSE, buf, buf_size);
return;
}
@ -584,6 +622,12 @@ static void stream_connection_takion_data_expect_bang(ChiakiStreamConnection *st
// stream_connection->state_mutex is expected to be locked by the caller of this function
stream_connection->state_finished = true;
chiaki_cond_signal(&stream_connection->state_cond);
err = stream_connection_send_controller_connection(stream_connection);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(stream_connection->log, "StreamConnection failed to send controller connection");
goto error;
}
return;
error:
stream_connection->state_failed = true;
@ -811,6 +855,37 @@ static ChiakiErrorCode stream_connection_send_big(ChiakiStreamConnection *stream
return err;
}
static ChiakiErrorCode stream_connection_send_controller_connection(ChiakiStreamConnection *stream_connection)
{
ChiakiSession *session = stream_connection->session;
tkproto_TakionMessage msg;
memset(&msg, 0, sizeof(msg));
msg.type = tkproto_TakionMessage_PayloadType_CONTROLLERCONNECTION;
msg.has_controller_connection_payload = true;
msg.controller_connection_payload.has_connected = true;
msg.controller_connection_payload.connected = true;
msg.controller_connection_payload.has_controller_id = false;
msg.controller_connection_payload.has_controller_type = true;
msg.controller_connection_payload.controller_type = session->connect_info.enable_dualsense
? tkproto_ControllerConnectionPayload_ControllerType_DUALSENSE
: tkproto_ControllerConnectionPayload_ControllerType_DUALSHOCK4;
uint8_t buf[2048];
size_t buf_size;
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
bool pbr = pb_encode(&stream, tkproto_TakionMessage_fields, &msg);
if(!pbr)
{
CHIAKI_LOGE(stream_connection->log, "StreamConnection controller connection protobuf encoding failed");
return CHIAKI_ERR_UNKNOWN;
}
buf_size = stream.bytes_written;
return chiaki_takion_send_message_data(&stream_connection->takion, 1, 1, buf, buf_size, NULL);
}
static ChiakiErrorCode stream_connection_send_streaminfo_ack(ChiakiStreamConnection *stream_connection)
{
tkproto_TakionMessage msg;
@ -867,6 +942,8 @@ static void stream_connection_takion_av(ChiakiStreamConnection *stream_connectio
if(packet->is_video)
chiaki_video_receiver_av_packet(stream_connection->video_receiver, packet);
else if(packet->is_haptics)
chiaki_audio_receiver_av_packet(stream_connection->haptics_receiver, packet);
else
chiaki_audio_receiver_av_packet(stream_connection->audio_receiver, packet);
}

View file

@ -57,7 +57,8 @@ typedef enum takion_packet_type_t {
TAKION_PACKET_TYPE_CONGESTION = 5,
TAKION_PACKET_TYPE_FEEDBACK_STATE = 6,
TAKION_PACKET_TYPE_CLIENT_INFO = 8,
TAKION_PACKET_TYPE_PAD_INFO_EVENT = 9
TAKION_PACKET_TYPE_PAD_INFO_EVENT = 9,
TAKION_PACKET_TYPE_PAD_ADAPTIVE_TRIGGERS = 11,
} TakionPacketType;
/**
@ -215,6 +216,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, Chiaki
takion->postponed_packets = NULL;
takion->postponed_packets_size = 0;
takion->postponed_packets_count = 0;
takion->enable_dualsense = info->enable_dualsense;
CHIAKI_LOGI(takion->log, "Takion connecting (version %u)", (unsigned int)info->protocol_version);
@ -950,6 +952,7 @@ static void takion_flush_data_queue(ChiakiTakion *takion)
if(data_type != CHIAKI_TAKION_MESSAGE_DATA_TYPE_PROTOBUF
&& data_type != CHIAKI_TAKION_MESSAGE_DATA_TYPE_RUMBLE
&& data_type != CHIAKI_TAKION_MESSAGE_DATA_TYPE_TRIGGER_EFFECTS
&& data_type != CHIAKI_TAKION_MESSAGE_DATA_TYPE_9)
{
CHIAKI_LOGW(takion->log, "Takion received data with unexpected data type %#x", data_type);
@ -1308,7 +1311,7 @@ static ChiakiErrorCode av_packet_parse(bool v12, ChiakiTakionAVPacket *packet, C
if(v12 && !packet->is_video)
{
packet->byte_before_audio_data = *av;
packet->is_haptics = *av == 0x02;
av += 1;
av_size -= 1;
}

13
scripts/Dockerfile.noble Normal file
View file

@ -0,0 +1,13 @@
FROM ubuntu:noble
RUN apt-get update
# Hint: python3-setuptools should not be needed with nanopb >= 0.4.9
RUN apt-get -y install git g++ cmake ninja-build curl pkg-config unzip \
python3-protobuf protobuf-compiler \
python3-setuptools \
libssl-dev libopus-dev qtbase5-dev qtmultimedia5-dev libqt5multimedia5-plugins libqt5svg5-dev \
libgl1-mesa-dev nasm libudev-dev libva-dev fuse libevdev-dev libudev-dev file
CMD []

View file

@ -1,13 +0,0 @@
FROM ubuntu:xenial
RUN apt-get update
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:beineri/opt-qt-5.12.3-xenial
RUN apt-get update
RUN apt-get -y install git g++ cmake ninja-build curl pkg-config unzip python3-pip \
libssl-dev libopus-dev qt512base qt512multimedia qt512svg \
libgl1-mesa-dev nasm libudev-dev libva-dev fuse libevdev-dev libudev-dev
CMD []

View file

@ -1,77 +1,92 @@
#!/bin/bash
echo "APPVEYOR_BUILD_FOLDER=$APPVEYOR_BUILD_FOLDER"
set -xe
mkdir ninja && cd ninja || exit 1
wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-win.zip && 7z x ninja-win.zip || exit 1
cd .. || exit 1
BUILD_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
BUILD_ROOT="$(echo $BUILD_ROOT | sed 's|^/\([a-z]\)|\1:|g')" # replace /c/... by c:/... for cmake to understand it
echo "BUILD_ROOT=$BUILD_ROOT"
mkdir yasm && cd yasm || exit 1
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe && mv yasm-1.3.0-win64.exe yasm.exe || exit 1
cd .. || exit 1
mkdir ninja && cd ninja
wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-win.zip && 7z x ninja-win.zip
cd ..
mkdir yasm && cd yasm
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe && mv yasm-1.3.0-win64.exe yasm.exe
cd ..
export PATH="$PWD/ninja:$PWD/yasm:/c/Qt/5.12/msvc2017_64/bin:$PATH"
scripts/build-ffmpeg.sh . --target-os=win64 --arch=x86_64 --toolchain=msvc || exit 1
scripts/build-ffmpeg.sh . --target-os=win64 --arch=x86_64 --toolchain=msvc
git clone https://github.com/xiph/opus.git && cd opus && git checkout ad8fe90db79b7d2a135e3dfd2ed6631b0c5662ab || exit 1
mkdir build && cd build || exit 1
git clone https://github.com/xiph/opus.git && cd opus && git checkout ad8fe90db79b7d2a135e3dfd2ed6631b0c5662ab
mkdir build && cd build
cmake \
-G Ninja \
-DCMAKE_C_COMPILER=cl \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$APPVEYOR_BUILD_FOLDER/opus-prefix" \
.. || exit 1
ninja || exit 1
ninja install || exit 1
cd ../.. || exit 1
-DCMAKE_INSTALL_PREFIX="$BUILD_ROOT/opus-prefix" \
..
ninja
ninja install
cd ../..
wget https://mirror.firedaemon.com/OpenSSL/openssl-1.1.1d-dev.zip && 7z x openssl-1.1.1d-dev.zip || exit 1
wget https://download.firedaemon.com/FireDaemon-OpenSSL/openssl-1.1.1s.zip && 7z x openssl-1.1.*.zip
wget https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip && 7z x SDL2-devel-2.0.10-VC.zip || exit 1
export SDL_ROOT="$APPVEYOR_BUILD_FOLDER/SDL2-2.0.10" || exit 1
export SDL_ROOT=${SDL_ROOT//[\\]//} || exit 1
wget https://www.libsdl.org/release/SDL2-devel-2.26.2-VC.zip && 7z x SDL2-devel-2.26.2-VC.zip
export SDL_ROOT="$BUILD_ROOT/SDL2-2.26.2"
export SDL_ROOT=${SDL_ROOT//[\\]//}
echo "set(SDL2_INCLUDE_DIRS \"$SDL_ROOT/include\")
set(SDL2_LIBRARIES \"$SDL_ROOT/lib/x64/SDL2.lib\")
set(SDL2_LIBDIR \"$SDL_ROOT/lib/x64\")" > "$SDL_ROOT/SDL2Config.cmake" || exit 1
set(SDL2_LIBDIR \"$SDL_ROOT/lib/x64\")
include($SDL_ROOT/cmake/sdl2-config-version.cmake)" > "$SDL_ROOT/SDL2Config.cmake"
mkdir protoc && cd protoc || exit 1
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-win64.zip && 7z x protoc-3.9.1-win64.zip || exit 1
cd .. || exit 1
export PATH="$PWD/protoc/bin:$PATH" || exit 1
mkdir protoc && cd protoc
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-win64.zip && 7z x protoc-3.9.1-win64.zip
cd ..
export PATH="$PWD/protoc/bin:$PATH"
PYTHON="C:/Python37/python.exe"
"$PYTHON" -m pip install protobuf || exit 1
"$PYTHON" -m pip install protobuf==3.19.5
QT_PATH="C:/Qt/5.12/msvc2017_64"
QT_PATH="C:/Qt/5.15/msvc2019_64"
COPY_DLLS="$PWD/openssl-1.1/x64/bin/libcrypto-1_1-x64.dll $PWD/openssl-1.1/x64/bin/libssl-1_1-x64.dll $SDL_ROOT/lib/x64/SDL2.dll"
mkdir build && cd build || exit 1
echo "-- Configure"
mkdir build && cd build
cmake \
-G Ninja \
-DCMAKE_C_COMPILER=cl \
-DCMAKE_C_FLAGS="-we4013" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_PREFIX_PATH="$APPVEYOR_BUILD_FOLDER/ffmpeg-prefix;$APPVEYOR_BUILD_FOLDER/opus-prefix;$APPVEYOR_BUILD_FOLDER/openssl-1.1/x64;$QT_PATH;$SDL_ROOT" \
-DCMAKE_PREFIX_PATH="$BUILD_ROOT/ffmpeg-prefix;$BUILD_ROOT/opus-prefix;$BUILD_ROOT/openssl-1.1/x64;$QT_PATH;$SDL_ROOT" \
-DPYTHON_EXECUTABLE="$PYTHON" \
-DCHIAKI_ENABLE_TESTS=ON \
-DCHIAKI_ENABLE_CLI=OFF \
-DCHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER=ON \
.. || exit 1
..
ninja || exit 1
echo "-- Build"
test/chiaki-unit.exe || exit 1
ninja
cd .. || exit 1
echo "-- Test"
cp $COPY_DLLS test/
test/chiaki-unit.exe
cd ..
# Deploy
mkdir Chiaki && cp build/gui/chiaki.exe Chiaki || exit 1
mkdir Chiaki-PDB && cp build/gui/chiaki.pdb Chiaki-PDB || exit 1
echo "-- Deploy"
"$QT_PATH/bin/windeployqt.exe" Chiaki/chiaki.exe || exit 1
mkdir Chiaki && cp build/gui/chiaki.exe Chiaki
mkdir Chiaki-PDB && cp build/gui/chiaki.pdb Chiaki-PDB
"$QT_PATH/bin/windeployqt.exe" Chiaki/chiaki.exe
cp -v $COPY_DLLS Chiaki

View file

@ -2,10 +2,11 @@
set -xe
# sometimes there are errors in linuxdeploy in docker/podman when the appdir is on a mount
appdir=${1:-`pwd`/appimage/appdir}
mkdir appimage
pip3 install --user protobuf
scripts/fetch-protoc.sh appimage
export PATH="`pwd`/appimage/protoc/bin:$PATH"
scripts/build-ffmpeg.sh appimage
scripts/build-sdl2.sh appimage
@ -15,31 +16,31 @@ cd build_appimage
cmake \
-GNinja \
-DCMAKE_BUILD_TYPE=Release \
"-DCMAKE_PREFIX_PATH=`pwd`/../appimage/ffmpeg-prefix;`pwd`/../appimage/sdl2-prefix;/opt/qt512" \
"-DCMAKE_PREFIX_PATH=`pwd`/../appimage/ffmpeg-prefix;`pwd`/../appimage/sdl2-prefix" \
-DCHIAKI_ENABLE_TESTS=ON \
-DCHIAKI_ENABLE_CLI=OFF \
-DCHIAKI_ENABLE_GUI=ON \
-DCHIAKI_ENABLE_SETSU=ON \
-DCHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER=ON \
-DCMAKE_INSTALL_PREFIX=/usr \
..
cd ..
# purge leftover proto/nanopb_pb2.py which may have been created with another protobuf version
rm -fv third-party/nanopb/generator/proto/nanopb_pb2.py
ninja -C build_appimage
build_appimage/test/chiaki-unit
DESTDIR=`pwd`/appimage/appdir ninja -C build_appimage install
DESTDIR="${appdir}" ninja -C build_appimage install
cd appimage
curl -L -O https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
curl -L -O https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
chmod +x linuxdeploy-plugin-qt-x86_64.AppImage
set +e
source /opt/qt512/bin/qt512-env.sh
set -e
export LD_LIBRARY_PATH="`pwd`/sdl2-prefix/lib:$LD_LIBRARY_PATH"
export EXTRA_QT_PLUGINS=opengl
./linuxdeploy-x86_64.AppImage --appdir=appdir -e appdir/usr/bin/chiaki -d appdir/usr/share/applications/chiaki.desktop --plugin qt --output appimage
mv Chiaki-*-x86_64.AppImage Chiaki.AppImage
./linuxdeploy-x86_64.AppImage --appdir="${appdir}" -e "${appdir}/usr/bin/chiaki" -d "${appdir}/usr/share/applications/chiaki.desktop" --plugin qt --output appimage
mv Chiaki*-x86_64.AppImage Chiaki.AppImage

View file

@ -1,5 +1,8 @@
#!/bin/bash
# purge leftover proto/nanopb_pb2.py which may have been created with another protobuf version
rm -fv third-party/nanopb/generator/proto/nanopb_pb2.py
mkdir build && cd build || exit 1
cmake \
-DCMAKE_BUILD_TYPE=Release \

View file

@ -5,7 +5,7 @@ cd "./$1"
shift
ROOT="`pwd`"
TAG=n4.3.1
TAG=n4.3.9
git clone https://git.ffmpeg.org/ffmpeg.git --depth 1 -b $TAG && cd ffmpeg || exit 1

View file

@ -6,9 +6,10 @@ cd $(dirname "${BASH_SOURCE[0]}")/..
cd "./$1"
ROOT="`pwd`"
URL=https://www.libsdl.org/release/SDL2-2.0.10.tar.gz
FILE=SDL2-2.0.10.tar.gz
DIR=SDL2-2.0.10
SDL_VER=2.26.1
URL=https://www.libsdl.org/release/SDL2-${SDL_VER}.tar.gz
FILE=SDL2-${SDL_VER}.tar.gz
DIR=SDL2-${SDL_VER}
if [ ! -d "$DIR" ]; then
curl -L "$URL" -O
@ -21,14 +22,14 @@ mkdir -p build && cd build || exit 1
cmake \
-DCMAKE_INSTALL_PREFIX="$ROOT/sdl2-prefix" \
-DSDL_ATOMIC=OFF \
-DSDL_AUDIO=OFF \
-DSDL_AUDIO=ON \
-DSDL_CPUINFO=OFF \
-DSDL_EVENTS=ON \
-DSDL_FILE=OFF \
-DSDL_FILESYSTEM=OFF \
-DSDL_HAPTIC=ON \
-DSDL_JOYSTICK=ON \
-DSDL_LOADSO=OFF \
-DSDL_LOADSO=ON \
-DSDL_RENDER=OFF \
-DSDL_SHARED=ON \
-DSDL_STATIC=OFF \

View file

@ -1,13 +0,0 @@
#!/bin/bash
set -xe
cd $(dirname "${BASH_SOURCE[0]}")/..
cd "./$1"
ROOT="`pwd`"
URL=https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-linux-x86_64.zip
curl -L "$URL" -o protoc.zip
unzip protoc.zip -d protoc

View file

@ -89,8 +89,8 @@
{
"type": "git",
"url": "https://git.sr.ht/~thestr4ng3r/chiaki",
"tag": "v2.1.0",
"commit": "fcdc414692b33ecae1f30a19dc4cd81d4bd77121"
"tag": "v2.1.1",
"commit": "2257030adeb5c5a84380c78d34be4d783971663c"
}
]
}

18
scripts/macos-dist-local.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
# Build Chiaki for macOS distribution using dependencies from MacPorts and custom ffmpeg
set -xe
cd $(dirname "${BASH_SOURCE[0]}")/..
scripts/build-ffmpeg.sh
export CMAKE_PREFIX_PATH="`pwd`/ffmpeg-prefix"
scripts/build-common.sh
cp -a build/gui/chiaki.app Chiaki.app
/opt/local/libexec/qt5/bin/macdeployqt Chiaki.app
# Remove all LC_RPATH load commands that have absolute paths of the build machine
RPATHS=$(otool -l Chiaki.app/Contents/MacOS/chiaki | grep -A 2 LC_RPATH | grep 'path /' | awk '{print $2}')
for p in ${RPATHS}; do install_name_tool -delete_rpath "$p" Chiaki.app/Contents/MacOS/chiaki; done
# This may warn because we already ran macdeployqt above
/opt/local/libexec/qt5/bin/macdeployqt Chiaki.app -dmg

View file

@ -1,15 +0,0 @@
#!/bin/bash
set -xe
cd "`dirname $(readlink -f ${0})`"
docker build -t chiaki-xenial . -f Dockerfile.xenial
cd ..
docker run --rm \
-v "`pwd`:/build/chiaki" \
-w "/build/chiaki" \
--device /dev/fuse \
--cap-add SYS_ADMIN \
-t chiaki-xenial \
/bin/bash -c "scripts/build-appimage.sh"

View file

@ -1,14 +0,0 @@
#!/bin/bash
set -xe
cd "`dirname $(readlink -f ${0})`"
docker build -t chiaki-bullseye . -f Dockerfile.bullseye
cd ..
docker run --rm -v "`pwd`:/build" chiaki-bullseye /bin/bash -c "
cd /build &&
mkdir build_bullseye &&
cmake -Bbuild_bullseye -GNinja -DCHIAKI_ENABLE_SETSU=ON -DCHIAKI_USE_SYSTEM_JERASURE=ON -DCHIAKI_USE_SYSTEM_NANOPB=ON &&
ninja -C build_bullseye &&
ninja -C build_bullseye test"

View file

@ -0,0 +1,16 @@
#!/bin/bash
set -xe
cd "`dirname $(readlink -f ${0})`"
podman build --arch amd64 -t localhost/chiaki-noble . -f Dockerfile.noble
cd ..
podman run --rm \
--arch amd64 \
-v "`pwd`:/build/chiaki" \
-w "/build/chiaki" \
--device /dev/fuse \
--cap-add SYS_ADMIN \
-t localhost/chiaki-noble \
/bin/bash -c "scripts/build-appimage.sh /build/appdir"

View file

@ -0,0 +1,15 @@
#!/bin/bash
set -xe
cd "`dirname $(readlink -f ${0})`"
podman build -t chiaki-bullseye . -f Dockerfile.bullseye
cd ..
podman run --rm -v "`pwd`:/build" chiaki-bullseye /bin/bash -c "
cd /build &&
rm -fv third-party/nanopb/generator/proto/nanopb_pb2.py &&
mkdir build_bullseye &&
cmake -Bbuild_bullseye -GNinja -DCHIAKI_USE_SYSTEM_JERASURE=ON -DCHIAKI_USE_SYSTEM_NANOPB=ON &&
ninja -C build_bullseye &&
ninja -C build_bullseye test"

View file

@ -5,10 +5,7 @@ set -xveo pipefail
arg1=$1
build="./build"
if [ "$arg1" != "linux" ]; then
# source /opt/devkitpro/switchvars.sh
# toolchain="${DEVKITPRO}/switch.cmake"
toolchain="cmake/switch.cmake"
export PORTLIBS_PREFIX="$(${DEVKITPRO}/portlibs_prefix.sh switch)"
build="./build_switch"
fi
@ -19,6 +16,9 @@ build_chiaki (){
pushd "${BASEDIR}"
#rm -rf ./build
# purge leftover proto/nanopb_pb2.py which may have been created with another protobuf version
rm -fv third-party/nanopb/generator/proto/nanopb_pb2.py
cmake -B "${build}" \
-GNinja \
-DCMAKE_TOOLCHAIN_FILE=${toolchain} \

View file

@ -2,10 +2,9 @@
cd "`dirname $(readlink -f ${0})`/../.."
docker run \
podman run --rm \
-v "`pwd`:/build/chiaki" \
-w "/build/chiaki" \
-t \
thestr4ng3r/chiaki-build-switch \
-c "scripts/switch/build.sh"
-it \
quay.io/thestr4ng3r/chiaki-build-switch:v3 \
/bin/bash

View file

@ -0,0 +1,10 @@
#!/bin/bash
cd "`dirname $(readlink -f ${0})`/../.."
podman run --rm \
-v "`pwd`:/build/chiaki" \
-w "/build/chiaki" \
-it \
quay.io/thestr4ng3r/chiaki-build-switch:v3 \
${1:-/bin/bash -c "scripts/switch/build.sh"}

View file

@ -61,17 +61,16 @@ target_include_directories(borealis PUBLIC
find_package(glfw3 REQUIRED)
find_library(EGL EGL)
find_library(GLAPI glapi)
find_library(DRM_NOUVEAU drm_nouveau)
target_link_libraries(borealis
target_link_libraries(borealis PUBLIC
glfw
${EGL}
${GLAPI}
${DRM_NOUVEAU})
${EGL})
if(CHIAKI_IS_SWITCH)
target_compile_definitions(borealis PUBLIC
BOREALIS_RESOURCES="romfs:/")
find_library(GLAPI glapi)
find_library(DRM_NOUVEAU drm_nouveau)
target_link_libraries(borealis PUBLIC ${GLAPI} ${DRM_NOUVEAU})
else()
target_compile_definitions(borealis PUBLIC
BOREALIS_RESOURCES="./switch/res/")
@ -114,9 +113,7 @@ target_link_libraries(chiaki-borealis
if(CHIAKI_IS_SWITCH)
# libnx is forced by the switch toolchain
find_library(Z z)
find_library(GLAPI glapi) # TODO: make it transitive from borealis
find_library(DRM_NOUVEAU drm_nouveau) # TODO: make it transitive from borealis
target_link_libraries(chiaki-borealis ${Z} ${GLAPI} ${DRM_NOUVEAU})
target_link_libraries(chiaki-borealis ${Z} ${GLAPI})
endif()
install(TARGETS chiaki-borealis

View file

@ -7,7 +7,7 @@ but the easiest way is to use the following container.
Build Project
-------------
```
bash scripts/switch/run-docker-build-chiaki.sh
bash scripts/switch/run-podman-build-chiaki.sh
```
tools
@ -15,7 +15,7 @@ tools
Push to homebrew Netloader
```
# where X.X.X.X is the IP of your switch
bash scripts/switch/push-docker-build-chiaki.sh -a 192.168.0.200
bash scripts/switch/push-podman-build-chiaki.sh -a 192.168.0.200
```
Troubleshoot

@ -1 +1 @@
Subproject commit cbdc1b65314d1eeb2799deae5cf6f113d6d67b46
Subproject commit eae1371831d6cebf11b8ebd4c611069bccc6fb9b

View file

@ -67,7 +67,7 @@ class IO
// default nintendo switch res
int screen_width = 1280;
int screen_height = 720;
AVCodec *codec;
const AVCodec *codec;
AVCodecContext *codec_context;
AVFrame *frame;
SDL_AudioDeviceID sdl_audio_device_id = 0;

View file

@ -49,7 +49,7 @@ class Settings
// the goal is to read/write inernal flat configuration file
const std::map<Settings::ConfigurationItem, std::regex> re_map = {
{HOST_NAME, std::regex("^\\[\\s*(.+)\\s*\\]")},
{HOST_ADDR, std::regex("^\\s*host_(?:ip|addr)\\s*=\\s*\"?((\\d+\\.\\d+\\.\\d+\\.\\d+)|([A-Za-z0-9-]{1,255}))\"?")},
{HOST_ADDR, std::regex("^\\s*host_(?:ip|addr)\\s*=\\s*\"?([^\"]*)\"?")},
{PSN_ONLINE_ID, std::regex("^\\s*psn_online_id\\s*=\\s*\"?([\\w_-]+)\"?")},
{PSN_ACCOUNT_ID, std::regex("^\\s*psn_account_id\\s*=\\s*\"?([\\w/=+]+)\"?")},
{RP_KEY, std::regex("^\\s*rp_key\\s*=\\s*\"?([\\w/=+]+)\"?")},
@ -61,7 +61,6 @@ class Settings
};
ConfigurationItem ParseLine(std::string * line, std::string * value);
size_t GetB64encodeSize(size_t);
public:
// singleton configuration

View file

@ -28,8 +28,6 @@ bool appletMainLoop()
// use a custom nintendo switch socket config
// chiaki requiers many threads with udp/tcp sockets
static const SocketInitConfig g_chiakiSocketInitConfig = {
.bsdsockets_version = 1,
.tcp_tx_buf_size = 0x8000,
.tcp_rx_buf_size = 0x10000,
.tcp_tx_buf_max_size = 0x40000,

View file

@ -29,11 +29,7 @@ Settings::ConfigurationItem Settings::ParseLine(std::string *line, std::string *
return UNKNOWN;
}
size_t Settings::GetB64encodeSize(size_t in)
{
// calculate base64 buffer size after encode
return ((4 * in / 3) + 3) & ~3;
}
#define B64_ENCODED_SIZE(in) (((4 * in / 3) + 3) & ~3)
Settings *Settings::instance = nullptr;
@ -458,8 +454,7 @@ std::string Settings::GetHostRPKey(Host *host)
{
if(host->rp_key_data || host->registered)
{
size_t rp_key_b64_sz = this->GetB64encodeSize(0x10);
char rp_key_b64[rp_key_b64_sz + 1] = { 0 };
char rp_key_b64[B64_ENCODED_SIZE(0x10) + 1] = { 0 };
ChiakiErrorCode err;
err = chiaki_base64_encode(
host->rp_key, 0x10,
@ -502,8 +497,7 @@ std::string Settings::GetHostRPRegistKey(Host *host)
{
if(host->rp_key_data || host->registered)
{
size_t rp_regist_key_b64_sz = this->GetB64encodeSize(CHIAKI_SESSION_AUTH_SIZE);
char rp_regist_key_b64[rp_regist_key_b64_sz + 1] = { 0 };
char rp_regist_key_b64[B64_ENCODED_SIZE(CHIAKI_SESSION_AUTH_SIZE) + 1] = { 0 };
ChiakiErrorCode err;
err = chiaki_base64_encode(
(uint8_t *)host->rp_regist_key, CHIAKI_SESSION_AUTH_SIZE,

View file

@ -4,11 +4,13 @@ if(NOT CHIAKI_USE_SYSTEM_NANOPB)
# nanopb
##################
add_definitions(-DPB_C99_STATIC_ASSERT) # Fix PB_STATIC_ASSERT on msvc without using C11 for now
add_subdirectory(nanopb EXCLUDE_FROM_ALL)
set(NANOPB_GENERATOR_PY "${CMAKE_CURRENT_SOURCE_DIR}/nanopb/generator/nanopb_generator.py" PARENT_SCOPE)
add_library(nanopb INTERFACE)
target_link_libraries(nanopb INTERFACE protobuf-nanopb-static)
target_include_directories(nanopb INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/nanopb")
target_compile_definitions(nanopb INTERFACE -DPB_C99_STATIC_ASSERT) # see above
add_library(Nanopb::nanopb ALIAS nanopb)
endif()

2
third-party/nanopb vendored

@ -1 +1 @@
Subproject commit ae9901f2a31500e8fdc93fa9804d24851c58bb1e
Subproject commit afc499f9a410fc9bbf6c9c48cdd8d8b199d49eb4