Skip to content

Commit 886381c

Browse files
jrdclaude
andcommitted
Add JSON-RPC client connection control
New methods: jamulusclient/connect, jamulusclient/disconnect and jamulusclient/getConnectionState. New notifications: jamulusclient/connecting, jamulusclient/connectingFailed and jamulusclient/connectionStateChanged. Together with the existing connected/disconnected notifications this gives JSON-RPC full parity with the UI for joining and leaving servers (#3801) and makes a --nogui client fully scriptable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 34beff2 commit 886381c

2 files changed

Lines changed: 183 additions & 0 deletions

File tree

docs/JSON-RPC.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,41 @@ Results:
129129
| result.version | string | The Jamulus version. |
130130

131131

132+
### jamulusclient/connect
133+
134+
Connects the client to a server. Any current connection is terminated first. The connection is established asynchronously: subscribe to the jamulusclient/connecting, jamulusclient/connected, jamulusclient/connectingFailed and jamulusclient/connectionStateChanged notifications to follow its progress.
135+
136+
Parameters:
137+
138+
| Name | Type | Description |
139+
| --- | --- | --- |
140+
| params.address | string | Socket address of the server (host:port). |
141+
| params.serverName | string | Optional human readable server name used for display purposes. Defaults to the address. |
142+
143+
Results:
144+
145+
| Name | Type | Description |
146+
| --- | --- | --- |
147+
| result | string | "ok" once the connection attempt has been initiated. |
148+
149+
150+
### jamulusclient/disconnect
151+
152+
Disconnects the client from the current server. Does nothing if the client is not connected.
153+
154+
Parameters:
155+
156+
| Name | Type | Description |
157+
| --- | --- | --- |
158+
| params | object | No parameters (empty object). |
159+
160+
Results:
161+
162+
| Name | Type | Description |
163+
| --- | --- | --- |
164+
| result | string | Always "ok". |
165+
166+
132167
### jamulusclient/getChannelInfo
133168

134169
Returns the client's profile information.
@@ -188,6 +223,24 @@ Results:
188223
| result.clients | array | The client list. See jamulusclient/clientListReceived for the format. |
189224

190225

226+
### jamulusclient/getConnectionState
227+
228+
Returns the current connection state.
229+
230+
Parameters:
231+
232+
| Name | Type | Description |
233+
| --- | --- | --- |
234+
| params | object | No parameters (empty object). |
235+
236+
Results:
237+
238+
| Name | Type | Description |
239+
| --- | --- | --- |
240+
| result.state | string | The connection state (disconnected, connecting, or connected). |
241+
| result.serverName | string | The human readable name of the current server (empty if disconnected). |
242+
243+
191244
### jamulusclient/getCurrentDirectory
192245

193246
Returns the currently selected directory socket address.
@@ -656,6 +709,39 @@ Parameters:
656709
| params.id | number | The channel ID assigned to the client. |
657710

658711

712+
### jamulusclient/connecting
713+
714+
Emitted when a connection to a server has been requested but is not yet established.
715+
716+
Parameters:
717+
718+
| Name | Type | Description |
719+
| --- | --- | --- |
720+
| params.serverName | string | The human readable server name (or the address if no name is known). |
721+
722+
723+
### jamulusclient/connectingFailed
724+
725+
Emitted when a connection attempt failed before it could be requested from the server.
726+
727+
Parameters:
728+
729+
| Name | Type | Description |
730+
| --- | --- | --- |
731+
| params.error | string | The error message. |
732+
733+
734+
### jamulusclient/connectionStateChanged
735+
736+
Emitted whenever the connection state changes.
737+
738+
Parameters:
739+
740+
| Name | Type | Description |
741+
| --- | --- | --- |
742+
| params.state | string | The new connection state (disconnected, connecting, or connected). |
743+
744+
659745
### jamulusclient/disconnected
660746

661747
Emitted when the client is disconnected from the server.

src/clientrpc.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@
4747

4848
#include "clientrpc.h"
4949

50+
static QString ConnectionStateToString ( const EConnectionState eState )
51+
{
52+
switch ( eState )
53+
{
54+
case CS_CONNECTING:
55+
return "connecting";
56+
57+
case CS_CONNECTED:
58+
return "connected";
59+
60+
default:
61+
return "disconnected";
62+
}
63+
}
64+
5065
CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServer* pRpcServer, QObject* parent ) :
5166
QObject ( parent ),
5267
m_pSettings ( pSettings )
@@ -168,6 +183,36 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe
168183
/// @param {object} params - No parameters (empty object).
169184
connect ( pClient, &CClient::Disconnected, [=]() { pRpcServer->BroadcastNotification ( "jamulusclient/disconnected", QJsonObject{} ); } );
170185

