diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index f40070cc8f..a0374ad19b 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -41,7 +41,7 @@ struct InputSubsystem::Impl { sdl = SDL::Init(); #endif - auto udp = std::make_shared(); + udp = std::make_shared(); udpmotion = std::make_shared(udp); Input::RegisterFactory("cemuhookudp", udpmotion); udptouch = std::make_shared(udp); @@ -80,8 +80,8 @@ struct InputSubsystem::Impl { auto sdl_devices = sdl->GetInputDevices(); devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end()); #endif - //auto udp_devices = udp->GetInputDevices(); - //devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); + auto udp_devices = udp->GetInputDevices(); + devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); return devices; } @@ -128,6 +128,7 @@ struct InputSubsystem::Impl { std::shared_ptr gcanalog; std::shared_ptr udpmotion; std::shared_ptr udptouch; + std::shared_ptr udp; }; InputSubsystem::InputSubsystem() : impl{std::make_unique()} {} diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index a4a267d5b2..d5f4577ad8 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp @@ -8,6 +8,7 @@ #include #include #include "common/logging/log.h" +#include "core/settings.h" #include "input_common/udp/client.h" #include "input_common/udp/protocol.h" @@ -133,7 +134,8 @@ Client::Client() { LOG_INFO(Input, "Udp Initialization started"); for (std::size_t client = 0; client < clients.size(); client++) { u8 pad = client % 4; - StartCommunication(client, DEFAULT_ADDR, DEFAULT_PORT, pad, 24872); + StartCommunication(client, Settings::values.udp_input_address, + Settings::values.udp_input_port, pad, 24872); // Set motion parameters // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode // Real HW values are unkown, 0.0006 is an aproximate to Standard @@ -145,6 +147,37 @@ Client::~Client() { Reset(); } +std::vector Client::GetInputDevices() const { + std::vector devices; + for (std::size_t client = 0; client < clients.size(); client++) { + if (!DeviceConnected(client)) { + continue; + } + std::string name = fmt::format("UDP Controller{} {} {}", clients[client].active, + clients[client].active == 1, client); + devices.emplace_back(Common::ParamPackage{ + {"class", "cemuhookudp"}, + {"display", std::move(name)}, + {"port", std::to_string(client)}, + }); + } + return devices; +} + +bool Client::DeviceConnected(std::size_t pad) const { + // Use last timestamp to detect if the socket has stopped sending data + const auto now = std::chrono::system_clock::now(); + u64 time_difference = + std::chrono::duration_cast(now - clients[pad].last_motion_update) + .count(); + return time_difference < 1000 && clients[pad].active == 1; +} + +void Client::ReloadUDPClient() { + for (std::size_t client = 0; client < clients.size(); client++) { + ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client); + } +} void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) { // client number must be determined from host / port and pad index std::size_t client = pad_index; @@ -172,6 +205,7 @@ void Client::OnPadData(Response::PadData data) { clients[client].packet_sequence, data.packet_counter); return; } + clients[client].active = data.info.is_pad_active; clients[client].packet_sequence = data.packet_counter; const auto now = std::chrono::system_clock::now(); u64 time_difference = std::chrono::duration_cast( @@ -239,8 +273,8 @@ void Client::Reset() { } } -void Client::UpdateYuzuSettings(std::size_t client, Common::Vec3 acc, - Common::Vec3 gyro, bool touch) { +void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3& acc, + const Common::Vec3& gyro, bool touch) { if (configuring) { UDPPadStatus pad; if (touch) { @@ -276,11 +310,11 @@ void Client::EndConfiguration() { configuring = false; } -DeviceStatus& Client::GetPadState(std::string ip, std::size_t port, std::size_t pad) { +DeviceStatus& Client::GetPadState(std::size_t pad) { return clients[pad].status; } -const DeviceStatus& Client::GetPadState(std::string ip, std::size_t port, std::size_t pad) const { +const DeviceStatus& Client::GetPadState(std::size_t pad) const { return clients[pad].status; } diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h index 798e3e0790..92136b8c47 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/udp/client.h @@ -12,6 +12,7 @@ #include #include #include "common/common_types.h" +#include "common/param_package.h" #include "common/thread.h" #include "common/threadsafe_queue.h" #include "common/vector_math.h" @@ -31,9 +32,9 @@ struct Version; } // namespace Response enum class PadMotion { - GyrX, - GyrY, - GyrZ, + GyroX, + GyroY, + GyroZ, AccX, AccY, AccZ, @@ -70,30 +71,36 @@ struct DeviceStatus { class Client { public: - /// Initialize the UDP client capture and read sequence + // Initialize the UDP client capture and read sequence Client(); - /// Close and relase the client + // Close and release the client ~Client(); - /// Used for polling + + // Used for polling void BeginConfiguration(); void EndConfiguration(); + std::vector GetInputDevices() const; + + bool DeviceConnected(std::size_t pad) const; + void ReloadUDPClient(); void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0, u32 client_id = 24872); std::array, 4>& GetPadQueue(); const std::array, 4>& GetPadQueue() const; - DeviceStatus& GetPadState(std::string ip, std::size_t port, std::size_t pad); - const DeviceStatus& GetPadState(std::string ip, std::size_t port, std::size_t pad) const; + DeviceStatus& GetPadState(std::size_t pad); + const DeviceStatus& GetPadState(std::size_t pad) const; private: - struct Clients { + struct ClientData { std::unique_ptr socket; DeviceStatus status; std::thread thread; u64 packet_sequence = 0; + u8 active; // Realtime values // motion is initalized with PID values for drift correction on joycons @@ -101,21 +108,20 @@ private: std::chrono::time_point last_motion_update; }; - /// For shutting down, clear all data, join all threads, release usb + // For shutting down, clear all data, join all threads, release usb void Reset(); - // void UpdateOrientation(Joycon& jc, u64 time, std::size_t iteration); void OnVersion(Response::Version); void OnPortInfo(Response::PortInfo); void OnPadData(Response::PadData); void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index, u32 client_id); - void UpdateYuzuSettings(std::size_t client, Common::Vec3 acc, Common::Vec3 gyro, - bool touch); + void UpdateYuzuSettings(std::size_t client, const Common::Vec3& acc, + const Common::Vec3& gyro, bool touch); bool configuring = false; - std::array clients; + std::array clients; std::array, 4> pad_queue; }; diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp index c2322f05a4..a0afaf2d21 100644 --- a/src/input_common/udp/udp.cpp +++ b/src/input_common/udp/udp.cpp @@ -13,7 +13,7 @@ namespace InputCommon { -class UDPMotion final : public Input::RealMotionDevice { +class UDPMotion final : public Input::MotionDevice { public: UDPMotion(std::string ip_, int port_, int pad_, InputCommon::CemuhookUDP::Client* client_) : ip(ip_), port(port_), pad(pad_), client(client_) {} @@ -21,7 +21,7 @@ public: std::tuple, Common::Vec3, Common::Vec3, std::array> GetStatus() const override { - return client->GetPadState(ip, port, pad).motion_status; + return client->GetPadState(pad).motion_status; } private: @@ -41,8 +41,7 @@ UDPMotionFactory::UDPMotionFactory(std::shared_ptr UDPMotionFactory::Create( - const Common::ParamPackage& params) { +std::unique_ptr UDPMotionFactory::Create(const Common::ParamPackage& params) { const std::string ip = params.Get("ip", "127.0.0.1"); const int port = params.Get("port", 26760); const int pad = params.Get("pad_index", 0); @@ -84,10 +83,10 @@ Common::ParamPackage UDPMotionFactory::GetNextInput() { class UDPTouch final : public Input::TouchDevice { public: UDPTouch(std::string ip_, int port_, int pad_, InputCommon::CemuhookUDP::Client* client_) - : ip(ip_), port(port_), pad(pad_), client(client_) {} + : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} std::tuple GetStatus() const override { - return client->GetPadState(ip, port, pad).touch_status; + return client->GetPadState(pad).touch_status; } private: diff --git a/src/input_common/udp/udp.h b/src/input_common/udp/udp.h index 78ba3de983..fdba4a4175 100644 --- a/src/input_common/udp/udp.h +++ b/src/input_common/udp/udp.h @@ -11,11 +11,11 @@ namespace InputCommon { /// A motion device factory that creates motion devices from udp clients -class UDPMotionFactory final : public Input::Factory { +class UDPMotionFactory final : public Input::Factory { public: explicit UDPMotionFactory(std::shared_ptr client_); - std::unique_ptr Create(const Common::ParamPackage& params) override; + std::unique_ptr Create(const Common::ParamPackage& params) override; Common::ParamPackage GetNextInput(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 2acf1dc278..2be19d0f3b 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -17,8 +17,8 @@ #include "core/hle/service/hid/hid.h" #include "core/hle/service/sm/sm.h" #include "input_common/gcadapter/gc_poller.h" -#include "input_common/udp/udp.h" #include "input_common/main.h" +#include "input_common/udp/udp.h" #include "ui_configure_input_player.h" #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input_player.h"