start decoupling LAN/netplay dialogs from the actual modules
This commit is contained in:
parent
ead4f35705
commit
5d84f3831c
|
@ -54,6 +54,8 @@ set(SOURCES_QT_SDL
|
|||
|
||||
LAN.cpp
|
||||
Netplay.cpp
|
||||
LANDialog.cpp
|
||||
NetplayDialog.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -63,344 +63,6 @@
|
|||
|
||||
using namespace melonDS;
|
||||
|
||||
|
||||
extern EmuThread* emuThread;
|
||||
LANStartClientDialog* lanClientDlg = nullptr;
|
||||
LANDialog* lanDlg = nullptr;
|
||||
|
||||
|
||||
LANStartHostDialog::LANStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANStartHostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// 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)
|
||||
ui->sbNumPlayers->setRange(2, 16);
|
||||
ui->sbNumPlayers->setValue(16);
|
||||
}
|
||||
|
||||
LANStartHostDialog::~LANStartHostDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANStartHostDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
int numplayers = ui->sbNumPlayers->value();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
|
||||
LAN::StartHost(player.c_str(), numplayers);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
LANStartClientDialog::LANStartClientDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANStartClientDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvAvailableGames->setModel(model);
|
||||
const QStringList listheader = {"Name", "Players", "Status", "Host IP"};
|
||||
model->setHorizontalHeaderLabels(listheader);
|
||||
|
||||
connect(ui->tvAvailableGames->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(onGameSelectionChanged(const QItemSelection&, const QItemSelection&)));
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Connect");
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
QPushButton* btn = ui->buttonBox->addButton("Direct connect...", QDialogButtonBox::ActionRole);
|
||||
connect(btn, SIGNAL(clicked()), this, SLOT(onDirectConnect()));
|
||||
|
||||
connect(this, &LANStartClientDialog::sgUpdateDiscoveryList, this, &LANStartClientDialog::doUpdateDiscoveryList);
|
||||
|
||||
lanClientDlg = this;
|
||||
LAN::StartDiscovery();
|
||||
}
|
||||
|
||||
LANStartClientDialog::~LANStartClientDialog()
|
||||
{
|
||||
lanClientDlg = nullptr;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANStartClientDialog::onGameSelectionChanged(const QItemSelection& cur, const QItemSelection& prev)
|
||||
{
|
||||
QModelIndexList indlist = cur.indexes();
|
||||
if (indlist.count() == 0)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LANStartClientDialog::on_tvAvailableGames_doubleClicked(QModelIndex index)
|
||||
{
|
||||
done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::onDirectConnect()
|
||||
{
|
||||
if (ui->txtPlayerName->text().trimmed().isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, "melonDS", "Please enter a player name before connecting.");
|
||||
return;
|
||||
}
|
||||
|
||||
QString host = QInputDialog::getText(this, "Direct connect", "Host address:");
|
||||
if (host.isEmpty()) return;
|
||||
|
||||
std::string hostname = host.toStdString();
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
|
||||
setEnabled(false);
|
||||
LAN::EndDiscovery();
|
||||
if (!LAN::StartClient(player.c_str(), hostname.c_str()))
|
||||
{
|
||||
QString msg = QString("Failed to connect to the host %0.").arg(QString::fromStdString(hostname));
|
||||
QMessageBox::warning(this, "melonDS", msg);
|
||||
setEnabled(true);
|
||||
LAN::StartDiscovery();
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabled(true);
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
QDialog::done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
if (ui->txtPlayerName->text().trimmed().isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, "melonDS", "Please enter a player name before connecting.");
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList indlist = ui->tvAvailableGames->selectionModel()->selectedRows();
|
||||
if (indlist.count() == 0) return;
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvAvailableGames->model();
|
||||
QStandardItem* item = model->item(indlist[0].row());
|
||||
u32 addr = item->data().toUInt();
|
||||
char hostname[16];
|
||||
snprintf(hostname, 16, "%d.%d.%d.%d", (addr>>24), ((addr>>16)&0xFF), ((addr>>8)&0xFF), (addr&0xFF));
|
||||
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
|
||||
setEnabled(false);
|
||||
LAN::EndDiscovery();
|
||||
if (!LAN::StartClient(player.c_str(), hostname))
|
||||
{
|
||||
QString msg = QString("Failed to connect to the host %0.").arg(QString(hostname));
|
||||
QMessageBox::warning(this, "melonDS", msg);
|
||||
setEnabled(true);
|
||||
LAN::StartDiscovery();
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabled(true);
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
LAN::EndDiscovery();
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::updateDiscoveryList()
|
||||
{
|
||||
emit sgUpdateDiscoveryList();
|
||||
}
|
||||
|
||||
void LANStartClientDialog::doUpdateDiscoveryList()
|
||||
{
|
||||
LAN::DiscoveryMutex.lock();
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvAvailableGames->model();
|
||||
int curcount = model->rowCount();
|
||||
int newcount = LAN::DiscoveryList.size();
|
||||
if (curcount > newcount)
|
||||
{
|
||||
model->removeRows(newcount, curcount-newcount);
|
||||
}
|
||||
else if (curcount < newcount)
|
||||
{
|
||||
for (int i = curcount; i < newcount; i++)
|
||||
{
|
||||
QList<QStandardItem*> row;
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
model->appendRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (const auto& [key, data] : LAN::DiscoveryList)
|
||||
{
|
||||
model->item(i, 0)->setText(data.SessionName);
|
||||
model->item(i, 0)->setData(QVariant(key));
|
||||
|
||||
QString plcount = QString("%0/%1").arg(data.NumPlayers).arg(data.MaxPlayers);
|
||||
model->item(i, 1)->setText(plcount);
|
||||
|
||||
QString status;
|
||||
switch (data.Status)
|
||||
{
|
||||
case 0: status = "Idle"; break;
|
||||
case 1: status = "Playing"; break;
|
||||
}
|
||||
model->item(i, 2)->setText(status);
|
||||
|
||||
QString ip = QString("%0.%1.%2.%3").arg(key>>24).arg((key>>16)&0xFF).arg((key>>8)&0xFF).arg(key&0xFF);
|
||||
model->item(i, 3)->setText(ip);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
LAN::DiscoveryMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
LANDialog::LANDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvPlayerList->setModel(model);
|
||||
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
|
||||
model->setHorizontalHeaderLabels(header);
|
||||
|
||||
connect(this, &LANDialog::sgUpdatePlayerList, this, &LANDialog::doUpdatePlayerList);
|
||||
}
|
||||
|
||||
LANDialog::~LANDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANDialog::done(int r)
|
||||
{
|
||||
// ???
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void LANDialog::updatePlayerList()
|
||||
{
|
||||
playerListMutex.lock();
|
||||
memcpy(playerList, LAN::Players, sizeof(playerList));
|
||||
memcpy(playerPing, LAN::PlayerPing, sizeof(playerPing));
|
||||
numPlayers = LAN::NumPlayers;
|
||||
maxPlayers = LAN::MaxPlayers;
|
||||
myPlayerID = LAN::MyPlayer.ID;
|
||||
hostAddress = LAN::HostAddress;
|
||||
playerListMutex.unlock();
|
||||
|
||||
emit sgUpdatePlayerList();
|
||||
}
|
||||
|
||||
void LANDialog::doUpdatePlayerList()
|
||||
{
|
||||
playerListMutex.lock();
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
|
||||
int curcount = model->rowCount();
|
||||
int newcount = numPlayers;
|
||||
if (curcount > newcount)
|
||||
{
|
||||
model->removeRows(newcount, curcount-newcount);
|
||||
}
|
||||
else if (curcount < newcount)
|
||||
{
|
||||
for (int i = curcount; i < newcount; i++)
|
||||
{
|
||||
QList<QStandardItem*> row;
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
model->appendRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
LAN::Player* player = &playerList[i];
|
||||
if (player->Status == 0) break;
|
||||
|
||||
QString id = QString("%0/%1").arg(player->ID+1).arg(maxPlayers);
|
||||
model->item(i, 0)->setText(id);
|
||||
|
||||
QString name = player->Name;
|
||||
model->item(i, 1)->setText(name);
|
||||
|
||||
QString status;
|
||||
switch (player->Status)
|
||||
{
|
||||
case 1: status = "Connected"; break;
|
||||
case 2: status = "Game host"; break;
|
||||
case 3: status = "Connecting"; break;
|
||||
case 4: status = "Connection lost"; break;
|
||||
}
|
||||
model->item(i, 2)->setText(status);
|
||||
|
||||
if (i == myPlayerID)
|
||||
{
|
||||
model->item(i, 3)->setText("-");
|
||||
model->item(i, 4)->setText("(local)");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->Status == 1 || player->Status == 2)
|
||||
{
|
||||
QString ping = QString("%0 ms").arg(playerPing[i]);
|
||||
model->item(i, 3)->setText(ping);
|
||||
}
|
||||
else
|
||||
{
|
||||
model->item(i, 3)->setText("-");
|
||||
}
|
||||
|
||||
// note on the player IP display
|
||||
// * we make an exception for the host -- the player list is issued by the host, so the host IP would be 127.0.0.1
|
||||
// * for the same reason, the host can't know its own IP, so for the current player we force it to 127.0.0.1
|
||||
u32 ip;
|
||||
if (player->Status == 2)
|
||||
ip = hostAddress;
|
||||
else
|
||||
ip = player->Address;
|
||||
|
||||
QString ips = QString("%0.%1.%2.%3").arg(ip&0xFF).arg((ip>>8)&0xFF).arg((ip>>16)&0xFF).arg(ip>>24);
|
||||
model->item(i, 4)->setText(ips);
|
||||
}
|
||||
}
|
||||
|
||||
playerListMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
namespace LAN
|
||||
{
|
||||
|
||||
|
|
|
@ -21,19 +21,9 @@
|
|||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <QDialog>
|
||||
#include <QMutex>
|
||||
#include <QItemSelection>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LANStartHostDialog;
|
||||
class LANStartClientDialog;
|
||||
class LANDialog;
|
||||
}
|
||||
|
||||
namespace LAN
|
||||
{
|
||||
|
||||
|
@ -56,101 +46,6 @@ struct DiscoveryData
|
|||
melonDS::u8 Status; // 0=idle 1=playing
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class LANStartHostDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANStartHostDialog(QWidget* parent);
|
||||
~LANStartHostDialog();
|
||||
|
||||
static LANStartHostDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANStartHostDialog* dlg = new LANStartHostDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::LANStartHostDialog* ui;
|
||||
};
|
||||
|
||||
class LANStartClientDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANStartClientDialog(QWidget* parent);
|
||||
~LANStartClientDialog();
|
||||
|
||||
static LANStartClientDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANStartClientDialog* dlg = new LANStartClientDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updateDiscoveryList();
|
||||
|
||||
signals:
|
||||
void sgUpdateDiscoveryList();
|
||||
|
||||
private slots:
|
||||
void onGameSelectionChanged(const QItemSelection& cur, const QItemSelection& prev);
|
||||
void on_tvAvailableGames_doubleClicked(QModelIndex index);
|
||||
void onDirectConnect();
|
||||
void done(int r);
|
||||
|
||||
void doUpdateDiscoveryList();
|
||||
|
||||
private:
|
||||
Ui::LANStartClientDialog* ui;
|
||||
};
|
||||
|
||||
class LANDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANDialog(QWidget* parent);
|
||||
~LANDialog();
|
||||
|
||||
static LANDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANDialog* dlg = new LANDialog(parent);
|
||||
dlg->show();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updatePlayerList();
|
||||
|
||||
signals:
|
||||
void sgUpdatePlayerList();
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
void doUpdatePlayerList();
|
||||
|
||||
private:
|
||||
Ui::LANDialog* ui;
|
||||
|
||||
LAN::Player playerList[16];
|
||||
melonDS::u32 playerPing[16];
|
||||
int numPlayers;
|
||||
int maxPlayers;
|
||||
int myPlayerID;
|
||||
melonDS::u32 hostAddress;
|
||||
QMutex playerListMutex;
|
||||
};
|
||||
|
||||
namespace LAN
|
||||
{
|
||||
|
||||
extern bool Active;
|
||||
|
||||
|
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
Copyright 2016-2024 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#define socket_t SOCKET
|
||||
#define sockaddr_t SOCKADDR
|
||||
#define sockaddr_in_t SOCKADDR_IN
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define socket_t int
|
||||
#define sockaddr_t struct sockaddr
|
||||
#define sockaddr_in_t struct sockaddr_in
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET (socket_t)-1
|
||||
#endif
|
||||
|
||||
#include <enet/enet.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QPushButton>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "LANDialog.h"
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "ui_LANStartHostDialog.h"
|
||||
#include "ui_LANStartClientDialog.h"
|
||||
#include "ui_LANDialog.h"
|
||||
|
||||
using namespace melonDS;
|
||||
|
||||
|
||||
extern EmuThread* emuThread;
|
||||
LANStartClientDialog* lanClientDlg = nullptr;
|
||||
LANDialog* lanDlg = nullptr;
|
||||
|
||||
|
||||
LANStartHostDialog::LANStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANStartHostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// 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)
|
||||
ui->sbNumPlayers->setRange(2, 16);
|
||||
ui->sbNumPlayers->setValue(16);
|
||||
}
|
||||
|
||||
LANStartHostDialog::~LANStartHostDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANStartHostDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
int numplayers = ui->sbNumPlayers->value();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
|
||||
LAN::StartHost(player.c_str(), numplayers);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
LANStartClientDialog::LANStartClientDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANStartClientDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvAvailableGames->setModel(model);
|
||||
const QStringList listheader = {"Name", "Players", "Status", "Host IP"};
|
||||
model->setHorizontalHeaderLabels(listheader);
|
||||
|
||||
connect(ui->tvAvailableGames->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(onGameSelectionChanged(const QItemSelection&, const QItemSelection&)));
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Connect");
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
QPushButton* btn = ui->buttonBox->addButton("Direct connect...", QDialogButtonBox::ActionRole);
|
||||
connect(btn, SIGNAL(clicked()), this, SLOT(onDirectConnect()));
|
||||
|
||||
connect(this, &LANStartClientDialog::sgUpdateDiscoveryList, this, &LANStartClientDialog::doUpdateDiscoveryList);
|
||||
|
||||
lanClientDlg = this;
|
||||
LAN::StartDiscovery();
|
||||
}
|
||||
|
||||
LANStartClientDialog::~LANStartClientDialog()
|
||||
{
|
||||
lanClientDlg = nullptr;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANStartClientDialog::onGameSelectionChanged(const QItemSelection& cur, const QItemSelection& prev)
|
||||
{
|
||||
QModelIndexList indlist = cur.indexes();
|
||||
if (indlist.count() == 0)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LANStartClientDialog::on_tvAvailableGames_doubleClicked(QModelIndex index)
|
||||
{
|
||||
done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::onDirectConnect()
|
||||
{
|
||||
if (ui->txtPlayerName->text().trimmed().isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, "melonDS", "Please enter a player name before connecting.");
|
||||
return;
|
||||
}
|
||||
|
||||
QString host = QInputDialog::getText(this, "Direct connect", "Host address:");
|
||||
if (host.isEmpty()) return;
|
||||
|
||||
std::string hostname = host.toStdString();
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
|
||||
setEnabled(false);
|
||||
LAN::EndDiscovery();
|
||||
if (!LAN::StartClient(player.c_str(), hostname.c_str()))
|
||||
{
|
||||
QString msg = QString("Failed to connect to the host %0.").arg(QString::fromStdString(hostname));
|
||||
QMessageBox::warning(this, "melonDS", msg);
|
||||
setEnabled(true);
|
||||
LAN::StartDiscovery();
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabled(true);
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
QDialog::done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
if (ui->txtPlayerName->text().trimmed().isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, "melonDS", "Please enter a player name before connecting.");
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList indlist = ui->tvAvailableGames->selectionModel()->selectedRows();
|
||||
if (indlist.count() == 0) return;
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvAvailableGames->model();
|
||||
QStandardItem* item = model->item(indlist[0].row());
|
||||
u32 addr = item->data().toUInt();
|
||||
char hostname[16];
|
||||
snprintf(hostname, 16, "%d.%d.%d.%d", (addr>>24), ((addr>>16)&0xFF), ((addr>>8)&0xFF), (addr&0xFF));
|
||||
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
|
||||
setEnabled(false);
|
||||
LAN::EndDiscovery();
|
||||
if (!LAN::StartClient(player.c_str(), hostname))
|
||||
{
|
||||
QString msg = QString("Failed to connect to the host %0.").arg(QString(hostname));
|
||||
QMessageBox::warning(this, "melonDS", msg);
|
||||
setEnabled(true);
|
||||
LAN::StartDiscovery();
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabled(true);
|
||||
lanDlg = LANDialog::openDlg(parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
LAN::EndDiscovery();
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void LANStartClientDialog::updateDiscoveryList()
|
||||
{
|
||||
emit sgUpdateDiscoveryList();
|
||||
}
|
||||
|
||||
void LANStartClientDialog::doUpdateDiscoveryList()
|
||||
{
|
||||
LAN::DiscoveryMutex.lock();
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvAvailableGames->model();
|
||||
int curcount = model->rowCount();
|
||||
int newcount = LAN::DiscoveryList.size();
|
||||
if (curcount > newcount)
|
||||
{
|
||||
model->removeRows(newcount, curcount-newcount);
|
||||
}
|
||||
else if (curcount < newcount)
|
||||
{
|
||||
for (int i = curcount; i < newcount; i++)
|
||||
{
|
||||
QList<QStandardItem*> row;
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
model->appendRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (const auto& [key, data] : LAN::DiscoveryList)
|
||||
{
|
||||
model->item(i, 0)->setText(data.SessionName);
|
||||
model->item(i, 0)->setData(QVariant(key));
|
||||
|
||||
QString plcount = QString("%0/%1").arg(data.NumPlayers).arg(data.MaxPlayers);
|
||||
model->item(i, 1)->setText(plcount);
|
||||
|
||||
QString status;
|
||||
switch (data.Status)
|
||||
{
|
||||
case 0: status = "Idle"; break;
|
||||
case 1: status = "Playing"; break;
|
||||
}
|
||||
model->item(i, 2)->setText(status);
|
||||
|
||||
QString ip = QString("%0.%1.%2.%3").arg(key>>24).arg((key>>16)&0xFF).arg((key>>8)&0xFF).arg(key&0xFF);
|
||||
model->item(i, 3)->setText(ip);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
LAN::DiscoveryMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
LANDialog::LANDialog(QWidget* parent) : QDialog(parent), ui(new Ui::LANDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvPlayerList->setModel(model);
|
||||
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
|
||||
model->setHorizontalHeaderLabels(header);
|
||||
|
||||
connect(this, &LANDialog::sgUpdatePlayerList, this, &LANDialog::doUpdatePlayerList);
|
||||
}
|
||||
|
||||
LANDialog::~LANDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LANDialog::done(int r)
|
||||
{
|
||||
// ???
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void LANDialog::updatePlayerList()
|
||||
{
|
||||
playerListMutex.lock();
|
||||
memcpy(playerList, LAN::Players, sizeof(playerList));
|
||||
memcpy(playerPing, LAN::PlayerPing, sizeof(playerPing));
|
||||
numPlayers = LAN::NumPlayers;
|
||||
maxPlayers = LAN::MaxPlayers;
|
||||
myPlayerID = LAN::MyPlayer.ID;
|
||||
hostAddress = LAN::HostAddress;
|
||||
playerListMutex.unlock();
|
||||
|
||||
emit sgUpdatePlayerList();
|
||||
}
|
||||
|
||||
void LANDialog::doUpdatePlayerList()
|
||||
{
|
||||
playerListMutex.lock();
|
||||
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
|
||||
int curcount = model->rowCount();
|
||||
int newcount = numPlayers;
|
||||
if (curcount > newcount)
|
||||
{
|
||||
model->removeRows(newcount, curcount-newcount);
|
||||
}
|
||||
else if (curcount < newcount)
|
||||
{
|
||||
for (int i = curcount; i < newcount; i++)
|
||||
{
|
||||
QList<QStandardItem*> row;
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
row.append(new QStandardItem());
|
||||
model->appendRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
LAN::Player* player = &playerList[i];
|
||||
if (player->Status == 0) break;
|
||||
|
||||
QString id = QString("%0/%1").arg(player->ID+1).arg(maxPlayers);
|
||||
model->item(i, 0)->setText(id);
|
||||
|
||||
QString name = player->Name;
|
||||
model->item(i, 1)->setText(name);
|
||||
|
||||
QString status;
|
||||
switch (player->Status)
|
||||
{
|
||||
case 1: status = "Connected"; break;
|
||||
case 2: status = "Game host"; break;
|
||||
case 3: status = "Connecting"; break;
|
||||
case 4: status = "Connection lost"; break;
|
||||
}
|
||||
model->item(i, 2)->setText(status);
|
||||
|
||||
if (i == myPlayerID)
|
||||
{
|
||||
model->item(i, 3)->setText("-");
|
||||
model->item(i, 4)->setText("(local)");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->Status == 1 || player->Status == 2)
|
||||
{
|
||||
QString ping = QString("%0 ms").arg(playerPing[i]);
|
||||
model->item(i, 3)->setText(ping);
|
||||
}
|
||||
else
|
||||
{
|
||||
model->item(i, 3)->setText("-");
|
||||
}
|
||||
|
||||
// note on the player IP display
|
||||
// * we make an exception for the host -- the player list is issued by the host, so the host IP would be 127.0.0.1
|
||||
// * for the same reason, the host can't know its own IP, so for the current player we force it to 127.0.0.1
|
||||
u32 ip;
|
||||
if (player->Status == 2)
|
||||
ip = hostAddress;
|
||||
else
|
||||
ip = player->Address;
|
||||
|
||||
QString ips = QString("%0.%1.%2.%3").arg(ip&0xFF).arg((ip>>8)&0xFF).arg((ip>>16)&0xFF).arg(ip>>24);
|
||||
model->item(i, 4)->setText(ips);
|
||||
}
|
||||
}
|
||||
|
||||
playerListMutex.unlock();
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
Copyright 2016-2024 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LANDIALOG_H
|
||||
#define LANDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMutex>
|
||||
#include <QItemSelection>
|
||||
|
||||
#include "types.h"
|
||||
#include "LAN.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LANStartHostDialog;
|
||||
class LANStartClientDialog;
|
||||
class LANDialog;
|
||||
}
|
||||
|
||||
class LANStartHostDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANStartHostDialog(QWidget* parent);
|
||||
~LANStartHostDialog();
|
||||
|
||||
static LANStartHostDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANStartHostDialog* dlg = new LANStartHostDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::LANStartHostDialog* ui;
|
||||
};
|
||||
|
||||
class LANStartClientDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANStartClientDialog(QWidget* parent);
|
||||
~LANStartClientDialog();
|
||||
|
||||
static LANStartClientDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANStartClientDialog* dlg = new LANStartClientDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updateDiscoveryList();
|
||||
|
||||
signals:
|
||||
void sgUpdateDiscoveryList();
|
||||
|
||||
private slots:
|
||||
void onGameSelectionChanged(const QItemSelection& cur, const QItemSelection& prev);
|
||||
void on_tvAvailableGames_doubleClicked(QModelIndex index);
|
||||
void onDirectConnect();
|
||||
void done(int r);
|
||||
|
||||
void doUpdateDiscoveryList();
|
||||
|
||||
private:
|
||||
Ui::LANStartClientDialog* ui;
|
||||
};
|
||||
|
||||
class LANDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LANDialog(QWidget* parent);
|
||||
~LANDialog();
|
||||
|
||||
static LANDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
LANDialog* dlg = new LANDialog(parent);
|
||||
dlg->show();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updatePlayerList();
|
||||
|
||||
signals:
|
||||
void sgUpdatePlayerList();
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
void doUpdatePlayerList();
|
||||
|
||||
private:
|
||||
Ui::LANDialog* ui;
|
||||
|
||||
LAN::Player playerList[16];
|
||||
melonDS::u32 playerPing[16];
|
||||
int numPlayers;
|
||||
int maxPlayers;
|
||||
int myPlayerID;
|
||||
melonDS::u32 hostAddress;
|
||||
QMutex playerListMutex;
|
||||
};
|
||||
|
||||
#endif // LANDIALOG_H
|
|
@ -43,144 +43,6 @@
|
|||
|
||||
using namespace melonDS;
|
||||
|
||||
|
||||
extern EmuThread* emuThread;
|
||||
NetplayDialog* netplayDlg;
|
||||
|
||||
|
||||
NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartHostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->txtPort->setText("8064");
|
||||
}
|
||||
|
||||
NetplayStartHostDialog::~NetplayStartHostDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayStartHostDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
int port = ui->txtPort->text().toInt();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||
|
||||
Netplay::StartHost(player.c_str(), port);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
NetplayStartClientDialog::NetplayStartClientDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartClientDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->txtPort->setText("8064");
|
||||
}
|
||||
|
||||
NetplayStartClientDialog::~NetplayStartClientDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayStartClientDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
std::string host = ui->txtIPAddress->text().toStdString();
|
||||
int port = ui->txtPort->text().toInt();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||
|
||||
Netplay::StartClient(player.c_str(), host.c_str(), port);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
NetplayDialog::NetplayDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvPlayerList->setModel(model);
|
||||
|
||||
connect(this, &NetplayDialog::sgUpdatePlayerList, this, &NetplayDialog::doUpdatePlayerList);
|
||||
}
|
||||
|
||||
NetplayDialog::~NetplayDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayDialog::done(int r)
|
||||
{
|
||||
// ???
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void NetplayDialog::updatePlayerList(Netplay::Player* players, int num)
|
||||
{
|
||||
emit sgUpdatePlayerList(players, num);
|
||||
}
|
||||
|
||||
void NetplayDialog::doUpdatePlayerList(Netplay::Player* players, int num)
|
||||
{
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
|
||||
|
||||
model->clear();
|
||||
model->setRowCount(num);
|
||||
|
||||
// TODO: remove IP column in final product
|
||||
|
||||
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
|
||||
model->setHorizontalHeaderLabels(header);
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
Netplay::Player* player = &players[i];
|
||||
|
||||
QString id = QString("%0").arg(player->ID+1);
|
||||
model->setItem(i, 0, new QStandardItem(id));
|
||||
|
||||
QString name = player->Name;
|
||||
model->setItem(i, 1, new QStandardItem(name));
|
||||
|
||||
QString status;
|
||||
switch (player->Status)
|
||||
{
|
||||
case 1: status = ""; break;
|
||||
case 2: status = "Host"; break;
|
||||
default: status = "ded"; break;
|
||||
}
|
||||
model->setItem(i, 2, new QStandardItem(status));
|
||||
|
||||
// TODO: ping
|
||||
model->setItem(i, 3, new QStandardItem("x"));
|
||||
|
||||
char ip[32];
|
||||
u32 addr = player->Address;
|
||||
sprintf(ip, "%d.%d.%d.%d", addr&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF, addr>>24);
|
||||
model->setItem(i, 4, new QStandardItem(ip));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Netplay
|
||||
{
|
||||
|
||||
|
|
|
@ -19,21 +19,8 @@
|
|||
#ifndef NETPLAY_H
|
||||
#define NETPLAY_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class NetplayStartHostDialog;
|
||||
class NetplayStartClientDialog;
|
||||
class NetplayDialog;
|
||||
}
|
||||
|
||||
class NetplayStartHostDialog;
|
||||
class NetplayStartClientDialog;
|
||||
class NetplayDialog;
|
||||
|
||||
namespace Netplay
|
||||
{
|
||||
|
||||
|
@ -45,83 +32,6 @@ struct Player
|
|||
melonDS::u32 Address;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class NetplayStartHostDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayStartHostDialog(QWidget* parent);
|
||||
~NetplayStartHostDialog();
|
||||
|
||||
static NetplayStartHostDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayStartHostDialog* dlg = new NetplayStartHostDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::NetplayStartHostDialog* ui;
|
||||
};
|
||||
|
||||
class NetplayStartClientDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayStartClientDialog(QWidget* parent);
|
||||
~NetplayStartClientDialog();
|
||||
|
||||
static NetplayStartClientDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayStartClientDialog* dlg = new NetplayStartClientDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::NetplayStartClientDialog* ui;
|
||||
};
|
||||
|
||||
class NetplayDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayDialog(QWidget* parent);
|
||||
~NetplayDialog();
|
||||
|
||||
static NetplayDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayDialog* dlg = new NetplayDialog(parent);
|
||||
dlg->show();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
signals:
|
||||
void sgUpdatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
void doUpdatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
private:
|
||||
Ui::NetplayDialog* ui;
|
||||
};
|
||||
|
||||
namespace Netplay
|
||||
{
|
||||
|
||||
extern bool Active;
|
||||
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
Copyright 2016-2024 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <queue>
|
||||
|
||||
#include <enet/enet.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QProcess>
|
||||
|
||||
#include "NDS.h"
|
||||
#include "NDSCart.h"
|
||||
#include "main.h"
|
||||
#include "IPC.h"
|
||||
#include "Netplay.h"
|
||||
#include "Input.h"
|
||||
#include "ROMManager.h"
|
||||
#include "Config.h"
|
||||
#include "Savestate.h"
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ui_NetplayStartHostDialog.h"
|
||||
#include "ui_NetplayStartClientDialog.h"
|
||||
#include "ui_NetplayDialog.h"
|
||||
|
||||
using namespace melonDS;
|
||||
|
||||
|
||||
extern EmuThread* emuThread;
|
||||
NetplayDialog* netplayDlg;
|
||||
|
||||
|
||||
NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartHostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->txtPort->setText("8064");
|
||||
}
|
||||
|
||||
NetplayStartHostDialog::~NetplayStartHostDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayStartHostDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
int port = ui->txtPort->text().toInt();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||
|
||||
Netplay::StartHost(player.c_str(), port);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
NetplayStartClientDialog::NetplayStartClientDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartClientDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->txtPort->setText("8064");
|
||||
}
|
||||
|
||||
NetplayStartClientDialog::~NetplayStartClientDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayStartClientDialog::done(int r)
|
||||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
std::string player = ui->txtPlayerName->text().toStdString();
|
||||
std::string host = ui->txtIPAddress->text().toStdString();
|
||||
int port = ui->txtPort->text().toInt();
|
||||
|
||||
// TODO validate input!!
|
||||
|
||||
netplayDlg = NetplayDialog::openDlg(parentWidget());
|
||||
|
||||
Netplay::StartClient(player.c_str(), host.c_str(), port);
|
||||
}
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
|
||||
NetplayDialog::NetplayDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QStandardItemModel* model = new QStandardItemModel();
|
||||
ui->tvPlayerList->setModel(model);
|
||||
|
||||
connect(this, &NetplayDialog::sgUpdatePlayerList, this, &NetplayDialog::doUpdatePlayerList);
|
||||
}
|
||||
|
||||
NetplayDialog::~NetplayDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NetplayDialog::done(int r)
|
||||
{
|
||||
// ???
|
||||
|
||||
QDialog::done(r);
|
||||
}
|
||||
|
||||
void NetplayDialog::updatePlayerList(Netplay::Player* players, int num)
|
||||
{
|
||||
emit sgUpdatePlayerList(players, num);
|
||||
}
|
||||
|
||||
void NetplayDialog::doUpdatePlayerList(Netplay::Player* players, int num)
|
||||
{
|
||||
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
|
||||
|
||||
model->clear();
|
||||
model->setRowCount(num);
|
||||
|
||||
// TODO: remove IP column in final product
|
||||
|
||||
const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
|
||||
model->setHorizontalHeaderLabels(header);
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
Netplay::Player* player = &players[i];
|
||||
|
||||
QString id = QString("%0").arg(player->ID+1);
|
||||
model->setItem(i, 0, new QStandardItem(id));
|
||||
|
||||
QString name = player->Name;
|
||||
model->setItem(i, 1, new QStandardItem(name));
|
||||
|
||||
QString status;
|
||||
switch (player->Status)
|
||||
{
|
||||
case 1: status = ""; break;
|
||||
case 2: status = "Host"; break;
|
||||
default: status = "ded"; break;
|
||||
}
|
||||
model->setItem(i, 2, new QStandardItem(status));
|
||||
|
||||
// TODO: ping
|
||||
model->setItem(i, 3, new QStandardItem("x"));
|
||||
|
||||
char ip[32];
|
||||
u32 addr = player->Address;
|
||||
sprintf(ip, "%d.%d.%d.%d", addr&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF, addr>>24);
|
||||
model->setItem(i, 4, new QStandardItem(ip));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Copyright 2016-2024 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef NETPLAYDIALOG_H
|
||||
#define NETPLAYDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "types.h"
|
||||
#include "Netplay.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class NetplayStartHostDialog;
|
||||
class NetplayStartClientDialog;
|
||||
class NetplayDialog;
|
||||
}
|
||||
|
||||
class NetplayStartHostDialog;
|
||||
class NetplayStartClientDialog;
|
||||
class NetplayDialog;
|
||||
|
||||
class NetplayStartHostDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayStartHostDialog(QWidget* parent);
|
||||
~NetplayStartHostDialog();
|
||||
|
||||
static NetplayStartHostDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayStartHostDialog* dlg = new NetplayStartHostDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::NetplayStartHostDialog* ui;
|
||||
};
|
||||
|
||||
class NetplayStartClientDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayStartClientDialog(QWidget* parent);
|
||||
~NetplayStartClientDialog();
|
||||
|
||||
static NetplayStartClientDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayStartClientDialog* dlg = new NetplayStartClientDialog(parent);
|
||||
dlg->open();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
private:
|
||||
Ui::NetplayStartClientDialog* ui;
|
||||
};
|
||||
|
||||
class NetplayDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetplayDialog(QWidget* parent);
|
||||
~NetplayDialog();
|
||||
|
||||
static NetplayDialog* openDlg(QWidget* parent)
|
||||
{
|
||||
NetplayDialog* dlg = new NetplayDialog(parent);
|
||||
dlg->show();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void updatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
signals:
|
||||
void sgUpdatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
private slots:
|
||||
void done(int r);
|
||||
|
||||
void doUpdatePlayerList(Netplay::Player* players, int num);
|
||||
|
||||
private:
|
||||
Ui::NetplayDialog* ui;
|
||||
};
|
||||
|
||||
#endif // NETPLAYDIALOG_H
|
Loading…
Reference in New Issue