Compare commits

..

No commits in common. "master" and "v2.0.0" have entirely different histories.

196 changed files with 1963 additions and 5273 deletions

View file

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

View file

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

View file

@ -9,47 +9,38 @@ packages:
- ninja - ninja
- protoc - protoc
- py3-protobuf - py3-protobuf
- py3-setuptools
- opus-dev - opus-dev
- qt5-qtbase-dev - qt5-qtbase-dev
- qt5-qtsvg-dev - qt5-qtsvg-dev
- qt5-qtmultimedia-dev - qt5-qtmultimedia-dev
- ffmpeg-dev - ffmpeg-dev
- sdl2-dev - sdl2-dev
- podman - sdl2-static # this is gone on alpine edge so might be necessary to remove later
- docker
- fuse - fuse
- udev
- argp-standalone
artifacts: artifacts:
- chiaki.nro - chiaki.nro
- Chiaki.AppImage - Chiaki.AppImage
tasks: tasks:
- setup_podman: | - start_docker: |
sudo rc-service udev start sudo service docker start
sudo rc-service cgroups start sudo chmod +s /usr/bin/docker # Yes, I know what I am doing
sudo rc-service fuse start # Fuse for AppImages sudo 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: | - local_build_and_test: |
cd chiaki cd chiaki
cmake -Bbuild -GNinja -DCHIAKI_ENABLE_CLI=ON -DCHIAKI_ENABLE_GUI=ON -DCHIAKI_CLI_ARGP_STANDALONE=ON cmake -Bbuild -GNinja
ninja -C build ninja -C build
build/test/chiaki-unit build/test/chiaki-unit
- appimage: | - appimage: |
cd chiaki cd chiaki
scripts/run-podman-build-appimage.sh scripts/run-docker-build-appimage.sh
cp appimage/Chiaki.AppImage ../Chiaki.AppImage cp appimage/Chiaki.AppImage ../Chiaki.AppImage
- switch: | - switch: |
cd chiaki cd chiaki
scripts/switch/run-podman-build-chiaki.sh scripts/switch/run-docker-build-chiaki.sh
cp build_switch/switch/chiaki.nro ../chiaki.nro cp build_switch/switch/chiaki.nro ../chiaki.nro
- bullseye: | - bullseye: |
cd chiaki cd chiaki
scripts/run-podman-build-bullseye.sh scripts/run-docker-build-bullseye.sh

View file

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

View file

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

2
.gitignore vendored
View file

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

2
.gitmodules vendored
View file

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

View file

@ -24,7 +24,6 @@ endif()
tri_option(CHIAKI_ENABLE_FFMPEG_DECODER "Enable FFMPEG video decoder" ${CHIAKI_FFMPEG_DEFAULT}) 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) 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_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_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_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON)
option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF) option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
@ -32,7 +31,7 @@ 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) tri_option(CHIAKI_USE_SYSTEM_NANOPB "Use system-provided nanopb instead of submodule" AUTO)
set(CHIAKI_VERSION_MAJOR 2) set(CHIAKI_VERSION_MAJOR 2)
set(CHIAKI_VERSION_MINOR 2) set(CHIAKI_VERSION_MINOR 0)
set(CHIAKI_VERSION_PATCH 0) set(CHIAKI_VERSION_PATCH 0)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH}) set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
@ -90,20 +89,6 @@ endif()
if(CHIAKI_LIB_ENABLE_MBEDTLS) if(CHIAKI_LIB_ENABLE_MBEDTLS)
add_definitions(-DCHIAKI_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() endif()
if(CHIAKI_ENABLE_FFMPEG_DECODER) if(CHIAKI_ENABLE_FFMPEG_DECODER)
@ -150,15 +135,7 @@ if(CHIAKI_ENABLE_CLI)
add_subdirectory(cli) add_subdirectory(cli)
endif() endif()
if(CHIAKI_ENABLE_GUI AND CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
find_package(SDL2 MODULE REQUIRED)
endif()
if(CHIAKI_ENABLE_SETSU) if(CHIAKI_ENABLE_SETSU)
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)
else()
find_package(Udev QUIET) find_package(Udev QUIET)
find_package(Evdev QUIET) find_package(Evdev QUIET)
if(Udev_FOUND AND Evdev_FOUND) if(Udev_FOUND AND Evdev_FOUND)
@ -175,7 +152,6 @@ if(CHIAKI_ENABLE_SETSU)
add_subdirectory(setsu) add_subdirectory(setsu)
endif() endif()
endif() endif()
endif()
if(CHIAKI_ENABLE_SETSU) if(CHIAKI_ENABLE_SETSU)
message(STATUS "Setsu enabled") message(STATUS "Setsu enabled")
@ -184,6 +160,7 @@ else()
endif() endif()
if(CHIAKI_ENABLE_GUI) if(CHIAKI_ENABLE_GUI)
#add_subdirectory(setsu)
add_subdirectory(gui) add_subdirectory(gui)
endif() endif()

View file

@ -8,35 +8,33 @@
[![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?) [![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 Chiaki is a Free and Open Source Software Client for PlayStation 4 and PlayStation 5 Remote Play
for Linux, FreeBSD, OpenBSD, NetBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms. for Linux, FreeBSD, OpenBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
## 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 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) ![Screenshot](assets/screenshot.png)
## Features
Everything necessary for a full streaming session, including the initial
registration and wakeup of the console, is supported.
The following features however are yet to be implemented:
* Rumble
* Accelerometer/Gyroscope
## Installing ## Installing
You can either download a pre-built release or build Chiaki from source. You can either download a pre-built release (easier) or build Chiaki from source.
### Downloading a Release ### Downloading a Release
Builds are provided for Linux, Android, macOS, Nintendo Switch and Windows. Builds are provided for Linux, Android, macOS and Windows.
You can download them [here](https://git.sr.ht/~thestr4ng3r/chiaki/refs). 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. * **Linux**: The provided file is an [AppImage](https://appimage.org/). Simply make it executable (`chmod +x <file>.AppImage`) and run it.
* **Android**: Install from [F-Droid](https://f-droid.org/packages/com.metallic.chiaki/) or download the APK from Sourcehut. * **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.
* **macOS**: Drag the application from the `.dmg` into your Applications folder. * **macOS**: Drag the application from the `.dmg` into your Applications folder.
* **Windows**: Extract the `.zip` file and execute `chiaki.exe`. * **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. * **Switch**: Follow README specific [instructions](./switch/README.md)
### Building from Source ### Building from Source
@ -49,8 +47,8 @@ cmake ..
make make
``` ```
For more detailed platform-specific instructions, see [doc/platform-build.md](doc/platform-build.md) or [switch/](./switch/README.md) for Nintendo Switch. For more detailed platform-specific instructions, see [doc/platform-build.md](doc/platform-build.md).
in
## Usage ## Usage
If your Console is on your local network, is turned on or in standby mode and does not have Discovery explicitly disabled, Chiaki should find it. If your Console is on your local network, is turned on or in standby mode and does not have Discovery explicitly disabled, Chiaki should find it.
@ -73,6 +71,13 @@ Settings -> Remote Play -> Add Device, or on a PS5: Settings -> System -> Remote
You can now double-click your Console in Chiaki's main window to start Remote Play. You can now double-click your Console in Chiaki's main window to start Remote Play.
## Joining the Community or Getting Help
There are official groups for Chiaki on Telegram and IRC. They are bridged so you can join whichever you like:
- **Telegram:** https://t.me/chiakitg
- **IRC:** #chiaki on irc.freenode.net
## Acknowledgements ## Acknowledgements
This project has only been made possible because of the following Open Source projects: This project has only been made possible because of the following Open Source projects:

View file

@ -1,6 +1,6 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
def rootCMakeLists = "../../CMakeLists.txt" def rootCMakeLists = "../../CMakeLists.txt"
@ -18,12 +18,13 @@ def chiakiVersion = "$chiakiVersionMajor.$chiakiVersionMinor.$chiakiVersionPatch
println("Determined Chiaki Version: $chiakiVersion") println("Determined Chiaki Version: $chiakiVersion")
android { android {
compileSdkVersion 33 compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig { defaultConfig {
applicationId "com.metallic.chiaki" applicationId "com.metallic.chiaki"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 30
versionCode 12 versionCode 8
versionName chiakiVersion versionName chiakiVersion
externalNativeBuild { externalNativeBuild {
cmake { cmake {
@ -32,16 +33,11 @@ android {
"-DCHIAKI_ENABLE_GUI=OFF", "-DCHIAKI_ENABLE_GUI=OFF",
"-DCHIAKI_ENABLE_SETSU=OFF", "-DCHIAKI_ENABLE_SETSU=OFF",
"-DCHIAKI_ENABLE_ANDROID=ON", "-DCHIAKI_ENABLE_ANDROID=ON",
"-DCHIAKI_ENABLE_FFMPEG_DECODER=OFF",
"-DCHIAKI_ENABLE_PI_DECODER=OFF",
"-DCHIAKI_LIB_ENABLE_OPUS=OFF", "-DCHIAKI_LIB_ENABLE_OPUS=OFF",
"-DCHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT=ON" "-DCHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT=ON"
} }
} }
} }
buildFeatures {
viewBinding true
}
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
@ -51,7 +47,7 @@ android {
} }
externalNativeBuild { externalNativeBuild {
cmake { cmake {
version "3.22.1" version "3.10.2+"
path rootCMakeLists path rootCMakeLists
} }
} }
@ -65,7 +61,6 @@ android {
} }
} }
Properties properties = new Properties() Properties properties = new Properties()
def propertiesFile = file("../local.properties") def propertiesFile = file("../local.properties")
if (propertiesFile.exists()) { if (propertiesFile.exists()) {
@ -91,26 +86,31 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
} }
} }
androidExtensions {
// for @Parcelize
experimental = true
}
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.preference:preference:1.2.0' implementation 'androidx.preference:preference:1.1.0'
implementation 'com.google.android.material:material:1.8.0' implementation 'com.google.android.material:material:1.1.0-beta02'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.5.1' implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.2.0'
implementation "io.reactivex.rxjava2:rxjava:2.2.20" implementation "io.reactivex.rxjava2:rxjava:2.2.12"
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0" implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
def room_version = "2.5.0" def room_version = "2.2.4"
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version" kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version" implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-rxjava2:$room_version" implementation "androidx.room:room-rxjava2:$room_version"
implementation "com.squareup.moshi:moshi:1.14.0" implementation "com.squareup.moshi:moshi:1.9.2"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.14.0" kapt "com.squareup.moshi:moshi-kotlin-codegen:1.9.2"
} }

View file

@ -5,8 +5,6 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <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 <application
android:allowBackup="true" android:allowBackup="true"
@ -29,8 +27,7 @@
</provider> </provider>
<activity android:name=".main.MainActivity" <activity android:name=".main.MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <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)); return E->NewStringUTF(env, chiaki_quit_reason_string((ChiakiQuitReason)value));
} }
JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsError)(JNIEnv *env, jobject obj, jint value) JNIEXPORT jboolean JNICALL JNI_FCN(quitReasonIsStopped)(JNIEnv *env, jobject obj, jint value)
{ {
return chiaki_quit_reason_is_error(value); return value == CHIAKI_QUIT_REASON_STOPPED;
} }
JNIEXPORT jobject JNICALL JNI_FCN(videoProfilePreset)(JNIEnv *env, jobject obj, jint resolution_preset, jint fps_preset, jobject codec) JNIEXPORT jobject JNICALL JNI_FCN(videoProfilePreset)(JNIEnv *env, jobject obj, jint resolution_preset, jint fps_preset, jobject codec)
@ -133,7 +133,6 @@ typedef struct android_chiaki_session_t
jmethodID java_session_event_connected_meth; jmethodID java_session_event_connected_meth;
jmethodID java_session_event_login_pin_request_meth; jmethodID java_session_event_login_pin_request_meth;
jmethodID java_session_event_quit_meth; jmethodID java_session_event_quit_meth;
jmethodID java_session_event_rumble_meth;
jfieldID java_controller_state_buttons; jfieldID java_controller_state_buttons;
jfieldID java_controller_state_l2_state; jfieldID java_controller_state_l2_state;
jfieldID java_controller_state_r2_state; jfieldID java_controller_state_r2_state;
@ -141,20 +140,6 @@ typedef struct android_chiaki_session_t
jfieldID java_controller_state_left_y; jfieldID java_controller_state_left_y;
jfieldID java_controller_state_right_x; jfieldID java_controller_state_right_x;
jfieldID java_controller_state_right_y; jfieldID java_controller_state_right_y;
jfieldID java_controller_state_touches;
jfieldID java_controller_state_gyro_x;
jfieldID java_controller_state_gyro_y;
jfieldID java_controller_state_gyro_z;
jfieldID java_controller_state_accel_x;
jfieldID java_controller_state_accel_y;
jfieldID java_controller_state_accel_z;
jfieldID java_controller_state_orient_x;
jfieldID java_controller_state_orient_y;
jfieldID java_controller_state_orient_z;
jfieldID java_controller_state_orient_w;
jfieldID java_controller_touch_x;
jfieldID java_controller_touch_y;
jfieldID java_controller_touch_id;
AndroidChiakiVideoDecoder video_decoder; AndroidChiakiVideoDecoder video_decoder;
AndroidChiakiAudioDecoder audio_decoder; AndroidChiakiAudioDecoder audio_decoder;
@ -193,14 +178,6 @@ static void android_chiaki_event_cb(ChiakiEvent *event, void *user)
free(reason_str); free(reason_str);
break; break;
} }
case CHIAKI_EVENT_RUMBLE:
E->CallVoidMethod(env, session->java_session,
session->java_session_event_rumble_meth,
(jint)event->rumble.left,
(jint)event->rumble.right);
break;
default:
break;
} }
(*global_vm)->DetachCurrentThread(global_vm); (*global_vm)->DetachCurrentThread(global_vm);
@ -319,7 +296,6 @@ JNIEXPORT void JNICALL JNI_FCN(sessionCreate)(JNIEnv *env, jobject obj, jobject
session->java_session_event_connected_meth = E->GetMethodID(env, session->java_session_class, "eventConnected", "()V"); session->java_session_event_connected_meth = E->GetMethodID(env, session->java_session_class, "eventConnected", "()V");
session->java_session_event_login_pin_request_meth = E->GetMethodID(env, session->java_session_class, "eventLoginPinRequest", "(Z)V"); session->java_session_event_login_pin_request_meth = E->GetMethodID(env, session->java_session_class, "eventLoginPinRequest", "(Z)V");
session->java_session_event_quit_meth = E->GetMethodID(env, session->java_session_class, "eventQuit", "(ILjava/lang/String;)V"); session->java_session_event_quit_meth = E->GetMethodID(env, session->java_session_class, "eventQuit", "(ILjava/lang/String;)V");
session->java_session_event_rumble_meth = E->GetMethodID(env, session->java_session_class, "eventRumble", "(II)V");
jclass controller_state_class = E->FindClass(env, BASE_PACKAGE"/ControllerState"); jclass controller_state_class = E->FindClass(env, BASE_PACKAGE"/ControllerState");
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I"); session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
@ -329,22 +305,6 @@ JNIEXPORT void JNICALL JNI_FCN(sessionCreate)(JNIEnv *env, jobject obj, jobject
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "leftY", "S"); session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "leftY", "S");
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "rightX", "S"); session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "rightX", "S");
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "rightY", "S"); session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "rightY", "S");
session->java_controller_state_touches = E->GetFieldID(env, controller_state_class, "touches", "[L"BASE_PACKAGE"/ControllerTouch;");
session->java_controller_state_gyro_x = E->GetFieldID(env, controller_state_class, "gyroX", "F");
session->java_controller_state_gyro_y = E->GetFieldID(env, controller_state_class, "gyroY", "F");
session->java_controller_state_gyro_z = E->GetFieldID(env, controller_state_class, "gyroZ", "F");
session->java_controller_state_accel_x = E->GetFieldID(env, controller_state_class, "accelX", "F");
session->java_controller_state_accel_y = E->GetFieldID(env, controller_state_class, "accelY", "F");
session->java_controller_state_accel_z = E->GetFieldID(env, controller_state_class, "accelZ", "F");
session->java_controller_state_orient_x = E->GetFieldID(env, controller_state_class, "orientX", "F");
session->java_controller_state_orient_y = E->GetFieldID(env, controller_state_class, "orientY", "F");
session->java_controller_state_orient_z = E->GetFieldID(env, controller_state_class, "orientZ", "F");
session->java_controller_state_orient_w = E->GetFieldID(env, controller_state_class, "orientW", "F");
jclass controller_touch_class = E->FindClass(env, BASE_PACKAGE"/ControllerTouch");
session->java_controller_touch_x = E->GetFieldID(env, controller_touch_class, "x", "S");
session->java_controller_touch_y = E->GetFieldID(env, controller_touch_class, "y", "S");
session->java_controller_touch_id = E->GetFieldID(env, controller_touch_class, "id", "B");
chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session); chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session);
chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder); chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder);
@ -413,8 +373,7 @@ JNIEXPORT void JNICALL JNI_FCN(sessionSetSurface)(JNIEnv *env, jobject obj, jlon
JNIEXPORT void JNICALL JNI_FCN(sessionSetControllerState)(JNIEnv *env, jobject obj, jlong ptr, jobject controller_state_java) JNIEXPORT void JNICALL JNI_FCN(sessionSetControllerState)(JNIEnv *env, jobject obj, jlong ptr, jobject controller_state_java)
{ {
AndroidChiakiSession *session = (AndroidChiakiSession *)ptr; AndroidChiakiSession *session = (AndroidChiakiSession *)ptr;
ChiakiControllerState controller_state; ChiakiControllerState controller_state = { 0 };
chiaki_controller_state_set_idle(&controller_state);
controller_state.buttons = (uint32_t)E->GetIntField(env, controller_state_java, session->java_controller_state_buttons); controller_state.buttons = (uint32_t)E->GetIntField(env, controller_state_java, session->java_controller_state_buttons);
controller_state.l2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_l2_state); controller_state.l2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_l2_state);
controller_state.r2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_r2_state); controller_state.r2_state = (uint8_t)E->GetByteField(env, controller_state_java, session->java_controller_state_r2_state);
@ -422,34 +381,6 @@ JNIEXPORT void JNICALL JNI_FCN(sessionSetControllerState)(JNIEnv *env, jobject o
controller_state.left_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_left_y); controller_state.left_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_left_y);
controller_state.right_x = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_x); controller_state.right_x = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_x);
controller_state.right_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_y); controller_state.right_y = (int16_t)E->GetShortField(env, controller_state_java, session->java_controller_state_right_y);
jobjectArray touch_array = E->GetObjectField(env, controller_state_java, session->java_controller_state_touches);
size_t touch_array_len = (size_t)E->GetArrayLength(env, touch_array);
for(size_t i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
{
if(i < touch_array_len)
{
jobject touch = E->GetObjectArrayElement(env, touch_array, i);
controller_state.touches[i].x = (uint16_t)E->GetShortField(env, touch, session->java_controller_touch_x);
controller_state.touches[i].y = (uint16_t)E->GetShortField(env, touch, session->java_controller_touch_y);
controller_state.touches[i].id = (int8_t)E->GetByteField(env, touch, session->java_controller_touch_id);
}
else
{
controller_state.touches[i].x = 0;
controller_state.touches[i].y = 0;
controller_state.touches[i].id = -1;
}
}
controller_state.gyro_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_x);
controller_state.gyro_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_y);
controller_state.gyro_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_gyro_z);
controller_state.accel_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_x);
controller_state.accel_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_y);
controller_state.accel_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_accel_z);
controller_state.orient_x = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_x);
controller_state.orient_y = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_y);
controller_state.orient_z = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_z);
controller_state.orient_w = E->GetFloatField(env, controller_state_java, session->java_controller_state_orient_w);
chiaki_session_set_controller_state(&session->session, &controller_state); chiaki_session_set_controller_state(&session->session, &controller_state);
} }

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

View file

