diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index d6f0dafc..1d32ae02 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1695,6 +1695,25 @@ void consoleWin_t::createMainMenu(void) netPlayMenu->addAction(act); + // NetPlay -> Client Status Dialog + act = new QAction(tr("Host &Status"), this); + //act->setShortcut( QKeySequence(tr("Shift+F7"))); + act->setStatusTip(tr("Open Netplay Host Status Dialog")); + connect(act, SIGNAL(triggered()), this, SLOT(openNetPlayStatusWindow(void)) ); + netPlayHostStatAct = act; + + netPlayMenu->addAction(act); + + // NetPlay -> Client Status Dialog + act = new QAction(tr("Client &Status"), this); + //act->setShortcut( QKeySequence(tr("Shift+F7"))); + act->setStatusTip(tr("Open Netplay Client Status Dialog")); + connect(act, SIGNAL(triggered()), this, SLOT(openNetPlayStatusWindow(void)) ); + netPlayClientStatAct = act; + + netPlayMenu->addAction(act); + + //netPlayMenu->setEnabled(false); //----------------------------------------------------------------------- // Tools @@ -3202,6 +3221,20 @@ void consoleWin_t::openNetPlayJoinWindow(void) openNetPlayJoinDialog(this); } +void consoleWin_t::openNetPlayStatusWindow(void) +{ + //printf("Open NetPlay Status Window\n"); + + if (isNetPlayHost()) + { + openNetPlayHostStatusDialog(this); + } + else + { + openNetPlayClientStatusDialog(this); + } +} + void consoleWin_t::closeNetPlaySession(void) { NetPlayCloseSession(); @@ -4766,11 +4799,27 @@ void consoleWin_t::updatePeriodic(void) stopWavAct->setEnabled( FCEUI_WaveRecordRunning() ); tasEditorAct->setEnabled( FCEU_IsValidUI(FCEUI_TASEDITOR) ); - bool netPlayactv = NetPlayActive(); + const bool netPlayactv = NetPlayActive(); netPlayHostAct->setEnabled( !netPlayactv ); netPlayJoinAct->setEnabled( !netPlayactv ); netPlayDiscAct->setEnabled( netPlayactv ); + + if (netPlayactv) + { + const bool isHost = isNetPlayHost(); + netPlayHostStatAct->setEnabled(isHost); + netPlayHostStatAct->setVisible(isHost); + netPlayClientStatAct->setEnabled(!isHost); + netPlayClientStatAct->setVisible(!isHost); + } + else + { + netPlayHostStatAct->setEnabled(false); + netPlayHostStatAct->setVisible(false); + netPlayClientStatAct->setEnabled(false); + netPlayClientStatAct->setVisible(false); + } } if ( errorMsgValid ) diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index dc21571d..a753341d 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -263,6 +263,8 @@ class consoleWin_t : public QMainWindow QAction *netPlayHostAct; QAction *netPlayJoinAct; QAction *netPlayDiscAct; + QAction *netPlayHostStatAct; + QAction *netPlayClientStatAct; //QAction *aviHudAct; //QAction *aviMsgAct; @@ -362,6 +364,7 @@ class consoleWin_t : public QMainWindow void openPaletteEditorWin(void); void openNetPlayHostWindow(void); void openNetPlayJoinWindow(void); + void openNetPlayStatusWindow(void); void closeNetPlaySession(void); void openAviRiffViewer(void); void openTimingStatWin(void); diff --git a/src/drivers/Qt/NetPlay.cpp b/src/drivers/Qt/NetPlay.cpp index c1f14897..d1056419 100644 --- a/src/drivers/Qt/NetPlay.cpp +++ b/src/drivers/Qt/NetPlay.cpp @@ -134,6 +134,32 @@ struct NetPlayFrameDataHist_t }; static NetPlayFrameDataHist_t netPlayFrameData; //----------------------------------------------------------------------------- +const char* NetPlayPlayerRoleToString(int role) +{ + const char* roleString = nullptr; + + switch (role) + { + default: + case netPlayerId::NETPLAY_SPECTATOR: + roleString = "Spectator"; + break; + case netPlayerId::NETPLAY_PLAYER1: + roleString = "Player 1"; + break; + case netPlayerId::NETPLAY_PLAYER2: + roleString = "Player 2"; + break; + case netPlayerId::NETPLAY_PLAYER3: + roleString = "Player 3"; + break; + case netPlayerId::NETPLAY_PLAYER4: + roleString = "Player 4"; + break; + } + return roleString; +} +//----------------------------------------------------------------------------- //--- NetPlayServer //----------------------------------------------------------------------------- NetPlayServer *NetPlayServer::instance = nullptr; @@ -365,6 +391,7 @@ bool NetPlayServer::claimRole(NetPlayClient* client, int _role) success = true; roleMask |= mask; clientPlayer[_role] = client; + client->role = _role; } } return success; @@ -1417,6 +1444,113 @@ void NetPlayJoinDialog::onSocketError(const QString& errorMsg) client = nullptr; } } +//----------------------------------------------------------------------------- +//--- NetPlayJoinDialog +//----------------------------------------------------------------------------- +NetPlayHostStatusDialog* NetPlayHostStatusDialog::instance = nullptr; +//----------------------------------------------------------------------------- +NetPlayHostStatusDialog::NetPlayHostStatusDialog(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout; + QHBoxLayout *hbox; + //QGridLayout *grid; + QPushButton *closeButton; + //QLabel *lbl; + + instance = this; + + setWindowTitle("NetPlay Status"); + + mainLayout = new QVBoxLayout(); + + clientTree = new QTreeWidget(); + mainLayout->addWidget( clientTree ); + + clientTree->setColumnCount(3); + + auto* item = new QTreeWidgetItem(); + item->setText( 0, QString::fromStdString( "Player" ) ); + item->setText( 1, QString::fromStdString( "Role" ) ); + item->setText( 2, QString::fromStdString( "State" ) ); + item->setTextAlignment( 0, Qt::AlignLeft); + item->setTextAlignment( 1, Qt::AlignLeft); + item->setTextAlignment( 2, Qt::AlignLeft); + + //connect( clientTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), + //this, SLOT(watchClicked( QTreeWidgetItem*, int)) ); + + clientTree->setHeaderItem( item ); + + closeButton = new QPushButton( tr("Close") ); + closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); + connect(closeButton, SIGNAL(clicked(void)), this, SLOT(closeWindow(void))); + + hbox = new QHBoxLayout(); + hbox->addStretch(5); + hbox->addWidget( closeButton, 1 ); + mainLayout->addLayout( hbox ); + + setLayout(mainLayout); + + loadClientTree(); +} +//---------------------------------------------------------------------------- +NetPlayHostStatusDialog::~NetPlayHostStatusDialog(void) +{ + instance = nullptr; + //printf("Destroy NetPlay Status Window\n"); +} +//---------------------------------------------------------------------------- +void NetPlayHostStatusDialog::closeEvent(QCloseEvent *event) +{ + //printf("NetPlay Host Close Window Event\n"); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------------------------------- +void NetPlayHostStatusDialog::closeWindow(void) +{ + //printf("Close Window\n"); + done(0); + deleteLater(); +} +//---------------------------------------------------------------------------- +void NetPlayHostStatusDialog::loadClientTree() +{ + auto* server = NetPlayServer::GetInstance(); + + if (server == nullptr) + { + return; + } + const char *roleString = NetPlayPlayerRoleToString( server->getRole() ); + auto* serverTopLvlItem = new NetPlayClientTreeItem(); + + serverTopLvlItem->server = server; + serverTopLvlItem->setText( 0, tr("Host") ); + serverTopLvlItem->setText( 1, tr(roleString) ); + + clientTree->addTopLevelItem( serverTopLvlItem ); + + auto& clientList = server->getClientList(); + + for (auto& client : clientList) + { + roleString = NetPlayPlayerRoleToString( client->role ); + + auto* clientTopLvlItem = new NetPlayClientTreeItem(); + + clientTopLvlItem->client = client; + + clientTopLvlItem->setText( 0, client->userName ); + clientTopLvlItem->setText( 1, tr(roleString) ); + + clientTree->addTopLevelItem( clientTopLvlItem ); + } + +} //---------------------------------------------------------------------------- //---- Global Functions //---------------------------------------------------------------------------- @@ -1515,13 +1649,13 @@ void NetPlayCloseSession(void) NetPlayServer::Destroy(); } //---------------------------------------------------------------------------- -void openNetPlayHostDialog(QWidget* parent) +template void openSingletonDialog(QWidget* parent) { - NetPlayHostDialog* win = NetPlayHostDialog::GetInstance(); + T* win = T::GetInstance(); if (win == nullptr) { - win = new NetPlayHostDialog(parent); + win = new T(parent); win->show(); } @@ -1532,21 +1666,24 @@ void openNetPlayHostDialog(QWidget* parent) } } //---------------------------------------------------------------------------- +void openNetPlayHostDialog(QWidget* parent) +{ + openSingletonDialog(parent); +} +//---------------------------------------------------------------------------- void openNetPlayJoinDialog(QWidget* parent) { - NetPlayJoinDialog* win = NetPlayJoinDialog::GetInstance(); - - if (win == nullptr) - { - win = new NetPlayJoinDialog(parent); - - win->show(); - } - else - { - win->activateWindow(); - win->raise(); - } + openSingletonDialog(parent); +} +//---------------------------------------------------------------------------- +void openNetPlayHostStatusDialog(QWidget* parent) +{ + openSingletonDialog(parent); +} +//---------------------------------------------------------------------------- +void openNetPlayClientStatusDialog(QWidget* parent) +{ + //openSingletonDialog(parent); } //---------------------------------------------------------------------------- //---- Network Byte Swap Utilities diff --git a/src/drivers/Qt/NetPlay.h b/src/drivers/Qt/NetPlay.h index b4cbf8cb..be4aa629 100644 --- a/src/drivers/Qt/NetPlay.h +++ b/src/drivers/Qt/NetPlay.h @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include #include @@ -73,6 +76,8 @@ class NetPlayServer : public QTcpServer static int Create(QObject *parent = 0); static int Destroy(); + typedef std::list ClientList_t; + int closeAllConnections(void); void update(void); @@ -123,6 +128,7 @@ class NetPlayServer : public QTcpServer int sendRomLoadReq( NetPlayClient *client ); int sendStateSyncReq( NetPlayClient *client ); void setRole(int _role); + int getRole(void){ return role; } bool claimRole(NetPlayClient* client, int _role); uint32_t getMaxLeadFrames(){ return maxLeadFrames; } @@ -130,6 +136,8 @@ class NetPlayServer : public QTcpServer void serverProcessMessage( NetPlayClient *client, void *msgBuf, size_t msgSize ); + ClientList_t& getClientList(){ return clientList; } + QString sessionName; QString sessionPasswd; private: @@ -137,7 +145,7 @@ class NetPlayServer : public QTcpServer void processPendingConnections(void); - std::list clientList; + ClientList_t clientList; std::list input; FCEU::mutex inputMtx; int role = -1; @@ -330,6 +338,42 @@ public slots: void onSocketError(const QString& errorMsg); }; +class NetPlayClientTreeItem : public QTreeWidgetItem +{ + public: + NetPlayClientTreeItem() + : QTreeWidgetItem() + { + + } + + NetPlayClient* client = nullptr; + NetPlayServer* server = nullptr; + private: +}; + +class NetPlayHostStatusDialog : public QDialog +{ + Q_OBJECT + +public: + NetPlayHostStatusDialog(QWidget *parent = 0); + ~NetPlayHostStatusDialog(void); + + static NetPlayHostStatusDialog *GetInstance(void){ return instance; }; + +protected: + void closeEvent(QCloseEvent *event); + void loadClientTree(void); + + QTreeWidget *clientTree; + + static NetPlayHostStatusDialog* instance; + +public slots: + void closeWindow(void); +}; + bool NetPlayActive(void); bool isNetPlayHost(void); void NetPlayPeriodicUpdate(void); @@ -341,3 +385,6 @@ void NetPlayCloseSession(void); void NetPlayTraceInstruction(uint8_t *opcode, int size); void openNetPlayHostDialog(QWidget* parent = nullptr); void openNetPlayJoinDialog(QWidget* parent = nullptr); +void openNetPlayHostStatusDialog(QWidget* parent = nullptr); +void openNetPlayClientStatusDialog(QWidget* parent = nullptr); +const char* NetPlayPlayerRoleToString(int role);