mirror of
https://github.com/rock88/moonlight-nx
synced 2024-11-10 06:14:15 +00:00
UI fixes and refactoring...
This commit is contained in:
parent
934bda43dc
commit
c457e48f6c
15 changed files with 99 additions and 77 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "BoxArtManager.hpp"
|
||||
#include "Settings.hpp"
|
||||
#include "Data.hpp"
|
||||
#include "nanovg.h"
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
#include "Singleton.hpp"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "Data.hpp"
|
||||
#pragma once
|
||||
|
||||
struct NVGcontext;
|
||||
struct Data;
|
||||
|
||||
class BoxArtManager {
|
||||
class BoxArtManager: public Singleton<BoxArtManager> {
|
||||
public:
|
||||
static BoxArtManager* manager() {
|
||||
static BoxArtManager manager;
|
||||
return &manager;
|
||||
}
|
||||
|
||||
bool has_boxart(int app_id);
|
||||
|
||||
void set_data(Data data, int app_id);
|
||||
|
@ -21,8 +17,6 @@ public:
|
|||
int texture_id(int app_id);
|
||||
|
||||
private:
|
||||
BoxArtManager() {};
|
||||
|
||||
std::map<int, bool> m_has_boxart;
|
||||
std::map<int, int> m_texture_handle;
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
GLFWgamepadstate glfw_gamepad_state;
|
||||
int moonlight_exit = 0;
|
||||
|
||||
int m_width, m_height, m_fb_width, m_fb_height;
|
||||
static int m_width, m_height, m_fb_width, m_fb_height;
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
glfwInit();
|
||||
|
@ -63,6 +63,8 @@ int main(int argc, const char * argv[]) {
|
|||
nanogui::window_resize_callback_event(width, height, m_fb_width, m_fb_height);
|
||||
});
|
||||
|
||||
GameStreamClient::instance().start();
|
||||
|
||||
MouseController::instance().init(window);
|
||||
KeyboardController::instance().init(window);
|
||||
|
||||
|
@ -93,7 +95,7 @@ int main(int argc, const char * argv[]) {
|
|||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
GameStreamClient::client()->stop();
|
||||
GameStreamClient::instance().stop();
|
||||
nanogui::leave();
|
||||
nanogui::shutdown();
|
||||
glfwDestroyWindow(window);
|
||||
|
|
|
@ -63,7 +63,7 @@ void perform_async(std::function<void()> task) {
|
|||
m_tasks.push_back(task);
|
||||
}
|
||||
|
||||
GameStreamClient::GameStreamClient() {
|
||||
void GameStreamClient::start() {
|
||||
start_task_loop();
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ void GameStreamClient::stop() {
|
|||
|
||||
void GameStreamClient::wake_up_host(const Host &host, ServerCallback<bool> callback) {
|
||||
perform_async([this, host, callback] {
|
||||
if (WakeOnLanManager::manager()->wake_up_host(host)) {
|
||||
if (WakeOnLanManager::instance().wake_up_host(host)) {
|
||||
usleep(5'000'000);
|
||||
nanogui::async([callback] { callback(GSResult<bool>::success(true)); });
|
||||
} else {
|
||||
|
@ -128,22 +128,31 @@ void GameStreamClient::pair(const std::string &address, const std::string &pin,
|
|||
});
|
||||
}
|
||||
|
||||
void GameStreamClient::applist(const std::string &address, ServerCallback<PAPP_LIST> callback) {
|
||||
void GameStreamClient::applist(const std::string &address, ServerCallback<AppInfoList> callback) {
|
||||
if (m_server_data.count(address) == 0) {
|
||||
callback(GSResult<PAPP_LIST>::failure("Firstly call connect() & pair()..."));
|
||||
callback(GSResult<AppInfoList>::failure("Firstly call connect() & pair()..."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_app_list[address] = PAPP_LIST();
|
||||
|
||||
perform_async([this, address, callback] {
|
||||
int status = gs_applist(&m_server_data[address], &m_app_list[address]);
|
||||
PAPP_LIST list;
|
||||
|
||||
nanogui::async([this, address, callback, status] {
|
||||
int status = gs_applist(&m_server_data[address], &list);
|
||||
|
||||
AppInfoList app_list;
|
||||
|
||||
while (list) {
|
||||
app_list.push_back({ .name = list->name, .app_id = list->id });
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
std::sort(app_list.begin(), app_list.end(), [](AppInfo a, AppInfo b) { return a.name < b.name; });
|
||||
|
||||
nanogui::async([this, app_list, callback, status] {
|
||||
if (status == GS_OK) {
|
||||
callback(GSResult<PAPP_LIST>::success(m_app_list[address]));
|
||||
callback(GSResult<AppInfoList>::success(app_list));
|
||||
} else {
|
||||
callback(GSResult<PAPP_LIST>::failure(gs_error()));
|
||||
callback(GSResult<AppInfoList>::failure(gs_error()));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "Singleton.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
@ -49,31 +50,31 @@ template<class T> using ServerCallback = const std::function<void(GSResult<T>)>;
|
|||
|
||||
struct Host;
|
||||
|
||||
class GameStreamClient {
|
||||
public:
|
||||
static GameStreamClient* client() {
|
||||
static GameStreamClient client;
|
||||
return &client;
|
||||
}
|
||||
struct AppInfo {
|
||||
std::string name;
|
||||
int app_id;
|
||||
};
|
||||
|
||||
using AppInfoList = std::vector<AppInfo>;
|
||||
|
||||
class GameStreamClient: public Singleton<GameStreamClient> {
|
||||
public:
|
||||
SERVER_DATA server_data(const std::string &address) {
|
||||
return m_server_data[address];
|
||||
}
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void wake_up_host(const Host &host, ServerCallback<bool> callback);
|
||||
void connect(const std::string &address, ServerCallback<SERVER_DATA> callback);
|
||||
void pair(const std::string &address, const std::string &pin, ServerCallback<bool> callback);
|
||||
void applist(const std::string &address, ServerCallback<PAPP_LIST> callback);
|
||||
void applist(const std::string &address, ServerCallback<AppInfoList> callback);
|
||||
void app_boxart(const std::string &address, int app_id, ServerCallback<Data> 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();
|
||||
|
||||
std::map<std::string, SERVER_DATA> m_server_data;
|
||||
std::map<std::string, PAPP_LIST> m_app_list;
|
||||
STREAM_CONFIGURATION m_config;
|
||||
};
|
||||
|
|
|
@ -215,11 +215,11 @@ void MoonlightSession::start(ServerCallback<bool> callback) {
|
|||
m_audio_callbacks.capabilities = m_audio_renderer->capabilities();
|
||||
}
|
||||
|
||||
GameStreamClient::client()->start(m_address, m_config, m_app_id, [this, callback](auto result) {
|
||||
GameStreamClient::instance().start(m_address, m_config, m_app_id, [this, callback](auto result) {
|
||||
if (result.isSuccess()) {
|
||||
m_config = result.value();
|
||||
|
||||
auto m_data = GameStreamClient::client()->server_data(m_address);
|
||||
auto m_data = GameStreamClient::instance().server_data(m_address);
|
||||
int result = LiStartConnection(&m_data.serverInfo, &m_config, &m_connection_callbacks, &m_video_callbacks, &m_audio_callbacks, NULL, 0, NULL, 0);
|
||||
|
||||
if (result != 0) {
|
||||
|
@ -237,7 +237,7 @@ void MoonlightSession::start(ServerCallback<bool> callback) {
|
|||
|
||||
void MoonlightSession::stop(int terminate_app) {
|
||||
if (terminate_app) {
|
||||
GameStreamClient::client()->quit(m_address, [](auto _) {});
|
||||
GameStreamClient::instance().quit(m_address, [](auto _) {});
|
||||
}
|
||||
|
||||
LiStopConnection();
|
||||
|
@ -249,9 +249,6 @@ void MoonlightSession::draw() {
|
|||
AVFrameHolder::holder()->get([this](auto frame) {
|
||||
m_video_renderer->draw(m_config.width, m_config.height, frame);
|
||||
});
|
||||
// if (auto frame = m_video_decoder->frame()) {
|
||||
// m_video_renderer->draw(m_config.width, m_config.height, frame);
|
||||
// }
|
||||
|
||||
m_session_stats.video_decode_stats = *m_video_decoder->video_decode_stats();
|
||||
m_session_stats.video_render_stats = *m_video_renderer->video_render_stats();
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
#include "Singleton.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
struct Host;
|
||||
|
||||
class WakeOnLanManager {
|
||||
class WakeOnLanManager: public Singleton<WakeOnLanManager> {
|
||||
private:
|
||||
static WakeOnLanManager* manager() {
|
||||
static WakeOnLanManager manager;
|
||||
return &manager;
|
||||
}
|
||||
|
||||
bool wake_up_host(const Host &host);
|
||||
|
||||
friend class GameStreamClient;
|
||||
|
|
|
@ -76,6 +76,7 @@ void Application::resize_callback_event(int width, int height, int fb_width, int
|
|||
for (auto window: m_windows) {
|
||||
window->set_size(Size(width, height));
|
||||
window->set_fixed_size(Size(width, height));
|
||||
window->perform_layout(nvg_context());
|
||||
}
|
||||
Screen::resize_callback_event(width, height, fb_width, fb_height);
|
||||
perform_layout();
|
||||
|
|
|
@ -8,25 +8,24 @@
|
|||
|
||||
using namespace nanogui;
|
||||
|
||||
AppButton::AppButton(Widget* parent, const std::string &address, APP_LIST app, int current_game): Button(parent, "") {
|
||||
AppButton::AppButton(Widget* parent, const std::string &address, AppInfo app, int current_game): Button(parent, "") {
|
||||
m_address = address;
|
||||
m_app = app;
|
||||
|
||||
set_fixed_size(Size(210, 296));
|
||||
set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle));
|
||||
|
||||
m_label = add<Label>(m_app.name);
|
||||
m_label->set_fixed_width(fixed_width() - 12);
|
||||
|
||||
if (m_app.id == current_game) {
|
||||
set_fixed_size(Size(210, 296));
|
||||
set_layout(new BoxLayout(Orientation::Vertical, Alignment::Minimum, 10));
|
||||
|
||||
if (m_app.app_id == current_game) {
|
||||
m_label->set_caption(m_label->caption() + " (Running)");
|
||||
}
|
||||
|
||||
if (!BoxArtManager::manager()->has_boxart(m_app.id)) {
|
||||
if (!BoxArtManager::instance().has_boxart(m_app.app_id)) {
|
||||
inc_ref();
|
||||
GameStreamClient::client()->app_boxart(m_address, m_app.id, [this](auto result) {
|
||||
GameStreamClient::instance().app_boxart(m_address, m_app.app_id, [this](auto result) {
|
||||
if (result.isSuccess()) {
|
||||
BoxArtManager::manager()->set_data(result.value(), m_app.id);
|
||||
BoxArtManager::instance().set_data(result.value(), m_app.app_id);
|
||||
}
|
||||
|
||||
dec_ref();
|
||||
|
@ -37,18 +36,24 @@ AppButton::AppButton(Widget* parent, const std::string &address, APP_LIST app, i
|
|||
bool AppButton::gamepad_button_event(int jid, int button, int action) {
|
||||
if (action && button == NANOGUI_GAMEPAD_BUTTON_Y) {
|
||||
if (auto application = dynamic_cast<Application *>(screen())) {
|
||||
application->push_window<InputSettingsWindow>(m_app.id, m_app.name);
|
||||
application->push_window<InputSettingsWindow>(m_app.app_id, m_app.name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return Button::gamepad_button_event(jid, button, action);
|
||||
}
|
||||
|
||||
void AppButton::draw(NVGcontext *ctx) {
|
||||
int handle = BoxArtManager::manager()->texture_id(m_app.id);
|
||||
void AppButton::set_fixed_size(const Vector2i &fixed_size) {
|
||||
m_label->set_fixed_width(fixed_size.x() - 10);
|
||||
|
||||
if (handle == -1 && BoxArtManager::manager()->has_boxart(m_app.id)) {
|
||||
BoxArtManager::manager()->make_texture_from_boxart(ctx, m_app.id);
|
||||
Button::set_fixed_size(fixed_size);
|
||||
}
|
||||
|
||||
void AppButton::draw(NVGcontext *ctx) {
|
||||
int handle = BoxArtManager::instance().texture_id(m_app.app_id);
|
||||
|
||||
if (handle == -1 && BoxArtManager::instance().has_boxart(m_app.app_id)) {
|
||||
BoxArtManager::instance().make_texture_from_boxart(ctx, m_app.app_id);
|
||||
}
|
||||
|
||||
if (handle != -1) {
|
||||
|
@ -72,7 +77,7 @@ void AppButton::draw(NVGcontext *ctx) {
|
|||
nvgSave(ctx);
|
||||
nvgFillColor(ctx, Color(0, 0, 0, 200));
|
||||
nvgBeginPath(ctx);
|
||||
nvgRect(ctx, m_pos.x(), m_pos.y(), width(), m_label->height());
|
||||
nvgRect(ctx, m_pos.x(), m_pos.y(), width(), m_label->height() + 20);
|
||||
nvgFill(ctx);
|
||||
nvgRestore(ctx);
|
||||
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
|
||||
class AppButton: public nanogui::Button {
|
||||
public:
|
||||
AppButton(Widget* parent, const std::string &address, APP_LIST app, int current_game);
|
||||
AppButton(Widget* parent, const std::string &address, AppInfo app, int current_game);
|
||||
|
||||
bool gamepad_button_event(int jid, int button, int action) override;
|
||||
|
||||
void set_fixed_size(const nanogui::Vector2i &fixed_size);
|
||||
void draw(NVGcontext *ctx) override;
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
APP_LIST m_app;
|
||||
AppInfo m_app;
|
||||
nanogui::Label* m_label;
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ HostButton::HostButton(Widget* parent, const Host &host): Button(parent, "") {
|
|||
m_label->set_font_size(20);
|
||||
|
||||
inc_ref();
|
||||
GameStreamClient::client()->connect(m_host.address, [this](auto result) {
|
||||
GameStreamClient::instance().connect(m_host.address, [this](auto result) {
|
||||
if (result.isSuccess()) {
|
||||
m_is_active = true;
|
||||
m_is_paired = result.value().paired;
|
||||
|
|
|
@ -61,7 +61,7 @@ AddHostWindow::AddHostWindow(Widget *parent): ContentWindow(parent, "Add Host")
|
|||
if (text->value().size() > 0) {
|
||||
auto loader = add<LoadingOverlay>();
|
||||
|
||||
GameStreamClient::client()->connect(text->value(), [this, loader](auto result) {
|
||||
GameStreamClient::instance().connect(text->value(), [this, loader](auto result) {
|
||||
loader->dispose();
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
|
|
@ -4,9 +4,28 @@
|
|||
#include "StreamWindow.hpp"
|
||||
#include "GamepadMapper.hpp"
|
||||
#include "Alert.hpp"
|
||||
#include "GameStreamClient.hpp"
|
||||
|
||||
using namespace nanogui;
|
||||
|
||||
class AppListLayout: public GridLayout {
|
||||
public:
|
||||
AppListLayout(): GridLayout(Orientation::Horizontal, 5, Alignment::Minimum, 0, 18) {}
|
||||
|
||||
Vector2i preferred_size(NVGcontext *ctx, const Widget *widget) const override {
|
||||
auto width = (widget->parent()->width() - spacing(0) * (resolution() - 1)) / resolution() - 10;
|
||||
auto size = Size(width, width * 1.4f);
|
||||
|
||||
for (auto &child: widget->children()) {
|
||||
if (child->fixed_size() != size) {
|
||||
child->set_fixed_size(size);
|
||||
child->perform_layout(ctx);
|
||||
}
|
||||
}
|
||||
return GridLayout::preferred_size(ctx, widget);
|
||||
}
|
||||
};
|
||||
|
||||
AppListWindow::AppListWindow(Widget *parent, const std::string &address): ContentWindow(parent, "Applications"), m_address(address) {
|
||||
set_left_pop_button();
|
||||
|
||||
|
@ -23,7 +42,7 @@ void AppListWindow::reload(std::function<void()> callback) {
|
|||
|
||||
auto loader = add<LoadingOverlay>();
|
||||
|
||||
GameStreamClient::client()->connect(m_address, [this, loader, callback](auto result) {
|
||||
GameStreamClient::instance().connect(m_address, [this, loader, callback](auto result) {
|
||||
if (result.isSuccess()) {
|
||||
auto currentGame = result.value().currentGame;
|
||||
|
||||
|
@ -33,7 +52,7 @@ void AppListWindow::reload(std::function<void()> callback) {
|
|||
});
|
||||
}
|
||||
|
||||
GameStreamClient::client()->applist(m_address, [this, loader, currentGame, callback](auto result) {
|
||||
GameStreamClient::instance().applist(m_address, [this, loader, currentGame, callback](auto result) {
|
||||
loader->dispose();
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
@ -41,17 +60,15 @@ void AppListWindow::reload(std::function<void()> callback) {
|
|||
container()->add<Widget>()->set_fixed_height(6);
|
||||
|
||||
auto button_container = container()->add<Widget>();
|
||||
button_container->set_layout(new GridLayout(Orientation::Horizontal, 5, Alignment::Minimum, 0, 18));
|
||||
button_container->set_layout(new AppListLayout());
|
||||
|
||||
PAPP_LIST app = result.value();
|
||||
|
||||
while (app != NULL) {
|
||||
auto button = button_container->add<AppButton>(m_address, *app, currentGame);
|
||||
for (auto &app: result.value()) {
|
||||
auto button = button_container->add<AppButton>(m_address, app, currentGame);
|
||||
button->set_callback([this, app] {
|
||||
run_game(app->id);
|
||||
run_game(app.app_id);
|
||||
});
|
||||
app = app->next;
|
||||
}
|
||||
|
||||
perform_layout();
|
||||
|
||||
if (callback) {
|
||||
|
@ -69,7 +86,7 @@ void AppListWindow::reload(std::function<void()> callback) {
|
|||
}
|
||||
|
||||
void AppListWindow::run_game(int app_id) {
|
||||
int current_app_id = GameStreamClient::client()->server_data(m_address).currentGame;
|
||||
int current_app_id = GameStreamClient::instance().server_data(m_address).currentGame;
|
||||
|
||||
if (current_app_id == 0 || current_app_id == app_id) {
|
||||
GamepadMapper::mapper()->load_gamepad_map(app_id);
|
||||
|
@ -92,7 +109,7 @@ void AppListWindow::run_game(int app_id) {
|
|||
void AppListWindow::close_game(std::function<void()> callback) {
|
||||
auto loader = add<LoadingOverlay>();
|
||||
|
||||
GameStreamClient::client()->quit(m_address, [this, loader, callback](auto result) {
|
||||
GameStreamClient::instance().quit(m_address, [this, loader, callback](auto result) {
|
||||
loader->dispose();
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "ContentWindow.hpp"
|
||||
#include "GameStreamClient.hpp"
|
||||
#pragma once
|
||||
|
||||
class AppListWindow: public ContentWindow {
|
||||
|
@ -14,5 +13,4 @@ private:
|
|||
void close_game(std::function<void()> callback = NULL);
|
||||
|
||||
std::string m_address;
|
||||
PAPP_LIST m_app_list;
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ void MainWindow::reload() {
|
|||
} else {
|
||||
auto loader = add<LoadingOverlay>("Pairing... (Enter 0000)");
|
||||
|
||||
GameStreamClient::client()->pair(button->host().address, "0000", [this, loader](auto result){
|
||||
GameStreamClient::instance().pair(button->host().address, "0000", [this, loader](auto result){
|
||||
loader->dispose();
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
@ -104,7 +104,7 @@ void MainWindow::draw(NVGcontext *ctx) {
|
|||
void MainWindow::wake_up_host(const Host &host) {
|
||||
auto loader = add<LoadingOverlay>("Sending Wake Up...");
|
||||
|
||||
GameStreamClient::client()->wake_up_host(host, [this, loader](auto result) {
|
||||
GameStreamClient::instance().wake_up_host(host, [this, loader](auto result) {
|
||||
loader->dispose();
|
||||
|
||||
if (result.isSuccess()) {
|
||||
|
|
Loading…
Reference in a new issue