@ -26,11 +26,13 @@ ChiakiErrorCode android_chiaki_video_decoder_init(AndroidChiakiVideoDecoder *dec
return chiaki_mutex_init(&decoder->codec_mutex, false); return chiaki_mutex_init(&decoder->codec_mutex, false);
} }
static void kill_decoder(AndroidChiakiVideoDecoder *decoder) void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder)
{
if(decoder->codec)
{ {
chiaki_mutex_lock(&decoder->codec_mutex); chiaki_mutex_lock(&decoder->codec_mutex);
decoder->shutdown_output = true; decoder->shutdown_output = true;
ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, 1000); ssize_t codec_buf_index = AMediaCodec_dequeueInputBuffer(decoder->codec, -1);
if(codec_buf_index >= 0) if(codec_buf_index >= 0)
{ {
CHIAKI_LOGI(decoder->log, "Video Decoder sending EOS buffer"); CHIAKI_LOGI(decoder->log, "Video Decoder sending EOS buffer");
@ -46,14 +48,7 @@ static void kill_decoder(AndroidChiakiVideoDecoder *decoder)
chiaki_mutex_unlock(&decoder->codec_mutex); chiaki_mutex_unlock(&decoder->codec_mutex);
} }
AMediaCodec_delete(decoder->codec); AMediaCodec_delete(decoder->codec);
decoder->codec = NULL;
decoder->shutdown_output = false;
} }
void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder)
{
if(decoder->codec)
kill_decoder(decoder);
chiaki_mutex_fini(&decoder->codec_mutex); chiaki_mutex_fini(&decoder->codec_mutex);
} }
@ -61,16 +56,6 @@ void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder
{ {
chiaki_mutex_lock(&decoder->codec_mutex); chiaki_mutex_lock(&decoder->codec_mutex);
if(!surface)
{
if(decoder->codec)
{
kill_decoder(decoder);
CHIAKI_LOGI(decoder->log, "Decoder shut down after surface was removed");
}
return;
}
if(decoder->codec) if(decoder->codec)
{ {
#if __ANDROID_API__ >= 23 #if __ANDROID_API__ >= 23

View file

@ -23,11 +23,9 @@ val MIGRATION_1_2 = object : Migration(1, 2)
{ {
override fun migrate(database: SupportSQLiteDatabase) override fun migrate(database: SupportSQLiteDatabase)
{ {
database.execSQL("ALTER TABLE registered_host RENAME ps4_mac TO server_mac")
database.execSQL("ALTER TABLE registered_host RENAME ps4_nickname TO server_nickname")
database.execSQL("ALTER TABLE registered_host ADD target INTEGER NOT NULL DEFAULT 1000") database.execSQL("ALTER TABLE registered_host ADD target INTEGER NOT NULL DEFAULT 1000")
database.execSQL("CREATE TABLE `new_registered_host` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `target` INTEGER NOT NULL, `ap_ssid` TEXT, `ap_bssid` TEXT, `ap_key` TEXT, `ap_name` TEXT, `server_mac` INTEGER NOT NULL, `server_nickname` TEXT, `rp_regist_key` BLOB NOT NULL, `rp_key_type` INTEGER NOT NULL, `rp_key` BLOB NOT NULL)");
database.execSQL("INSERT INTO `new_registered_host` SELECT `id`, `target`, `ap_ssid`, `ap_bssid`, `ap_key`, `ap_name`, `ps4_mac`, `ps4_nickname`, `rp_regist_key`, `rp_key_type`, `rp_key` FROM `registered_host`")
database.execSQL("DROP TABLE registered_host")
database.execSQL("ALTER TABLE new_registered_host RENAME TO registered_host")
} }
} }

View file

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

View file

@ -68,26 +68,11 @@ class Preferences(context: Context)
get() = sharedPreferences.getBoolean(onScreenControlsEnabledKey, true) get() = sharedPreferences.getBoolean(onScreenControlsEnabledKey, true)
set(value) { sharedPreferences.edit().putBoolean(onScreenControlsEnabledKey, value).apply() } set(value) { sharedPreferences.edit().putBoolean(onScreenControlsEnabledKey, value).apply() }
val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_enabled_key) val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_key)
var touchpadOnlyEnabled var touchpadOnlyEnabled
get() = sharedPreferences.getBoolean(touchpadOnlyEnabledKey, false) get() = sharedPreferences.getBoolean(touchpadOnlyEnabledKey, false)
set(value) { sharedPreferences.edit().putBoolean(touchpadOnlyEnabledKey, value).apply() } set(value) { sharedPreferences.edit().putBoolean(touchpadOnlyEnabledKey, value).apply() }
val rumbleEnabledKey get() = resources.getString(R.string.preferences_rumble_enabled_key)
var rumbleEnabled
get() = sharedPreferences.getBoolean(rumbleEnabledKey, true)
set(value) { sharedPreferences.edit().putBoolean(rumbleEnabledKey, value).apply() }
val motionEnabledKey get() = resources.getString(R.string.preferences_motion_enabled_key)
var motionEnabled
get() = sharedPreferences.getBoolean(motionEnabledKey, true)
set(value) { sharedPreferences.edit().putBoolean(motionEnabledKey, value).apply() }
val buttonHapticEnabledKey get() = resources.getString(R.string.preferences_button_haptic_enabled_key)
var buttonHapticEnabled
get() = sharedPreferences.getBoolean(buttonHapticEnabledKey, true)
set(value) { sharedPreferences.edit().putBoolean(buttonHapticEnabledKey, value).apply() }
val logVerboseKey get() = resources.getString(R.string.preferences_log_verbose_key) val logVerboseKey get() = resources.getString(R.string.preferences_log_verbose_key)
var logVerbose var logVerbose
get() = sharedPreferences.getBoolean(logVerboseKey, false) get() = sharedPreferences.getBoolean(logVerboseKey, false)

View file

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

View file

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

View file

@ -3,7 +3,8 @@ package com.metallic.chiaki.lib
import android.os.Parcelable import android.os.Parcelable
import android.util.Log import android.util.Log
import android.view.Surface import android.view.Surface
import kotlinx.parcelize.Parcelize import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
import java.lang.Exception import java.lang.Exception
import java.net.InetSocketAddress import java.net.InetSocketAddress
import kotlin.math.abs import kotlin.math.abs
@ -83,14 +84,14 @@ private class ChiakiNative
} }
@JvmStatic external fun errorCodeToString(value: Int): String @JvmStatic external fun errorCodeToString(value: Int): String
@JvmStatic external fun quitReasonToString(value: Int): String @JvmStatic external fun quitReasonToString(value: Int): String
@JvmStatic external fun quitReasonIsError(value: Int): Boolean @JvmStatic external fun quitReasonIsStopped(value: Int): Boolean
@JvmStatic external fun videoProfilePreset(resolutionPreset: Int, fpsPreset: Int, codec: Codec): ConnectVideoProfile @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 sessionCreate(result: CreateResult, connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean, javaSession: Session)
@JvmStatic external fun sessionFree(ptr: Long) @JvmStatic external fun sessionFree(ptr: Long)
@JvmStatic external fun sessionStart(ptr: Long): Int @JvmStatic external fun sessionStart(ptr: Long): Int
@JvmStatic external fun sessionStop(ptr: Long): Int @JvmStatic external fun sessionStop(ptr: Long): Int
@JvmStatic external fun sessionJoin(ptr: Long): Int @JvmStatic external fun sessionJoin(ptr: Long): Int
@JvmStatic external fun sessionSetSurface(ptr: Long, surface: Surface?) @JvmStatic external fun sessionSetSurface(ptr: Long, surface: Surface)
@JvmStatic external fun sessionSetControllerState(ptr: Long, controllerState: ControllerState) @JvmStatic external fun sessionSetControllerState(ptr: Long, controllerState: ControllerState)
@JvmStatic external fun sessionSetLoginPin(ptr: Long, pin: String) @JvmStatic external fun sessionSetLoginPin(ptr: Long, pin: String)
@JvmStatic external fun discoveryServiceCreate(result: CreateResult, options: DiscoveryServiceOptions, javaService: DiscoveryService) @JvmStatic external fun discoveryServiceCreate(result: CreateResult, options: DiscoveryServiceOptions, javaService: DiscoveryService)
@ -149,14 +150,6 @@ class ChiakiLog(val levelMask: Int, val callback: (level: Int, text: String) ->
private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b
private val CONTROLLER_TOUCHES_MAX = 2 // must be the same as CHIAKI_CONTROLLER_TOUCHES_MAX
data class ControllerTouch(
var x: UShort = 0U,
var y: UShort = 0U,
var id: Byte = -1 // -1 = up
)
data class ControllerState constructor( data class ControllerState constructor(
var buttons: UInt = 0U, var buttons: UInt = 0U,
var l2State: UByte = 0U, var l2State: UByte = 0U,
@ -164,19 +157,7 @@ data class ControllerState constructor(
var leftX: Short = 0, var leftX: Short = 0,
var leftY: Short = 0, var leftY: Short = 0,
var rightX: Short = 0, var rightX: Short = 0,
var rightY: Short = 0, var rightY: Short = 0
private var touchIdNext: UByte = 0U,
var touches: Array<ControllerTouch> = arrayOf(ControllerTouch(), ControllerTouch()),
var gyroX: Float = 0.0f,
var gyroY: Float = 0.0f,
var gyroZ: Float = 0.0f,
var accelX: Float = 0.0f,
var accelY: Float = 1.0f,
var accelZ: Float = 0.0f,
var orientX: Float = 0.0f,
var orientY: Float = 0.0f,
var orientZ: Float = 0.0f,
var orientW: Float = 1.0f
){ ){
companion object companion object
{ {
@ -196,8 +177,6 @@ data class ControllerState constructor(
val BUTTON_SHARE = (1 shl 13).toUInt() val BUTTON_SHARE = (1 shl 13).toUInt()
val BUTTON_TOUCHPAD = (1 shl 14).toUInt() val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
val BUTTON_PS = (1 shl 15).toUInt() val BUTTON_PS = (1 shl 15).toUInt()
val TOUCHPAD_WIDTH: UShort = 1920U
val TOUCHPAD_HEIGHT: UShort = 942U
} }
infix fun or(o: ControllerState) = ControllerState( infix fun or(o: ControllerState) = ControllerState(
@ -207,116 +186,24 @@ data class ControllerState constructor(
leftX = maxAbs(leftX, o.leftX), leftX = maxAbs(leftX, o.leftX),
leftY = maxAbs(leftY, o.leftY), leftY = maxAbs(leftY, o.leftY),
rightX = maxAbs(rightX, o.rightX), rightX = maxAbs(rightX, o.rightX),
rightY = maxAbs(rightY, o.rightY), rightY = maxAbs(rightY, o.rightY)
touches = touches.zip(o.touches) { a, b -> if(a.id >= 0) a else b }.toTypedArray(),
gyroX = gyroX,
gyroY = gyroY,
gyroZ = gyroZ,
accelX = accelX,
accelY = accelY,
accelZ = accelZ,
orientX = orientX,
orientY = orientY,
orientZ = orientZ,
orientW = orientW
) )
override fun equals(other: Any?): Boolean
{
if(this === other) return true
if(javaClass != other?.javaClass) return false
other as ControllerState
if(buttons != other.buttons) return false
if(l2State != other.l2State) return false
if(r2State != other.r2State) return false
if(leftX != other.leftX) return false
if(leftY != other.leftY) return false
if(rightX != other.rightX) return false
if(rightY != other.rightY) return false
if(touchIdNext != other.touchIdNext) return false
if(!touches.contentEquals(other.touches)) return false
if(gyroX != other.gyroX) return false
if(gyroY != other.gyroY) return false
if(gyroZ != other.gyroZ) return false
if(accelX != other.accelX) return false
if(accelY != other.accelY) return false
if(accelZ != other.accelZ) return false
if(orientX != other.orientX) return false
if(orientY != other.orientY) return false
if(orientZ != other.orientZ) return false
if(orientW != other.orientW) return false
return true
}
override fun hashCode(): Int
{
var result = buttons.hashCode()
result = 31 * result + l2State.hashCode()
result = 31 * result + r2State.hashCode()
result = 31 * result + leftX
result = 31 * result + leftY
result = 31 * result + rightX
result = 31 * result + rightY
result = 31 * result + touchIdNext.hashCode()
result = 31 * result + touches.contentHashCode()
result = 31 * result + gyroX.hashCode()
result = 31 * result + gyroY.hashCode()
result = 31 * result + gyroZ.hashCode()
result = 31 * result + accelX.hashCode()
result = 31 * result + accelY.hashCode()
result = 31 * result + accelZ.hashCode()
result = 31 * result + orientX.hashCode()
result = 31 * result + orientY.hashCode()
result = 31 * result + orientZ.hashCode()
result = 31 * result + orientW.hashCode()
return result
}
fun startTouch(x: UShort, y: UShort): UByte? =
touches
.find { it.id < 0 }
?.also {
it.id = touchIdNext.toByte()
it.x = x
it.y = y
touchIdNext = ((touchIdNext + 1U) and 0x7fU).toUByte()
}?.id?.toUByte()
fun stopTouch(id: UByte)
{
touches.find {
it.id >= 0 && it.id == id.toByte()
}?.let {
it.id = -1
}
}
fun setTouchPos(id: UByte, x: UShort, y: UShort): Boolean
= touches.find {
it.id >= 0 && it.id == id.toByte()
}?.let {
val r = it.x != x || it.y != y
it.x = x
it.y = y
r
} ?: false
} }
class QuitReason(val value: Int) class QuitReason(val value: Int)
{ {
override fun toString() = ChiakiNative.quitReasonToString(value) override fun toString() = ChiakiNative.quitReasonToString(value)
val isError = ChiakiNative.quitReasonIsError(value) /**
* whether the reason is CHIAKI_QUIT_REASON_STOPPED
*/
val isStopped = ChiakiNative.quitReasonIsStopped(value)
} }
sealed class Event sealed class Event
object ConnectedEvent: Event() object ConnectedEvent: Event()
data class LoginPinRequestEvent(val pinIncorrect: Boolean): Event() data class LoginPinRequestEvent(val pinIncorrect: Boolean): Event()
data class QuitEvent(val reason: QuitReason, val reasonString: String?): Event() data class QuitEvent(val reason: QuitReason, val reasonString: String?): Event()
data class RumbleEvent(val left: UByte, val right: UByte): Event()
class CreateError(val errorCode: ErrorCode): Exception("Failed to create a native object: $errorCode") class CreateError(val errorCode: ErrorCode): Exception("Failed to create a native object: $errorCode")
@ -372,12 +259,7 @@ class Session(connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean)
event(QuitEvent(QuitReason(reasonValue), reasonString)) event(QuitEvent(QuitReason(reasonValue), reasonString))
} }
private fun eventRumble(left: Int, right: Int) fun setSurface(surface: Surface)
{
event(RumbleEvent(left.toUByte(), right.toUByte()))
}
fun setSurface(surface: Surface?)
{ {
ChiakiNative.sessionSetSurface(nativePtr, surface) ChiakiNative.sessionSetSurface(nativePtr, surface)
} }

View file

@ -3,7 +3,6 @@
package com.metallic.chiaki.main package com.metallic.chiaki.main
import android.util.Log import android.util.Log
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
@ -17,8 +16,8 @@ import com.metallic.chiaki.common.DiscoveredDisplayHost
import com.metallic.chiaki.common.DisplayHost import com.metallic.chiaki.common.DisplayHost
import com.metallic.chiaki.common.ManualDisplayHost import com.metallic.chiaki.common.ManualDisplayHost
import com.metallic.chiaki.common.ext.inflate import com.metallic.chiaki.common.ext.inflate
import com.metallic.chiaki.databinding.ItemDisplayHostBinding
import com.metallic.chiaki.lib.DiscoveryHost import com.metallic.chiaki.lib.DiscoveryHost
import kotlinx.android.synthetic.main.item_display_host.view.*
class DisplayHostDiffCallback(val old: List<DisplayHost>, val new: List<DisplayHost>): DiffUtil.Callback() class DisplayHostDiffCallback(val old: List<DisplayHost>, val new: List<DisplayHost>): DiffUtil.Callback()
{ {
@ -43,10 +42,10 @@ class DisplayHostRecyclerViewAdapter(
diff.dispatchUpdatesTo(this) diff.dispatchUpdatesTo(this)
} }
class ViewHolder(val binding: ItemDisplayHostBinding): RecyclerView.ViewHolder(binding.root) class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
= ViewHolder(ItemDisplayHostBinding.inflate(LayoutInflater.from(parent.context), parent, false)) = ViewHolder(parent.inflate(R.layout.item_display_host))
override fun getItemCount() = hosts.count() override fun getItemCount() = hosts.count()
@ -54,7 +53,7 @@ class DisplayHostRecyclerViewAdapter(
{ {
val context = holder.itemView.context val context = holder.itemView.context
val host = hosts[position] val host = hosts[position]
holder.binding.also { holder.itemView.also {
it.nameTextView.text = host.name it.nameTextView.text = host.name
it.hostTextView.text = context.getString(R.string.display_host_host, host.host) it.hostTextView.text = context.getString(R.string.display_host_host, host.host)
val id = host.id val id = host.id
@ -88,7 +87,7 @@ class DisplayHostRecyclerViewAdapter(
else -> R.drawable.ic_console else -> R.drawable.ic_console
} }
) )
it.root.setOnClickListener { clickCallback(host) } it.setOnClickListener { clickCallback(host) }
val canWakeup = host.registeredHost != null val canWakeup = host.registeredHost != null
val canEditDelete = host is ManualDisplayHost val canEditDelete = host is ManualDisplayHost

View file

@ -17,54 +17,52 @@ import com.metallic.chiaki.R
import com.metallic.chiaki.common.* import com.metallic.chiaki.common.*
import com.metallic.chiaki.common.ext.putRevealExtra import com.metallic.chiaki.common.ext.putRevealExtra
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.databinding.ActivityMainBinding
import com.metallic.chiaki.lib.ConnectInfo import com.metallic.chiaki.lib.ConnectInfo
import com.metallic.chiaki.lib.DiscoveryHost import com.metallic.chiaki.lib.DiscoveryHost
import com.metallic.chiaki.manualconsole.EditManualConsoleActivity import com.metallic.chiaki.manualconsole.EditManualConsoleActivity
import com.metallic.chiaki.regist.RegistActivity import com.metallic.chiaki.regist.RegistActivity
import com.metallic.chiaki.settings.SettingsActivity import com.metallic.chiaki.settings.SettingsActivity
import com.metallic.chiaki.stream.StreamActivity import com.metallic.chiaki.stream.StreamActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() class MainActivity : AppCompatActivity()
{ {
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var binding: ActivityMainBinding
private var discoveryMenuItem: MenuItem? = null private var discoveryMenuItem: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) setContentView(R.layout.activity_main)
setContentView(binding.root)
title = "" title = ""
setSupportActionBar(binding.toolbar) setSupportActionBar(toolbar)
binding.floatingActionButton.setOnClickListener { floatingActionButton.setOnClickListener {
expandFloatingActionButton(!binding.floatingActionButton.isExpanded) expandFloatingActionButton(!floatingActionButton.isExpanded)
} }
binding.floatingActionButtonDialBackground.setOnClickListener { floatingActionButtonDialBackground.setOnClickListener {
expandFloatingActionButton(false) expandFloatingActionButton(false)
} }
binding.addManualButton.setOnClickListener { addManualConsole() } addManualButton.setOnClickListener { addManualConsole() }
binding.addManualLabelButton.setOnClickListener { addManualConsole() } addManualLabelButton.setOnClickListener { addManualConsole() }
binding.registerButton.setOnClickListener { showRegistration() } registerButton.setOnClickListener { showRegistration() }
binding.registerLabelButton.setOnClickListener { showRegistration() } registerLabelButton.setOnClickListener { showRegistration() }
viewModel = ViewModelProvider(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) }) viewModel = ViewModelProvider(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) })
.get(MainViewModel::class.java) .get(MainViewModel::class.java)
val recyclerViewAdapter = DisplayHostRecyclerViewAdapter(this::hostTriggered, this::wakeupHost, this::editHost, this::deleteHost) val recyclerViewAdapter = DisplayHostRecyclerViewAdapter(this::hostTriggered, this::wakeupHost, this::editHost, this::deleteHost)
binding.hostsRecyclerView.adapter = recyclerViewAdapter hostsRecyclerView.adapter = recyclerViewAdapter
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(this) hostsRecyclerView.layoutManager = LinearLayoutManager(this)
viewModel.displayHosts.observe(this, Observer { viewModel.displayHosts.observe(this, Observer {
val top = binding.hostsRecyclerView.computeVerticalScrollOffset() == 0 val top = hostsRecyclerView.computeVerticalScrollOffset() == 0
recyclerViewAdapter.hosts = it recyclerViewAdapter.hosts = it
if(top) if(top)
binding.hostsRecyclerView.scrollToPosition(0) hostsRecyclerView.scrollToPosition(0)
updateEmptyInfo() updateEmptyInfo()
}) })
@ -78,19 +76,19 @@ class MainActivity : AppCompatActivity()
{ {
if(viewModel.displayHosts.value?.isEmpty() ?: true) if(viewModel.displayHosts.value?.isEmpty() ?: true)
{ {
binding.emptyInfoLayout.visibility = View.VISIBLE emptyInfoLayout.visibility = View.VISIBLE
val discoveryActive = viewModel.discoveryActive.value ?: false val discoveryActive = viewModel.discoveryActive.value ?: false
binding.emptyInfoImageView.setImageResource(if(discoveryActive) R.drawable.ic_discover_on else R.drawable.ic_discover_off) emptyInfoImageView.setImageResource(if(discoveryActive) R.drawable.ic_discover_on else R.drawable.ic_discover_off)
binding.emptyInfoTextView.setText(if(discoveryActive) R.string.display_hosts_empty_discovery_on_info else R.string.display_hosts_empty_discovery_off_info) emptyInfoTextView.setText(if(discoveryActive) R.string.display_hosts_empty_discovery_on_info else R.string.display_hosts_empty_discovery_off_info)
} }
else else
binding.emptyInfoLayout.visibility = View.GONE emptyInfoLayout.visibility = View.GONE
} }
private fun expandFloatingActionButton(expand: Boolean) private fun expandFloatingActionButton(expand: Boolean)
{ {
binding.floatingActionButton.isExpanded = expand floatingActionButton.isExpanded = expand
binding.floatingActionButton.isActivated = binding.floatingActionButton.isExpanded floatingActionButton.isActivated = floatingActionButton.isExpanded
} }
override fun onStart() override fun onStart()
@ -107,7 +105,7 @@ class MainActivity : AppCompatActivity()
override fun onBackPressed() override fun onBackPressed()
{ {
if(binding.floatingActionButton.isExpanded) if(floatingActionButton.isExpanded)
{ {
expandFloatingActionButton(false) expandFloatingActionButton(false)
return return
@ -153,7 +151,7 @@ class MainActivity : AppCompatActivity()
private fun addManualConsole() private fun addManualConsole()
{ {
Intent(this, EditManualConsoleActivity::class.java).also { Intent(this, EditManualConsoleActivity::class.java).also {
it.putRevealExtra(binding.addManualButton, binding.rootLayout) it.putRevealExtra(addManualButton, rootLayout)
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()) startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
} }
} }
@ -161,7 +159,7 @@ class MainActivity : AppCompatActivity()
private fun showRegistration() private fun showRegistration()
{ {
Intent(this, RegistActivity::class.java).also { Intent(this, RegistActivity::class.java).also {
it.putRevealExtra(binding.registerButton, binding.rootLayout) it.putRevealExtra(registerButton, rootLayout)
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()) startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
} }
} }

View file

@ -16,10 +16,10 @@ import com.metallic.chiaki.common.RegisteredHost
import com.metallic.chiaki.common.ext.RevealActivity import com.metallic.chiaki.common.ext.RevealActivity
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.databinding.ActivityEditManualBinding
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.addTo
import kotlinx.android.synthetic.main.activity_edit_manual.*
class EditManualConsoleActivity: AppCompatActivity(), RevealActivity class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
{ {
@ -28,20 +28,18 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
const val EXTRA_MANUAL_HOST_ID = "manual_host_id" const val EXTRA_MANUAL_HOST_ID = "manual_host_id"
} }
private lateinit var viewModel: EditManualConsoleViewModel
private lateinit var binding: ActivityEditManualBinding
override val revealIntent: Intent get() = intent override val revealIntent: Intent get() = intent
override val revealRootLayout: View get() = binding.rootLayout override val revealRootLayout: View get() = rootLayout
override val revealWindow: Window get() = window override val revealWindow: Window get() = window
private lateinit var viewModel: EditManualConsoleViewModel
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityEditManualBinding.inflate(layoutInflater) setContentView(R.layout.activity_edit_manual)
setContentView(binding.root)
handleReveal() handleReveal()
viewModel = ViewModelProvider(this, viewModelFactory { viewModel = ViewModelProvider(this, viewModelFactory {
@ -54,17 +52,17 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
.get(EditManualConsoleViewModel::class.java) .get(EditManualConsoleViewModel::class.java)
viewModel.existingHost?.observe(this, Observer { viewModel.existingHost?.observe(this, Observer {
binding.hostEditText.setText(it.host) hostEditText.setText(it.host)
}) })
viewModel.selectedRegisteredHost.observe(this, Observer { viewModel.selectedRegisteredHost.observe(this, Observer {
binding.registeredHostTextView.setText(titleForRegisteredHost(it)) registeredHostTextView.setText(titleForRegisteredHost(it))
}) })
viewModel.registeredHosts.observe(this, Observer { hosts -> viewModel.registeredHosts.observe(this, Observer { hosts ->
binding.registeredHostTextView.setAdapter(ArrayAdapter<String>(this, R.layout.dropdown_menu_popup_item, registeredHostTextView.setAdapter(ArrayAdapter<String>(this, R.layout.dropdown_menu_popup_item,
hosts.map { titleForRegisteredHost(it) })) hosts.map { titleForRegisteredHost(it) }))
binding.registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener { registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener {
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
{ {
if(position >= hosts.size) if(position >= hosts.size)
@ -75,7 +73,8 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
} }
}) })
binding.saveButton.setOnClickListener { saveHost() }
saveButton.setOnClickListener { saveHost() }
} }
private fun titleForRegisteredHost(registeredHost: RegisteredHost?) = private fun titleForRegisteredHost(registeredHost: RegisteredHost?) =
@ -86,14 +85,14 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
private fun saveHost() private fun saveHost()
{ {
val host = binding.hostEditText.text.toString().trim() val host = hostEditText.text.toString().trim()
if(host.isEmpty()) if(host.isEmpty())
{ {
binding.hostEditText.error = getString(R.string.entered_host_invalid) hostEditText.error = getString(R.string.entered_host_invalid)
return return
} }
binding.saveButton.isEnabled = false saveButton.isEnabled = false
viewModel.saveHost(host) viewModel.saveHost(host)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { .subscribe {

View file

@ -12,9 +12,9 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.metallic.chiaki.R import com.metallic.chiaki.R
import com.metallic.chiaki.common.ext.RevealActivity import com.metallic.chiaki.common.ext.RevealActivity
import com.metallic.chiaki.databinding.ActivityRegistBinding
import com.metallic.chiaki.lib.RegistInfo import com.metallic.chiaki.lib.RegistInfo
import com.metallic.chiaki.lib.Target import com.metallic.chiaki.lib.Target
import kotlinx.android.synthetic.main.activity_regist.*
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
class RegistActivity: AppCompatActivity(), RevealActivity class RegistActivity: AppCompatActivity(), RevealActivity
@ -30,35 +30,33 @@ class RegistActivity: AppCompatActivity(), RevealActivity
private const val REQUEST_REGIST = 1 private const val REQUEST_REGIST = 1
} }
private lateinit var viewModel: RegistViewModel
private lateinit var binding: ActivityRegistBinding
override val revealWindow: Window get() = window override val revealWindow: Window get() = window
override val revealIntent: Intent get() = intent override val revealIntent: Intent get() = intent
override val revealRootLayout: View get() = binding.rootLayout override val revealRootLayout: View get() = rootLayout
private lateinit var viewModel: RegistViewModel
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityRegistBinding.inflate(layoutInflater) setContentView(R.layout.activity_regist)
setContentView(binding.root)
handleReveal() handleReveal()
viewModel = ViewModelProvider(this).get(RegistViewModel::class.java) viewModel = ViewModelProvider(this).get(RegistViewModel::class.java)
binding.hostEditText.setText(intent.getStringExtra(EXTRA_HOST) ?: "255.255.255.255") hostEditText.setText(intent.getStringExtra(EXTRA_HOST) ?: "255.255.255.255")
binding.broadcastCheckBox.isChecked = intent.getBooleanExtra(EXTRA_BROADCAST, true) broadcastCheckBox.isChecked = intent.getBooleanExtra(EXTRA_BROADCAST, true)
binding.registButton.setOnClickListener { doRegist() } registButton.setOnClickListener { doRegist() }
binding.ps4VersionRadioGroup.check(when(viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5) { ps4VersionRadioGroup.check(when(viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5) {
RegistViewModel.ConsoleVersion.PS5 -> R.id.ps5RadioButton RegistViewModel.ConsoleVersion.PS5 -> R.id.ps5RadioButton
RegistViewModel.ConsoleVersion.PS4_GE_8 -> R.id.ps4VersionGE8RadioButton RegistViewModel.ConsoleVersion.PS4_GE_8 -> R.id.ps4VersionGE8RadioButton
RegistViewModel.ConsoleVersion.PS4_GE_7 -> R.id.ps4VersionGE7RadioButton RegistViewModel.ConsoleVersion.PS4_GE_7 -> R.id.ps4VersionGE7RadioButton
RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.id.ps4VersionLT7RadioButton RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.id.ps4VersionLT7RadioButton
}) })
binding.ps4VersionRadioGroup.setOnCheckedChangeListener { _, checkedId -> ps4VersionRadioGroup.setOnCheckedChangeListener { _, checkedId ->
viewModel.ps4Version.value = when(checkedId) viewModel.ps4Version.value = when(checkedId)
{ {
R.id.ps5RadioButton -> RegistViewModel.ConsoleVersion.PS5 R.id.ps5RadioButton -> RegistViewModel.ConsoleVersion.PS5
@ -70,14 +68,14 @@ class RegistActivity: AppCompatActivity(), RevealActivity
} }
viewModel.ps4Version.observe(this, Observer { viewModel.ps4Version.observe(this, Observer {
binding.psnAccountIdHelpGroup.visibility = if(it == RegistViewModel.ConsoleVersion.PS4_LT_7) View.GONE else View.VISIBLE psnAccountIdHelpGroup.visibility = if(it == RegistViewModel.ConsoleVersion.PS4_LT_7) View.GONE else View.VISIBLE
binding.psnIdTextInputLayout.hint = getString(when(it!!) psnIdTextInputLayout.hint = getString(when(it!!)
{ {
RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.string.hint_regist_psn_online_id RegistViewModel.ConsoleVersion.PS4_LT_7 -> R.string.hint_regist_psn_online_id
else -> R.string.hint_regist_psn_account_id else -> R.string.hint_regist_psn_account_id
}) })
binding.pinHelpBeforeTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_before else R.string.regist_pin_instructions_ps4_before) pinHelpBeforeTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_before else R.string.regist_pin_instructions_ps4_before)
binding.pinHelpNavigationTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_navigation else R.string.regist_pin_instructions_ps4_navigation) pinHelpNavigationTextView.setText(if(it.isPS5) R.string.regist_pin_instructions_ps5_navigation else R.string.regist_pin_instructions_ps4_navigation)
}) })
} }
@ -85,11 +83,11 @@ class RegistActivity: AppCompatActivity(), RevealActivity
{ {
val ps4Version = viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5 val ps4Version = viewModel.ps4Version.value ?: RegistViewModel.ConsoleVersion.PS5
val host = binding.hostEditText.text.toString().trim() val host = hostEditText.text.toString().trim()
val hostValid = host.isNotEmpty() val hostValid = host.isNotEmpty()
val broadcast = binding.broadcastCheckBox.isChecked val broadcast = broadcastCheckBox.isChecked
val psnId = binding.psnIdEditText.text.toString().trim() val psnId = psnIdEditText.text.toString().trim()
val psnOnlineId: String? = if(ps4Version == RegistViewModel.ConsoleVersion.PS4_LT_7) psnId else null val psnOnlineId: String? = if(ps4Version == RegistViewModel.ConsoleVersion.PS4_LT_7) psnId else null
val psnAccountId: ByteArray? = val psnAccountId: ByteArray? =
if(ps4Version != RegistViewModel.ConsoleVersion.PS4_LT_7) if(ps4Version != RegistViewModel.ConsoleVersion.PS4_LT_7)
@ -103,11 +101,11 @@ class RegistActivity: AppCompatActivity(), RevealActivity
} }
val pin = binding.pinEditText.text.toString() val pin = pinEditText.text.toString()
val pinValid = pin.length == PIN_LENGTH val pinValid = pin.length == PIN_LENGTH
binding.hostEditText.error = if(!hostValid) getString(R.string.entered_host_invalid) else null hostEditText.error = if(!hostValid) getString(R.string.entered_host_invalid) else null
binding.psnIdEditText.error = psnIdEditText.error =
if(!psnIdValid) if(!psnIdValid)
getString(when(ps4Version) getString(when(ps4Version)
{ {
@ -116,7 +114,7 @@ class RegistActivity: AppCompatActivity(), RevealActivity
}) })
else else
null null
binding.pinEditText.error = if(!pinValid) getString(R.string.regist_pin_invalid, PIN_LENGTH) else null pinEditText.error = if(!pinValid) getString(R.string.regist_pin_invalid, PIN_LENGTH) else null
if(!hostValid || !psnIdValid || !pinValid) if(!hostValid || !psnIdValid || !pinValid)
return return

View file

@ -16,8 +16,8 @@ import com.metallic.chiaki.R
import com.metallic.chiaki.common.MacAddress import com.metallic.chiaki.common.MacAddress
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.databinding.ActivityRegistExecuteBinding
import com.metallic.chiaki.lib.RegistInfo import com.metallic.chiaki.lib.RegistInfo
import kotlinx.android.synthetic.main.activity_regist_execute.*
import kotlin.math.max import kotlin.math.max
class RegistExecuteActivity: AppCompatActivity() class RegistExecuteActivity: AppCompatActivity()
@ -31,57 +31,55 @@ class RegistExecuteActivity: AppCompatActivity()
} }
private lateinit var viewModel: RegistExecuteViewModel private lateinit var viewModel: RegistExecuteViewModel
private lateinit var binding: ActivityRegistExecuteBinding
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityRegistExecuteBinding.inflate(layoutInflater) setContentView(R.layout.activity_regist_execute)
setContentView(binding.root)
viewModel = ViewModelProvider(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) }) viewModel = ViewModelProvider(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) })
.get(RegistExecuteViewModel::class.java) .get(RegistExecuteViewModel::class.java)
binding.logTextView.setHorizontallyScrolling(true) logTextView.setHorizontallyScrolling(true)
binding.logTextView.movementMethod = ScrollingMovementMethod() logTextView.movementMethod = ScrollingMovementMethod()
viewModel.logText.observe(this, Observer { viewModel.logText.observe(this, Observer {
val textLayout = binding.logTextView.layout ?: return@Observer val textLayout = logTextView.layout ?: return@Observer
val lineCount = textLayout.lineCount val lineCount = textLayout.lineCount
if(lineCount < 1) if(lineCount < 1)
return@Observer return@Observer
binding.logTextView.text = it logTextView.text = it
val scrollY = textLayout.getLineBottom(lineCount - 1) - binding.logTextView.height + binding.logTextView.paddingTop + binding.logTextView.paddingBottom val scrollY = textLayout.getLineBottom(lineCount - 1) - logTextView.height + logTextView.paddingTop + logTextView.paddingBottom
binding.logTextView.scrollTo(0, max(scrollY, 0)) logTextView.scrollTo(0, max(scrollY, 0))
}) })
viewModel.state.observe(this, Observer { viewModel.state.observe(this, Observer {
binding.progressBar.visibility = if(it == RegistExecuteViewModel.State.RUNNING) View.VISIBLE else View.GONE progressBar.visibility = if(it == RegistExecuteViewModel.State.RUNNING) View.VISIBLE else View.GONE
when(it) when(it)
{ {
RegistExecuteViewModel.State.FAILED -> RegistExecuteViewModel.State.FAILED ->
{ {
binding.infoTextView.visibility = View.VISIBLE infoTextView.visibility = View.VISIBLE
binding.infoTextView.setText(R.string.regist_info_failed) infoTextView.setText(R.string.regist_info_failed)
setResult(RESULT_FAILED) setResult(RESULT_FAILED)
} }
RegistExecuteViewModel.State.SUCCESSFUL, RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE -> RegistExecuteViewModel.State.SUCCESSFUL, RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE ->
{ {
binding.infoTextView.visibility = View.VISIBLE infoTextView.visibility = View.VISIBLE
binding.infoTextView.setText(R.string.regist_info_success) infoTextView.setText(R.string.regist_info_success)
setResult(RESULT_OK) setResult(RESULT_OK)
if(it == RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE) if(it == RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE)
showDuplicateDialog() showDuplicateDialog()
} }
RegistExecuteViewModel.State.STOPPED -> RegistExecuteViewModel.State.STOPPED ->
{ {
binding.infoTextView.visibility = View.GONE infoTextView.visibility = View.GONE
setResult(Activity.RESULT_CANCELED) setResult(Activity.RESULT_CANCELED)
} }
else -> binding.infoTextView.visibility = View.GONE else -> infoTextView.visibility = View.GONE
} }
}) })
binding.shareLogButton.setOnClickListener { shareLogButton.setOnClickListener {
val log = viewModel.logText.value ?: "" val log = viewModel.logText.value ?: ""
Intent(Intent.ACTION_SEND).also { Intent(Intent.ACTION_SEND).also {
it.type = "text/plain" it.type = "text/plain"

View file

@ -1,37 +1,19 @@
package com.metallic.chiaki.session package com.metallic.chiaki.session
import android.content.Context import android.util.Log
import android.hardware.* import android.view.InputDevice
import android.view.* import android.view.KeyEvent
import androidx.lifecycle.Lifecycle import android.view.MotionEvent
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import com.metallic.chiaki.common.Preferences import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.lib.ControllerState import com.metallic.chiaki.lib.ControllerState
class StreamInput(val context: Context, val preferences: Preferences) class StreamInput(val preferences: Preferences)
{ {
var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null
val controllerState: ControllerState get() val controllerState: ControllerState get()
{ {
val controllerState = sensorControllerState or keyControllerState or motionControllerState val controllerState = keyControllerState or motionControllerState
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
@Suppress("DEPRECATION")
when(windowManager.defaultDisplay.rotation)
{
Surface.ROTATION_90 -> {
controllerState.accelX *= -1.0f
controllerState.accelZ *= -1.0f
controllerState.gyroX *= -1.0f
controllerState.gyroZ *= -1.0f
controllerState.orientX *= -1.0f
controllerState.orientZ *= -1.0f
}
else -> {}
}
// prioritize motion controller's l2 and r2 over key // prioritize motion controller's l2 and r2 over key
// (some controllers send only key, others both but key earlier than full press) // (some controllers send only key, others both but key earlier than full press)
@ -43,7 +25,6 @@ class StreamInput(val context: Context, val preferences: Preferences)
return controllerState or touchControllerState return controllerState or touchControllerState
} }
private val sensorControllerState = ControllerState() // from Motion Sensors
private val keyControllerState = ControllerState() // from KeyEvents private val keyControllerState = ControllerState() // from KeyEvents
private val motionControllerState = ControllerState() // from MotionEvents private val motionControllerState = ControllerState() // from MotionEvents
var touchControllerState = ControllerState() var touchControllerState = ControllerState()
@ -55,66 +36,6 @@ class StreamInput(val context: Context, val preferences: Preferences)
private val swapCrossMoon = preferences.swapCrossMoon private val swapCrossMoon = preferences.swapCrossMoon
private val sensorEventListener = object: SensorEventListener {
override fun onSensorChanged(event: SensorEvent)
{
when(event.sensor.type)
{
Sensor.TYPE_ACCELEROMETER -> {
sensorControllerState.accelX = event.values[1] / SensorManager.GRAVITY_EARTH
sensorControllerState.accelY = event.values[2] / SensorManager.GRAVITY_EARTH
sensorControllerState.accelZ = event.values[0] / SensorManager.GRAVITY_EARTH
}
Sensor.TYPE_GYROSCOPE -> {
sensorControllerState.gyroX = event.values[1]
sensorControllerState.gyroY = event.values[2]
sensorControllerState.gyroZ = event.values[0]
}
Sensor.TYPE_ROTATION_VECTOR -> {
val q = floatArrayOf(0f, 0f, 0f, 0f)
SensorManager.getQuaternionFromVector(q, event.values)
sensorControllerState.orientX = q[2]
sensorControllerState.orientY = q[3]
sensorControllerState.orientZ = q[1]
sensorControllerState.orientW = q[0]
}
else -> return
}
controllerStateUpdated()
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
private val motionLifecycleObserver = object: LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume()
{
val samplingPeriodUs = 4000
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
listOfNotNull(
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
).forEach {
sensorManager.registerListener(sensorEventListener, it, samplingPeriodUs)
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause()
{
val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensorManager.unregisterListener(sensorEventListener)
}
}
fun observe(lifecycleOwner: LifecycleOwner)
{
if(preferences.motionEnabled)
lifecycleOwner.lifecycle.addObserver(motionLifecycleObserver)
}
private fun controllerStateUpdated() private fun controllerStateUpdated()
{ {
controllerStateChangedCallback?.let { it(controllerState) } controllerStateChangedCallback?.let { it(controllerState) }
@ -177,7 +98,7 @@ class StreamInput(val context: Context, val preferences: Preferences)
{ {
if(event.source and InputDevice.SOURCE_CLASS_JOYSTICK != InputDevice.SOURCE_CLASS_JOYSTICK) if(event.source and InputDevice.SOURCE_CLASS_JOYSTICK != InputDevice.SOURCE_CLASS_JOYSTICK)
return false return false
fun Float.signedAxis() = (this * Short.MAX_VALUE).toInt().toShort() fun Float.signedAxis() = (this * Short.MAX_VALUE).toShort()
fun Float.unsignedAxis() = (this * UByte.MAX_VALUE.toFloat()).toUInt().toUByte() fun Float.unsignedAxis() = (this * UByte.MAX_VALUE.toFloat()).toUInt().toUByte()
motionControllerState.leftX = event.getAxisValue(MotionEvent.AXIS_X).signedAxis() motionControllerState.leftX = event.getAxisValue(MotionEvent.AXIS_X).signedAxis()
motionControllerState.leftY = event.getAxisValue(MotionEvent.AXIS_Y).signedAxis() motionControllerState.leftY = event.getAxisValue(MotionEvent.AXIS_Y).signedAxis()

View file

@ -25,11 +25,8 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
private val _state = MutableLiveData<StreamState>(StreamStateIdle) private val _state = MutableLiveData<StreamState>(StreamStateIdle)
val state: LiveData<StreamState> get() = _state val state: LiveData<StreamState> get() = _state
private val _rumbleState = MutableLiveData<RumbleEvent>(RumbleEvent(0U, 0U))
val rumbleState: LiveData<RumbleEvent> get() = _rumbleState
private var surfaceTexture: SurfaceTexture? = null var surfaceTexture: SurfaceTexture? = null
private var surface: Surface? = null
init init
{ {
@ -62,9 +59,9 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
_state.value = StreamStateConnecting _state.value = StreamStateConnecting
session.eventCallback = this::eventCallback session.eventCallback = this::eventCallback
session.start() session.start()
val surface = surface val surfaceTexture = surfaceTexture
if(surface != null) if(surfaceTexture != null)
session.setSurface(surface) session.setSurface(Surface(surfaceTexture))
this.session = session this.session = session
} }
catch(e: CreateError) catch(e: CreateError)
@ -89,30 +86,9 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
event.pinIncorrect event.pinIncorrect
) )
) )
is RumbleEvent -> _rumbleState.postValue(event)
} }
} }
fun attachToSurfaceView(surfaceView: SurfaceView)
{
surfaceView.holder.addCallback(object: SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) { }
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int)
{
val surface = holder.surface
this@StreamSession.surface = surface
session?.setSurface(surface)
}
override fun surfaceDestroyed(holder: SurfaceHolder)
{
this@StreamSession.surface = null
session?.setSurface(null)
}
})
}
fun attachToTextureView(textureView: TextureView) fun attachToTextureView(textureView: TextureView)
{ {
textureView.surfaceTextureListener = object: TextureView.SurfaceTextureListener { textureView.surfaceTextureListener = object: TextureView.SurfaceTextureListener {
@ -121,7 +97,6 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
if(surfaceTexture != null) if(surfaceTexture != null)
return return
surfaceTexture = surface surfaceTexture = surface
this@StreamSession.surface = Surface(surfaceTexture)
session?.setSurface(Surface(surface)) session?.setSurface(Surface(surface))
} }

View file

@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.metallic.chiaki.R import com.metallic.chiaki.R
import com.metallic.chiaki.databinding.ActivitySettingsBinding import kotlinx.android.synthetic.main.activity_settings.*
interface TitleFragment interface TitleFragment
{ {
@ -18,23 +18,20 @@ interface TitleFragment
class SettingsActivity: AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback class SettingsActivity: AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
{ {
private lateinit var binding: ActivitySettingsBinding
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater) setContentView(R.layout.activity_settings)
setContentView(binding.root)
title = "" title = ""
setSupportActionBar(binding.toolbar) setSupportActionBar(toolbar)
val rootFragment = SettingsFragment() val rootFragment = SettingsFragment()
replaceFragment(rootFragment, false) replaceFragment(rootFragment, false)
supportFragmentManager.addOnBackStackChangedListener { supportFragmentManager.addOnBackStackChangedListener {
val titleFragment = supportFragmentManager.findFragmentById(R.id.settingsFragment) as? TitleFragment ?: return@addOnBackStackChangedListener val titleFragment = supportFragmentManager.findFragmentById(R.id.settingsFragment) as? TitleFragment ?: return@addOnBackStackChangedListener
binding.titleTextView.text = titleFragment.getTitle(resources) titleTextView.text = titleFragment.getTitle(resources)
} }
binding.titleTextView.text = rootFragment.getTitle(resources) titleTextView.text = rootFragment.getTitle(resources)
} }
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference) = when(pref.fragment) override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference) = when(pref.fragment)

View file

@ -16,6 +16,7 @@ import com.metallic.chiaki.common.exportAndShareAllSettings
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.common.importSettingsFromUri import com.metallic.chiaki.common.importSettingsFromUri
import com.metallic.chiaki.lib.Codec
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.addTo
@ -25,9 +26,6 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
{ {
preferences.logVerboseKey -> preferences.logVerbose preferences.logVerboseKey -> preferences.logVerbose
preferences.swapCrossMoonKey -> preferences.swapCrossMoon preferences.swapCrossMoonKey -> preferences.swapCrossMoon
preferences.rumbleEnabledKey -> preferences.rumbleEnabled
preferences.motionEnabledKey -> preferences.motionEnabled
preferences.buttonHapticEnabledKey -> preferences.buttonHapticEnabled
else -> defValue else -> defValue
} }
@ -37,9 +35,6 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
{ {
preferences.logVerboseKey -> preferences.logVerbose = value preferences.logVerboseKey -> preferences.logVerbose = value
preferences.swapCrossMoonKey -> preferences.swapCrossMoon = value preferences.swapCrossMoonKey -> preferences.swapCrossMoon = value
preferences.rumbleEnabledKey -> preferences.rumbleEnabled = value
preferences.motionEnabledKey -> preferences.motionEnabled = value
preferences.buttonHapticEnabledKey -> preferences.buttonHapticEnabled = value
} }
} }

View file

@ -2,13 +2,13 @@
package com.metallic.chiaki.settings package com.metallic.chiaki.settings
import android.view.LayoutInflater import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.metallic.chiaki.R import com.metallic.chiaki.R
import com.metallic.chiaki.common.LogFile import com.metallic.chiaki.common.LogFile
import com.metallic.chiaki.common.ext.inflate import com.metallic.chiaki.common.ext.inflate
import com.metallic.chiaki.databinding.ItemLogFileBinding import kotlinx.android.synthetic.main.item_log_file.view.*
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -20,7 +20,7 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
private val dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT) private val dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT)
private val timeFormat = SimpleDateFormat("HH:mm:ss:SSS", Locale.getDefault()) private val timeFormat = SimpleDateFormat("HH:mm:ss:SSS", Locale.getDefault())
class ViewHolder(val binding: ItemLogFileBinding): RecyclerView.ViewHolder(binding.root) class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
var logFiles: List<LogFile> = listOf() var logFiles: List<LogFile> = listOf()
set(value) set(value)
@ -29,16 +29,16 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_log_file))
ViewHolder(ItemLogFileBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun getItemCount() = logFiles.size override fun getItemCount() = logFiles.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) override fun onBindViewHolder(holder: ViewHolder, position: Int)
{ {
val view = holder.itemView
val logFile = logFiles[position] val logFile = logFiles[position]
holder.binding.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}" view.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}"
holder.binding.summaryTextView.text = logFile.filename view.summaryTextView.text = logFile.filename
holder.binding.shareButton.setOnClickListener { shareCallback?.let { it(logFile) } } view.shareButton.setOnClickListener { shareCallback?.let { it(logFile) } }
} }
} }