186+
/// @rpc_notification jamulusclient/connecting
187+
/// @brief Emitted when a connection to a server has been requested but is not yet established.
188+
/// @param {string} params.serverName - The human readable server name (or the address if no name is known).
189+
connect ( pClient, &CClient::Connecting, [=] ( QString strServerName ) {
190+
pRpcServer->BroadcastNotification ( "jamulusclient/connecting",
191+
QJsonObject{
192+
{ "serverName", strServerName },
193+
} );
194+
} );
195+
196+
/// @rpc_notification jamulusclient/connectingFailed
197+
/// @brief Emitted when a connection attempt failed before it could be requested from the server.
198+
/// @param {string} params.error - The error message.
199+
connect ( pClient, &CClient::ConnectingFailed, [=] ( QString strError ) {
200+
pRpcServer->BroadcastNotification ( "jamulusclient/connectingFailed",
201+
QJsonObject{
202+
{ "error", strError },
203+
} );
204+
} );
205+
206+
/// @rpc_notification jamulusclient/connectionStateChanged
207+
/// @brief Emitted whenever the connection state changes.
208+
/// @param {string} params.state - The new connection state (disconnected, connecting, or connected).
209+
connect ( pClient, &CClient::ConnectionStateChanged, [=] ( EConnectionState eState ) {
210+
pRpcServer->BroadcastNotification ( "jamulusclient/connectionStateChanged",
211+
QJsonObject{
212+
{ "state", ConnectionStateToString ( eState ) },
213+
} );
214+
} );
215+
171216
/// @rpc_notification jamulusclient/recorderState
172217
/// @brief Emitted when the client is connected to a server whose recorder state changes.
173218
/// @param {number} params.state - The recorder state.
@@ -212,6 +257,58 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe
212257
Q_UNUSED ( params );
213258
} );
214259

260+
/// @rpc_method jamulusclient/connect
261+
/// @brief Connects the client to a server. Any current connection is terminated first.
262+
/// The connection is established asynchronously: subscribe to the jamulusclient/connecting,
263+
/// jamulusclient/connected, jamulusclient/connectingFailed and jamulusclient/connectionStateChanged
264+
/// notifications to follow its progress.
265+
/// @param {string} params.address - Socket address of the server (host:port).
266+
/// @param {string} params.serverName - Optional human readable server name used for display purposes. Defaults to the address.
267+
/// @result {string} result - "ok" once the connection attempt has been initiated.
268+
pRpcServer->HandleMethod ( "jamulusclient/connect", [=] ( const QJsonObject& params, QJsonObject& response ) {
269+
auto jsonAddress = params["address"];
270+
if ( !jsonAddress.isString() )
271+
{
272+
response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: address is not a string" );
273+
return;
274+
}
275+
276+
auto jsonServerName = params["serverName"];
277+
const QString strAddress = NetworkUtil::FixAddress ( jsonAddress.toString() );
278+
const QString strServerName = jsonServerName.isString() ? jsonServerName.toString() : strAddress;
279+
280+
pClient->Connect ( strAddress, strServerName );
281+
282+
response["result"] = "ok";
283+
} );
284+
285+
/// @rpc_method jamulusclient/disconnect
286+
/// @brief Disconnects the client from the current server. Does nothing if the client is not connected.
287+
/// @param {object} params - No parameters (empty object).
288+
/// @result {string} result - Always "ok".
289+
pRpcServer->HandleMethod ( "jamulusclient/disconnect", [=] ( const QJsonObject& params, QJsonObject& response ) {
290+
pClient->Disconnect();
291+
292+
response["result"] = "ok";
293+
Q_UNUSED ( params );
294+
} );
295+
296+
/// @rpc_method jamulusclient/getConnectionState
297+
/// @brief Returns the current connection state.
298+
/// @param {object} params - No parameters (empty object).
299+
/// @result {string} result.state - The connection state (disconnected, connecting, or connected).
300+
/// @result {string} result.serverName - The human readable name of the current server (empty if disconnected).
301+
pRpcServer->HandleMethod ( "jamulusclient/getConnectionState", [=] ( const QJsonObject& params, QJsonObject& response ) {
302+
const EConnectionState eState = pClient->GetConnectionState();
303+
304+
QJsonObject result{
305+
{ "state", ConnectionStateToString ( eState ) },
306+
{ "serverName", eState == CS_DISCONNECTED ? QString() : pClient->GetConnectedServerName() },
307+
};
308+
response["result"] = result;
309+
Q_UNUSED ( params );
310+
} );
311+
215312
/// @rpc_method jamulus/getMode
216313
/// @brief Returns the current mode, i.e. whether Jamulus is running as a server or client.
217314
/// @param {object} params - No parameters (empty object).

0 commit comments

Comments
 (0)