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:
only:
- master
- develop
- /^v\d.*$/
- /^deploy-test(-.*)?$/
@ -37,14 +36,14 @@ for:
install:
- git submodule update --init --recursive
- 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
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
- 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:
- path: Chiaki.dmg

View file

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

View file

@ -9,47 +9,38 @@ packages:
- ninja
- protoc
- py3-protobuf
- py3-setuptools
- opus-dev
- qt5-qtbase-dev
- qt5-qtsvg-dev
- qt5-qtmultimedia-dev
- ffmpeg-dev
- sdl2-dev
- podman
- sdl2-static # this is gone on alpine edge so might be necessary to remove later
- docker
- fuse
- udev
- argp-standalone
artifacts:
- chiaki.nro
- Chiaki.AppImage
tasks:
- setup_podman: |
sudo rc-service udev start
sudo rc-service cgroups start
sudo rc-service fuse start # Fuse for AppImages
echo build:100000:65536 | sudo tee /etc/subuid
echo build:100000:65536 | sudo tee /etc/subgid
# https://www.kernel.org/doc/Documentation/networking/tuntap.txt
# for slirp4netns
sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 0666 /dev/net/tun
- start_docker: |
sudo service docker start
sudo chmod +s /usr/bin/docker # Yes, I know what I am doing
sudo service fuse start # Fuse for AppImages
- local_build_and_test: |
cd chiaki
cmake -Bbuild -GNinja -DCHIAKI_ENABLE_CLI=ON -DCHIAKI_ENABLE_GUI=ON -DCHIAKI_CLI_ARGP_STANDALONE=ON
cmake -Bbuild -GNinja
ninja -C build
build/test/chiaki-unit
- appimage: |
cd chiaki
scripts/run-podman-build-appimage.sh
scripts/run-docker-build-appimage.sh
cp appimage/Chiaki.AppImage ../Chiaki.AppImage
- switch: |
cd chiaki
scripts/switch/run-podman-build-chiaki.sh
scripts/switch/run-docker-build-chiaki.sh
cp build_switch/switch/chiaki.nro ../chiaki.nro
- bullseye: |
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:
- https://git.sr.ht/~thestr4ng3r/chiaki
@ -7,8 +7,7 @@ sources:
packages:
- cmake
- protobuf
- py311-setuptools # should not be needed with nanopb >= 0.4.9
- py311-protobuf
- py37-protobuf
- opus
- qt5-core
- qt5-qmake

View file

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

2
.gitignore vendored
View file

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

2
.gitmodules vendored
View file

@ -15,4 +15,4 @@
url = https://github.com/google/oboe
[submodule "switch/borealis"]
path = switch/borealis
url = https://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_PI_DECODER "Enable Raspberry Pi-specific video decoder (requires libraspberrypi0 and libraspberrypi-doc)" AUTO)
option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
option(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT "Fetch Mbed TLS instead of using system-provided libs" OFF)
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON)
option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
@ -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)
set(CHIAKI_VERSION_MAJOR 2)
set(CHIAKI_VERSION_MINOR 2)
set(CHIAKI_VERSION_MINOR 0)
set(CHIAKI_VERSION_PATCH 0)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
@ -90,20 +89,6 @@ endif()
if(CHIAKI_LIB_ENABLE_MBEDTLS)
add_definitions(-DCHIAKI_LIB_ENABLE_MBEDTLS)
if(CHIAKI_LIB_MBEDTLS_EXTERNAL_PROJECT)
set(FETCHCONTENT_QUIET CACHE BOOL FALSE)
include(FetchContent)
set(ENABLE_TESTING CACHE INTERNAL OFF)
set(ENABLE_PROGRAMS CACHE INTERNAL OFF)
set(USE_SHARED_MBEDTLS_LIBRARY CACHE INTERNAL OFF)
FetchContent_Declare(
mbedtls
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
GIT_TAG 8b3f26a5ac38d4fdccbc5c5366229f3e01dafcc0 # v2.28.0
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(mbedtls)
endif()
endif()
if(CHIAKI_ENABLE_FFMPEG_DECODER)
@ -150,15 +135,7 @@ if(CHIAKI_ENABLE_CLI)
add_subdirectory(cli)
endif()
if(CHIAKI_ENABLE_GUI AND CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
find_package(SDL2 MODULE REQUIRED)
endif()
if(CHIAKI_ENABLE_SETSU)
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(Evdev QUIET)
if(Udev_FOUND AND Evdev_FOUND)
@ -175,7 +152,6 @@ if(CHIAKI_ENABLE_SETSU)
add_subdirectory(setsu)
endif()
endif()
endif()
if(CHIAKI_ENABLE_SETSU)
message(STATUS "Setsu enabled")
@ -184,6 +160,7 @@ else()
endif()
if(CHIAKI_ENABLE_GUI)
#add_subdirectory(setsu)
add_subdirectory(gui)
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?)
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.
## 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.**
for Linux, FreeBSD, OpenBSD, Android, macOS, Windows, Nintendo Switch and potentially even more platforms.
![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
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
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).
* **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.
* **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
@ -49,8 +47,8 @@ cmake ..
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
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.
## 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
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: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
def rootCMakeLists = "../../CMakeLists.txt"
@ -18,12 +18,13 @@ def chiakiVersion = "$chiakiVersionMajor.$chiakiVersionMinor.$chiakiVersionPatch
println("Determined Chiaki Version: $chiakiVersion")
android {
compileSdkVersion 33
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.metallic.chiaki"
minSdkVersion 21
targetSdkVersion 33
versionCode 12
targetSdkVersion 30
versionCode 8
versionName chiakiVersion
externalNativeBuild {
cmake {
@ -32,16 +33,11 @@ android {
"-DCHIAKI_ENABLE_GUI=OFF",
"-DCHIAKI_ENABLE_SETSU=OFF",
"-DCHIAKI_ENABLE_ANDROID=ON",
"-DCHIAKI_ENABLE_FFMPEG_DECODER=OFF",
"-DCHIAKI_ENABLE_PI_DECODER=OFF",
"-DCHIAKI_LIB_ENABLE_OPUS=OFF",
"-DCHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT=ON"
}
}
}
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
@ -51,7 +47,7 @@ android {
}
externalNativeBuild {
cmake {
version "3.22.1"
version "3.10.2+"
path rootCMakeLists
}
}
@ -65,7 +61,6 @@ android {
}
}
Properties properties = new Properties()
def propertiesFile = file("../local.properties")
if (propertiesFile.exists()) {
@ -91,26 +86,31 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
}
}
androidExtensions {
// for @Parcelize
experimental = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.preference:preference:1.2.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
implementation 'com.google.android.material:material:1.1.0-beta02'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.5.1'
implementation "io.reactivex.rxjava2:rxjava:2.2.20"
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.2.0'
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
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"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-rxjava2:$room_version"
implementation "com.squareup.moshi:moshi:1.14.0"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.14.0"
implementation "com.squareup.moshi:moshi:1.9.2"
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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
<application
android:allowBackup="true"
@ -29,8 +27,7 @@
</provider>
<activity android:name=".main.MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:exported="true">
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View file

@ -110,9 +110,9 @@ JNIEXPORT jstring JNICALL JNI_FCN(quitReasonToString)(JNIEnv *env, jobject obj,
return E->NewStringUTF(env, chiaki_quit_reason_string((ChiakiQuitReason)value));
}
JNIEXPORT jboolean JNICALL JNI_FCN(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)
@ -133,7 +133,6 @@ typedef struct android_chiaki_session_t
jmethodID java_session_event_connected_meth;
jmethodID java_session_event_login_pin_request_meth;
jmethodID java_session_event_quit_meth;
jmethodID java_session_event_rumble_meth;
jfieldID java_controller_state_buttons;
jfieldID java_controller_state_l2_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_right_x;
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;
AndroidChiakiAudioDecoder audio_decoder;
@ -193,14 +178,6 @@ static void android_chiaki_event_cb(ChiakiEvent *event, void *user)
free(reason_str);
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);
@ -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_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_rumble_meth = E->GetMethodID(env, session->java_session_class, "eventRumble", "(II)V");
jclass controller_state_class = E->FindClass(env, BASE_PACKAGE"/ControllerState");
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_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_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_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)
{
AndroidChiakiSession *session = (AndroidChiakiSession *)ptr;
ChiakiControllerState controller_state;
chiaki_controller_state_set_idle(&controller_state);
ChiakiControllerState controller_state = { 0 };
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.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.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);
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);
}

