diff --git a/PROTOCOL.md b/PROTOCOL.md index d6af0f63..d80e36c0 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -205,7 +205,7 @@ Objects in the "transitions" array have only one field : Get the name of the currently selected transition in the frontend's dropdown menu. __Request fields__ : none -__Request__ : always OK, with these additional fields : +__Response__ : always OK, with these additional fields : - **"name"** (string) : name of the selected transition *New in OBS Studio* @@ -218,6 +218,25 @@ __Response__ : OK if specified transition exists, error otherwise. *New in OBS Studio* +#### "SetVolume" +Set the volume of a specific source. + +__Request fields__ : +- **"source"** (string) : the name of the source +- **"volume"** (double) : the desired volume + +__Response__ : OK if specified source exists, error otherwise. + +#### "GetVolume" +Get the volume of a specific source. + +__Request fields__ : +- **"source"** (string) : name of the source + +__Response__ : OK if source exists, with these additional fields : +- **"name"** (string) : name of the requested source +- **"volume"** (double) : volume of the requested source, on a linear scale (0.0 to 1.0) + ### Authentication A call to `GetAuthRequired` gives the client two elements : - A challenge : a random string that will be used to generate the auth response diff --git a/WSRequestHandler.cpp b/WSRequestHandler.cpp index 046e2932..ba535a9d 100644 --- a/WSRequestHandler.cpp +++ b/WSRequestHandler.cpp @@ -42,19 +42,21 @@ WSRequestHandler::WSRequestHandler(QWebSocket *client) : messageMap["GetStreamingStatus"] = WSRequestHandler::HandleGetStreamingStatus; messageMap["StartStopStreaming"] = WSRequestHandler::HandleStartStopStreaming; messageMap["StartStopRecording"] = WSRequestHandler::HandleStartStopRecording; - messageMap["ToggleMute"] = WSRequestHandler::ErrNotImplemented; - messageMap["GetVolumes"] = WSRequestHandler::ErrNotImplemented; - messageMap["SetVolume"] = WSRequestHandler::ErrNotImplemented; messageMap["GetTransitionList"] = WSRequestHandler::HandleGetTransitionList; messageMap["GetCurrentTransition"] = WSRequestHandler::HandleGetCurrentTransition; messageMap["SetCurrentTransition"] = WSRequestHandler::HandleSetCurrentTransition; + messageMap["SetVolume"] = WSRequestHandler::HandleSetVolume; + messageMap["GetVolume"] = WSRequestHandler::HandleGetVolume; + messageMap["ToggleMute"] = WSRequestHandler::ErrNotImplemented; + messageMap["GetVolumes"] = WSRequestHandler::ErrNotImplemented; + authNotRequired.insert("GetVersion"); authNotRequired.insert("GetAuthRequired"); authNotRequired.insert("Authenticate"); - QByteArray client_ip = _client->peerAddress().toString().toLocal8Bit(); + QByteArray client_ip = _client->peerAddress().toString().toUtf8(); blog(LOG_INFO, "[obs-websockets] new client connection from %s:%d", client_ip.constData(), _client->peerPort()); connect(_client, &QWebSocket::textMessageReceived, this, &WSRequestHandler::processTextMessage); @@ -62,7 +64,7 @@ WSRequestHandler::WSRequestHandler(QWebSocket *client) : } void WSRequestHandler::processTextMessage(QString textMessage) { - QByteArray msgData = textMessage.toLocal8Bit(); + QByteArray msgData = textMessage.toUtf8(); const char *msg = msgData; _requestData = obs_data_create_from_json(msg); @@ -100,7 +102,7 @@ void WSRequestHandler::processTextMessage(QString textMessage) { } void WSRequestHandler::socketDisconnected() { - QByteArray client_ip = _client->peerAddress().toString().toLocal8Bit(); + QByteArray client_ip = _client->peerAddress().toString().toUtf8(); blog(LOG_INFO, "[obs-websockets] client %s:%d disconnected", client_ip.constData(), _client->peerPort()); _authenticated = false; @@ -347,6 +349,46 @@ void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler *owner) { } } +void WSRequestHandler::HandleSetVolume(WSRequestHandler *owner) { + const char *item_name = obs_data_get_string(owner->_requestData, "source"); + float item_volume = obs_data_get_double(owner->_requestData, "volume"); + + if (item_name == NULL || item_volume < 0.0 || item_volume > 1.0) { + owner->SendErrorResponse("invalid request parameters"); + return; + } + + obs_source_t* item = obs_get_source_by_name(item_name); + if (!item) { + owner->SendErrorResponse("specified source doesn't exist"); + return; + } + + obs_source_set_volume(item, item_volume); + owner->SendOKResponse(); + + obs_source_release(item); +} + +void WSRequestHandler::HandleGetVolume(WSRequestHandler *owner) { + const char *item_name = obs_data_get_string(owner->_requestData, "source"); + if (item_name == NULL) { + owner->SendErrorResponse("invalid request parameters"); + return; + } + + obs_source_t* item = obs_get_source_by_name(item_name); + + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "name", item_name); + obs_data_set_double(response, "volume", obs_source_get_volume(item)); + + owner->SendOKResponse(response); + + obs_data_release(response); + obs_source_release(item); +} + void WSRequestHandler::ErrNotImplemented(WSRequestHandler *owner) { owner->SendErrorResponse("not implemented"); } diff --git a/WSRequestHandler.h b/WSRequestHandler.h index f776c646..720cadcd 100644 --- a/WSRequestHandler.h +++ b/WSRequestHandler.h @@ -71,6 +71,9 @@ class WSRequestHandler : public QObject static void HandleGetTransitionList(WSRequestHandler *owner); static void HandleGetCurrentTransition(WSRequestHandler *owner); static void HandleSetCurrentTransition(WSRequestHandler *owner); + + static void HandleSetVolume(WSRequestHandler *owner); + static void HandleGetVolume(WSRequestHandler *owner); }; #endif // WSPROTOCOL_H