View file

@ -21,35 +21,29 @@ import com.metallic.chiaki.common.LogFile
import com.metallic.chiaki.common.LogManager import com.metallic.chiaki.common.LogManager
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.fileProviderAuthority import com.metallic.chiaki.common.fileProviderAuthority
import com.metallic.chiaki.databinding.FragmentSettingsLogsBinding import kotlinx.android.synthetic.main.fragment_settings_logs.*
class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
{ {
private lateinit var viewModel: SettingsLogsViewModel private lateinit var viewModel: SettingsLogsViewModel
private var _binding: FragmentSettingsLogsBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
FragmentSettingsLogsBinding.inflate(inflater, container, false).let { inflater.inflate(R.layout.fragment_settings_logs, container, false)
_binding = it
it.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{ {
val context = requireContext() val context = context!!
viewModel = ViewModelProvider(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) }) viewModel = ViewModelProvider(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) })
.get(SettingsLogsViewModel::class.java) .get(SettingsLogsViewModel::class.java)
val adapter = SettingsLogsAdapter() val adapter = SettingsLogsAdapter()
binding.logsRecyclerView.layoutManager = LinearLayoutManager(context) logsRecyclerView.layoutManager = LinearLayoutManager(context)
binding.logsRecyclerView.adapter = adapter logsRecyclerView.adapter = adapter
adapter.shareCallback = this::shareLogFile adapter.shareCallback = this::shareLogFile
viewModel.sessionLogs.observe(viewLifecycleOwner, Observer { viewModel.sessionLogs.observe(viewLifecycleOwner, Observer {
adapter.logFiles = it adapter.logFiles = it
binding.emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
}) })
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context) val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context)
@ -61,7 +55,7 @@ class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
viewModel.deleteLog(file) viewModel.deleteLog(file)
} }
} }
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(binding.logsRecyclerView) ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(logsRecyclerView)
} }
override fun getTitle(resources: Resources): String = resources.getString(R.string.preferences_logs_title) override fun getTitle(resources: Resources): String = resources.getString(R.string.preferences_logs_title)

