diff --git a/src/requesthandler/RequestHandler.cpp b/src/requesthandler/RequestHandler.cpp index 5bcdc488..fa70c6e0 100644 --- a/src/requesthandler/RequestHandler.cpp +++ b/src/requesthandler/RequestHandler.cpp @@ -89,6 +89,7 @@ const std::unordered_map RequestHandler::_han {"GetInputAudioMonitorType", &RequestHandler::GetInputAudioMonitorType}, {"SetInputAudioMonitorType", &RequestHandler::SetInputAudioMonitorType}, {"GetInputAudioTracks", &RequestHandler::GetInputAudioTracks}, + {"SetInputAudioTracks", &RequestHandler::SetInputAudioTracks}, {"GetInputPropertiesListPropertyItems", &RequestHandler::GetInputPropertiesListPropertyItems}, {"PressInputPropertiesButton", &RequestHandler::PressInputPropertiesButton}, diff --git a/src/requesthandler/RequestHandler.h b/src/requesthandler/RequestHandler.h index e1e1def5..6807af4d 100644 --- a/src/requesthandler/RequestHandler.h +++ b/src/requesthandler/RequestHandler.h @@ -107,6 +107,7 @@ class RequestHandler { RequestResult GetInputAudioMonitorType(const Request&); RequestResult SetInputAudioMonitorType(const Request&); RequestResult GetInputAudioTracks(const Request&); + RequestResult SetInputAudioTracks(const Request&); RequestResult GetInputPropertiesListPropertyItems(const Request&); RequestResult PressInputPropertiesButton(const Request&); diff --git a/src/requesthandler/RequestHandler_Inputs.cpp b/src/requesthandler/RequestHandler_Inputs.cpp index 75c1d03f..d8bf11e0 100644 --- a/src/requesthandler/RequestHandler_Inputs.cpp +++ b/src/requesthandler/RequestHandler_Inputs.cpp @@ -715,7 +715,7 @@ RequestResult RequestHandler::SetInputAudioMonitorType(const Request& request) * @responseField inputAudioTracks | Object | Object of audio tracks and associated enable states * * @requestType GetInputAudioTracks - * @complexity 3 + * @complexity 2 * @rpcVersion -1 * @initialVersion 5.0.0 * @api requests @@ -745,6 +745,57 @@ RequestResult RequestHandler::GetInputAudioTracks(const Request& request) return RequestResult::Success(responseData); } +/** + * Sets the enable state of audio tracks of an input. + * + * @requestField inputName | String | Name of the input + * @requestField inputAudioTracks | Object | Track settings to apply + * + * @requestType SetInputAudioTracks + * @complexity 2 + * @rpcVersion -1 + * @initialVersion 5.0.0 + * @api requests + * @category inputs + */ +RequestResult RequestHandler::SetInputAudioTracks(const Request& request) +{ + RequestStatus::RequestStatus statusCode; + std::string comment; + OBSSourceAutoRelease input = request.ValidateInput("inputName", statusCode, comment); + if (!input || !request.ValidateObject("inputAudioTracks", statusCode, comment)) + return RequestResult::Error(statusCode, comment); + + if (!(obs_source_get_output_flags(input) & OBS_SOURCE_AUDIO)) + return RequestResult::Error(RequestStatus::InvalidResourceState, "The specified input does not support audio."); + + json inputAudioTracks = request.RequestData["inputAudioTracks"]; + + long long mixers = obs_source_get_audio_mixers(input); + + for (long long i = 0; i < MAX_AUDIO_MIXES; i++) { + std::string track = std::to_string(i + 1); + + if (!Utils::Json::Contains(inputAudioTracks, track)) + continue; + + if (!inputAudioTracks[track].is_boolean()) + return RequestResult::Error(RequestStatus::InvalidRequestFieldType, "The value of one of your tracks is not a boolean."); + + bool enabled = inputAudioTracks[track]; + + if (enabled) + mixers |= (1 << i); + else + mixers &= ~(1 << i); + } + + // Decided that checking if tracks have actually changed is unnecessary + obs_source_set_audio_mixers(input, mixers); + + return RequestResult::Success(); +} + /** * Gets the items of a list property from an input's properties. * diff --git a/src/utils/Json.cpp b/src/utils/Json.cpp index 65a0c7c0..114f3afe 100644 --- a/src/utils/Json.cpp +++ b/src/utils/Json.cpp @@ -21,7 +21,7 @@ with this program. If not, see #include "Platform.h" #include "../plugin-macros.generated.h" -bool Utils::Json::JsonArrayIsValidObsArray(json j) +bool Utils::Json::JsonArrayIsValidObsArray(const json &j) { for (auto it : j) { if (!it.is_object()) @@ -191,7 +191,7 @@ bool Utils::Json::GetJsonFileContent(std::string fileName, json &content) return true; } -bool Utils::Json::SetJsonFileContent(std::string fileName, json content, bool createNew) +bool Utils::Json::SetJsonFileContent(std::string fileName, const json &content, bool createNew) { std::string textContent = content.dump(2); return Utils::Platform::SetTextFileContent(fileName, textContent, createNew); diff --git a/src/utils/Json.h b/src/utils/Json.h index 1f6aaef8..f2b88f2b 100644 --- a/src/utils/Json.h +++ b/src/utils/Json.h @@ -27,10 +27,11 @@ using json = nlohmann::json; namespace Utils { namespace Json { - bool JsonArrayIsValidObsArray(json j); + bool JsonArrayIsValidObsArray(const json &j); obs_data_t *JsonToObsData(json j); json ObsDataToJson(obs_data_t *d, bool includeDefault = false); bool GetJsonFileContent(std::string fileName, json &content); - bool SetJsonFileContent(std::string fileName, json content, bool createNew = true); + bool SetJsonFileContent(std::string fileName, const json &content, bool createNew = true); + static inline bool Contains(const json &j, std::string key) { return j.contains(key) && !j[key].is_null(); } } }