From c40fc98ea0435d4ea55a8aa13c8c6d9a2eec3570 Mon Sep 17 00:00:00 2001 From: jrd Date: Thu, 4 Jun 2026 17:00:17 +0000 Subject: [PATCH] Add jamulusserver/getSilenceStatus RPC endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tracks whether the server audio mix has been below threshold for ≥2 seconds. In OnTimer(), scan the decoded PCM frames; if any sample exceeds ±100 (out of 32767), update m_iLastAudioActivityMs. m_bIsSilent is true when no such activity has occurred for more than 2 s. When no clients are connected the flag is reset to false. The new RPC method jamulusserver/getSilenceStatus returns {"silent": bool}. Co-Authored-By: Claude Sonnet 4.6 --- src/server.cpp | 16 ++++++++++++++++ src/server.h | 5 +++++ src/serverrpc.cpp | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/src/server.cpp b/src/server.cpp index d6cd2bf0cc..64ef5c6dd8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -660,6 +660,20 @@ void CServer::OnTimer() // calculate levels for all connected clients const bool bSendChannelLevels = CreateLevelsForAllConChannels ( iNumClients, vecNumAudioChannels, vecvecsData, vecChannelLevels ); + { + bool bAnyActivity = false; + for ( int j = 0; j < iNumClients && !bAnyActivity; j++ ) + { + const int iDataSize = vecvecsData[j].Size(); + for ( int k = 0; k < iDataSize && !bAnyActivity; k++ ) + { + if ( vecvecsData[j][k] < -100 || vecvecsData[j][k] > 100 ) bAnyActivity = true; + } + } + if ( bAnyActivity ) m_iLastAudioActivityMs = QDateTime::currentMSecsSinceEpoch(); + m_bIsSilent = ( QDateTime::currentMSecsSinceEpoch() - m_iLastAudioActivityMs ) > 2000; + } + for ( int iChanCnt = 0; iChanCnt < iNumClients; iChanCnt++ ) { // get actual ID of current channel @@ -731,6 +745,8 @@ void CServer::OnTimer() { // Disable server if no clients are connected. In this case the server // does not consume any significant CPU when no client is connected. + m_iLastAudioActivityMs = QDateTime::currentMSecsSinceEpoch(); + m_bIsSilent = false; Stop(); } } diff --git a/src/server.h b/src/server.h index 6a42a8f9b8..849c9aa437 100644 --- a/src/server.h +++ b/src/server.h @@ -155,6 +155,8 @@ class CServer : public QObject, public CServerSlots } QString GetRecordingDir() { return JamController.GetRecordingDir(); } + bool GetIsSilent() const { return m_bIsSilent; } + void SetWelcomeMessage ( const QString& strNWelcMess ); QString GetWelcomeMessage() { return strWelcomeMessage; } @@ -312,6 +314,9 @@ class CServer : public QObject, public CServerSlots std::unique_ptr pThreadPool; + bool m_bIsSilent = false; + qint64 m_iLastAudioActivityMs = 0; + signals: void Started(); void Stopped(); diff --git a/src/serverrpc.cpp b/src/serverrpc.cpp index 6ed1b1506e..7d92f8ee78 100644 --- a/src/serverrpc.cpp +++ b/src/serverrpc.cpp @@ -270,6 +270,15 @@ CServerRpc::CServerRpc ( CServer* pServer, CRpcServer* pRpcServer, QObject* pare response["result"] = "acknowledged"; Q_UNUSED ( params ); } ); + + /// @rpc_method jamulusserver/getSilenceStatus + /// @brief Returns whether the server mix is currently silent. + /// @param {object} params - No parameters (empty object). + /// @result {boolean} result.silent - True if all connected clients have been below the audio threshold for ≥2 seconds. False if no clients are connected or audio is active. + pRpcServer->HandleMethod ( "jamulusserver/getSilenceStatus", [=] ( const QJsonObject& params, QJsonObject& response ) { + response["result"] = QJsonObject{ { "silent", pServer->GetIsSilent() } }; + Q_UNUSED ( params ); + } ); } #if defined( Q_OS_MACOS ) && QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )