From a0aaa1178871b00b60d1e4dd0fa8c3361af7ce27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Tue, 28 Jan 2020 21:42:52 +0100
Subject: [PATCH 001/269] Build SDL2 with udev on Linux (for #32)
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 11f706c..4dbcca6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -56,6 +56,7 @@ matrix:
- qt512svg
- libgl1-mesa-dev
- nasm
+ - libudev-dev
env:
- CMAKE_PREFIX_PATH="$TRAVIS_BUILD_DIR/ffmpeg-prefix;$TRAVIS_BUILD_DIR/sdl2-prefix;/opt/qt512"
- CMAKE_EXTRA_ARGS="-DCMAKE_INSTALL_PREFIX=/usr"
From 5bf530d56df09bdab4c6bb0cf49106baff626c29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Tue, 28 Jan 2020 22:09:33 +0100
Subject: [PATCH 002/269] Add oshi.at upload from Travis (#153)
---
.travis.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 4dbcca6..606f380 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -145,7 +145,9 @@ before_install:
- if [ ! -z "$encrypted_31d5e6477a29_iv" ]; then openssl aes-256-cbc -K $encrypted_31d5e6477a29_key -iv $encrypted_31d5e6477a29_iv -in secret.tar.enc -out secret.tar -d && tar -xf secret.tar; fi
after_success:
- - if [ ! -z "$DEPLOY_FILE" ]; then curl -m 30 --upload-file "$DEPLOY_FILE" "https://transfer.sh/$DEPLOY_FILE"; echo; fi
+ - if [ ! -z "$DEPLOY_FILE" ]; then echo "--- SHA256 for $DEPLOY_FILE"; openssl dgst -sha256 "$DEPLOY_FILE"; echo; fi
+ - if [ ! -z "$DEPLOY_FILE" ]; then echo "--- transfer.sh"; curl -m 30 --upload-file "$DEPLOY_FILE" "https://transfer.sh/$DEPLOY_FILE"; echo; fi
+ - if [ ! -z "$DEPLOY_FILE" ]; then echo "--- oshi.at"; curl -m 30 --upload-file "$DEPLOY_FILE" "https://oshi.at/$DEPLOY_FILE/129600"; echo; fi
deploy:
skip_cleanup: true
From fe1e3835f8f5a46bcc9c9b2f3d5e558f6c15dfb2 Mon Sep 17 00:00:00 2001
From: 3kinox <42655690+3kinox@users.noreply.github.com>
Date: Sun, 16 Feb 2020 17:59:09 +0100
Subject: [PATCH 003/269] Use Mouse Click for Touchpad Button in GUI (#167)
---
gui/include/streamsession.h | 2 ++
gui/include/streamwindow.h | 2 ++
gui/src/streamsession.cpp | 9 +++++++++
gui/src/streamwindow.cpp | 12 ++++++++++++
4 files changed, 25 insertions(+)
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index a6ca741..721270b 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -28,6 +28,7 @@
#include
#include
+#include
#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
class QGamepad;
@@ -105,6 +106,7 @@ class StreamSession : public QObject
VideoDecoder *GetVideoDecoder() { return &video_decoder; }
void HandleKeyboardEvent(QKeyEvent *event);
+ void HandleMouseEvent(QMouseEvent *event);
signals:
void CurrentImageUpdated();
diff --git a/gui/include/streamwindow.h b/gui/include/streamwindow.h
index 5e67e6e..3e664bc 100644
--- a/gui/include/streamwindow.h
+++ b/gui/include/streamwindow.h
@@ -44,6 +44,8 @@ class StreamWindow: public QMainWindow
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void closeEvent(QCloseEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index 2b4eafa..e4edf59 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -141,6 +141,15 @@ void StreamSession::SetLoginPIN(const QString &pin)
chiaki_session_set_login_pin(&session, (const uint8_t *)data.constData(), data.size());
}
+void StreamSession::HandleMouseEvent(QMouseEvent *event)
+{
+ if(event->type() == QEvent::MouseButtonPress)
+ keyboard_state.buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
+ else
+ keyboard_state.buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
+ SendFeedbackState();
+}
+
void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
{
uint64_t button_mask;
diff --git a/gui/src/streamwindow.cpp b/gui/src/streamwindow.cpp
index cfddbda..91ae8b0 100644
--- a/gui/src/streamwindow.cpp
+++ b/gui/src/streamwindow.cpp
@@ -86,6 +86,18 @@ void StreamWindow::keyReleaseEvent(QKeyEvent *event)
session->HandleKeyboardEvent(event);
}
+void StreamWindow::mousePressEvent(QMouseEvent *event)
+{
+ if(session)
+ session->HandleMouseEvent(event);
+}
+
+void StreamWindow::mouseReleaseEvent(QMouseEvent *event)
+{
+ if(session)
+ session->HandleMouseEvent(event);
+}
+
void StreamWindow::closeEvent(QCloseEvent *)
{
if(session)
From d9773c55e0a83d61ec8a56816e258f927f9ba720 Mon Sep 17 00:00:00 2001
From: Ritiek Malhotra
Date: Wed, 19 Feb 2020 23:03:00 +0530
Subject: [PATCH 004/269] Add wakeup command to CLI (#168)
---
cli/CMakeLists.txt | 3 +-
cli/include/chiaki-cli.h | 1 +
cli/src/main.c | 5 ++-
cli/src/wakeup.c | 92 ++++++++++++++++++++++++++++++++++++++++
gui/src/main.cpp | 3 +-
5 files changed, 101 insertions(+), 3 deletions(-)
create mode 100644 cli/src/wakeup.c
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index c718185..83c37a9 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -1,7 +1,8 @@
set(SOURCE
include/chiaki-cli.h
- src/discover.c)
+ src/discover.c
+ src/wakeup.c)
add_library(chiaki-cli-lib STATIC ${SOURCE})
target_include_directories(chiaki-cli-lib PUBLIC "include")
diff --git a/cli/include/chiaki-cli.h b/cli/include/chiaki-cli.h
index 0bd1e1b..13743e0 100644
--- a/cli/include/chiaki-cli.h
+++ b/cli/include/chiaki-cli.h
@@ -26,6 +26,7 @@ extern "C" {
#endif
CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[]);
+CHIAKI_EXPORT int chiaki_cli_cmd_wakeup(ChiakiLog *log, int argc, char *argv[]);
#ifdef __cplusplus
}
diff --git a/cli/src/main.c b/cli/src/main.c
index 7395ba8..05f0b4c 100644
--- a/cli/src/main.c
+++ b/cli/src/main.c
@@ -27,7 +27,8 @@ static const char doc[] =
"CLI for Chiaki (PS4 Remote Play Client)"
"\v"
"Supported commands are:\n"
- " discover Discover Consoles.\n";
+ " discover Discover Consoles.\n"
+ " wakeup Send Wakeup Packet.\n";
#define ARG_KEY_VERBOSE 'v'
@@ -73,6 +74,8 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
case ARGP_KEY_ARG:
if(strcmp(arg, "discover") == 0)
exit(call_subcmd(state, "discover", chiaki_cli_cmd_discover));
+ else if(strcmp(arg, "wakeup") == 0)
+ exit(call_subcmd(state, "wakeup", chiaki_cli_cmd_wakeup));
// fallthrough
case ARGP_KEY_END:
argp_usage(state);
diff --git a/cli/src/wakeup.c b/cli/src/wakeup.c
new file mode 100644
index 0000000..06a6220
--- /dev/null
+++ b/cli/src/wakeup.c
@@ -0,0 +1,92 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#include
+
+#include
+
+#include
+#include
+
+static char doc[] = "Send a PS4 wakeup packet.";
+
+#define ARG_KEY_HOST 'h'
+#define ARG_KEY_REGISTKEY 'r'
+
+static struct argp_option options[] = {
+ { "host", ARG_KEY_HOST, "Host", 0, "Host to send wakeup packet to", 0 },
+ { "registkey", ARG_KEY_REGISTKEY, "RegistKey", 0, "PS4 registration key", 0 },
+ { 0 }
+};
+
+typedef struct arguments
+{
+ const char *host;
+ const char *registkey;
+} Arguments;
+
+static int parse_opt(int key, char *arg, struct argp_state *state)
+{
+ Arguments *arguments = state->input;
+
+ switch(key)
+ {
+ case ARG_KEY_HOST:
+ arguments->host = arg;
+ break;
+ case ARG_KEY_REGISTKEY:
+ arguments->registkey = arg;
+ break;
+ case ARGP_KEY_ARG:
+ argp_usage(state);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+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 };
+ error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
+ if(argp_r != 0)
+ return 1;
+
+ if(!arguments.host)
+ {
+ fprintf(stderr, "No host specified, see --help.\n");
+ return 1;
+ }
+ if(!arguments.registkey)
+ {
+ fprintf(stderr, "No registration key specified, see --help.\n");
+ return 1;
+ }
+ if(strlen(arguments.registkey) > 8)
+ {
+ fprintf(stderr, "Given registkey is too long.\n");
+ return 1;
+ }
+
+ uint64_t credential = (uint64_t)strtoull(arguments.registkey, NULL, 16);
+
+ return chiaki_discovery_wakeup(log, NULL, arguments.host, credential);
+}
diff --git a/gui/src/main.cpp b/gui/src/main.cpp
index ec5ec30..3a2b449 100644
--- a/gui/src/main.cpp
+++ b/gui/src/main.cpp
@@ -40,7 +40,8 @@ struct CLICommand
};
static const QMap cli_commands = {
- { "discover", { chiaki_cli_cmd_discover } }
+ { "discover", { chiaki_cli_cmd_discover } },
+ { "wakeup", { chiaki_cli_cmd_wakeup } }
};
#endif
From a605ba083d1cfde8154c6372446440bee5d5d0eb Mon Sep 17 00:00:00 2001
From: Felipe Lavratti
Date: Sat, 29 Feb 2020 11:38:03 -0300
Subject: [PATCH 005/269] GUI: Add settings for keyboard mapping (#174)
---
gui/CMakeLists.txt | 2 +
gui/include/settings.h | 18 +++++
gui/include/settingskeycapturedialog.h | 37 ++++++++++
gui/include/streamsession.h | 5 +-
gui/src/settings.cpp | 97 ++++++++++++++++++++++++++
gui/src/settingsdialog.cpp | 61 +++++++++++++---
gui/src/settingskeycapturedialog.cpp | 45 ++++++++++++
gui/src/streamsession.cpp | 79 ++++++++++-----------
8 files changed, 292 insertions(+), 52 deletions(-)
create mode 100644 gui/include/settingskeycapturedialog.h
create mode 100644 gui/src/settingskeycapturedialog.cpp
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 76aec59..072320f 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -60,6 +60,8 @@ add_executable(chiaki WIN32
src/registdialog.cpp
include/host.h
src/host.cpp
+ include/settingskeycapturedialog.h
+ src/settingskeycapturedialog.cpp
include/settingsdialog.h
src/settingsdialog.cpp
include/manualhostdialog.h
diff --git a/gui/include/settings.h b/gui/include/settings.h
index 71cff6c..e15a56a 100644
--- a/gui/include/settings.h
+++ b/gui/include/settings.h
@@ -24,6 +24,19 @@
#include
+enum class ControllerButtonExt
+{
+ // must not overlap with ChiakiControllerButton and ChiakiControllerAnalogButton
+ ANALOG_STICK_LEFT_X_UP = (1 << 18),
+ ANALOG_STICK_LEFT_X_DOWN = (1 << 19),
+ ANALOG_STICK_LEFT_Y_UP = (1 << 20),
+ ANALOG_STICK_LEFT_Y_DOWN = (1 << 21),
+ ANALOG_STICK_RIGHT_X_UP = (1 << 22),
+ ANALOG_STICK_RIGHT_X_DOWN = (1 << 23),
+ ANALOG_STICK_RIGHT_Y_UP = (1 << 24),
+ ANALOG_STICK_RIGHT_Y_DOWN = (1 << 25),
+};
+
class Settings : public QObject
{
Q_OBJECT
@@ -90,6 +103,11 @@ class Settings : public QObject
bool GetManualHostExists(int id) { return manual_hosts.contains(id); }
ManualHost GetManualHost(int id) const { return manual_hosts[id]; }
+ static QString GetChiakiControllerButtonName(int);
+ void SetControllerButtonMapping(int, Qt::Key);
+ QMap GetControllerMapping();
+ QMap GetControllerMappingForDecoding();
+
signals:
void RegisteredHostsUpdated();
void ManualHostsUpdated();
diff --git a/gui/include/settingskeycapturedialog.h b/gui/include/settingskeycapturedialog.h
new file mode 100644
index 0000000..a4d7b36
--- /dev/null
+++ b/gui/include/settingskeycapturedialog.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#ifndef CHIAKI_SETTINGSKEYCAPTUREDIALOG_H
+#define CHIAKI_SETTINGSKEYCAPTUREDIALOG_H
+
+#include
+
+class SettingsKeyCaptureDialog : public QDialog
+{
+ Q_OBJECT
+
+ signals:
+ void KeyCaptured(Qt::Key);
+
+ protected:
+ void keyReleaseEvent(QKeyEvent *event) override;
+
+ public:
+ explicit SettingsKeyCaptureDialog(QWidget *parent = nullptr);
+};
+
+#endif // CHIAKI_SETTINGSKEYCAPTUREDIALOG_H
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index 721270b..fabb634 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
class QGamepad;
@@ -47,6 +48,7 @@ class ChiakiException: public Exception
struct StreamSessionConnectInfo
{
+ QMap key_map;
uint32_t log_level_mask;
QString log_file;
QString host;
@@ -55,7 +57,6 @@ struct StreamSessionConnectInfo
ChiakiConnectVideoProfile video_profile;
unsigned int audio_buffer_size;
- StreamSessionConnectInfo();
StreamSessionConnectInfo(Settings *settings, QString host, QByteArray regist_key, QByteArray morning);
};
@@ -83,6 +84,8 @@ class StreamSession : public QObject
QAudioOutput *audio_output;
QIODevice *audio_io;
+ QMap key_map;
+
void PushAudioFrame(int16_t *buf, size_t samples_count);
void PushVideoSample(uint8_t *buf, size_t buf_size);
void Event(ChiakiEvent *event);
diff --git a/gui/src/settings.cpp b/gui/src/settings.cpp
index b74552b..559c4e4 100644
--- a/gui/src/settings.cpp
+++ b/gui/src/settings.cpp
@@ -16,6 +16,7 @@
*/
#include
+#include
#define SETTINGS_VERSION 1
@@ -207,3 +208,99 @@ void Settings::RemoveManualHost(int id)
SaveManualHosts();
emit ManualHostsUpdated();
}
+
+QString Settings::GetChiakiControllerButtonName(int button)
+{
+ switch(button)
+ {
+ case CHIAKI_CONTROLLER_BUTTON_CROSS : return tr("Cross");
+ case CHIAKI_CONTROLLER_BUTTON_MOON : return tr("Moon");
+ case CHIAKI_CONTROLLER_BUTTON_BOX : return tr("Box");
+ case CHIAKI_CONTROLLER_BUTTON_PYRAMID : return tr("Pyramid");
+ case CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT : return tr("D-Pad Left");
+ case CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT : return tr("D-Pad Right");
+ case CHIAKI_CONTROLLER_BUTTON_DPAD_UP : return tr("D-Pad Up");
+ case CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN : return tr("D-Pad Down");
+ case CHIAKI_CONTROLLER_BUTTON_L1 : return tr("L1");
+ case CHIAKI_CONTROLLER_BUTTON_R1 : return tr("R1");
+ case CHIAKI_CONTROLLER_BUTTON_L3 : return tr("L3");
+ case CHIAKI_CONTROLLER_BUTTON_R3 : return tr("R3");
+ case CHIAKI_CONTROLLER_BUTTON_OPTIONS : return tr("Options");
+ case CHIAKI_CONTROLLER_BUTTON_SHARE : return tr("Share");
+ case CHIAKI_CONTROLLER_BUTTON_TOUCHPAD : return tr("Touchpad");
+ case CHIAKI_CONTROLLER_BUTTON_PS : return tr("PS");
+ case CHIAKI_CONTROLLER_ANALOG_BUTTON_L2 : return tr("L2");
+ case CHIAKI_CONTROLLER_ANALOG_BUTTON_R2 : return tr("R2");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_UP) : return tr("Left Stick Right");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_UP) : return tr("Left Stick Up");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_UP) : return tr("Right Stick Right");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_UP) : return tr("Right Stick Up");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_DOWN) : return tr("Left Stick Left");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_DOWN) : return tr("Left Stick Down");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_DOWN) : return tr("Right Stick Left");
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_DOWN) : return tr("Right Stick Down");
+ default: return "Unknown";
+ }
+}
+
+void Settings::SetControllerButtonMapping(int chiaki_button, Qt::Key key)
+{
+ auto button_name = GetChiakiControllerButtonName(chiaki_button).replace(' ', '_').toLower();
+ settings.setValue("keymap/" + button_name, QKeySequence(key).toString());
+}
+
+QMap Settings::GetControllerMapping()
+{
+ // Initialize with default values
+ QMap result =
+ {
+ {CHIAKI_CONTROLLER_BUTTON_CROSS , Qt::Key::Key_Return},
+ {CHIAKI_CONTROLLER_BUTTON_MOON , Qt::Key::Key_Backspace},
+ {CHIAKI_CONTROLLER_BUTTON_BOX , Qt::Key::Key_Backslash},
+ {CHIAKI_CONTROLLER_BUTTON_PYRAMID , Qt::Key::Key_C},
+ {CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT , Qt::Key::Key_Left},
+ {CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT, Qt::Key::Key_Right},
+ {CHIAKI_CONTROLLER_BUTTON_DPAD_UP , Qt::Key::Key_Up},
+ {CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN , Qt::Key::Key_Down},
+ {CHIAKI_CONTROLLER_BUTTON_L1 , Qt::Key::Key_2},
+ {CHIAKI_CONTROLLER_BUTTON_R1 , Qt::Key::Key_3},
+ {CHIAKI_CONTROLLER_BUTTON_L3 , Qt::Key::Key_5},
+ {CHIAKI_CONTROLLER_BUTTON_R3 , Qt::Key::Key_6},
+ {CHIAKI_CONTROLLER_BUTTON_OPTIONS , Qt::Key::Key_O},
+ {CHIAKI_CONTROLLER_BUTTON_SHARE , Qt::Key::Key_F},
+ {CHIAKI_CONTROLLER_BUTTON_TOUCHPAD , Qt::Key::Key_T},
+ {CHIAKI_CONTROLLER_BUTTON_PS , Qt::Key::Key_Escape},
+ {CHIAKI_CONTROLLER_ANALOG_BUTTON_L2 , Qt::Key::Key_1},
+ {CHIAKI_CONTROLLER_ANALOG_BUTTON_R2 , Qt::Key::Key_4},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_UP) , Qt::Key::Key_BracketRight},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_DOWN) , Qt::Key::Key_BracketLeft},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_UP) , Qt::Key::Key_Insert},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_DOWN) , Qt::Key::Key_Delete},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_UP) , Qt::Key::Key_Equal},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_DOWN), Qt::Key::Key_Minus},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_UP) , Qt::Key::Key_PageUp},
+ {static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_DOWN), Qt::Key::Key_PageDown}
+ };
+
+ // Then fill in from settings
+ auto chiaki_buttons = result.keys();
+ for(auto chiaki_button : chiaki_buttons)
+ {
+ auto button_name = GetChiakiControllerButtonName(chiaki_button).replace(' ', '_').toLower();
+ if(settings.contains("keymap/" + button_name))
+ result[static_cast(chiaki_button)] = Qt::Key(QKeySequence(settings.value("keymap/" + button_name).toString())[0]);
+ }
+
+ return result;
+}
+
+QMap Settings::GetControllerMappingForDecoding()
+{
+ auto map = GetControllerMapping();
+ QMap result;
+ for(auto it = map.begin(); it != map.end(); ++it)
+ {
+ result[it.value()] = it.key();
+ }
+ return result;
+}
diff --git a/gui/src/settingsdialog.cpp b/gui/src/settingsdialog.cpp
index 86b47d9..30dc00a 100644
--- a/gui/src/settingsdialog.cpp
+++ b/gui/src/settingsdialog.cpp
@@ -17,9 +17,11 @@
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -32,7 +34,6 @@
#include
#include
-
const char * const about_string =
"Chiaki by thestr4ng3r, version " CHIAKI_VERSION
""
@@ -46,21 +47,28 @@ const char * const about_string =
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
"GNU General Public License for more details.
";
-
SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(parent)
{
this->settings = settings;
setWindowTitle(tr("Settings"));
- auto layout = new QVBoxLayout(this);
- setLayout(layout);
+ auto root_layout = new QVBoxLayout(this);
+ setLayout(root_layout);
+ auto horizontal_layout = new QHBoxLayout();
+ root_layout->addLayout(horizontal_layout);
+
+ auto left_layout = new QVBoxLayout();
+ horizontal_layout->addLayout(left_layout);
+
+ auto right_layout = new QVBoxLayout();
+ horizontal_layout->addLayout(right_layout);
// General
auto general_group_box = new QGroupBox(tr("General"));
- layout->addWidget(general_group_box);
+ left_layout->addWidget(general_group_box);
auto general_layout = new QFormLayout();
general_group_box->setLayout(general_layout);
@@ -85,7 +93,7 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
// Stream Settings
auto stream_settings_group_box = new QGroupBox(tr("Stream Settings"));
- layout->addWidget(stream_settings_group_box);
+ left_layout->addWidget(stream_settings_group_box);
auto stream_settings_layout = new QFormLayout();
stream_settings_group_box->setLayout(stream_settings_layout);
@@ -141,7 +149,7 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
// Registered Consoles
auto registered_hosts_group_box = new QGroupBox(tr("Registered Consoles"));
- layout->addWidget(registered_hosts_group_box);
+ left_layout->addWidget(registered_hosts_group_box);
auto registered_hosts_layout = new QHBoxLayout();
registered_hosts_group_box->setLayout(registered_hosts_layout);
@@ -162,8 +170,43 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
registered_hosts_buttons_layout->addStretch();
+ // Key Settings
+ auto key_settings_group_box = new QGroupBox(tr("Key Settings"));
+ right_layout->addWidget(key_settings_group_box);
+ auto key_horizontal = new QHBoxLayout();
+ key_settings_group_box->setLayout(key_horizontal);
+ key_horizontal->setSpacing(10);
+
+ auto key_left_form = new QFormLayout();
+ auto key_right_form = new QFormLayout();
+ key_horizontal->addLayout(key_left_form);
+ key_horizontal->addLayout(key_right_form);
+
+ QMap key_map = this->settings->GetControllerMapping();
+
+ int i = 0;
+ for(auto it = key_map.begin(); it != key_map.end(); ++it, ++i)
+ {
+ int chiaki_button = it.key();
+ auto button = new QPushButton(QKeySequence(it.value()).toString(), this);
+ button->setAutoDefault(false);
+ auto form = i % 2 ? key_left_form : key_right_form;
+ form->addRow(Settings::GetChiakiControllerButtonName(chiaki_button), button);
+ // Launch key capture dialog on clicked event
+ connect(button, &QPushButton::clicked, this, [this, chiaki_button, button](){
+ auto dialog = new SettingsKeyCaptureDialog(this);
+ // Store captured key to settings and change button label on KeyCaptured event
+ connect(dialog, &SettingsKeyCaptureDialog::KeyCaptured, button, [this, button, chiaki_button](Qt::Key key){
+ button->setText(QKeySequence(key).toString());
+ this->settings->SetControllerButtonMapping(chiaki_button, key);
+ });
+ dialog->exec();
+ });
+ }
+
+ // Close Button
auto button_box = new QDialogButtonBox(QDialogButtonBox::Close, this);
- layout->addWidget(button_box);
+ root_layout->addWidget(button_box);
connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
button_box->button(QDialogButtonBox::Close)->setDefault(true);
@@ -241,4 +284,4 @@ void SettingsDialog::DeleteRegisteredHost()
return;
settings->RemoveRegisteredHost(mac);
-}
\ No newline at end of file
+}
diff --git a/gui/src/settingskeycapturedialog.cpp b/gui/src/settingskeycapturedialog.cpp
new file mode 100644
index 0000000..10e0bb3
--- /dev/null
+++ b/gui/src/settingskeycapturedialog.cpp
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#include "settingskeycapturedialog.h"
+
+#include
+#include
+#include
+#include
+
+SettingsKeyCaptureDialog::SettingsKeyCaptureDialog(QWidget* parent)
+{
+ setWindowTitle(tr("Key Capture"));
+
+ auto root_layout = new QVBoxLayout(this);
+ setLayout(root_layout);
+
+ auto label = new QLabel(tr("Press any key to configure button or click close."));
+ root_layout->addWidget(label);
+
+ auto button = new QPushButton(tr("Close"), this);
+ root_layout->addWidget(button);
+ button->setAutoDefault(false);
+ connect(button, &QPushButton::clicked, this, &QDialog::accept);
+}
+
+void SettingsKeyCaptureDialog::keyReleaseEvent(QKeyEvent* event)
+{
+ KeyCaptured(Qt::Key(event->key()));
+ accept();
+}
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index e4edf59..2e427f8 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -32,15 +32,9 @@
#include
#include
-StreamSessionConnectInfo::StreamSessionConnectInfo()
-{
- log_level_mask = CHIAKI_LOG_ALL;
- std::memset(&video_profile, 0, sizeof(video_profile));
- audio_buffer_size = 9600;
-}
-
StreamSessionConnectInfo::StreamSessionConnectInfo(Settings *settings, QString host, QByteArray regist_key, QByteArray morning)
{
+ key_map = settings->GetControllerMappingForDecoding();
log_level_mask = settings->GetLogLevelMask();
log_file = CreateLogFilename();
video_profile = settings->GetVideoProfile();
@@ -104,6 +98,7 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
connect(ControllerManager::GetInstance(), &ControllerManager::AvailableControllersUpdated, this, &StreamSession::UpdateGamepads);
#endif
+ key_map = connect_info.key_map;
UpdateGamepads();
}
@@ -152,55 +147,55 @@ void StreamSession::HandleMouseEvent(QMouseEvent *event)
void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
{
- uint64_t button_mask;
- switch(event->key())
+ if(key_map.contains(Qt::Key(event->key())) == false)
+ return;
+
+ if(event->isAutoRepeat())
+ return;
+
+ int button = key_map[Qt::Key(event->key())];
+ bool press_event = event->type() == QEvent::Type::KeyPress;
+
+ switch(button)
{
- case Qt::Key::Key_Left:
- button_mask = CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT;
+ case CHIAKI_CONTROLLER_ANALOG_BUTTON_L2:
+ keyboard_state.l2_state = press_event ? 0xff : 0;
break;
- case Qt::Key::Key_Right:
- button_mask = CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT;
+ case CHIAKI_CONTROLLER_ANALOG_BUTTON_R2:
+ keyboard_state.r2_state = press_event ? 0xff : 0;
break;
- case Qt::Key::Key_Up:
- button_mask = CHIAKI_CONTROLLER_BUTTON_DPAD_UP;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_UP):
+ keyboard_state.right_y = press_event ? -0x3fff : 0;
break;
- case Qt::Key::Key_Down:
- button_mask = CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_DOWN):
+ keyboard_state.right_y = press_event ? 0x3fff : 0;
break;
- case Qt::Key::Key_Return:
- button_mask = CHIAKI_CONTROLLER_BUTTON_CROSS;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_UP):
+ keyboard_state.right_x = press_event ? 0x3fff : 0;
break;
- case Qt::Key::Key_Backspace:
- button_mask = CHIAKI_CONTROLLER_BUTTON_MOON;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_DOWN):
+ keyboard_state.right_x = press_event ? -0x3fff : 0;
break;
- case Qt::Key::Key_Backslash:
- case Qt::Key::Key_X:
- button_mask = CHIAKI_CONTROLLER_BUTTON_BOX;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_UP):
+ keyboard_state.left_y = press_event ? -0x3fff : 0;
break;
- case Qt::Key::Key_C:
- case Qt::Key::Key_BracketRight:
- button_mask = CHIAKI_CONTROLLER_BUTTON_PYRAMID;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_DOWN):
+ keyboard_state.left_y = press_event ? 0x3fff : 0;
break;
- case Qt::Key::Key_F:
- case Qt::Key::Key_BracketLeft:
- button_mask = CHIAKI_CONTROLLER_BUTTON_SHARE;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_UP):
+ keyboard_state.left_x = press_event ? 0x3fff : 0;
break;
- case Qt::Key::Key_Escape:
- button_mask = CHIAKI_CONTROLLER_BUTTON_PS;
- break;
- case Qt::Key::Key_T:
- button_mask = CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
+ case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_DOWN):
+ keyboard_state.left_x = press_event ? -0x3fff : 0;
break;
default:
- // not interested
- return;
+ if(press_event)
+ keyboard_state.buttons |= button;
+ else
+ keyboard_state.buttons &= ~button;
+ break;
}
- if(event->type() == QEvent::KeyPress)
- keyboard_state.buttons |= button_mask;
- else
- keyboard_state.buttons &= ~button_mask;
-
SendFeedbackState();
}
From b0b8bac984b3b13ffc162c2eedbebebc1c1f0be9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 29 Feb 2020 15:40:00 +0100
Subject: [PATCH 006/269] Update README.md for Keybindings
---
README.md | 8 --------
1 file changed, 8 deletions(-)
diff --git a/README.md b/README.md
index 01fc9a0..83de09e 100644
--- a/README.md
+++ b/README.md
@@ -21,14 +21,6 @@ The following features however are yet to be implemented:
* H264 Error Concealment (FEC and active error recovery however are implemented)
* Touchpad support (Triggering the Touchpad Button is currently possible by pressing `T` on the keyboard)
* Rumble
-* Configurable Keybindings. Though, for the moment you can use the following:
- * `⏎` -> Cross
- * `⌫` -> Moon
- * `\` or `X` -> Box
- * `]` or `C` -> Pyramid
- * `F` or `[` -> Share
- * `⇦⇧⇩⇨` -> D-Pad
- * `Esc` -> PS
## Installing
From 599d08b8bf1cfb10ab68c465ee31dd5e3418f8f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Tue, 10 Mar 2020 20:10:30 +0100
Subject: [PATCH 007/269] Fix Keyboard Stick Constant
---
gui/src/streamsession.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index 2e427f8..cccab98 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -165,28 +165,28 @@ void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
keyboard_state.r2_state = press_event ? 0xff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_UP):
- keyboard_state.right_y = press_event ? -0x3fff : 0;
+ keyboard_state.right_y = press_event ? -0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_Y_DOWN):
- keyboard_state.right_y = press_event ? 0x3fff : 0;
+ keyboard_state.right_y = press_event ? 0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_UP):
- keyboard_state.right_x = press_event ? 0x3fff : 0;
+ keyboard_state.right_x = press_event ? 0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_RIGHT_X_DOWN):
- keyboard_state.right_x = press_event ? -0x3fff : 0;
+ keyboard_state.right_x = press_event ? -0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_UP):
- keyboard_state.left_y = press_event ? -0x3fff : 0;
+ keyboard_state.left_y = press_event ? -0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_Y_DOWN):
- keyboard_state.left_y = press_event ? 0x3fff : 0;
+ keyboard_state.left_y = press_event ? 0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_UP):
- keyboard_state.left_x = press_event ? 0x3fff : 0;
+ keyboard_state.left_x = press_event ? 0x7fff : 0;
break;
case static_cast(ControllerButtonExt::ANALOG_STICK_LEFT_X_DOWN):
- keyboard_state.left_x = press_event ? -0x3fff : 0;
+ keyboard_state.left_x = press_event ? -0x7fff : 0;
break;
default:
if(press_event)
From 7873ced39e68953527c220f88e877822f6f6f397 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Tue, 10 Mar 2020 20:11:50 +0100
Subject: [PATCH 008/269] Temporarily enable Homebrew Update on Travis
---
.travis.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index 606f380..8109c57 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -77,6 +77,7 @@ matrix:
osx_image: xcode11
addons:
homebrew:
+ update: true # tmp
packages:
- qt
- opus
@@ -88,6 +89,8 @@ matrix:
- CMAKE_EXTRA_ARGS=""
- DEPLOY=1
install:
+ - brew unlink python@2 # tmp
+ - brew link python # tmp
- scripts/build-ffmpeg.sh
script:
- scripts/travis-build.sh
From ec2cad480ca8f5df25663157c498fa4000cda784 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Wed, 11 Mar 2020 19:30:49 +0100
Subject: [PATCH 009/269] Update Android Dependencies
---
android/app/build.gradle | 19 +++++++++++++------
.../gradle/wrapper/gradle-wrapper.properties | 4 ++--
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/android/app/build.gradle b/android/app/build.gradle
index db962f9..1b0bb56 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,6 +37,13 @@ android {
}
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
externalNativeBuild {
cmake {
version "3.10.2+"
@@ -95,18 +102,18 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'androidx.core:core-ktx:1.1.0'
+ implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'androidx.recyclerview:recyclerview:1.0.0'
+ 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.1.0'
- implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
- implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.1.0'
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
+ implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.2.0'
implementation "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.2.1"
+ 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"
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 2362665..71e8098 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Sep 14 10:53:58 CEST 2019
+#Wed Mar 11 18:48:31 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
From ffe7d0908838caaf0c288a80ed2dda87998902b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Wed, 11 Mar 2020 19:38:14 +0100
Subject: [PATCH 010/269] Fix Android Warnings
---
.../metallic/chiaki/common/SerializedSettings.kt | 2 +-
.../com/metallic/chiaki/main/MainActivity.kt | 5 ++---
.../manualconsole/EditManualConsoleActivity.kt | 5 ++---
.../com/metallic/chiaki/regist/RegistActivity.kt | 4 ++--
.../chiaki/regist/RegistExecuteActivity.kt | 5 ++---
.../metallic/chiaki/settings/SettingsFragment.kt | 16 ++++++----------
.../chiaki/settings/SettingsLogsFragment.kt | 7 +++----
.../settings/SettingsRegisteredHostsFragment.kt | 5 ++---
.../com/metallic/chiaki/stream/StreamActivity.kt | 4 ++--
9 files changed, 22 insertions(+), 31 deletions(-)
diff --git a/android/app/src/main/java/com/metallic/chiaki/common/SerializedSettings.kt b/android/app/src/main/java/com/metallic/chiaki/common/SerializedSettings.kt
index 174e620..234f5db 100644
--- a/android/app/src/main/java/com/metallic/chiaki/common/SerializedSettings.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/common/SerializedSettings.kt
@@ -150,7 +150,7 @@ fun exportAndShareAllSettings(activity: Activity): Disposable
file
}
.observeOn(AndroidSchedulers.mainThread())
- .subscribe { it: File ->
+ .subscribe { _ ->
val uri = FileProvider.getUriForFile(activity, fileProviderAuthority, file)
Intent(Intent.ACTION_SEND).also {
it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
diff --git a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt
index 9e85b91..07c06eb 100644
--- a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt
@@ -25,7 +25,7 @@ import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.metallic.chiaki.R
@@ -67,8 +67,7 @@ class MainActivity : AppCompatActivity()
registerButton.setOnClickListener { showRegistration() }
registerLabelButton.setOnClickListener { showRegistration() }
- viewModel = ViewModelProviders
- .of(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) })
+ viewModel = ViewModelProvider(this, viewModelFactory { MainViewModel(getDatabase(this), Preferences(this)) })
.get(MainViewModel::class.java)
val recyclerViewAdapter = DisplayHostRecyclerViewAdapter(this::hostTriggered, this::wakeupHost, this::editHost, this::deleteHost)
diff --git a/android/app/src/main/java/com/metallic/chiaki/manualconsole/EditManualConsoleActivity.kt b/android/app/src/main/java/com/metallic/chiaki/manualconsole/EditManualConsoleActivity.kt
index 01ed245..c200781 100644
--- a/android/app/src/main/java/com/metallic/chiaki/manualconsole/EditManualConsoleActivity.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/manualconsole/EditManualConsoleActivity.kt
@@ -25,7 +25,7 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import com.metallic.chiaki.R
import com.metallic.chiaki.common.RegisteredHost
import com.metallic.chiaki.common.ext.RevealActivity
@@ -57,8 +57,7 @@ class EditManualConsoleActivity: AppCompatActivity(), RevealActivity
setContentView(R.layout.activity_edit_manual)
handleReveal()
- viewModel = ViewModelProviders
- .of(this, viewModelFactory {
+ viewModel = ViewModelProvider(this, viewModelFactory {
EditManualConsoleViewModel(getDatabase(this),
if(intent.hasExtra(EXTRA_MANUAL_HOST_ID))
intent.getLongExtra(EXTRA_MANUAL_HOST_ID, 0)
diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt
index aa8b650..04e29f0 100644
--- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt
@@ -24,7 +24,7 @@ import android.view.View
import android.view.Window
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import com.metallic.chiaki.R
import com.metallic.chiaki.common.ext.RevealActivity
import com.metallic.chiaki.lib.RegistInfo
@@ -56,7 +56,7 @@ class RegistActivity: AppCompatActivity(), RevealActivity
setContentView(R.layout.activity_regist)
handleReveal()
- viewModel = ViewModelProviders.of(this).get(RegistViewModel::class.java)
+ viewModel = ViewModelProvider(this).get(RegistViewModel::class.java)
hostEditText.setText(intent.getStringExtra(EXTRA_HOST) ?: "255.255.255.255")
broadcastCheckBox.isChecked = intent.getBooleanExtra(EXTRA_BROADCAST, true)
diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt
index d339578..c56a86c 100644
--- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt
@@ -25,7 +25,7 @@ import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.metallic.chiaki.R
import com.metallic.chiaki.common.MacAddress
@@ -52,8 +52,7 @@ class RegistExecuteActivity: AppCompatActivity()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_regist_execute)
- viewModel = ViewModelProviders
- .of(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) })
+ viewModel = ViewModelProvider(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) })
.get(RegistExecuteViewModel::class.java)
logTextView.setHorizontallyScrolling(true)
diff --git a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsFragment.kt b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsFragment.kt
index ee2cf57..e541a61 100644
--- a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsFragment.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsFragment.kt
@@ -18,24 +18,21 @@
package com.metallic.chiaki.settings
import android.app.Activity
-import android.content.ClipData
import android.content.Intent
import android.content.res.Resources
import android.os.Bundle
import android.text.InputType
-import androidx.core.content.FileProvider
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import androidx.preference.*
import com.metallic.chiaki.R
-import com.metallic.chiaki.common.*
-import com.metallic.chiaki.common.ext.toLiveData
+import com.metallic.chiaki.common.Preferences
+import com.metallic.chiaki.common.exportAndShareAllSettings
import com.metallic.chiaki.common.ext.viewModelFactory
-import io.reactivex.android.schedulers.AndroidSchedulers
+import com.metallic.chiaki.common.getDatabase
+import com.metallic.chiaki.common.importSettingsFromUri
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
-import io.reactivex.schedulers.Schedulers
-import java.io.File
class DataStore(val preferences: Preferences): PreferenceDataStore()
{
@@ -96,8 +93,7 @@ class SettingsFragment: PreferenceFragmentCompat(), TitleFragment
{
val context = context ?: return
- val viewModel = ViewModelProviders
- .of(this, viewModelFactory { SettingsViewModel(getDatabase(context), Preferences(context)) })
+ val viewModel = ViewModelProvider(this, viewModelFactory { SettingsViewModel(getDatabase(context), Preferences(context)) })
.get(SettingsViewModel::class.java)
val preferences = viewModel.preferences
diff --git a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsLogsFragment.kt b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsLogsFragment.kt
index b1edbba..82c3a15 100644
--- a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsLogsFragment.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsLogsFragment.kt
@@ -27,7 +27,7 @@ import android.view.ViewGroup
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.core.content.FileProvider
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -49,15 +49,14 @@ class SettingsLogsFragment: AppCompatDialogFragment(), TitleFragment
{
val context = context!!
- viewModel = ViewModelProviders
- .of(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) })
+ viewModel = ViewModelProvider(this, viewModelFactory { SettingsLogsViewModel(LogManager(context)) })
.get(SettingsLogsViewModel::class.java)
val adapter = SettingsLogsAdapter()
logsRecyclerView.layoutManager = LinearLayoutManager(context)
logsRecyclerView.adapter = adapter
adapter.shareCallback = this::shareLogFile
- viewModel.sessionLogs.observe(this, Observer {
+ viewModel.sessionLogs.observe(viewLifecycleOwner, Observer {
adapter.logFiles = it
emptyInfoGroup.visibility = if(it.isEmpty()) View.VISIBLE else View.GONE
})
diff --git a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsRegisteredHostsFragment.kt b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsRegisteredHostsFragment.kt
index 517f08e..946c3ea 100644
--- a/android/app/src/main/java/com/metallic/chiaki/settings/SettingsRegisteredHostsFragment.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/settings/SettingsRegisteredHostsFragment.kt
@@ -26,7 +26,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -47,8 +47,7 @@ class SettingsRegisteredHostsFragment: AppCompatDialogFragment(), TitleFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
- viewModel = ViewModelProviders
- .of(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context!!)) })
+ viewModel = ViewModelProvider(this, viewModelFactory { SettingsRegisteredHostsViewModel(getDatabase(context!!)) })
.get(SettingsRegisteredHostsViewModel::class.java)
val adapter = SettingsRegisteredHostsAdapter()
diff --git a/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt b/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt
index 40be5f9..a7913a4 100644
--- a/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt
+++ b/android/app/src/main/java/com/metallic/chiaki/stream/StreamActivity.kt
@@ -72,7 +72,7 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
return
}
- viewModel = ViewModelProviders.of(this, viewModelFactory {
+ viewModel = ViewModelProvider(this, viewModelFactory {
StreamViewModel(Preferences(this), LogManager(this), connectInfo)
})[StreamViewModel::class.java]
@@ -101,7 +101,7 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
showOverlay()
}
- displayModeToggle.addOnButtonCheckedListener {group, checkedId, _ ->
+ 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
From 8c651b08905cae160a3751c5165cd2f572a7677c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Siudut?=
Date: Wed, 22 Apr 2020 09:57:18 +0100
Subject: [PATCH 011/269] Add VAAPI support to Qt GUI (Fix #26) (#205)
---
gui/include/avopenglwidget.h | 27 +++++++-
gui/include/settings.h | 4 ++
gui/include/settingsdialog.h | 2 +
gui/include/streamsession.h | 1 +
gui/include/videodecoder.h | 25 ++++++-
gui/src/avopenglwidget.cpp | 124 ++++++++++++++++++++++++++---------
gui/src/settings.cpp | 19 ++++++
gui/src/settingsdialog.cpp | 29 ++++++++
gui/src/streamsession.cpp | 3 +-
gui/src/videodecoder.cpp | 73 +++++++++++++++++++--
scripts/build-ffmpeg.sh | 2 +-
11 files changed, 269 insertions(+), 40 deletions(-)
diff --git a/gui/include/avopenglwidget.h b/gui/include/avopenglwidget.h
index 6451d8f..312f16c 100644
--- a/gui/include/avopenglwidget.h
+++ b/gui/include/avopenglwidget.h
@@ -28,15 +28,36 @@ extern "C"
#include
}
+#define MAX_PANES 3
+
class VideoDecoder;
class AVOpenGLFrameUploader;
+struct PlaneConfig
+{
+ unsigned int width_divider;
+ unsigned int height_divider;
+ unsigned int data_per_pixel;
+ GLint internal_format;
+ GLenum format;
+};
+
+struct ConversionConfig
+{
+ enum AVPixelFormat pixel_format;
+ const char *shader_vert_glsl;
+ const char *shader_frag_glsl;
+ unsigned int planes;
+ struct PlaneConfig plane_configs[MAX_PANES];
+};
+
struct AVOpenGLFrame
{
- GLuint pbo[3];
- GLuint tex[3];
+ GLuint pbo[MAX_PANES];
+ GLuint tex[MAX_PANES];
unsigned int width;
unsigned int height;
+ ConversionConfig *conversion_config;
bool Update(AVFrame *frame, ChiakiLog *log);
};
@@ -61,6 +82,8 @@ class AVOpenGLWidget: public QOpenGLWidget
QTimer *mouse_timer;
+ ConversionConfig *conversion_config;
+
public:
static QSurfaceFormat CreateSurfaceFormat();
diff --git a/gui/include/settings.h b/gui/include/settings.h
index e15a56a..c52b42f 100644
--- a/gui/include/settings.h
+++ b/gui/include/settings.h
@@ -21,6 +21,7 @@
#include
#include "host.h"
+#include "videodecoder.h"
#include
@@ -76,6 +77,9 @@ class Settings : public QObject
unsigned int GetBitrate() const;
void SetBitrate(unsigned int bitrate);
+ HardwareDecodeEngine GetHardwareDecodeEngine() const;
+ void SetHardwareDecodeEngine(HardwareDecodeEngine enabled);
+
unsigned int GetAudioBufferSizeDefault() const;
/**
diff --git a/gui/include/settingsdialog.h b/gui/include/settingsdialog.h
index abc5a33..13a40c9 100644
--- a/gui/include/settingsdialog.h
+++ b/gui/include/settingsdialog.h
@@ -39,6 +39,7 @@ class SettingsDialog : public QDialog
QComboBox *fps_combo_box;
QLineEdit *bitrate_edit;
QLineEdit *audio_buffer_size_edit;
+ QComboBox *hardware_decode_combo_box;
QListWidget *registered_hosts_list_widget;
QPushButton *delete_registered_host_button;
@@ -52,6 +53,7 @@ class SettingsDialog : public QDialog
void FPSSelected();
void BitrateEdited();
void AudioBufferSizeEdited();
+ void HardwareDecodeEngineSelected();
void UpdateRegisteredHosts();
void UpdateRegisteredHostsButtons();
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index fabb634..15ac4c5 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -49,6 +49,7 @@ class ChiakiException: public Exception
struct StreamSessionConnectInfo
{
QMap key_map;
+ HardwareDecodeEngine hw_decode_engine;
uint32_t log_level_mask;
QString log_file;
QString host;
diff --git a/gui/include/videodecoder.h b/gui/include/videodecoder.h
index e71e3c6..84ccf0a 100644
--- a/gui/include/videodecoder.h
+++ b/gui/include/videodecoder.h
@@ -22,6 +22,7 @@
#include "exception.h"
+#include
#include
#include
@@ -32,6 +33,20 @@ extern "C"
#include
+
+typedef enum {
+ HW_DECODE_NONE = 0,
+ HW_DECODE_VAAPI = 1,
+ HW_DECODE_VDPAU = 2,
+} HardwareDecodeEngine;
+
+
+static const QMap hardware_decode_engine_names = {
+ { HW_DECODE_NONE, "none"},
+ { HW_DECODE_VAAPI, "vaapi"},
+ { HW_DECODE_VDPAU, "vdpau"},
+};
+
class VideoDecoderException: public Exception
{
public:
@@ -43,23 +58,31 @@ class VideoDecoder: public QObject
Q_OBJECT
public:
- VideoDecoder(ChiakiLog *log);
+ VideoDecoder(HardwareDecodeEngine hw_decode_engine, ChiakiLog *log);
~VideoDecoder();
void PushFrame(uint8_t *buf, size_t buf_size);
AVFrame *PullFrame();
+ AVFrame *GetFromHardware(AVFrame *hw_frame);
ChiakiLog *GetChiakiLog() { return log; }
+ enum AVPixelFormat PixelFormat() { return hw_decode_engine?AV_PIX_FMT_NV12:AV_PIX_FMT_YUV420P; }
+
signals:
void FramesAvailable();
private:
+ HardwareDecodeEngine hw_decode_engine;
+
ChiakiLog *log;
QMutex mutex;
AVCodec *codec;
AVCodecContext *codec_context;
+
+ enum AVPixelFormat hw_pix_fmt;
+ AVBufferRef *hw_device_ctx;
};
#endif // CHIAKI_VIDEODECODER_H
diff --git a/gui/src/avopenglwidget.cpp b/gui/src/avopenglwidget.cpp
index 164836d..11d4b09 100644
--- a/gui/src/avopenglwidget.cpp
+++ b/gui/src/avopenglwidget.cpp
@@ -43,12 +43,35 @@ void main()
}
)glsl";
-static const char *shader_frag_glsl = R"glsl(
+static const char *yuv420p_shader_frag_glsl = R"glsl(
#version 150 core
-uniform sampler2D tex_y;
-uniform sampler2D tex_u;
-uniform sampler2D tex_v;
+uniform sampler2D plane1; // Y
+uniform sampler2D plane2; // U
+uniform sampler2D plane3; // V
+
+in vec2 uv_var;
+out vec4 out_color;
+
+void main()
+{
+ vec3 yuv = vec3(
+ (texture(plane1, uv_var).r - (16.0 / 255.0)) / ((235.0 - 16.0) / 255.0),
+ (texture(plane2, uv_var).r - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5,
+ (texture(plane3, uv_var).r - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5);
+ vec3 rgb = mat3(
+ 1.0, 1.0, 1.0,
+ 0.0, -0.21482, 2.12798,
+ 1.28033, -0.38059, 0.0) * yuv;
+ out_color = vec4(rgb, 1.0);
+}
+)glsl";
+
+static const char *nv12_shader_frag_glsl = R"glsl(
+#version 150 core
+
+uniform sampler2D plane1; // Y
+uniform sampler2D plane2; // interlaced UV
in vec2 uv_var;
@@ -57,9 +80,10 @@ out vec4 out_color;
void main()
{
vec3 yuv = vec3(
- (texture(tex_y, uv_var).r - (16.0 / 255.0)) / ((235.0 - 16.0) / 255.0),
- (texture(tex_u, uv_var).r - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5,
- (texture(tex_v, uv_var).r - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5);
+ (texture(plane1, uv_var).r - (16.0 / 255.0)) / ((235.0 - 16.0) / 255.0),
+ (texture(plane2, uv_var).r - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5,
+ (texture(plane2, uv_var).g - (16.0 / 255.0)) / ((240.0 - 16.0) / 255.0) - 0.5
+ );
vec3 rgb = mat3(
1.0, 1.0, 1.0,
0.0, -0.21482, 2.12798,
@@ -68,6 +92,30 @@ void main()
}
)glsl";
+ConversionConfig conversion_configs[] = {
+ {
+ AV_PIX_FMT_YUV420P,
+ shader_vert_glsl,
+ yuv420p_shader_frag_glsl,
+ 3,
+ {
+ { 1, 1, 1, GL_R8, GL_RED },
+ { 2, 2, 1, GL_R8, GL_RED },
+ { 2, 2, 1, GL_R8, GL_RED }
+ }
+ },
+ {
+ AV_PIX_FMT_NV12,
+ shader_vert_glsl,
+ nv12_shader_frag_glsl,
+ 2,
+ {
+ { 1, 1, 1, GL_R8, GL_RED },
+ { 2, 2, 2, GL_RG8, GL_RG }
+ }
+ }
+};
+
static const float vert_pos[] = {
0.0f, 0.0f,
0.0f, 1.0f,
@@ -93,6 +141,19 @@ AVOpenGLWidget::AVOpenGLWidget(VideoDecoder *decoder, QWidget *parent)
: QOpenGLWidget(parent),
decoder(decoder)
{
+ conversion_config = nullptr;
+ for(auto &cc: conversion_configs)
+ {
+ if(decoder->PixelFormat() == cc.pixel_format)
+ {
+ conversion_config = &cc;
+ break;
+ }
+ }
+
+ if(!conversion_config)
+ throw Exception("No matching video conversion config can be found");
+
setFormat(CreateSurfaceFormat());
frame_uploader_context = nullptr;
@@ -146,7 +207,7 @@ bool AVOpenGLFrame::Update(AVFrame *frame, ChiakiLog *log)
{
auto f = QOpenGLContext::currentContext()->extraFunctions();
- if(frame->format != AV_PIX_FMT_YUV420P)
+ if(frame->format != conversion_config->pixel_format)
{
CHIAKI_LOGE(log, "AVOpenGLFrame got AVFrame with invalid format");
return false;
@@ -155,20 +216,16 @@ bool AVOpenGLFrame::Update(AVFrame *frame, ChiakiLog *log)
width = frame->width;
height = frame->height;
- for(int i=0; i<3; i++)
+ for(int i=0; iplanes; i++)
{
- int width = frame->width;
- int height = frame->height;
- if(i > 0)
- {
- width /= 2;
- height /= 2;
- }
+ int width = frame->width / conversion_config->plane_configs[i].width_divider;
+ int height = frame->height / conversion_config->plane_configs[i].height_divider;
+ int size = width * height * conversion_config->plane_configs[i].data_per_pixel;
f->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[i]);
- f->glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height, nullptr, GL_STREAM_DRAW);
+ f->glBufferData(GL_PIXEL_UNPACK_BUFFER, size, nullptr, GL_STREAM_DRAW);
- auto buf = reinterpret_cast(f->glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
+ auto buf = reinterpret_cast(f->glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
if(!buf)
{
CHIAKI_LOGE(log, "AVOpenGLFrame failed to map PBO");
@@ -176,17 +233,17 @@ bool AVOpenGLFrame::Update(AVFrame *frame, ChiakiLog *log)
}
if(frame->linesize[i] == width)
- memcpy(buf, frame->data[i], width * height);
+ memcpy(buf, frame->data[i], size);
else
{
for(int l=0; ldata[i] + frame->linesize[i] * l, width);
+ memcpy(buf + width * l * conversion_config->plane_configs[i].data_per_pixel, frame->data[i] + frame->linesize[i] * l, width * conversion_config->plane_configs[i].data_per_pixel);
}
f->glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
f->glBindTexture(GL_TEXTURE_2D, tex[i]);
- f->glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
+ f->glTexImage2D(GL_TEXTURE_2D, 0, conversion_config->plane_configs[i].internal_format, width, height, 0, conversion_config->plane_configs[i].format, GL_UNSIGNED_BYTE, nullptr);
}
f->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -226,12 +283,12 @@ void AVOpenGLWidget::initializeGL()
};
GLuint shader_vert = f->glCreateShader(GL_VERTEX_SHADER);
- f->glShaderSource(shader_vert, 1, &shader_vert_glsl, nullptr);
+ f->glShaderSource(shader_vert, 1, &conversion_config->shader_vert_glsl, nullptr);
f->glCompileShader(shader_vert);
CheckShaderCompiled(shader_vert);
GLuint shader_frag = f->glCreateShader(GL_FRAGMENT_SHADER);
- f->glShaderSource(shader_frag, 1, &shader_frag_glsl, nullptr);
+ f->glShaderSource(shader_frag, 1, &conversion_config->shader_frag_glsl, nullptr);
f->glCompileShader(shader_frag);
CheckShaderCompiled(shader_frag);
@@ -256,26 +313,31 @@ void AVOpenGLWidget::initializeGL()
for(int i=0; i<2; i++)
{
- f->glGenTextures(3, frames[i].tex);
- f->glGenBuffers(3, frames[i].pbo);
- uint8_t uv_default = 127;
- for(int j=0; j<3; j++)
+ frames[i].conversion_config = conversion_config;
+ f->glGenTextures(conversion_config->planes, frames[i].tex);
+ f->glGenBuffers(conversion_config->planes, frames[i].pbo);
+ uint8_t uv_default[] = {0x7f, 0x7f};
+ for(int j=0; jplanes; j++)
{
f->glBindTexture(GL_TEXTURE_2D, frames[i].tex[j]);
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- f->glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, j > 0 ? &uv_default : nullptr);
+ f->glTexImage2D(GL_TEXTURE_2D, 0, conversion_config->plane_configs[j].internal_format, 1, 1, 0, conversion_config->plane_configs[j].format, GL_UNSIGNED_BYTE, j > 0 ? uv_default : nullptr);
}
frames[i].width = 0;
frames[i].height = 0;
}
f->glUseProgram(program);
- f->glUniform1i(f->glGetUniformLocation(program, "tex_y"), 0);
- f->glUniform1i(f->glGetUniformLocation(program, "tex_u"), 1);
- f->glUniform1i(f->glGetUniformLocation(program, "tex_v"), 2);
+
+ // bind only as many planes as we need
+ const char *plane_names[] = {"plane1", "plane2", "plane3"};
+ for(int i=0; iglUniform1i(f->glGetUniformLocation(program, plane_names[i]), i);
+ }
f->glGenVertexArrays(1, &vao);
f->glBindVertexArray(vao);
diff --git a/gui/src/settings.cpp b/gui/src/settings.cpp
index 559c4e4..90a5c03 100644
--- a/gui/src/settings.cpp
+++ b/gui/src/settings.cpp
@@ -94,6 +94,25 @@ unsigned int Settings::GetAudioBufferSizeRaw() const
return settings.value("settings/audio_buffer_size", 0).toUInt();
}
+static const QMap hw_decode_engine_values = {
+ { HW_DECODE_NONE, "none" },
+ { HW_DECODE_VAAPI, "vaapi" },
+ { HW_DECODE_VDPAU, "vdpau" }
+};
+
+static const HardwareDecodeEngine hw_decode_engine_default = HW_DECODE_NONE;
+
+HardwareDecodeEngine Settings::GetHardwareDecodeEngine() const
+{
+ auto v = settings.value("settings/hw_decode_engine", hw_decode_engine_values[hw_decode_engine_default]).toString();
+ return hw_decode_engine_values.key(v, hw_decode_engine_default);
+}
+
+void Settings::SetHardwareDecodeEngine(HardwareDecodeEngine engine)
+{
+ settings.setValue("settings/hw_decode_engine", hw_decode_engine_values[engine]);
+}
+
unsigned int Settings::GetAudioBufferSize() const
{
unsigned int v = GetAudioBufferSizeRaw();
diff --git a/gui/src/settingsdialog.cpp b/gui/src/settingsdialog.cpp
index 30dc00a..3b0892a 100644
--- a/gui/src/settingsdialog.cpp
+++ b/gui/src/settingsdialog.cpp
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
#include
@@ -146,6 +147,29 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
audio_buffer_size_edit->setPlaceholderText(tr("Default (%1)").arg(settings->GetAudioBufferSizeDefault()));
connect(audio_buffer_size_edit, &QLineEdit::textEdited, this, &SettingsDialog::AudioBufferSizeEdited);
+ // Decode Settings
+
+ auto decode_settings = new QGroupBox(tr("Decode Settings"));
+ left_layout->addWidget(decode_settings);
+
+ auto decode_settings_layout = new QFormLayout();
+ decode_settings->setLayout(decode_settings_layout);
+
+ hardware_decode_combo_box = new QComboBox(this);
+ static const QList> hardware_decode_engines = {
+ { HW_DECODE_NONE, "none"},
+ { HW_DECODE_VAAPI, "vaapi"}
+ };
+ auto current_hardware_decode_engine = settings->GetHardwareDecodeEngine();
+ for(const auto &p : hardware_decode_engines)
+ {
+ hardware_decode_combo_box->addItem(p.second, (int)p.first);
+ if(current_hardware_decode_engine == p.first)
+ hardware_decode_combo_box->setCurrentIndex(hardware_decode_combo_box->count() - 1);
+ }
+ connect(hardware_decode_combo_box, SIGNAL(currentIndexChanged(int)), this, SLOT(HardwareDecodeEngineSelected()));
+ decode_settings_layout->addRow(tr("Hardware decode method:"), hardware_decode_combo_box);
+
// Registered Consoles
auto registered_hosts_group_box = new QGroupBox(tr("Registered Consoles"));
@@ -243,6 +267,11 @@ void SettingsDialog::AudioBufferSizeEdited()
settings->SetAudioBufferSize(audio_buffer_size_edit->text().toUInt());
}
+void SettingsDialog::HardwareDecodeEngineSelected()
+{
+ settings->SetHardwareDecodeEngine((HardwareDecodeEngine)hardware_decode_combo_box->currentData().toInt());
+}
+
void SettingsDialog::UpdateBitratePlaceholder()
{
bitrate_edit->setPlaceholderText(tr("Automatic (%1)").arg(settings->GetVideoProfile().bitrate));
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index cccab98..bad6305 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -35,6 +35,7 @@
StreamSessionConnectInfo::StreamSessionConnectInfo(Settings *settings, QString host, QByteArray regist_key, QByteArray morning)
{
key_map = settings->GetControllerMappingForDecoding();
+ hw_decode_engine = settings->GetHardwareDecodeEngine();
log_level_mask = settings->GetLogLevelMask();
log_file = CreateLogFilename();
video_profile = settings->GetVideoProfile();
@@ -56,7 +57,7 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
gamepad(nullptr),
#endif
controller(nullptr),
- video_decoder(log.GetChiakiLog()),
+ video_decoder(connect_info.hw_decode_engine, log.GetChiakiLog()),
audio_output(nullptr),
audio_io(nullptr)
{
diff --git a/gui/src/videodecoder.cpp b/gui/src/videodecoder.cpp
index 4937142..ba59fe0 100644
--- a/gui/src/videodecoder.cpp
+++ b/gui/src/videodecoder.cpp
@@ -21,10 +21,13 @@
#include
-VideoDecoder::VideoDecoder(ChiakiLog *log) : log(log)
+VideoDecoder::VideoDecoder(HardwareDecodeEngine hw_decode_engine, ChiakiLog *log) : hw_decode_engine(hw_decode_engine), log(log)
{
+ enum AVHWDeviceType type;
+ hw_device_ctx = nullptr;
+
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
- avcodec_register_all();
+ avcodec_register_all();
#endif
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if(!codec)
@@ -34,6 +37,34 @@ VideoDecoder::VideoDecoder(ChiakiLog *log) : log(log)
if(!codec_context)
throw VideoDecoderException("Failed to alloc codec context");
+ if(hw_decode_engine)
+ {
+ if(!hardware_decode_engine_names.contains(hw_decode_engine))
+ throw VideoDecoderException("Unknown hardware decode engine!");
+
+ const char *hw_dec_eng = hardware_decode_engine_names[hw_decode_engine];
+ CHIAKI_LOGI(log, "Using hardware decode %s", hw_dec_eng);
+ type = av_hwdevice_find_type_by_name(hw_dec_eng);
+ if (type == AV_HWDEVICE_TYPE_NONE)
+ throw VideoDecoderException("Can't initialize vaapi");
+
+ for(int i = 0;; i++) {
+ const AVCodecHWConfig *config = avcodec_get_hw_config(codec, i);
+ if(!config)
+ throw VideoDecoderException("avcodec_get_hw_config failed");
+ if(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
+ config->device_type == type)
+ {
+ hw_pix_fmt = config->pix_fmt;
+ break;
+ }
+ }
+
+ if(av_hwdevice_ctx_create(&hw_device_ctx, type, NULL, NULL, 0) < 0)
+ throw VideoDecoderException("Failed to create hwdevice context");
+ codec_context->hw_device_ctx = av_buffer_ref(hw_device_ctx);
+ }
+
if(avcodec_open2(codec_context, codec, nullptr) < 0)
{
avcodec_free_context(&codec_context);
@@ -45,6 +76,10 @@ VideoDecoder::~VideoDecoder()
{
avcodec_close(codec_context);
avcodec_free_context(&codec_context);
+ if(hw_device_ctx)
+ {
+ av_buffer_unref(&hw_device_ctx);
+ }
}
void VideoDecoder::PushFrame(uint8_t *buf, size_t buf_size)
@@ -98,7 +133,8 @@ AVFrame *VideoDecoder::PullFrame()
// always try to pull as much as possible and return only the very last frame
AVFrame *frame_last = nullptr;
- AVFrame *frame = nullptr;
+ AVFrame *sw_frame = nullptr;
+ AVFrame *frame = nullptr;
while(true)
{
AVFrame *next_frame;
@@ -116,7 +152,11 @@ AVFrame *VideoDecoder::PullFrame()
frame_last = frame;
frame = next_frame;
int r = avcodec_receive_frame(codec_context, frame);
- if(r != 0)
+ if(r == 0)
+ {
+ frame = hw_decode_engine ? GetFromHardware(frame) : frame;
+ }
+ else
{
if(r != AVERROR(EAGAIN))
CHIAKI_LOGE(log, "Decoding with FFMPEG failed");
@@ -125,3 +165,28 @@ AVFrame *VideoDecoder::PullFrame()
}
}
}
+
+AVFrame *VideoDecoder::GetFromHardware(AVFrame *hw_frame)
+{
+ AVFrame *frame;
+ AVFrame *sw_frame;
+
+ sw_frame = av_frame_alloc();
+
+ int ret = av_hwframe_transfer_data(sw_frame, hw_frame, 0);
+
+ if(ret < 0)
+ {
+ CHIAKI_LOGE(log, "Failed to transfer frame from hardware");
+ }
+
+ av_frame_unref(hw_frame);
+
+ if(sw_frame->width <= 0)
+ {
+ av_frame_unref(sw_frame);
+ return nullptr;
+ }
+
+ return sw_frame;
+}
diff --git a/scripts/build-ffmpeg.sh b/scripts/build-ffmpeg.sh
index db73be4..af44a22 100755
--- a/scripts/build-ffmpeg.sh
+++ b/scripts/build-ffmpeg.sh
@@ -9,4 +9,4 @@ git clone https://git.ffmpeg.org/ffmpeg.git --depth 1 -b $TAG && cd ffmpeg || ex
./configure --disable-all --enable-avcodec --enable-decoder=h264 --prefix="$ROOT/ffmpeg-prefix" "$@" || exit 1
make -j4 || exit 1
-make install || exit 1
\ No newline at end of file
+make install || exit 1
From ef6952b8f3bb6a79513b7c4ae8ef4699268dda30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 25 Apr 2020 21:38:42 +0200
Subject: [PATCH 012/269] Fix Alpine Build after SDL2 2.0.12-r0 Update (#211)
---
.builds/alpine.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.builds/alpine.yml b/.builds/alpine.yml
index 88cb3ad..07066c9 100644
--- a/.builds/alpine.yml
+++ b/.builds/alpine.yml
@@ -14,6 +14,7 @@ packages:
- qt5-qtmultimedia-dev
- ffmpeg-dev
- sdl2-dev
+ - sdl2-static
tasks:
- build: |
From 509f312a6af0b032515e281b4fe8081084074e95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 26 Apr 2020 14:32:12 +0200
Subject: [PATCH 013/269] Fix Android Build in PRs (#213)
---
.travis.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8109c57..6ac595c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -126,10 +126,10 @@ matrix:
script:
- cd android
- ./gradlew assembleRelease bundleRelease
- - export DEPLOY_FILE_BASE="Chiaki-$CHIAKI_VERSION-Android"
- - export DEPLOY_FILE="$DEPLOY_FILE_BASE.a[pa][kb]"
- - cp app/build/outputs/apk/release/app-release.apk "../$DEPLOY_FILE_BASE.apk"
- - cp app/build/outputs/bundle/release/app-release.aab "../$DEPLOY_FILE_BASE.aab"
+ - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then export DEPLOY_FILE_BASE="Chiaki-$CHIAKI_VERSION-Android"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then export DEPLOY_FILE="$DEPLOY_FILE_BASE.a[pa][kb]"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then cp app/build/outputs/apk/release/app-release.apk "../$DEPLOY_FILE_BASE.apk"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then cp app/build/outputs/bundle/release/app-release.aab "../$DEPLOY_FILE_BASE.aab"; fi
- cd ..
- name: "Source Package"
From 4ac29127cca6ee3de954b4209e0e799904074ca1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 26 Apr 2020 15:53:41 +0200
Subject: [PATCH 014/269] Add OpenBSD Support (#212)
* Add OpenBSD Sourcehut Job
* Fix Code for OpenBSD
---
.builds/openbsd.yml | 25 +++++++++++++++++++++++++
lib/src/ecdh.c | 1 +
lib/src/takion.c | 11 +++++++----
3 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 .builds/openbsd.yml
diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml
new file mode 100644
index 0000000..b384168
--- /dev/null
+++ b/.builds/openbsd.yml
@@ -0,0 +1,25 @@
+
+image: openbsd/latest
+
+sources:
+ - https://github.com/thestr4ng3r/chiaki
+
+packages:
+ - cmake
+ - protobuf
+ - py3-protobuf
+ - opus
+ - qtbase
+ - qtsvg
+ - qtmultimedia
+ - ffmpeg
+ - sdl2
+
+tasks:
+ - build: |
+ cd chiaki
+ mkdir build && cd build
+ cmake -DCMAKE_PREFIX_PATH="/usr/local/lib;/usr/local/lib/qt5/cmake" ..
+ make -j4
+ test/chiaki-unit
+
diff --git a/lib/src/ecdh.c b/lib/src/ecdh.c
index 3ae49e1..ad07515 100644
--- a/lib/src/ecdh.c
+++ b/lib/src/ecdh.c
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
diff --git a/lib/src/takion.c b/lib/src/takion.c
index 64e4c69..89dbfda 100644
--- a/lib/src/takion.c
+++ b/lib/src/takion.c
@@ -249,19 +249,22 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, Chiaki
if(info->ip_dontfrag)
{
-#if __APPLE__
- CHIAKI_LOGW(takion->log, "Don't fragment is not supported on macOS, MTU values may be incorrect.");
-#else
#if defined(_WIN32)
const DWORD dontfragment_val = 1;
r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAGMENT, (const void *)&dontfragment_val, sizeof(dontfragment_val));
#elif defined(__FreeBSD__)
const int dontfrag_val = 1;
r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAG, (const void *)&dontfrag_val, sizeof(dontfrag_val));
-#else
+#elif defined(IP_PMTUDISC_DO)
const int mtu_discover_val = IP_PMTUDISC_DO;
r = setsockopt(takion->sock, IPPROTO_IP, IP_MTU_DISCOVER, (const void *)&mtu_discover_val, sizeof(mtu_discover_val));
+#else
+ // macOS and OpenBSD
+ CHIAKI_LOGW(takion->log, "Don't fragment is not supported on this platform, MTU values may be incorrect.");
+#define NO_DONTFRAG
#endif
+
+#ifndef NO_DONTFRAG
if(r < 0)
{
CHIAKI_LOGE(takion->log, "Takion failed to setsockopt IP_MTU_DISCOVER: %s", strerror(errno));
From 143566840f0c6c18c993e71bf89bfe35f737fa71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 26 Apr 2020 19:49:04 +0200
Subject: [PATCH 015/269] Version 1.2.0
---
CMakeLists.txt | 4 ++--
README.md | 5 +++--
android/app/build.gradle | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 90529e0..08a0e26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,8 +14,8 @@ option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" O
option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
set(CHIAKI_VERSION_MAJOR 1)
-set(CHIAKI_VERSION_MINOR 1)
-set(CHIAKI_VERSION_PATCH 3)
+set(CHIAKI_VERSION_MINOR 2)
+set(CHIAKI_VERSION_PATCH 0)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
diff --git a/README.md b/README.md
index 83de09e..3f60122 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
[](https://travis-ci.com/thestr4ng3r/chiaki) [](https://ci.appveyor.com/project/thestr4ng3r/chiaki) [](https://builds.sr.ht/~thestr4ng3r/chiaki?)
Chiaki is a Free and Open Source Software Client for PlayStation 4 Remote Play
-for Linux, Android, macOS, Windows and potentially even more platforms.
+for Linux, FreeBSD, OpenBSD, Android, macOS, Windows and potentially even more platforms.

@@ -19,8 +19,9 @@ registration and wakeup of the console, is supported.
The following features however are yet to be implemented:
* Congestion Control
* H264 Error Concealment (FEC and active error recovery however are implemented)
-* Touchpad support (Triggering the Touchpad Button is currently possible by pressing `T` on the keyboard)
+* Touchpad support (Triggering the Touchpad Button is currently possible from the keyboard though)
* Rumble
+* Accelerometer/Gyroscope
## Installing
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 1b0bb56..b5285c0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -24,7 +24,7 @@ android {
applicationId "com.metallic.chiaki"
minSdkVersion 21
targetSdkVersion 29
- versionCode 4
+ versionCode 5
versionName chiakiVersion
externalNativeBuild {
cmake {
From f3e91784eee9400814d2de074e56fcb69f04213d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 26 Apr 2020 21:54:31 +0200
Subject: [PATCH 016/269] Fix Travis Script
---
.travis.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 6ac595c..f739d74 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -126,10 +126,10 @@ matrix:
script:
- cd android
- ./gradlew assembleRelease bundleRelease
- - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then export DEPLOY_FILE_BASE="Chiaki-$CHIAKI_VERSION-Android"; fi
- - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then export DEPLOY_FILE="$DEPLOY_FILE_BASE.a[pa][kb]"; fi
- - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then cp app/build/outputs/apk/release/app-release.apk "../$DEPLOY_FILE_BASE.apk"; fi
- - if [ "$TRAVIS_PULL_REQUEST" = "false"]; then cp app/build/outputs/bundle/release/app-release.aab "../$DEPLOY_FILE_BASE.aab"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then export DEPLOY_FILE_BASE="Chiaki-$CHIAKI_VERSION-Android"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then export DEPLOY_FILE="$DEPLOY_FILE_BASE.a[pa][kb]"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp app/build/outputs/apk/release/app-release.apk "../$DEPLOY_FILE_BASE.apk"; fi
+ - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp app/build/outputs/bundle/release/app-release.aab "../$DEPLOY_FILE_BASE.aab"; fi
- cd ..
- name: "Source Package"
From 4e301b98857f98f1769816443bf43a813ad6bd85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Mon, 27 Apr 2020 18:16:32 +0200
Subject: [PATCH 017/269] Enable VAAPI in build-ffmpeg.sh (#215)
---
.travis.yml | 2 ++
scripts/build-ffmpeg.sh | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index f739d74..ef3245a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,7 @@ matrix:
- libgl1-mesa-dev
- nasm
- libsdl2-dev
+ - libva-dev
env:
- CMAKE_PREFIX_PATH="$TRAVIS_BUILD_DIR/ffmpeg-prefix;/opt/qt512"
- CMAKE_EXTRA_ARGS="-DCMAKE_INSTALL_PREFIX=/usr"
@@ -57,6 +58,7 @@ matrix:
- libgl1-mesa-dev
- nasm
- libudev-dev
+ - libva-dev
env:
- CMAKE_PREFIX_PATH="$TRAVIS_BUILD_DIR/ffmpeg-prefix;$TRAVIS_BUILD_DIR/sdl2-prefix;/opt/qt512"
- CMAKE_EXTRA_ARGS="-DCMAKE_INSTALL_PREFIX=/usr"
diff --git a/scripts/build-ffmpeg.sh b/scripts/build-ffmpeg.sh
index af44a22..dfce4bb 100755
--- a/scripts/build-ffmpeg.sh
+++ b/scripts/build-ffmpeg.sh
@@ -7,6 +7,6 @@ TAG=n4.2
git clone https://git.ffmpeg.org/ffmpeg.git --depth 1 -b $TAG && cd ffmpeg || exit 1
-./configure --disable-all --enable-avcodec --enable-decoder=h264 --prefix="$ROOT/ffmpeg-prefix" "$@" || exit 1
+./configure --disable-all --enable-avcodec --enable-decoder=h264 --enable-hwaccel=h264_vaapi --prefix="$ROOT/ffmpeg-prefix" "$@" || exit 1
make -j4 || exit 1
make install || exit 1
From f5fa8d6f7210fe31c6eba4f9fa641608e51d4fe4 Mon Sep 17 00:00:00 2001
From: DefaultUser
Date: Fri, 1 May 2020 21:27:51 +0200
Subject: [PATCH 018/269] Add CPack support (#210)
---
CMakeLists.txt | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08a0e26..e74e57c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,16 @@ set(CHIAKI_VERSION_MINOR 2)
set(CHIAKI_VERSION_PATCH 0)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
+set(CPACK_PACKAGE_NAME "chiaki")
+set(CPACK_PACKAGE_DESCRIPTION "Open Source PS4 remote play client")
+set(CPACK_PACKAGE_VERSION_MAJOR ${CHIAKI_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${CHIAKI_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${CHIAKI_VERSION_PATCH})
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
+set(CPACK_DEBIAN_PACKAGE_SECTION "games")
+include(CPack)
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_subdirectory(third-party)
@@ -45,4 +55,4 @@ endif()
if(CHIAKI_ENABLE_ANDROID)
add_subdirectory(android/app)
-endif()
\ No newline at end of file
+endif()
From 3009e1f9bb72f63677855e9e7ef420ff0d804d5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 3 May 2020 10:43:49 +0200
Subject: [PATCH 019/269] Add Issue Templates
---
.github/ISSUE_TEMPLATE/bug_report.md | 44 +++++++++++++++++++++++
.github/ISSUE_TEMPLATE/feature_request.md | 29 +++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..96380c0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,44 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+
+
+**Environment**
+ - OS/Distribution:
+ - Desktop Environment:
+ - Hardware:
+ - Exact Version or Commit Hash and Installation Method:
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Log Files**
+If your issue is about Registration or Streaming, you MUST attach a log file of a session that showed your issue here.
+Do not enable Verbose Logging unless explicitly told to.
+On desktop, you can see the directory that log files are written to in the Settings under "Log Directory".
+On Android, go into Settings -> Session Logs and export one from there.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..78e1101
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,29 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+
+
+**What platform does your feature request apply to?**
+Choose one or more: Desktop/Android/Both/...
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
+
From 41686e441cc5a542b5b9eff6f2ea5933430b9355 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 8 May 2020 15:03:41 +0200
Subject: [PATCH 020/269] Add Simple Wide Logo
---
assets/chiaki_wide_simple.svg | 147 ++++++++++++++++++++++++++++++++++
1 file changed, 147 insertions(+)
create mode 100644 assets/chiaki_wide_simple.svg
diff --git a/assets/chiaki_wide_simple.svg b/assets/chiaki_wide_simple.svg
new file mode 100644
index 0000000..4ce93ac
--- /dev/null
+++ b/assets/chiaki_wide_simple.svg
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+ 千秋
+
+
+
+
+
From dbd91246af5ca6aa57fcf5f57cd155fa0ed502e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 8 May 2020 15:14:00 +0200
Subject: [PATCH 021/269] Add Platform-Specific Docs
---
README.md | 2 ++
doc/platform-build.md | 8 ++++++++
2 files changed, 10 insertions(+)
create mode 100644 doc/platform-build.md
diff --git a/README.md b/README.md
index 3f60122..bf21566 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,8 @@ cmake ..
make
```
+For more detailed platform-specific instructions, see [doc/platform-build.md](doc/platform-build.md).
+
## Usage
If your PS4 is on your local network, is turned on or in standby mode and does not have Discovery explicitly disabled, Chiaki should find it.
diff --git a/doc/platform-build.md b/doc/platform-build.md
new file mode 100644
index 0000000..fe20008
--- /dev/null
+++ b/doc/platform-build.md
@@ -0,0 +1,8 @@
+
+# Platform-specific build instructions
+
+## Windows
+
+Windows support is reduced to the absolute minimum for maintainability.
+Official Windows builds are done on AppVeyor within MSYS2 using this script, which can also work as a template for building locally: [scripts/appveyor.sh](../scripts/appveyor.sh).
+Other methods of building may work, but will not be officially supported.
From 090c37fb0a8bc3eb26b269de12610db27b27e741 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 8 May 2020 15:03:58 +0200
Subject: [PATCH 022/269] Fix Surface for EGL (Fix #71)
---
gui/include/avopenglwidget.h | 2 ++
gui/src/avopenglwidget.cpp | 7 ++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/gui/include/avopenglwidget.h b/gui/include/avopenglwidget.h
index 312f16c..d9ddc0d 100644
--- a/gui/include/avopenglwidget.h
+++ b/gui/include/avopenglwidget.h
@@ -32,6 +32,7 @@ extern "C"
class VideoDecoder;
class AVOpenGLFrameUploader;
+class QOffscreenSurface;
struct PlaneConfig
{
@@ -76,6 +77,7 @@ class AVOpenGLWidget: public QOpenGLWidget
AVOpenGLFrame frames[2];
int frame_fg;
QMutex frames_mutex;
+ QOffscreenSurface *frame_uploader_surface;
QOpenGLContext *frame_uploader_context;
AVOpenGLFrameUploader *frame_uploader;
QThread *frame_uploader_thread;
diff --git a/gui/src/avopenglwidget.cpp b/gui/src/avopenglwidget.cpp
index 11d4b09..21b51f3 100644
--- a/gui/src/avopenglwidget.cpp
+++ b/gui/src/avopenglwidget.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
#include
@@ -177,6 +178,7 @@ AVOpenGLWidget::~AVOpenGLWidget()
}
delete frame_uploader;
delete frame_uploader_context;
+ delete frame_uploader_surface;
}
void AVOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
@@ -363,7 +365,10 @@ void AVOpenGLWidget::initializeGL()
return;
}
- frame_uploader = new AVOpenGLFrameUploader(decoder, this, frame_uploader_context, context()->surface());
+ frame_uploader_surface = new QOffscreenSurface();
+ frame_uploader_surface->setFormat(context()->format());
+ frame_uploader_surface->create();
+ frame_uploader = new AVOpenGLFrameUploader(decoder, this, frame_uploader_context, frame_uploader_surface);
frame_fg = 0;
frame_uploader_thread = new QThread(this);
From 6d02714d0e348c1f08b3af18c41351e50016176f Mon Sep 17 00:00:00 2001
From: Tommy He
Date: Sun, 10 May 2020 02:45:18 +0800
Subject: [PATCH 023/269] More details on build dependencies and vaapi in
README and docs.
---
README.md | 5 ++---
doc/platform-build.md | 22 ++++++++++++++++++++++
gui/chiaki.desktop | 2 +-
3 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index bf21566..c4a2df8 100644
--- a/README.md
+++ b/README.md
@@ -40,9 +40,8 @@ You can download them [here](https://github.com/thestr4ng3r/chiaki/releases).
### Building from Source
-Dependencies are CMake, Qt 5 with QtMultimedia, QtOpenGL and QtSvg, FFMPEG (libavcodec with H264 is enough), libopus, OpenSSL 1.1,
-protoc and the protobuf Python library (only used during compilation for Nanopb).
-Then, Chiaki builds just like any other CMake project:
+Dependencies are CMake, Qt 5 with QtMultimedia, QtOpenGL and QtSvg, FFMPEG (libavcodec with H264 is enough), libopus, OpenSSL 1.1, SDL 2,
+protoc and the protobuf Python library (only used during compilation for Nanopb). Then, Chiaki builds just like any other CMake project:
```
git submodule update --init
mkdir build && cd build
diff --git a/doc/platform-build.md b/doc/platform-build.md
index fe20008..133e3c5 100644
--- a/doc/platform-build.md
+++ b/doc/platform-build.md
@@ -1,6 +1,28 @@
# Platform-specific build instructions
+## Fedora
+
+On Fedora, build dependencies can be installed via:
+
+```
+sudo dnf install cmake make qt5-qtmultimedia-devel qt5-qtsvg-devel qt5-qtbase-gui ffmpeg-devel opus-devel openssl-devel python3-protobuf protobuf-c protobuf-devel qt5-rpm-macros SDL2-devel
+```
+
+Then, Chiaki builds just like any other CMake project:
+```
+git submodule update --init
+mkdir build && cd build
+cmake ..
+make
+```
+
+In order to utilize hardware decoding, necessary VA-API component needs to be installed separately depending on your GPU. For example on Fedora:
+
+* **Intel**: `libva-intel-driver`(majority laptop and desktop) OR `libva-intel-hybrid-driver`(most netbook with Atom processor)
+* **AMD**: Already part of default installation
+* **Nvidia**: `libva-vdpau-driver`
+
## Windows
Windows support is reduced to the absolute minimum for maintainability.
diff --git a/gui/chiaki.desktop b/gui/chiaki.desktop
index 6ee0326..80ee51b 100644
--- a/gui/chiaki.desktop
+++ b/gui/chiaki.desktop
@@ -4,4 +4,4 @@ Name=Chiaki
Comment=PlayStation 4 Remote Play Client
Exec=chiaki
Icon=chiaki
-Categories=Game;
\ No newline at end of file
+Categories=Game;
From f35311bf61fa3cb0ce12549e29ac92eb9f30ade1 Mon Sep 17 00:00:00 2001
From: H0neyBadger
Date: Fri, 15 May 2020 11:06:54 +0200
Subject: [PATCH 024/269] Add Nintendo Switch chiaki-lib support (#233)
---
CMakeLists.txt | 27 +++++
cmake/switch.cmake | 99 ++++++++++++++++
lib/CMakeLists.txt | 14 ++-
lib/include/chiaki/ecdh.h | 16 +++
lib/include/chiaki/stoppipe.h | 11 ++
lib/src/audio.c | 3 +
lib/src/discovery.c | 6 +-
lib/src/ecdh.c | 134 +++++++++++++++++++++-
lib/src/gkcrypt.c | 105 ++++++++++++++++-
lib/src/random.c | 37 +++++-
lib/src/regist.c | 2 +-
lib/src/rpcrypt.c | 95 +++++++++++++++
lib/src/stoppipe.c | 54 ++++++++-
lib/src/takion.c | 7 +-
lib/src/thread.c | 21 ++++
scripts/switch/Dockerfile | 81 +++++++++++++
scripts/switch/build.sh | 42 +++++++
scripts/switch/devkit_repo | 6 +
scripts/switch/fake_ctest.nintendo.net.py | 31 +++++
19 files changed, 771 insertions(+), 20 deletions(-)
create mode 100644 cmake/switch.cmake
create mode 100644 scripts/switch/Dockerfile
create mode 100755 scripts/switch/build.sh
create mode 100644 scripts/switch/devkit_repo
create mode 100644 scripts/switch/fake_ctest.nintendo.net.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e74e57c..9cffd0d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,9 @@ option(CHIAKI_ENABLE_TESTS "Enable tests for Chiaki" ON)
option(CHIAKI_ENABLE_CLI "Enable CLI for Chiaki" OFF)
option(CHIAKI_ENABLE_GUI "Enable Qt GUI" ON)
option(CHIAKI_ENABLE_ANDROID "Enable Android (Use only as part of the Gradle Project)" OFF)
+option(CHIAKI_ENABLE_SWITCH "Enable Nintendo Switch (Requires devKitPro libnx)" OFF)
option(CHIAKI_LIB_ENABLE_OPUS "Use Opus as part of Chiaki Lib" ON)
+option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
option(CHIAKI_GUI_ENABLE_QT_GAMEPAD "Use QtGamepad for Input" OFF)
option(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER "Use SDL Gamecontroller for Input" ON)
@@ -30,6 +32,22 @@ include(CPack)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+# configure nintendo switch toolchain
+if(CHIAKI_ENABLE_SWITCH AND CHIAKI_ENABLE_SWITCH_LINUX)
+ # CHIAKI_ENABLE_SWITCH_LINUX is a special testing version
+ # the aim is to troubleshoot nitendo switch chiaki verison
+ # from a x86 linux os
+ add_definitions(-DCHIAKI_ENABLE_SWITCH_LINUX)
+ set(CMAKE_BUILD_TYPE Debug)
+elseif(CHIAKI_ENABLE_SWITCH)
+ add_definitions(-D__SWITCH__)
+ # load switch.cmake toolchain form ./cmake folder
+ include(switch)
+ # TODO check if android ... or other versions are enabled
+ # force mbedtls as crypto lib
+ set(CHIAKI_LIB_ENABLE_MBEDTLS ON)
+endif()
+
add_subdirectory(third-party)
add_definitions(-DCHIAKI_VERSION_MAJOR=${CHIAKI_VERSION_MAJOR} -DCHIAKI_VERSION_MINOR=${CHIAKI_VERSION_MINOR} -DCHIAKI_VERSION_PATCH=${CHIAKI_VERSION_PATCH} -DCHIAKI_VERSION=\"${CHIAKI_VERSION}\")
@@ -38,6 +56,10 @@ if(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT)
include(OpenSSLExternalProject)
endif()
+if(CHIAKI_LIB_ENABLE_MBEDTLS)
+ add_definitions(-DCHIAKI_LIB_ENABLE_MBEDTLS)
+endif()
+
add_subdirectory(lib)
if(CHIAKI_ENABLE_CLI)
@@ -56,3 +78,8 @@ endif()
if(CHIAKI_ENABLE_ANDROID)
add_subdirectory(android/app)
endif()
+
+if(CHIAKI_ENABLE_SWITCH)
+ #TODO
+ #add_subdirectory(switch)
+endif()
diff --git a/cmake/switch.cmake b/cmake/switch.cmake
new file mode 100644
index 0000000..5409422
--- /dev/null
+++ b/cmake/switch.cmake
@@ -0,0 +1,99 @@
+# https://github.com/nxengine/nxengine-evo
+
+# Find DEVKITPRO
+if(NOT DEFINED ENV{DEVKITPRO})
+ message(FATAL_ERROR "You must have defined DEVKITPRO before calling cmake.")
+endif()
+
+set(DEVKITPRO $ENV{DEVKITPRO})
+
+function(switchvar cmakevar var default)
+ # read or set env var
+ if(NOT DEFINED "ENV{$var}")
+ set("ENV{$var}" default)
+ endif()
+ set("$cmakevar" "ENV{$var}")
+endfunction()
+
+# allow gcc -g to use
+# aarch64-none-elf-addr2line -e build_switch/switch/chiaki -f -p -C -a 0xCCB5C
+set(CMAKE_BUILD_TYPE Debug)
+
+set( TOOL_OS_SUFFIX "" )
+if( CMAKE_HOST_WIN32 )
+ set( TOOL_OS_SUFFIX ".exe" )
+endif()
+
+set(CMAKE_SYSTEM_PROCESSOR "armv8-a")
+set(CMAKE_C_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+set(CMAKE_CXX_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+set(CMAKE_ASM_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-as${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+set(CMAKE_STRIP "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip")
+set(CMAKE_AR "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive")
+set(CMAKE_LINKER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker")
+set(CMAKE_NM "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm")
+set(CMAKE_OBJCOPY "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy")
+set(CMAKE_OBJDUMP "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump")
+set(CMAKE_RANLIB "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib")
+
+# custom /opt/devkitpro/switchvars.sh
+switchvar(PORTLIBS_PREFIX PORTLIBS_PREFIX "${DEVKITPRO}/portlibs/switch")
+switchvar(ARCH ARCH "-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec")
+switchvar(CMAKE_C_FLAGS CFLAGS "${ARCH} -O2 -ffunction-sections -fdata-sections")
+switchvar(CMAKE_CXX_FLAGS CXXFLAGS "${CMAKE_C_FLAGS}")
+switchvar(CMAKE_CPP_FLAGS CPPFLAGS "-D__SWITCH__ -I${PORTLIBS_PREFIX}/include -isystem${DEVKITPRO}/libnx/include")
+switchvar(CMAKE_LD_FLAGS LDFLAGS "${ARCH} -L${PORTLIBS_PREFIX}/lib -L${DEVKITPRO}/libnx/lib")
+switchvar(LIBS LIBS "-lnx")
+
+# switchvar(CMAKE_CXX_FLAGS CXXFLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+include_directories(${DEVKITPRO}/libnx/include ${PORTLIBS_PREFIX}/include)
+
+# where is the target environment
+set(CMAKE_FIND_ROOT_PATH
+ ${DEVKITPRO}/devkitA64
+ ${DEVKITPRO}/libnx
+ ${DEVKITPRO}/portlibs/switch)
+
+# only search for libraries and includes in toolchain
+set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+
+find_program(ELF2NRO elf2nro ${DEVKITPRO}/tools/bin)
+if (ELF2NRO)
+ message(STATUS "elf2nro: ${ELF2NRO} - found")
+else ()
+ message(WARNING "elf2nro - not found")
+endif ()
+
+find_program(NACPTOOL nacptool ${DEVKITPRO}/tools/bin)
+if (NACPTOOL)
+ message(STATUS "nacptool: ${NACPTOOL} - found")
+else ()
+ message(WARNING "nacptool - not found")
+endif ()
+
+function(__add_nacp target APP_TITLE APP_AUTHOR APP_VERSION)
+ set(__NACP_COMMAND ${NACPTOOL} --create ${APP_TITLE} ${APP_AUTHOR} ${APP_VERSION} ${CMAKE_CURRENT_BINARY_DIR}/${target})
+
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}
+ COMMAND ${__NACP_COMMAND}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
+ VERBATIM
+ )
+endfunction()
+
+function(add_nro_target target title author version icon romfs)
+ get_filename_component(target_we ${target} NAME_WE)
+ if (NOT ${target_we}.nacp)
+ __add_nacp(${target_we}.nacp ${title} ${author} ${version})
+ endif ()
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro
+ COMMAND ${ELF2NRO} $ ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro --icon=${icon} --nacp=${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nacp
+ # --romfsdir=${romfs}
+ DEPENDS ${target} ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nacp
+ VERBATIM
+ )
+ add_custom_target(${target_we}_nro ALL SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${target_we}.nro)
+endfunction()
+
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index cfb2c04..c002ab8 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -99,16 +99,26 @@ target_include_directories(chiaki-lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/includ
find_package(Threads REQUIRED)
target_link_libraries(chiaki-lib Threads::Threads)
-if(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT)
+if(CHIAKI_LIB_ENABLE_MBEDTLS)
+ # provided by mbedtls-static (mbedtls-devel)
+ # find_package(mbedcrypto REQUIRED)
+ target_link_libraries(chiaki-lib mbedtls mbedx509 mbedcrypto)
+elseif(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT)
target_link_libraries(chiaki-lib OpenSSL_Crypto)
else()
+ # default
find_package(OpenSSL REQUIRED)
target_link_libraries(chiaki-lib OpenSSL::Crypto)
endif()
+if(CHIAKI_ENABLE_SWITCH AND NOT CHIAKI_ENABLE_SWITCH_LINUX)
+ # to provides csrngGetRandomBytes
+ target_link_libraries(chiaki-lib nx)
+endif()
+
target_link_libraries(chiaki-lib protobuf-nanopb-static)
target_link_libraries(chiaki-lib jerasure)
if(CHIAKI_LIB_ENABLE_OPUS)
target_link_libraries(chiaki-lib ${Opus_LIBRARIES})
-endif()
\ No newline at end of file
+endif()
diff --git a/lib/include/chiaki/ecdh.h b/lib/include/chiaki/ecdh.h
index 440fcb8..fed92c4 100644
--- a/lib/include/chiaki/ecdh.h
+++ b/lib/include/chiaki/ecdh.h
@@ -27,12 +27,28 @@
extern "C" {
#endif
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#include "mbedtls/ecdh.h"
+#include "mbedtls/ctr_drbg.h"
+#endif
+
+
#define CHIAKI_ECDH_SECRET_SIZE 32
typedef struct chiaki_ecdh_t
{
+// the following lines may lead to memory corruption
+// __SWITCH__ or CHIAKI_LIB_ENABLE_MBEDTLS must be defined
+// globally (whole project)
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ // mbedtls ecdh context
+ mbedtls_ecdh_context ctx;
+ // deterministic random bit generator
+ mbedtls_ctr_drbg_context drbg;
+#else
struct ec_group_st *group;
struct ec_key_st *key_local;
+#endif
} ChiakiECDH;
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh);
diff --git a/lib/include/chiaki/stoppipe.h b/lib/include/chiaki/stoppipe.h
index 229995e..1a1ab71 100644
--- a/lib/include/chiaki/stoppipe.h
+++ b/lib/include/chiaki/stoppipe.h
@@ -26,6 +26,8 @@
#ifdef _WIN32
#include
+#else
+#include
#endif
#ifdef __cplusplus
@@ -36,6 +38,15 @@ typedef struct chiaki_stop_pipe_t
{
#ifdef _WIN32
WSAEVENT event;
+#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ // due to a lack pipe/event/socketpair
+ // on switch env, we use a physical socket
+ // to send/trigger the cancel signal
+ struct sockaddr_in addr;
+ // local stop socket file descriptor
+ // this fd is audited by 'select' as
+ // fd_set *readfds
+ int fd;
#else
int fds[2];
#endif
diff --git a/lib/src/audio.c b/lib/src/audio.c
index c7a3512..2bd4168 100644
--- a/lib/src/audio.c
+++ b/lib/src/audio.c
@@ -23,6 +23,9 @@
#include
#endif
+#ifdef __SWITCH__
+#include
+#endif
void chiaki_audio_header_load(ChiakiAudioHeader *audio_header, const uint8_t *buf)
{
diff --git a/lib/src/discovery.c b/lib/src/discovery.c
index e2d5205..e069aaa 100644
--- a/lib/src/discovery.c
+++ b/lib/src/discovery.c
@@ -127,7 +127,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery,
discovery->log = log;
- discovery->socket = socket(AF_INET, SOCK_DGRAM, 0);
+ discovery->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(CHIAKI_SOCKET_IS_INVALID(discovery->socket))
{
CHIAKI_LOGE(discovery->log, "Discovery failed to create socket");
@@ -138,9 +138,13 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery,
discovery->local_addr.sa_family = family;
if(family == AF_INET6)
{
+#ifndef __SWITCH__
struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
+#endif
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&discovery->local_addr;
+#ifndef __SWITCH__
addr->sin6_addr = anyaddr;
+#endif
addr->sin6_port = htons(0);
}
else // AF_INET
diff --git a/lib/src/ecdh.c b/lib/src/ecdh.c
index ad07515..056d69d 100644
--- a/lib/src/ecdh.c
+++ b/lib/src/ecdh.c
@@ -19,23 +19,58 @@
#include
#include
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#include "mbedtls/entropy.h"
+#include "mbedtls/md.h"
+#else
#include
#include
#include
#include
#include
+#endif
+// memset
#include
#include
-
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh)
{
memset(ecdh, 0, sizeof(ChiakiECDH));
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#define CHECK(err) if((err) != 0) { \
+ chiaki_ecdh_fini(ecdh); \
+ return CHIAKI_ERR_UNKNOWN; }
+ // mbedtls ecdh example:
+ // https://github.com/ARMmbed/mbedtls/blob/development/programs/pkey/ecdh_curve25519.c
+ const char pers[] = "ecdh";
+ mbedtls_entropy_context entropy;
+ //init RNG Seed context
+ mbedtls_entropy_init(&entropy);
+ // init local key
+ //mbedtls_ecp_keypair_init(&ecdh->key_local);
+ mbedtls_ecdh_init(&ecdh->ctx);
+ // init ecdh group
+ // keep rng context in ecdh for later reuse
+ mbedtls_ctr_drbg_init(&ecdh->drbg);
+ // build RNG seed
+ CHECK(mbedtls_ctr_drbg_seed(&ecdh->drbg, mbedtls_entropy_func, &entropy,
+ (const unsigned char *) pers, sizeof pers));
+
+ // build MBEDTLS_ECP_DP_SECP256K1 group
+ CHECK(mbedtls_ecp_group_load(&ecdh->ctx.grp, MBEDTLS_ECP_DP_SECP256K1));
+ // build key
+ CHECK(mbedtls_ecdh_gen_public(&ecdh->ctx.grp, &ecdh->ctx.d,
+ &ecdh->ctx.Q, mbedtls_ctr_drbg_random, &ecdh->drbg));
+
+ // relese entropy ptr
+ mbedtls_entropy_free(&entropy);
+#undef CHECK
+
+#else
#define CHECK(a) if(!(a)) { chiaki_ecdh_fini(ecdh); return CHIAKI_ERR_UNKNOWN; }
-
CHECK(ecdh->group = EC_GROUP_new_by_curve_name(NID_secp256k1));
CHECK(ecdh->key_local = EC_KEY_new());
@@ -43,19 +78,53 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh)
CHECK(EC_KEY_generate_key(ecdh->key_local));
#undef CHECK
+#endif
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh)
{
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ mbedtls_ecdh_free(&ecdh->ctx);
+ mbedtls_ctr_drbg_free(&ecdh->drbg);
+#else
EC_KEY_free(ecdh->key_local);
EC_GROUP_free(ecdh->group);
+#endif
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_set_local_key(ChiakiECDH *ecdh, const uint8_t *private_key, size_t private_key_size, const uint8_t *public_key, size_t public_key_size)
{
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ //https://tls.mbed.org/discussions/generic/publickey-binary-data-in-der
+ // Load keys from buffers (i.e: config file)
+ // TODO test
+
+ // public
+ int r = 0;
+ r = mbedtls_ecp_point_read_binary(&ecdh->ctx.grp, &ecdh->ctx.Q,
+ public_key, public_key_size);
+ if(r != 0 ){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ // secret
+ r = mbedtls_mpi_read_binary(&ecdh->ctx.d, private_key, private_key_size);
+ if(r != 0 ){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ // regen key
+ r = mbedtls_ecdh_gen_public(&ecdh->ctx.grp, &ecdh->ctx.d,
+ &ecdh->ctx.Q, mbedtls_ctr_drbg_random, &ecdh->drbg);
+ if(r != 0 ){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ return CHIAKI_ERR_SUCCESS;
+#else
ChiakiErrorCode err = CHIAKI_ERR_SUCCESS;
BIGNUM *private_key_bn = BN_bin2bn(private_key, (int)private_key_size, NULL);
@@ -92,10 +161,40 @@ error_pub:
error_priv:
BN_free(private_key_bn);
return err;
+#endif
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, uint8_t *key_out, size_t *key_out_size, const uint8_t *handshake_key, uint8_t *sig_out, size_t *sig_out_size)
{
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ mbedtls_md_context_t ctx;
+ mbedtls_md_init(&ctx);
+
+#define GOTO_ERROR(err) do { \
+ if((err) !=0){ \
+ goto error; \
+ }} while(0)
+ // extract pub key to build dh shared secret
+ // this key is sent to the remote server
+ GOTO_ERROR(mbedtls_ecp_point_write_binary( &ecdh->ctx.grp, &ecdh->ctx.Q,
+ MBEDTLS_ECP_PF_UNCOMPRESSED, key_out_size, key_out, *key_out_size ));
+
+ // https://tls.mbed.org/module-level-design-hashing
+ // HMAC
+ GOTO_ERROR(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) , 1));
+ GOTO_ERROR(mbedtls_md_hmac_starts(&ctx, handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE));
+ GOTO_ERROR(mbedtls_md_hmac_update(&ctx, key_out, *key_out_size));
+ GOTO_ERROR(mbedtls_md_hmac_finish(&ctx, sig_out));
+ // SHA256 = 8*32
+ *sig_out_size = 32;
+#undef GOTO_ERROR
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_SUCCESS;
+
+error:
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+#else
const EC_POINT *point = EC_KEY_get0_public_key(ecdh->key_local);
if(!point)
return CHIAKI_ERR_UNKNOWN;
@@ -106,12 +205,40 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, ui
if(!HMAC(EVP_sha256(), handshake_key, CHIAKI_HANDSHAKE_KEY_SIZE, key_out, *key_out_size, sig_out, (unsigned int *)sig_out_size))
return CHIAKI_ERR_UNKNOWN;
-
return CHIAKI_ERR_SUCCESS;
+
+#endif
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_derive_secret(ChiakiECDH *ecdh, uint8_t *secret_out, const uint8_t *remote_key, size_t remote_key_size, const uint8_t *handshake_key, const uint8_t *remote_sig, size_t remote_sig_size)
{
+ //compute DH shared key
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ // https://github.com/ARMmbed/mbedtls/blob/development/programs/pkey/ecdh_curve25519.c#L151
+#define GOTO_ERROR(err) do { \
+ if((err) !=0){ \
+ goto error;} \
+ } while(0)
+
+ GOTO_ERROR(mbedtls_mpi_lset(&ecdh->ctx.Qp.Z, 1));
+ // load Qp point form remote PK
+ GOTO_ERROR(mbedtls_ecp_point_read_binary(&ecdh->ctx.grp,
+ &ecdh->ctx.Qp, remote_key, remote_key_size));
+
+ // build shared secret (diffie-hellman)
+ GOTO_ERROR(mbedtls_ecdh_compute_shared(&ecdh->ctx.grp,
+ &ecdh->ctx.z, &ecdh->ctx.Qp, &ecdh->ctx.d,
+ mbedtls_ctr_drbg_random, &ecdh->drbg));
+
+ // export shared secret to data buffer
+ GOTO_ERROR(mbedtls_mpi_write_binary(&ecdh->ctx.z,
+ secret_out, CHIAKI_ECDH_SECRET_SIZE));
+
+ return CHIAKI_ERR_SUCCESS;
+error:
+ return CHIAKI_ERR_UNKNOWN;
+
+#else
EC_POINT *remote_public_key = EC_POINT_new(ecdh->group);
if(!remote_public_key)
return CHIAKI_ERR_UNKNOWN;
@@ -130,4 +257,5 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_derive_secret(ChiakiECDH *ecdh, uint8_
return CHIAKI_ERR_UNKNOWN;
return CHIAKI_ERR_SUCCESS;
+#endif
}
diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c
index f8be2c1..50678ea 100644
--- a/lib/src/gkcrypt.c
+++ b/lib/src/gkcrypt.c
@@ -21,9 +21,16 @@
#include
#include
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#include "mbedtls/aes.h"
+#include "mbedtls/md.h"
+#include "mbedtls/gcm.h"
+#include "mbedtls/sha256.h"
+#else
#include
#include
#include
+#endif
#include "utils.h"
@@ -69,7 +76,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_init(ChiakiGKCrypt *gkcrypt, Chiaki
{
gkcrypt->key_buf = NULL;
}
-
err = gkcrypt_gen_key_iv(gkcrypt, index, handshake_key, ecdh_secret);
if(err != CHIAKI_ERR_SUCCESS)
{
@@ -132,9 +138,37 @@ static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index,
uint8_t hmac[CHIAKI_GKCRYPT_BLOCK_SIZE*2];
size_t hmac_size = sizeof(hmac);
+ #if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ mbedtls_md_context_t ctx;
+ mbedtls_md_init(&ctx);
+
+ if(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) , 1) != 0){
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ if(mbedtls_md_hmac_starts(&ctx, ecdh_secret, CHIAKI_ECDH_SECRET_SIZE) != 0){
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ if(mbedtls_md_hmac_update(&ctx, data, sizeof(data)) != 0){
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ if(mbedtls_md_hmac_finish(&ctx, hmac) != 0){
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ mbedtls_md_free(&ctx);
+
+ #else
if(!HMAC(EVP_sha256(), ecdh_secret, CHIAKI_ECDH_SECRET_SIZE, data, sizeof(data), hmac, (unsigned int *)&hmac_size))
return CHIAKI_ERR_UNKNOWN;
+ #endif
assert(hmac_size == sizeof(hmac));
memcpy(gkcrypt->key_base, hmac, CHIAKI_GKCRYPT_BLOCK_SIZE);
@@ -164,7 +198,14 @@ CHIAKI_EXPORT void chiaki_gkcrypt_gen_gmac_key(uint64_t index, const uint8_t *ke
memcpy(data, key_base, 0x10);
counter_add(data + 0x10, iv, index * CHIAKI_GKCRYPT_GMAC_KEY_REFRESH_IV_OFFSET);
uint8_t md[0x20];
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ // last param
+ // is224 Determines which function to use.
+ // This must be either 0 for SHA-256, or 1 for SHA-224.
+ mbedtls_sha256_ret(data, sizeof(data), md, 0);
+#else
SHA256(data, 0x20, md);
+#endif
xor_bytes(md, md + 0x10, 0x10);
memcpy(key_out, md, CHIAKI_GKCRYPT_BLOCK_SIZE);
}
@@ -189,6 +230,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry
assert(key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
assert(buf_size % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ // build mbedtls aes context
+ mbedtls_aes_context ctx;
+ mbedtls_aes_init(&ctx);
+
+ if(mbedtls_aes_setkey_enc(&ctx, gkcrypt->key_base, 128) != 0){
+ mbedtls_aes_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+#else
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if(!ctx)
return CHIAKI_ERR_UNKNOWN;
@@ -204,12 +256,23 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry
EVP_CIPHER_CTX_free(ctx);
return CHIAKI_ERR_UNKNOWN;
}
-
+#endif
int counter_offset = (int)(key_pos / CHIAKI_GKCRYPT_BLOCK_SIZE);
for(uint8_t *cur = buf, *end = buf + buf_size; cur < end; cur += CHIAKI_GKCRYPT_BLOCK_SIZE)
counter_add(cur, gkcrypt->iv, counter_offset++);
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ for(int i=0; ilog, "GKCrypt %d thread starting", (int)gkcrypt->index);
ChiakiErrorCode err = chiaki_mutex_lock(&gkcrypt->key_buf_mutex);
assert(err == CHIAKI_ERR_SUCCESS);
-
while(1)
{
err = chiaki_cond_wait_pred(&gkcrypt->key_buf_cond, &gkcrypt->key_buf_mutex, key_buf_mutex_pred, gkcrypt);
+
if(gkcrypt->key_buf_thread_stop || err != CHIAKI_ERR_SUCCESS)
break;
@@ -438,7 +534,6 @@ static void *gkcrypt_thread_func(void *user)
gkcrypt->key_buf_key_pos_min += KEY_BUF_CHUNK_SIZE;
gkcrypt->key_buf_populated -= KEY_BUF_CHUNK_SIZE;
}
-
err = gkcrypt_generate_next_chunk(gkcrypt);
if(err != CHIAKI_ERR_SUCCESS)
break;
diff --git a/lib/src/random.c b/lib/src/random.c
index beaf373..d28cb7d 100644
--- a/lib/src/random.c
+++ b/lib/src/random.c
@@ -17,17 +17,52 @@
#include
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+//#include
+#include
+#include
+#else
#include
+#endif
CHIAKI_EXPORT ChiakiErrorCode chiaki_random_bytes_crypt(uint8_t *buf, size_t buf_size)
{
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ // mbedtls_havege_state hs;
+ // mbedtls_havege_init(&hs);
+ // int r = mbedtls_havege_random( &hs, buf, sizeof( buf ) );
+ // if(r != 0 )
+ // return CHIAKI_ERR_UNKNOWN;
+ // return CHIAKI_ERR_SUCCESS;
+
+ // https://github.com/ARMmbed/mbedtls/blob/development/programs/random/gen_random_ctr_drbg.c
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_context entropy;
+
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+ mbedtls_entropy_init(&entropy);
+
+ mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
+ if(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) "RANDOM_GEN", 10 ) != 0 ){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+ if(mbedtls_ctr_drbg_random(&ctr_drbg, buf, buf_size) != 0){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+
+ mbedtls_ctr_drbg_free(&ctr_drbg);
+ mbedtls_entropy_free(&entropy);
+ return CHIAKI_ERR_SUCCESS;
+
+#else
int r = RAND_bytes(buf, (int)buf_size);
if(!r)
return CHIAKI_ERR_UNKNOWN;
return CHIAKI_ERR_SUCCESS;
+#endif
}
CHIAKI_EXPORT uint32_t chiaki_random_32()
{
return rand() % UINT32_MAX;
-}
\ No newline at end of file
+}
diff --git a/lib/src/regist.c b/lib/src/regist.c
index 947b713..a50504e 100644
--- a/lib/src/regist.c
+++ b/lib/src/regist.c
@@ -404,7 +404,7 @@ static chiaki_socket_t regist_search_connect(ChiakiRegist *regist, struct addrin
set_port(send_addr, htons(REGIST_PORT));
- sock = socket(ai->ai_family, SOCK_DGRAM, 0);
+ sock = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
if(CHIAKI_SOCKET_IS_INVALID(sock))
{
CHIAKI_LOGE(regist->log, "Regist failed to create socket for search");
diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c
index 708947f..f2982b6 100644
--- a/lib/src/rpcrypt.c
+++ b/lib/src/rpcrypt.c
@@ -17,12 +17,18 @@
#include
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#include "mbedtls/aes.h"
+#include "mbedtls/md.h"
+#else
#include
#include
+#endif
#include
#include
+
static const uint8_t echo_b[] = { 0xe1, 0xec, 0x9c, 0x3a, 0xdd, 0xbd, 0x08, 0x85, 0xfc, 0x0e, 0x1d, 0x78, 0x90, 0x32, 0xc0, 0x04 };
CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning)
@@ -77,6 +83,7 @@ CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint
rpcrypt->bright[3] ^= (uint8_t)((pin >> 0x00) & 0xff);
}
+#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter)
{
uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
@@ -92,6 +99,93 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt,
buf[CHIAKI_RPCRYPT_KEY_SIZE + 6] = (uint8_t)((counter >> 0x08) & 0xff);
buf[CHIAKI_RPCRYPT_KEY_SIZE + 7] = (uint8_t)((counter >> 0x00) & 0xff);
+ uint8_t hmac[CHIAKI_RPCRYPT_KEY_SIZE];
+ unsigned int hmac_len = 0;
+
+
+ mbedtls_md_context_t ctx;
+ mbedtls_md_type_t type = MBEDTLS_MD_SHA256;
+
+ mbedtls_md_init(&ctx);
+
+#define GOTO_ERROR(err) do { \
+ if((err) !=0){ \
+ goto error;} \
+ } while(0)
+ // https://tls.mbed.org/module-level-design-hashing
+ GOTO_ERROR(mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(type) , 1));
+ GOTO_ERROR(mbedtls_md_hmac_starts(&ctx, hmac_key, sizeof(hmac_key)));
+ GOTO_ERROR(mbedtls_md_hmac_update(&ctx, (const unsigned char *) buf, sizeof(buf)));
+ GOTO_ERROR(mbedtls_md_hmac_finish(&ctx, hmac));
+#undef GOTO_ERROR
+ memcpy(iv, hmac, CHIAKI_RPCRYPT_KEY_SIZE);
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_SUCCESS;
+error:
+ mbedtls_md_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+}
+
+
+static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz, bool encrypt)
+{
+
+#define GOTO_ERROR(err) do { \
+ if((err) !=0){ \
+ goto error;} \
+ } while(0)
+
+ // https://github.com/ARMmbed/mbedtls/blob/development/programs/aes/aescrypt2.c
+ // build aes context
+ mbedtls_aes_context ctx;
+ mbedtls_aes_init(&ctx);
+
+ // initialization vector
+ uint8_t iv[CHIAKI_RPCRYPT_KEY_SIZE];
+ ChiakiErrorCode err = chiaki_rpcrypt_generate_iv(rpcrypt, iv, counter);
+ if(err != CHIAKI_ERR_SUCCESS)
+ return err;
+
+ GOTO_ERROR(mbedtls_aes_setkey_enc(&ctx, rpcrypt->bright, 128));
+ size_t iv_off = 0;
+ if(encrypt)
+ {
+ GOTO_ERROR(mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, sz, &iv_off, iv, in, out));
+ }
+ else
+ {
+ // the aes_crypt_cfb128 does not seems to use the setkey_dec
+ // GOTO_ERROR(mbedtls_aes_setkey_dec(&ctx, rpcrypt->bright, 128));
+ GOTO_ERROR(mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, sz, &iv_off, iv, in, out));
+ }
+
+#undef GOTO_ERROR
+ mbedtls_aes_free(&ctx);
+
+ return CHIAKI_ERR_SUCCESS;
+
+error:
+ mbedtls_aes_free(&ctx);
+ return CHIAKI_ERR_UNKNOWN;
+}
+
+#else
+CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter)
+{
+ uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
+
+ uint8_t buf[CHIAKI_RPCRYPT_KEY_SIZE + 8];
+ memcpy(buf, rpcrypt->ambassador, CHIAKI_RPCRYPT_KEY_SIZE);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 0] = (uint8_t)((counter >> 0x38) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 1] = (uint8_t)((counter >> 0x30) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 2] = (uint8_t)((counter >> 0x28) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 3] = (uint8_t)((counter >> 0x20) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 4] = (uint8_t)((counter >> 0x18) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 5] = (uint8_t)((counter >> 0x10) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 6] = (uint8_t)((counter >> 0x08) & 0xff);
+ buf[CHIAKI_RPCRYPT_KEY_SIZE + 7] = (uint8_t)((counter >> 0x00) & 0xff);
+
+
uint8_t hmac[32];
unsigned int hmac_len = 0;
if(!HMAC(EVP_sha256(), hmac_key, CHIAKI_RPCRYPT_KEY_SIZE, buf, sizeof(buf), hmac, &hmac_len))
@@ -150,6 +244,7 @@ static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t cou
EVP_CIPHER_CTX_free(ctx);
return CHIAKI_ERR_SUCCESS;
}
+#endif
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz)
{
diff --git a/lib/src/stoppipe.c b/lib/src/stoppipe.c
index cb90309..3262a98 100644
--- a/lib/src/stoppipe.c
+++ b/lib/src/stoppipe.c
@@ -34,11 +34,36 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe)
stop_pipe->event = WSACreateEvent();
if(stop_pipe->event == WSA_INVALID_EVENT)
return CHIAKI_ERR_UNKNOWN;
+#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ // currently pipe or socketpare are not available on switch
+ // use a custom udp socket as pipe
+
+ // struct sockaddr_in addr;
+ int addr_size = sizeof(stop_pipe->addr);
+
+ stop_pipe->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(stop_pipe->fd < 0){
+ return CHIAKI_ERR_UNKNOWN;
+ }
+ stop_pipe->addr.sin_family = AF_INET;
+ // bind to localhost
+ stop_pipe->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ // use a random port (dedicate one socket per object)
+ stop_pipe->addr.sin_port = htons(0);
+ // bind on localhost
+ bind(stop_pipe->fd, (struct sockaddr *) &stop_pipe->addr, addr_size);
+ // listen
+ getsockname(stop_pipe->fd, (struct sockaddr *) &stop_pipe->addr, &addr_size);
+ int r = fcntl(stop_pipe->fd, F_SETFL, O_NONBLOCK);
+ if(r == -1)
+ {
+ close(stop_pipe->fd);
+ return CHIAKI_ERR_UNKNOWN;
+ }
#else
int r = pipe(stop_pipe->fds);
if(r < 0)
return CHIAKI_ERR_UNKNOWN;
-
r = fcntl(stop_pipe->fds[0], F_SETFL, O_NONBLOCK);
if(r == -1)
{
@@ -47,7 +72,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_init(ChiakiStopPipe *stop_pipe)
return CHIAKI_ERR_UNKNOWN;
}
#endif
-
return CHIAKI_ERR_SUCCESS;
}
@@ -55,6 +79,8 @@ CHIAKI_EXPORT void chiaki_stop_pipe_fini(ChiakiStopPipe *stop_pipe)
{
#ifdef _WIN32
WSACloseEvent(stop_pipe->event);
+#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ close(stop_pipe->fd);
#else
close(stop_pipe->fds[0]);
close(stop_pipe->fds[1]);
@@ -65,6 +91,10 @@ CHIAKI_EXPORT void chiaki_stop_pipe_stop(ChiakiStopPipe *stop_pipe)
{
#ifdef _WIN32
WSASetEvent(stop_pipe->event);
+#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ // send to local socket (FIXME MSG_CONFIRM)
+ sendto(stop_pipe->fd, "\x00", 1, 0,
+ (struct sockaddr*)&stop_pipe->addr, sizeof(struct sockaddr_in));
#else
write(stop_pipe->fds[1], "\x00", 1);
#endif
@@ -105,12 +135,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
#else
fd_set rfds;
FD_ZERO(&rfds);
- FD_SET(stop_pipe->fds[0], &rfds);
+#if defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ // push udp local socket as fd
+ int stop_fd = stop_pipe->fd;
+#else
+ int stop_fd = stop_pipe->fds[0];
+#endif
+ FD_SET(stop_fd, &rfds);
+ int nfds = stop_fd;
fd_set wfds;
FD_ZERO(&wfds);
-
- int nfds = stop_pipe->fds[0];
if(!CHIAKI_SOCKET_IS_INVALID(fd))
{
FD_SET(fd, write ? &wfds : &rfds);
@@ -129,10 +164,11 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_select_single(ChiakiStopPipe *sto
}
int r = select(nfds, &rfds, write ? &wfds : NULL, NULL, timeout);
+
if(r < 0)
return CHIAKI_ERR_UNKNOWN;
- if(FD_ISSET(stop_pipe->fds[0], &rfds))
+ if(FD_ISSET(stop_fd, &rfds))
return CHIAKI_ERR_CANCELED;
if(!CHIAKI_SOCKET_IS_INVALID(fd) && FD_ISSET(fd, write ? &wfds : &rfds))
@@ -223,6 +259,12 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stop_pipe_reset(ChiakiStopPipe *stop_pipe)
#ifdef _WIN32
BOOL r = WSAResetEvent(stop_pipe->event);
return r ? CHIAKI_ERR_SUCCESS : CHIAKI_ERR_UNKNOWN;
+#elif defined(__SWITCH__) || defined(CHIAKI_ENABLE_SWITCH_LINUX)
+ //FIXME
+ uint8_t v;
+ int r;
+ while((r = read(stop_pipe->fd, &v, sizeof(v))) > 0);
+ return r < 0 ? CHIAKI_ERR_UNKNOWN : CHIAKI_ERR_SUCCESS;
#else
uint8_t v;
int r;
diff --git a/lib/src/takion.c b/lib/src/takion.c
index 89dbfda..9964a1d 100644
--- a/lib/src/takion.c
+++ b/lib/src/takion.c
@@ -28,6 +28,11 @@
#ifdef _WIN32
#include
+#elif defined(__SWITCH__)
+#include
+#include
+#include
+#include
#else
#include
#include
@@ -252,7 +257,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, Chiaki
#if defined(_WIN32)
const DWORD dontfragment_val = 1;
r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAGMENT, (const void *)&dontfragment_val, sizeof(dontfragment_val));
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__SWITCH__)
const int dontfrag_val = 1;
r = setsockopt(takion->sock, IPPROTO_IP, IP_DONTFRAG, (const void *)&dontfrag_val, sizeof(dontfrag_val));
#elif defined(IP_PMTUDISC_DO)
diff --git a/lib/src/thread.c b/lib/src/thread.c
index 27efd2f..563a140 100644
--- a/lib/src/thread.c
+++ b/lib/src/thread.c
@@ -24,6 +24,10 @@
#include
#include
+#ifdef __SWITCH__
+#include
+#endif
+
#if _WIN32
static DWORD WINAPI win32_thread_func(LPVOID param)
{
@@ -33,6 +37,18 @@ static DWORD WINAPI win32_thread_func(LPVOID param)
}
#endif
+#ifdef __SWITCH__
+int64_t get_thread_limit(){
+ uint64_t resource_limit_handle_value = INVALID_HANDLE;
+ svcGetInfo(&resource_limit_handle_value, InfoType_ResourceLimit, INVALID_HANDLE, 0);
+ int64_t thread_cur_value = 0, thread_lim_value = 0;
+ svcGetResourceLimitCurrentValue(&thread_cur_value, resource_limit_handle_value, LimitableResource_Threads);
+ svcGetResourceLimitLimitValue(&thread_lim_value, resource_limit_handle_value, LimitableResource_Threads);
+ //printf("thread_cur_value: %lu, thread_lim_value: %lu\n", thread_cur_value, thread_lim_value);
+ return thread_lim_value - thread_cur_value;
+}
+#endif
+
CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiThreadFunc func, void *arg)
{
#if _WIN32
@@ -43,6 +59,11 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_thread_create(ChiakiThread *thread, ChiakiT
if(!thread->thread)
return CHIAKI_ERR_THREAD;
#else
+#ifdef __SWITCH__
+ if(get_thread_limit() <= 1){
+ return CHIAKI_ERR_THREAD;
+ }
+#endif
int r = pthread_create(&thread->thread, NULL, func, arg);
if(r != 0)
return CHIAKI_ERR_THREAD;
diff --git a/scripts/switch/Dockerfile b/scripts/switch/Dockerfile
new file mode 100644
index 0000000..cd59827
--- /dev/null
+++ b/scripts/switch/Dockerfile
@@ -0,0 +1,81 @@
+FROM docker.io/archlinux/base
+
+ENV DEVKITPRO=/opt/devkitpro
+ENV DEVKITARM=/opt/devkitpro/devkitARM
+ENV DEVKITPPC=/opt/devkitpro/devkitPPC
+ENV PATH="${PATH}:${DEVKITARM}/bin/:${DEVKITPPC}/bin/"
+
+
+ENV WORKDIR="/build"
+WORKDIR "${WORKDIR}"
+
+# Upgarde image
+RUN pacman --noconfirm -Syu
+
+# Install requirements for libtransistor
+RUN pacman --noconfirm -S \
+ llvm \
+ clang \
+ lld \
+ python \
+ python-pip \
+ python-virtualenv \
+ squashfs-tools \
+ base-devel \
+ git \
+ cmake \
+ libx11 \
+ vim
+
+RUN pacman-key --init
+# Install devkitpro
+# doc source :
+# https://devkitpro.org/wiki/devkitPro_pacman
+
+# First import the key which is used to validate the packages
+RUN pacman-key --recv F7FD5492264BB9D0
+RUN pacman-key --lsign F7FD5492264BB9D0
+
+# Add the devkitPro repositories
+ADD devkit_repo ./devkit_repo
+RUN cat ./devkit_repo >> /etc/pacman.conf
+# Install the keyring which adds more keys which may be used to verify the packages.
+RUN pacman --noconfirm -U https://downloads.devkitpro.org/devkitpro-keyring-r1.787e015-2-any.pkg.tar.xz
+# Now resync the database and update installed packages.
+RUN pacman -Sy
+
+RUN pacman --noconfirm -Syu
+
+#RUN pacman --noconfirm -S $(pacman -Slq dkp-libs)
+
+RUN pacman --noconfirm -S \
+ protobuf \
+ python-protobuf \
+ sfml \
+ devkitARM \
+ switch-pkg-config \
+ devkitpro-pkgbuild-helpers \
+ switch-dev \
+ switch-zlib \
+ switch-sdl2 \
+ switch-freetype \
+ switch-curl \
+ switch-mesa \
+ switch-glad \
+ switch-glm \
+ switch-libconfig \
+ switch-sdl2_gfx \
+ switch-sdl2_ttf \
+ switch-sdl2_image \
+ switch-libexpat \
+ switch-bzip2 \
+ switch-libopus \
+ switch-ffmpeg \
+ switch-mbedtls
+
+RUN pip3 install -U pip
+
+VOLUME ${WORKDIR}
+# nxlink server port
+EXPOSE 28771
+ENTRYPOINT ["/bin/bash"]
diff --git a/scripts/switch/build.sh b/scripts/switch/build.sh
new file mode 100755
index 0000000..fb8bf6f
--- /dev/null
+++ b/scripts/switch/build.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -xveo pipefail
+
+arg1=$1
+CHIAKI_ENABLE_SWITCH_LINUX="ON"
+build="./build"
+if [ "$arg1" != "linux" ]; then
+ CHIAKI_ENABLE_SWITCH_LINUX="OFF"
+ source /opt/devkitpro/switchvars.sh
+ toolchain=/opt/devkitpro/switch.cmake
+
+ export CC=${TOOL_PREFIX}gcc
+ export CXX=${TOOL_PREFIX}g++
+ build="./build_switch"
+fi
+
+SCRIPTDIR=$(dirname "$0")
+BASEDIR=$(realpath "${SCRIPTDIR}/../../")
+
+build_chiaki (){
+ pushd "${BASEDIR}"
+ #rm -rf ./build
+
+ cmake -B "${build}" -DCMAKE_TOOLCHAIN_FILE=${toolchain} \
+ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
+ -DCHIAKI_ENABLE_TESTS=OFF \
+ -DCHIAKI_ENABLE_CLI=OFF \
+ -DCHIAKI_ENABLE_GUI=OFF \
+ -DCHIAKI_ENABLE_ANDROID=OFF \
+ -DCHIAKI_ENABLE_SWITCH=ON \
+ -DCHIAKI_ENABLE_SWITCH_LINUX="${CHIAKI_ENABLE_SWITCH_LINUX}" \
+ -DCHIAKI_LIB_ENABLE_MBEDTLS=ON
+
+ pushd "${BASEDIR}/${build}/switch/"
+ make
+ popd
+ popd
+}
+
+build_chiaki
+
diff --git a/scripts/switch/devkit_repo b/scripts/switch/devkit_repo
new file mode 100644
index 0000000..2646e2d
--- /dev/null
+++ b/scripts/switch/devkit_repo
@@ -0,0 +1,6 @@
+[dkp-libs]
+Server = http://downloads.devkitpro.org/packages
+
+[dkp-linux]
+Server = http://downloads.devkitpro.org/packages/linux
+
diff --git a/scripts/switch/fake_ctest.nintendo.net.py b/scripts/switch/fake_ctest.nintendo.net.py
new file mode 100644
index 0000000..b4cb83d
--- /dev/null
+++ b/scripts/switch/fake_ctest.nintendo.net.py
@@ -0,0 +1,31 @@
+# simple python3 http server to emulate ctest.nintendo.net
+# you have to redirect nintendo.net to your own host
+# https://gitlab.com/a/90dns
+
+# the aim is to fake ctest.nintendo.net server
+# to allow nintendo switch lan connection
+
+# The nintendo switch tries to join ctest to validate wifi settings
+# without 200 OK from ctest.nintendo.net, the LAN connection is denied
+
+import http.server
+import socketserver
+
+from http.server import HTTPServer, BaseHTTPRequestHandler
+
+
+class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+
+ def do_GET(self):
+ self.send_response(200)
+ self.send_header("Content-Type", "text/plain")
+ self.send_header("X-Organization", "Nintendo")
+ self.end_headers()
+ self.wfile.write(b'ok')
+
+
+PORT = 80
+
+httpd = HTTPServer(('0.0.0.0', PORT), SimpleHTTPRequestHandler)
+httpd.serve_forever()
+
From 6e2d93ec2c09cf917b8bfd1c2381772d9c1fa4b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 15 May 2020 12:04:21 +0200
Subject: [PATCH 025/269] Add CI Build for Switch (#234)
---
.github/workflows/switch.yml | 18 ++++++++++++++++++
.gitignore | 2 ++
scripts/switch/Dockerfile | 9 ++++-----
scripts/switch/build-docker-image.sh | 5 +++++
scripts/switch/build.sh | 5 ++---
scripts/switch/run-docker-build-chiaki.sh | 10 ++++++++++
6 files changed, 41 insertions(+), 8 deletions(-)
create mode 100644 .github/workflows/switch.yml
create mode 100755 scripts/switch/build-docker-image.sh
create mode 100755 scripts/switch/run-docker-build-chiaki.sh
diff --git a/.github/workflows/switch.yml b/.github/workflows/switch.yml
new file mode 100644
index 0000000..944b40e
--- /dev/null
+++ b/.github/workflows/switch.yml
@@ -0,0 +1,18 @@
+name: Switch
+on: [push]
+
+jobs:
+ build:
+ name: Switch
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Checkout submodules
+ run: |
+ git submodule init
+ git submodule update
+ - name: Docker Build
+ run: scripts/switch/build-docker-image.sh
+ - name: Build Chiaki
+ run: scripts/switch/run-docker-build-chiaki.sh
+
diff --git a/.gitignore b/.gitignore
index 43359e6..78d5d3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
.idea
build
cmake-build-*
+/build_*
+/build-*
.DS_store
*.AppImage
appdir
diff --git a/scripts/switch/Dockerfile b/scripts/switch/Dockerfile
index cd59827..494013d 100644
--- a/scripts/switch/Dockerfile
+++ b/scripts/switch/Dockerfile
@@ -1,15 +1,14 @@
-FROM docker.io/archlinux/base
+FROM archlinux:latest
ENV DEVKITPRO=/opt/devkitpro
ENV DEVKITARM=/opt/devkitpro/devkitARM
ENV DEVKITPPC=/opt/devkitpro/devkitPPC
ENV PATH="${PATH}:${DEVKITARM}/bin/:${DEVKITPPC}/bin/"
-
ENV WORKDIR="/build"
WORKDIR "${WORKDIR}"
-# Upgarde image
+# Upgrade image
RUN pacman --noconfirm -Syu
# Install requirements for libtransistor
@@ -33,7 +32,7 @@ RUN pacman-key --init
# https://devkitpro.org/wiki/devkitPro_pacman
# First import the key which is used to validate the packages
-RUN pacman-key --recv F7FD5492264BB9D0
+RUN pacman-key --recv-keys F7FD5492264BB9D0
RUN pacman-key --lsign F7FD5492264BB9D0
# Add the devkitPro repositories
@@ -73,7 +72,7 @@ RUN pacman --noconfirm -S \
switch-ffmpeg \
switch-mbedtls
-RUN pip3 install -U pip
+# RUN pip3 install -U pip
VOLUME ${WORKDIR}
# nxlink server port
diff --git a/scripts/switch/build-docker-image.sh b/scripts/switch/build-docker-image.sh
new file mode 100755
index 0000000..f8c7ea2
--- /dev/null
+++ b/scripts/switch/build-docker-image.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+cd "`dirname $(readlink -f ${0})`"
+
+docker build "$@" -t chiaki-switch .
diff --git a/scripts/switch/build.sh b/scripts/switch/build.sh
index fb8bf6f..ffec0b7 100755
--- a/scripts/switch/build.sh
+++ b/scripts/switch/build.sh
@@ -23,7 +23,6 @@ build_chiaki (){
#rm -rf ./build
cmake -B "${build}" -DCMAKE_TOOLCHAIN_FILE=${toolchain} \
- -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
-DCHIAKI_ENABLE_TESTS=OFF \
-DCHIAKI_ENABLE_CLI=OFF \
-DCHIAKI_ENABLE_GUI=OFF \
@@ -32,8 +31,8 @@ build_chiaki (){
-DCHIAKI_ENABLE_SWITCH_LINUX="${CHIAKI_ENABLE_SWITCH_LINUX}" \
-DCHIAKI_LIB_ENABLE_MBEDTLS=ON
- pushd "${BASEDIR}/${build}/switch/"
- make
+ pushd "${BASEDIR}/${build}"
+ make -j8
popd
popd
}
diff --git a/scripts/switch/run-docker-build-chiaki.sh b/scripts/switch/run-docker-build-chiaki.sh
new file mode 100755
index 0000000..660ab42
--- /dev/null
+++ b/scripts/switch/run-docker-build-chiaki.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+cd "`dirname $(readlink -f ${0})`/../.."
+
+docker run \
+ -v "`pwd`:/build/chiaki" \
+ -t \
+ chiaki-switch \
+ -c "cd /build/chiaki && scripts/switch/build.sh"
+
From 44b6058e06873ba3aed88563c7343e5d1ab27e82 Mon Sep 17 00:00:00 2001
From: h0neybadger
Date: Mon, 18 May 2020 12:43:24 +0200
Subject: [PATCH 026/269] Remove redundant __SWITCH__ with
CHIAKI_LIB_ENABLE_MBEDTLS definition
---
lib/include/chiaki/ecdh.h | 6 +++---
lib/src/ecdh.c | 12 ++++++------
lib/src/gkcrypt.c | 12 ++++++------
lib/src/random.c | 4 ++--
lib/src/rpcrypt.c | 4 ++--
5 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/lib/include/chiaki/ecdh.h b/lib/include/chiaki/ecdh.h
index fed92c4..0185c09 100644
--- a/lib/include/chiaki/ecdh.h
+++ b/lib/include/chiaki/ecdh.h
@@ -27,7 +27,7 @@
extern "C" {
#endif
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
#include "mbedtls/ecdh.h"
#include "mbedtls/ctr_drbg.h"
#endif
@@ -38,9 +38,9 @@ extern "C" {
typedef struct chiaki_ecdh_t
{
// the following lines may lead to memory corruption
-// __SWITCH__ or CHIAKI_LIB_ENABLE_MBEDTLS must be defined
+// CHIAKI_LIB_ENABLE_MBEDTLS must be defined
// globally (whole project)
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
// mbedtls ecdh context
mbedtls_ecdh_context ctx;
// deterministic random bit generator
diff --git a/lib/src/ecdh.c b/lib/src/ecdh.c
index 056d69d..8549a97 100644
--- a/lib/src/ecdh.c
+++ b/lib/src/ecdh.c
@@ -19,7 +19,7 @@
#include
#include
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
#include "mbedtls/entropy.h"
#include "mbedtls/md.h"
#else
@@ -38,7 +38,7 @@
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh)
{
memset(ecdh, 0, sizeof(ChiakiECDH));
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
#define CHECK(err) if((err) != 0) { \
chiaki_ecdh_fini(ecdh); \
return CHIAKI_ERR_UNKNOWN; }
@@ -85,7 +85,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_init(ChiakiECDH *ecdh)
CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh)
{
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
mbedtls_ecdh_free(&ecdh->ctx);
mbedtls_ctr_drbg_free(&ecdh->drbg);
#else
@@ -97,7 +97,7 @@ CHIAKI_EXPORT void chiaki_ecdh_fini(ChiakiECDH *ecdh)
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_set_local_key(ChiakiECDH *ecdh, const uint8_t *private_key, size_t private_key_size, const uint8_t *public_key, size_t public_key_size)
{
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
//https://tls.mbed.org/discussions/generic/publickey-binary-data-in-der
// Load keys from buffers (i.e: config file)
// TODO test
@@ -166,7 +166,7 @@ error_priv:
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_get_local_pub_key(ChiakiECDH *ecdh, uint8_t *key_out, size_t *key_out_size, const uint8_t *handshake_key, uint8_t *sig_out, size_t *sig_out_size)
{
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
mbedtls_md_context_t ctx;
mbedtls_md_init(&ctx);
@@ -213,7 +213,7 @@ error:
CHIAKI_EXPORT ChiakiErrorCode chiaki_ecdh_derive_secret(ChiakiECDH *ecdh, uint8_t *secret_out, const uint8_t *remote_key, size_t remote_key_size, const uint8_t *handshake_key, const uint8_t *remote_sig, size_t remote_sig_size)
{
//compute DH shared key
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
// https://github.com/ARMmbed/mbedtls/blob/development/programs/pkey/ecdh_curve25519.c#L151
#define GOTO_ERROR(err) do { \
if((err) !=0){ \
diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c
index 50678ea..0a2bc15 100644
--- a/lib/src/gkcrypt.c
+++ b/lib/src/gkcrypt.c
@@ -21,7 +21,7 @@
#include
#include
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
#include "mbedtls/gcm.h"
@@ -138,7 +138,7 @@ static ChiakiErrorCode gkcrypt_gen_key_iv(ChiakiGKCrypt *gkcrypt, uint8_t index,
uint8_t hmac[CHIAKI_GKCRYPT_BLOCK_SIZE*2];
size_t hmac_size = sizeof(hmac);
- #if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+ #ifdef CHIAKI_LIB_ENABLE_MBEDTLS
mbedtls_md_context_t ctx;
mbedtls_md_init(&ctx);
@@ -198,7 +198,7 @@ CHIAKI_EXPORT void chiaki_gkcrypt_gen_gmac_key(uint64_t index, const uint8_t *ke
memcpy(data, key_base, 0x10);
counter_add(data + 0x10, iv, index * CHIAKI_GKCRYPT_GMAC_KEY_REFRESH_IV_OFFSET);
uint8_t md[0x20];
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
// last param
// is224 Determines which function to use.
// This must be either 0 for SHA-256, or 1 for SHA-224.
@@ -230,7 +230,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry
assert(key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
assert(buf_size % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
// build mbedtls aes context
mbedtls_aes_context ctx;
mbedtls_aes_init(&ctx);
@@ -262,7 +262,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcry
for(uint8_t *cur = buf, *end = buf + buf_size; cur < end; cur += CHIAKI_GKCRYPT_BLOCK_SIZE)
counter_add(cur, gkcrypt->iv, counter_offset++);
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
for(int i=0; i
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
//#include
#include
#include
@@ -27,7 +27,7 @@
CHIAKI_EXPORT ChiakiErrorCode chiaki_random_bytes_crypt(uint8_t *buf, size_t buf_size)
{
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
// mbedtls_havege_state hs;
// mbedtls_havege_init(&hs);
// int r = mbedtls_havege_random( &hs, buf, sizeof( buf ) );
diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c
index f2982b6..5659105 100644
--- a/lib/src/rpcrypt.c
+++ b/lib/src/rpcrypt.c
@@ -17,7 +17,7 @@
#include
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
#else
@@ -83,7 +83,7 @@ CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint
rpcrypt->bright[3] ^= (uint8_t)((pin >> 0x00) & 0xff);
}
-#if defined(__SWITCH__) || defined(CHIAKI_LIB_ENABLE_MBEDTLS)
+#ifdef CHIAKI_LIB_ENABLE_MBEDTLS
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter)
{
uint8_t hmac_key[] = { 0xac, 0x07, 0x88, 0x83, 0xc8, 0x3a, 0x1f, 0xe8, 0x11, 0x46, 0x3a, 0xf3, 0x9e, 0xe3, 0xe3, 0x77 };
From e116d3fa4c6f9b85652a2e19158ffb60d04f2e96 Mon Sep 17 00:00:00 2001
From: h0neybadger
Date: Mon, 18 May 2020 12:45:43 +0200
Subject: [PATCH 027/269] Remove out of scope switch fake_ctest.nintendo.net.py
script
---
scripts/switch/fake_ctest.nintendo.net.py | 31 -----------------------
1 file changed, 31 deletions(-)
delete mode 100644 scripts/switch/fake_ctest.nintendo.net.py
diff --git a/scripts/switch/fake_ctest.nintendo.net.py b/scripts/switch/fake_ctest.nintendo.net.py
deleted file mode 100644
index b4cb83d..0000000
--- a/scripts/switch/fake_ctest.nintendo.net.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# simple python3 http server to emulate ctest.nintendo.net
-# you have to redirect nintendo.net to your own host
-# https://gitlab.com/a/90dns
-
-# the aim is to fake ctest.nintendo.net server
-# to allow nintendo switch lan connection
-
-# The nintendo switch tries to join ctest to validate wifi settings
-# without 200 OK from ctest.nintendo.net, the LAN connection is denied
-
-import http.server
-import socketserver
-
-from http.server import HTTPServer, BaseHTTPRequestHandler
-
-
-class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
-
- def do_GET(self):
- self.send_response(200)
- self.send_header("Content-Type", "text/plain")
- self.send_header("X-Organization", "Nintendo")
- self.end_headers()
- self.wfile.write(b'ok')
-
-
-PORT = 80
-
-httpd = HTTPServer(('0.0.0.0', PORT), SimpleHTTPRequestHandler)
-httpd.serve_forever()
-
From bf8685c761eb54e8a14160b6873477b6b3022348 Mon Sep 17 00:00:00 2001
From: Roy P
Date: Sat, 30 May 2020 07:25:50 -0400
Subject: [PATCH 028/269] Adding manifest to build flatpak package (#239)
---
.../com.github.thestr4ng3r.Chiaki.json | 96 +++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
diff --git a/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json b/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
new file mode 100644
index 0000000..831c079
--- /dev/null
+++ b/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
@@ -0,0 +1,96 @@
+{
+ "app-id": "org.flatpak.Chiaki",
+ "runtime": "org.kde.Platform",
+ "runtime-version": "5.14",
+ "sdk": "org.kde.Sdk",
+ "command": "chiaki",
+ "rename-icon": "chiaki",
+ "rename-desktop-file": "chiaki.desktop",
+ "separate-locales": false,
+ "finish-args": [
+ "--share=network",
+ "--share=ipc",
+ "--socket=wayland",
+ "--socket=x11",
+ "--device=all",
+ "--device=dri",
+ "--allow=bluetooth",
+ "--socket=pulseaudio",
+ "--filesystem=home",
+ "--own-name=org.kde.*",
+ "--env=DBUS_FATAL_WARNINGS=0",
+ "--talk-name=org.freedesktop.ScreenSaver"
+ ],
+ "add-extensions": {
+ "org.freedesktop.Platform.ffmpeg-full": {
+ "directory": "lib/ffmpeg",
+ "add-ld-path": ".",
+ "version": "19.08",
+ "autodownload": true,
+ "autodelete": false
+ },
+ "org.freedesktop.Platform.VAAPI.Intel": {
+ "directory": "lib/intel-vaapi-driver",
+ "add-ld-path": "lib",
+ "version": "19.08"
+ }
+ },
+ "modules": [
+ {
+ "name": "protobuf-compilers",
+ "buildsystem": "simple",
+ "build-commands": [
+ "install -D protoc /app/bin/protoc"
+ ],
+ "sources": [
+ {
+ "type": "archive",
+ "url": "https://github.com/protocolbuffers/protobuf/releases/download/v3.12.0/protoc-3.12.0-linux-x86_64.zip",
+ "sha256": "3af5f90ad973c36bdaf5c4bd0082cfdc8881593ddf530fc6aa1442ee3d7a4e4b"
+ }
+ ]
+ },
+ {
+ "name": "ffmpeg",
+ "cleanup": [ "/include", "/lib/pkgconfig", "/share/ffmpeg/examples" ],
+ "config-opts": [
+ "--enable-shared",
+ "--disable-static",
+ "--enable-gnutls",
+ "--disable-doc",
+ "--disable-programs",
+ "--disable-encoders",
+ "--disable-muxers",
+ "--enable-encoder=png"
+ ],
+ "sources": [{
+ "type": "archive",
+ "url": "https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.xz",
+ "sha256": "cb754255ab0ee2ea5f66f8850e1bd6ad5cac1cd855d0a2f4990fb8c668b0d29c"
+ }]
+ },
+ {
+ "name": "pip-install",
+ "buildsystem": "simple",
+ "build-options": {
+ "build-args": [
+ "--share=network"
+ ]
+ },
+ "build-commands": [
+ "pip3 install --prefix=/app google&&pip3 install --prefix=/app protobuf"
+ ]
+ },
+ {
+ "name": "chiaki",
+ "buildsystem": "cmake",
+ "builddir": "true",
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://github.com/thestr4ng3r/chiaki.git"
+ }
+ ]
+ }
+ ]
+}
From df8d537b2f59ab86c3a76ab052d41b92aadc1f8f Mon Sep 17 00:00:00 2001
From: Felipe Lavratti
Date: Sat, 30 May 2020 09:14:18 -0300
Subject: [PATCH 029/269] GUI - Controller: Fixing int16_t to uint8_t cast
(#243)
---
gui/src/controllermanager.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/gui/src/controllermanager.cpp b/gui/src/controllermanager.cpp
index 77941de..caf244d 100644
--- a/gui/src/controllermanager.cpp
+++ b/gui/src/controllermanager.cpp
@@ -219,8 +219,8 @@ ChiakiControllerState Controller::GetState()
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_START) ? CHIAKI_CONTROLLER_BUTTON_OPTIONS : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_BACK) ? CHIAKI_CONTROLLER_BUTTON_SHARE : 0;
state.buttons |= SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_GUIDE) ? CHIAKI_CONTROLLER_BUTTON_PS : 0;
- state.l2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 4);
- state.r2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 4);
+ state.l2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7);
+ state.r2_state = (uint8_t)(SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7);
state.left_x = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
state.left_y = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
state.right_x = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
@@ -228,4 +228,4 @@ ChiakiControllerState Controller::GetState()
#endif
return state;
-}
\ No newline at end of file
+}
From 626937fb20b896784d6ee46243ff22d99cea1807 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 30 May 2020 14:20:55 +0200
Subject: [PATCH 030/269] Fix a deprecated Qt API usage
---
gui/src/controllermanager.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gui/src/controllermanager.cpp b/gui/src/controllermanager.cpp
index caf244d..224f555 100644
--- a/gui/src/controllermanager.cpp
+++ b/gui/src/controllermanager.cpp
@@ -116,7 +116,7 @@ void ControllerManager::ControllerEvent(int device_id)
QList ControllerManager::GetAvailableControllers()
{
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
- return available_controllers.toList();
+ return available_controllers.values();
#else
return {};
#endif
From 0df3ba69cd11d1833a328cee93aa21669bba70e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 30 May 2020 15:26:27 +0200
Subject: [PATCH 031/269] Temporarily use local Switch Toolchain File
---
CMakeLists.txt | 2 --
cmake/switch.cmake | 17 +++++++++++++++++
scripts/switch/build.sh | 2 +-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9cffd0d..d32e8d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,6 @@ if(CHIAKI_ENABLE_SWITCH AND CHIAKI_ENABLE_SWITCH_LINUX)
set(CMAKE_BUILD_TYPE Debug)
elseif(CHIAKI_ENABLE_SWITCH)
add_definitions(-D__SWITCH__)
- # load switch.cmake toolchain form ./cmake folder
- include(switch)
# TODO check if android ... or other versions are enabled
# force mbedtls as crypto lib
set(CHIAKI_LIB_ENABLE_MBEDTLS ON)
diff --git a/cmake/switch.cmake b/cmake/switch.cmake
index 5409422..e9a07e5 100644
--- a/cmake/switch.cmake
+++ b/cmake/switch.cmake
@@ -45,6 +45,23 @@ switchvar(CMAKE_CPP_FLAGS CPPFLAGS "-D__SWITCH__ -I${PORTLIBS_PREFIX}/include -i
switchvar(CMAKE_LD_FLAGS LDFLAGS "${ARCH} -L${PORTLIBS_PREFIX}/lib -L${DEVKITPRO}/libnx/lib")
switchvar(LIBS LIBS "-lnx")
+
+
+# cache flags
+set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" )
+set( CMAKE_C_FLAGS "" CACHE STRING "c flags" )
+set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
+set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
+set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" )
+set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" )
+set( CMAKE_EXE_LINKER_FLAGS "-mtp=soft -fPIE -L${DEVKITPRO}/portlibs/switch/lib -L${DEVKITPRO}/libnx/lib -specs=${DEVKITPRO}/libnx/switch.specs -g" CACHE STRING "executable linker flags" )
+
+# we require the relocation table
+set(CMAKE_C_FLAGS "-I/opt/devkitpro/libnx/include -D__SWITCH__ -march=armv8-a -mtune=cortex-a57 -mtp=soft -ffunction-sections -fdata-sections -fPIE")
+set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
# switchvar(CMAKE_CXX_FLAGS CXXFLAGS "${CMAKE_C_FLAGS} -fno-rtti")
include_directories(${DEVKITPRO}/libnx/include ${PORTLIBS_PREFIX}/include)
diff --git a/scripts/switch/build.sh b/scripts/switch/build.sh
index ffec0b7..bd351f5 100755
--- a/scripts/switch/build.sh
+++ b/scripts/switch/build.sh
@@ -8,7 +8,7 @@ build="./build"
if [ "$arg1" != "linux" ]; then
CHIAKI_ENABLE_SWITCH_LINUX="OFF"
source /opt/devkitpro/switchvars.sh
- toolchain=/opt/devkitpro/switch.cmake
+ toolchain=../cmake/switch.cmake # TODO: devkitpro ships a toolchain in /opt/devkitpro/switch.cmake, but it's broken.
export CC=${TOOL_PREFIX}gcc
export CXX=${TOOL_PREFIX}g++
From 89c9bd44c354d1351fb9b9a8f9f0aade8077a129 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 30 May 2020 17:41:33 +0200
Subject: [PATCH 032/269] Version 1.2.1
---
CMakeLists.txt | 2 +-
android/app/build.gradle | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d32e8d0..4c203ef 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,7 +17,7 @@ option(CHIAKI_CLI_ARGP_STANDALONE "Search for standalone argp lib for CLI" OFF)
set(CHIAKI_VERSION_MAJOR 1)
set(CHIAKI_VERSION_MINOR 2)
-set(CHIAKI_VERSION_PATCH 0)
+set(CHIAKI_VERSION_PATCH 1)
set(CHIAKI_VERSION ${CHIAKI_VERSION_MAJOR}.${CHIAKI_VERSION_MINOR}.${CHIAKI_VERSION_PATCH})
set(CPACK_PACKAGE_NAME "chiaki")
diff --git a/android/app/build.gradle b/android/app/build.gradle
index b5285c0..a83e35a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -24,7 +24,7 @@ android {
applicationId "com.metallic.chiaki"
minSdkVersion 21
targetSdkVersion 29
- versionCode 5
+ versionCode 6
versionName chiakiVersion
externalNativeBuild {
cmake {
From 74e0f331f5197db8e10230583c1605c28a9be720 Mon Sep 17 00:00:00 2001
From: Mateusz Gozdek
Date: Wed, 3 Jun 2020 10:28:29 +0200
Subject: [PATCH 033/269] Add missing import of QPainterPath (#254, Fix #253)
---
gui/src/servericonwidget.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/gui/src/servericonwidget.cpp b/gui/src/servericonwidget.cpp
index e9d4e08..f7d60d7 100644
--- a/gui/src/servericonwidget.cpp
+++ b/gui/src/servericonwidget.cpp
@@ -18,6 +18,7 @@
#include
#include
+#include
ServerIconWidget::ServerIconWidget(QWidget *parent) : QWidget(parent)
{
From 2f8d9d189d1e66fe8b91e8f81567d57c76a63b43 Mon Sep 17 00:00:00 2001
From: Roy P
Date: Mon, 15 Jun 2020 12:56:09 -0400
Subject: [PATCH 034/269] Pin the flatpak file to the v1.2.1 release
---
scripts/flatpak/com.github.thestr4ng3r.Chiaki.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json b/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
index 831c079..abd3710 100644
--- a/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
+++ b/scripts/flatpak/com.github.thestr4ng3r.Chiaki.json
@@ -88,7 +88,9 @@
"sources": [
{
"type": "git",
- "url": "https://github.com/thestr4ng3r/chiaki.git"
+ "url": "https://github.com/thestr4ng3r/chiaki.git",
+ "tag": "v1.2.1",
+ "commit": "89c9bd44c354d1351fb9b9a8f9f0aade8077a129"
}
]
}
From ec7b46ac67a7c535c14d210339fe9bf969af4d80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 21 Jun 2020 14:19:30 +0200
Subject: [PATCH 035/269] Begin libsetsu with udev scan
---
.gitignore | 2 +
CMakeLists.txt | 1 +
setsu/CMakeLists.txt | 24 +++++
setsu/cmake/FindUDEV.cmake | 26 ++++++
setsu/include/setsu.h | 26 ++++++
setsu/src/setsu.c | 177 +++++++++++++++++++++++++++++++++++++
setsu/test/main.c | 25 ++++++
7 files changed, 281 insertions(+)
create mode 100644 setsu/CMakeLists.txt
create mode 100644 setsu/cmake/FindUDEV.cmake
create mode 100644 setsu/include/setsu.h
create mode 100644 setsu/src/setsu.c
create mode 100644 setsu/test/main.c
diff --git a/.gitignore b/.gitignore
index 78d5d3a..5e82c02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ chiaki.rb
*.jks
secret.tar
keystore-env.sh
+compile_commands.json
+.ccls-cache
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c203ef..841e1d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,6 +65,7 @@ if(CHIAKI_ENABLE_CLI)
endif()
if(CHIAKI_ENABLE_GUI)
+ add_subdirectory(setsu)
add_subdirectory(gui)
endif()
diff --git a/setsu/CMakeLists.txt b/setsu/CMakeLists.txt
new file mode 100644
index 0000000..e230c49
--- /dev/null
+++ b/setsu/CMakeLists.txt
@@ -0,0 +1,24 @@
+
+cmake_minimum_required(VERSION 3.2)
+
+project(libsetsu)
+
+option(SETSU_BUILD_TEST "Build testing executable for libsetsu" OFF)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+add_library(setsu
+ include/setsu.h
+ src/setsu.c)
+
+target_include_directories(setsu PUBLIC include)
+
+find_package(UDEV REQUIRED)
+target_link_libraries(setsu UDEV::libudev)
+
+if(SETSU_BUILD_TEST)
+ add_executable(setsutest
+ test/main.c)
+ target_link_libraries(setsutest setsu)
+endif()
+
diff --git a/setsu/cmake/FindUDEV.cmake b/setsu/cmake/FindUDEV.cmake
new file mode 100644
index 0000000..3b6b1e0
--- /dev/null
+++ b/setsu/cmake/FindUDEV.cmake
@@ -0,0 +1,26 @@
+# Provides: UDEV::libudev
+
+set(_prefix UDEV)
+set(_target "${_prefix}::libudev")
+
+find_package(PkgConfig REQUIRED)
+
+pkg_check_modules("${_prefix}" libudev)
+
+function(resolve_location)
+
+endfunction()
+
+if(${_prefix}_FOUND)
+ add_library("${_target}" INTERFACE IMPORTED)
+ target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
+ target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args("${_prefix}"
+ REQUIRED_VARS "${_prefix}_LIBRARIES"
+ VERSION_VAR "${_prefix}_VERSION")
+
+unset(_prefix)
+unset(_target)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
new file mode 100644
index 0000000..8df7536
--- /dev/null
+++ b/setsu/include/setsu.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#ifndef _SETSU_H
+#define _SETSU_H
+
+typedef struct setsu_ctx_t SetsuCtx;
+
+SetsuCtx *setsu_ctx_new();
+void setsu_ctx_free(SetsuCtx *ctx);
+
+#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
new file mode 100644
index 0000000..76ae7d5
--- /dev/null
+++ b/setsu/src/setsu.c
@@ -0,0 +1,177 @@
+
+#include
+
+#include
+
+#include
+#include
+#include
+
+
+#include
+
+typedef struct setsu_device_t
+{
+ struct setsu_device_t *next;
+ char *path;
+ int fd;
+} SetsuDevice;
+
+struct setsu_ctx_t
+{
+ struct udev *udev_ctx;
+ SetsuDevice *dev;
+};
+
+
+static void scan(SetsuCtx *ctx);
+static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added);
+static SetsuDevice *connect(SetsuCtx *ctx, const char *path);
+static void disconnect(SetsuCtx *ctx, SetsuDevice *dev);
+
+SetsuCtx *setsu_ctx_new()
+{
+ SetsuCtx *ctx = malloc(sizeof(SetsuCtx));
+ if(!ctx)
+ return NULL;
+
+ ctx->dev = NULL;
+
+ ctx->udev_ctx = udev_new();
+ if(!ctx->udev_ctx)
+ {
+ free(ctx);
+ return NULL;
+ }
+
+ // TODO: monitor
+
+ scan(ctx);
+
+ return ctx;
+}
+
+void setsu_ctx_free(SetsuCtx *ctx)
+{
+ while(ctx->dev)
+ disconnect(ctx, ctx->dev);
+ udev_unref(ctx->udev_ctx);
+ free(ctx);
+}
+
+static void scan(SetsuCtx *ctx)
+{
+ struct udev_enumerate *udev_enum = udev_enumerate_new(ctx->udev_ctx);
+ if(!udev_enum)
+ return;
+
+ if(udev_enumerate_add_match_subsystem(udev_enum, "input") < 0)
+ goto beach;
+
+ if(udev_enumerate_add_match_property(udev_enum, "ID_INPUT_TOUCHPAD", "1") < 0)
+ goto beach;
+
+ if(udev_enumerate_scan_devices(udev_enum) < 0)
+ goto beach;
+
+ for(struct udev_list_entry *entry = udev_enumerate_get_list_entry(udev_enum); entry; entry = udev_list_entry_get_next(entry))
+ {
+ const char *path = udev_list_entry_get_name(entry);
+ if(!path)
+ continue;
+ struct udev_device *dev = udev_device_new_from_syspath(ctx->udev_ctx, path);
+ if(!dev)
+ continue;
+ update_device(ctx, dev, true);
+ udev_device_unref(dev);
+ }
+
+beach:
+ udev_enumerate_unref(udev_enum);
+}
+
+static bool is_device_interesting(struct udev_device *dev)
+{
+ static const char *device_ids[] = {
+ // vendor id, model id
+ "054c", "05c4", // DualShock 4 USB
+ NULL
+ };
+
+ // Filter mouse-device (/dev/input/mouse*) away and only keep the evdev (/dev/input/event*) one:
+ if(!udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD_INTEGRATION"))
+ return false;
+
+ const char *vendor = udev_device_get_property_value(dev, "ID_VENDOR_ID");
+ const char *model = udev_device_get_property_value(dev, "ID_MODEL_ID");
+ if(!vendor || !model)
+ return false;
+
+ for(const char **dev_id = device_ids; *dev_id; dev_id += 2)
+ {
+ if(!strcmp(vendor, dev_id[0]) && !strcmp(model, dev_id[1]))
+ return true;
+ }
+ return false;
+}
+
+static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added)
+{
+ if(!is_device_interesting(dev))
+ return;
+ const char *path = udev_device_get_devnode(dev);
+ if(!path)
+ return;
+
+ for(SetsuDevice *dev = ctx->dev; dev; dev=dev->next)
+ {
+ if(!strcmp(dev->path, path))
+ {
+ if(added)
+ return; // already added, do nothing
+ disconnect(ctx, dev);
+ }
+ }
+ connect(ctx, path);
+}
+
+static SetsuDevice *connect(SetsuCtx *ctx, const char *path)
+{
+ SetsuDevice *dev = malloc(sizeof(SetsuDevice));
+ if(!dev)
+ return NULL;
+ dev->path = strdup(path);
+ if(!dev->path)
+ {
+ free(dev);
+ return NULL;
+ }
+
+ printf("connect %s\n", dev->path);
+ //dev->fd = open(dev->path, O_RDONLY | O_NONBLOCK);
+
+ dev->next = ctx->dev;
+ ctx->dev = dev;
+ return dev;
+}
+
+static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
+{
+ if(ctx->dev == dev)
+ ctx->dev = dev->next;
+ else
+ {
+ for(SetsuDevice *pdev = ctx->dev; pdev; pdev=pdev->next)
+ {
+ if(pdev->next == dev)
+ {
+ pdev->next = dev->next;
+ break;
+ }
+ }
+ }
+
+ free(dev->path);
+ free(dev);
+}
+
diff --git a/setsu/test/main.c b/setsu/test/main.c
new file mode 100644
index 0000000..823c283
--- /dev/null
+++ b/setsu/test/main.c
@@ -0,0 +1,25 @@
+
+#include
+
+#include
+#include
+
+SetsuCtx *ctx;
+
+void quit()
+{
+ setsu_ctx_free(ctx);
+}
+
+int main()
+{
+ ctx = setsu_ctx_new();
+ if(!ctx)
+ {
+ printf("Failed to init setsu\n");
+ return 1;
+ }
+ atexit(quit);
+ return 0;
+}
+
From 15f2ad5142ca1d42363e58a88fef18e0af107639 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 21 Jun 2020 14:22:11 +0200
Subject: [PATCH 036/269] Temporarily disable libsetsu for full project
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 841e1d3..459002c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,7 +65,7 @@ if(CHIAKI_ENABLE_CLI)
endif()
if(CHIAKI_ENABLE_GUI)
- add_subdirectory(setsu)
+ #add_subdirectory(setsu)
add_subdirectory(gui)
endif()
From d9d89f712280844fb4fd69a2dd7ed7c664e6d963 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 21 Jun 2020 21:30:46 +0200
Subject: [PATCH 037/269] Get Events from evdev
---
setsu/CMakeLists.txt | 5 +-
setsu/cmake/FindEvdev.cmake | 26 ++++++++
.../cmake/{FindUDEV.cmake => FindUdev.cmake} | 4 +-
setsu/include/setsu.h | 1 +
setsu/src/setsu.c | 65 +++++++++++++++++--
setsu/test/main.c | 17 +++++
6 files changed, 108 insertions(+), 10 deletions(-)
create mode 100644 setsu/cmake/FindEvdev.cmake
rename setsu/cmake/{FindUDEV.cmake => FindUdev.cmake} (92%)
diff --git a/setsu/CMakeLists.txt b/setsu/CMakeLists.txt
index e230c49..3c63a9f 100644
--- a/setsu/CMakeLists.txt
+++ b/setsu/CMakeLists.txt
@@ -13,8 +13,9 @@ add_library(setsu
target_include_directories(setsu PUBLIC include)
-find_package(UDEV REQUIRED)
-target_link_libraries(setsu UDEV::libudev)
+find_package(Udev REQUIRED)
+find_package(Evdev REQUIRED)
+target_link_libraries(setsu Udev::libudev Evdev::libevdev)
if(SETSU_BUILD_TEST)
add_executable(setsutest
diff --git a/setsu/cmake/FindEvdev.cmake b/setsu/cmake/FindEvdev.cmake
new file mode 100644
index 0000000..a6be138
--- /dev/null
+++ b/setsu/cmake/FindEvdev.cmake
@@ -0,0 +1,26 @@
+# Provides: Evdev::libevdev
+
+set(_prefix Evdev)
+set(_target "${_prefix}::libevdev")
+
+find_package(PkgConfig REQUIRED)
+
+pkg_check_modules("${_prefix}" libevdev)
+
+function(resolve_location)
+
+endfunction()
+
+if(${_prefix}_FOUND)
+ add_library("${_target}" INTERFACE IMPORTED)
+ target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
+ target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args("${_prefix}"
+ REQUIRED_VARS "${_prefix}_LIBRARIES"
+ VERSION_VAR "${_prefix}_VERSION")
+
+unset(_prefix)
+unset(_target)
diff --git a/setsu/cmake/FindUDEV.cmake b/setsu/cmake/FindUdev.cmake
similarity index 92%
rename from setsu/cmake/FindUDEV.cmake
rename to setsu/cmake/FindUdev.cmake
index 3b6b1e0..369f806 100644
--- a/setsu/cmake/FindUDEV.cmake
+++ b/setsu/cmake/FindUdev.cmake
@@ -1,6 +1,6 @@
-# Provides: UDEV::libudev
+# Provides: Udev::libudev
-set(_prefix UDEV)
+set(_prefix Udev)
set(_target "${_prefix}::libudev")
find_package(PkgConfig REQUIRED)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index 8df7536..5d8e766 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -22,5 +22,6 @@ typedef struct setsu_ctx_t SetsuCtx;
SetsuCtx *setsu_ctx_new();
void setsu_ctx_free(SetsuCtx *ctx);
+void setsu_ctx_run(SetsuCtx *ctx);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 76ae7d5..5bd2681 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -1,11 +1,31 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
#include
#include
+#include
#include
#include
#include
+#include
+#include
+#include
#include
@@ -15,6 +35,7 @@ typedef struct setsu_device_t
struct setsu_device_t *next;
char *path;
int fd;
+ struct libevdev *evdev;
} SetsuDevice;
struct setsu_ctx_t
@@ -140,19 +161,32 @@ static SetsuDevice *connect(SetsuCtx *ctx, const char *path)
SetsuDevice *dev = malloc(sizeof(SetsuDevice));
if(!dev)
return NULL;
+ memset(dev, 0, sizeof(*dev));
+ dev->fd = -1;
dev->path = strdup(path);
if(!dev->path)
- {
- free(dev);
- return NULL;
- }
+ goto error;
- printf("connect %s\n", dev->path);
- //dev->fd = open(dev->path, O_RDONLY | O_NONBLOCK);
+ dev->fd = open(dev->path, O_RDONLY | O_NONBLOCK);
+ if(dev->fd == -1)
+ goto error;
+
+ if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
+ goto error;
+
+ printf("connected to %s\n", libevdev_get_name(dev->evdev));
dev->next = ctx->dev;
ctx->dev = dev;
return dev;
+error:
+ if(dev->evdev)
+ libevdev_free(dev->evdev);
+ if(dev->fd != -1)
+ close(dev->fd);
+ free(dev->path);
+ free(dev);
+ return NULL;
}
static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
@@ -175,3 +209,22 @@ static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
free(dev);
}
+void setsu_ctx_run(SetsuCtx *ctx)
+{
+ SetsuDevice *dev = ctx->dev;
+ if(!dev)
+ return;
+
+ int rc;
+ do
+ {
+ struct input_event ev;
+ rc = libevdev_next_event(dev->evdev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+ if (rc == 0)
+ printf("Event: %s %s %d\n",
+ libevdev_event_type_get_name(ev.type),
+ libevdev_event_code_get_name(ev.type, ev.code),
+ ev.value);
+ } while (rc == 1 || rc == 0 || rc == -EAGAIN);
+}
+
diff --git a/setsu/test/main.c b/setsu/test/main.c
index 823c283..bfbf0f7 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -1,3 +1,19 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
#include
@@ -19,6 +35,7 @@ int main()
printf("Failed to init setsu\n");
return 1;
}
+ setsu_ctx_run(ctx);
atexit(quit);
return 0;
}
From 919d3b1c3b8faccff298495d75a8d586ee1e4df5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 27 Jun 2020 12:30:13 +0200
Subject: [PATCH 038/269] Fix macOS on Travis (#265)
---
.travis.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index ef3245a..7af6368 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -79,7 +79,6 @@ matrix:
osx_image: xcode11
addons:
homebrew:
- update: true # tmp
packages:
- qt
- opus
@@ -91,8 +90,7 @@ matrix:
- CMAKE_EXTRA_ARGS=""
- DEPLOY=1
install:
- - brew unlink python@2 # tmp
- - brew link python # tmp
+ - pip3 install protobuf
- scripts/build-ffmpeg.sh
script:
- scripts/travis-build.sh
From 9c91843d9879bc29854fac5cc304ae8c23b4fc8c Mon Sep 17 00:00:00 2001
From: Kaiwen Xu
Date: Sat, 27 Jun 2020 03:42:26 -0700
Subject: [PATCH 039/269] Expose videotoolbox hardware decoder (#261)
---
gui/include/videodecoder.h | 2 ++
gui/src/settings.cpp | 3 ++-
gui/src/settingsdialog.cpp | 3 ++-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/gui/include/videodecoder.h b/gui/include/videodecoder.h
index 84ccf0a..9fa1d5b 100644
--- a/gui/include/videodecoder.h
+++ b/gui/include/videodecoder.h
@@ -38,6 +38,7 @@ typedef enum {
HW_DECODE_NONE = 0,
HW_DECODE_VAAPI = 1,
HW_DECODE_VDPAU = 2,
+ HW_DECODE_VIDEOTOOLBOX = 3,
} HardwareDecodeEngine;
@@ -45,6 +46,7 @@ static const QMap hardware_decode_engine_nam
{ HW_DECODE_NONE, "none"},
{ HW_DECODE_VAAPI, "vaapi"},
{ HW_DECODE_VDPAU, "vdpau"},
+ { HW_DECODE_VIDEOTOOLBOX, "videotoolbox"},
};
class VideoDecoderException: public Exception
diff --git a/gui/src/settings.cpp b/gui/src/settings.cpp
index 90a5c03..8b23f55 100644
--- a/gui/src/settings.cpp
+++ b/gui/src/settings.cpp
@@ -97,7 +97,8 @@ unsigned int Settings::GetAudioBufferSizeRaw() const
static const QMap hw_decode_engine_values = {
{ HW_DECODE_NONE, "none" },
{ HW_DECODE_VAAPI, "vaapi" },
- { HW_DECODE_VDPAU, "vdpau" }
+ { HW_DECODE_VDPAU, "vdpau" },
+ { HW_DECODE_VIDEOTOOLBOX, "videotoolbox" }
};
static const HardwareDecodeEngine hw_decode_engine_default = HW_DECODE_NONE;
diff --git a/gui/src/settingsdialog.cpp b/gui/src/settingsdialog.cpp
index 3b0892a..04352bc 100644
--- a/gui/src/settingsdialog.cpp
+++ b/gui/src/settingsdialog.cpp
@@ -158,7 +158,8 @@ SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) : QDialog(pa
hardware_decode_combo_box = new QComboBox(this);
static const QList> hardware_decode_engines = {
{ HW_DECODE_NONE, "none"},
- { HW_DECODE_VAAPI, "vaapi"}
+ { HW_DECODE_VAAPI, "vaapi"},
+ { HW_DECODE_VIDEOTOOLBOX, "videotoolbox"}
};
auto current_hardware_decode_engine = settings->GetHardwareDecodeEngine();
for(const auto &p : hardware_decode_engines)
From 092355ff006adec596c3547495194e6166f07c0a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Mon, 29 Jun 2020 22:28:42 +0200
Subject: [PATCH 040/269] Better Polling in Setsu
---
setsu/include/setsu.h | 8 +--
setsu/src/setsu.c | 137 ++++++++++++++++++++++++++----------------
setsu/test/main.c | 11 ++--
3 files changed, 94 insertions(+), 62 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index 5d8e766..17439d0 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -18,10 +18,10 @@
#ifndef _SETSU_H
#define _SETSU_H
-typedef struct setsu_ctx_t SetsuCtx;
+typedef struct setsu_t Setsu;
-SetsuCtx *setsu_ctx_new();
-void setsu_ctx_free(SetsuCtx *ctx);
-void setsu_ctx_run(SetsuCtx *ctx);
+Setsu *setsu_new();
+void setsu_free(Setsu *setsu);
+void setsu_poll(Setsu *setsu);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 5bd2681..8be00c4 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -30,6 +30,10 @@
#include
+
+#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
+
+
typedef struct setsu_device_t
{
struct setsu_device_t *next;
@@ -38,51 +42,53 @@ typedef struct setsu_device_t
struct libevdev *evdev;
} SetsuDevice;
-struct setsu_ctx_t
+struct setsu_t
{
- struct udev *udev_ctx;
+ struct udev *udev_setsu;
SetsuDevice *dev;
};
-static void scan(SetsuCtx *ctx);
-static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added);
-static SetsuDevice *connect(SetsuCtx *ctx, const char *path);
-static void disconnect(SetsuCtx *ctx, SetsuDevice *dev);
+static void scan(Setsu *setsu);
+static void update_device(Setsu *setsu, struct udev_device *dev, bool added);
+static SetsuDevice *connect(Setsu *setsu, const char *path);
+static void disconnect(Setsu *setsu, SetsuDevice *dev);
+static void poll_device(Setsu *setsu, SetsuDevice *dev);
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev);
-SetsuCtx *setsu_ctx_new()
+Setsu *setsu_new()
{
- SetsuCtx *ctx = malloc(sizeof(SetsuCtx));
- if(!ctx)
+ Setsu *setsu = malloc(sizeof(Setsu));
+ if(!setsu)
return NULL;
- ctx->dev = NULL;
+ setsu->dev = NULL;
- ctx->udev_ctx = udev_new();
- if(!ctx->udev_ctx)
+ setsu->udev_setsu = udev_new();
+ if(!setsu->udev_setsu)
{
- free(ctx);
+ free(setsu);
return NULL;
}
// TODO: monitor
- scan(ctx);
+ scan(setsu);
- return ctx;
+ return setsu;
}
-void setsu_ctx_free(SetsuCtx *ctx)
+void setsu_free(Setsu *setsu)
{
- while(ctx->dev)
- disconnect(ctx, ctx->dev);
- udev_unref(ctx->udev_ctx);
- free(ctx);
+ while(setsu->dev)
+ disconnect(setsu, setsu->dev);
+ udev_unref(setsu->udev_setsu);
+ free(setsu);
}
-static void scan(SetsuCtx *ctx)
+static void scan(Setsu *setsu)
{
- struct udev_enumerate *udev_enum = udev_enumerate_new(ctx->udev_ctx);
+ struct udev_enumerate *udev_enum = udev_enumerate_new(setsu->udev_setsu);
if(!udev_enum)
return;
@@ -100,10 +106,11 @@ static void scan(SetsuCtx *ctx)
const char *path = udev_list_entry_get_name(entry);
if(!path)
continue;
- struct udev_device *dev = udev_device_new_from_syspath(ctx->udev_ctx, path);
+ struct udev_device *dev = udev_device_new_from_syspath(setsu->udev_setsu, path);
if(!dev)
continue;
- update_device(ctx, dev, true);
+ SETSU_LOG("enum device: %s\n", path);
+ update_device(setsu, dev, true);
udev_device_unref(dev);
}
@@ -115,7 +122,8 @@ static bool is_device_interesting(struct udev_device *dev)
{
static const char *device_ids[] = {
// vendor id, model id
- "054c", "05c4", // DualShock 4 USB
+ "054c", "05c4", // DualShock 4 Gen 1 USB
+ "054c", "09cc", // DualShock 4 Gen 2 USB
NULL
};
@@ -136,7 +144,7 @@ static bool is_device_interesting(struct udev_device *dev)
return false;
}
-static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added)
+static void update_device(Setsu *setsu, struct udev_device *dev, bool added)
{
if(!is_device_interesting(dev))
return;
@@ -144,19 +152,19 @@ static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added)
if(!path)
return;
- for(SetsuDevice *dev = ctx->dev; dev; dev=dev->next)
+ for(SetsuDevice *dev = setsu->dev; dev; dev=dev->next)
{
if(!strcmp(dev->path, path))
{
if(added)
return; // already added, do nothing
- disconnect(ctx, dev);
+ disconnect(setsu, dev);
}
}
- connect(ctx, path);
+ connect(setsu, path);
}
-static SetsuDevice *connect(SetsuCtx *ctx, const char *path)
+static SetsuDevice *connect(Setsu *setsu, const char *path)
{
SetsuDevice *dev = malloc(sizeof(SetsuDevice));
if(!dev)
@@ -174,10 +182,10 @@ static SetsuDevice *connect(SetsuCtx *ctx, const char *path)
if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
goto error;
- printf("connected to %s\n", libevdev_get_name(dev->evdev));
+ SETSU_LOG("connected to %s\n", libevdev_get_name(dev->evdev));
- dev->next = ctx->dev;
- ctx->dev = dev;
+ dev->next = setsu->dev;
+ setsu->dev = dev;
return dev;
error:
if(dev->evdev)
@@ -189,13 +197,13 @@ error:
return NULL;
}
-static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
+static void disconnect(Setsu *setsu, SetsuDevice *dev)
{
- if(ctx->dev == dev)
- ctx->dev = dev->next;
+ if(setsu->dev == dev)
+ setsu->dev = dev->next;
else
{
- for(SetsuDevice *pdev = ctx->dev; pdev; pdev=pdev->next)
+ for(SetsuDevice *pdev = setsu->dev; pdev; pdev=pdev->next)
{
if(pdev->next == dev)
{
@@ -209,22 +217,45 @@ static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
free(dev);
}
-void setsu_ctx_run(SetsuCtx *ctx)
+void setsu_poll(Setsu *setsu)
{
- SetsuDevice *dev = ctx->dev;
- if(!dev)
- return;
-
- int rc;
- do
- {
- struct input_event ev;
- rc = libevdev_next_event(dev->evdev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
- if (rc == 0)
- printf("Event: %s %s %d\n",
- libevdev_event_type_get_name(ev.type),
- libevdev_event_code_get_name(ev.type, ev.code),
- ev.value);
- } while (rc == 1 || rc == 0 || rc == -EAGAIN);
+ for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next)
+ poll_device(setsu, dev);
+}
+
+static void poll_device(Setsu *setsu, SetsuDevice *dev)
+{
+ bool sync = false;
+ while(true)
+ {
+ struct input_event ev;
+ int r = libevdev_next_event(dev->evdev, sync ? LIBEVDEV_READ_FLAG_SYNC : LIBEVDEV_READ_FLAG_NORMAL, &ev);
+ if(r == -EAGAIN)
+ {
+ if(sync)
+ {
+ sync = false;
+ continue;
+ }
+ break;
+ }
+ if(r == LIBEVDEV_READ_STATUS_SUCCESS || (sync && r == LIBEVDEV_READ_STATUS_SYNC))
+ device_event(setsu, dev, &ev);
+ else if(r == LIBEVDEV_READ_STATUS_SYNC)
+ sync = true;
+ else
+ {
+ SETSU_LOG("evdev poll failed\n");
+ break;
+ }
+ }
+}
+
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev)
+{
+ printf("Event: %s %s %d\n",
+ libevdev_event_type_get_name(ev->type),
+ libevdev_event_code_get_name(ev->type, ev->code),
+ ev->value);
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index bfbf0f7..fa1c137 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -20,22 +20,23 @@
#include
#include
-SetsuCtx *ctx;
+Setsu *setsu;
void quit()
{
- setsu_ctx_free(ctx);
+ setsu_free(setsu);
}
int main()
{
- ctx = setsu_ctx_new();
- if(!ctx)
+ setsu = setsu_new();
+ if(!setsu)
{
printf("Failed to init setsu\n");
return 1;
}
- setsu_ctx_run(ctx);
+ while(1)
+ setsu_poll(setsu);
atexit(quit);
return 0;
}
From aabb305eef6d50a859f852e18701f1bb1c54b09b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Mon, 29 Jun 2020 23:58:26 +0200
Subject: [PATCH 041/269] Add some ugly events to setsu
---
setsu/include/setsu.h | 19 +++++++-
setsu/src/setsu.c | 78 +++++++++++++++++++++++++------
setsu/test/main.c | 106 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 187 insertions(+), 16 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index 17439d0..aecf352 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -19,9 +19,26 @@
#define _SETSU_H
typedef struct setsu_t Setsu;
+typedef struct setsu_device_t SetsuDevice;
+
+typedef enum {
+ SETSU_EVENT_DOWN,
+ SETSU_EVENT_UP,
+ SETSU_EVENT_POSITION_X,
+ SETSU_EVENT_POSITION_Y
+} SetsuEventType;
+
+typedef struct setsu_event_t {
+ SetsuDevice *dev;
+ unsigned int tracking_id;
+ SetsuEventType type;
+ unsigned int value;
+} SetsuEvent;
+
+typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
Setsu *setsu_new();
void setsu_free(Setsu *setsu);
-void setsu_poll(Setsu *setsu);
+void setsu_poll(Setsu *setsu, SetsuEventCb cb);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 8be00c4..8a09455 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -33,6 +33,7 @@
#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
+#define SLOTS_COUNT 16
typedef struct setsu_device_t
{
@@ -40,6 +41,12 @@ typedef struct setsu_device_t
char *path;
int fd;
struct libevdev *evdev;
+
+ struct {
+ bool down;
+ unsigned int tracking_id;
+ } slots[SLOTS_COUNT];
+ unsigned int slot_cur;
} SetsuDevice;
struct setsu_t
@@ -53,8 +60,8 @@ static void scan(Setsu *setsu);
static void update_device(Setsu *setsu, struct udev_device *dev, bool added);
static SetsuDevice *connect(Setsu *setsu, const char *path);
static void disconnect(Setsu *setsu, SetsuDevice *dev);
-static void poll_device(Setsu *setsu, SetsuDevice *dev);
-static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev);
+static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb);
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb);
Setsu *setsu_new()
{
@@ -166,10 +173,9 @@ static void update_device(Setsu *setsu, struct udev_device *dev, bool added)
static SetsuDevice *connect(Setsu *setsu, const char *path)
{
- SetsuDevice *dev = malloc(sizeof(SetsuDevice));
+ SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
if(!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
dev->fd = -1;
dev->path = strdup(path);
if(!dev->path)
@@ -182,7 +188,12 @@ static SetsuDevice *connect(Setsu *setsu, const char *path)
if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
goto error;
- SETSU_LOG("connected to %s\n", libevdev_get_name(dev->evdev));
+ // TODO: expose these values:
+ int min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X);
+ int min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y);
+ int max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X);
+ int max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y);
+ SETSU_LOG("connected to %s: %d %d -> %d %d\n", libevdev_get_name(dev->evdev), min_x, min_y, max_x, max_y);
dev->next = setsu->dev;
setsu->dev = dev;
@@ -217,13 +228,13 @@ static void disconnect(Setsu *setsu, SetsuDevice *dev)
free(dev);
}
-void setsu_poll(Setsu *setsu)
+void setsu_poll(Setsu *setsu, SetsuEventCb cb)
{
for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next)
- poll_device(setsu, dev);
+ poll_device(setsu, dev, cb);
}
-static void poll_device(Setsu *setsu, SetsuDevice *dev)
+static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb)
{
bool sync = false;
while(true)
@@ -240,7 +251,7 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev)
break;
}
if(r == LIBEVDEV_READ_STATUS_SUCCESS || (sync && r == LIBEVDEV_READ_STATUS_SYNC))
- device_event(setsu, dev, &ev);
+ device_event(setsu, dev, &ev, cb);
else if(r == LIBEVDEV_READ_STATUS_SYNC)
sync = true;
else
@@ -251,11 +262,50 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev)
}
}
-static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev)
+static void send_event(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, SetsuEventType type, unsigned int value)
{
- printf("Event: %s %s %d\n",
- libevdev_event_type_get_name(ev->type),
- libevdev_event_code_get_name(ev->type, ev->code),
- ev->value);
+ SetsuEvent event;
+ event.dev = dev;
+ event.tracking_id = dev->slots[dev->slot_cur].tracking_id;
+ event.type = type;
+ event.value = value;
+ cb(&event, NULL);
+}
+
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb)
+{
+ if(ev->type == EV_ABS)
+ {
+ switch(ev->code)
+ {
+ case ABS_MT_SLOT:
+ if((unsigned int)ev->value >= SLOTS_COUNT)
+ {
+ SETSU_LOG("slot too high\n");
+ break;
+ }
+ dev->slot_cur = ev->value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ if(ev->value == -1)
+ {
+ dev->slots[dev->slot_cur].down = false;
+ send_event(setsu, dev, cb, SETSU_EVENT_UP, 0);
+ }
+ else
+ {
+ dev->slots[dev->slot_cur].down = true;
+ dev->slots[dev->slot_cur].tracking_id = ev->value;
+ send_event(setsu, dev, cb, SETSU_EVENT_DOWN, 0);
+ }
+ break;
+ case ABS_MT_POSITION_X:
+ send_event(setsu, dev, cb, SETSU_EVENT_POSITION_X, ev->value);
+ break;
+ case ABS_MT_POSITION_Y:
+ send_event(setsu, dev, cb, SETSU_EVENT_POSITION_Y, ev->value);
+ break;
+ }
+ }
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index fa1c137..bed5096 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -19,24 +19,128 @@
#include
#include
+#include
+#include
+#include
Setsu *setsu;
+#define WIDTH 1920
+#define HEIGHT 942
+#define TOUCHES_MAX 8
+
+struct {
+ bool down;
+ unsigned int tracking_id;
+ unsigned int x, y;
+} touches[TOUCHES_MAX];
+
+bool dirty = false;
+
void quit()
{
setsu_free(setsu);
}
+void print_state()
+{
+ for(size_t i=0; itype)
+ {
+ case SETSU_EVENT_DOWN:
+ for(size_t i=0; itracking_id;
+ break;
+ }
+ }
+ break;
+ case SETSU_EVENT_POSITION_X:
+ case SETSU_EVENT_POSITION_Y:
+ case SETSU_EVENT_UP:
+ for(size_t i=0; itracking_id)
+ {
+ switch(event->type)
+ {
+ case SETSU_EVENT_POSITION_X:
+ touches[i].x = event->value;
+ break;
+ case SETSU_EVENT_POSITION_Y:
+ touches[i].y = event->value;
+ break;
+ case SETSU_EVENT_UP:
+ touches[i].down = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
int main()
{
+ memset(touches, 0, sizeof(touches));
setsu = setsu_new();
if(!setsu)
{
printf("Failed to init setsu\n");
return 1;
}
+ dirty = true;
while(1)
- setsu_poll(setsu);
+ {
+ if(dirty)
+ print_state();
+ dirty = false;
+ setsu_poll(setsu, event);
+ }
atexit(quit);
return 0;
}
From 43dd40e46659dba4c76eba27a793f2be9354e34d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Tue, 30 Jun 2020 10:31:18 +0200
Subject: [PATCH 042/269] Make setsu events nicer
---
setsu/include/setsu.h | 12 +++--
setsu/src/setsu.c | 105 ++++++++++++++++++++++++++++++------------
setsu/test/main.c | 13 ++----
3 files changed, 87 insertions(+), 43 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index aecf352..de64970 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -18,27 +18,29 @@
#ifndef _SETSU_H
#define _SETSU_H
+#include
+
typedef struct setsu_t Setsu;
typedef struct setsu_device_t SetsuDevice;
+typedef int SetsuTrackingId;
typedef enum {
SETSU_EVENT_DOWN,
SETSU_EVENT_UP,
- SETSU_EVENT_POSITION_X,
- SETSU_EVENT_POSITION_Y
+ SETSU_EVENT_POSITION
} SetsuEventType;
typedef struct setsu_event_t {
SetsuDevice *dev;
- unsigned int tracking_id;
+ SetsuTrackingId tracking_id;
SetsuEventType type;
- unsigned int value;
+ uint32_t x, y;
} SetsuEvent;
typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
Setsu *setsu_new();
void setsu_free(Setsu *setsu);
-void setsu_poll(Setsu *setsu, SetsuEventCb cb);
+void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 8a09455..f43a3cc 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -43,8 +43,17 @@ typedef struct setsu_device_t
struct libevdev *evdev;
struct {
- bool down;
- unsigned int tracking_id;
+ /* Saves the old tracking id that was just up-ed.
+ * also for handling "atomic" up->down
+ * i.e. when there is an up, then down with a different tracking id
+ * in a single frame (before SYN_REPORT), this saves the old
+ * tracking id that must be reported as up. */
+ int tracking_id_prev;
+
+ int tracking_id;
+ int x, y;
+ bool downed;
+ bool pos_dirty;
} slots[SLOTS_COUNT];
unsigned int slot_cur;
} SetsuDevice;
@@ -60,8 +69,9 @@ static void scan(Setsu *setsu);
static void update_device(Setsu *setsu, struct udev_device *dev, bool added);
static SetsuDevice *connect(Setsu *setsu, const char *path);
static void disconnect(Setsu *setsu, SetsuDevice *dev);
-static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb);
-static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb);
+static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user);
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb, void *user);
+static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user);
Setsu *setsu_new()
{
@@ -228,13 +238,13 @@ static void disconnect(Setsu *setsu, SetsuDevice *dev)
free(dev);
}
-void setsu_poll(Setsu *setsu, SetsuEventCb cb)
+void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user)
{
for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next)
- poll_device(setsu, dev, cb);
+ poll_device(setsu, dev, cb, user);
}
-static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb)
+static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user)
{
bool sync = false;
while(true)
@@ -251,7 +261,7 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb)
break;
}
if(r == LIBEVDEV_READ_STATUS_SUCCESS || (sync && r == LIBEVDEV_READ_STATUS_SYNC))
- device_event(setsu, dev, &ev, cb);
+ device_event(setsu, dev, &ev, cb, user);
else if(r == LIBEVDEV_READ_STATUS_SYNC)
sync = true;
else
@@ -262,18 +272,15 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb)
}
}
-static void send_event(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, SetsuEventType type, unsigned int value)
-{
- SetsuEvent event;
- event.dev = dev;
- event.tracking_id = dev->slots[dev->slot_cur].tracking_id;
- event.type = type;
- event.value = value;
- cb(&event, NULL);
-}
-
-static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb)
+static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb, void *user)
{
+#if 0
+ SETSU_LOG("Event: %s %s %d\n",
+ libevdev_event_type_get_name(ev->type),
+ libevdev_event_code_get_name(ev->type, ev->code),
+ ev->value);
+#endif
+#define S dev->slots[dev->slot_cur]
if(ev->type == EV_ABS)
{
switch(ev->code)
@@ -287,25 +294,63 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev,
dev->slot_cur = ev->value;
break;
case ABS_MT_TRACKING_ID:
- if(ev->value == -1)
+ if(S.tracking_id != -1 && S.tracking_id_prev == -1)
{
- dev->slots[dev->slot_cur].down = false;
- send_event(setsu, dev, cb, SETSU_EVENT_UP, 0);
- }
- else
- {
- dev->slots[dev->slot_cur].down = true;
- dev->slots[dev->slot_cur].tracking_id = ev->value;
- send_event(setsu, dev, cb, SETSU_EVENT_DOWN, 0);
+ // up the tracking id
+ S.tracking_id_prev = S.tracking_id;
+ // reset the rest
+ S.x = S.y = 0;
+ S.pos_dirty = false;
}
+ S.tracking_id = ev->value;
+ S.downed = true;
break;
case ABS_MT_POSITION_X:
- send_event(setsu, dev, cb, SETSU_EVENT_POSITION_X, ev->value);
+ S.x = ev->value;
+ S.pos_dirty = true;
break;
case ABS_MT_POSITION_Y:
- send_event(setsu, dev, cb, SETSU_EVENT_POSITION_Y, ev->value);
+ S.y = ev->value;
+ S.pos_dirty = true;
break;
}
}
+ else if(ev->type == EV_SYN && ev->code == SYN_REPORT)
+ device_drain(setsu, dev, cb, user);
+}
+
+static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user)
+{
+ SetsuEvent event;
+#define BEGIN_EVENT(tp) do { memset(&event, 0, sizeof(event)); event.dev = dev; event.type = tp; } while(0)
+#define SEND_EVENT() do { cb(&event, user); } while (0)
+ for(size_t i=0; islots[i].tracking_id_prev != -1)
+ {
+ BEGIN_EVENT(SETSU_EVENT_UP);
+ event.tracking_id = dev->slots[i].tracking_id_prev;
+ SEND_EVENT();
+ dev->slots[i].tracking_id_prev = -1;
+ }
+ if(dev->slots[i].downed)
+ {
+ BEGIN_EVENT(SETSU_EVENT_DOWN);
+ event.tracking_id = dev->slots[i].tracking_id;
+ SEND_EVENT();
+ dev->slots[i].downed = false;
+ }
+ if(dev->slots[i].pos_dirty)
+ {
+ BEGIN_EVENT(SETSU_EVENT_POSITION);
+ event.tracking_id = dev->slots[i].tracking_id;
+ event.x = dev->slots[i].x;
+ event.y = dev->slots[i].y;
+ SEND_EVENT();
+ dev->slots[i].pos_dirty = false;
+ }
+ }
+#undef BEGIN_EVENT
+#undef SEND_EVENT
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index bed5096..6bc5882 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -97,8 +97,7 @@ void event(SetsuEvent *event, void *user)
}
}
break;
- case SETSU_EVENT_POSITION_X:
- case SETSU_EVENT_POSITION_Y:
+ case SETSU_EVENT_POSITION:
case SETSU_EVENT_UP:
for(size_t i=0; itype)
{
- case SETSU_EVENT_POSITION_X:
- touches[i].x = event->value;
- break;
- case SETSU_EVENT_POSITION_Y:
- touches[i].y = event->value;
+ case SETSU_EVENT_POSITION:
+ touches[i].x = event->x;
+ touches[i].y = event->y;
break;
case SETSU_EVENT_UP:
touches[i].down = false;
@@ -139,7 +136,7 @@ int main()
if(dirty)
print_state();
dirty = false;
- setsu_poll(setsu, event);
+ setsu_poll(setsu, event, NULL);
}
atexit(quit);
return 0;
From 4a1ad05b5dde9b607fa09dd1c128030596f38a3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Wed, 1 Jul 2020 18:44:54 +0200
Subject: [PATCH 043/269] Device Events in Setsu
---
setsu/include/setsu.h | 37 +++++++++--
setsu/src/setsu.c | 151 ++++++++++++++++++++++++++++++++----------
setsu/test/main.c | 5 ++
3 files changed, 155 insertions(+), 38 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index de64970..eaf32a6 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -25,16 +25,43 @@ typedef struct setsu_device_t SetsuDevice;
typedef int SetsuTrackingId;
typedef enum {
+ /* New device available to connect.
+ * Event will have path set to the new device. */
+ SETSU_EVENT_DEVICE_ADDED,
+
+ /* Previously available device removed.
+ * Event will have path set to the new device.
+ * Any SetsuDevice connected to this path will automatically
+ * be disconnected and their pointers will be invalid immediately
+ * after the callback for this event returns. */
+ SETSU_EVENT_DEVICE_REMOVED,
+
+ /* Touch down.
+ * Event will have dev and tracking_id set. */
SETSU_EVENT_DOWN,
+
+ /* Touch down.
+ * Event will have dev and tracking_id set. */
SETSU_EVENT_UP,
+
+ /* Touch position update.
+ * Event will have dev, tracking_id, x and y set. */
SETSU_EVENT_POSITION
} SetsuEventType;
-typedef struct setsu_event_t {
- SetsuDevice *dev;
- SetsuTrackingId tracking_id;
+typedef struct setsu_event_t
+{
SetsuEventType type;
- uint32_t x, y;
+ union
+ {
+ const char *path;
+ struct
+ {
+ SetsuDevice *dev;
+ SetsuTrackingId tracking_id;
+ uint32_t x, y;
+ };
+ };
} SetsuEvent;
typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
@@ -42,5 +69,7 @@ typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
Setsu *setsu_new();
void setsu_free(Setsu *setsu);
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user);
+SetsuDevice *setsu_connect(Setsu *setsu, const char *path);
+void setsu_disconnect(Setsu *setsu, SetsuDevice *dev);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index f43a3cc..56682fb 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -27,12 +27,18 @@
#include
#include
-
#include
-
#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
+typedef struct setsu_avail_device_t
+{
+ struct setsu_avail_device_t *next;
+ char *path;
+ bool connect_dirty; // whether the connect has not been sent as an event yet
+ bool disconnect_dirty; // whether the disconnect has not been sent as an event yet
+} SetsuAvailDevice;
+
#define SLOTS_COUNT 16
typedef struct setsu_device_t
@@ -41,6 +47,7 @@ typedef struct setsu_device_t
char *path;
int fd;
struct libevdev *evdev;
+ int min_x, min_y, max_x, max_y;
struct {
/* Saves the old tracking id that was just up-ed.
@@ -60,13 +67,13 @@ typedef struct setsu_device_t
struct setsu_t
{
- struct udev *udev_setsu;
+ struct udev *udev;
+ SetsuAvailDevice *avail_dev;
SetsuDevice *dev;
};
-
-static void scan(Setsu *setsu);
-static void update_device(Setsu *setsu, struct udev_device *dev, bool added);
+static void scan_udev(Setsu *setsu);
+static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added);
static SetsuDevice *connect(Setsu *setsu, const char *path);
static void disconnect(Setsu *setsu, SetsuDevice *dev);
static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user);
@@ -75,14 +82,12 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *
Setsu *setsu_new()
{
- Setsu *setsu = malloc(sizeof(Setsu));
+ Setsu *setsu = calloc(1, sizeof(Setsu));
if(!setsu)
return NULL;
- setsu->dev = NULL;
-
- setsu->udev_setsu = udev_new();
- if(!setsu->udev_setsu)
+ setsu->udev = udev_new();
+ if(!setsu->udev)
{
free(setsu);
return NULL;
@@ -90,7 +95,7 @@ Setsu *setsu_new()
// TODO: monitor
- scan(setsu);
+ scan_udev(setsu);
return setsu;
}
@@ -98,14 +103,14 @@ Setsu *setsu_new()
void setsu_free(Setsu *setsu)
{
while(setsu->dev)
- disconnect(setsu, setsu->dev);
- udev_unref(setsu->udev_setsu);
+ setsu_disconnect(setsu, setsu->dev);
+ udev_unref(setsu->udev);
free(setsu);
}
-static void scan(Setsu *setsu)
+static void scan_udev(Setsu *setsu)
{
- struct udev_enumerate *udev_enum = udev_enumerate_new(setsu->udev_setsu);
+ struct udev_enumerate *udev_enum = udev_enumerate_new(setsu->udev);
if(!udev_enum)
return;
@@ -123,11 +128,11 @@ static void scan(Setsu *setsu)
const char *path = udev_list_entry_get_name(entry);
if(!path)
continue;
- struct udev_device *dev = udev_device_new_from_syspath(setsu->udev_setsu, path);
+ struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path);
if(!dev)
continue;
SETSU_LOG("enum device: %s\n", path);
- update_device(setsu, dev, true);
+ update_udev_device(setsu, dev, true);
udev_device_unref(dev);
}
@@ -161,7 +166,7 @@ static bool is_device_interesting(struct udev_device *dev)
return false;
}
-static void update_device(Setsu *setsu, struct udev_device *dev, bool added)
+static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added)
{
if(!is_device_interesting(dev))
return;
@@ -169,19 +174,32 @@ static void update_device(Setsu *setsu, struct udev_device *dev, bool added)
if(!path)
return;
- for(SetsuDevice *dev = setsu->dev; dev; dev=dev->next)
+ for(SetsuAvailDevice *adev = setsu->avail_dev; adev; adev=adev->next)
{
- if(!strcmp(dev->path, path))
+ if(!strcmp(adev->path, path))
{
if(added)
return; // already added, do nothing
- disconnect(setsu, dev);
+ // disconnected
+ adev->disconnect_dirty = true;
}
}
- connect(setsu, path);
+ // not yet added
+ SetsuAvailDevice *adev = calloc(1, sizeof(SetsuAvailDevice));
+ if(!adev)
+ return;
+ adev->path = strdup(path);
+ if(!adev->path)
+ {
+ free(adev);
+ return;
+ }
+ adev->next = setsu->avail_dev;
+ setsu->avail_dev = adev;
+ adev->connect_dirty = true;
}
-static SetsuDevice *connect(Setsu *setsu, const char *path)
+SetsuDevice *setsu_connect(Setsu *setsu, const char *path)
{
SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
if(!dev)
@@ -196,14 +214,21 @@ static SetsuDevice *connect(Setsu *setsu, const char *path)
goto error;
if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
+ {
+ dev->evdev = NULL;
goto error;
+ }
- // TODO: expose these values:
- int min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X);
- int min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y);
- int max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X);
- int max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y);
- SETSU_LOG("connected to %s: %d %d -> %d %d\n", libevdev_get_name(dev->evdev), min_x, min_y, max_x, max_y);
+ dev->min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X);
+ dev->min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y);
+ dev->max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X);
+ dev->max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y);
+
+ for(size_t i=0; islots[i].tracking_id_prev = -1;
+ dev->slots[i].tracking_id = -1;
+ }
dev->next = setsu->dev;
setsu->dev = dev;
@@ -218,13 +243,13 @@ error:
return NULL;
}
-static void disconnect(Setsu *setsu, SetsuDevice *dev)
+void setsu_disconnect(Setsu *setsu, SetsuDevice *dev)
{
if(setsu->dev == dev)
setsu->dev = dev->next;
else
{
- for(SetsuDevice *pdev = setsu->dev; pdev; pdev=pdev->next)
+ for(SetsuDevice *pdev = setsu->dev; pdev; pdev = pdev->next)
{
if(pdev->next == dev)
{
@@ -233,13 +258,69 @@ static void disconnect(Setsu *setsu, SetsuDevice *dev)
}
}
}
-
+ libevdev_free(dev->evdev);
+ close(dev->fd);
free(dev->path);
free(dev);
}
+void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
+{
+ for(SetsuDevice *dev = setsu->dev; dev;)
+ {
+ if(!strcmp(dev->path, adev->path))
+ {
+ SetsuDevice *next = dev->next;
+ setsu_disconnect(setsu, dev);
+ dev = next;
+ }
+ dev = dev->next;
+ }
+
+ if(setsu->avail_dev == adev)
+ setsu->avail_dev = adev->next;
+ else
+ {
+ for(SetsuAvailDevice *padev = setsu->avail_dev; padev; padev = padev->next)
+ {
+ if(padev->next == adev)
+ {
+ padev->next = adev->next;
+ break;
+ }
+ }
+ }
+ free(adev->path);
+ free(adev);
+}
+
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user)
{
+ for(SetsuAvailDevice *adev = setsu->avail_dev; adev;)
+ {
+ if(adev->connect_dirty)
+ {
+ SetsuEvent event = { 0 };
+ event.type = SETSU_EVENT_DEVICE_ADDED;
+ event.path = adev->path;
+ cb(&event, user);
+ adev->connect_dirty = false;
+ }
+ if(adev->disconnect_dirty)
+ {
+ SetsuEvent event = { 0 };
+ event.type = SETSU_EVENT_DEVICE_REMOVED;
+ event.path = adev->path;
+ cb(&event, user);
+ // kill the device only after sending the event
+ SetsuAvailDevice *next = adev->next;
+ kill_avail_device(setsu, adev);
+ adev = next;
+ continue;
+ }
+ adev = adev->next;
+ }
+
for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next)
poll_device(setsu, dev, cb, user);
}
@@ -303,7 +384,8 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev,
S.pos_dirty = false;
}
S.tracking_id = ev->value;
- S.downed = true;
+ if(ev->value != -1)
+ S.downed = true;
break;
case ABS_MT_POSITION_X:
S.x = ev->value;
@@ -317,6 +399,7 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev,
}
else if(ev->type == EV_SYN && ev->code == SYN_REPORT)
device_drain(setsu, dev, cb, user);
+#undef S
}
static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user)
diff --git a/setsu/test/main.c b/setsu/test/main.c
index 6bc5882..f9bdbab 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -86,6 +86,11 @@ void event(SetsuEvent *event, void *user)
dirty = true;
switch(event->type)
{
+ case SETSU_EVENT_DEVICE_ADDED:
+ setsu_connect(setsu, event->path);
+ break;
+ case SETSU_EVENT_DEVICE_REMOVED:
+ break;
case SETSU_EVENT_DOWN:
for(size_t i=0; i
Date: Wed, 1 Jul 2020 20:48:01 +0200
Subject: [PATCH 044/269] Add udev monitor to setsu
---
setsu/include/setsu.h | 1 +
setsu/src/setsu.c | 64 ++++++++++++++++++++++++++++++++++++++-----
setsu/test/main.c | 37 ++++++++++++++++++++++---
3 files changed, 91 insertions(+), 11 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index eaf32a6..3e8b51e 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -71,5 +71,6 @@ void setsu_free(Setsu *setsu);
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user);
SetsuDevice *setsu_connect(Setsu *setsu, const char *path);
void setsu_disconnect(Setsu *setsu, SetsuDevice *dev);
+const char *setsu_device_get_path(SetsuDevice *dev);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 56682fb..6a4eb38 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -29,7 +29,13 @@
#include
+#define ENABLE_LOG
+
+#ifdef ENABLE_LOG
#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define SETSU_LOG(...) do {} while(0)
+#endif
typedef struct setsu_avail_device_t
{
@@ -68,12 +74,13 @@ typedef struct setsu_device_t
struct setsu_t
{
struct udev *udev;
+ struct udev_monitor *udev_mon;
SetsuAvailDevice *avail_dev;
SetsuDevice *dev;
};
static void scan_udev(Setsu *setsu);
-static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added);
+static void update_udev_device(Setsu *setsu, struct udev_device *dev);
static SetsuDevice *connect(Setsu *setsu, const char *path);
static void disconnect(Setsu *setsu, SetsuDevice *dev);
static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user);
@@ -93,7 +100,14 @@ Setsu *setsu_new()
return NULL;
}
- // TODO: monitor
+ setsu->udev_mon = udev_monitor_new_from_netlink(setsu->udev, "udev");
+ if(setsu->udev_mon)
+ {
+ udev_monitor_filter_add_match_subsystem_devtype(setsu->udev_mon, "input", NULL);
+ udev_monitor_enable_receiving(setsu->udev_mon);
+ }
+ else
+ SETSU_LOG("Failed to create udev monitor\n");
scan_udev(setsu);
@@ -104,6 +118,8 @@ void setsu_free(Setsu *setsu)
{
while(setsu->dev)
setsu_disconnect(setsu, setsu->dev);
+ if(setsu->udev_mon)
+ udev_monitor_unref(setsu->udev_mon);
udev_unref(setsu->udev);
free(setsu);
}
@@ -131,8 +147,7 @@ static void scan_udev(Setsu *setsu)
struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path);
if(!dev)
continue;
- SETSU_LOG("enum device: %s\n", path);
- update_udev_device(setsu, dev, true);
+ update_udev_device(setsu, dev);
udev_device_unref(dev);
}
@@ -166,14 +181,23 @@ static bool is_device_interesting(struct udev_device *dev)
return false;
}
-static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added)
+static void update_udev_device(Setsu *setsu, struct udev_device *dev)
{
if(!is_device_interesting(dev))
return;
const char *path = udev_device_get_devnode(dev);
if(!path)
return;
-
+
+ const char *action = udev_device_get_action(dev);
+ bool added;
+ if(!action || !strcmp(action, "add"))
+ added = true;
+ else if(!strcmp(action, "remove"))
+ added = false;
+ else
+ return;
+
for(SetsuAvailDevice *adev = setsu->avail_dev; adev; adev=adev->next)
{
if(!strcmp(adev->path, path))
@@ -182,6 +206,7 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added
return; // already added, do nothing
// disconnected
adev->disconnect_dirty = true;
+ return;
}
}
// not yet added
@@ -199,6 +224,20 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added
adev->connect_dirty = true;
}
+static void poll_udev_monitor(Setsu *setsu)
+{
+ if(!setsu->udev_mon)
+ return;
+ while(1)
+ {
+ struct udev_device *dev = udev_monitor_receive_device(setsu->udev_mon);
+ if(!dev)
+ break;
+ update_udev_device(setsu, dev);
+ udev_device_unref(dev);
+ }
+}
+
SetsuDevice *setsu_connect(Setsu *setsu, const char *path)
{
SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
@@ -264,6 +303,11 @@ void setsu_disconnect(Setsu *setsu, SetsuDevice *dev)
free(dev);
}
+const char *setsu_device_get_path(SetsuDevice *dev)
+{
+ return dev->path;
+}
+
void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
{
for(SetsuDevice *dev = setsu->dev; dev;)
@@ -273,6 +317,7 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
SetsuDevice *next = dev->next;
setsu_disconnect(setsu, dev);
dev = next;
+ continue;
}
dev = dev->next;
}
@@ -296,6 +341,8 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user)
{
+ poll_udev_monitor(setsu);
+
for(SetsuAvailDevice *adev = setsu->avail_dev; adev;)
{
if(adev->connect_dirty)
@@ -345,9 +392,12 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *u
device_event(setsu, dev, &ev, cb, user);
else if(r == LIBEVDEV_READ_STATUS_SYNC)
sync = true;
+ else if(r == -ENODEV) { break; } // device probably disconnected, udev remove event should follow soon
else
{
- SETSU_LOG("evdev poll failed\n");
+ char buf[256];
+ strerror_r(-r, buf, sizeof(buf));
+ SETSU_LOG("evdev poll failed: %s\n", buf);
break;
}
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index f9bdbab..0244cad 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -36,6 +36,9 @@ struct {
} touches[TOUCHES_MAX];
bool dirty = false;
+bool log_mode;
+
+#define LOG(...) do { if(log_mode) fprintf(stderr, __VA_ARGS__); } while(0)
void quit()
{
@@ -86,12 +89,16 @@ void event(SetsuEvent *event, void *user)
dirty = true;
switch(event->type)
{
- case SETSU_EVENT_DEVICE_ADDED:
- setsu_connect(setsu, event->path);
+ case SETSU_EVENT_DEVICE_ADDED: {
+ SetsuDevice *dev = setsu_connect(setsu, event->path);
+ LOG("Device added: %s, connect %s\n", event->path, dev ? "succeeded" : "FAILED!");
break;
+ }
case SETSU_EVENT_DEVICE_REMOVED:
+ LOG("Device removed: %s\n", event->path);
break;
case SETSU_EVENT_DOWN:
+ LOG("Down for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id);
for(size_t i=0; itype == SETSU_EVENT_UP)
+ LOG("Up for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id);
+ else
+ LOG("Position for %s, tracking id %d: %u, %u\n", setsu_device_get_path(event->dev),
+ event->tracking_id, (unsigned int)event->x, (unsigned int)event->y);
for(size_t i=0; itracking_id)
@@ -126,8 +138,25 @@ void event(SetsuEvent *event, void *user)
}
}
-int main()
+void usage(const char *prog)
{
+ printf("usage: %s [-l]\n -l log mode\n", prog);
+ exit(1);
+}
+
+int main(int argc, const char *argv[])
+{
+ log_mode = false;
+ if(argc == 2)
+ {
+ if(!strcmp(argv[1], "-l"))
+ log_mode = true;
+ else
+ usage(argv[0]);
+ }
+ else if(argc != 1)
+ usage(argv[0]);
+
memset(touches, 0, sizeof(touches));
setsu = setsu_new();
if(!setsu)
@@ -138,7 +167,7 @@ int main()
dirty = true;
while(1)
{
- if(dirty)
+ if(dirty && !log_mode)
print_state();
dirty = false;
setsu_poll(setsu, event, NULL);
From 000a125a8dc1ee7e41c9d2b65817e44b05a254a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Wed, 1 Jul 2020 20:55:26 +0200
Subject: [PATCH 045/269] Add width/height to Setsu
---
setsu/include/setsu.h | 2 ++
setsu/src/setsu.c | 14 ++++++++++++--
setsu/test/main.c | 11 +----------
3 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index 3e8b51e..a34250a 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -72,5 +72,7 @@ void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user);
SetsuDevice *setsu_connect(Setsu *setsu, const char *path);
void setsu_disconnect(Setsu *setsu, SetsuDevice *dev);
const char *setsu_device_get_path(SetsuDevice *dev);
+uint32_t setsu_device_get_width(SetsuDevice *dev);
+uint32_t setsu_device_get_height(SetsuDevice *dev);
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 6a4eb38..2e78e9a 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -308,6 +308,16 @@ const char *setsu_device_get_path(SetsuDevice *dev)
return dev->path;
}
+uint32_t setsu_device_get_width(SetsuDevice *dev)
+{
+ return dev->max_x - dev->min_x;
+}
+
+uint32_t setsu_device_get_height(SetsuDevice *dev)
+{
+ return dev->max_y - dev->min_y;
+}
+
void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
{
for(SetsuDevice *dev = setsu->dev; dev;)
@@ -477,8 +487,8 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *
{
BEGIN_EVENT(SETSU_EVENT_POSITION);
event.tracking_id = dev->slots[i].tracking_id;
- event.x = dev->slots[i].x;
- event.y = dev->slots[i].y;
+ event.x = (uint32_t)(dev->slots[i].x - dev->min_x);
+ event.y = (uint32_t)(dev->slots[i].y - dev->min_y);
SEND_EVENT();
dev->slots[i].pos_dirty = false;
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index 0244cad..41401ac 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -28,6 +28,7 @@ Setsu *setsu;
#define WIDTH 1920
#define HEIGHT 942
#define TOUCHES_MAX 8
+#define SCALE 16
struct {
bool down;
@@ -47,15 +48,6 @@ void quit()
void print_state()
{
- for(size_t i=0; i
Date: Wed, 1 Jul 2020 22:31:35 +0200
Subject: [PATCH 046/269] Build setsu from root (#267)
---
CMakeLists.txt | 33 ++++++++++++++++++++++++++++++++-
setsu/cmake/FindEvdev.cmake | 19 ++++++++-----------
setsu/cmake/FindUdev.cmake | 20 ++++++++------------
3 files changed, 48 insertions(+), 24 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 459002c..551bb58 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,11 +3,18 @@ cmake_minimum_required(VERSION 3.2)
project(chiaki)
+# Like option(), but the value can also be AUTO
+macro(tri_option name desc default)
+ set("${name}" "${default}" CACHE STRING "${desc}")
+ set_property(CACHE "${name}" PROPERTY STRINGS AUTO ON OFF)
+endmacro()
+
option(CHIAKI_ENABLE_TESTS "Enable tests for Chiaki" ON)
option(CHIAKI_ENABLE_CLI "Enable CLI for Chiaki" OFF)
option(CHIAKI_ENABLE_GUI "Enable Qt GUI" ON)
option(CHIAKI_ENABLE_ANDROID "Enable Android (Use only as part of the Gradle Project)" OFF)
option(CHIAKI_ENABLE_SWITCH "Enable Nintendo Switch (Requires devKitPro libnx)" OFF)
+tri_option(CHIAKI_ENABLE_SETSU "Enable libsetsu for touchpad input from controller" AUTO)
option(CHIAKI_LIB_ENABLE_OPUS "Use Opus as part of Chiaki Lib" ON)
option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
@@ -30,7 +37,7 @@ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
include(CPack)
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_CURRENT_SOURCE_DIR}/setsu/cmake")
# configure nintendo switch toolchain
if(CHIAKI_ENABLE_SWITCH AND CHIAKI_ENABLE_SWITCH_LINUX)
@@ -64,6 +71,30 @@ if(CHIAKI_ENABLE_CLI)
add_subdirectory(cli)
endif()
+if(CHIAKI_ENABLE_SETSU)
+ find_package(Udev)
+ find_package(Evdev)
+ if(Udev_FOUND AND Evdev_FOUND)
+ set(CHIAKI_ENABLE_SETSU ON)
+ else()
+ if(NOT CHIAKI_ENABLE_SETSU STREQUAL AUTO)
+ message(FATAL_ERROR "
+CHIAKI_ENABLE_SETSU is set to ON, but its dependencies (udev and evdev) could not be resolved.
+Keep in mind that setsu is only supported on Linux!")
+ endif()
+ set(CHIAKI_ENABLE_SETSU OFF)
+ endif()
+ if(CHIAKI_ENABLE_SETSU)
+ add_subdirectory(setsu)
+ endif()
+endif()
+
+if(CHIAKI_ENABLE_SETSU)
+ message(STATUS "Setsu enabled")
+else()
+ message(STATUS "Setsu disabled")
+endif()
+
if(CHIAKI_ENABLE_GUI)
#add_subdirectory(setsu)
add_subdirectory(gui)
diff --git a/setsu/cmake/FindEvdev.cmake b/setsu/cmake/FindEvdev.cmake
index a6be138..0703889 100644
--- a/setsu/cmake/FindEvdev.cmake
+++ b/setsu/cmake/FindEvdev.cmake
@@ -3,18 +3,15 @@
set(_prefix Evdev)
set(_target "${_prefix}::libevdev")
-find_package(PkgConfig REQUIRED)
+find_package(PkgConfig)
-pkg_check_modules("${_prefix}" libevdev)
-
-function(resolve_location)
-
-endfunction()
-
-if(${_prefix}_FOUND)
- add_library("${_target}" INTERFACE IMPORTED)
- target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
- target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+if(PkgConfig_FOUND)
+ pkg_check_modules("${_prefix}" libevdev)
+ if(${_prefix}_FOUND AND NOT TARGET "${_target}")
+ add_library("${_target}" INTERFACE IMPORTED)
+ target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
+ target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+ endif()
endif()
include(FindPackageHandleStandardArgs)
diff --git a/setsu/cmake/FindUdev.cmake b/setsu/cmake/FindUdev.cmake
index 369f806..a35b5f6 100644
--- a/setsu/cmake/FindUdev.cmake
+++ b/setsu/cmake/FindUdev.cmake
@@ -3,18 +3,14 @@
set(_prefix Udev)
set(_target "${_prefix}::libudev")
-find_package(PkgConfig REQUIRED)
-
-pkg_check_modules("${_prefix}" libudev)
-
-function(resolve_location)
-
-endfunction()
-
-if(${_prefix}_FOUND)
- add_library("${_target}" INTERFACE IMPORTED)
- target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
- target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+find_package(PkgConfig)
+if(PkgConfig_FOUND)
+ pkg_check_modules("${_prefix}" libudev)
+ if(${_prefix}_FOUND AND NOT TARGET "${_target}")
+ add_library("${_target}" INTERFACE IMPORTED)
+ target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
+ target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
+ endif()
endif()
include(FindPackageHandleStandardArgs)
From 0b9f8798eb3b6597b446ecb1c1a50ffeee9c3081 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 19:16:23 +0200
Subject: [PATCH 047/269] Add Touches to Controller State
---
lib/include/chiaki/controller.h | 25 +++++++++++++++++++++++--
lib/src/controller.c | 13 +++++++++++++
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/lib/include/chiaki/controller.h b/lib/include/chiaki/controller.h
index 0239c6c..2a870d0 100644
--- a/lib/include/chiaki/controller.h
+++ b/lib/include/chiaki/controller.h
@@ -56,6 +56,14 @@ typedef enum chiaki_controller_analog_button_t
CHIAKI_CONTROLLER_ANALOG_BUTTON_R2 = (1 << 17)
} ChiakiControllerAnalogButton;
+typedef struct chiaki_controller_touch_t
+{
+ uint16_t x, y;
+ int8_t id; // -1 = up
+} ChiakiControllerTouch;
+
+#define CHIAKI_CONTROLLER_TOUCHES_MAX 2
+
typedef struct chiaki_controller_state_t
{
/**
@@ -70,19 +78,32 @@ typedef struct chiaki_controller_state_t
int16_t left_y;
int16_t right_x;
int16_t right_y;
+
+ uint8_t touch_id_next;
+ ChiakiControllerTouch touches[CHIAKI_CONTROLLER_TOUCHES_MAX];
} ChiakiControllerState;
CHIAKI_EXPORT void chiaki_controller_state_set_idle(ChiakiControllerState *state);
static inline bool chiaki_controller_state_equals(ChiakiControllerState *a, ChiakiControllerState *b)
{
- return a->buttons == b->buttons
+ if(!(a->buttons == b->buttons
&& a->l2_state == b->l2_state
&& a->r2_state == b->r2_state
&& a->left_x == b->left_x
&& a->left_y == b->left_y
&& a->right_x == b->right_x
- && a->right_y == b->right_y;
+ && a->right_y == b->right_y))
+ return false;
+
+ for(size_t i=0; itouches[i].id != b->touches[i].id)
+ return false;
+ if(a->touches[i].id >= 0 && (a->touches[i].x != b->touches[i].x || a->touches[i].y != b->touches[i].y))
+ return false;
+ }
+ return true;
}
CHIAKI_EXPORT void chiaki_controller_state_or(ChiakiControllerState *out, ChiakiControllerState *a, ChiakiControllerState *b);
diff --git a/lib/src/controller.c b/lib/src/controller.c
index f71371c..a3853bd 100644
--- a/lib/src/controller.c
+++ b/lib/src/controller.c
@@ -39,4 +39,17 @@ CHIAKI_EXPORT void chiaki_controller_state_or(ChiakiControllerState *out, Chiaki
out->left_y = MAX_ABS(a->left_y, b->left_y);
out->right_x = MAX_ABS(a->right_x, b->right_x);
out->right_y = MAX_ABS(a->right_y, b->right_y);
+
+ out->touch_id_next = 0;
+ for(size_t i=0; itouches[i].id >= 0 ? &a->touches[i] : b->touches[i].id >= 0 ? &b->touches[i] : NULL;
+ if(!touch)
+ {
+ out->touches[i].id = -1;
+ out->touches[i].x = out->touches[i].y = 0;
+ continue;
+ }
+ out->touches[i] = *touch;
+ }
}
From 02d026f20528a30da53ef61fbbb94d0802a0c9a7 Mon Sep 17 00:00:00 2001
From: Florian Maerkl
Date: Thu, 2 Jul 2020 13:04:02 +0200
Subject: [PATCH 048/269] Add Touchpad Feedback History Formatting
---
lib/include/chiaki/feedback.h | 10 +++++++++-
lib/src/feedback.c | 11 +++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/lib/include/chiaki/feedback.h b/lib/include/chiaki/feedback.h
index 6a74ae1..19e9d7f 100644
--- a/lib/include/chiaki/feedback.h
+++ b/lib/include/chiaki/feedback.h
@@ -44,7 +44,7 @@ typedef struct chiaki_feedback_state_t
CHIAKI_EXPORT void chiaki_feedback_state_format(uint8_t *buf, ChiakiFeedbackState *state);
-#define CHIAKI_HISTORY_EVENT_SIZE_MAX 0x3 // TODO: will be bigger later for touchpad at least
+#define CHIAKI_HISTORY_EVENT_SIZE_MAX 0x5
typedef struct chiaki_feedback_history_event_t
{
@@ -58,6 +58,14 @@ typedef struct chiaki_feedback_history_event_t
*/
CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFeedbackHistoryEvent *event, uint64_t button, uint8_t state);
+/**
+ * @param pointer_id identifier for the touch from 0 to 127
+ * @param x from 0 to 1920
+ * @param y from 0 to 942
+ */
+CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
+ bool down, uint8_t pointer_id, uint16_t x, uint16_t y);
+
/**
* Ring buffer of ChiakiFeedbackHistoryEvent
*/
diff --git a/lib/src/feedback.c b/lib/src/feedback.c
index c294264..b852f7d 100644
--- a/lib/src/feedback.c
+++ b/lib/src/feedback.c
@@ -119,6 +119,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFee
return CHIAKI_ERR_SUCCESS;
}
+CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
+ bool down, uint8_t pointer_id, uint16_t x, uint16_t y)
+{
+ event->len = 5;
+ event->buf[0] = down ? 0xd0 : 0xc0;
+ event->buf[1] = pointer_id / 0x7f;
+ event->buf[2] = (uint8_t)(x >> 4);
+ event->buf[3] = (uint8_t)((x & 0xf) << 4) | (uint8_t)(y >> 8);
+ event->buf[4] = (uint8_t)y;
+}
+
CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_buffer_init(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, size_t size)
{
feedback_history_buffer->events = calloc(size, sizeof(ChiakiFeedbackHistoryEvent));
From cd3d700df832db0a509f98115de8c2357ef2c372 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 19:40:34 +0200
Subject: [PATCH 049/269] Add Touchpad to Feedback Sender
---
lib/include/chiaki/feedback.h | 2 +-
lib/src/feedback.c | 2 +-
lib/src/feedbacksender.c | 37 +++++++++++++++++++++++++++++++++--
3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/lib/include/chiaki/feedback.h b/lib/include/chiaki/feedback.h
index 19e9d7f..83cb08a 100644
--- a/lib/include/chiaki/feedback.h
+++ b/lib/include/chiaki/feedback.h
@@ -63,7 +63,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFee
* @param x from 0 to 1920
* @param y from 0 to 942
*/
-CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
+CHIAKI_EXPORT void chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
bool down, uint8_t pointer_id, uint16_t x, uint16_t y);
/**
diff --git a/lib/src/feedback.c b/lib/src/feedback.c
index b852f7d..d7a8b49 100644
--- a/lib/src/feedback.c
+++ b/lib/src/feedback.c
@@ -119,7 +119,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFee
return CHIAKI_ERR_SUCCESS;
}
-CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
+CHIAKI_EXPORT void chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHistoryEvent *event,
bool down, uint8_t pointer_id, uint16_t x, uint16_t y)
{
event->len = 5;
diff --git a/lib/src/feedbacksender.c b/lib/src/feedbacksender.c
index b812d39..2fee4b6 100644
--- a/lib/src/feedbacksender.c
+++ b/lib/src/feedbacksender.c
@@ -118,9 +118,19 @@ static void feedback_sender_send_state(ChiakiFeedbackSender *feedback_sender)
static bool controller_state_equals_for_feedback_history(ChiakiControllerState *a, ChiakiControllerState *b)
{
- return a->buttons == b->buttons
+ if(!(a->buttons == b->buttons
&& a->l2_state == b->l2_state
- && a->r2_state == b->r2_state;
+ && a->r2_state == b->r2_state))
+ return false;
+
+ for(size_t i=0; itouches[i].id != b->touches[i].id)
+ return false;
+ if(a->touches[i].id >= 0 && (a->touches[i].x != b->touches[i].x || a->touches[i].y != b->touches[i].y))
+ return false;
+ }
+ return true;
}
static void feedback_sender_send_history_packet(ChiakiFeedbackSender *feedback_sender)
@@ -189,6 +199,29 @@ static void feedback_sender_send_history(ChiakiFeedbackSender *feedback_sender)
else
CHIAKI_LOGE(feedback_sender->log, "Feedback Sender failed to format button history event for R2");
}
+
+ for(size_t i=0; itouches[i].id != state_now->touches[i].id && state_prev->touches[i].id >= 0)
+ {
+ ChiakiFeedbackHistoryEvent event;
+ chiaki_feedback_history_event_set_touchpad(&event, false, (uint8_t)state_prev->touches[i].id,
+ state_prev->touches[i].x, state_prev->touches[i].y);
+ chiaki_feedback_history_buffer_push(&feedback_sender->history_buf, &event);
+ feedback_sender_send_history_packet(feedback_sender);
+ }
+ else if(state_now->touches[i].id >= 0
+ && (state_prev->touches[i].id != state_now->touches[i].id
+ || state_prev->touches[i].x != state_now->touches[i].x
+ || state_prev->touches[i].y != state_now->touches[i].y))
+ {
+ ChiakiFeedbackHistoryEvent event;
+ chiaki_feedback_history_event_set_touchpad(&event, true, (uint8_t)state_now->touches[i].id,
+ state_now->touches[i].x, state_now->touches[i].y);
+ chiaki_feedback_history_buffer_push(&feedback_sender->history_buf, &event);
+ feedback_sender_send_history_packet(feedback_sender);
+ }
+ }
}
static bool state_cond_check(void *user)
From 7d4cbccfbf71580b971cf1d2dc4f73e2b14c500f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 19:57:36 +0200
Subject: [PATCH 050/269] Add Touch Tracking Functions to Controller State
---
lib/include/chiaki/controller.h | 9 +++++++
lib/src/controller.c | 44 +++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/include/chiaki/controller.h b/lib/include/chiaki/controller.h
index 2a870d0..258cd89 100644
--- a/lib/include/chiaki/controller.h
+++ b/lib/include/chiaki/controller.h
@@ -85,6 +85,15 @@ typedef struct chiaki_controller_state_t
CHIAKI_EXPORT void chiaki_controller_state_set_idle(ChiakiControllerState *state);
+/**
+ * @return A non-negative newly allocated touch id allocated or -1 if there are no slots left
+ */
+CHIAKI_EXPORT int8_t chiaki_controller_state_start_touch(ChiakiControllerState *state, uint16_t x, uint16_t y);
+
+CHIAKI_EXPORT void chiaki_controller_state_stop_touch(ChiakiControllerState *state, uint8_t id);
+
+CHIAKI_EXPORT void chiaki_controller_state_set_touch_pos(ChiakiControllerState *state, uint8_t id, uint16_t x, uint16_t y);
+
static inline bool chiaki_controller_state_equals(ChiakiControllerState *a, ChiakiControllerState *b)
{
if(!(a->buttons == b->buttons
diff --git a/lib/src/controller.c b/lib/src/controller.c
index a3853bd..a50cac4 100644
--- a/lib/src/controller.c
+++ b/lib/src/controller.c
@@ -17,6 +17,8 @@
#include
+#define TOUCH_ID_MASK 0x7f
+
CHIAKI_EXPORT void chiaki_controller_state_set_idle(ChiakiControllerState *state)
{
state->buttons = 0;
@@ -26,6 +28,48 @@ CHIAKI_EXPORT void chiaki_controller_state_set_idle(ChiakiControllerState *state
state->right_y = 0;
}
+CHIAKI_EXPORT int8_t chiaki_controller_state_start_touch(ChiakiControllerState *state, uint16_t x, uint16_t y)
+{
+ for(size_t i=0; itouches[i].id < 0)
+ {
+ state->touches[i].id = state->touch_id_next;
+ state->touch_id_next = (state->touch_id_next + 1) & TOUCH_ID_MASK;
+ state->touches[i].x = x;
+ state->touches[i].y = y;
+ break;
+ }
+ }
+ return -1;
+}
+
+CHIAKI_EXPORT void chiaki_controller_state_stop_touch(ChiakiControllerState *state, uint8_t id)
+{
+ for(size_t i=0; itouches[i].id == id)
+ {
+ state->touches[i].id = -1;
+ break;
+ }
+ }
+}
+
+CHIAKI_EXPORT void chiaki_controller_state_set_touch_pos(ChiakiControllerState *state, uint8_t id, uint16_t x, uint16_t y)
+{
+ id &= TOUCH_ID_MASK;
+ for(size_t i=0; itouches[i].id == id)
+ {
+ state->touches[i].x = x;
+ state->touches[i].y = y;
+ break;
+ }
+ }
+}
+
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define ABS(a) ((a) > 0 ? (a) : -(a))
#define MAX_ABS(a, b) (ABS(a) > ABS(b) ? (a) : (b))
From 699d6bb1d9c29ae91a0608c39aab7d402d65585d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 21:18:03 +0200
Subject: [PATCH 051/269] Fix Sourcehut OpenBSD Image (#268)
---
.builds/openbsd.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml
index b384168..b7f5156 100644
--- a/.builds/openbsd.yml
+++ b/.builds/openbsd.yml
@@ -1,5 +1,5 @@
-image: openbsd/latest
+image: openbsd/6.7
sources:
- https://github.com/thestr4ng3r/chiaki
From 57b0b683e80aee9a32cd4e1a89b3faaa313f348e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 21:18:12 +0200
Subject: [PATCH 052/269] Drop Support for QtGamepad
---
CMakeLists.txt | 1 -
gui/CMakeLists.txt | 10 -----
gui/include/streamsession.h | 10 -----
gui/src/streamsession.cpp | 81 -------------------------------------
scripts/appveyor.sh | 1 -
scripts/travis-build.sh | 1 -
6 files changed, 104 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 551bb58..9e3f063 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,6 @@ tri_option(CHIAKI_ENABLE_SETSU "Enable libsetsu for touchpad input from controll
option(CHIAKI_LIB_ENABLE_OPUS "Use Opus as part of Chiaki Lib" ON)
option(CHIAKI_LIB_ENABLE_MBEDTLS "Use mbedtls instead of OpenSSL as part of Chiaki Lib" OFF)
option(CHIAKI_LIB_OPENSSL_EXTERNAL_PROJECT "Use OpenSSL as CMake external project" OFF)
-option(CHIAKI_GUI_ENABLE_QT_GAMEPAD "Use QtGamepad for Input" 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)
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 072320f..210e513 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -6,12 +6,6 @@ find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Multimedia OpenGL Svg)
if(APPLE)
find_package(Qt5 REQUIRED COMPONENTS MacExtras)
endif()
-if(CHIAKI_GUI_ENABLE_QT_GAMEPAD AND CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
- message(FATAL_ERROR "Only one input method may be enabled. Disable either CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER or CHIAKI_GUI_ENABLE_QT_GAMEPAD.")
-endif()
-if(CHIAKI_GUI_ENABLE_QT_GAMEPAD)
- find_package(Qt5 REQUIRED COMPONENTS Gamepad)
-endif()
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
find_package(SDL2 MODULE REQUIRED)
endif()
@@ -85,10 +79,6 @@ if(APPLE)
target_link_libraries(chiaki Qt5::MacExtras)
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_QT_MACEXTRAS)
endif()
-if(CHIAKI_GUI_ENABLE_QT_GAMEPAD)
- target_link_libraries(chiaki Qt5::Gamepad)
- target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_QT_GAMEPAD)
-endif()
if(CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
target_link_libraries(chiaki SDL2::SDL2)
target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER)
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index 15ac4c5..b6a5b29 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -31,10 +31,6 @@
#include
#include
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
-class QGamepad;
-#endif
-
class QAudioOutput;
class QIODevice;
class QKeyEvent;
@@ -72,9 +68,6 @@ class StreamSession : public QObject
ChiakiSession session;
ChiakiOpusDecoder opus_decoder;
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- QGamepad *gamepad;
-#endif
Controller *controller;
ChiakiControllerState keyboard_state;
@@ -103,9 +96,6 @@ class StreamSession : public QObject
void SetLoginPIN(const QString &pin);
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- QGamepad *GetGamepad() { return gamepad; }
-#endif
Controller *GetController() { return controller; }
VideoDecoder *GetVideoDecoder() { return &video_decoder; }
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index bad6305..a0c85a1 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -21,11 +21,6 @@
#include
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
-#include
-#include
-#endif
-
#include
#include
@@ -53,9 +48,6 @@ static void EventCb(ChiakiEvent *event, void *user);
StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent)
: QObject(parent),
log(this, connect_info.log_level_mask, connect_info.log_file),
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- gamepad(nullptr),
-#endif
controller(nullptr),
video_decoder(connect_info.hw_decode_engine, log.GetChiakiLog()),
audio_output(nullptr),
@@ -92,9 +84,6 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
chiaki_session_set_video_sample_cb(&session, VideoSampleCb, this);
chiaki_session_set_event_cb(&session, EventCb, this);
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- connect(QGamepadManager::instance(), &QGamepadManager::connectedGamepadsChanged, this, &StreamSession::UpdateGamepads);
-#endif
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
connect(ControllerManager::GetInstance(), &ControllerManager::AvailableControllersUpdated, this, &StreamSession::UpdateGamepads);
#endif
@@ -108,9 +97,6 @@ StreamSession::~StreamSession()
chiaki_session_join(&session);
chiaki_session_fini(&session);
chiaki_opus_decoder_fini(&opus_decoder);
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- delete gamepad;
-#endif
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
delete controller;
#endif
@@ -202,46 +188,6 @@ void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
void StreamSession::UpdateGamepads()
{
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- if(!gamepad || !gamepad->isConnected())
- {
- if(gamepad)
- {
- CHIAKI_LOGI(log.GetChiakiLog(), "Gamepad %d disconnected", gamepad->deviceId());
- delete gamepad;
- gamepad = nullptr;
- }
- const auto connected_pads = QGamepadManager::instance()->connectedGamepads();
- if(!connected_pads.isEmpty())
- {
- gamepad = new QGamepad(connected_pads[0], this);
- CHIAKI_LOGI(log.GetChiakiLog(), "Gamepad %d connected: \"%s\"", connected_pads[0], gamepad->name().toLocal8Bit().constData());
- connect(gamepad, &QGamepad::buttonAChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonBChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonXChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonYChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonLeftChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonRightChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonUpChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonDownChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonL1Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonR1Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonL1Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonL2Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonL3Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonR3Changed, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonStartChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonSelectChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::buttonGuideChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::axisLeftXChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::axisLeftYChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::axisRightXChanged, this, &StreamSession::SendFeedbackState);
- connect(gamepad, &QGamepad::axisRightYChanged, this, &StreamSession::SendFeedbackState);
- }
- }
-
- SendFeedbackState();
-#endif
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(!controller || !controller->IsConnected())
{
@@ -273,33 +219,6 @@ void StreamSession::SendFeedbackState()
{
ChiakiControllerState state = {};
-#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
- if(gamepad)
- {
- state.buttons |= gamepad->buttonA() ? CHIAKI_CONTROLLER_BUTTON_CROSS : 0;
- state.buttons |= gamepad->buttonB() ? CHIAKI_CONTROLLER_BUTTON_MOON : 0;
- state.buttons |= gamepad->buttonX() ? CHIAKI_CONTROLLER_BUTTON_BOX : 0;
- state.buttons |= gamepad->buttonY() ? CHIAKI_CONTROLLER_BUTTON_PYRAMID : 0;
- state.buttons |= gamepad->buttonLeft() ? CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT : 0;
- state.buttons |= gamepad->buttonRight() ? CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT : 0;
- state.buttons |= gamepad->buttonUp() ? CHIAKI_CONTROLLER_BUTTON_DPAD_UP : 0;
- state.buttons |= gamepad->buttonDown() ? CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN : 0;
- state.buttons |= gamepad->buttonL1() ? CHIAKI_CONTROLLER_BUTTON_L1 : 0;
- state.buttons |= gamepad->buttonR1() ? CHIAKI_CONTROLLER_BUTTON_R1 : 0;
- state.buttons |= gamepad->buttonL3() ? CHIAKI_CONTROLLER_BUTTON_L3 : 0;
- state.buttons |= gamepad->buttonR3() ? CHIAKI_CONTROLLER_BUTTON_R3 : 0;
- state.buttons |= gamepad->buttonStart() ? CHIAKI_CONTROLLER_BUTTON_OPTIONS : 0;
- state.buttons |= gamepad->buttonSelect() ? CHIAKI_CONTROLLER_BUTTON_SHARE : 0;
- state.buttons |= gamepad->buttonGuide() ? CHIAKI_CONTROLLER_BUTTON_PS : 0;
- state.l2_state = (uint8_t)(gamepad->buttonL2() * 0xff);
- state.r2_state = (uint8_t)(gamepad->buttonR2() * 0xff);
- state.left_x = static_cast(gamepad->axisLeftX() * 0x7fff);
- state.left_y = static_cast(gamepad->axisLeftY() * 0x7fff);
- state.right_x = static_cast(gamepad->axisRightX() * 0x7fff);
- state.right_y = static_cast(gamepad->axisRightY() * 0x7fff);
- }
-#endif
-
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(controller)
state = controller->GetState();
diff --git a/scripts/appveyor.sh b/scripts/appveyor.sh
index 077884a..0e49286 100755
--- a/scripts/appveyor.sh
+++ b/scripts/appveyor.sh
@@ -58,7 +58,6 @@ cmake \
-DPYTHON_EXECUTABLE="$PYTHON" \
-DCHIAKI_ENABLE_TESTS=ON \
-DCHIAKI_ENABLE_CLI=OFF \
- -DCHIAKI_GUI_ENABLE_QT_GAMEPAD=OFF \
-DCHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER=ON \
.. || exit 1
diff --git a/scripts/travis-build.sh b/scripts/travis-build.sh
index e1790dd..a16ec77 100755
--- a/scripts/travis-build.sh
+++ b/scripts/travis-build.sh
@@ -6,7 +6,6 @@ cmake \
-DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \
-DCHIAKI_ENABLE_TESTS=ON \
-DCHIAKI_ENABLE_CLI=OFF \
- -DCHIAKI_GUI_ENABLE_QT_GAMEPAD=OFF \
-DCHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER=ON \
$CMAKE_EXTRA_ARGS \
.. || exit 1
From a688974c898a6412017e319089ddf1d408dfccc1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 21:37:52 +0200
Subject: [PATCH 053/269] Minor Setsu Fixes
---
setsu/include/setsu.h | 8 ++++++++
setsu/src/setsu.c | 9 +++++++++
setsu/test/main.c | 17 +++++++++++++----
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index a34250a..0303024 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -20,6 +20,10 @@
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct setsu_t Setsu;
typedef struct setsu_device_t SetsuDevice;
typedef int SetsuTrackingId;
@@ -75,4 +79,8 @@ const char *setsu_device_get_path(SetsuDevice *dev);
uint32_t setsu_device_get_width(SetsuDevice *dev);
uint32_t setsu_device_get_height(SetsuDevice *dev);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 2e78e9a..bfce543 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -116,11 +116,20 @@ Setsu *setsu_new()
void setsu_free(Setsu *setsu)
{
+ if(!setsu)
+ return;
while(setsu->dev)
setsu_disconnect(setsu, setsu->dev);
if(setsu->udev_mon)
udev_monitor_unref(setsu->udev_mon);
udev_unref(setsu->udev);
+ while(setsu->avail_dev)
+ {
+ SetsuAvailDevice *adev = setsu->avail_dev;
+ setsu->avail_dev = adev->next;
+ free(adev->path);
+ free(adev);
+ }
free(setsu);
}
diff --git a/setsu/test/main.c b/setsu/test/main.c
index 41401ac..be36535 100644
--- a/setsu/test/main.c
+++ b/setsu/test/main.c
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
Setsu *setsu;
@@ -38,12 +39,13 @@ struct {
bool dirty = false;
bool log_mode;
+volatile bool should_quit;
#define LOG(...) do { if(log_mode) fprintf(stderr, __VA_ARGS__); } while(0)
-void quit()
+void sigint(int s)
{
- setsu_free(setsu);
+ should_quit = true;
}
void print_state()
@@ -155,15 +157,22 @@ int main(int argc, const char *argv[])
printf("Failed to init setsu\n");
return 1;
}
+
+ struct sigaction sa = {0};
+ sa.sa_handler = sigint;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+
dirty = true;
- while(1)
+ while(!should_quit)
{
if(dirty && !log_mode)
print_state();
dirty = false;
setsu_poll(setsu, event, NULL);
}
- atexit(quit);
+ setsu_free(setsu);
+ printf("\nさよなら!\n");
return 0;
}
From f3be4ed22a5849fd6951a51945f24df677d3a9ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Thu, 2 Jul 2020 22:34:57 +0200
Subject: [PATCH 054/269] Integrate Setsu in GUI
---
gui/CMakeLists.txt | 4 ++
gui/include/streamsession.h | 12 +++++
gui/src/controllermanager.cpp | 3 +-
gui/src/streamsession.cpp | 95 ++++++++++++++++++++++++++++++++++-
lib/src/controller.c | 16 ++++--
5 files changed, 124 insertions(+), 6 deletions(-)
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 210e513..7072b83 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -83,6 +83,10 @@ 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)
+ target_link_libraries(chiaki setsu)
+ target_compile_definitions(chiaki PRIVATE CHIAKI_GUI_ENABLE_SETSU)
+endif()
set_target_properties(chiaki PROPERTIES
MACOSX_BUNDLE TRUE
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index b6a5b29..94399ad 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -21,6 +21,10 @@
#include
#include
+#if CHIAKI_GUI_ENABLE_SETSU
+#include
+#endif
+
#include "videodecoder.h"
#include "exception.h"
#include "sessionlog.h"
@@ -69,6 +73,11 @@ class StreamSession : public QObject
ChiakiOpusDecoder opus_decoder;
Controller *controller;
+#if CHIAKI_GUI_ENABLE_SETSU
+ Setsu *setsu;
+ QMap, uint8_t> setsu_ids;
+ ChiakiControllerState setsu_state;
+#endif
ChiakiControllerState keyboard_state;
@@ -83,6 +92,9 @@ class StreamSession : public QObject
void PushAudioFrame(int16_t *buf, size_t samples_count);
void PushVideoSample(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);
diff --git a/gui/src/controllermanager.cpp b/gui/src/controllermanager.cpp
index 224f555..2a52ea6 100644
--- a/gui/src/controllermanager.cpp
+++ b/gui/src/controllermanager.cpp
@@ -199,7 +199,8 @@ QString Controller::GetName()
ChiakiControllerState Controller::GetState()
{
- ChiakiControllerState state = {};
+ ChiakiControllerState state;
+ chiaki_controller_state_set_idle(&state);
#ifdef CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(!controller)
return state;
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index a0c85a1..dd4104a 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -27,6 +27,8 @@
#include
#include
+#define SETSU_UPDATE_INTERVAL_MS 4
+
StreamSessionConnectInfo::StreamSessionConnectInfo(Settings *settings, QString host, QByteArray regist_key, QByteArray morning)
{
key_map = settings->GetControllerMappingForDecoding();
@@ -44,6 +46,7 @@ static void AudioSettingsCb(uint32_t channels, uint32_t rate, void *user);
static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user);
static bool VideoSampleCb(uint8_t *buf, size_t buf_size, void *user);
static void EventCb(ChiakiEvent *event, void *user);
+static void SessionSetsuCb(SetsuEvent *event, void *user);
StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent)
: QObject(parent),
@@ -70,7 +73,7 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
throw ChiakiException("Morning invalid");
memcpy(chiaki_connect_info.morning, connect_info.morning.constData(), sizeof(chiaki_connect_info.morning));
- memset(&keyboard_state, 0, sizeof(keyboard_state));
+ chiaki_controller_state_set_idle(&keyboard_state);
ChiakiErrorCode err = chiaki_session_init(&session, &chiaki_connect_info, log.GetChiakiLog());
if(err != CHIAKI_ERR_SUCCESS)
@@ -88,6 +91,16 @@ StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObje
connect(ControllerManager::GetInstance(), &ControllerManager::AvailableControllersUpdated, this, &StreamSession::UpdateGamepads);
#endif
+#if CHIAKI_GUI_ENABLE_SETSU
+ chiaki_controller_state_set_idle(&setsu_state);
+ setsu = setsu_new();
+ auto timer = new QTimer(this);
+ connect(timer, &QTimer::timeout, this, [this]{
+ setsu_poll(setsu, SessionSetsuCb, this);
+ });
+ timer->start(SETSU_UPDATE_INTERVAL_MS);
+#endif
+
key_map = connect_info.key_map;
UpdateGamepads();
}
@@ -100,6 +113,9 @@ StreamSession::~StreamSession()
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
delete controller;
#endif
+#if CHIAKI_GUI_ENABLE_SETSU
+ setsu_free(setsu);
+#endif
}
void StreamSession::Start()
@@ -217,13 +233,18 @@ void StreamSession::UpdateGamepads()
void StreamSession::SendFeedbackState()
{
- ChiakiControllerState state = {};
+ ChiakiControllerState state;
+ chiaki_controller_state_set_idle(&state);
#if CHIAKI_GUI_ENABLE_SDL_GAMECONTROLLER
if(controller)
state = controller->GetState();
#endif
+#if CHIAKI_GUI_ENABLE_SETSU
+ chiaki_controller_state_or(&state, &state, &setsu_state);
+#endif
+
chiaki_controller_state_or(&state, &state, &keyboard_state);
chiaki_session_set_controller_state(&session, &state);
}
@@ -275,6 +296,8 @@ void StreamSession::Event(ChiakiEvent *event)
{
switch(event->type)
{
+ case CHIAKI_EVENT_CONNECTED:
+ break;
case CHIAKI_EVENT_QUIT:
emit SessionQuit(event->quit.reason, event->quit.reason_str ? QString::fromUtf8(event->quit.reason_str) : QString());
break;
@@ -284,6 +307,63 @@ void StreamSession::Event(ChiakiEvent *event)
}
}
+#if CHIAKI_GUI_ENABLE_SETSU
+void StreamSession::HandleSetsuEvent(SetsuEvent *event)
+{
+ if(!setsu)
+ return;
+ switch(event->type)
+ {
+ case SETSU_EVENT_DEVICE_ADDED:
+ setsu_connect(setsu, event->path);
+ break;
+ case SETSU_EVENT_DEVICE_REMOVED:
+ for(auto it=setsu_ids.begin(); it!=setsu_ids.end();)
+ {
+ if(it.key().first == event->path)
+ {
+ chiaki_controller_state_stop_touch(&setsu_state, it.value());
+ setsu_ids.erase(it++);
+ }
+ else
+ it++;
+ }
+ SendFeedbackState();
+ break;
+ case SETSU_EVENT_DOWN:
+ break;
+ case SETSU_EVENT_UP:
+ for(auto it=setsu_ids.begin(); it!=setsu_ids.end(); it++)
+ {
+ if(it.key().first == setsu_device_get_path(event->dev) && it.key().second == event->tracking_id)
+ {
+ chiaki_controller_state_stop_touch(&setsu_state, it.value());
+ setsu_ids.erase(it);
+ break;
+ }
+ }
+ SendFeedbackState();
+ break;
+ case SETSU_EVENT_POSITION: {
+ QPair k = { setsu_device_get_path(event->dev), event->tracking_id };
+ auto it = setsu_ids.find(k);
+ if(it == setsu_ids.end())
+ {
+ int8_t cid = chiaki_controller_state_start_touch(&setsu_state, event->x, event->y);
+ if(cid >= 0)
+ setsu_ids[k] = (uint8_t)cid;
+ else
+ break;
+ }
+ else
+ chiaki_controller_state_set_touch_pos(&setsu_state, it.value(), event->x, event->y);
+ SendFeedbackState();
+ break;
+ }
+ }
+}
+#endif
+
class StreamSessionPrivate
{
public:
@@ -295,6 +375,9 @@ class StreamSessionPrivate
static void PushAudioFrame(StreamSession *session, int16_t *buf, size_t samples_count) { session->PushAudioFrame(buf, samples_count); }
static void PushVideoSample(StreamSession *session, uint8_t *buf, size_t buf_size) { session->PushVideoSample(buf, buf_size); }
static void Event(StreamSession *session, ChiakiEvent *event) { session->Event(event); }
+#if CHIAKI_GUI_ENABLE_SETSU
+ static void HandleSetsuEvent(StreamSession *session, SetsuEvent *event) { session->HandleSetsuEvent(event); }
+#endif
};
static void AudioSettingsCb(uint32_t channels, uint32_t rate, void *user)
@@ -321,3 +404,11 @@ static void EventCb(ChiakiEvent *event, void *user)
auto session = reinterpret_cast(user);
StreamSessionPrivate::Event(session, event);
}
+
+#if CHIAKI_GUI_ENABLE_SETSU
+static void SessionSetsuCb(SetsuEvent *event, void *user)
+{
+ auto session = reinterpret_cast(user);
+ StreamSessionPrivate::HandleSetsuEvent(session, event);
+}
+#endif
diff --git a/lib/src/controller.c b/lib/src/controller.c
index a50cac4..222b380 100644
--- a/lib/src/controller.c
+++ b/lib/src/controller.c
@@ -22,10 +22,19 @@
CHIAKI_EXPORT void chiaki_controller_state_set_idle(ChiakiControllerState *state)
{
state->buttons = 0;
+ state->l2_state = 0;
+ state->r2_state = 0;
state->left_x = 0;
state->left_y = 0;
state->right_x = 0;
state->right_y = 0;
+ state->touch_id_next = 0;
+ for(size_t i=0; itouches[i].id = -1;
+ state->touches[i].x = 0;
+ state->touches[i].y = 0;
+ }
}
CHIAKI_EXPORT int8_t chiaki_controller_state_start_touch(ChiakiControllerState *state, uint16_t x, uint16_t y)
@@ -38,7 +47,7 @@ CHIAKI_EXPORT int8_t chiaki_controller_state_start_touch(ChiakiControllerState *
state->touch_id_next = (state->touch_id_next + 1) & TOUCH_ID_MASK;
state->touches[i].x = x;
state->touches[i].y = y;
- break;
+ return state->touches[i].id;
}
}
return -1;
@@ -87,13 +96,14 @@ CHIAKI_EXPORT void chiaki_controller_state_or(ChiakiControllerState *out, Chiaki
out->touch_id_next = 0;
for(size_t i=0; itouches[i].id >= 0 ? &a->touches[i] : b->touches[i].id >= 0 ? &b->touches[i] : NULL;
+ ChiakiControllerTouch *touch = a->touches[i].id >= 0 ? &a->touches[i] : (b->touches[i].id >= 0 ? &b->touches[i] : NULL);
if(!touch)
{
out->touches[i].id = -1;
out->touches[i].x = out->touches[i].y = 0;
continue;
}
- out->touches[i] = *touch;
+ if(touch != &out->touches[i])
+ out->touches[i] = *touch;
}
}
From e0db330924fe42a1ad372f5132f67314f841de62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 14:55:16 +0200
Subject: [PATCH 055/269] Fix Pointer Id in Feedback History
---
lib/src/feedback.c | 2 +-
lib/src/feedbacksender.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/src/feedback.c b/lib/src/feedback.c
index d7a8b49..ce9a9bf 100644
--- a/lib/src/feedback.c
+++ b/lib/src/feedback.c
@@ -124,7 +124,7 @@ CHIAKI_EXPORT void chiaki_feedback_history_event_set_touchpad(ChiakiFeedbackHist
{
event->len = 5;
event->buf[0] = down ? 0xd0 : 0xc0;
- event->buf[1] = pointer_id / 0x7f;
+ event->buf[1] = pointer_id & 0x7f;
event->buf[2] = (uint8_t)(x >> 4);
event->buf[3] = (uint8_t)((x & 0xf) << 4) | (uint8_t)(y >> 8);
event->buf[4] = (uint8_t)y;
diff --git a/lib/src/feedbacksender.c b/lib/src/feedbacksender.c
index 2fee4b6..adddd44 100644
--- a/lib/src/feedbacksender.c
+++ b/lib/src/feedbacksender.c
@@ -275,4 +275,4 @@ static void *feedback_sender_thread_func(void *user)
chiaki_mutex_unlock(&feedback_sender->state_mutex);
return NULL;
-}
\ No newline at end of file
+}
From b8f572842cc27fdafddd8541fe49ccf2081d746c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 14:56:42 +0200
Subject: [PATCH 056/269] Fix GUI build without Setsu
---
gui/src/streamsession.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index dd4104a..45cfc3a 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -46,7 +46,9 @@ static void AudioSettingsCb(uint32_t channels, uint32_t rate, void *user);
static void AudioFrameCb(int16_t *buf, size_t samples_count, void *user);
static bool VideoSampleCb(uint8_t *buf, size_t buf_size, void *user);
static void EventCb(ChiakiEvent *event, void *user);
+#if CHIAKI_GUI_ENABLE_SETSU
static void SessionSetsuCb(SetsuEvent *event, void *user);
+#endif
StreamSession::StreamSession(const StreamSessionConnectInfo &connect_info, QObject *parent)
: QObject(parent),
From 686e2a7a9b842e693e3878f2aa3caca21ff43923 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 16:00:31 +0200
Subject: [PATCH 057/269] Support Bluetooth Connection in Setsu
---
setsu/src/setsu.c | 54 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 43 insertions(+), 11 deletions(-)
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index bfce543..252d4c6 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -79,6 +79,7 @@ struct setsu_t
SetsuDevice *dev;
};
+bool get_dev_ids(const char *path, uint32_t *vendor_id, uint32_t *model_id);
static void scan_udev(Setsu *setsu);
static void update_udev_device(Setsu *setsu, struct udev_device *dev);
static SetsuDevice *connect(Setsu *setsu, const char *path);
@@ -166,25 +167,38 @@ beach:
static bool is_device_interesting(struct udev_device *dev)
{
- static const char *device_ids[] = {
+ static const uint32_t device_ids[] = {
// vendor id, model id
- "054c", "05c4", // DualShock 4 Gen 1 USB
- "054c", "09cc", // DualShock 4 Gen 2 USB
- NULL
+ 0x054c, 0x05c4, // DualShock 4 Gen 1 USB
+ 0x054c, 0x09cc // DualShock 4 Gen 2 USB
};
// Filter mouse-device (/dev/input/mouse*) away and only keep the evdev (/dev/input/event*) one:
if(!udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD_INTEGRATION"))
return false;
- const char *vendor = udev_device_get_property_value(dev, "ID_VENDOR_ID");
- const char *model = udev_device_get_property_value(dev, "ID_MODEL_ID");
- if(!vendor || !model)
- return false;
-
- for(const char **dev_id = device_ids; *dev_id; dev_id += 2)
+ uint32_t vendor;
+ uint32_t model;
+ // Try to get the ids from udev first. This fails for bluetooth.
+ const char *vendor_str = udev_device_get_property_value(dev, "ID_VENDOR_ID");
+ const char *model_str = udev_device_get_property_value(dev, "ID_MODEL_ID");
+ if(vendor_str && model_str)
{
- if(!strcmp(vendor, dev_id[0]) && !strcmp(model, dev_id[1]))
+ vendor = strtoul(vendor_str, NULL, 16);
+ model = strtoul(model_str, NULL, 16);
+ }
+ else
+ {
+ const char *path = udev_device_get_devnode(dev);
+ if(!path)
+ return false;
+ if(!get_dev_ids(path, &vendor, &model))
+ return false;
+ }
+
+ for(const uint32_t *dev_id = device_ids; (char *)dev_id != ((char *)device_ids) + sizeof(device_ids); dev_id += 2)
+ {
+ if(vendor == dev_id[0] && model == dev_id[1])
return true;
}
return false;
@@ -247,6 +261,24 @@ static void poll_udev_monitor(Setsu *setsu)
}
}
+bool get_dev_ids(const char *path, uint32_t *vendor_id, uint32_t *model_id)
+{
+ int fd = open(path, O_RDONLY | O_NONBLOCK);
+ if(fd == -1)
+ return false;
+
+ struct libevdev *evdev;
+ if(libevdev_new_from_fd(fd, &evdev) < 0)
+ {
+ close(fd);
+ return false;
+ }
+
+ *vendor_id = (uint32_t)libevdev_get_id_vendor(evdev);
+ *model_id = (uint32_t)libevdev_get_id_product(evdev);
+ return true;
+}
+
SetsuDevice *setsu_connect(Setsu *setsu, const char *path)
{
SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
From da1ca629430e56bbad308c3feaae673ffb1108cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 16:02:22 +0200
Subject: [PATCH 058/269] Rename Setsu test to demo
---
setsu/CMakeLists.txt | 10 +++++-----
setsu/{test => demo}/main.c | 0
2 files changed, 5 insertions(+), 5 deletions(-)
rename setsu/{test => demo}/main.c (100%)
diff --git a/setsu/CMakeLists.txt b/setsu/CMakeLists.txt
index 3c63a9f..90c1465 100644
--- a/setsu/CMakeLists.txt
+++ b/setsu/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.2)
project(libsetsu)
-option(SETSU_BUILD_TEST "Build testing executable for libsetsu" OFF)
+option(SETSU_BUILD_DEMO "Build testing executable for libsetsu" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@@ -17,9 +17,9 @@ find_package(Udev REQUIRED)
find_package(Evdev REQUIRED)
target_link_libraries(setsu Udev::libudev Evdev::libevdev)
-if(SETSU_BUILD_TEST)
- add_executable(setsutest
- test/main.c)
- target_link_libraries(setsutest setsu)
+if(SETSU_BUILD_DEMO)
+ add_executable(setsu-demo
+ demo/main.c)
+ target_link_libraries(setsu-demo setsu)
endif()
diff --git a/setsu/test/main.c b/setsu/demo/main.c
similarity index 100%
rename from setsu/test/main.c
rename to setsu/demo/main.c
From fd62af5b6ccba30a503e61f860986882fc3cc8b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 17:16:09 +0200
Subject: [PATCH 059/269] Fix Setsu Disconnect for evdev id check
---
setsu/src/setsu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 252d4c6..fdca7b2 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -206,8 +206,6 @@ static bool is_device_interesting(struct udev_device *dev)
static void update_udev_device(Setsu *setsu, struct udev_device *dev)
{
- if(!is_device_interesting(dev))
- return;
const char *path = udev_device_get_devnode(dev);
if(!path)
return;
@@ -232,7 +230,11 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev)
return;
}
}
+
// not yet added
+ if(!is_device_interesting(dev))
+ return;
+
SetsuAvailDevice *adev = calloc(1, sizeof(SetsuAvailDevice));
if(!adev)
return;
From 8bdf1a000328c27e80bda3e2cfb1f530fa2b4ad6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 17:23:41 +0200
Subject: [PATCH 060/269] Fix a leak in Setsu
---
setsu/src/setsu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index fdca7b2..25be3a1 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -278,6 +278,8 @@ bool get_dev_ids(const char *path, uint32_t *vendor_id, uint32_t *model_id)
*vendor_id = (uint32_t)libevdev_get_id_vendor(evdev);
*model_id = (uint32_t)libevdev_get_id_product(evdev);
+ libevdev_free(evdev);
+ close(fd);
return true;
}
From abec268ab69492899b971363813425c648f15621 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 18:18:50 +0200
Subject: [PATCH 061/269] Add Buttons to Setsu
---
setsu/demo/main.c | 17 ++++---
setsu/include/setsu.h | 27 ++++++++--
setsu/src/setsu.c | 114 +++++++++++++++++++++++++++++-------------
3 files changed, 112 insertions(+), 46 deletions(-)
diff --git a/setsu/demo/main.c b/setsu/demo/main.c
index be36535..a1167e7 100644
--- a/setsu/demo/main.c
+++ b/setsu/demo/main.c
@@ -90,7 +90,7 @@ void event(SetsuEvent *event, void *user)
case SETSU_EVENT_DEVICE_REMOVED:
LOG("Device removed: %s\n", event->path);
break;
- case SETSU_EVENT_DOWN:
+ case SETSU_EVENT_TOUCH_DOWN:
LOG("Down for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id);
for(size_t i=0; itype == SETSU_EVENT_UP)
+ case SETSU_EVENT_TOUCH_POSITION:
+ case SETSU_EVENT_TOUCH_UP:
+ if(event->type == SETSU_EVENT_TOUCH_UP)
LOG("Up for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id);
else
LOG("Position for %s, tracking id %d: %u, %u\n", setsu_device_get_path(event->dev),
@@ -115,11 +115,11 @@ void event(SetsuEvent *event, void *user)
{
switch(event->type)
{
- case SETSU_EVENT_POSITION:
+ case SETSU_EVENT_TOUCH_POSITION:
touches[i].x = event->x;
touches[i].y = event->y;
break;
- case SETSU_EVENT_UP:
+ case SETSU_EVENT_TOUCH_UP:
touches[i].down = false;
break;
default:
@@ -128,6 +128,11 @@ void event(SetsuEvent *event, void *user)
}
}
break;
+ case SETSU_EVENT_BUTTON_DOWN:
+ case SETSU_EVENT_BUTTON_UP:
+ LOG("Button for %s: %llu %s\n", setsu_device_get_path(event->dev),
+ (unsigned long long)event->button, event->type == SETSU_EVENT_BUTTON_DOWN ? "down" : "up");
+ break;
}
}
diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h
index 0303024..a83f1a1 100644
--- a/setsu/include/setsu.h
+++ b/setsu/include/setsu.h
@@ -42,17 +42,27 @@ typedef enum {
/* Touch down.
* Event will have dev and tracking_id set. */
- SETSU_EVENT_DOWN,
+ SETSU_EVENT_TOUCH_DOWN,
/* Touch down.
* Event will have dev and tracking_id set. */
- SETSU_EVENT_UP,
+ SETSU_EVENT_TOUCH_UP,
/* Touch position update.
* Event will have dev, tracking_id, x and y set. */
- SETSU_EVENT_POSITION
+ SETSU_EVENT_TOUCH_POSITION,
+
+ /* Event will have dev and button set. */
+ SETSU_EVENT_BUTTON_DOWN,
+
+ /* Event will have dev and button set. */
+ SETSU_EVENT_BUTTON_UP
} SetsuEventType;
+#define SETSU_BUTTON_0 (1u << 0)
+
+typedef uint64_t SetsuButton;
+
typedef struct setsu_event_t
{
SetsuEventType type;
@@ -62,8 +72,15 @@ typedef struct setsu_event_t
struct
{
SetsuDevice *dev;
- SetsuTrackingId tracking_id;
- uint32_t x, y;
+ union
+ {
+ struct
+ {
+ SetsuTrackingId tracking_id;
+ uint32_t x, y;
+ };
+ SetsuButton button;
+ };
};
};
} SetsuEvent;
diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c
index 25be3a1..00ab5bb 100644
--- a/setsu/src/setsu.c
+++ b/setsu/src/setsu.c
@@ -69,6 +69,9 @@ typedef struct setsu_device_t
bool pos_dirty;
} slots[SLOTS_COUNT];
unsigned int slot_cur;
+
+ uint64_t buttons_prev;
+ uint64_t buttons_cur;
} SetsuDevice;
struct setsu_t
@@ -458,6 +461,17 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *u
}
}
+static uint64_t button_from_evdev(int key)
+{
+ switch(key)
+ {
+ case BTN_LEFT:
+ return SETSU_BUTTON_0;
+ default:
+ return 0;
+ }
+}
+
static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, SetsuEventCb cb, void *user)
{
#if 0
@@ -467,43 +481,57 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev,
ev->value);
#endif
#define S dev->slots[dev->slot_cur]
- if(ev->type == EV_ABS)
+ switch(ev->type)
{
- switch(ev->code)
- {
- case ABS_MT_SLOT:
- if((unsigned int)ev->value >= SLOTS_COUNT)
- {
- SETSU_LOG("slot too high\n");
+ case EV_ABS:
+ switch(ev->code)
+ {
+ case ABS_MT_SLOT:
+ if((unsigned int)ev->value >= SLOTS_COUNT)
+ {
+ SETSU_LOG("slot too high\n");
+ break;
+ }
+ dev->slot_cur = ev->value;
break;
- }
- dev->slot_cur = ev->value;
- break;
- case ABS_MT_TRACKING_ID:
- if(S.tracking_id != -1 && S.tracking_id_prev == -1)
- {
- // up the tracking id
- S.tracking_id_prev = S.tracking_id;
- // reset the rest
- S.x = S.y = 0;
- S.pos_dirty = false;
- }
- S.tracking_id = ev->value;
- if(ev->value != -1)
- S.downed = true;
- break;
- case ABS_MT_POSITION_X:
- S.x = ev->value;
- S.pos_dirty = true;
- break;
- case ABS_MT_POSITION_Y:
- S.y = ev->value;
- S.pos_dirty = true;
+ case ABS_MT_TRACKING_ID:
+ if(S.tracking_id != -1 && S.tracking_id_prev == -1)
+ {
+ // up the tracking id
+ S.tracking_id_prev = S.tracking_id;
+ // reset the rest
+ S.x = S.y = 0;
+ S.pos_dirty = false;
+ }
+ S.tracking_id = ev->value;
+ if(ev->value != -1)
+ S.downed = true;
+ break;
+ case ABS_MT_POSITION_X:
+ S.x = ev->value;
+ S.pos_dirty = true;
+ break;
+ case ABS_MT_POSITION_Y:
+ S.y = ev->value;
+ S.pos_dirty = true;
+ break;
+ }
+ break;
+ case EV_KEY: {
+ uint64_t button = button_from_evdev(ev->code);
+ if(!button)
break;
+ if(ev->value)
+ dev->buttons_cur |= button;
+ else
+ dev->buttons_cur &= ~button;
+ break;
}
+ case EV_SYN:
+ if(ev->code == SYN_REPORT)
+ device_drain(setsu, dev, cb, user);
+ break;
}
- else if(ev->type == EV_SYN && ev->code == SYN_REPORT)
- device_drain(setsu, dev, cb, user);
#undef S
}
@@ -516,21 +544,21 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *
{
if(dev->slots[i].tracking_id_prev != -1)
{
- BEGIN_EVENT(SETSU_EVENT_UP);
+ BEGIN_EVENT(SETSU_EVENT_TOUCH_UP);
event.tracking_id = dev->slots[i].tracking_id_prev;
SEND_EVENT();
dev->slots[i].tracking_id_prev = -1;
}
if(dev->slots[i].downed)
{
- BEGIN_EVENT(SETSU_EVENT_DOWN);
+ BEGIN_EVENT(SETSU_EVENT_TOUCH_DOWN);
event.tracking_id = dev->slots[i].tracking_id;
SEND_EVENT();
dev->slots[i].downed = false;
}
if(dev->slots[i].pos_dirty)
{
- BEGIN_EVENT(SETSU_EVENT_POSITION);
+ BEGIN_EVENT(SETSU_EVENT_TOUCH_POSITION);
event.tracking_id = dev->slots[i].tracking_id;
event.x = (uint32_t)(dev->slots[i].x - dev->min_x);
event.y = (uint32_t)(dev->slots[i].y - dev->min_y);
@@ -538,6 +566,22 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *
dev->slots[i].pos_dirty = false;
}
}
+
+ uint64_t buttons_diff = dev->buttons_prev ^ dev->buttons_cur;
+ for(uint64_t i=0; i<64; i++)
+ {
+ if(buttons_diff & 1)
+ {
+ uint64_t button = 1 << i;
+ BEGIN_EVENT((dev->buttons_cur & button) ? SETSU_EVENT_BUTTON_DOWN : SETSU_EVENT_BUTTON_UP);
+ event.button = button;
+ SEND_EVENT();
+ }
+ buttons_diff >>= 1;
+ if(!buttons_diff)
+ break;
+ }
+ dev->buttons_prev = dev->buttons_cur;
#undef BEGIN_EVENT
#undef SEND_EVENT
}
From eac18f81e0695a7155618cdb8df9a717b78bc757 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Fri, 3 Jul 2020 18:23:00 +0200
Subject: [PATCH 062/269] Use Button from Setsu in GUI
---
gui/src/streamsession.cpp | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index 45cfc3a..dd4ddfd 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -332,9 +332,9 @@ void StreamSession::HandleSetsuEvent(SetsuEvent *event)
}
SendFeedbackState();
break;
- case SETSU_EVENT_DOWN:
+ case SETSU_EVENT_TOUCH_DOWN:
break;
- case SETSU_EVENT_UP:
+ case SETSU_EVENT_TOUCH_UP:
for(auto it=setsu_ids.begin(); it!=setsu_ids.end(); it++)
{
if(it.key().first == setsu_device_get_path(event->dev) && it.key().second == event->tracking_id)
@@ -346,7 +346,7 @@ void StreamSession::HandleSetsuEvent(SetsuEvent *event)
}
SendFeedbackState();
break;
- case SETSU_EVENT_POSITION: {
+ case SETSU_EVENT_TOUCH_POSITION: {
QPair k = { setsu_device_get_path(event->dev), event->tracking_id };
auto it = setsu_ids.find(k);
if(it == setsu_ids.end())
@@ -362,6 +362,12 @@ void StreamSession::HandleSetsuEvent(SetsuEvent *event)
SendFeedbackState();
break;
}
+ case SETSU_EVENT_BUTTON_DOWN:
+ setsu_state.buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
+ break;
+ case SETSU_EVENT_BUTTON_UP:
+ setsu_state.buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD;
+ break;
}
}
#endif
From 68aadd4343bae914ee09432551410639ac607358 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sat, 4 Jul 2020 12:06:14 +0200
Subject: [PATCH 063/269] Make initial udev/evdev checks QUIET
---
CMakeLists.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e3f063..f7049a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,8 +71,8 @@ if(CHIAKI_ENABLE_CLI)
endif()
if(CHIAKI_ENABLE_SETSU)
- find_package(Udev)
- find_package(Evdev)
+ find_package(Udev QUIET)
+ find_package(Evdev QUIET)
if(Udev_FOUND AND Evdev_FOUND)
set(CHIAKI_ENABLE_SETSU ON)
else()
From 736b4835dfee77e34c09faa2623612691f7c1489 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=A4rkl?=
Date: Sun, 12 Jul 2020 19:28:36 +0200
Subject: [PATCH 064/269] Add Key State Tracker
---
lib/include/chiaki/gkcrypt.h | 7 +++++
lib/src/gkcrypt.c | 16 ++++++++++
test/CMakeLists.txt | 1 +
test/keystate.c | 57 ++++++++++++++++++++++++++++++++++++
test/main.c | 8 +++++
5 files changed, 89 insertions(+)
create mode 100644 test/keystate.c
diff --git a/lib/include/chiaki/gkcrypt.h b/lib/include/chiaki/gkcrypt.h
index a2c76e7..4573810 100644
--- a/lib/include/chiaki/gkcrypt.h
+++ b/lib/include/chiaki/gkcrypt.h
@@ -96,6 +96,13 @@ static inline void chiaki_gkcrypt_free(ChiakiGKCrypt *gkcrypt)
free(gkcrypt);
}
+typedef struct chiaki_key_state_t {
+ uint64_t prev;
+} ChiakiKeyState;
+
+CHIAKI_EXPORT void chiaki_key_state_init(ChiakiKeyState *state);
+CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/src/gkcrypt.c b/lib/src/gkcrypt.c
index 0a2bc15..b398a28 100644
--- a/lib/src/gkcrypt.c
+++ b/lib/src/gkcrypt.c
@@ -542,3 +542,19 @@ static void *gkcrypt_thread_func(void *user)
chiaki_mutex_unlock(&gkcrypt->key_buf_mutex);
return NULL;
}
+
+CHIAKI_EXPORT void chiaki_key_state_init(ChiakiKeyState *state)
+{
+ state->prev = 0;
+}
+
+CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low)
+{
+ uint32_t prev_low = (uint32_t)state->prev;
+ uint32_t high = (uint32_t)(state->prev >> 32);
+ if(chiaki_seq_num_32_gt(low, prev_low) && low < prev_low)
+ high++;
+ else if(chiaki_seq_num_32_lt(low, prev_low) && low > prev_low && high)
+ high--;
+ return state->prev = (((uint64_t)high) << 32) | ((uint64_t)low);
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 52bc34a..827f4a7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -9,6 +9,7 @@ add_executable(chiaki-unit
gkcrypt.c
takion.c
seqnum.c
+ keystate.c
reorderqueue.c
fec.c
test_log.c
diff --git a/test/keystate.c b/test/keystate.c
new file mode 100644
index 0000000..97bb6f2
--- /dev/null
+++ b/test/keystate.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chiaki is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chiaki. If not, see .
+ */
+
+#include
+
+#include
+
+static MunitResult test_key_state(const MunitParameter params[], void *user)
+{
+ ChiakiKeyState state;
+ chiaki_key_state_init(&state);
+
+ uint64_t pos = chiaki_key_state_request_pos(&state, 0);
+ munit_assert_uint64(pos, ==, 0);
+ pos = chiaki_key_state_request_pos(&state, 0x1337);
+ munit_assert_uint64(pos, ==, 0x1337);
+ pos = chiaki_key_state_request_pos(&state, 0xffff0000);
+ munit_assert_uint64(pos, ==, 0xffff0000);
+ pos = chiaki_key_state_request_pos(&state, 0x1337);
+ munit_assert_uint64(pos, ==, 0x100001337);
+ pos = chiaki_key_state_request_pos(&state, 0xffff1337);
+ munit_assert_uint64(pos, ==, 0xffff1337);
+ pos = chiaki_key_state_request_pos(&state, 0x50000000);
+ munit_assert_uint64(pos, ==, 0x150000000);
+ pos = chiaki_key_state_request_pos(&state, 0xb0000000);
+ munit_assert_uint64(pos, ==, 0x1b0000000);
+ pos = chiaki_key_state_request_pos(&state, 0x00000000);
+ munit_assert_uint64(pos, ==, 0x200000000);
+
+ return MUNIT_OK;
+}
+
+MunitTest tests_key_state[] = {
+ {
+ "/key_state",
+ test_key_state,
+ NULL,
+ NULL,
+ MUNIT_TEST_OPTION_NONE,
+ NULL
+ },
+ { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
+};
diff --git a/test/main.c b/test/main.c
index 299382f..6a43def 100644
--- a/test/main.c
+++ b/test/main.c
@@ -18,6 +18,7 @@
#include