From 4f252cb7137705a4fd653b9015859a4a38ff71ca Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 10 Aug 2024 16:57:29 +0200 Subject: [PATCH] integrate LAN into the UI better also fix the MPInterface destructor --- src/frontend/qt_sdl/LANDialog.cpp | 28 ++++++++--- src/frontend/qt_sdl/LANDialog.h | 1 + src/frontend/qt_sdl/LANDialog.ui | 32 ++++++++++--- src/frontend/qt_sdl/Window.cpp | 15 ++++++ src/frontend/qt_sdl/Window.h | 4 ++ src/frontend/qt_sdl/main.cpp | 25 +++++++++- src/frontend/qt_sdl/main.h | 3 ++ src/net/LAN.cpp | 77 +++++++++++++++---------------- src/net/LAN.h | 1 + src/net/MPInterface.cpp | 3 ++ src/net/MPInterface.h | 4 ++ 11 files changed, 138 insertions(+), 55 deletions(-) diff --git a/src/frontend/qt_sdl/LANDialog.cpp b/src/frontend/qt_sdl/LANDialog.cpp index 0a5c7449..58baf908 100644 --- a/src/frontend/qt_sdl/LANDialog.cpp +++ b/src/frontend/qt_sdl/LANDialog.cpp @@ -49,7 +49,7 @@ LANStartHostDialog::LANStartHostDialog(QWidget* parent) : QDialog(parent), ui(ne ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - MPInterface::Set(MPInterface_LAN); + setMPInterface(MPInterface_LAN); // TODO: remember the last setting? so this doesn't suck massively // we could also remember the player name (and auto-init it from the firmware name or whatever) @@ -85,7 +85,7 @@ void LANStartHostDialog::done(int r) } else { - MPInterface::Set(MPInterface_Local); + setMPInterface(MPInterface_Local); } QDialog::done(r); @@ -97,7 +97,7 @@ LANStartClientDialog::LANStartClientDialog(QWidget* parent) : QDialog(parent), u ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - MPInterface::Set(MPInterface_LAN); + setMPInterface(MPInterface_LAN); QStandardItemModel* model = new QStandardItemModel(); ui->tvAvailableGames->setModel(model); @@ -213,7 +213,7 @@ void LANStartClientDialog::done(int r) else { lan().EndDiscovery(); - MPInterface::Set(MPInterface_Local); + setMPInterface(MPInterface_Local); } QDialog::done(r); @@ -293,10 +293,26 @@ LANDialog::~LANDialog() delete ui; } +void LANDialog::on_btnLeaveGame_clicked() +{ + done(QDialog::Accepted); +} + void LANDialog::done(int r) { - // ??? - // TODO handle this situation, and provide the user a way to reopen this dialog + bool showwarning = true; + if (lan().GetNumPlayers() < 2) + showwarning = false; + + if (showwarning) + { + if (QMessageBox::warning(this, "melonDS", "Really leave this LAN game?", + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) + return; + } + + lan().EndSession(); + setMPInterface(MPInterface_Local); QDialog::done(r); } diff --git a/src/frontend/qt_sdl/LANDialog.h b/src/frontend/qt_sdl/LANDialog.h index c4b6255e..03857d79 100644 --- a/src/frontend/qt_sdl/LANDialog.h +++ b/src/frontend/qt_sdl/LANDialog.h @@ -104,6 +104,7 @@ protected: void timerEvent(QTimerEvent* event) override; private slots: + void on_btnLeaveGame_clicked(); void done(int r); void doUpdatePlayerList(); diff --git a/src/frontend/qt_sdl/LANDialog.ui b/src/frontend/qt_sdl/LANDialog.ui index e99000e4..88e9718f 100644 --- a/src/frontend/qt_sdl/LANDialog.ui +++ b/src/frontend/qt_sdl/LANDialog.ui @@ -11,15 +11,35 @@ - LAN SHITO + LAN game - melonDS - + - - - STATUS PLACEHOLDER + + + 0 - + + + + Leave game + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp index 84cc7222..e0b76d19 100644 --- a/src/frontend/qt_sdl/Window.cpp +++ b/src/frontend/qt_sdl/Window.cpp @@ -749,6 +749,8 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) : QObject::connect(qApp, &QApplication::applicationStateChanged, this, &MainWindow::onAppStateChanged); onUpdateInterfaceSettings(); + + updateMPInterface(MPInterface::GetType()); } MainWindow::~MainWindow() @@ -1712,6 +1714,19 @@ void MainWindow::onNPTest() //Netplay::StartGame(); } +void MainWindow::updateMPInterface(MPInterfaceType type) +{ + // MP interface was changed, reflect it in the UI + + bool enable = (type == MPInterface_Local); + actMPNewInstance->setEnabled(enable); + actLANStartHost->setEnabled(enable); + actLANStartClient->setEnabled(enable); + actNPStartHost->setEnabled(enable); + actNPStartClient->setEnabled(enable); + actNPTest->setEnabled(enable); +} + bool MainWindow::lanWarning(bool host) { if (numEmuInstances() < 2) diff --git a/src/frontend/qt_sdl/Window.h b/src/frontend/qt_sdl/Window.h index 67a16ae5..1dfd680c 100644 --- a/src/frontend/qt_sdl/Window.h +++ b/src/frontend/qt_sdl/Window.h @@ -35,6 +35,7 @@ #include "Screen.h" #include "Config.h" +#include "MPInterface.h" class EmuInstance; @@ -125,6 +126,9 @@ public: void osdAddMessage(unsigned int color, const char* msg); + // called when the MP interface is changed + void updateMPInterface(melonDS::MPInterfaceType type); + protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 001d0f4f..9a9c93cb 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -205,6 +205,28 @@ void pathInit() } +void setMPInterface(MPInterfaceType type) +{ + // switch to the requested MP interface + MPInterface::Set(type); + + // set receive timeout + // TODO: different settings per interface? + MPInterface::Get().SetRecvTimeout(Config::GetGlobalTable().GetInt("MP.RecvTimeout")); + + // update UI appropriately + // TODO: decide how to deal with multi-window when it becomes a thing + for (int i = 0; i < kMaxEmuInstances; i++) + { + EmuInstance* inst = emuInstances[i]; + if (!inst) continue; + + MainWindow* win = inst->getMainWindow(); + if (win) win->updateMPInterface(type); + } +} + + MelonApplication::MelonApplication(int& argc, char** argv) : QApplication(argc, argv) @@ -313,8 +335,7 @@ int main(int argc, char** argv) // default MP interface type is local MP // this will be changed if a LAN or netplay session is initiated - MPInterface::Set(MPInterface_Local); - MPInterface::Get().SetRecvTimeout(Config::GetGlobalTable().GetInt("MP.RecvTimeout")); + setMPInterface(MPInterface_Local); NetInit(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 6bd07d75..77cdf4ee 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -29,6 +29,7 @@ #include "Window.h" #include "EmuThread.h" #include "ScreenLayout.h" +#include "MPInterface.h" class MelonApplication : public QApplication { @@ -49,4 +50,6 @@ void deleteEmuInstance(int id); void deleteAllEmuInstances(int first = 0); int numEmuInstances(); +void setMPInterface(melonDS::MPInterfaceType type); + #endif // MAIN_H diff --git a/src/net/LAN.cpp b/src/net/LAN.cpp index 358bb92a..ebc66fd8 100644 --- a/src/net/LAN.cpp +++ b/src/net/LAN.cpp @@ -17,10 +17,7 @@ */ #include -#include #include -#include -#include #ifdef __WIN32__ #include @@ -107,46 +104,25 @@ LAN::LAN() noexcept : Inited(false) // TODO make this somewhat nicer if (enet_initialize() != 0) { - printf("enet shat itself :(\n"); + Platform::Log(Platform::LogLevel::Error, "LAN: failed to initialize enet\n"); return; } - printf("enet init OK\n"); + Platform::Log(Platform::LogLevel::Info, "LAN: enet initialized\n"); Inited = true; } LAN::~LAN() noexcept { - if (DiscoverySocket) - { - closesocket(DiscoverySocket); - DiscoverySocket = INVALID_SOCKET; - } - - while (!RXQueue.empty()) - { - ENetPacket* packet = RXQueue.front(); - RXQueue.pop(); - enet_packet_destroy(packet); - } - - for (int i = 0; i < 16; i++) - { - if (i == MyPlayer.ID) continue; - - if (RemotePeers[i]) - enet_peer_disconnect(RemotePeers[i], 0); - - RemotePeers[i] = nullptr; - } - - enet_host_destroy(Host); - Host = nullptr; + EndSession(); + Inited = false; enet_deinitialize(); Platform::Mutex_Free(DiscoveryMutex); Platform::Mutex_Free(PlayersMutex); + + Platform::Log(Platform::LogLevel::Info, "LAN: enet deinitialized\n"); } @@ -281,9 +257,6 @@ bool LAN::StartHost(const char* playername, int numplayers) Active = true; IsHost = true; - //if (lanDlg) - // lanDlg->updatePlayerList(); - StartDiscovery(); return true; } @@ -398,6 +371,35 @@ bool LAN::StartClient(const char* playername, const char* host) return true; } +void LAN::EndSession() +{ + if (!Active) return; + if (IsHost) EndDiscovery(); + + Active = false; + + while (!RXQueue.empty()) + { + ENetPacket* packet = RXQueue.front(); + RXQueue.pop(); + enet_packet_destroy(packet); + } + + for (int i = 0; i < 16; i++) + { + if (i == MyPlayer.ID) continue; + + if (RemotePeers[i]) + enet_peer_disconnect(RemotePeers[i], 0); + + RemotePeers[i] = nullptr; + } + + enet_host_destroy(Host); + Host = nullptr; + IsHost = false; +} + void LAN::ProcessDiscovery() { @@ -631,7 +633,6 @@ void LAN::ProcessHostEvent(ENetEvent& event) { if (event.packet->dataLength != 1) break; Player* player = (Player*)event.peer->data; - //printf("HOST: PLAYER CONNECT %p\n", player); if (!player) break; ConnectedBitmask |= (1 << player->ID); @@ -642,7 +643,6 @@ void LAN::ProcessHostEvent(ENetEvent& event) { if (event.packet->dataLength != 1) break; Player* player = (Player*)event.peer->data; - //printf("HOST: PLAYER DISCONNECT %p\n", player); if (!player) break; ConnectedBitmask &= ~(1 << player->ID); @@ -757,7 +757,6 @@ void LAN::ProcessClientEvent(ENetEvent& event) { if (event.packet->dataLength != 1) break; Player* player = (Player*)event.peer->data; - //printf("CLIENT: PLAYER CONNECT %p\n", player); if (!player) break; ConnectedBitmask |= (1 << player->ID); @@ -768,7 +767,6 @@ void LAN::ProcessClientEvent(ENetEvent& event) { if (event.packet->dataLength != 1) break; Player* player = (Player*)event.peer->data; - //printf("CLIENT: PLAYER DISCONNECT %p\n", player); if (!player) break; ConnectedBitmask &= ~(1 << player->ID); @@ -796,7 +794,6 @@ void LAN::ProcessEvent(ENetEvent& event) void LAN::ProcessLAN(int type) { if (!Host) return; - //printf("Process(%d): %d %d\n", type, RXQueue.empty(), RXQueue.size()); u32 time_last = (u32)Platform::GetMSCount(); @@ -842,7 +839,7 @@ void LAN::ProcessLAN(int type) if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == Chan_MP) { MPPacketHeader* header = (MPPacketHeader*)&event.packet->data[0]; - //printf("- enet_host_service: (%d) got MP frame, len=%d type=%08X fc=%04X\n", type, event.packet->dataLength, header->Type, *(u16*)&event.packet->data[sizeof(MPPacketHeader)+12]); + bool good = true; if (event.packet->dataLength < sizeof(MPPacketHeader)) good = false; @@ -870,7 +867,6 @@ void LAN::ProcessLAN(int type) } else { - //printf("- enet_host_service: got something else, time=%d\n", SDL_GetTicks()-time_last); ProcessEvent(event); } @@ -1053,7 +1049,6 @@ u16 LAN::RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask) if (RXQueue.empty()) { // no more replies available - //printf("RecvMPReplies timeout, ret=%04X myinstmask=%04X conn=%04X aidmask=%04X\n", ret, myinstmask, ConnectedBitmask, aidmask); return ret; } diff --git a/src/net/LAN.h b/src/net/LAN.h index d507e04d..87282539 100644 --- a/src/net/LAN.h +++ b/src/net/LAN.h @@ -87,6 +87,7 @@ public: void EndDiscovery(); bool StartHost(const char* player, int numplayers); bool StartClient(const char* player, const char* host); + void EndSession(); std::map GetDiscoveryList(); std::vector GetPlayerList(); diff --git a/src/net/MPInterface.cpp b/src/net/MPInterface.cpp index c92ac4fd..39d1915d 100644 --- a/src/net/MPInterface.cpp +++ b/src/net/MPInterface.cpp @@ -42,6 +42,7 @@ public: std::unique_ptr MPInterface::Current(std::make_unique()); +MPInterfaceType MPInterface::CurrentType = MPInterface_Dummy; void MPInterface::Set(MPInterfaceType type) @@ -60,6 +61,8 @@ void MPInterface::Set(MPInterfaceType type) Current = std::make_unique(); break; } + + CurrentType = type; } } diff --git a/src/net/MPInterface.h b/src/net/MPInterface.h index 5900a97a..eb5bef88 100644 --- a/src/net/MPInterface.h +++ b/src/net/MPInterface.h @@ -46,7 +46,10 @@ struct MPPacketHeader class MPInterface { public: + virtual ~MPInterface() = default; + static MPInterface& Get() { return *Current; } + static MPInterfaceType GetType() { return CurrentType; } static void Set(MPInterfaceType type); [[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; } @@ -70,6 +73,7 @@ protected: int RecvTimeout = 25; private: + static MPInterfaceType CurrentType; static std::unique_ptr Current; };