From b729ccff20af439d48f70e599d5565054b36139b Mon Sep 17 00:00:00 2001 From: rock88 Date: Mon, 4 May 2020 22:13:13 +0300 Subject: [PATCH] Improve stream quit; Start work on gamepad input... --- Makefile | 2 +- moonlight.xcodeproj/project.pbxproj | 4 +- .../xcshareddata/xcschemes/moonlight.xcscheme | 10 +- src/GameStreamClient.cpp | 21 ++++- src/GameStreamClient.hpp | 1 + src/moonlight_glfw.cpp | 11 +++ src/moonlight_libretro.c | 4 +- src/moonlight_libretro_wrapper.cpp | 49 +++++++++- src/moonlight_libretro_wrapper.h | 13 +++ src/ui/Application.cpp | 5 + src/ui/windows/AddHostWindow.cpp | 2 +- src/ui/windows/AddHostWindow.hpp | 5 - src/ui/windows/MainWindow.cpp | 6 +- src/ui/windows/StreamWindow.cpp | 92 ++++++++++++++++--- src/ui/windows/StreamWindow.hpp | 3 + 15 files changed, 186 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index cfb0362..5094d07 100755 --- a/Makefile +++ b/Makefile @@ -197,7 +197,7 @@ CXX_SOURCES = $(MOONLIGHT_LIBRETRO_CXX_SOURCES) $(NANOGUI_CXX_SOURCES) OBJECTS := $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o) DEFINES += -DNANOGUI_USE_OPENGL -DNVG_STB_IMAGE_IMPLEMENTATION -DNANOGUI_NO_GLFW \ - -DHAS_SOCKLEN_T -DHAS_POLL -DHAS_FCNTL -D_GNU_SOURCE + -DHAS_SOCKLEN_T -DHAS_POLL -DHAS_FCNTL -D_GNU_SOURCE -D__LIBRETRO__ CFLAGS += -Wall -pedantic $(fpic) -std=gnu11 $(DEFINES) CXXFLAGS += -std=gnu++17 -fno-permissive $(DEFINES) diff --git a/moonlight.xcodeproj/project.pbxproj b/moonlight.xcodeproj/project.pbxproj index ca860e7..a50f54e 100644 --- a/moonlight.xcodeproj/project.pbxproj +++ b/moonlight.xcodeproj/project.pbxproj @@ -560,6 +560,7 @@ 3652F046245C292B001FABF3 /* src */ = { isa = PBXGroup; children = ( + 3652F04E245C292B001FABF3 /* Limelight.h */, 3652F047245C292B001FABF3 /* PlatformThreads.h */, 3652F048245C292B001FABF3 /* Input.h */, 3652F049245C292B001FABF3 /* ControlStream.c */, @@ -567,7 +568,6 @@ 3652F04B245C292B001FABF3 /* Rtsp.h */, 3652F04C245C292B001FABF3 /* SimpleStun.c */, 3652F04D245C292B001FABF3 /* InputStream.c */, - 3652F04E245C292B001FABF3 /* Limelight.h */, 3652F04F245C292B001FABF3 /* RtpFecQueue.h */, 3652F050245C292B001FABF3 /* RtspConnection.c */, 3652F051245C292B001FABF3 /* ByteBuffer.h */, @@ -775,7 +775,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\nmake DEBUG=1\n"; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\n#make DEBUG=1\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/moonlight.xcodeproj/xcshareddata/xcschemes/moonlight.xcscheme b/moonlight.xcodeproj/xcshareddata/xcschemes/moonlight.xcscheme index 56df672..8068702 100644 --- a/moonlight.xcodeproj/xcshareddata/xcschemes/moonlight.xcscheme +++ b/moonlight.xcodeproj/xcshareddata/xcschemes/moonlight.xcscheme @@ -41,12 +41,8 @@ debugDocumentVersioning = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES"> - - - + - + ::failure("Firstly call connect() & pair()...")); + return; + } + + perform_async([this, address, callback] { + int status = gs_quit_app(&m_server_data[address]); + + nanogui::async([this, callback, status] { + if (status == GS_OK) { + callback(Result::success(true)); + } else { + callback(Result::failure(gs_error != NULL ? gs_error : "Unknown error...")); + } + }); + }); +} diff --git a/src/GameStreamClient.hpp b/src/GameStreamClient.hpp index 7730cf3..7a71e76 100644 --- a/src/GameStreamClient.hpp +++ b/src/GameStreamClient.hpp @@ -74,6 +74,7 @@ public: void pair(const std::string &address, const std::string &pin, ServerCallback(bool) callback); void applist(const std::string &address, ServerCallback(PAPP_LIST) callback); void start(const std::string &address, STREAM_CONFIGURATION config, int app_id, ServerCallback(STREAM_CONFIGURATION) callback); + void quit(const std::string &address, ServerCallback(bool) callback); private: GameStreamClient() {}; diff --git a/src/moonlight_glfw.cpp b/src/moonlight_glfw.cpp index 99848e9..7b0fede 100644 --- a/src/moonlight_glfw.cpp +++ b/src/moonlight_glfw.cpp @@ -4,7 +4,9 @@ #include "glsym/glsym.h" #include "Application.hpp" #include "GameStreamClient.hpp" +#include "moonlight_libretro_wrapper.h" #include "gl_render.h" +#include "libretro.h" int main(int argc, const char * argv[]) { glfwInit(); @@ -37,6 +39,15 @@ int main(int argc, const char * argv[]) { nanogui::scroll_callback_event(x, y); }); + glfwSetKeyCallback(window, [](GLFWwindow *w, int key, int scancode, int action, int mods) { + if (GLFW_KEY_A <= key && key <= GLFW_KEY_Z) { + keyboard_state[RETROK_a + key - GLFW_KEY_A] = action == GLFW_PRESS; + } + + keyboard_state[RETROK_w] ? game_pad_state.buttonFlags |= UP_FLAG : game_pad_state.buttonFlags &= ~UP_FLAG; + keyboard_state[RETROK_s] ? game_pad_state.buttonFlags |= DOWN_FLAG : game_pad_state.buttonFlags &= ~DOWN_FLAG; + }); + int width, height, fb_width, fb_height; glfwGetWindowSize(window, &width, &height); glfwGetFramebufferSize(window, &fb_width, &fb_height); diff --git a/src/moonlight_libretro.c b/src/moonlight_libretro.c index 9eaa256..63358cc 100644 --- a/src/moonlight_libretro.c +++ b/src/moonlight_libretro.c @@ -38,7 +38,7 @@ static retro_audio_sample_t audio_cb; retro_audio_sample_batch_t audio_batch_cb; static retro_environment_t environ_cb; static retro_input_poll_t input_poll_cb; -static retro_input_state_t input_state_cb; +retro_input_state_t input_state_cb; static retro_log_printf_t log_cb; void retro_init(void) { @@ -159,6 +159,8 @@ void retro_run(void) { keyboard_state[i] = input_state_cb(0, RETRO_DEVICE_KEYBOARD, 0, i); } + moonlight_libretro_wrapper_handle_game_pad(); + // Draw glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer()); diff --git a/src/moonlight_libretro_wrapper.cpp b/src/moonlight_libretro_wrapper.cpp index 7e358ea..7bf1c0e 100644 --- a/src/moonlight_libretro_wrapper.cpp +++ b/src/moonlight_libretro_wrapper.cpp @@ -1,10 +1,11 @@ #include "moonlight_libretro_wrapper.h" +#include "libretro.h" +#include "gl_render.h" #include "Application.hpp" #include "GameStreamClient.hpp" -#include "gl_render.h" -#include -#include "libretro.h" +#include "Limelight.h" #include +#include static bool moonlight_is_initialized = false; @@ -12,6 +13,9 @@ static Application* app; static std::string working_dir; int16_t keyboard_state[RETROK_LAST]; +struct GamePadState game_pad_state; + +extern retro_input_state_t input_state_cb; void moonlight_libretro_wrapper_preinit() { OpenSSL_add_all_algorithms(); @@ -32,7 +36,7 @@ void moonlight_libretro_wrapper_init(int width, int height) { nanogui::init(); app = new Application(Size(width, height), Size(width, height)); - nanogui::setup(1.0 / 60.0 * 1000); + //nanogui::setup(1.0 / 60.0 * 1000); no needs anymore? } void moonlight_libretro_wrapper_set_working_dir(const char* dir) { @@ -49,6 +53,43 @@ void moonlight_libretro_wrapper_handle_mouse_button(int button, int action, int nanogui::mouse_button_callback_event(button, action, modifiers); } +static void set_game_pad_state(short flag, int16_t state) { + if (state) { + game_pad_state.buttonFlags |= flag; + } else { + game_pad_state.buttonFlags &= ~flag; + } +} + +void moonlight_libretro_wrapper_handle_game_pad() { + game_pad_state.leftStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); + game_pad_state.leftStickY = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); + game_pad_state.rightStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X); + game_pad_state.rightStickY = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y); + + #define GAME_PAD_STATE(KEY) \ + input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, KEY) + + set_game_pad_state(UP_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_UP)); + set_game_pad_state(DOWN_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_DOWN)); + set_game_pad_state(LEFT_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_LEFT)); + set_game_pad_state(RIGHT_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_RIGHT)); + + set_game_pad_state(BACK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_SELECT)); + set_game_pad_state(PLAY_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_START)); + + set_game_pad_state(A_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_A)); + set_game_pad_state(B_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_B)); + set_game_pad_state(X_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_X)); + set_game_pad_state(Y_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_Y)); + + set_game_pad_state(LB_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_L)); + set_game_pad_state(RB_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_R)); + + set_game_pad_state(LS_CLK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_L3)); + set_game_pad_state(RS_CLK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_R3)); +} + void moonlight_libretro_wrapper_draw() { nanogui::draw(); } diff --git a/src/moonlight_libretro_wrapper.h b/src/moonlight_libretro_wrapper.h index 20ec56e..d8412de 100755 --- a/src/moonlight_libretro_wrapper.h +++ b/src/moonlight_libretro_wrapper.h @@ -9,9 +9,22 @@ EXTERN int16_t keyboard_state[]; +struct GamePadState { + short buttonFlags; + unsigned char leftTrigger; + unsigned char rightTrigger; + short leftStickX; + short leftStickY; + short rightStickX; + short rightStickY; +}; + +EXTERN struct GamePadState game_pad_state; + EXTERN void moonlight_libretro_wrapper_preinit(); EXTERN void moonlight_libretro_wrapper_init(int width, int height); EXTERN void moonlight_libretro_wrapper_set_working_dir(const char* dir); EXTERN void moonlight_libretro_wrapper_handle_mouse_move(double x, double y); EXTERN void moonlight_libretro_wrapper_handle_mouse_button(int button, int action, int modifiers); +EXTERN void moonlight_libretro_wrapper_handle_game_pad(); EXTERN void moonlight_libretro_wrapper_draw(); diff --git a/src/ui/Application.cpp b/src/ui/Application.cpp index 9534d4e..5d071e9 100644 --- a/src/ui/Application.cpp +++ b/src/ui/Application.cpp @@ -21,4 +21,9 @@ void Application::pop_window() { m_windows.back()->set_visible(true); perform_layout(); } + + if (m_windows.size() == 1) { + auto main = static_cast(m_windows.front()); + main->reload(); + } } diff --git a/src/ui/windows/AddHostWindow.cpp b/src/ui/windows/AddHostWindow.cpp index 2298260..7929f12 100644 --- a/src/ui/windows/AddHostWindow.cpp +++ b/src/ui/windows/AddHostWindow.cpp @@ -57,7 +57,7 @@ AddHostWindow::AddHostWindow(Widget *parent): ContentWindow(parent, "Add Host") loader->dispose(); if (result.isSuccess()) { - m_host_added_callback(result.value()); + this->pop(); } else { screen()->add(MessageDialog::Type::Information, "Error", result.error()); } diff --git a/src/ui/windows/AddHostWindow.hpp b/src/ui/windows/AddHostWindow.hpp index 9c8ce74..6998e81 100644 --- a/src/ui/windows/AddHostWindow.hpp +++ b/src/ui/windows/AddHostWindow.hpp @@ -5,9 +5,4 @@ class AddHostWindow: public ContentWindow { public: AddHostWindow(Widget *parent); - - void set_host_added_callback(const std::function &callback) { m_host_added_callback = callback; } - -private: - std::function m_host_added_callback; }; diff --git a/src/ui/windows/MainWindow.cpp b/src/ui/windows/MainWindow.cpp index 4dbacd0..86c7475 100644 --- a/src/ui/windows/MainWindow.cpp +++ b/src/ui/windows/MainWindow.cpp @@ -47,11 +47,7 @@ void MainWindow::reload() { auto button = container()->add