View file

@ -2,15 +2,17 @@
package com.metallic.chiaki.settings package com.metallic.chiaki.settings
import android.view.LayoutInflater import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.metallic.chiaki.R
import com.metallic.chiaki.common.RegisteredHost import com.metallic.chiaki.common.RegisteredHost
import com.metallic.chiaki.databinding.ItemRegisteredHostBinding import com.metallic.chiaki.common.ext.inflate
import kotlinx.android.synthetic.main.item_registered_host.view.*
class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHostsAdapter.ViewHolder>() class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHostsAdapter.ViewHolder>()
{ {
class ViewHolder(val binding: ItemRegisteredHostBinding): RecyclerView.ViewHolder(binding.root) class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
var hosts: List<RegisteredHost> = listOf() var hosts: List<RegisteredHost> = listOf()
set(value) set(value)
@ -19,15 +21,15 @@ class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHos
notifyDataSetChanged() notifyDataSetChanged()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_registered_host))
= ViewHolder(ItemRegisteredHostBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun getItemCount() = hosts.size override fun getItemCount() = hosts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) override fun onBindViewHolder(holder: ViewHolder, position: Int)
{ {
val view = holder.itemView
val host = hosts[position] val host = hosts[position]
holder.binding.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})" view.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})"
holder.binding.summaryTextView.text = host.serverMac.toString() view.summaryTextView.text = host.serverMac.toString()
} }
} }

View file

@ -20,32 +20,25 @@ import com.metallic.chiaki.R
import com.metallic.chiaki.common.ext.putRevealExtra import com.metallic.chiaki.common.ext.putRevealExtra
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.databinding.FragmentSettingsRegisteredHostsBinding
import com.metallic.chiaki.regist.RegistActivity import com.metallic.chiaki.regist.RegistActivity
import kotlinx.android.synthetic.main.fragment_settings_registered_hosts.*
class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
{ {
private lateinit var viewModel: SettingsRegisteredHostsViewModel private lateinit var viewModel: SettingsRegisteredHostsViewModel
private var _binding: FragmentSettingsRegisteredHostsBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
FragmentSettingsRegisteredHostsBinding.inflate(inflater, container, false).let { inflater.inflate(R.layout.fragment_settings_registered_hosts, container, false)
_binding = it
it.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{ {
val context = requireContext() viewModel = ViewModelProvider(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context!!)) })
viewModel = ViewModelProvider(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context)) })
.get(SettingsRegisteredHostsViewModel::class.java) .get(SettingsRegisteredHostsViewModel::class.java)
val adapter = SettingsRegisteredHostsAdapter() val adapter = SettingsRegisteredHostsAdapter()
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(context) hostsRecyclerView.layoutManager = LinearLayoutManager(context)
binding.hostsRecyclerView.adapter = adapter hostsRecyclerView.adapter = adapter
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context) val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context!!)
{ {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
{ {
@ -63,15 +56,15 @@ class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
.show() .show()
} }
} }
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(binding.hostsRecyclerView) ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(hostsRecyclerView)
viewModel.registeredHosts.observe(this, Observer { viewModel.registeredHosts.observe(this, Observer {
adapter.hosts = it adapter.hosts = it
binding.emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
}) })
binding.floatingActionButton.setOnClickListener { floatingActionButton.setOnClickListener {
Intent(context, RegistActivity::class.java).also { Intent(context, RegistActivity::class.java).also {
it.putRevealExtra(binding.floatingActionButton, binding.rootLayout) it.putRevealExtra(floatingActionButton, rootLayout)
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(activity).toBundle()) startActivity(it, ActivityOptions.makeSceneTransitionAnimation(activity).toBundle())
} }
} }

View file

@ -1,68 +0,0 @@
package com.metallic.chiaki.stream
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
// see ExoPlayer's AspectRatioFrameLayout
class AspectRatioFrameLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): FrameLayout(context, attrs)
{
companion object
{
private const val MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f
}
var aspectRatio = 0f
set(value)
{
if(field != value)
{
field = value
requestLayout()
}
}
var mode: TransformMode = TransformMode.FIT
set(value)
{
if(field != value)
{
field = value
requestLayout()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if(aspectRatio <= 0)
{
// Aspect ratio not set.
return
}
var width = measuredWidth
var height = measuredHeight
val viewAspectRatio = width.toFloat() / height
val aspectDeformation = aspectRatio / viewAspectRatio - 1
if(Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION)
return
when(mode)
{
TransformMode.ZOOM ->
if(aspectDeformation > 0)
width = (height * aspectRatio).toInt()
else
height = (width / aspectRatio).toInt()
TransformMode.FIT ->
if(aspectDeformation > 0)
height = (width / aspectRatio).toInt()
else
width = (height * aspectRatio).toInt()
TransformMode.STRETCH -> {}
}
super.onMeasure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
)
}
}

View file

@ -6,8 +6,12 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter
import android.app.AlertDialog import android.app.AlertDialog
import android.graphics.Matrix import android.graphics.Matrix
import android.os.* import android.os.Bundle
import android.view.* import android.os.Handler
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.TextureView
import android.view.View
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone import androidx.core.view.isGone
@ -16,18 +20,15 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.* import androidx.lifecycle.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.metallic.chiaki.R import com.metallic.chiaki.R
import com.metallic.chiaki.common.LogManager
import com.metallic.chiaki.common.Preferences import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.databinding.ActivityStreamBinding
import com.metallic.chiaki.lib.ConnectInfo import com.metallic.chiaki.lib.ConnectInfo
import com.metallic.chiaki.lib.ConnectVideoProfile import com.metallic.chiaki.lib.ConnectVideoProfile
import com.metallic.chiaki.session.* import com.metallic.chiaki.session.*
import com.metallic.chiaki.touchcontrols.DefaultTouchControlsFragment
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
import io.reactivex.disposables.CompositeDisposable import com.metallic.chiaki.touchcontrols.TouchControlsFragment
import io.reactivex.rxkotlin.addTo import kotlinx.android.synthetic.main.activity_stream.*
import kotlin.math.min
private sealed class DialogContents private sealed class DialogContents
private object StreamQuitDialog: DialogContents() private object StreamQuitDialog: DialogContents()
@ -43,8 +44,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
} }
private lateinit var viewModel: StreamViewModel private lateinit var viewModel: StreamViewModel
private lateinit var binding: ActivityStreamBinding
private val uiVisibilityHandler = Handler() private val uiVisibilityHandler = Handler()
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
@ -59,75 +58,63 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
} }
viewModel = ViewModelProvider(this, viewModelFactory { viewModel = ViewModelProvider(this, viewModelFactory {
StreamViewModel(application, connectInfo) StreamViewModel(Preferences(this), LogManager(this), connectInfo)
})[StreamViewModel::class.java] })[StreamViewModel::class.java]
viewModel.input.observe(this) setContentView(R.layout.activity_stream)
binding = ActivityStreamBinding.inflate(layoutInflater)
setContentView(binding.root)
window.decorView.setOnSystemUiVisibilityChangeListener(this) window.decorView.setOnSystemUiVisibilityChangeListener(this)
viewModel.onScreenControlsEnabled.observe(this, Observer { viewModel.onScreenControlsEnabled.observe(this, Observer {
if(binding.onScreenControlsSwitch.isChecked != it) if(onScreenControlsSwitch.isChecked != it)
binding.onScreenControlsSwitch.isChecked = it onScreenControlsSwitch.isChecked = it
if(binding.onScreenControlsSwitch.isChecked) if(onScreenControlsSwitch.isChecked)
binding.touchpadOnlySwitch.isChecked = false touchpadOnlySwitch.isChecked = false
}) })
binding.onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked -> onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.setOnScreenControlsEnabled(isChecked) viewModel.setOnScreenControlsEnabled(isChecked)
showOverlay() showOverlay()
} }
viewModel.touchpadOnlyEnabled.observe(this, Observer { viewModel.touchpadOnlyEnabled.observe(this, Observer {
if(binding.touchpadOnlySwitch.isChecked != it) if(touchpadOnlySwitch.isChecked != it)
binding.touchpadOnlySwitch.isChecked = it touchpadOnlySwitch.isChecked = it
if(binding.touchpadOnlySwitch.isChecked) if(touchpadOnlySwitch.isChecked)
binding.onScreenControlsSwitch.isChecked = false onScreenControlsSwitch.isChecked = false
}) })
binding.touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked -> touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.setTouchpadOnlyEnabled(isChecked) viewModel.setTouchpadOnlyEnabled(isChecked)
showOverlay() showOverlay()
} }
binding.displayModeToggle.addOnButtonCheckedListener { _, _, _ -> displayModeToggle.addOnButtonCheckedListener { _, checkedId, _ ->
adjustStreamViewAspect() // following 'if' is a workaround until selectionRequired for MaterialButtonToggleGroup
// comes out of alpha.
// See https://stackoverflow.com/questions/56164004/required-single-selection-on-materialbuttontogglegroup
if (displayModeToggle.checkedButtonId == -1)
displayModeToggle.check(checkedId)
adjustTextureViewAspect()
showOverlay() showOverlay()
} }
//viewModel.session.attachToTextureView(textureView) viewModel.session.attachToTextureView(textureView)
viewModel.session.attachToSurfaceView(binding.surfaceView)
viewModel.session.state.observe(this, Observer { this.stateChanged(it) }) viewModel.session.state.observe(this, Observer { this.stateChanged(it) })
adjustStreamViewAspect() textureView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
adjustTextureViewAspect()
if(Preferences(this).rumbleEnabled)
{
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
viewModel.session.rumbleState.observe(this, Observer {
val amplitude = min(255, (it.left.toInt() + it.right.toInt()) / 2)
vibrator.cancel()
if(amplitude == 0)
return@Observer
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
vibrator.vibrate(VibrationEffect.createOneShot(1000, amplitude))
else
vibrator.vibrate(1000)
})
} }
} }
private val controlsDisposable = CompositeDisposable()
override fun onAttachFragment(fragment: Fragment) override fun onAttachFragment(fragment: Fragment)
{ {
super.onAttachFragment(fragment) super.onAttachFragment(fragment)
if(fragment is TouchControlsFragment) if(fragment is TouchControlsFragment)
{ {
fragment.controllerState fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
.subscribe { viewModel.input.touchControllerState = it }
.addTo(controlsDisposable)
fragment.onScreenControlsEnabled = viewModel.onScreenControlsEnabled fragment.onScreenControlsEnabled = viewModel.onScreenControlsEnabled
}
if(fragment is TouchpadOnlyFragment) if(fragment is TouchpadOnlyFragment)
{
fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
fragment.touchpadOnlyEnabled = viewModel.touchpadOnlyEnabled fragment.touchpadOnlyEnabled = viewModel.touchpadOnlyEnabled
} }
} }
@ -145,12 +132,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
viewModel.session.pause() viewModel.session.pause()
} }
override fun onDestroy()
{
super.onDestroy()
controlsDisposable.dispose()
}
private fun reconnect() private fun reconnect()
{ {
viewModel.session.shutdown() viewModel.session.shutdown()
@ -169,14 +150,14 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
private fun showOverlay() private fun showOverlay()
{ {
binding.overlay.isVisible = true overlay.isVisible = true
binding.overlay.animate() overlay.animate()
.alpha(1.0f) .alpha(1.0f)
.setListener(object: AnimatorListenerAdapter() .setListener(object: AnimatorListenerAdapter()
{ {
override fun onAnimationEnd(animation: Animator) override fun onAnimationEnd(animation: Animator?)
{ {
binding.overlay.alpha = 1.0f overlay.alpha = 1.0f
} }
}) })
uiVisibilityHandler.removeCallbacks(hideSystemUIRunnable) uiVisibilityHandler.removeCallbacks(hideSystemUIRunnable)
@ -185,13 +166,13 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
private fun hideOverlay() private fun hideOverlay()
{ {
binding.overlay.animate() overlay.animate()
.alpha(0.0f) .alpha(0.0f)
.setListener(object: AnimatorListenerAdapter() .setListener(object: AnimatorListenerAdapter()
{ {
override fun onAnimationEnd(animation: Animator) override fun onAnimationEnd(animation: Animator?)
{ {
binding.overlay.isGone = true overlay.isGone = true
} }
}) })
} }
@ -224,15 +205,13 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
private fun stateChanged(state: StreamState) private fun stateChanged(state: StreamState)
{ {
binding.progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE
when(state) when(state)
{ {
is StreamStateQuit -> is StreamStateQuit ->
{ {
if(dialogContents != StreamQuitDialog) if(!state.reason.isStopped && dialogContents != StreamQuitDialog)
{
if(state.reason.isError)
{ {
dialog?.dismiss() dialog?.dismiss()
val reasonStr = state.reasonString val reasonStr = state.reasonString
@ -255,9 +234,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
dialogContents = StreamQuitDialog dialogContents = StreamQuitDialog
dialog.show() dialog.show()
} }
else
finish()
}
} }
is StreamStateCreateError -> is StreamStateCreateError ->
@ -311,89 +287,77 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
dialog.show() dialog.show()
} }
} }
else -> {}
} }
} }
private fun adjustTextureViewAspect(textureView: TextureView) private fun adjustTextureViewAspect()
{ {
val trans = TextureViewTransform(viewModel.session.connectInfo.videoProfile, textureView) val displayInfo = DisplayInfo(viewModel.session.connectInfo.videoProfile, textureView)
val resolution = trans.resolutionFor(TransformMode.fromButton(binding.displayModeToggle.checkedButtonId)) val resolution = displayInfo.computeResolutionFor(displayModeToggle.checkedButtonId)
Matrix().also { Matrix().also {
textureView.getTransform(it) textureView.getTransform(it)
it.setScale(resolution.width / trans.viewWidth, resolution.height / trans.viewHeight) it.setScale(resolution.width / displayInfo.viewWidth, resolution.height / displayInfo.viewHeight)
it.postTranslate((trans.viewWidth - resolution.width) * 0.5f, (trans.viewHeight - resolution.height) * 0.5f) it.postTranslate((displayInfo.viewWidth - resolution.width) * 0.5f, (displayInfo.viewHeight - resolution.height) * 0.5f)
textureView.setTransform(it) textureView.setTransform(it)
} }
} }
private fun adjustSurfaceViewAspect()
{
val videoProfile = viewModel.session.connectInfo.videoProfile
binding.aspectRatioLayout.aspectRatio = videoProfile.width.toFloat() / videoProfile.height.toFloat()
binding.aspectRatioLayout.mode = TransformMode.fromButton(binding.displayModeToggle.checkedButtonId)
}
private fun adjustStreamViewAspect() = adjustSurfaceViewAspect()
override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event) override fun dispatchKeyEvent(event: KeyEvent) = viewModel.input.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event) override fun onGenericMotionEvent(event: MotionEvent) = viewModel.input.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
} }
enum class TransformMode
{
FIT,
STRETCH,
ZOOM;
companion object class DisplayInfo constructor(val videoProfile: ConnectVideoProfile, val textureView: TextureView)
{ {
fun fromButton(displayModeButtonId: Int) val contentWidth : Float get() = videoProfile.width.toFloat()
= when (displayModeButtonId) val contentHeight : Float get() = videoProfile.height.toFloat()
{
R.id.display_mode_stretch_button -> STRETCH
R.id.display_mode_zoom_button -> ZOOM
else -> FIT
}
}
}
class TextureViewTransform(private val videoProfile: ConnectVideoProfile, private val textureView: TextureView)
{
private val contentWidth : Float get() = videoProfile.width.toFloat()
private val contentHeight : Float get() = videoProfile.height.toFloat()
val viewWidth : Float get() = textureView.width.toFloat() val viewWidth : Float get() = textureView.width.toFloat()
val viewHeight : Float get() = textureView.height.toFloat() val viewHeight : Float get() = textureView.height.toFloat()
private val contentAspect : Float get() = contentHeight / contentWidth val contentAspect : Float get() = contentHeight / contentWidth
fun resolutionFor(mode: TransformMode): Resolution fun computeResolutionFor(displayModeButtonId: Int) : Resolution
= when(mode)
{ {
TransformMode.STRETCH -> strechedResolution when (displayModeButtonId)
TransformMode.ZOOM -> zoomedResolution {
TransformMode.FIT -> normalResolution R.id.display_mode_stretch_button -> return computeStrechedResolution()
R.id.display_mode_zoom_button -> return computeZoomedResolution()
else -> return computeNormalResolution()
}
} }
private val strechedResolution get() = Resolution(viewWidth, viewHeight) private fun computeStrechedResolution(): Resolution
{
return Resolution(viewWidth, viewHeight)
}
private val zoomedResolution get() = private fun computeZoomedResolution(): Resolution
{
if (viewHeight > viewWidth * contentAspect) if (viewHeight > viewWidth * contentAspect)
{ {
val zoomFactor = viewHeight / contentHeight val zoomFactor = viewHeight / contentHeight
Resolution(contentWidth * zoomFactor, viewHeight) return Resolution(contentWidth * zoomFactor, viewHeight)
} }
else else
{ {
val zoomFactor = viewWidth / contentWidth val zoomFactor = viewWidth / contentWidth
Resolution(viewWidth, contentHeight * zoomFactor) return Resolution(viewWidth, contentHeight * zoomFactor)
}
} }
private val normalResolution get() = private fun computeNormalResolution(): Resolution
{
if (viewHeight > viewWidth * contentAspect) if (viewHeight > viewWidth * contentAspect)
Resolution(viewWidth, viewWidth * contentAspect) {
return Resolution(viewWidth, viewWidth * contentAspect)
}
else else
Resolution(viewHeight / contentAspect, viewHeight) {
return Resolution(viewHeight / contentAspect, viewHeight)
}
}
} }

View file

@ -2,22 +2,19 @@
package com.metallic.chiaki.stream package com.metallic.chiaki.stream
import android.app.Application import androidx.lifecycle.LiveData
import android.content.Context import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.* import androidx.lifecycle.ViewModel
import com.metallic.chiaki.common.LogManager import com.metallic.chiaki.common.LogManager
import com.metallic.chiaki.session.StreamSession import com.metallic.chiaki.session.StreamSession
import com.metallic.chiaki.common.Preferences import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.lib.* import com.metallic.chiaki.lib.*
import com.metallic.chiaki.session.StreamInput import com.metallic.chiaki.session.StreamInput
class StreamViewModel(val application: Application, val connectInfo: ConnectInfo): ViewModel() class StreamViewModel(val preferences: Preferences, val logManager: LogManager, val connectInfo: ConnectInfo): ViewModel()
{ {
val preferences = Preferences(application)
val logManager = LogManager(application)
private var _session: StreamSession? = null private var _session: StreamSession? = null
val input = StreamInput(application, preferences) val input = StreamInput(preferences)
val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input) val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input)
private var _onScreenControlsEnabled = MutableLiveData<Boolean>(preferences.onScreenControlsEnabled) private var _onScreenControlsEnabled = MutableLiveData<Boolean>(preferences.onScreenControlsEnabled)

View file

@ -1,29 +0,0 @@
package com.metallic.chiaki.touchcontrols
import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import androidx.appcompat.app.AppCompatActivity
import com.metallic.chiaki.common.Preferences
class ButtonHaptics(val context: Context)
{
private val enabled = Preferences(context).buttonHapticEnabled
fun trigger(harder: Boolean = false)
{
if(!enabled)
return
val vibrator = context.getSystemService(AppCompatActivity.VIBRATOR_SERVICE) as Vibrator
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
vibrator.vibrate(
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
VibrationEffect.createPredefined(if(harder) VibrationEffect.EFFECT_CLICK else VibrationEffect.EFFECT_TICK)
else
VibrationEffect.createOneShot(10, if(harder) 200 else 100)
)
else
vibrator.vibrate(10)
}
}

View file