@ -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);
}
static void kill_decoder(AndroidChiakiVideoDecoder *decoder)
void android_chiaki_video_decoder_fini(AndroidChiakiVideoDecoder *decoder)
{
if(decoder->codec)
{
chiaki_mutex_lock(&decoder->codec_mutex);
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)
{
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);
}
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);
}
@ -61,16 +56,6 @@ void android_chiaki_video_decoder_set_surface(AndroidChiakiVideoDecoder *decoder
{
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 __ANDROID_API__ >= 23

View file

@ -23,11 +23,9 @@ val MIGRATION_1_2 = object : Migration(1, 2)
{
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("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
import androidx.room.*
import androidx.room.ForeignKey.Companion.SET_NULL
import androidx.room.ForeignKey.SET_NULL
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Single

View file

@ -68,26 +68,11 @@ class Preferences(context: Context)
get() = sharedPreferences.getBoolean(onScreenControlsEnabledKey, true)
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
get() = sharedPreferences.getBoolean(touchpadOnlyEnabledKey, false)
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)
var logVerbose
get() = sharedPreferences.getBoolean(logVerboseKey, false)

View file

@ -3,7 +3,7 @@
package com.metallic.chiaki.common
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.Target
import io.reactivex.Completable

View file

@ -25,8 +25,6 @@ import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
import okio.Buffer
import okio.Okio
import okio.buffer
import okio.source
import java.io.File
import java.io.IOException
@ -166,7 +164,7 @@ fun importSettingsFromUri(activity: Activity, uri: Uri, disposable: CompositeDis
try
{
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 adapter = moshi().serializedSettingsAdapter()

View file

@ -3,7 +3,8 @@ package com.metallic.chiaki.lib
import android.os.Parcelable
import android.util.Log
import android.view.Surface
import kotlinx.parcelize.Parcelize
import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
import java.lang.Exception
import java.net.InetSocketAddress
import kotlin.math.abs
@ -83,14 +84,14 @@ private class ChiakiNative
}
@JvmStatic external fun errorCodeToString(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 sessionCreate(result: CreateResult, connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean, javaSession: Session)
@JvmStatic external fun sessionFree(ptr: Long)
@JvmStatic external fun sessionStart(ptr: Long): Int
@JvmStatic external fun sessionStop(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 sessionSetLoginPin(ptr: Long, pin: String)
@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 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(
var buttons: UInt = 0U,
var l2State: UByte = 0U,
@ -164,19 +157,7 @@ data class ControllerState constructor(
var leftX: Short = 0,
var leftY: Short = 0,
var rightX: 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
var rightY: Short = 0
){
companion object
{
@ -196,8 +177,6 @@ data class ControllerState constructor(
val BUTTON_SHARE = (1 shl 13).toUInt()
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
val BUTTON_PS = (1 shl 15).toUInt()
val TOUCHPAD_WIDTH: UShort = 1920U
val TOUCHPAD_HEIGHT: UShort = 942U
}
infix fun or(o: ControllerState) = ControllerState(
@ -207,116 +186,24 @@ data class ControllerState constructor(
leftX = maxAbs(leftX, o.leftX),
leftY = maxAbs(leftY, o.leftY),
rightX = maxAbs(rightX, o.rightX),
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
rightY = maxAbs(rightY, o.rightY)
)
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)
{
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
object ConnectedEvent: Event()
data class LoginPinRequestEvent(val pinIncorrect: Boolean): 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")
@ -372,12 +259,7 @@ class Session(connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean)
event(QuitEvent(QuitReason(reasonValue), reasonString))
}
private fun eventRumble(left: Int, right: Int)
{
event(RumbleEvent(left.toUByte(), right.toUByte()))
}
fun setSurface(surface: Surface?)
fun setSurface(surface: Surface)
{
ChiakiNative.sessionSetSurface(nativePtr, surface)
}

View file

@ -3,7 +3,6 @@
package com.metallic.chiaki.main
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
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.ManualDisplayHost
import com.metallic.chiaki.common.ext.inflate
import com.metallic.chiaki.databinding.ItemDisplayHostBinding
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()
{
@ -43,10 +42,10 @@ class DisplayHostRecyclerViewAdapter(
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)
= ViewHolder(ItemDisplayHostBinding.inflate(LayoutInflater.from(parent.context), parent, false))
= ViewHolder(parent.inflate(R.layout.item_display_host))
override fun getItemCount() = hosts.count()
@ -54,7 +53,7 @@ class DisplayHostRecyclerViewAdapter(
{
val context = holder.itemView.context
val host = hosts[position]
holder.binding.also {
holder.itemView.also {
it.nameTextView.text = host.name
it.hostTextView.text = context.getString(R.string.display_host_host, host.host)
val id = host.id
@ -88,7 +87,7 @@ class DisplayHostRecyclerViewAdapter(
else -> R.drawable.ic_console
}
)
it.root.setOnClickListener { clickCallback(host) }
it.setOnClickListener { clickCallback(host) }
val canWakeup = host.registeredHost != null
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.ext.putRevealExtra
import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.databinding.ActivityMainBinding
import com.metallic.chiaki.lib.ConnectInfo
import com.metallic.chiaki.lib.DiscoveryHost
import com.metallic.chiaki.manualconsole.EditManualConsoleActivity
import com.metallic.chiaki.regist.RegistActivity
import com.metallic.chiaki.settings.SettingsActivity
import com.metallic.chiaki.stream.StreamActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity()
{
private lateinit var viewModel: MainViewModel
private lateinit var binding: ActivityMainBinding
private var discoveryMenuItem: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_main)
title = ""
setSupportActionBar(binding.toolbar)
setSupportActionBar(toolbar)
binding.floatingActionButton.setOnClickListener {
expandFloatingActionButton(!binding.floatingActionButton.isExpanded)
floatingActionButton.setOnClickListener {
expandFloatingActionButton(!floatingActionButton.isExpanded)
}
binding.floatingActionButtonDialBackground.setOnClickListener {
floatingActionButtonDialBackground.setOnClickListener {
expandFloatingActionButton(false)
}
binding.addManualButton.setOnClickListener { addManualConsole() }
binding.addManualLabelButton.setOnClickListener { addManualConsole() }
addManualButton.setOnClickListener { addManualConsole() }
addManualLabelButton.setOnClickListener { addManualConsole() }
binding.registerButton.setOnClickListener { showRegistration() }
binding.registerLabelButton.setOnClickListener { showRegistration() }
registerButton.setOnClickListener { showRegistration() }
registerLabelButton.setOnClickListener { showRegistration() }
viewModel = ViewModelProvider(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) })
.get(MainViewModel::class.java)
val recyclerViewAdapter = DisplayHostRecyclerViewAdapter(this::hostTriggered, this::wakeupHost, this::editHost, this::deleteHost)
binding.hostsRecyclerView.adapter = recyclerViewAdapter
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(this)
hostsRecyclerView.adapter = recyclerViewAdapter
hostsRecyclerView.layoutManager = LinearLayoutManager(this)
viewModel.displayHosts.observe(this, Observer {
val top = binding.hostsRecyclerView.computeVerticalScrollOffset() == 0
val top = hostsRecyclerView.computeVerticalScrollOffset() == 0
recyclerViewAdapter.hosts = it
if(top)
binding.hostsRecyclerView.scrollToPosition(0)
hostsRecyclerView.scrollToPosition(0)
updateEmptyInfo()
})
@ -78,19 +76,19 @@ class MainActivity : AppCompatActivity()
{
if(viewModel.displayHosts.value?.isEmpty() ?: true)
{
binding.emptyInfoLayout.visibility = View.VISIBLE
emptyInfoLayout.visibility = View.VISIBLE
val discoveryActive = viewModel.discoveryActive.value ?: false
binding.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)
emptyInfoImageView.setImageResource(if(discoveryActive) R.drawable.ic_discover_on else R.drawable.ic_discover_off)
emptyInfoTextView.setText(if(discoveryActive) R.string.display_hosts_empty_discovery_on_info else R.string.display_hosts_empty_discovery_off_info)
}
else
binding.emptyInfoLayout.visibility = View.GONE
emptyInfoLayout.visibility = View.GONE
}
private fun expandFloatingActionButton(expand: Boolean)
{
binding.floatingActionButton.isExpanded = expand
binding.floatingActionButton.isActivated = binding.floatingActionButton.isExpanded
floatingActionButton.isExpanded = expand
floatingActionButton.isActivated = floatingActionButton.isExpanded
}
override fun onStart()
@ -107,7 +105,7 @@ class MainActivity : AppCompatActivity()
override fun onBackPressed()
{
if(binding.floatingActionButton.isExpanded)
if(floatingActionButton.isExpanded)
{
expandFloatingActionButton(false)
return
@ -153,7 +151,7 @@ class MainActivity : AppCompatActivity()
private fun addManualConsole()
{
Intent(this, EditManualConsoleActivity::class.java).also {
it.putRevealExtra(binding.addManualButton, binding.rootLayout)
it.putRevealExtra(addManualButton, rootLayout)
startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
}
}
@ -161,7 +159,7 @@ class MainActivity : AppCompatActivity()
private fun showRegistration()
{
Intent(this, RegistActivity::class.java).also {
it.putRevealExtra(binding.registerButton, binding.rootLayout)
it.putRevealExtra(registerButton, rootLayout)
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.viewModelFactory
import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.databinding.ActivityEditManualBinding
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import kotlinx.android.synthetic.main.activity_edit_manual.*
class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
{
@ -28,20 +28,18 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
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 revealRootLayout: View get() = binding.rootLayout
override val revealRootLayout: View get() = rootLayout
override val revealWindow: Window get() = window
private lateinit var viewModel: EditManualConsoleViewModel
private val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
binding = ActivityEditManualBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_edit_manual)
handleReveal()
viewModel = ViewModelProvider(this, viewModelFactory {
@ -54,17 +52,17 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
.get(EditManualConsoleViewModel::class.java)
viewModel.existingHost?.observe(this, Observer {
binding.hostEditText.setText(it.host)
hostEditText.setText(it.host)
})
viewModel.selectedRegisteredHost.observe(this, Observer {
binding.registeredHostTextView.setText(titleForRegisteredHost(it))
registeredHostTextView.setText(titleForRegisteredHost(it))
})
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) }))
binding.registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener {
registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener {
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
{
if(position >= hosts.size)
@ -75,7 +73,8 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
}
})
binding.saveButton.setOnClickListener { saveHost() }
saveButton.setOnClickListener { saveHost() }
}
private fun titleForRegisteredHost(registeredHost: RegisteredHost?) =
@ -86,14 +85,14 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
private fun saveHost()
{
val host = binding.hostEditText.text.toString().trim()
val host = hostEditText.text.toString().trim()
if(host.isEmpty())
{
binding.hostEditText.error = getString(R.string.entered_host_invalid)
hostEditText.error = getString(R.string.entered_host_invalid)
return
}
binding.saveButton.isEnabled = false
saveButton.isEnabled = false
viewModel.saveHost(host)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {

View file

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

View file

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

View file

@ -1,37 +1,19 @@
package com.metallic.chiaki.session
import android.content.Context
import android.hardware.*
import android.view.*
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import android.util.Log
import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.lib.ControllerState
class StreamInput(val context: Context, val preferences: Preferences)
class StreamInput(val preferences: Preferences)
{
var controllerStateChangedCallback: ((ControllerState) -> Unit)? = null
val controllerState: ControllerState get()
{
val controllerState = sensorControllerState or 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 -> {}
}
val controllerState = keyControllerState or motionControllerState
// prioritize motion controller's l2 and r2 over key
// (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
}
private val sensorControllerState = ControllerState() // from Motion Sensors
private val keyControllerState = ControllerState() // from KeyEvents
private val motionControllerState = ControllerState() // from MotionEvents
var touchControllerState = ControllerState()
@ -55,66 +36,6 @@ class StreamInput(val context: Context, val preferences: Preferences)
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()
{
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)
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()
motionControllerState.leftX = event.getAxisValue(MotionEvent.AXIS_X).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)
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
private var surface: Surface? = null
var surfaceTexture: SurfaceTexture? = null
init
{
@ -62,9 +59,9 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
_state.value = StreamStateConnecting
session.eventCallback = this::eventCallback
session.start()
val surface = surface
if(surface != null)
session.setSurface(surface)
val surfaceTexture = surfaceTexture
if(surfaceTexture != null)
session.setSurface(Surface(surfaceTexture))
this.session = session
}
catch(e: CreateError)
@ -89,30 +86,9 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
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)
{
textureView.surfaceTextureListener = object: TextureView.SurfaceTextureListener {
@ -121,7 +97,6 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
if(surfaceTexture != null)
return
surfaceTexture = surface
this@StreamSession.surface = Surface(surfaceTexture)
session?.setSurface(Surface(surface))
}

View file

@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.metallic.chiaki.R
import com.metallic.chiaki.databinding.ActivitySettingsBinding
import kotlinx.android.synthetic.main.activity_settings.*
interface TitleFragment
{
@ -18,23 +18,20 @@ interface TitleFragment
class SettingsActivity: AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
{
private lateinit var binding: ActivitySettingsBinding
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_settings)
title = ""
setSupportActionBar(binding.toolbar)
setSupportActionBar(toolbar)
val rootFragment = SettingsFragment()
replaceFragment(rootFragment, false)
supportFragmentManager.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)

View file

@ -16,6 +16,7 @@ import com.metallic.chiaki.common.exportAndShareAllSettings
import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.common.importSettingsFromUri
import com.metallic.chiaki.lib.Codec
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
@ -25,9 +26,6 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
{
preferences.logVerboseKey -> preferences.logVerbose
preferences.swapCrossMoonKey -> preferences.swapCrossMoon
preferences.rumbleEnabledKey -> preferences.rumbleEnabled
preferences.motionEnabledKey -> preferences.motionEnabled
preferences.buttonHapticEnabledKey -> preferences.buttonHapticEnabled
else -> defValue
}
@ -37,9 +35,6 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
{
preferences.logVerboseKey -> preferences.logVerbose = 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
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.metallic.chiaki.R
import com.metallic.chiaki.common.LogFile
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.SimpleDateFormat
import java.util.*
@ -20,7 +20,7 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
private val dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT)
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()
set(value)
@ -29,16 +29,16 @@ class SettingsLogsAdapter: RecyclerView.Adapter<SettingsLogsAdapter.ViewHolder>(
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
ViewHolder(ItemLogFileBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_log_file))
override fun getItemCount() = logFiles.size
override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
val view = holder.itemView
val logFile = logFiles[position]
holder.binding.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}"
holder.binding.summaryTextView.text = logFile.filename
holder.binding.shareButton.setOnClickListener { shareCallback?.let { it(logFile) } }
view.nameTextView.text = "${dateFormat.format(logFile.date)} ${timeFormat.format(logFile.date)}"
view.summaryTextView.text = logFile.filename
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.ext.viewModelFactory
import com.metallic.chiaki.common.fileProviderAuthority
import com.metallic.chiaki.databinding.FragmentSettingsLogsBinding
import kotlinx.android.synthetic.main.fragment_settings_logs.*
class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
{
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 =
FragmentSettingsLogsBinding.inflate(inflater, container, false).let {
_binding = it
it.root
}
inflater.inflate(R.layout.fragment_settings_logs, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
val context = requireContext()
val context = context!!
viewModel = ViewModelProvider(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) })
.get(SettingsLogsViewModel::class.java)
val adapter = SettingsLogsAdapter()
binding.logsRecyclerView.layoutManager = LinearLayoutManager(context)
binding.logsRecyclerView.adapter = adapter
logsRecyclerView.layoutManager = LinearLayoutManager(context)
logsRecyclerView.adapter = adapter
adapter.shareCallback = this::shareLogFile
viewModel.sessionLogs.observe(viewLifecycleOwner, Observer {
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)
@ -61,7 +55,7 @@ class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
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)

View file

@ -2,15 +2,17 @@
package com.metallic.chiaki.settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.metallic.chiaki.R
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 ViewHolder(val binding: ItemRegisteredHostBinding): RecyclerView.ViewHolder(binding.root)
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
var hosts: List<RegisteredHost> = listOf()
set(value)
@ -19,15 +21,15 @@ class SettingsRegisteredHostsAdapter: RecyclerView.Adapter<SettingsRegisteredHos
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
= ViewHolder(ItemRegisteredHostBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_registered_host))
override fun getItemCount() = hosts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
val view = holder.itemView
val host = hosts[position]
holder.binding.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})"
holder.binding.summaryTextView.text = host.serverMac.toString()
view.nameTextView.text = "${host.serverNickname} (${if(host.target.isPS5) "PS5" else "PS4"})"
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.viewModelFactory
import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.databinding.FragmentSettingsRegisteredHostsBinding
import com.metallic.chiaki.regist.RegistActivity
import kotlinx.android.synthetic.main.fragment_settings_registered_hosts.*
class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
{
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 =
FragmentSettingsRegisteredHostsBinding.inflate(inflater, container, false).let {
_binding = it
it.root
}
inflater.inflate(R.layout.fragment_settings_registered_hosts, container, false)
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)
val adapter = SettingsRegisteredHostsAdapter()
binding.hostsRecyclerView.layoutManager = LinearLayoutManager(context)
binding.hostsRecyclerView.adapter = adapter
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context)
hostsRecyclerView.layoutManager = LinearLayoutManager(context)
hostsRecyclerView.adapter = adapter
val itemTouchSwipeCallback = object : ItemTouchSwipeCallback(context!!)
{
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
{
@ -63,15 +56,15 @@ class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
.show()
}
}
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(binding.hostsRecyclerView)
ItemTouchHelper(itemTouchSwipeCallback).attachToRecyclerView(hostsRecyclerView)
viewModel.registeredHosts.observe(this, Observer {
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 {
it.putRevealExtra(binding.floatingActionButton, binding.rootLayout)
it.putRevealExtra(floatingActionButton, rootLayout)
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.app.AlertDialog
import android.graphics.Matrix
import android.os.*
import android.view.*
import android.os.Bundle
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 androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone
@ -16,18 +20,15 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.metallic.chiaki.R
import com.metallic.chiaki.common.LogManager
import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.databinding.ActivityStreamBinding
import com.metallic.chiaki.lib.ConnectInfo
import com.metallic.chiaki.lib.ConnectVideoProfile
import com.metallic.chiaki.session.*
import com.metallic.chiaki.touchcontrols.DefaultTouchControlsFragment
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import kotlin.math.min
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
import kotlinx.android.synthetic.main.activity_stream.*
private sealed class DialogContents
private object StreamQuitDialog: DialogContents()
@ -43,8 +44,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
}
private lateinit var viewModel: StreamViewModel
private lateinit var binding: ActivityStreamBinding
private val uiVisibilityHandler = Handler()
override fun onCreate(savedInstanceState: Bundle?)
@ -59,75 +58,63 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
}
viewModel = ViewModelProvider(this, viewModelFactory {
StreamViewModel(application, connectInfo)
StreamViewModel(Preferences(this), LogManager(this), connectInfo)
})[StreamViewModel::class.java]
viewModel.input.observe(this)
binding = ActivityStreamBinding.inflate(layoutInflater)
setContentView(binding.root)
setContentView(R.layout.activity_stream)
window.decorView.setOnSystemUiVisibilityChangeListener(this)
viewModel.onScreenControlsEnabled.observe(this, Observer {
if(binding.onScreenControlsSwitch.isChecked != it)
binding.onScreenControlsSwitch.isChecked = it
if(binding.onScreenControlsSwitch.isChecked)
binding.touchpadOnlySwitch.isChecked = false
if(onScreenControlsSwitch.isChecked != it)
onScreenControlsSwitch.isChecked = it
if(onScreenControlsSwitch.isChecked)
touchpadOnlySwitch.isChecked = false
})
binding.onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked ->
onScreenControlsSwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.setOnScreenControlsEnabled(isChecked)
showOverlay()
}
viewModel.touchpadOnlyEnabled.observe(this, Observer {
if(binding.touchpadOnlySwitch.isChecked != it)
binding.touchpadOnlySwitch.isChecked = it
if(binding.touchpadOnlySwitch.isChecked)
binding.onScreenControlsSwitch.isChecked = false
if(touchpadOnlySwitch.isChecked != it)
touchpadOnlySwitch.isChecked = it
if(touchpadOnlySwitch.isChecked)
onScreenControlsSwitch.isChecked = false
})
binding.touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked ->
touchpadOnlySwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.setTouchpadOnlyEnabled(isChecked)
showOverlay()
}
binding.displayModeToggle.addOnButtonCheckedListener { _, _, _ ->
adjustStreamViewAspect()
displayModeToggle.addOnButtonCheckedListener { _, checkedId, _ ->
// 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()
}
//viewModel.session.attachToTextureView(textureView)
viewModel.session.attachToSurfaceView(binding.surfaceView)
viewModel.session.attachToTextureView(textureView)
viewModel.session.state.observe(this, Observer { this.stateChanged(it) })
adjustStreamViewAspect()
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)
})
textureView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
adjustTextureViewAspect()
}
}
private val controlsDisposable = CompositeDisposable()
override fun onAttachFragment(fragment: Fragment)
{
super.onAttachFragment(fragment)
if(fragment is TouchControlsFragment)
{
fragment.controllerState
.subscribe { viewModel.input.touchControllerState = it }
.addTo(controlsDisposable)
fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
fragment.onScreenControlsEnabled = viewModel.onScreenControlsEnabled
}
if(fragment is TouchpadOnlyFragment)
{
fragment.controllerStateCallback = { viewModel.input.touchControllerState = it }
fragment.touchpadOnlyEnabled = viewModel.touchpadOnlyEnabled
}
}
@ -145,12 +132,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
viewModel.session.pause()
}
override fun onDestroy()
{
super.onDestroy()
controlsDisposable.dispose()
}
private fun reconnect()
{
viewModel.session.shutdown()
@ -169,14 +150,14 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
private fun showOverlay()
{
binding.overlay.isVisible = true
binding.overlay.animate()
overlay.isVisible = true
overlay.animate()
.alpha(1.0f)
.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)
@ -185,13 +166,13 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
private fun hideOverlay()
{
binding.overlay.animate()
overlay.animate()
.alpha(0.0f)
.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)
{
binding.progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE
progressBar.visibility = if(state == StreamStateConnecting) View.VISIBLE else View.GONE
when(state)
{
is StreamStateQuit ->
{
if(dialogContents != StreamQuitDialog)
{
if(state.reason.isError)
if(!state.reason.isStopped && dialogContents != StreamQuitDialog)
{
dialog?.dismiss()
val reasonStr = state.reasonString
@ -255,9 +234,6 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
dialogContents = StreamQuitDialog
dialog.show()
}
else
finish()
}
}
is StreamStateCreateError ->
@ -311,89 +287,77 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
dialog.show()
}
}
else -> {}
}
}
private fun adjustTextureViewAspect(textureView: TextureView)
private fun adjustTextureViewAspect()
{
val trans = TextureViewTransform(viewModel.session.connectInfo.videoProfile, textureView)
val resolution = trans.resolutionFor(TransformMode.fromButton(binding.displayModeToggle.checkedButtonId))
val displayInfo = DisplayInfo(viewModel.session.connectInfo.videoProfile, textureView)
val resolution = displayInfo.computeResolutionFor(displayModeToggle.checkedButtonId)
Matrix().also {
textureView.getTransform(it)
it.setScale(resolution.width / trans.viewWidth, resolution.height / trans.viewHeight)
it.postTranslate((trans.viewWidth - resolution.width) * 0.5f, (trans.viewHeight - resolution.height) * 0.5f)
it.setScale(resolution.width / displayInfo.viewWidth, resolution.height / displayInfo.viewHeight)
it.postTranslate((displayInfo.viewWidth - resolution.width) * 0.5f, (displayInfo.viewHeight - resolution.height) * 0.5f)
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 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)
= when (displayModeButtonId)
{
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 contentWidth : Float get() = videoProfile.width.toFloat()
val contentHeight : Float get() = videoProfile.height.toFloat()
val viewWidth : Float get() = textureView.width.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
= when(mode)
fun computeResolutionFor(displayModeButtonId: Int) : Resolution
{
TransformMode.STRETCH -> strechedResolution
TransformMode.ZOOM -> zoomedResolution
TransformMode.FIT -> normalResolution
when (displayModeButtonId)
{
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)
{
val zoomFactor = viewHeight / contentHeight
Resolution(contentWidth * zoomFactor, viewHeight)
return Resolution(contentWidth * zoomFactor, viewHeight)
}
else
{
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)
Resolution(viewWidth, viewWidth * contentAspect)
{
return Resolution(viewWidth, viewWidth * contentAspect)
}
else
Resolution(viewHeight / contentAspect, viewHeight)
{
return Resolution(viewHeight / contentAspect, viewHeight)
}
}
}

View file

@ -2,22 +2,19 @@
package com.metallic.chiaki.stream
import android.app.Application
import android.content.Context
import androidx.lifecycle.*
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.metallic.chiaki.common.LogManager
import com.metallic.chiaki.session.StreamSession
import com.metallic.chiaki.common.Preferences
import com.metallic.chiaki.lib.*
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
val input = StreamInput(application, preferences)
val input = StreamInput(preferences)
val session = StreamSession(connectInfo, logManager, preferences.logVerbose, input)
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.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import com.metallic.chiaki.R
class ButtonView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr)
{
private val haptics = ButtonHaptics(context)
var buttonPressed = false
private set(value)
{
@ -26,8 +21,6 @@ class ButtonView @JvmOverloads constructor(
field = value
if(diff)
{
if(value)
haptics.trigger()
invalidate()
buttonPressedCallback?.let { it(field) }
}
@ -53,39 +46,16 @@ class ButtonView @JvmOverloads constructor(
{
super.onDraw(canvas)
val drawable = if(buttonPressed) drawablePressed else drawableIdle
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
drawable?.setBounds(0, 0, width, height)
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
{
when(event.actionMasked)
when(event.action)
{
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
if(bestFittingTouchView(event.getX(event.actionIndex), event.getY(event.actionIndex)) != this)
return false
buttonPressed = true
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
buttonPressed = false
}
MotionEvent.ACTION_DOWN -> buttonPressed = true
MotionEvent.ACTION_UP -> buttonPressed = false
}
return true
}

View file

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

View file

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

View file

@ -26,7 +26,7 @@ class TouchTracker
if(pointerId == null)
{
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.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import com.metallic.chiaki.databinding.FragmentTouchpadOnlyBinding
import io.reactivex.rxkotlin.Observables.combineLatest
import com.metallic.chiaki.R
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
private var _binding: FragmentTouchpadOnlyBinding? = null
private val binding get() = _binding!!
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 onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
= inflater.inflate(R.layout.fragment_touchpad_only, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
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
})
}
private fun buttonStateChanged(buttonMask: UInt) = { pressed: Boolean ->
ownControllerState = ownControllerState.copy().apply {
controllerState = controllerState.copy().apply {
buttons =
if(pressed)
buttons or buttonMask
else
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
import android.view.View
import kotlin.math.sqrt
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 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"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
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_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"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_primary"
android:strokeColor="#00000000"
android:strokeLineCap="round"/>
</vector>

View file

@ -1,12 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:height="128dp"
android:viewportWidth="67.73333"
android:viewportHeight="67.73334">
android:viewportHeight="33.86667">
<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:strokeWidth="5.54109"
android:strokeWidth="23.7399"
android:fillColor="@color/control_pressed"
android:strokeColor="#00000000"
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_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"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
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_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".stream.StreamActivity"
android:keepScreenOn="true">
<com.metallic.chiaki.stream.AspectRatioFrameLayout
android:id="@+id/aspectRatioLayout"
<TextureView
android:id="@+id/textureView"
android:layout_width="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>
android:layout_height="match_parent"/>
<ProgressBar
android:id="@+id/progressBar"
@ -28,7 +20,7 @@
<fragment
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_height="match_parent"/>
@ -42,6 +34,7 @@
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
@ -83,7 +76,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:singleSelection="true"
app:selectionRequired="true"
app:checkedButton="@id/display_mode_normal_button">
<com.google.android.material.button.MaterialButton

View file

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

View file

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

View file

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

View file

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="control_face_button_size_half">88dp</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_face_button_size">48dp</dimen>
<dimen name="control_analog_stick_radius">48dp</dimen>
<dimen name="control_analog_stick_handle_radius">32dp</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_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_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_manual_host">Are you sure you want to delete the console entry for %s?</string>
<string name="action_keep">Keep</string>
@ -107,10 +101,7 @@
<!-- Don't localize these -->
<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_touchpad_only_enabled_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_touchpad_only_key">touchpad_only_enabled</string>
<string name="preferences_log_verbose_key">log_verbose</string>
<string name="preferences_import_settings_key">import_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: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
app:key="@string/preferences_log_verbose_key"
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.
buildscript {
ext.kotlin_version = '1.8.0'
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()
}
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"
// NOTE: Do not place your application dependencies here; they belong
// 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
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
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: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"
sodipodi:docname="l1.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
viewBox="0 0 67.733332 33.866668"
height="128"
width="256">
<defs
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
id="metadata5">
<rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF>
</metadata>
<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
id="path2031"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
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"
transform="scale(0.26458334)" />
inkscape:connector-curvature="0"
transform="scale(0.26458333)"
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"
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>
</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: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"
sodipodi:docname="l2.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
viewBox="0 0 67.733332 33.866668"
height="128"
width="256">
<defs
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
id="metadata5">
<rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF>
</metadata>
<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
id="path2127"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
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"
transform="scale(0.26458334)" />
inkscape:connector-curvature="0"
transform="scale(0.26458333)"
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"
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>
</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: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"
sodipodi:docname="r1.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
viewBox="0 0 67.733332 33.866668"
height="128"
width="256">
<defs
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
id="metadata5">
<rdf:RDF>
@ -25,12 +49,28 @@
</rdf:RDF>
</metadata>
<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
id="path2117"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
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"
transform="scale(0.26458334)" />
inkscape:connector-curvature="0"
transform="scale(0.26458333)"
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"
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>
</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: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"
sodipodi:docname="r2.svg"
inkscape:version="1.0beta1 (5c3063637d, 2019-10-15)"
id="svg8"
version="1.1"
viewBox="0 0 67.733332 67.733336"
height="256"
viewBox="0 0 67.733332 33.866668"
height="128"
width="256">
<defs
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
id="metadata5">
<rdf:RDF>
@ -25,13 +49,28 @@
</rdf:RDF>
</metadata>
<g
id="g2145"
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
id="path2137"
style="fill:#ffffff;stroke-width:5.54109;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
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"
transform="matrix(-0.26458334,0,0,0.26458334,67.733334,0)" />
inkscape:connector-curvature="0"
transform="scale(0.26458333)"
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"
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>
</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)
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;
}
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4); // TODO: IPv6, PS5, should probably use the service
ChiakiDiscoveryPacket packet;
memset(&packet, 0, sizeof(packet));
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS4;
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS4);
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
if(err != CHIAKI_ERR_SUCCESS)
CHIAKI_LOGE(log, "Failed to send discovery packet for PS4: %s", chiaki_error_string(err));
packet.protocol_version = CHIAKI_DISCOVERY_PROTOCOL_VERSION_PS5;
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT_PS5);
err = chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
if(err != CHIAKI_ERR_SUCCESS)
CHIAKI_LOGE(log, "Failed to send discovery packet for PS5: %s", chiaki_error_string(err));
chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
while(1)
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_REGISTKEY 'r'
#define ARG_KEY_PS4 '4'
#define ARG_KEY_PS5 '5'
static struct argp_option options[] = {
{ "host", ARG_KEY_HOST, "Host", 0, "Host to send wakeup packet to", 0 },
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "Remote Play registration key (plaintext)", 0 },
{ "ps4", ARG_KEY_PS4, NULL, 0, "PlayStation 4", 0 },
{ "ps5", ARG_KEY_PS5, NULL, 0, "PlayStation 5 (default)", 0 },
{ "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "PS4 registration key", 0 },
{ 0 }
};
@ -26,7 +22,6 @@ typedef struct arguments
{
const char *host;
const char *registkey;
bool ps5;
} Arguments;
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:
argp_usage(state);
break;
case ARG_KEY_PS4:
arguments->ps5 = false;
break;
case ARG_KEY_PS5:
arguments->ps5 = true;
break;
default:
return ARGP_ERR_UNKNOWN;
}
@ -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[])
{
Arguments arguments = { 0 };
arguments.ps5 = true;
error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
if(argp_r != 0)
return 1;
@ -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);
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
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)
endif()
if(FFMPEG_${component}_FOUND)
if((TARGET PkgConfig::FFMPEG_${component}) AND (NOT CMAKE_VERSION VERSION_LESS "3.11.0"))
if(APPLE)
@ -73,9 +69,6 @@ function (_ffmpeg_find component headername)
add_library(FFMPEG::${component} ALIAS PkgConfig::FFMPEG_${component})
else()
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
INTERFACE_LINK_DIRECTORIES "${FFMPEG_${component}_LIBRARY_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
"FFMPEG_${_ffmpeg_component}_LIBRARIES")
else()
if(NOT FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS)
set(FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIR}")
endif()
if(NOT FFMPEG_${_ffmpeg_component}_LIBRARIES)
set(FFMPEG_${_ffmpeg_component}_LIBRARIES
"${FFMPEG_${_ffmpeg_component}_LIBRARY}")
endif()
list(APPEND FFMPEG_INCLUDE_DIRS
"${FFMPEG_${_ffmpeg_component}_INCLUDE_DIRS}")
list(APPEND FFMPEG_LIBRARIES

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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