diff --git a/docs/JSON-RPC.md b/docs/JSON-RPC.md index cfe8dfbe3e..bff0bfc92e 100644 --- a/docs/JSON-RPC.md +++ b/docs/JSON-RPC.md @@ -291,6 +291,23 @@ Results: | result | string | Always "ok". | +### jamulusclient/setMuted + +Mutes or unmutes the client. + +Parameters: + +| Name | Type | Description | +| --- | --- | --- | +| params.muted | boolean | muted (true or false). | + +Results: + +| Name | Type | Description | +| --- | --- | --- | +| result | string | Always "ok". | + + ### jamulusclient/setName Sets your name. @@ -325,6 +342,23 @@ Results: | result | string | Always "ok". | +### jamulusserver/broadcastChatMessage + +Sends a message (as the server) to all connected clients. This can be used to broadcast messages from external sources (e.g. scripts or monitoring tools). + +Parameters: + +| Name | Type | Description | +| --- | --- | --- | +| params.chatMessage | string | The chat message text. | + +Results: + +| Name | Type | Description | +| --- | --- | --- | +| result | string | Always "ok". | + + ### jamulusserver/getClients Returns the list of connected clients along with details about them. @@ -621,3 +655,38 @@ Parameters: | params.servers[*].city | string | Server city. | +### jamulusserver/chatMessageReceived + +Emitted when a chat message is received from either a Jamulus or RPC client and to be broadcast to all connected clients. + +Parameters: + +| Name | Type | Description | +| --- | --- | --- | +| params.chatMessage | string | Chat message text. | + + +### jamulusserver/clientConnected + +Emitted when a client has connected to the server. + +Parameters: + +| Name | Type | Description | +| --- | --- | --- | +| params.id | number | The channel ID assigned to the client. | +| params.address | string | The client's address. | +| params.totalChannels | number | Number of total channels connected to the server. | + + +### jamulusserver/clientDisconnected + +Emitted when a client has disconnected from the server. + +Parameters: + +| Name | Type | Description | +| --- | --- | --- | +| params.id | number | The channel ID assigned to the client. | + + diff --git a/src/client.h b/src/client.h index 27c78cdf3d..b3a160be5b 100644 --- a/src/client.h +++ b/src/client.h @@ -329,6 +329,7 @@ class CClient : public QObject // settings CChannelCoreInfo ChannelInfo; QString strClientName; + void OnRPCInMuteMyself ( bool bMute ) { OnControllerInMuteMyself ( bMute ); } public: void SetSettings ( CClientSettings* settings ); diff --git a/src/clientrpc.cpp b/src/clientrpc.cpp index 02324121e3..9ba7060a1d 100644 --- a/src/clientrpc.cpp +++ b/src/clientrpc.cpp @@ -497,6 +497,23 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe response["result"] = jsonDevices; Q_UNUSED ( params ); } ); + + /// @rpc_method jamulusclient/setMuted + /// @brief Mutes or unmutes the client. + /// @param {boolean} params.muted - muted (true or false). + /// @result {string} result - Always "ok". + pRpcServer->HandleMethod ( "jamulusclient/setMuted", [=] ( const QJsonObject& params, QJsonObject& response ) { + auto muted = params["muted"]; + if ( !muted.isBool() ) + { + response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: muted is not a boolean" ); + return; + } + + pClient->OnRPCInMuteMyself ( muted.toBool() ); + + response["result"] = "ok"; + } ); } QJsonValue CClientRpc::SerializeSkillLevel ( ESkillLevel eSkillLevel ) diff --git a/src/server.cpp b/src/server.cpp index 67274965bc..15f3d74e3f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -470,6 +470,8 @@ void CServer::OnNewConnection ( int iChID, int iTotChans, CHostAddress RecHostAd // logging of new connected channel Logging.AddNewConnection ( RecHostAddr.InetAddr, iTotChans ); + + emit ClientConnected ( iChID, RecHostAddr.InetAddr, iTotChans ); } void CServer::OnServerFull ( CHostAddress RecHostAddr ) @@ -872,10 +874,7 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) // and emit the client disconnected signal if ( eGetStat == GS_CHAN_NOW_DISCONNECTED ) { - if ( JamController.GetRecordingEnabled() ) - { - emit ClientDisconnected ( iCurChanID ); // TODO do this outside the mutex lock? - } + emit ClientDisconnected ( iCurChanID ); // TODO do this outside the mutex lock? FreeChannel ( iCurChanID ); // note that the channel is now not in use @@ -1296,15 +1295,26 @@ void CServer::CreateAndSendChatTextForAllConChannels ( const int iCurChanID, con const QString strActualMessageText = "(" + QTime::currentTime().toString ( "hh:mm:ss AP" ) + ") " + ChanName.toHtmlEscaped() + " " + strChatText.toHtmlEscaped(); + SendChatTextToAllChannels ( strActualMessageText ); +} - // Send chat text to all connected clients --------------------------------- +void CServer::SendChatTextToAllChannels ( const QString& strChatText ) +{ + // Send chat text to all channels ------------------------------------------- for ( int i = 0; i < iMaxNumChannels; i++ ) { - if ( vecChannels[i].IsConnected() ) - { - // send message - vecChannels[i].CreateChatTextMes ( strActualMessageText ); - } + SendChatTextToConChannel ( i, strChatText ); + } + emit sentChatMessage ( strChatText ); +} + +void CServer::SendChatTextToConChannel ( const int iCurChanID, const QString& strChatText ) +{ + // Only send chat text if channel is connected ------------------------------ + if ( vecChannels[iCurChanID].IsConnected() ) + { + // send message + vecChannels[iCurChanID].CreateChatTextMes ( strChatText ); } } diff --git a/src/server.h b/src/server.h index 2e6b13e835..c87baba95c 100644 --- a/src/server.h +++ b/src/server.h @@ -191,6 +191,8 @@ class CServer : public QObject, public CServerSlots void SetEnableDelayPanning ( bool bDelayPanningOn ) { bDelayPan = bDelayPanningOn; } bool IsDelayPanningEnabled() { return bDelayPan; } + void SendChatTextToAllChannels ( const QString& strChatText ); + protected: // access functions for actual channels bool IsConnected ( const int iChanNum ) { return vecChannels[iChanNum].IsConnected(); } @@ -205,6 +207,7 @@ class CServer : public QObject, public CServerSlots virtual void CreateAndSendChanListForThisChan ( const int iCurChanID ); virtual void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, const QString& strChatText ); + void SendChatTextToConChannel ( const int iCurChanID, const QString& strChatText ); virtual void CreateOtherMuteStateChanged ( const int iCurChanID, const int iOtherChanID, const bool bIsMuted ); @@ -328,6 +331,8 @@ class CServer : public QObject, public CServerSlots void Started(); void Stopped(); void ClientDisconnected ( const int iChID ); + void ClientConnected ( const int iChID, const QHostAddress RecHostAddr, const int iTotChans ); + void sentChatMessage ( const QString& strChatText ); void SvrRegStatusChanged(); void AudioFrame ( const int iChID, const QString stChName, diff --git a/src/serverrpc.cpp b/src/serverrpc.cpp index 315a3e262c..d1bf12f02f 100644 --- a/src/serverrpc.cpp +++ b/src/serverrpc.cpp @@ -56,6 +56,57 @@ CServerRpc::CServerRpc ( CServer* pServer, CRpcServer* pRpcServer, QObject* pare Q_UNUSED ( params ); } ); + /// @rpc_notification jamulusserver/clientConnected + /// @brief Emitted when a client has connected to the server. + /// @param {number} params.id - The channel ID assigned to the client. + /// @param {string} params.address - The client's address. + /// @param {number} params.totalChannels - Number of total channels connected to the server. + connect ( pServer, &CServer::ClientConnected, [=] ( const int iChanID, const QHostAddress RecHostAddr, const int iTotChans ) { + pRpcServer->BroadcastNotification ( "jamulusserver/clientConnected", + QJsonObject{ + { "id", iChanID }, + { "address", RecHostAddr.toString() }, + { "totalChannels", iTotChans }, + } ); + } ); + + /// @rpc_notification jamulusserver/clientDisconnected + /// @brief Emitted when a client has disconnected from the server. + /// @param {number} params.id - The channel ID assigned to the client. + connect ( pServer, &CServer::ClientDisconnected, [=] ( const int iChanID ) { + pRpcServer->BroadcastNotification ( "jamulusserver/clientDisconnected", + QJsonObject{ + { "id", iChanID }, + } ); + } ); + + /// @rpc_notification jamulusserver/chatMessageReceived + /// @brief Emitted when a chat message is received from either a Jamulus or RPC client and to be broadcast to all connected clients. + /// @param {string} params.chatMessage - Chat message text. + connect ( pServer, &CServer::sentChatMessage, [=] ( const QString& strChatText ) { + pRpcServer->BroadcastNotification ( "jamulusserver/chatMessageReceived", + QJsonObject{ + { "chatMessage", strChatText }, + } ); + } ); + + /// @rpc_method jamulusserver/broadcastChatMessage + /// @brief Sends a message (as the server) to all connected clients. This can be used to broadcast messages from external sources (e.g. scripts or + /// monitoring tools). + /// @param {string} params.chatMessage - The chat message text. + /// @result {string} result - Always "ok". + pRpcServer->HandleMethod ( "jamulusserver/broadcastChatMessage", [=] ( const QJsonObject& params, QJsonObject& response ) { + auto jsonChatMessage = params["chatMessage"]; + if ( !jsonChatMessage.isString() ) + { + response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: chatMessage is not a string" ); + return; + } + + pServer->SendChatTextToAllChannels ( jsonChatMessage.toString() ); + response["result"] = "ok"; + } ); + /// @rpc_method jamulusserver/getRecorderStatus /// @brief Returns the recorder state. /// @param {object} params - No parameters (empty object).