@ -6,19 +6,14 @@ import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import com.metallic.chiaki.R import com.metallic.chiaki.R
class ButtonView @JvmOverloads constructor( class ButtonView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) ) : View(context, attrs, defStyleAttr)
{ {
private val haptics = ButtonHaptics(context)
var buttonPressed = false var buttonPressed = false
private set(value) private set(value)
{ {
@ -26,8 +21,6 @@ class ButtonView @JvmOverloads constructor(
field = value field = value
if(diff) if(diff)
{ {
if(value)
haptics.trigger()
invalidate() invalidate()
buttonPressedCallback?.let { it(field) } buttonPressedCallback?.let { it(field) }
} }
@ -53,39 +46,16 @@ class ButtonView @JvmOverloads constructor(
{ {
super.onDraw(canvas) super.onDraw(canvas)
val drawable = if(buttonPressed) drawablePressed else drawableIdle val drawable = if(buttonPressed) drawablePressed else drawableIdle
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom) drawable?.setBounds(0, 0, width, height)
drawable?.draw(canvas) drawable?.draw(canvas)
} }
/**
* If this button overlaps with others in the same layout,
* let the one whose center is closest to the touch handle it.
*/
private fun bestFittingTouchView(x: Float, y: Float): View
{
val loc = locationOnScreen + Vector(x, y)
return (parent as? ViewGroup)?.children?.filter {
it is ButtonView
}?.filter {
val pos = it.locationOnScreen
loc.x >= pos.x && loc.x < pos.x + it.width && loc.y >= pos.y && loc.y < pos.y + it.height
}?.sortedBy {
(loc - (it.locationOnScreen + Vector(it.width.toFloat(), it.height.toFloat()) * 0.5f)).lengthSq
}?.firstOrNull() ?: this
}
override fun onTouchEvent(event: MotionEvent): Boolean override fun onTouchEvent(event: MotionEvent): Boolean
{ {
when(event.actionMasked) when(event.action)
{ {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> { MotionEvent.ACTION_DOWN -> buttonPressed = true
if(bestFittingTouchView(event.getX(event.actionIndex), event.getY(event.actionIndex)) != this) MotionEvent.ACTION_UP -> buttonPressed = false
return false
buttonPressed = true
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
buttonPressed = false
}
} }
return true return true
} }

View file

@ -16,8 +16,6 @@ class DPadView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) ) : View(context, attrs, defStyleAttr)
{ {
private val haptics = ButtonHaptics(context)
enum class Direction { enum class Direction {
LEFT, LEFT,
RIGHT, RIGHT,
@ -73,7 +71,7 @@ class DPadView @JvmOverloads constructor(
else else
drawable = dpadIdleDrawable drawable = dpadIdleDrawable
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom) drawable?.setBounds(0, 0, width, height)
//drawable?.alpha = 127 //drawable?.alpha = 127
drawable?.draw(canvas) drawable?.draw(canvas)
} }
@ -115,8 +113,6 @@ class DPadView @JvmOverloads constructor(
if(state != newState) if(state != newState)
{ {
if(newState != null)
haptics.trigger()
state = newState state = newState
invalidate() invalidate()
stateChangeCallback?.let { it(state) } stateChangeCallback?.let { it(state) }

View file

@ -3,97 +3,74 @@
package com.metallic.chiaki.touchcontrols package com.metallic.chiaki.touchcontrols
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.metallic.chiaki.databinding.FragmentControlsBinding import com.metallic.chiaki.R
import com.metallic.chiaki.lib.ControllerState import com.metallic.chiaki.lib.ControllerState
import io.reactivex.Observable import kotlinx.android.synthetic.main.fragment_controls.*
import io.reactivex.rxkotlin.Observables.combineLatest
import io.reactivex.subjects.BehaviorSubject
import io.reactivex.subjects.Subject
abstract class TouchControlsFragment : Fragment() class TouchControlsFragment : Fragment()
{ {
protected var ownControllerState = ControllerState() private var controllerState = ControllerState()
set(value) private set(value)
{ {
val diff = field != value val diff = field != value
field = value field = value
if(diff) if(diff)
ownControllerStateSubject.onNext(ownControllerState) controllerStateCallback?.let { it(value) }
} }
protected val ownControllerStateSubject: Subject<ControllerState> var controllerStateCallback: ((ControllerState) -> Unit)? = null
= BehaviorSubject.create<ControllerState>().also { it.onNext(ownControllerState) }
// to delay attaching to the touchpadView until it's available
protected val controllerStateProxy: Subject<Observable<ControllerState>>
= BehaviorSubject.create<Observable<ControllerState>>().also { it.onNext(ownControllerStateSubject) }
val controllerState: Observable<ControllerState> get() =
controllerStateProxy.flatMap { it }
var onScreenControlsEnabled: LiveData<Boolean>? = null var onScreenControlsEnabled: LiveData<Boolean>? = null
}
class DefaultTouchControlsFragment : TouchControlsFragment() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
{ = inflater.inflate(R.layout.fragment_controls, container, false)
private var _binding: FragmentControlsBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
FragmentControlsBinding.inflate(inflater, container, false).let {
_binding = it
controllerStateProxy.onNext(
combineLatest(ownControllerStateSubject, binding.touchpadView.controllerState) { a, b -> a or b }
)
it.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{ {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.dpadView.stateChangeCallback = this::dpadStateChanged dpadView.stateChangeCallback = this::dpadStateChanged
binding.crossButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_CROSS) crossButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_CROSS)
binding.moonButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_MOON) moonButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_MOON)
binding.pyramidButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PYRAMID) pyramidButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PYRAMID)
binding.boxButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_BOX) boxButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_BOX)
binding.l1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L1) l1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L1)
binding.r1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R1) r1ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R1)
binding.l3ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_L3) optionsButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_OPTIONS)
binding.r3ButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_R3) shareButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_SHARE)
binding.optionsButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_OPTIONS) psButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PS)
binding.shareButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_SHARE) touchpadButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_TOUCHPAD)
binding.psButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_PS)
binding.l2ButtonView.buttonPressedCallback = { ownControllerState = ownControllerState.copy().apply { l2State = if(it) 255U else 0U } } l2ButtonView.buttonPressedCallback = { controllerState = controllerState.copy().apply { l2State = if(it) 255U else 0U } }
binding.r2ButtonView.buttonPressedCallback = { ownControllerState = ownControllerState.copy().apply { r2State = if(it) 255U else 0U } } r2ButtonView.buttonPressedCallback = { controllerState = controllerState.copy().apply { r2State = if(it) 255U else 0U } }
val quantizeStick = { f: Float -> val quantizeStick = { f: Float ->
(Short.MAX_VALUE * f).toInt().toShort() (Short.MAX_VALUE * f).toShort()
} }
binding.leftAnalogStickView.stateChangedCallback = { ownControllerState = ownControllerState.copy().apply { leftAnalogStickView.stateChangedCallback = { controllerState = controllerState.copy().apply {
leftX = quantizeStick(it.x) leftX = quantizeStick(it.x)
leftY = quantizeStick(it.y) leftY = quantizeStick(it.y)
}} }}
binding.rightAnalogStickView.stateChangedCallback = { ownControllerState = ownControllerState.copy().apply { rightAnalogStickView.stateChangedCallback = { controllerState = controllerState.copy().apply {
rightX = quantizeStick(it.x) rightX = quantizeStick(it.x)
rightY = quantizeStick(it.y) rightY = quantizeStick(it.y)
}} }}
onScreenControlsEnabled?.observe(viewLifecycleOwner, Observer { onScreenControlsEnabled?.observe(this, Observer {
view.visibility = if(it) View.VISIBLE else View.GONE view.visibility = if(it) View.VISIBLE else View.GONE
}) })
} }
private fun dpadStateChanged(direction: DPadView.Direction?) private fun dpadStateChanged(direction: DPadView.Direction?)
{ {
ownControllerState = ownControllerState.copy().apply { controllerState = controllerState.copy().apply {
buttons = ((buttons buttons = ((buttons
and ControllerState.BUTTON_DPAD_LEFT.inv() and ControllerState.BUTTON_DPAD_LEFT.inv()
and ControllerState.BUTTON_DPAD_RIGHT.inv() and ControllerState.BUTTON_DPAD_RIGHT.inv()
@ -115,7 +92,7 @@ class DefaultTouchControlsFragment : TouchControlsFragment()
} }
private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean -> private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean ->
ownControllerState = ownControllerState.copy().apply { controllerState = controllerState.copy().apply {
buttons = buttons =
if(pressed) if(pressed)
buttons or buttonMask buttons or buttonMask

View file

@ -26,7 +26,7 @@ class TouchTracker
if(pointerId == null) if(pointerId == null)
{ {
pointerId = event.getPointerId(event.actionIndex) pointerId = event.getPointerId(event.actionIndex)
currentPosition = Vector(event.getX(event.actionIndex), event.getY(event.actionIndex)) currentPosition = Vector(event.x, event.y)
} }
} }

View file

@ -6,42 +6,49 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.metallic.chiaki.databinding.FragmentTouchpadOnlyBinding import com.metallic.chiaki.R
import io.reactivex.rxkotlin.Observables.combineLatest import com.metallic.chiaki.lib.ControllerState
import kotlinx.android.synthetic.main.fragment_controls.*
class TouchpadOnlyFragment : TouchControlsFragment() class TouchpadOnlyFragment : Fragment()
{ {
private var controllerState = ControllerState()
private set(value)
{
val diff = field != value
field = value
if(diff)
controllerStateCallback?.let { it(value) }
}
var controllerStateCallback: ((ControllerState) -> Unit)? = null
var touchpadOnlyEnabled: LiveData<Boolean>? = null var touchpadOnlyEnabled: LiveData<Boolean>? = null
private var _binding: FragmentTouchpadOnlyBinding? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
private val binding get() = _binding!! = inflater.inflate(R.layout.fragment_touchpad_only, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
FragmentTouchpadOnlyBinding.inflate(inflater, container, false).let {
_binding = it
controllerStateProxy.onNext(
combineLatest(ownControllerStateSubject, binding.touchpadView.controllerState) { a, b -> a or b }
)
it.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{ {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
touchpadOnlyEnabled?.observe(viewLifecycleOwner, Observer {
touchpadButtonView.buttonPressedCallback = buttonStateChanged(ControllerState.BUTTON_TOUCHPAD)
touchpadOnlyEnabled?.observe(this, Observer {
view.visibility = if(it) View.VISIBLE else View.GONE view.visibility = if(it) View.VISIBLE else View.GONE
}) })
} }
private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean -> private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean ->
ownControllerState = ownControllerState.copy().apply { controllerState = controllerState.copy().apply {
buttons = buttons =
if(pressed) if(pressed)
buttons or buttonMask buttons or buttonMask
else else
buttons and buttonMask.inv() buttons and buttonMask.inv()
} }
} }
} }

View file

@ -1,168 +0,0 @@
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
package com.metallic.chiaki.touchcontrols
import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.metallic.chiaki.R
import com.metallic.chiaki.lib.ControllerState
import io.reactivex.Observable
import io.reactivex.subjects.BehaviorSubject
import io.reactivex.subjects.Subject
import kotlin.math.max
class TouchpadView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr)
{
companion object
{
private const val BUTTON_PRESS_MAX_MOVE_DIST_DP = 32.0f
private const val SHORT_BUTTON_PRESS_DURATION_MS = 200L
private const val BUTTON_HOLD_DELAY_MS = 500L
}
private val haptics = ButtonHaptics(context)
private val drawableIdle: Drawable?
private val drawablePressed: Drawable?
private val state: ControllerState = ControllerState()
inner class Touch(
val stateId: UByte,
private val startX: Float,
private val startY: Float)
{
var lifted = false // will be true but touch still in list when only relevant for short touch
private var maxDist: Float = 0.0f
val moveInsignificant: Boolean get() = maxDist < BUTTON_PRESS_MAX_MOVE_DIST_DP
fun onMove(x: Float, y: Float)
{
val d = (Vector(x, y) - Vector(startX, startY)).length / resources.displayMetrics.density
maxDist = max(d, maxDist)
}
val startButtonHoldRunnable = Runnable {
if(!moveInsignificant || buttonHeld)
return@Runnable
haptics.trigger(true)
state.buttons = state.buttons or ControllerState.BUTTON_TOUCHPAD
buttonHeld = true
triggerStateChanged()
}
}
private val pointerTouches = mutableMapOf<Int, Touch>()
private val stateSubject: Subject<ControllerState>
= BehaviorSubject.create<ControllerState>().also { it.onNext(state) }
val controllerState: Observable<ControllerState> get() = stateSubject
private var shortPressingTouches = listOf<Touch>()
private val shortButtonPressLiftRunnable = Runnable {
state.buttons = state.buttons and ControllerState.BUTTON_TOUCHPAD.inv()
shortPressingTouches.forEach {
state.stopTouch(it.stateId)
}
shortPressingTouches = listOf()
triggerStateChanged()
}
private var buttonHeld = false
init
{
context.theme.obtainStyledAttributes(attrs, R.styleable.TouchpadView, 0, 0).apply {
drawableIdle = getDrawable(R.styleable.TouchpadView_drawableIdle)
drawablePressed = getDrawable(R.styleable.TouchpadView_drawablePressed)
recycle()
}
isClickable = true
}
override fun onDraw(canvas: Canvas)
{
super.onDraw(canvas)
if(pointerTouches.values.find { !it.lifted } == null)
return
val drawable = if(state.buttons and ControllerState.BUTTON_TOUCHPAD != 0U) drawablePressed else drawableIdle
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
drawable?.draw(canvas)
}
private fun touchX(event: MotionEvent, index: Int): UShort =
maxOf(0U.toUShort(), minOf((ControllerState.TOUCHPAD_WIDTH - 1u).toUShort(),
(ControllerState.TOUCHPAD_WIDTH.toFloat() * event.getX(index) / width.toFloat()).toUInt().toUShort()))
private fun touchY(event: MotionEvent, index: Int): UShort =
maxOf(0U.toUShort(), minOf((ControllerState.TOUCHPAD_HEIGHT - 1u).toUShort(),
(ControllerState.TOUCHPAD_HEIGHT.toFloat() * event.getY(index) / height.toFloat()).toUInt().toUShort()))
override fun onTouchEvent(event: MotionEvent): Boolean
{
when(event.actionMasked)
{
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
state.startTouch(touchX(event, event.actionIndex), touchY(event, event.actionIndex))?.let {
haptics.trigger()
val touch = Touch(it, event.getX(event.actionIndex), event.getY(event.actionIndex))
pointerTouches[event.getPointerId(event.actionIndex)] = touch
if(!buttonHeld)
postDelayed(touch.startButtonHoldRunnable, BUTTON_HOLD_DELAY_MS)
triggerStateChanged()
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
pointerTouches.remove(event.getPointerId(event.actionIndex))?.let {
removeCallbacks(it.startButtonHoldRunnable)
when
{
buttonHeld ->
{
buttonHeld = false
state.buttons = state.buttons and ControllerState.BUTTON_TOUCHPAD.inv()
state.stopTouch(it.stateId)
}
it.moveInsignificant -> triggerShortButtonPress(it)
else -> state.stopTouch(it.stateId)
}
triggerStateChanged()
}
}
MotionEvent.ACTION_MOVE -> {
val changed = pointerTouches.entries.fold(false) { acc, it ->
val index = event.findPointerIndex(it.key)
if(index < 0)
acc
else
{
it.value.onMove(event.getX(event.actionIndex), event.getY(event.actionIndex))
acc || state.setTouchPos(it.value.stateId, touchX(event, index), touchY(event, index))
}
}
if(changed)
triggerStateChanged()
}
}
return true
}
private fun triggerShortButtonPress(touch: Touch)
{
shortPressingTouches = shortPressingTouches + listOf(touch)
removeCallbacks(shortButtonPressLiftRunnable)
state.buttons = state.buttons or ControllerState.BUTTON_TOUCHPAD
postDelayed(shortButtonPressLiftRunnable, SHORT_BUTTON_PRESS_DURATION_MS)
}
private fun triggerStateChanged()
{
invalidate()
stateSubject.onNext(state)
}
}

View file

@ -2,7 +2,6 @@
package com.metallic.chiaki.touchcontrols package com.metallic.chiaki.touchcontrols
import android.view.View
import kotlin.math.sqrt import kotlin.math.sqrt
data class Vector(val x: Float, val y: Float) data class Vector(val x: Float, val y: Float)
@ -20,9 +19,3 @@ data class Vector(val x: Float, val y: Float)
val length get() = sqrt(lengthSq) val length get() = sqrt(lengthSq)
val normalized get() = this / length val normalized get() = this / length
} }
val View.locationOnScreen: Vector get() {
val v = intArrayOf(0, 0)
this.getLocationOnScreen(v)
return Vector(v[0].toFloat(), v[1].toFloat())
}

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M39.2255,0 L0,39.2255 20.3838,59.6093a27.7366,27.7366 88.4859,0 0,39.2255 0,27.7366 27.7366,88.4859 0,0 0,-39.2255zM25.4129,29.4287l2.7735,0l0,18.1643l9.9818,0l0,2.3342L25.4129,49.9272ZM46.3098,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8076,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299ZM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_primary" android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M39.2255,0 L0,39.2255 20.3838,59.6093a27.7366,27.7366 88.4859,0 0,39.2255 0,27.7366 27.7366,88.4859 0,0 0,-39.2255zM25.4129,29.4287l2.7735,0l0,18.1643l9.9818,0l0,2.3342L25.4129,49.9272ZM46.3098,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8076,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299ZM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed" android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="m27.6526,0a27.7366,27.7366 88.4859,0 0,-19.5285 8.1241,27.7366 27.7366,88.4859 0,0 0,39.2255L28.5078,67.7333 67.7333,28.5078 47.3496,8.1241A27.7366,27.7366 88.4859,0 0,27.6526 0ZM34.9017,15.1846c2.1235,0 3.8172,0.5309 5.0803,1.5927 1.2631,1.0618 1.8945,2.4804 1.8945,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9563,1.034 -2.1828,2.3063 -1.2265,1.2631 -2.9565,3.0342 -5.1899,5.3134l9.6795,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.3846,-1.9769 -1.1534,-2.6634 -0.7597,-0.6865 -1.7526,-1.0299 -2.9791,-1.0299 -0.8695,-0 -1.7898,0.1511 -2.76,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L29.1078,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM14.0053,15.5551l2.7735,0l0,18.1643l9.9813,0l0,2.3342L14.0053,36.0536Z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321 0.9062,-0.6682 2.1373,-1.002 3.6933,-1.002zM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299Z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_primary" android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="m27.6526,0a27.7366,27.7366 88.4859,0 0,-19.5285 8.1241,27.7366 27.7366,88.4859 0,0 0,39.2255L28.5078,67.7333 67.7333,28.5078 47.3496,8.1241A27.7366,27.7366 88.4859,0 0,27.6526 0ZM34.9017,15.1846c2.1235,0 3.8172,0.5309 5.0803,1.5927 1.2631,1.0618 1.8945,2.4804 1.8945,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9563,1.034 -2.1828,2.3063 -1.2265,1.2631 -2.9565,3.0342 -5.1899,5.3134l9.6795,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.3846,-1.9769 -1.1534,-2.6634 -0.7597,-0.6865 -1.7526,-1.0299 -2.9791,-1.0299 -0.8695,-0 -1.7898,0.1511 -2.76,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L29.1078,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM14.0053,15.5551l2.7735,0l0,18.1643l9.9813,0l0,2.3342L14.0053,36.0536Z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321 0.9062,-0.6682 2.1373,-1.002 3.6933,-1.002zM21.7852,8.2563l2.3337,0L24.1189,23.6745L31.89,23.6745L31.89,25.8299L21.7852,25.8299Z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed" android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M0,0 L-41.939,102.093 67.7333,67.7333C67.7333,30.3253 37.4081,0 0,0ZM33.6093,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8397,2.2423 1.8397,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5739,1.318 -2.773,1.6201 1.3272,0.2837 2.3613,0.8739 3.1027,1.771 0.7506,0.897 1.126,2.0047 1.126,3.3228 0,2.0228 -0.6959,3.5878 -2.0872,4.6953 -1.3913,1.1075 -3.368,1.6614 -5.9309,1.6614 -0.8604,0 -1.7486,-0.0871 -2.6639,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0621,-0.3434 3.9682,-1.0299 0.9153,-0.6865 1.3725,-1.6837 1.3725,-2.9926 0,-1.2082 -0.4252,-2.1514 -1.2764,-2.8288 -0.8421,-0.6865 -2.0187,-1.0294 -3.529,-1.0294l-2.3885,0l0,-2.2794l2.4986,0c1.3638,0 2.4075,-0.2697 3.1306,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.3755,-1.858 -1.126,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.037,-0.5124 2.9523,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM12.3832,31.6957l2.7735,0l0,18.1648l9.9813,0l0,2.3337L12.3832,52.1942Z"
android:strokeLineJoin="round"
android:strokeWidth="11.0688"
android:fillColor="@color/control_primary"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M0,0 L-41.939,102.093 67.7333,67.7333C67.7333,30.3253 37.4081,0 0,0ZM33.6093,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8397,2.2423 1.8397,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5739,1.318 -2.773,1.6201 1.3272,0.2837 2.3613,0.8739 3.1027,1.771 0.7506,0.897 1.126,2.0047 1.126,3.3228 0,2.0228 -0.6959,3.5878 -2.0872,4.6953 -1.3913,1.1075 -3.368,1.6614 -5.9309,1.6614 -0.8604,0 -1.7486,-0.0871 -2.6639,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0621,-0.3434 3.9682,-1.0299 0.9153,-0.6865 1.3725,-1.6837 1.3725,-2.9926 0,-1.2082 -0.4252,-2.1514 -1.2764,-2.8288 -0.8421,-0.6865 -2.0187,-1.0294 -3.529,-1.0294l-2.3885,0l0,-2.2794l2.4986,0c1.3638,0 2.4075,-0.2697 3.1306,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.3755,-1.858 -1.126,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.037,-0.5124 2.9523,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM12.3832,31.6957l2.7735,0l0,18.1648l9.9813,0l0,2.3337L12.3832,52.1942Z"
android:strokeLineJoin="round"
android:strokeWidth="11.0688"
android:fillColor="@color/control_pressed"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M28.5078,0 L8.1241,20.3838a27.7366,27.7366 88.4859,0 0,0 39.2255,27.7366 27.7366,88.4859 0,0 39.2255,0L67.7333,39.2255ZM12.4178,29.4287l6.2606,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4573 1.7301,4.4344 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.442 -2.6086,1.7715 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187L28.3853,49.9272L25.4062,49.9272l-2.6226,-5.2586C22.1063,43.2956 21.4472,42.385 20.8065,41.9365c-0.6316,-0.4485 -1.4963,-0.6728 -2.5947,-0.6728L15.1913,41.2636l0,8.6636L12.4178,49.9272ZM37.1864,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8075,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259zM15.1913,31.7076l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_primary" android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M28.5078,0 L8.1241,20.3838a27.7366,27.7366 88.4859,0 0,0 39.2255,27.7366 27.7366,88.4859 0,0 39.2255,0L67.7333,39.2255ZM12.4178,29.4287l6.2606,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4573 1.7301,4.4344 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.442 -2.6086,1.7715 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187L28.3853,49.9272L25.4062,49.9272l-2.6226,-5.2586C22.1063,43.2956 21.4472,42.385 20.8065,41.9365c-0.6316,-0.4485 -1.4963,-0.6728 -2.5947,-0.6728L15.1913,41.2636l0,8.6636L12.4178,49.9272ZM37.1864,29.4287l2.7735,0l0,18.1643l4.5305,0l0,2.3342l-11.8075,0l0,-2.3342l4.531,0l0,-15.6383l-4.9289,0.9886l0,-2.5259zM15.1913,31.7076l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM40.6771,8.2563l2.3342,0L43.0113,25.8299l-2.3342,0L40.6771,11.5512l-3.1853,3.1853 -1.6474,-1.6474zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed" android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M20.3838,8.1241 L0,28.5078 39.2255,67.7333 59.6093,47.3496a27.7366,27.7366 88.4859,0 0,0 -39.2255,27.7366 27.7366,88.4859 0,0 -39.2255,0zM48.9278,15.1846c2.1235,0 3.8167,0.5309 5.0798,1.5927 1.2631,1.0618 1.895,2.4804 1.895,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9568,1.034 -2.1833,2.3063 -1.2265,1.2631 -2.956,3.0342 -5.1893,5.3134l9.679,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.384,-1.9769 -1.1529,-2.6634 -0.7597,-0.6865 -1.7531,-1.0299 -2.9797,-1.0299 -0.8695,-0 -1.7893,0.1511 -2.7595,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L43.1338,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM24.1593,15.5551l6.2611,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7296,2.4578 1.7296,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187l2.8148,5.6017l-2.9797,0l-2.6221,-5.2586c-0.6773,-1.373 -1.3364,-2.2836 -1.9771,-2.7321 -0.6316,-0.4485 -1.4968,-0.6728 -2.5952,-0.6728l-3.0205,0l0,8.6636L24.1593,36.0536ZM26.9327,17.8346l0,7.2766l3.4876,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0294,-1.5331 1.0294,-2.7321 0,-1.1991 -0.3429,-2.1006 -1.0294,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321C37.8899,8.3705 39.1211,8.0367 40.6771,8.0367ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_primary" android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp" android:width="256dp"
android:height="256dp" android:height="128dp"
android:viewportWidth="67.73333" android:viewportWidth="67.73333"
android:viewportHeight="67.73334"> android:viewportHeight="33.86667">
<path <path
android:pathData="M20.3838,8.1241 L0,28.5078 39.2255,67.7333 59.6093,47.3496a27.7366,27.7366 88.4859,0 0,0 -39.2255,27.7366 27.7366,88.4859 0,0 -39.2255,0zM48.9278,15.1846c2.1235,0 3.8167,0.5309 5.0798,1.5927 1.2631,1.0618 1.895,2.4804 1.895,4.2561 0,0.8421 -0.1602,1.6432 -0.4806,2.403 -0.3112,0.7506 -0.8832,1.6383 -1.7162,2.6634 -0.2288,0.2654 -0.9568,1.034 -2.1833,2.3063 -1.2265,1.2631 -2.956,3.0342 -5.1893,5.3134l9.679,0l0,2.3342l-13.0157,0l0,-2.3342c1.0526,-1.0892 2.4851,-2.549 4.2974,-4.3796 1.8215,-1.8398 2.9655,-3.025 3.4323,-3.5559 0.8879,-0.9977 1.5058,-1.84 1.8536,-2.5265 0.357,-0.6956 0.5354,-1.3777 0.5354,-2.0459 0,-1.0892 -0.384,-1.9769 -1.1529,-2.6634 -0.7597,-0.6865 -1.7531,-1.0299 -2.9797,-1.0299 -0.8695,-0 -1.7893,0.1511 -2.7595,0.4532 -0.9611,0.3021 -1.9908,0.7598 -3.0892,1.373L43.1338,16.5437c1.1167,-0.4485 2.1603,-0.7871 3.1306,-1.016 0.9702,-0.2288 1.8579,-0.3431 2.6634,-0.3431zM24.1593,15.5551l6.2611,0c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7296,2.4578 1.7296,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6313 1.7296,1.2904 0.5675,0.659 1.1352,1.5654 1.7027,2.7187l2.8148,5.6017l-2.9797,0l-2.6221,-5.2586c-0.6773,-1.373 -1.3364,-2.2836 -1.9771,-2.7321 -0.6316,-0.4485 -1.4968,-0.6728 -2.5952,-0.6728l-3.0205,0l0,8.6636L24.1593,36.0536ZM26.9327,17.8346l0,7.2766l3.4876,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0294,-1.5331 1.0294,-2.7321 0,-1.1991 -0.3429,-2.1006 -1.0294,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z" android:pathData="M0,0L0,33.8667L67.7333,33.8667L67.7333,0ZM40.6771,8.0367c1.556,0 2.7872,0.3659 3.6933,1.0981 0.9062,0.7322 1.3591,1.7348 1.3591,3.0071 0,0.4027 -0.0139,0.7136 -0.0413,0.9333 -0.0183,0.2105 -0.0867,0.4989 -0.2057,0.8651 -0.1098,0.357 -0.3021,0.7506 -0.5767,1.1808 -0.2746,0.421 -0.6453,0.9242 -1.1121,1.51l-5.6291,7.0435l7.7845,0L45.9491,25.8299l-10.5441,0l0,-2.1554l6.6999,-8.3886c0.4119,-0.5126 0.7142,-0.9612 0.9064,-1.3457 0.1922,-0.3936 0.3017,-0.6911 0.3292,-0.8925 0.0366,-0.2105 0.0548,-0.5123 0.0548,-0.9059 0,-0.6041 -0.2425,-1.0805 -0.7276,-1.4283 -0.4851,-0.3478 -1.1485,-0.5214 -1.9906,-0.5214 -0.8421,0 -1.506,0.1736 -1.9911,0.5214 -0.4851,0.3478 -0.7276,0.8242 -0.7276,1.4283l-2.3337,-0.371c0,-1.1533 0.4529,-2.064 1.3591,-2.7321C37.8899,8.3705 39.1211,8.0367 40.6771,8.0367ZM21.3455,8.2563L27.4417,8.2563c1.5286,0 2.6865,0.352 3.4737,1.0568 0.7963,0.7048 1.1942,1.8814 1.1942,3.529 -0,2.2517 -1.034,3.6703 -3.1027,4.2561L32.7685,25.8299L30.2286,25.8299L26.618,17.4413L23.6797,17.4413L23.6797,25.8299l-2.3342,0zM23.6797,10.4118l0,4.8741l2.3342,0c1.2265,0 2.1601,-0.188 2.8009,-0.5633 0.6407,-0.3753 0.9607,-1.0018 0.9607,-1.8805 0,-0.8695 -0.2014,-1.4923 -0.6041,-1.8676 -0.3936,-0.3753 -0.9699,-0.5628 -1.7296,-0.5628z"
android:strokeLineJoin="round" android:strokeLineJoin="round"
android:strokeWidth="5.54109" android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed" android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/> android:strokeLineCap="round"/>
</vector> </vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M67.7333,0C30.3252,0 0,30.3252 0,67.7333l109.6724,34.3597zM50.2982,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8402,2.2423 1.8402,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5744,1.318 -2.7735,1.6201 1.3272,0.2837 2.3618,0.8739 3.1032,1.771 0.7506,0.897 1.1255,2.0047 1.1255,3.3228 0,2.0228 -0.6954,3.5878 -2.0867,4.6953 -1.3913,1.1075 -3.3685,1.6614 -5.9314,1.6614 -0.8604,0 -1.7481,-0.0871 -2.6634,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0616,-0.3434 3.9677,-1.0299 0.9153,-0.6865 1.373,-1.6837 1.373,-2.9926 0,-1.2082 -0.4257,-2.1514 -1.2769,-2.8288 -0.8421,-0.6865 -2.0182,-1.0294 -3.5285,-1.0294l-2.389,0l0,-2.2794l2.4991,0c1.3638,0 2.4069,-0.2697 3.13,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.375,-1.858 -1.1255,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.0364,-0.5124 2.9518,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM25.2005,31.6957L31.4611,31.6957c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4578 1.7301,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6319 1.7296,1.2909 0.5675,0.659 1.1352,1.5649 1.7027,2.7182l2.8143,5.6017l-2.9791,0l-2.6226,-5.2581c-0.6773,-1.373 -1.3364,-2.2841 -1.9771,-2.7326 -0.6316,-0.4485 -1.4963,-0.6723 -2.5947,-0.6723l-3.0205,0l0,8.663L25.2005,52.1942ZM27.974,33.9752l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
android:strokeLineJoin="round"
android:strokeWidth="11.0688"
android:fillColor="@color/control_primary"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M67.7333,0C30.3252,0 0,30.3252 0,67.7333l109.6724,34.3597zM50.2982,31.3252c2.1052,0 3.7711,0.4807 4.9976,1.4418 1.2265,0.9519 1.8402,2.2423 1.8402,3.8716 0,1.135 -0.3253,2.0964 -0.9751,2.8835 -0.6499,0.778 -1.5744,1.318 -2.7735,1.6201 1.3272,0.2837 2.3618,0.8739 3.1032,1.771 0.7506,0.897 1.1255,2.0047 1.1255,3.3228 0,2.0228 -0.6954,3.5878 -2.0867,4.6953 -1.3913,1.1075 -3.3685,1.6614 -5.9314,1.6614 -0.8604,0 -1.7481,-0.0871 -2.6634,-0.261 -0.9062,-0.1648 -1.8441,-0.4163 -2.8143,-0.755l0,-2.6774c0.7689,0.4485 1.6106,0.7871 2.5259,1.016 0.9153,0.2288 1.8719,0.3431 2.8696,0.3431 1.7391,0 3.0616,-0.3434 3.9677,-1.0299 0.9153,-0.6865 1.373,-1.6837 1.373,-2.9926 0,-1.2082 -0.4257,-2.1514 -1.2769,-2.8288 -0.8421,-0.6865 -2.0182,-1.0294 -3.5285,-1.0294l-2.389,0l0,-2.2794l2.4991,0c1.3638,0 2.4069,-0.2697 3.13,-0.8098 0.7231,-0.5492 1.0847,-1.3365 1.0847,-2.3616 0,-1.0526 -0.375,-1.858 -1.1255,-2.4164 -0.7414,-0.5675 -1.808,-0.8511 -3.1993,-0.8511 -0.7597,0 -1.5742,0.0823 -2.4438,0.247 -0.8695,0.1648 -1.8261,0.4211 -2.8696,0.7689l0,-2.4717c1.0526,-0.2929 2.0364,-0.5124 2.9518,-0.6589 0.9245,-0.1464 1.794,-0.2196 2.6086,-0.2196zM25.2005,31.6957L31.4611,31.6957c2.3432,0 4.0913,0.4898 5.2446,1.4692 1.1533,0.9794 1.7301,2.4578 1.7301,4.4349 0,1.2906 -0.3018,2.3615 -0.9059,3.2127 -0.595,0.8512 -1.4645,1.4414 -2.6086,1.771 0.595,0.2014 1.1713,0.6319 1.7296,1.2909 0.5675,0.659 1.1352,1.5649 1.7027,2.7182l2.8143,5.6017l-2.9791,0l-2.6226,-5.2581c-0.6773,-1.373 -1.3364,-2.2841 -1.9771,-2.7326 -0.6316,-0.4485 -1.4963,-0.6723 -2.5947,-0.6723l-3.0205,0l0,8.663L25.2005,52.1942ZM27.974,33.9752l0,7.2766l3.4871,0c1.3364,0 2.3432,-0.3066 3.0205,-0.9198 0.6865,-0.6224 1.0299,-1.5331 1.0299,-2.7321 0,-1.1991 -0.3434,-2.1006 -1.0299,-2.7047 -0.6773,-0.6133 -1.6841,-0.9198 -3.0205,-0.9198z"
android:strokeLineJoin="round"
android:strokeWidth="11.0688"
android:fillColor="@color/control_pressed"
android:strokeLineCap="round"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M16.9333,4.2333C7.5523,4.2333 0,10.8416 0,19.05l0,29.6333c0,8.2084 7.5523,14.8167 16.9333,14.8167l33.8667,0c9.3811,0 16.9333,-6.6082 16.9333,-14.8167L67.7333,19.05C67.7333,10.8416 60.1811,4.2333 50.8,4.2333ZM11.8701,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042A3.7042,3.7042 0,0 1,22.9826 19.05,3.7042 3.7042,0 0,1 26.6867,15.3458ZM41.5034,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042z"
android:strokeLineJoin="round"
android:strokeWidth="22.6959"
android:fillColor="@color/control_primary"
android:strokeLineCap="round"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
<path
android:pathData="M16.9333,4.2333C7.5523,4.2333 0,10.8416 0,19.05l0,29.6333c0,8.2084 7.5523,14.8167 16.9333,14.8167l33.8667,0c9.3811,0 16.9333,-6.6082 16.9333,-14.8167L67.7333,19.05C67.7333,10.8416 60.1811,4.2333 50.8,4.2333ZM11.8701,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042A3.7042,3.7042 0,0 1,22.9826 19.05,3.7042 3.7042,0 0,1 26.6867,15.3458ZM41.5034,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,15.3458a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,30.1625a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,135 0,1 -3.7042,3.7042 3.7042,3.7042 135,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM11.8701,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM26.6867,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM41.5034,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042zM56.3201,44.9792a3.7042,3.7042 0,0 1,3.7042 3.7042,3.7042 3.7042,0 0,1 -3.7042,3.7042 3.7042,3.7042 0,0 1,-3.7042 -3.7042,3.7042 3.7042,0 0,1 3.7042,-3.7042z"
android:strokeLineJoin="round"
android:strokeWidth="22.6959"
android:fillColor="@color/control_pressed"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1920dp"
android:height="942dp"
android:viewportWidth="508"
android:viewportHeight="249.2375">
<path
android:pathData="M32,0L476,0A32,32 0,0 1,508 32L508,217.238A32,32 0,0 1,476 249.238L32,249.238A32,32 0,0 1,-0 217.238L-0,32A32,32 0,0 1,32 0z"
android:strokeLineJoin="round"
android:strokeWidth="1.59637"
android:fillColor="@color/control_primary"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1920dp"
android:height="942dp"
android:viewportWidth="508"
android:viewportHeight="249.2375">
<path
android:pathData="M32,0L476,0A32,32 0,0 1,508 32L508,217.238A32,32 0,0 1,476 249.238L32,249.238A32,32 0,0 1,-0 217.238L-0,32A32,32 0,0 1,32 0z"
android:strokeLineJoin="round"
android:strokeWidth="1.59637"
android:fillColor="@color/control_pressed"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/textColorPrimary"
android:pathData="M9,11.24V7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5C7,9.06 7.79,10.43 9,11.24zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11H13v-6C13,6.67 12.33,6 11.5,6S10,6.67 10,7.5v10.74c-3.6,-0.76 -3.54,-0.75 -3.67,-0.75c-0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8l4.94,4.94C9.96,23.83 10.34,24 10.75,24h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2C19.75,16.63 19.37,16.09 18.84,15.87z"/>
</vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/textColorPrimary"
android:pathData="M16.48,2.52c3.27,1.55 5.61,4.72 5.97,8.48h1.5C23.44,4.84 18.29,0 12,0l-0.66,0.03 3.81,3.81 1.33,-1.32zM10.23,1.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L1.75,8.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12L10.23,1.75zM14.83,21.19L2.81,9.17l6.36,-6.36 12.02,12.02 -6.36,6.36zM7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32z"/>
</vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/textColorPrimary"
android:pathData="M0,15h2L2,9L0,9v6zM3,17h2L5,7L3,7v10zM22,9v6h2L24,9h-2zM19,17h2L21,7h-2v10zM16.5,3h-9C6.67,3 6,3.67 6,4.5v15c0,0.83 0.67,1.5 1.5,1.5h9c0.83,0 1.5,-0.67 1.5,-1.5v-15c0,-0.83 -0.67,-1.5 -1.5,-1.5zM16,19L8,19L8,5h8v14z"/>
</vector>

View file

@ -1,24 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/mainStreamLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".stream.StreamActivity" tools:context=".stream.StreamActivity"
android:keepScreenOn="true"> android:keepScreenOn="true">
<com.metallic.chiaki.stream.AspectRatioFrameLayout <TextureView
android:id="@+id/aspectRatioLayout" android:id="@+id/textureView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"/>
android:layout_gravity="center">
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</com.metallic.chiaki.stream.AspectRatioFrameLayout>
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
@ -28,7 +20,7 @@
<fragment <fragment
android:id="@+id/controlsFragment" android:id="@+id/controlsFragment"
android:name="com.metallic.chiaki.touchcontrols.DefaultTouchControlsFragment" android:name="com.metallic.chiaki.touchcontrols.TouchControlsFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
@ -42,6 +34,7 @@
android:id="@+id/overlay" android:id="@+id/overlay"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="bottom"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -83,7 +76,6 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:singleSelection="true" app:singleSelection="true"
app:selectionRequired="true"
app:checkedButton="@id/display_mode_normal_button"> app:checkedButton="@id/display_mode_normal_button">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton

View file

@ -1,12 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false" android:clipChildren="false">
tools:ignore="RtlHardcoded,RtlSymmetry">
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView <com.metallic.chiaki.touchcontrols.ControlsBackgroundView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -47,34 +45,20 @@
app:drawableHandle="@drawable/control_analog_stick_handle" app:drawableHandle="@drawable/control_analog_stick_handle"
/> />
<com.metallic.chiaki.touchcontrols.TouchpadView
android:id="@+id/touchpadView"
android:layout_width="0dp"
android:layout_height="0dp"
app:drawableIdle="@drawable/control_touchpad"
app:drawablePressed="@drawable/control_touchpad_pressed"
android:layout_marginTop="32dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="300dp"
app:layout_constraintDimensionRatio="1920:942"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<com.metallic.chiaki.touchcontrols.DPadView <com.metallic.chiaki.touchcontrols.DPadView
android:id="@+id/dpadView" android:id="@+id/dpadView"
android:layout_width="160dp" android:layout_width="128dp"
android:layout_height="160dp" android:layout_height="128dp"
android:padding="16dp" android:layout_marginLeft="32dp"
android:layout_marginLeft="16dp" android:layout_marginBottom="32dp"
android:layout_marginBottom="16dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/faceButtonsLayout" android:id="@+id/faceButtonsLayout"
android:layout_width="@dimen/control_face_button_size_full" android:layout_width="144dp"
android:layout_height="@dimen/control_face_button_size_full" android:layout_height="144dp"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -83,12 +67,9 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/crossButtonView" android:id="@+id/crossButtonView"
android:layout_width="@dimen/control_face_button_size_full" android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size_half" android:layout_height="@dimen/control_face_button_size"
android:paddingLeft="@dimen/control_face_button_padding_to_full" android:padding="8dp"
android:paddingRight="@dimen/control_face_button_padding_to_full"
android:paddingTop="@dimen/control_face_button_padding_to_center"
android:paddingBottom="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_cross" app:drawableIdle="@drawable/control_button_cross"
app:drawablePressed="@drawable/control_button_cross_pressed" app:drawablePressed="@drawable/control_button_cross_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -97,12 +78,9 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/moonButtonView" android:id="@+id/moonButtonView"
android:layout_width="@dimen/control_face_button_size_half" android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size_full" android:layout_height="@dimen/control_face_button_size"
android:paddingTop="@dimen/control_face_button_padding_to_full" android:padding="8dp"
android:paddingBottom="@dimen/control_face_button_padding_to_full"
android:paddingLeft="@dimen/control_face_button_padding_to_center"
android:paddingRight="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_moon" app:drawableIdle="@drawable/control_button_moon"
app:drawablePressed="@drawable/control_button_moon_pressed" app:drawablePressed="@drawable/control_button_moon_pressed"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
@ -111,12 +89,9 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/pyramidButtonView" android:id="@+id/pyramidButtonView"
android:layout_width="@dimen/control_face_button_size_full" android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size_half" android:layout_height="@dimen/control_face_button_size"
android:paddingLeft="@dimen/control_face_button_padding_to_full" android:padding="8dp"
android:paddingRight="@dimen/control_face_button_padding_to_full"
android:paddingBottom="@dimen/control_face_button_padding_to_center"
android:paddingTop="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_pyramid" app:drawableIdle="@drawable/control_button_pyramid"
app:drawablePressed="@drawable/control_button_pyramid_pressed" app:drawablePressed="@drawable/control_button_pyramid_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -125,12 +100,9 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/boxButtonView" android:id="@+id/boxButtonView"
android:layout_width="@dimen/control_face_button_size_half" android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size_full" android:layout_height="@dimen/control_face_button_size"
android:paddingTop="@dimen/control_face_button_padding_to_full" android:padding="8dp"
android:paddingBottom="@dimen/control_face_button_padding_to_full"
android:paddingRight="@dimen/control_face_button_padding_to_center"
android:paddingLeft="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_box" app:drawableIdle="@drawable/control_button_box"
app:drawablePressed="@drawable/control_button_box_pressed" app:drawablePressed="@drawable/control_button_box_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -140,30 +112,12 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/l3ButtonView"
android:layout_width="64dp"
android:layout_height="64dp"
app:drawableIdle="@drawable/control_button_l3"
app:drawablePressed="@drawable/control_button_l3_pressed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/r3ButtonView"
android:layout_width="64dp"
android:layout_height="64dp"
app:drawableIdle="@drawable/control_button_r3"
app:drawablePressed="@drawable/control_button_r3_pressed"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/psButtonView" android:id="@+id/psButtonView"
android:layout_width="48dp" android:layout_width="32dp"
android:layout_height="48dp" android:layout_height="32dp"
android:padding="8dp" android:padding="8dp"
android:layout_marginBottom="8dp"
app:drawableIdle="@drawable/control_button_home" app:drawableIdle="@drawable/control_button_home"
app:drawablePressed="@drawable/control_button_home_pressed" app:drawablePressed="@drawable/control_button_home_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -171,14 +125,25 @@
app:layout_constraintBottom_toBottomOf="parent"/> app:layout_constraintBottom_toBottomOf="parent"/>
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/touchpadButtonView"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
app:drawableIdle="@drawable/control_button_touchpad"
app:drawablePressed="@drawable/control_button_touchpad_pressed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/l2ButtonView" android:id="@+id/l2ButtonView"
android:layout_width="88dp" android:layout_width="64dp"
android:layout_height="80dp" android:layout_height="32dp"
android:paddingTop="8dp" android:padding="8dp"
android:paddingBottom="8dp" android:layout_marginTop="8dp"
android:paddingRight="8dp" android:layout_marginLeft="8dp"
android:paddingLeft="16dp"
app:drawableIdle="@drawable/control_button_l2" app:drawableIdle="@drawable/control_button_l2"
app:drawablePressed="@drawable/control_button_l2_pressed" app:drawablePressed="@drawable/control_button_l2_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -186,22 +151,23 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/l1ButtonView" android:id="@+id/l1ButtonView"
android:layout_width="80dp" android:layout_width="64dp"
android:layout_height="80dp" android:layout_height="32dp"
android:padding="8dp" android:padding="8dp"
android:layout_marginTop="32dp" android:layout_marginTop="8dp"
android:layout_marginLeft="40dp" android:layout_marginLeft="8dp"
app:drawableIdle="@drawable/control_button_l1" app:drawableIdle="@drawable/control_button_l1"
app:drawablePressed="@drawable/control_button_l1_pressed" app:drawablePressed="@drawable/control_button_l1_pressed"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toBottomOf="@id/l2ButtonView"/>
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/shareButtonView" android:id="@+id/shareButtonView"
android:layout_width="48dp" android:layout_width="32dp"
android:layout_height="48dp" android:layout_height="32dp"
android:padding="8dp" android:padding="8dp"
android:layout_marginLeft="32dp" android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:drawableIdle="@drawable/control_button_share" app:drawableIdle="@drawable/control_button_share"
app:drawablePressed="@drawable/control_button_share_pressed" app:drawablePressed="@drawable/control_button_share_pressed"
app:layout_constraintLeft_toRightOf="@id/l2ButtonView" app:layout_constraintLeft_toRightOf="@id/l2ButtonView"
@ -209,12 +175,11 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/r2ButtonView" android:id="@+id/r2ButtonView"
android:layout_width="88dp" android:layout_width="64dp"
android:layout_height="80dp" android:layout_height="32dp"
android:paddingTop="8dp" android:padding="8dp"
android:paddingRight="16dp" android:layout_marginTop="8dp"
android:paddingLeft="8dp" android:layout_marginRight="8dp"
android:paddingBottom="8dp"
app:drawableIdle="@drawable/control_button_r2" app:drawableIdle="@drawable/control_button_r2"
app:drawablePressed="@drawable/control_button_r2_pressed" app:drawablePressed="@drawable/control_button_r2_pressed"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
@ -222,22 +187,23 @@
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/r1ButtonView" android:id="@+id/r1ButtonView"
android:layout_width="80dp" android:layout_width="64dp"
android:layout_height="80dp" android:layout_height="32dp"
android:padding="8dp" android:padding="8dp"
android:layout_marginTop="32dp" android:layout_marginTop="8dp"
android:layout_marginRight="40dp" android:layout_marginRight="8dp"
app:drawableIdle="@drawable/control_button_r1" app:drawableIdle="@drawable/control_button_r1"
app:drawablePressed="@drawable/control_button_r1_pressed" app:drawablePressed="@drawable/control_button_r1_pressed"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toBottomOf="@id/r2ButtonView"/>
<com.metallic.chiaki.touchcontrols.ButtonView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/optionsButtonView" android:id="@+id/optionsButtonView"
android:layout_width="48dp" android:layout_width="32dp"
android:layout_height="48dp" android:layout_height="32dp"
android:padding="8dp" android:padding="8dp"
android:layout_marginRight="32dp" android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:drawableIdle="@drawable/control_button_options" app:drawableIdle="@drawable/control_button_options"
app:drawablePressed="@drawable/control_button_options_pressed" app:drawablePressed="@drawable/control_button_options_pressed"
app:layout_constraintRight_toLeftOf="@id/r2ButtonView" app:layout_constraintRight_toLeftOf="@id/r2ButtonView"

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -13,18 +12,16 @@
tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="90dp" /> tools:layout_editor_absoluteY="90dp" />
<com.metallic.chiaki.touchcontrols.TouchpadView <com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/touchpadView" android:id="@+id/touchpadButtonView"
android:layout_width="0dp" android:layout_width="32dp"
android:layout_height="0dp" android:layout_height="32dp"
app:drawableIdle="@drawable/control_touchpad" android:layout_marginEnd="32dp"
app:drawablePressed="@drawable/control_touchpad_pressed" android:layout_marginBottom="8dp"
app:layout_constraintDimensionRatio="1920:942" android:padding="8dp"
app:layout_constraintLeft_toLeftOf="parent" app:drawableIdle="@drawable/control_button_touchpad"
app:layout_constraintRight_toRightOf="parent" app:drawablePressed="@drawable/control_button_touchpad_pressed"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginLeft="80dp" app:layout_constraintEnd_toEndOf="parent" />
android:layout_marginRight="80dp"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<attr name="drawableIdle" format="reference" />
<attr name="drawablePressed" format="reference" />
<declare-styleable name="ButtonView"> <declare-styleable name="ButtonView">
<attr name="drawableIdle" /> <attr name="drawableIdle" format="reference" />
<attr name="drawablePressed" /> <attr name="drawablePressed" format="integer" />
</declare-styleable> </declare-styleable>
<declare-styleable name="AnalogStickView"> <declare-styleable name="AnalogStickView">
@ -14,9 +11,4 @@
<attr name="drawableBase" format="reference" /> <attr name="drawableBase" format="reference" />
<attr name="drawableHandle" format="reference" /> <attr name="drawableHandle" format="reference" />
</declare-styleable> </declare-styleable>
<declare-styleable name="TouchpadView">
<attr name="drawableIdle" />
<attr name="drawablePressed" />
</declare-styleable>
</resources> </resources>

View file

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="control_face_button_size_half">88dp</dimen> <dimen name="control_face_button_size">48dp</dimen>
<dimen name="control_face_button_size_full">176dp</dimen>
<dimen name="control_face_button_padding_to_center">24dp</dimen>
<dimen name="control_face_button_padding_to_outside">16dp</dimen>
<dimen name="control_face_button_padding_to_full">64dp</dimen>
<dimen name="control_analog_stick_radius">48dp</dimen> <dimen name="control_analog_stick_radius">48dp</dimen>
<dimen name="control_analog_stick_handle_radius">32dp</dimen> <dimen name="control_analog_stick_handle_radius">32dp</dimen>
<dimen name="floating_action_button_speed_dial_anim_offset">48dp</dimen> <dimen name="floating_action_button_speed_dial_anim_offset">48dp</dimen>

View file

@ -88,12 +88,6 @@
<string name="preferences_codec_title_h265">H265 (PS5 only)</string> <string name="preferences_codec_title_h265">H265 (PS5 only)</string>
<string name="preferences_swap_cross_moon_title">Swap Cross/Moon and Box/Pyramid Buttons</string> <string name="preferences_swap_cross_moon_title">Swap Cross/Moon and Box/Pyramid Buttons</string>
<string name="preferences_swap_cross_moon_summary">Swap face buttons if default mapping is incorrect (e.g. for 8BitDo controllers)</string> <string name="preferences_swap_cross_moon_summary">Swap face buttons if default mapping is incorrect (e.g. for 8BitDo controllers)</string>
<string name="preferences_rumble_enabled_title">Rumble</string>
<string name="preferences_rumble_enabled_summary">Use phone vibration motor for rumble</string>
<string name="preferences_motion_enabled_title">Motion</string>
<string name="preferences_motion_enabled_summary">Use device\'s motion sensors for controller motion</string>
<string name="preferences_button_haptic_enabled_title">Touch Haptics</string>
<string name="preferences_button_haptic_enabled_summary">Use phone vibration motor for short haptic feedback on button touches</string>
<string name="alert_message_delete_registered_host">Are you sure you want to delete the registered console %s with ID %s?</string> <string name="alert_message_delete_registered_host">Are you sure you want to delete the registered console %s with ID %s?</string>
<string name="alert_message_delete_manual_host">Are you sure you want to delete the console entry for %s?</string> <string name="alert_message_delete_manual_host">Are you sure you want to delete the console entry for %s?</string>
<string name="action_keep">Keep</string> <string name="action_keep">Keep</string>
@ -107,10 +101,7 @@
<!-- Don't localize these --> <!-- Don't localize these -->
<string name="preferences_discovery_enabled_key">discovery_enabled</string> <string name="preferences_discovery_enabled_key">discovery_enabled</string>
<string name="preferences_on_screen_controls_enabled_key">on_screen_controls_enabled</string> <string name="preferences_on_screen_controls_enabled_key">on_screen_controls_enabled</string>
<string name="preferences_touchpad_only_enabled_key">touchpad_only_enabled</string> <string name="preferences_touchpad_only_key">touchpad_only_enabled</string>
<string name="preferences_rumble_enabled_key">rumble_enabled</string>
<string name="preferences_motion_enabled_key">motion_enabled</string>
<string name="preferences_button_haptic_enabled_key">button_haptic_enabled</string>
<string name="preferences_log_verbose_key">log_verbose</string> <string name="preferences_log_verbose_key">log_verbose</string>
<string name="preferences_import_settings_key">import_settings</string> <string name="preferences_import_settings_key">import_settings</string>
<string name="preferences_export_settings_key">export_settings</string> <string name="preferences_export_settings_key">export_settings</string>

View file

@ -19,24 +19,6 @@
app:summary="@string/preferences_swap_cross_moon_summary" app:summary="@string/preferences_swap_cross_moon_summary"
app:icon="@drawable/ic_gamepad" /> app:icon="@drawable/ic_gamepad" />
<SwitchPreference
app:key="@string/preferences_rumble_enabled_key"
app:title="@string/preferences_rumble_enabled_title"
app:summary="@string/preferences_rumble_enabled_summary"
app:icon="@drawable/ic_rumble" />
<SwitchPreference
app:key="@string/preferences_motion_enabled_key"
app:title="@string/preferences_motion_enabled_title"
app:summary="@string/preferences_motion_enabled_summary"
app:icon="@drawable/ic_motion" />
<SwitchPreference
app:key="@string/preferences_button_haptic_enabled_key"
app:title="@string/preferences_button_haptic_enabled_title"
app:summary="@string/preferences_button_haptic_enabled_summary"
app:icon="@drawable/ic_button_haptic" />
<SwitchPreference <SwitchPreference
app:key="@string/preferences_log_verbose_key" app:key="@string/preferences_log_verbose_key"
app:title="@string/preferences_log_verbose_title" app:title="@string/preferences_log_verbose_title"

View file

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

View file

@ -1,6 +1,6 @@
#Sun Feb 05 16:25:19 CET 2023 #Wed Mar 11 18:48:31 CET 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

View file

@ -1,266 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -1,102 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -5,13 +5,37 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="l1.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8" id="svg8"
version="1.1" version="1.1"
viewBox="0 0 67.733332 67.733336" viewBox="0 0 67.733332 33.866668"
height="256" height="128"
width="256"> width="256">
<defs <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="15"
inkscape:window-x="1920"
inkscape:window-height="1048"
inkscape:window-width="1918"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="61.042937"
inkscape:cx="87.179174"
inkscape:zoom="2.8"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#000000"
id="base" />
<metadata <metadata
id="metadata5"> id="metadata5">
<rdf:RDF> <rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<g <g
id="g2115" style="display:inline"
style="display:inline"> id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
y="0"
x="0"
height="33.866665"
width="67.73333"
id="rect1406"
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve" />
<path <path
id="path2031" inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" transform="scale(0.26458333)"
d="M 148.25391,0 0,148.25391 77.041016,225.29492 a 104.83116,104.83117 0 0 0 148.253904,0 104.83116,104.83117 0 0 0 0,-148.253904 z M 96.048828,111.22656 h 10.482422 v 68.65235 h 37.72656 v 8.82226 H 96.048828 Z m 78.980472,0 h 10.48242 v 68.65235 h 17.12305 v 8.82226 h -44.62696 v -8.82226 h 17.125 v -59.10547 l -18.6289,3.73633 v -9.54688 z" d="M 0,0 V 128 H 256 V 0 Z m 82.337891,31.205078 h 8.820312 V 89.478516 H 120.5293 V 97.625 H 82.337891 Z m 71.402339,0 h 8.82227 V 97.625 h -8.82227 V 43.658203 l -12.03906,12.039063 -6.22656,-6.226563 z"
transform="scale(0.26458334)" /> style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
id="rect1518" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -5,13 +5,37 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="l2.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8" id="svg8"
version="1.1" version="1.1"
viewBox="0 0 67.733332 67.733336" viewBox="0 0 67.733332 33.866668"
height="256" height="128"
width="256"> width="256">
<defs <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="15"
inkscape:window-x="1920"
inkscape:window-height="1048"
inkscape:window-width="1918"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="66.072659"
inkscape:cx="112.07001"
inkscape:zoom="2.8"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#000000"
id="base" />
<metadata <metadata
id="metadata5"> id="metadata5">
<rdf:RDF> <rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<g <g
id="g2135" style="display:inline"
style="display:inline"> id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
y="0"
x="0"
height="33.866665"
width="67.73333"
id="rect1406"
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve" />
<path <path
id="path2127" inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" transform="scale(0.26458333)"
d="m 104.51367,0 a 104.83116,104.83117 0 0 0 -73.808592,30.705078 104.83116,104.83117 0 0 0 0,148.253902 L 107.74609,256 256,107.74609 178.95898,30.705078 A 104.83116,104.83117 0 0 0 104.51367,0 Z m 27.39844,57.390625 c 8.02592,0 14.42713,2.00657 19.20117,6.019531 4.77404,4.012961 7.16016,9.374608 7.16016,16.085938 0,3.182692 -0.6056,6.210686 -1.81641,9.082031 -1.17621,2.836747 -3.33823,6.191824 -6.48633,10.066406 -0.86486,1.003241 -3.61434,3.908169 -8.25,8.716799 -4.63566,4.77404 -11.17418,11.468 -19.61523,20.08203 h 36.58398 v 8.82226 h -49.19336 v -8.82226 c 3.97837,-4.11675 9.39248,-9.63383 16.24219,-16.55274 6.8843,-6.95349 11.20834,-11.432968 12.97266,-13.439448 3.35566,-3.770799 5.69127,-6.954243 7.00586,-9.548828 1.34918,-2.629183 2.02343,-5.207025 2.02343,-7.732422 0,-4.116745 -1.45343,-7.471821 -4.35937,-10.066406 -2.87134,-2.594588 -6.62411,-3.892578 -11.25977,-3.892578 -3.28647,-10e-7 -6.76462,0.571271 -10.43164,1.71289 -3.63242,1.141619 -7.52444,2.871623 -11.67578,5.189453 V 62.527344 c 4.22053,-1.695131 8.16502,-2.974982 11.83203,-3.839844 3.66702,-0.864862 7.0221,-1.296875 10.06641,-1.296875 z m -78.978516,1.400391 h 10.482422 v 68.652344 h 37.724604 v 8.82226 H 52.933594 Z" d="M 0,0 V 128 H 256 V 0 Z m 153.74023,30.375 c 5.88107,0 10.53413,1.382832 13.95899,4.150391 3.42485,2.767558 5.13672,6.556599 5.13672,11.365234 0,1.522157 -0.0525,2.697075 -0.15625,3.527344 -0.0692,0.795671 -0.32762,1.88575 -0.77735,3.269531 -0.41513,1.349186 -1.14185,2.83695 -2.17968,4.462891 -1.03784,1.591347 -2.43881,3.492984 -4.20313,5.707031 l -21.27539,26.621094 h 29.42188 V 97.625 h -39.85157 v -8.146484 l 25.32227,-31.705078 c 1.55675,-1.937291 2.6993,-3.632969 3.42578,-5.085938 0.72648,-1.487564 1.14035,-2.611968 1.24414,-3.373047 0.13843,-0.795674 0.20703,-1.936266 0.20703,-3.423828 0,-2.283238 -0.91649,-4.083848 -2.75,-5.398437 -1.83351,-1.314591 -4.34074,-1.970704 -7.52344,-1.970704 -3.18269,0 -5.69188,0.656113 -7.52539,1.970704 -1.8335,1.314589 -2.75,3.115199 -2.75,5.398437 l -8.82031,-1.402344 c 0,-4.358904 1.71187,-7.800773 5.13672,-10.326172 3.42485,-2.525397 8.07792,-3.787109 13.95898,-3.787109 z m -71.402339,0.830078 h 8.820312 V 89.478516 H 120.5293 V 97.625 H 82.337891 Z"
transform="scale(0.26458334)" /> style="fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
id="rect1462" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before After
Before After

View file

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
width="256">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="display:inline"
id="layer1">
<path
id="path1554"
style="fill:#ffffff;stroke-width:11.0688;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 0,0 -158.50977,385.86328 256,256 C 256,114.61511 141.38489,0 0,0 Z m 127.02734,118.39453 c 7.95674,0 14.25301,1.8168 18.88868,5.44922 4.63566,3.59783 6.95312,8.47499 6.95312,14.63281 0,4.28972 -1.22934,7.92331 -3.68555,10.89844 -2.4562,2.94053 -5.94857,4.98143 -10.48047,6.12305 5.01622,1.07243 8.92441,3.30309 11.72657,6.69336 2.83674,3.39026 4.25586,7.57698 4.25586,12.55859 0,7.64538 -2.63031,13.56016 -7.88867,17.74609 -5.25838,4.18594 -12.72957,6.2793 -22.41602,6.2793 -3.25188,0 -6.60891,-0.32903 -10.06836,-0.98633 -3.42485,-0.6227 -6.9697,-1.57352 -10.63672,-2.85351 v -10.11914 c 2.90594,1.69512 6.08743,2.97498 9.54688,3.83984 3.45945,0.86486 7.0749,1.29689 10.8457,1.29687 6.57295,10e-6 11.57319,-1.29799 14.99805,-3.89257 3.45945,-2.59459 5.1875,-6.36354 5.1875,-11.31055 0,-4.56647 -1.60693,-8.13141 -4.82422,-10.69141 -3.18269,-2.59458 -7.6298,-3.89062 -13.33789,-3.89062 h -9.02735 v -8.61524 h 9.44336 c 5.15458,0 9.09907,-1.01947 11.83203,-3.06054 2.73297,-2.07567 4.09961,-5.0512 4.09961,-8.92578 0,-3.97837 -1.41911,-7.02255 -4.25586,-9.13282 -2.80215,-2.14486 -6.83343,-3.21679 -12.09179,-3.21679 -2.87135,0 -5.94986,0.31089 -9.23633,0.93359 -3.28648,0.6227 -6.90193,1.59166 -10.8457,2.90625 v -9.3418 c 3.97836,-1.10702 7.69875,-1.93672 11.1582,-2.49023 3.49404,-0.55351 6.78046,-0.83008 9.85937,-0.83008 z m -80.224606,1.40039 h 10.482422 v 68.6543 h 37.72461 v 8.82031 H 46.802734 Z"
transform="scale(0.26458334)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
width="256">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="display:inline"
id="layer1">
<path
id="path1554"
style="fill:#ffffff;stroke-width:2.92862;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 0,0 C 37.408085,0 67.73333,30.325245 67.73333,67.73333 L -41.939116,102.09299 Z" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="translate(13.609727,26.364208)"><tspan
x="-3.9868231"
y="25.830172"><tspan>L3</tspan></tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
width="256"
sodipodi:docname="lr12.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1031"
id="namedview1468"
showgrid="false"
inkscape:zoom="0.79980469"
inkscape:cx="101.38147"
inkscape:cy="95.943219"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="g2115"
inkscape:label="l1"
style="display:inline">
<path
id="path2031"
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 39.225383,0 0,39.225383 20.383723,59.609106 a 27.736579,27.73658 0 0 0 39.225787,4.04e-4 27.736579,27.73658 0 0 0 -4.04e-4,-39.225787 z" />
<text
id="text1404-4"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="translate(26.639768,24.096855)"><tspan
x="-3.9868231"
y="25.830172"><tspan>L1</tspan></tspan></text>
</g>
<g
id="g2125"
inkscape:label="r1"
style="display:inline">
<path
id="path2117"
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 28.507951,0 67.733334,39.225383 47.349611,59.609106 a 27.736579,27.73658 0 0 1 -39.2257874,4.04e-4 27.736579,27.73658 0 0 1 4.04e-4,-39.225787 z" />
<text
id="text2123"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="translate(13.644494,24.096798)"><tspan
x="-3.9868231"
y="25.830172"><tspan>R1</tspan></tspan></text>
</g>
<g
id="g2135"
inkscape:label="l2"
style="display:inline">
<path
id="path2127"
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 28.507951,67.733335 67.733334,28.507952 47.349611,8.1242288 a 27.736579,27.73658 0 0 0 -39.2257874,-4.04e-4 27.736579,27.73658 0 0 0 4.04e-4,39.2257872 z" />
<text
id="text2133"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="translate(15.231995,10.223453)"><tspan
x="-3.9868231"
y="25.830172"><tspan>L2</tspan></tspan></text>
</g>
<g
id="g2145"
inkscape:label="r2"
style="display:inline"
transform="matrix(-1,0,0,1,67.733334,0)">
<path
id="path2137"
style="fill:#ffffff;stroke-width:1.46608;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 28.507951,67.733335 67.733334,28.507952 47.349611,8.1242288 a 27.736579,27.73658 0 0 0 -39.2257874,-4.04e-4 27.736579,27.73658 0 0 0 4.04e-4,39.2257872 z" />
<text
id="text2143"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="matrix(-1,0,0,1,42.347278,10.223453)"><tspan
x="-3.9868231"
y="25.830172"><tspan>R2</tspan></tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -5,13 +5,37 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="r1.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8" id="svg8"
version="1.1" version="1.1"
viewBox="0 0 67.733332 67.733336" viewBox="0 0 67.733332 33.866668"
height="256" height="128"
width="256"> width="256">
<defs <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="15"
inkscape:window-x="1920"
inkscape:window-height="1048"
inkscape:window-width="1918"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="56.825844"
inkscape:cx="96.071037"
inkscape:zoom="2.8"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#000000"
id="base" />
<metadata <metadata
id="metadata5"> id="metadata5">
<rdf:RDF> <rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<g <g
id="g2125" style="display:inline"
style="display:inline"> id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
y="0"
x="0"
height="33.866665"
width="67.73333"
id="rect1406"
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve" />
<path <path
id="path2117" inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" transform="scale(0.26458333)"
d="M 107.74609,0 30.705078,77.041016 a 104.83116,104.83117 0 0 0 0,148.253904 104.83116,104.83117 0 0 0 148.253902,0 L 256,148.25391 Z M 46.933594,111.22656 h 23.662109 c 8.856189,0 15.463362,1.85113 19.822266,5.55274 4.358906,3.70161 6.539062,9.28735 6.539062,16.75976 0,4.87783 -1.140593,8.92529 -3.423828,12.14258 -2.248642,3.21729 -5.535064,5.44991 -9.859375,6.69531 2.248643,0.76108 4.426845,2.38615 6.53711,4.87696 2.144856,2.4908 4.290687,5.91648 6.435546,10.27539 L 107.2832,188.70117 H 96.023438 l -9.91211,-19.875 C 83.551336,163.637 81.060286,160.19513 78.638672,158.5 c -2.387019,-1.69513 -5.655301,-2.54297 -9.806641,-2.54297 H 57.416016 v 32.74414 H 46.933594 Z m 93.613286,0 h 10.48242 v 68.65235 h 17.12304 v 8.82226 h -44.62695 v -8.82226 h 17.125 v -59.10547 l -18.62891,3.73633 v -9.54688 z m -83.130864,8.61328 v 27.50196 h 13.179687 c 5.050794,0 8.856023,-1.15874 11.416016,-3.47657 2.594587,-2.35242 3.892578,-5.79429 3.892578,-10.32617 0,-4.53188 -1.297991,-7.93942 -3.892578,-10.22265 -2.559993,-2.31783 -6.365222,-3.47657 -11.416016,-3.47657 z" d="M 0,0 V 128 H 256 V 0 Z M 80.675781,31.205078 H 103.7168 c 5.77728,0 10.15378,1.330365 13.1289,3.994141 3.00972,2.663775 4.51367,7.110882 4.51368,13.33789 -1e-5,8.510244 -3.90821,13.871891 -11.72657,16.085938 L 123.84961,97.625 H 114.25 L 100.60352,65.919922 H 89.498047 V 97.625 h -8.822266 z m 73.064449,0 h 8.82227 V 97.625 h -8.82227 V 43.658203 l -12.03906,12.039063 -6.22656,-6.226563 z m -64.242183,8.146484 v 18.421876 h 8.822265 c 4.635658,0 8.164328,-0.710533 10.585938,-2.128907 2.42161,-1.418373 3.63086,-3.786351 3.63086,-7.107422 0,-3.286475 -0.76105,-5.640217 -2.2832,-7.058593 -1.48757,-1.418374 -3.66577,-2.126954 -6.53711,-2.126954 z"
transform="scale(0.26458334)" /> style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
id="rect1556" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before After
Before After

View file

@ -5,13 +5,37 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="r2.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8" id="svg8"
version="1.1" version="1.1"
viewBox="0 0 67.733332 67.733336" viewBox="0 0 67.733332 33.866668"
height="256" height="128"
width="256"> width="256">
<defs <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="15"
inkscape:window-x="1920"
inkscape:window-height="1048"
inkscape:window-width="1918"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="56.825844"
inkscape:cx="96.071037"
inkscape:zoom="2.8"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#000000"
id="base" />
<metadata <metadata
id="metadata5"> id="metadata5">
<rdf:RDF> <rdf:RDF>
@ -25,13 +49,28 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<g <g
id="g2145"
style="display:inline" style="display:inline"
transform="matrix(-1,0,0,1,67.733334,0)"> id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
y="0"
x="0"
height="33.866665"
width="67.73333"
id="rect1406"
style="display:none;fill:#ffffff;stroke:none;stroke-width:6.28119;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve" />
<path <path
id="path2137" inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill" transform="scale(0.26458333)"
d="M 77.041016,30.705078 0,107.74609 148.25391,256 225.29492,178.95898 a 104.83116,104.83117 0 0 0 0,-148.253902 104.83116,104.83117 0 0 0 -148.253904,0 z M 184.92383,57.390625 c 8.02592,0 14.42518,2.00657 19.19922,6.019531 4.77403,4.012961 7.16211,9.374608 7.16211,16.085938 0,3.182692 -0.6056,6.210686 -1.81641,9.082031 -1.17621,2.836747 -3.33823,6.191824 -6.48633,10.066406 -0.86486,1.003241 -3.61629,3.908169 -8.25195,8.716799 -4.63566,4.77404 -11.17223,11.468 -19.61328,20.08203 h 36.58203 v 8.82226 h -49.19336 v -8.82226 c 3.97837,-4.11675 9.39248,-9.63383 16.24219,-16.55274 6.8843,-6.95349 11.20833,-11.432968 12.97265,-13.439448 3.35567,-3.770799 5.69127,-6.954243 7.00586,-9.548828 1.34919,-2.629183 2.02344,-5.207025 2.02344,-7.732422 0,-4.116745 -1.45148,-7.471821 -4.35742,-10.066406 -2.87134,-2.594588 -6.62606,-3.892578 -11.26172,-3.892578 -3.28648,-10e-7 -6.76267,0.571271 -10.42969,1.71289 -3.63242,1.141619 -7.52444,2.871623 -11.67578,5.189453 V 62.527344 c 4.22053,-1.695131 8.16502,-2.974982 11.83203,-3.839844 3.66702,-0.864862 7.02209,-1.296875 10.06641,-1.296875 z m -93.613283,1.400391 h 23.664063 c 8.85619,0 15.46335,1.851125 19.82227,5.552734 4.3589,3.701611 6.5371,9.289311 6.5371,16.761719 0,4.877823 -1.14059,8.92529 -3.42382,12.142578 -2.24865,3.217287 -5.53507,5.447957 -9.85938,6.693359 2.24864,0.761074 4.42685,2.386144 6.53711,4.876954 2.14486,2.4908 4.29069,5.91648 6.43555,10.27539 l 10.63867,21.17187 h -11.26172 l -9.91016,-19.875 c -2.55999,-5.18917 -5.05104,-8.63104 -7.47265,-10.32617 -2.38702,-1.69513 -5.65726,-2.54297 -9.8086,-2.54297 h -11.41601 v 32.74414 H 91.310547 Z m 10.482423,8.615234 v 27.501953 h 13.18164 c 5.05079,0 8.85602,-1.158732 11.41601,-3.476562 2.5946,-2.352424 3.89063,-5.794292 3.89063,-10.326172 0,-4.531878 -1.29603,-7.93942 -3.89063,-10.222657 -2.55999,-2.31783 -6.36522,-3.476562 -11.41601,-3.476562 z" d="M 0,0 V 128 H 256 V 0 Z m 153.74023,30.375 c 5.88107,0 10.53413,1.382832 13.95899,4.150391 3.42485,2.767558 5.13672,6.556599 5.13672,11.365234 0,1.522157 -0.0525,2.697075 -0.15625,3.527344 -0.0692,0.795671 -0.32762,1.88575 -0.77735,3.269531 -0.41513,1.349186 -1.14185,2.83695 -2.17968,4.462891 -1.03784,1.591347 -2.43881,3.492984 -4.20313,5.707031 l -21.27539,26.621094 h 29.42188 V 97.625 h -39.85157 v -8.146484 l 25.32227,-31.705078 c 1.55675,-1.937291 2.6993,-3.632969 3.42578,-5.085938 0.72648,-1.487564 1.14035,-2.611968 1.24414,-3.373047 0.13843,-0.795674 0.20703,-1.936266 0.20703,-3.423828 0,-2.283238 -0.91649,-4.083848 -2.75,-5.398437 -1.83351,-1.314591 -4.34074,-1.970704 -7.52344,-1.970704 -3.18269,0 -5.69188,0.656113 -7.52539,1.970704 -1.8335,1.314589 -2.75,3.115199 -2.75,5.398437 l -8.82031,-1.402344 c 0,-4.358904 1.71187,-7.800773 5.13672,-10.326172 C 143.2061,31.636712 147.85917,30.375 153.74023,30.375 Z M 80.675781,31.205078 H 103.7168 c 5.77728,0 10.15378,1.330365 13.1289,3.994141 3.00972,2.663775 4.51367,7.110882 4.51368,13.33789 -1e-5,8.510244 -3.90821,13.871891 -11.72657,16.085938 L 123.84961,97.625 H 114.25 L 100.60352,65.919922 H 89.498047 V 97.625 h -8.822266 z m 8.822266,8.146484 v 18.421876 h 8.822265 c 4.635658,0 8.164328,-0.710533 10.585938,-2.128907 2.42161,-1.418373 3.63086,-3.786351 3.63086,-7.107422 0,-3.286475 -0.76105,-5.640217 -2.2832,-7.058593 -1.48757,-1.418374 -3.66577,-2.126954 -6.53711,-2.126954 z"
transform="matrix(-0.26458334,0,0,0.26458334,67.733334,0)" /> style="display:inline;fill:#ffffff;stroke:none;stroke-width:23.7399;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke markers fill"
id="rect1556" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Before After
Before After

View file

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
width="256">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="display:inline"
id="layer1">
<path
id="path1554"
style="fill:#ffffff;stroke-width:11.0688;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 256,0 C 114.61511,0 0,114.61511 0,256 l 414.50977,129.86328 z m -65.89648,118.39453 c 7.95673,0 14.25301,1.8168 18.88867,5.44922 4.63566,3.59783 6.95508,8.47499 6.95508,14.63281 0,4.28972 -1.22934,7.92331 -3.68555,10.89844 -2.45621,2.94053 -5.95055,4.98143 -10.48242,6.12305 5.0162,1.07243 8.92636,3.30309 11.72851,6.69336 2.83675,3.39026 4.25391,7.57698 4.25391,12.55859 0,7.64538 -2.62836,13.56016 -7.88672,17.74609 -5.25836,4.18594 -12.73151,6.2793 -22.41797,6.2793 -3.25188,0 -6.60695,-0.32903 -10.06641,-0.98633 -3.42484,-0.6227 -6.9697,-1.57352 -10.63671,-2.85351 v -10.11914 c 2.90592,1.69512 6.08742,2.97498 9.54687,3.83984 3.45945,0.86486 7.07492,1.29689 10.8457,1.29687 6.57297,2e-5 11.57124,-1.29799 14.9961,-3.89257 3.45945,-2.59459 5.18945,-6.36354 5.18945,-11.31055 0,-4.56647 -1.60888,-8.13141 -4.82617,-10.69141 -3.18269,-2.59458 -7.62785,-3.89062 -13.33594,-3.89062 h -9.0293 v -8.61524 h 9.44532 c 5.15458,0 9.09711,-1.01947 11.83008,-3.06054 2.73296,-2.07567 4.0996,-5.0512 4.0996,-8.92578 2e-5,-3.97838 -1.41715,-7.02255 -4.2539,-9.13282 -2.80215,-2.14485 -6.83343,-3.21679 -12.0918,-3.21679 -2.87134,0 -5.94985,0.31089 -9.23633,0.93359 -3.28647,0.6227 -6.90193,1.59166 -10.8457,2.90625 v -9.3418 c 3.97837,-1.10702 7.6968,-1.93672 11.15625,-2.49023 3.49404,-0.55349 6.78046,-0.83008 9.85938,-0.83008 z m -94.857426,1.40039 H 118.9082 c 8.85619,0 15.46336,1.85113 19.82227,5.55274 4.35891,3.70161 6.53906,9.28931 6.53906,16.76172 0,4.87782 -1.14059,8.92529 -3.42383,12.14257 -2.24864,3.21729 -5.53506,5.44796 -9.85937,6.69336 2.24864,0.76108 4.42684,2.3881 6.53711,4.87891 2.14485,2.4908 4.29069,5.91453 6.43554,10.27344 l 10.63672,21.17187 h -11.25976 l -9.91211,-19.87305 c -2.55999,-5.18916 -5.05104,-8.63299 -7.47266,-10.32812 -2.38702,-1.69513 -5.6553,-2.54102 -9.80664,-2.54102 h -11.41601 v 32.74219 H 95.246094 Z m 10.482426,8.61524 v 27.50195 h 13.17968 c 5.0508,0 8.85603,-1.15873 11.41602,-3.47656 2.59459,-2.35243 3.89258,-5.79429 3.89258,-10.32617 0,-4.53189 -1.29799,-7.93942 -3.89258,-10.22266 -2.55999,-2.31783 -6.36522,-3.47656 -11.41602,-3.47656 z"
transform="scale(0.26458333)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3 KiB

View file

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
width="256">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="display:inline"
id="layer1">
<path
id="path1554"
style="fill:#ffffff;stroke-width:2.92862;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="M 67.733333,0 C 30.325248,0 3.2333333e-6,30.325245 3.2333333e-6,67.73333 L 109.67245,102.09299 Z" />
<text
id="text1404"
y="25.830172"
x="-3.9868231"
style="font-style:normal;font-weight:normal;font-size:28.1184px;line-height:1.25;font-family:sans-serif;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;inline-size:75.2671;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.70296"
xml:space="preserve"
transform="translate(26.427202,26.364208)"><tspan
x="-3.9868231"
y="25.830172"><tspan>R3</tspan></tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1920"
height="942"
viewBox="0 0 507.99999 249.23751"
version="1.1"
id="svg981"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="touchpad_surface.svg">
<defs
id="defs975" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.24748737"
inkscape:cx="876.84187"
inkscape:cy="725.61319"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="1916"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata978">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke-width:1.59637;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
id="rect1544"
width="508"
height="249.2375"
x="-1.7763568e-15"
y="0"
rx="32"
ry="32" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View file

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

View file

@ -142,19 +142,13 @@ CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[]
return 1; return 1;
} }
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4); // TODO: IPv6, PS5, should probably use the service
ChiakiDiscoveryPacket packet; ChiakiDiscoveryPacket packet;
memset(&packet, 0, sizeof(packet)); memset(&packet, 0, sizeof(packet));
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH; packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS4;
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4); chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
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) while(1)
sleep(1); // TODO: wtf sleep(1); // TODO: wtf

