This commit is contained in:
rock88 2020-05-02 15:31:44 +03:00
parent 048fca0705
commit 93de3481e5
19 changed files with 225 additions and 103 deletions

View file

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
3602C3B7245D903000368900 /* HostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B5245D903000368900 /* HostButton.cpp */; };
361F8A3A245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */; };
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF0F245B3B00001FABF3 /* widget.cpp */; };
3652EFCE245B3B00001FABF3 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF10245B3B00001FABF3 /* common.cpp */; };
@ -104,6 +105,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
3602C3B5245D903000368900 /* HostButton.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HostButton.cpp; sourceTree = "<group>"; };
3602C3B6245D903000368900 /* HostButton.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = HostButton.hpp; sourceTree = "<group>"; };
361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = moonlight_libretro_wrapper.cpp; sourceTree = "<group>"; };
361F8A39245CB44E00A8D9C0 /* moonlight_libretro_wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = moonlight_libretro_wrapper.h; sourceTree = "<group>"; };
3652ECE8245B3AFF001FABF3 /* colorpicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorpicker.h; sourceTree = "<group>"; };
@ -547,13 +550,13 @@
36DFE0D5245A1FEC00FC51CE /* glsym */,
36DFE0CA2459FA3F00FC51CE /* nanogui_resources */,
36DFDCF12459F79000FC51CE /* ui */,
36B406962459F460005BD903 /* moonlight_glfw.cpp */,
3652F003245C28C6001FABF3 /* Server.cpp */,
3652F004245C28C6001FABF3 /* Server.hpp */,
3652F084245C6CFC001FABF3 /* libretro.h */,
3652F085245C6CFC001FABF3 /* moonlight_libretro.c */,
361F8A39245CB44E00A8D9C0 /* moonlight_libretro_wrapper.h */,
361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */,
3652F085245C6CFC001FABF3 /* moonlight_libretro.c */,
36B406962459F460005BD903 /* moonlight_glfw.cpp */,
);
path = src;
sourceTree = "<group>";
@ -603,6 +606,8 @@
3652F001245B6961001FABF3 /* AddHostWindow.hpp */,
3652F081245C60D1001FABF3 /* LoadingOverlay.cpp */,
3652F082245C60D1001FABF3 /* LoadingOverlay.hpp */,
3602C3B5245D903000368900 /* HostButton.cpp */,
3602C3B6245D903000368900 /* HostButton.hpp */,
);
path = ui;
sourceTree = "<group>";
@ -754,6 +759,7 @@
3652EFDD245B3B00001FABF3 /* texture_gl.cpp in Sources */,
3652F013245C2919001FABF3 /* http.c in Sources */,
3652F069245C292B001FABF3 /* peer.c in Sources */,
3602C3B7245D903000368900 /* HostButton.cpp in Sources */,
3652EFD0245B3B00001FABF3 /* vscrollpanel.cpp in Sources */,
3652F06D245C292B001FABF3 /* win32.c in Sources */,
3652F012245C2919001FABF3 /* mkcert.c in Sources */,

View file

@ -34,7 +34,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
launchStyle = "0"
@ -43,11 +42,8 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<PathRunnable
runnableDebuggingMode = "0"
FilePath = "/Applications/RetroArch.app">
</PathRunnable>
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "36DBDE8D2450BB7E0057C8D3"
@ -55,7 +51,7 @@
BlueprintName = "moonlight"
ReferencedContainer = "container:moonlight.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-L /Users/rock88/Documents/Projects/RetroArch/moonlight-libretro/moonlight_libretro.dylib"

View file

