mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
requesthandler: Add Outputs requests
Co-authored-by: Ruggero Tomaselli <ruggerotomaselli@gmail.com> Co-authored-by: tt2468 <tt2468@irltoolkit.com>
This commit is contained in:
parent
a22a7cf993
commit
1dd57f6140
@ -151,6 +151,13 @@ const std::unordered_map<std::string, RequestMethodHandler> RequestHandler::_han
|
||||
{"StopReplayBuffer", &RequestHandler::StopReplayBuffer},
|
||||
{"SaveReplayBuffer", &RequestHandler::SaveReplayBuffer},
|
||||
{"GetLastReplayBufferReplay", &RequestHandler::GetLastReplayBufferReplay},
|
||||
{"GetOutputList", &RequestHandler::GetOutputList},
|
||||
{"GetOutputStatus", &RequestHandler::GetOutputStatus},
|
||||
{"ToggleOutput", &RequestHandler::ToggleOutput},
|
||||
{"StartOutput", &RequestHandler::StartOutput},
|
||||
{"StopOutput", &RequestHandler::StopOutput},
|
||||
{"GetOutputSettings", &RequestHandler::GetOutputSettings},
|
||||
{"SetOutputSettings", &RequestHandler::SetOutputSettings},
|
||||
|
||||
// Stream
|
||||
{"GetStreamStatus", &RequestHandler::GetStreamStatus},
|
||||
|
@ -170,6 +170,13 @@ private:
|
||||
RequestResult StopReplayBuffer(const Request &);
|
||||
RequestResult SaveReplayBuffer(const Request &);
|
||||
RequestResult GetLastReplayBufferReplay(const Request &);
|
||||
RequestResult GetOutputList(const Request &);
|
||||
RequestResult GetOutputStatus(const Request &);
|
||||
RequestResult ToggleOutput(const Request &);
|
||||
RequestResult StartOutput(const Request &);
|
||||
RequestResult StopOutput(const Request &);
|
||||
RequestResult GetOutputSettings(const Request &);
|
||||
RequestResult SetOutputSettings(const Request &);
|
||||
|
||||
// Stream
|
||||
RequestResult GetStreamStatus(const Request &);
|
||||
|
@ -275,3 +275,214 @@ RequestResult RequestHandler::GetLastReplayBufferReplay(const Request &)
|
||||
responseData["savedReplayPath"] = Utils::Obs::StringHelper::GetLastReplayBufferFileName();
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of available outputs.
|
||||
*
|
||||
* @requestType GetOutputList
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::GetOutputList(const Request &)
|
||||
{
|
||||
json responseData;
|
||||
responseData["outputs"] = Utils::Obs::ArrayHelper::GetOutputList();
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
*
|
||||
* @responseField outputActive | Boolean | Whether the output is active
|
||||
* @responseField outputReconnecting | Boolean | Whether the output is reconnecting
|
||||
* @responseField outputTimecode | String | Current formatted timecode string for the output
|
||||
* @responseField outputDuration | Number | Current duration in milliseconds for the output
|
||||
* @responseField outputCongestion | Number | Congestion of the output
|
||||
* @responseField outputBytes | Number | Number of bytes sent by the output
|
||||
* @responseField outputSkippedFrames | Number | Number of frames skipped by the output's process
|
||||
* @responseField outputTotalFrames | Number | Total number of frames delivered by the output's process
|
||||
*
|
||||
* @requestType GetOutputStatus
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::GetOutputStatus(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!output)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
uint64_t outputDuration = Utils::Obs::NumberHelper::GetOutputDuration(output);
|
||||
|
||||
json responseData;
|
||||
responseData["outputActive"] = obs_output_active(output);
|
||||
responseData["outputReconnecting"] = obs_output_reconnecting(output);
|
||||
responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration);
|
||||
responseData["outputDuration"] = outputDuration;
|
||||
responseData["outputCongestion"] = obs_output_get_congestion(output);
|
||||
responseData["outputBytes"] = obs_output_get_total_bytes(output);
|
||||
responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(output);
|
||||
responseData["outputTotalFrames"] = obs_output_get_total_frames(output);
|
||||
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the status of an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
*
|
||||
* @responseField outputActive | Boolean | Whether the output is active
|
||||
*
|
||||
* @requestType ToggleOutput
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::ToggleOutput(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!output)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
bool outputActive = obs_output_active(output);
|
||||
if (outputActive)
|
||||
obs_output_stop(output);
|
||||
else
|
||||
obs_output_start(output);
|
||||
|
||||
json responseData;
|
||||
responseData["outputActive"] = !outputActive;
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
*
|
||||
* @requestType StartOutput
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::StartOutput(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!output)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
if (obs_output_active(output))
|
||||
return RequestResult::Error(RequestStatus::OutputRunning);
|
||||
|
||||
obs_output_start(output);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
*
|
||||
* @requestType StopOutput
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::StopOutput(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!output)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
if (!obs_output_active(output))
|
||||
return RequestResult::Error(RequestStatus::OutputNotRunning);
|
||||
|
||||
obs_output_stop(output);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the settings of an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
*
|
||||
* @responseField outputSettings | Object | Output settings
|
||||
*
|
||||
* @requestType GetOutputSettings
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::GetOutputSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!output)
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
OBSDataAutoRelease outputSettings = obs_output_get_settings(output);
|
||||
|
||||
json responseData;
|
||||
responseData["outputSettings"] = Utils::Json::ObsDataToJson(outputSettings);
|
||||
return RequestResult::Success(responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the settings of an output.
|
||||
*
|
||||
* @requestField outputName | String | Output name
|
||||
* @requestField outputSettings | Object | Output settings
|
||||
*
|
||||
* @requestType SetOutputSettings
|
||||
* @complexity 4
|
||||
* @rpcVersion -1
|
||||
* @initialVersion 5.0.0
|
||||
* @api requests
|
||||
* @category outputs
|
||||
*/
|
||||
RequestResult RequestHandler::SetOutputSettings(const Request &request)
|
||||
{
|
||||
RequestStatus::RequestStatus statusCode;
|
||||
std::string comment;
|
||||
OBSOutputAutoRelease output = request.ValidateOutput("outputName", statusCode, comment);
|
||||
if (!(output && request.ValidateObject("outputSettings", statusCode, comment, true)))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
|
||||
OBSDataAutoRelease newSettings = Utils::Json::JsonToObsData(request.RequestData["outputSettings"]);
|
||||
if (!newSettings)
|
||||
// This should never happen
|
||||
return RequestResult::Error(RequestStatus::RequestProcessingFailed,
|
||||
"An internal data conversion operation failed. Please report this!");
|
||||
|
||||
obs_output_update(output, newSettings);
|
||||
|
||||
return RequestResult::Success();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
* @responseField outputReconnecting | Boolean | Whether the output is currently reconnecting
|
||||
* @responseField outputTimecode | String | Current formatted timecode string for the output
|
||||
* @responseField outputDuration | Number | Current duration in milliseconds for the output
|
||||
* @responseField outputCongestion | Number | Congestion of the output
|
||||
* @responseField outputBytes | Number | Number of bytes sent by the output
|
||||
* @responseField outputSkippedFrames | Number | Number of frames skipped by the output's process
|
||||
* @responseField outputTotalFrames | Number | Total number of frames delivered by the output's process
|
||||
@ -48,6 +49,7 @@ RequestResult RequestHandler::GetStreamStatus(const Request &)
|
||||
responseData["outputReconnecting"] = obs_output_reconnecting(streamOutput);
|
||||
responseData["outputTimecode"] = Utils::Obs::StringHelper::DurationToTimecode(outputDuration);
|
||||
responseData["outputDuration"] = outputDuration;
|
||||
responseData["outputCongestion"] = obs_output_get_congestion(streamOutput);
|
||||
responseData["outputBytes"] = (uint64_t)obs_output_get_total_bytes(streamOutput);
|
||||
responseData["outputSkippedFrames"] = obs_output_get_frames_dropped(streamOutput);
|
||||
responseData["outputTotalFrames"] = obs_output_get_total_frames(streamOutput);
|
||||
|
@ -232,7 +232,8 @@ RequestResult RequestHandler::OpenVideoMixProjector(const Request &request)
|
||||
else if (videoMixType == "OBS_WEBSOCKET_VIDEO_MIX_TYPE_MULTIVIEW")
|
||||
projectorType = "Multiview";
|
||||
else
|
||||
return RequestResult::Error(RequestStatus::InvalidRequestField, "The field `videoMixType` has an invalid enum value.");
|
||||
return RequestResult::Error(RequestStatus::InvalidRequestField,
|
||||
"The field `videoMixType` has an invalid enum value.");
|
||||
|
||||
int monitorIndex = -1;
|
||||
if (request.Contains("monitorIndex")) {
|
||||
@ -246,7 +247,8 @@ RequestResult RequestHandler::OpenVideoMixProjector(const Request &request)
|
||||
if (!request.ValidateOptionalString("projectorGeometry", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
if (monitorIndex != -1)
|
||||
return RequestResult::Error(RequestStatus::TooManyRequestFields, "`monitorIndex` and `projectorGeometry` are mutually exclusive.");
|
||||
return RequestResult::Error(RequestStatus::TooManyRequestFields,
|
||||
"`monitorIndex` and `projectorGeometry` are mutually exclusive.");
|
||||
projectorGeometry = request.RequestData["projectorGeometry"];
|
||||
}
|
||||
|
||||
@ -291,7 +293,8 @@ RequestResult RequestHandler::OpenSourceProjector(const Request &request)
|
||||
if (!request.ValidateOptionalString("projectorGeometry", statusCode, comment))
|
||||
return RequestResult::Error(statusCode, comment);
|
||||
if (monitorIndex != -1)
|
||||
return RequestResult::Error(RequestStatus::TooManyRequestFields, "`monitorIndex` and `projectorGeometry` are mutually exclusive.");
|
||||
return RequestResult::Error(RequestStatus::TooManyRequestFields,
|
||||
"`monitorIndex` and `projectorGeometry` are mutually exclusive.");
|
||||
projectorGeometry = request.RequestData["projectorGeometry"];
|
||||
}
|
||||
|
||||
|
@ -354,3 +354,21 @@ obs_sceneitem_t *Request::ValidateSceneItem(const std::string &sceneKeyName, con
|
||||
obs_sceneitem_addref(sceneItem);
|
||||
return sceneItem;
|
||||
}
|
||||
|
||||
obs_output_t *Request::ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const
|
||||
{
|
||||
if (!ValidateString(keyName, statusCode, comment))
|
||||
return nullptr;
|
||||
|
||||
std::string outputName = RequestData[keyName];
|
||||
|
||||
obs_output_t *ret = obs_get_output_by_name(outputName.c_str());
|
||||
if (!ret) {
|
||||
statusCode = RequestStatus::ResourceNotFound;
|
||||
comment = std::string("No output was found with the name `") + outputName + "`.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ struct Request {
|
||||
obs_sceneitem_t *ValidateSceneItem(const std::string &sceneKeyName, const std::string &sceneItemIdKeyName,
|
||||
RequestStatus::RequestStatus &statusCode, std::string &comment,
|
||||
const ObsWebSocketSceneFilter filter = OBS_WEBSOCKET_SCENE_FILTER_SCENE_ONLY) const;
|
||||
obs_output_t *ValidateOutput(const std::string &keyName, RequestStatus::RequestStatus &statusCode,
|
||||
std::string &comment) const;
|
||||
|
||||
std::string RequestType;
|
||||
bool HasRequestData;
|
||||
|
@ -205,6 +205,7 @@ namespace Utils {
|
||||
std::vector<json> GetSceneTransitionList();
|
||||
std::vector<json> GetSourceFilterList(obs_source_t *source);
|
||||
std::vector<std::string> GetFilterKindList();
|
||||
std::vector<json> GetOutputList();
|
||||
}
|
||||
|
||||
namespace ObjectHelper {
|
||||
|
@ -327,3 +327,35 @@ std::vector<json> Utils::Obs::ArrayHelper::GetSourceFilterList(obs_source_t *sou
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
std::vector<json> Utils::Obs::ArrayHelper::GetOutputList()
|
||||
{
|
||||
std::vector<json> outputs;
|
||||
|
||||
auto cb = [](void *param, obs_output_t *output) {
|
||||
auto outputs = reinterpret_cast<std::vector<json> *>(param);
|
||||
|
||||
auto rawFlags = obs_output_get_flags(output);
|
||||
json flags;
|
||||
flags["OBS_OUTPUT_AUDIO"] = !!(rawFlags & OBS_OUTPUT_AUDIO);
|
||||
flags["OBS_OUTPUT_VIDEO"] = !!(rawFlags & OBS_OUTPUT_VIDEO);
|
||||
flags["OBS_OUTPUT_ENCODED"] = !!(rawFlags & OBS_OUTPUT_ENCODED);
|
||||
flags["OBS_OUTPUT_MULTI_TRACK"] = !!(rawFlags & OBS_OUTPUT_MULTI_TRACK);
|
||||
flags["OBS_OUTPUT_SERVICE"] = !!(rawFlags & OBS_OUTPUT_SERVICE);
|
||||
|
||||
json outputJson;
|
||||
outputJson["outputName"] = obs_output_get_name(output);
|
||||
outputJson["outputKind"] = obs_output_get_id(output);
|
||||
outputJson["outputWidth"] = obs_output_get_width(output);
|
||||
outputJson["outputHeight"] = obs_output_get_height(output);
|
||||
outputJson["outputActive"] = obs_output_active(output);
|
||||
outputJson["outputFlags"] = flags;
|
||||
|
||||
outputs->push_back(outputJson);
|
||||
return true;
|
||||
};
|
||||
|
||||
obs_enum_outputs(cb, &outputs);
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user