View file

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

View file

@ -49,11 +49,7 @@ function (_ffmpeg_find component headername)
# Try pkg-config first # Try pkg-config first
if(PKG_CONFIG_FOUND) if(PKG_CONFIG_FOUND)
if(CMAKE_VERSION VERSION_LESS "3.6")
pkg_check_modules(FFMPEG_${component} lib${component})
else()
pkg_check_modules(FFMPEG_${component} lib${component} IMPORTED_TARGET) pkg_check_modules(FFMPEG_${component} lib${component} IMPORTED_TARGET)
endif()
if(FFMPEG_${component}_FOUND) if(FFMPEG_${component}_FOUND)
if((TARGET PkgConfig::FFMPEG_${component}) AND (NOT CMAKE_VERSION VERSION_LESS "3.11.0")) if((TARGET PkgConfig::FFMPEG_${component}) AND (NOT CMAKE_VERSION VERSION_LESS "3.11.0"))
if(APPLE) if(APPLE)
@ -73,9 +69,6 @@ function (_ffmpeg_find component headername)
add_library(FFMPEG::${component} ALIAS PkgConfig::FFMPEG_${component}) add_library(FFMPEG::${component} ALIAS PkgConfig::FFMPEG_${component})
else() else()
add_library("FFMPEG::${component}" INTERFACE IMPORTED) add_library("FFMPEG::${component}" INTERFACE IMPORTED)
if(CMAKE_VERSION VERSION_LESS "3.6")
link_directories("${FFMPEG_${component}_LIBRARY_DIRS}")
endif()
set_target_properties("FFMPEG::${component}" PROPERTIES set_target_properties("FFMPEG::${component}" PROPERTIES
INTERFACE_LINK_DIRECTORIES "${FFMPEG_${component}_LIBRARY_DIRS}" INTERFACE_LINK_DIRECTORIES "${FFMPEG_${component}_LIBRARY_DIRS}"
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_${component}_INCLUDE_DIRS}" INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_${component}_INCLUDE_DIRS}"
@ -231,14 +224,10 @@ foreach (_ffmpeg_component IN LISTS FFMPEG_FIND_COMPONENTS)
list(APPEND _ffmpeg_required_vars list(APPEND _ffmpeg_required_vars
"FFMPEG_${_ffmpeg_component}_LIBRARIES") "FFMPEG_${_ffmpeg_component}_LIBRARIES")
else() else()
if(NOT FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS)
set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}") "${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}")
endif()
if(NOT FFMPEG_${_ffmpeg_component}_LIBRARIES)
set(FFMPEG_${_ffmpeg_component}_LIBRARIES set(FFMPEG_${_ffmpeg_component}_LIBRARIES
"${FFMPEG_${_ffmpeg_component}_LIBRARY}") "${FFMPEG_${_ffmpeg_component}_LIBRARY}")
endif()
list(APPEND FFMPEG_INCLUDE_DIRS list(APPEND FFMPEG_INCLUDE_DIRS
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS}") "${FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS}")
list(APPEND FFMPEG_LIBRARIES list(APPEND FFMPEG_LIBRARIES

View file

@ -1,26 +1,6 @@
find_package(SDL2 NO_MODULE QUIET) 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)) if(SDL2_FOUND AND (NOT TARGET SDL2::SDL2))
add_library(SDL2::SDL2 UNKNOWN IMPORTED GLOBAL) add_library(SDL2::SDL2 UNKNOWN IMPORTED GLOBAL)
if(NOT SDL2_LIBDIR) if(NOT SDL2_LIBDIR)

View file

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

View file

@ -1,15 +1,34 @@
# Find DEVKITPRO # Find DEVKITPRO
set(DEVKITPRO "$ENV{DEVKITPRO}" CACHE PATH "Path to DevKitPro") set(DEVKITPRO "$ENV{DEVKITPRO}" CACHE PATH "Path to DevKitPro")
if(NOT DEVKITPRO) set(PORTLIBS_PREFIX "$ENV{PORTLIBS_PREFIX}" CACHE PATH "Path to portlibs inside DevKitPro")
message(FATAL_ERROR "Please set DEVKITPRO env before calling cmake. https://devkitpro.org/wiki/Getting_Started") 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")
endif() endif()
# include devkitpro toolchain # include devkitpro toolchain
include("${DEVKITPRO}/cmake/Switch.cmake") include("${DEVKITPRO}/switch.cmake")
set(NSWITCH TRUE) 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 # troubleshoot
message(STATUS "CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") message(STATUS "CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
message(STATUS "PKG_CONFIG_EXECUTABLE = ${PKG_CONFIG_EXECUTABLE}") message(STATUS "PKG_CONFIG_EXECUTABLE = ${PKG_CONFIG_EXECUTABLE}")
@ -60,3 +79,4 @@ function(add_nro_target output_name target title author version icon romfs)
endfunction() endfunction()
set(CMAKE_USE_SYSTEM_ENVIRONMENT_PATH OFF) set(CMAKE_USE_SYSTEM_ENVIRONMENT_PATH OFF)
set(CMAKE_PREFIX_PATH "/")

View file

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

Binary file not shown.

View file

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

View file

@ -12,12 +12,8 @@
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER #ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
#include <SDL.h> #include <SDL.h>
#include <chiaki/orientation.h>
#endif #endif
#define PS_TOUCHPAD_MAX_X 1920
#define PS_TOUCHPAD_MAX_Y 1079
class Controller; class Controller;
class ControllerManager : public QObject class ControllerManager : public QObject
@ -37,9 +33,7 @@ class ControllerManager : public QObject
private slots: private slots:
void UpdateAvailableControllers(); void UpdateAvailableControllers();
void HandleEvents(); void HandleEvents();
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER void ControllerEvent(int device_id);
void ControllerEvent(SDL_Event evt);
#endif
public: public:
static ControllerManager *GetInstance(); static ControllerManager *GetInstance();
@ -63,24 +57,12 @@ class Controller : public QObject
private: private:
Controller(int device_id, ControllerManager *manager); Controller(int device_id, ControllerManager *manager);
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER void UpdateState();
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; ControllerManager *manager;
int id; int id;
ChiakiOrientationTracker orientation_tracker;
ChiakiControllerState state;
bool is_dualsense;
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER #ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
QMap<QPair<Sint64, Sint64>, uint8_t> touch_ids;
SDL_GameController *controller; SDL_GameController *controller;
#endif #endif
@ -91,44 +73,9 @@ class Controller : public QObject
int GetDeviceID(); int GetDeviceID();
QString GetName(); QString GetName();
ChiakiControllerState GetState(); 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: signals:
void StateChanged(); 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 #endif // CHIAKI_CONTROLLERMANAGER_H

View file

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

View file

@ -63,9 +63,6 @@ class Settings : public QObject
void SetLogVerbose(bool enabled) { settings.setValue("settings/log_verbose", enabled); } void SetLogVerbose(bool enabled) { settings.setValue("settings/log_verbose", enabled); }
uint32_t GetLogLevelMask(); 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; ChiakiVideoResolutionPreset GetResolution() const;
void SetResolution(ChiakiVideoResolutionPreset resolution); void SetResolution(ChiakiVideoResolutionPreset resolution);

View file

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

View file

@ -13,14 +13,12 @@
#if CHIAKI_GUI_ENABLE_SETSU #if CHIAKI_GUI_ENABLE_SETSU
#include <setsu.h> #include <setsu.h>
#include <chiaki/orientation.h>
#endif #endif
#include "exception.h" #include "exception.h"
#include "sessionlog.h" #include "sessionlog.h"
#include "controllermanager.h" #include "controllermanager.h"
#include "settings.h" #include "settings.h"
#include "transformmode.h"
#include <QObject> #include <QObject>
#include <QImage> #include <QImage>
@ -54,18 +52,9 @@ struct StreamSessionConnectInfo
ChiakiConnectVideoProfile video_profile; ChiakiConnectVideoProfile video_profile;
unsigned int audio_buffer_size; unsigned int audio_buffer_size;
bool fullscreen; bool fullscreen;
TransformMode transform_mode;
bool enable_keyboard; bool enable_keyboard;
bool enable_dualsense;
StreamSessionConnectInfo( StreamSessionConnectInfo(Settings *settings, ChiakiTarget target, QString host, QByteArray regist_key, QByteArray morning, bool fullscreen);
Settings *settings,
ChiakiTarget target,
QString host,
QByteArray regist_key,
QByteArray morning,
bool fullscreen,
TransformMode transform_mode);
}; };
class StreamSession : public QObject class StreamSession : public QObject
@ -85,9 +74,6 @@ class StreamSession : public QObject
Setsu *setsu; Setsu *setsu;
QMap<QPair<QString, SetsuTrackingId>, uint8_t> setsu_ids; QMap<QPair<QString, SetsuTrackingId>, uint8_t> setsu_ids;
ChiakiControllerState setsu_state; ChiakiControllerState setsu_state;
SetsuDevice *setsu_motion_device;
ChiakiOrientationTracker orient_tracker;
bool orient_dirty;
#endif #endif
ChiakiControllerState keyboard_state; ChiakiControllerState keyboard_state;
@ -102,23 +88,17 @@ class StreamSession : public QObject
unsigned int audio_buffer_size; unsigned int audio_buffer_size;
QAudioOutput *audio_output; QAudioOutput *audio_output;
QIODevice *audio_io; QIODevice *audio_io;
SDL_AudioDeviceID haptics_output;
uint8_t *haptics_resampler_buf;
QMap<Qt::Key, int> key_map; QMap<Qt::Key, int> key_map;
void PushAudioFrame(int16_t *buf, size_t samples_count); void PushAudioFrame(int16_t *buf, size_t samples_count);
void PushHapticsFrame(uint8_t *buf, size_t buf_size); void Event(ChiakiEvent *event);
#if CHIAKI_GUI_ENABLE_SETSU #if CHIAKI_GUI_ENABLE_SETSU
void HandleSetsuEvent(SetsuEvent *event); void HandleSetsuEvent(SetsuEvent *event);
#endif #endif
private slots: private slots:
void InitAudio(unsigned int channels, unsigned int rate); void InitAudio(unsigned int channels, unsigned int rate);
void InitHaptics();
void Event(ChiakiEvent *event);
void DisconnectHaptics();
void ConnectHaptics();
public: public:
explicit StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent = nullptr); explicit StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent = nullptr);
@ -140,7 +120,7 @@ class StreamSession : public QObject
#endif #endif
void HandleKeyboardEvent(QKeyEvent *event); void HandleKeyboardEvent(QKeyEvent *event);
bool HandleMouseEvent(QMouseEvent *event); void HandleMouseEvent(QMouseEvent *event);
signals: signals:
void FfmpegFrameAvailable(); void FfmpegFrameAvailable();

View file

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

Some files were not shown because too many files have changed in this diff Show more