@ -4,50 +4,95 @@
#include <mutex>
#include <algorithm>
#include <vector>
#include <iostream>
#include <fstream>
#include <nanogui/nanogui.h>
using Task = const std::function<void()>;
using namespace std;
std::mutex m_task_mutex;
std::vector<Task> m_tasks;
std::thread m_task_thread;
using Task = const function<void()>;
mutex m_task_mutex;
vector<Task> m_tasks;
thread m_task_thread;
void perform_load_task(Task &task) {
std::lock_guard<std::mutex> guard(m_task_mutex);
lock_guard<std::mutex> guard(m_task_mutex);
m_tasks.push_back(task);
}
Server::Server() {
auto delay = std::chrono::microseconds((int64_t)(500'000));
auto delay = chrono::microseconds((int64_t)(500'000));
m_task_thread = std::thread([delay]() {
m_task_thread = thread([delay]() {
while (true) {
std::vector<Task> tasks; {
std::lock_guard<std::mutex> guard(m_task_mutex);
tasks = std::vector(m_tasks);
vector<Task> tasks; {
lock_guard<mutex> guard(m_task_mutex);
tasks = vector(m_tasks);
m_tasks.clear();
}
for (auto task: tasks) {
task();
}
std::this_thread::sleep_for(delay);
this_thread::sleep_for(delay);
}
}
);
}
void Server::connect(std::string address, ServerCallback<SERVER_DATA> &callback) {
perform_load_task([address, callback] {
void Server::add_host(string address) {
if (find(m_hosts.begin(), m_hosts.end(), address) == m_hosts.end()) {
m_hosts.push_back(address);
}
ofstream file(m_working_dir + "/hosts.txt");
for (auto host: m_hosts) {
file << host << endl;
}
file.close();
}
vector<string> Server::hosts() {
if (!m_hosts.empty()) {
return m_hosts;
}
ifstream in(m_working_dir + "/hosts.txt");
if (!in) {
return {};
}
string str;
while (getline(in, str)) {
if (str.size() > 0)
m_hosts.push_back(str);
}
in.close();
return m_hosts;
}
void Server::connect(string address, ServerCallback<SERVER_DATA> &callback) {
perform_load_task([this, address, callback] {
SERVER_DATA data;
int status = gs_init(&data, (char *)address.c_str(), "/Users/rock88/Documents/Projects/RetroArch/moonlight-libretro/key", 0, false);
int status = gs_init(&data, (char *)address.c_str(), (m_working_dir + "/key").c_str(), 0, false);
nanogui::async([address, callback, data, status] {
SERVER_DATA copy(data);
nanogui::async([address, callback, &data, status] {
if (status == GS_OK) {
callback(Result<SERVER_DATA>::success(&data));
callback(Result<SERVER_DATA>::success(&copy));
//free(data);
} else {
if (gs_error != NULL) {
callback(Result<SERVER_DATA>::failure(gs_error));
} else {
callback(Result<SERVER_DATA>::failure("Unknown error..."));
}
}
});
});

View file

@ -1,4 +1,5 @@
#include <string>
#include <vector>
extern "C" {
#include "client.h"
@ -48,16 +49,23 @@ template<class T> using ServerCallback = const std::function<void(Result<T>)>;
class Server {
public:
static Server server() {
static Server* server = NULL;
if (server == NULL) {
server = new Server();
static Server* server() {
static Server server;
return &server;
}
return *server;
void set_working_dir(const std::string &dir) {
m_working_dir = std::string(dir + "/moonlight");
}
void add_host(std::string address);
std::vector<std::string> hosts();
void connect(std::string address, ServerCallback<SERVER_DATA> &callback);
private:
Server();
std::string m_working_dir;
std::vector<std::string> m_hosts;
};

View file

@ -3,6 +3,7 @@
#include <GLFW/glfw3.h>
#include "glsym/glsym.h"
#include "Application.hpp"
#include "Server.hpp"
int main(int argc, const char * argv[]) {
glfwInit();
@ -33,26 +34,22 @@ int main(int argc, const char * argv[]) {
glfwGetWindowSize(window, &width, &height);
glfwGetFramebufferSize(window, &fb_width, &fb_height);
Server::server()->set_working_dir("/Users/rock88/Documents/RetroArch/system");
nanogui::init();
nanogui::ref<Application> app = new Application(Size(width, height), Size(fb_width, fb_height));
nanogui::setup(1.0 / 60.0);
nanogui::setup(1.0 / 60.0 * 1000);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
nanogui::draw();
//glfwGetWindowSize(win, &width, &height);
//glViewport(0, 0, width, height);
//glClear(GL_COLOR_BUFFER_BIT);
//glfwWaitEvents();
glfwSwapBuffers(window);
}
return 0;

View file

@ -133,39 +133,28 @@ void retro_run(void) {
double mouse_x = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
double mouse_y = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
double pointer_x = 0;
double pointer_y = 0;
// if (mouse_x == 0 && mouse_y == 0) {
// int pointer_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
// int pointer_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
//
// if (pointer_x != 0 && pointer_y != 0) {
// mouse_x = (pointer_x / 32768.0f + 1) / 2 * width;
// mouse_y = (pointer_y / 32768.0f + 1) / 2 * height;
// }
// }
// TODO: Pointers in MacBook currently work incorrectly...
if (input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) {
int p_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
int p_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
//int px=(int)((float)retro.width/854.0*(float)p_x);
//int py=(int)((float)retro.height/480.0*(float)p_y);
mouse_x=(int)((p_x+0x7fff)*width/0xffff);
mouse_y=(int)((p_y+0x7fff)*height/0xffff);
pointer_x = (p_x + 0x7fff) * width / 0xffff;
pointer_y = (p_y + 0x7fff) * height / 0xffff;
}
if (mouse_x != 0 && mouse_y != 0) {
moonlight_libretro_wrapper_handle_mouse_move(mouse_x, mouse_y);
}
last_mouse_x = mouse_x;
last_mouse_y = mouse_y;
static bool mouse_l_pressed = false;
if (input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) && !mouse_l_pressed) {
if (pointer_x != 0 && pointer_y != 0) {
moonlight_libretro_wrapper_handle_mouse_move(pointer_x, pointer_y);
}
mouse_l_pressed = true;
moonlight_libretro_wrapper_handle_mouse_button(0, 1, 0);
} else if (!input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) && mouse_l_pressed) {
@ -177,7 +166,6 @@ void retro_run(void) {
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
glViewport(0, 0, width, height);
moonlight_libretro_wrapper_draw();
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);

View file

@ -1,5 +1,6 @@
#include "moonlight_libretro_wrapper.h"
#include "Application.hpp"
#include "Server.hpp"
#include <openssl/ssl.h>
#include <curl/curl.h>
@ -23,17 +24,15 @@ void moonlight_libretro_wrapper_init(int width, int height) {
nanogui::setup(1.0 / 60.0);
}
void moonlight_libretro_wrapper_set_working_dir(char* dir) {
void moonlight_libretro_wrapper_set_working_dir(const char* dir) {
Server::server()->set_working_dir(dir);
}
void moonlight_libretro_wrapper_handle_mouse_move(double x, double y) {
//printf("mouse_move: %fx%f\n", x, y);
nanogui::cursor_pos_callback_event(x, y);
}
void moonlight_libretro_wrapper_handle_mouse_button(int button, int action, int modifiers) {
//printf("mouse_button: %i x %i\n", button, action);
nanogui::mouse_button_callback_event(button, action, modifiers);
}

View file

@ -7,7 +7,7 @@
#endif
EXTERN void moonlight_libretro_wrapper_init(int width, int height);
EXTERN void moonlight_libretro_wrapper_set_working_dir(char* dir);
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_draw();

View file

@ -37,6 +37,7 @@ AddHostWindow::AddHostWindow(Widget *parent): ContentWindow(parent, "Add Host")
auto backspace = other_buttons_container->add<Button>("");
backspace->set_icon(FA_BACKSPACE);
backspace->set_icon_extra_scale(2);
backspace->set_fixed_size(Size(210, 100));
backspace->set_callback([text] {
if (text->value().size() > 0) {
@ -52,14 +53,14 @@ AddHostWindow::AddHostWindow(Widget *parent): ContentWindow(parent, "Add Host")
if (text->value().size() > 0) {
auto loader = add<LoadingOverlay>();
Server::server().connect(text->value(), [this, loader](auto result) {
Server::server()->connect(text->value(), [this, loader](auto result) {
loader->dispose();
if (result.isSuccess()) {
printf("Pair: %i\n", result.value()->paired);
Server::server()->add_host(result.value()->serverInfo.address);
m_host_added_callback(*result.value());
} else {
screen()->add<MessageDialog>(MessageDialog::Type::Information, "Error", result.error());
printf("Error: %s\n", result.error().c_str());
}
});
}

View file

@ -5,24 +5,10 @@
using namespace nanogui;
Application::Application(Vector2f size, Vector2f framebuffer_size): Screen(size, framebuffer_size) {
auto main = push_window<MainWindow>();
main->set_add_host_callback([this] {
this->push_window<AddHostWindow>();
});
}
theme()->m_button_font_size = 24;
theme()->m_text_box_font_size = 34;
template<typename WidgetClass, typename... Args>
WidgetClass* Application::push_window(const Args&... args) {
for (auto window: m_windows) {
window->set_visible(false);
}
auto window = new WidgetClass(this, args...);
window->set_size(size());
window->set_fixed_size(size());
m_windows.push_back(window);
perform_layout();
return window;
push_window<MainWindow>();
}
void Application::pop_window() {

View file

@ -1,15 +1,28 @@
#include <nanogui/nanogui.h>
#include "ContentWindow.hpp"
#pragma once
#define Size(x, y) (nanogui::Vector2f((x), (y)))
class Application: public nanogui::Screen {
public:
Application(nanogui::Vector2f size, nanogui::Vector2f framebuffer_size);
template<typename WidgetClass, typename... Args>
WidgetClass* push_window(const Args&... args);
WidgetClass* push_window(const Args&... args) {
for (auto window: m_windows) {
window->set_visible(false);
}
auto window = new WidgetClass(this, args...);
window->set_size(size());
window->set_fixed_size(size());
m_windows.push_back(window);
perform_layout();
return window;
}
void pop_window();
private:
std::vector<ContentWindow *> m_windows;
std::vector<Widget *> m_windows;
};

View file

@ -60,6 +60,5 @@ void ContentWindow::set_left_title_button(int icon, const std::function<void()>
}
void ContentWindow::pop() {
auto app = static_cast<Application *>(screen());
app->pop_window();
application()->pop_window();
}

View file

@ -1,8 +1,7 @@
#include <nanogui/nanogui.h>
#include "Application.hpp"
#pragma once
#define Size(x, y) (nanogui::Vector2f((x), (y)))
class ContentWindow: public nanogui::Widget {
public:
ContentWindow(Widget *parent, const std::string& title);
@ -22,7 +21,12 @@ public:
return m_container;
}
void set_box_layout(nanogui::Orientation orientation, nanogui::Alignment alignment = nanogui::Alignment::Middle, int margin = 0, int spacing = 0) {
Application* application() {
auto application = static_cast<Application *>(screen());
return application;
}
void set_box_layout(nanogui::Orientation orientation, nanogui::Alignment alignment = nanogui::Alignment::Middle, int margin = 10, int spacing = 10) {
m_container->set_layout(new nanogui::BoxLayout(orientation, alignment, margin, spacing));
}

32
src/ui/HostButton.cpp Normal file
View file

@ -0,0 +1,32 @@
#include "HostButton.hpp"
#include "Server.hpp"
using namespace nanogui;
HostButton::HostButton(Widget* parent, const std::string &host): Button(parent, "", FA_QUESTION) {
m_host = host;
m_data.paired = false;
set_icon_extra_scale(2);
set_icon_position(IconPosition::LeftCentered);
set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle));
add<Widget>()->set_fixed_height(80);
add<Label>(host);
Server::server()->connect(host, [this](auto result) {
if (result.isSuccess()) {
m_data = *result.value();
if (m_data.paired) {
set_icon(FA_CHECK);
} else {
set_icon(FA_EXCLAMATION);
}
}
});
}
void HostButton::draw(NVGcontext *ctx) {
Button::draw(ctx);
Widget::draw(ctx);
}

18
src/ui/HostButton.hpp Normal file
View file

@ -0,0 +1,18 @@
#include <nanogui/nanogui.h>
#include "Server.hpp"
#pragma once
class HostButton: public nanogui::Button {
public:
HostButton(Widget* parent, const std::string &host);
SERVER_DATA server_data() {
return m_data;
}
void draw(NVGcontext *ctx) override;
private:
std::string m_host;
SERVER_DATA m_data;
};

View file

@ -3,8 +3,11 @@
using namespace nanogui;
LoadingOverlay::LoadingOverlay(Widget* parent): Widget(parent->screen()) {
LoadingOverlay::LoadingOverlay(Widget* parent, const std::string &caption): Widget(parent->screen()) {
set_fixed_size(parent->screen()->size());
set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle));
add<Widget>()->set_fixed_height(fixed_height() / 2 - 60);
add<Label>(caption)->set_font_size(24);
m_icon = FA_SPINNER;
screen()->perform_layout();
@ -33,6 +36,8 @@ void LoadingOverlay::draw(NVGcontext *ctx) {
nvgText(ctx, 0, 0, utf8(m_icon).data(), NULL);
nvgRestore(ctx);
Widget::draw(ctx);
}
bool LoadingOverlay::mouse_enter_event(const nanogui::Vector2i &p, bool enter) {

View file

@ -3,7 +3,7 @@
class LoadingOverlay: public nanogui::Widget {
public:
LoadingOverlay(nanogui::Widget* parent);
LoadingOverlay(nanogui::Widget* parent, const std::string &caption = "");
void draw(NVGcontext *ctx) override;

View file

@ -1,13 +1,41 @@
#include "MainWindow.hpp"
#include "AddHostWindow.hpp"
#include "HostButton.hpp"
#include "Server.hpp"
#include "LoadingOverlay.hpp"
using namespace nanogui;
MainWindow::MainWindow(Widget *parent): ContentWindow(parent, "Moonlight") {
set_box_layout(Orientation::Horizontal, Alignment::Minimum, 10, 10);
set_box_layout(Orientation::Horizontal, Alignment::Minimum);
reload();
}
void MainWindow::reload() {
for (auto child: container()->children()) {
container()->remove_child(child);
}
for (auto host: Server::server()->hosts()) {
auto button = container()->add<HostButton>(host);
button->set_fixed_size(Size(100, 100));
button->set_callback([this, button] {
if (button->server_data().paired) {
} else {
add<LoadingOverlay>("Pairing...");
}
});
}
auto button = container()->add<Button>("Add Host");
button->set_fixed_size(Size(100, 100));
button->set_callback([this] {
this->m_add_host_callback();
auto add_host = application()->push_window<AddHostWindow>();
add_host->set_host_added_callback([this](auto _) {
this->reload();
this->application()->pop_window();
});
});
}

View file

@ -5,8 +5,5 @@ class MainWindow: public ContentWindow {
public:
MainWindow(Widget *parent);
void set_add_host_callback(const std::function<void()> &callback) { m_add_host_callback = callback; }
private:
std::function<void()> m_add_host_callback;
void reload();
};