mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
commit
ac2ae90e8a
@ -42,6 +42,7 @@ set(obs-websocket_SOURCES
|
|||||||
src/WSRequestHandler_Streaming.cpp
|
src/WSRequestHandler_Streaming.cpp
|
||||||
src/WSRequestHandler_StudioMode.cpp
|
src/WSRequestHandler_StudioMode.cpp
|
||||||
src/WSRequestHandler_Transitions.cpp
|
src/WSRequestHandler_Transitions.cpp
|
||||||
|
src/WSRequestHandler_Outputs.cpp
|
||||||
src/WSEvents.cpp
|
src/WSEvents.cpp
|
||||||
src/Config.cpp
|
src/Config.cpp
|
||||||
src/Utils.cpp
|
src/Utils.cpp
|
||||||
|
@ -125,7 +125,12 @@ QHash<QString, HandlerResponse(*)(WSRequestHandler*)> WSRequestHandler::messageM
|
|||||||
{ "GetTextFreetype2Properties", WSRequestHandler::HandleGetTextFreetype2Properties },
|
{ "GetTextFreetype2Properties", WSRequestHandler::HandleGetTextFreetype2Properties },
|
||||||
|
|
||||||
{ "GetBrowserSourceProperties", WSRequestHandler::HandleGetBrowserSourceProperties },
|
{ "GetBrowserSourceProperties", WSRequestHandler::HandleGetBrowserSourceProperties },
|
||||||
{ "SetBrowserSourceProperties", WSRequestHandler::HandleSetBrowserSourceProperties }
|
{ "SetBrowserSourceProperties", WSRequestHandler::HandleSetBrowserSourceProperties },
|
||||||
|
|
||||||
|
{ "ListOutputs", WSRequestHandler::HandleListOutputs },
|
||||||
|
{ "GetOutputInfo", WSRequestHandler::HandleGetOutputInfo },
|
||||||
|
{ "StartOutput", WSRequestHandler::HandleStartOutput },
|
||||||
|
{ "StopOutput", WSRequestHandler::HandleStopOutput }
|
||||||
};
|
};
|
||||||
|
|
||||||
QSet<QString> WSRequestHandler::authNotRequired {
|
QSet<QString> WSRequestHandler::authNotRequired {
|
||||||
@ -196,9 +201,9 @@ HandlerResponse WSRequestHandler::SendOKResponse(obs_data_t* additionalFields) {
|
|||||||
return SendResponse("ok", additionalFields);
|
return SendResponse("ok", additionalFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandlerResponse WSRequestHandler::SendErrorResponse(const char* errorMessage) {
|
HandlerResponse WSRequestHandler::SendErrorResponse(QString errorMessage) {
|
||||||
OBSDataAutoRelease fields = obs_data_create();
|
OBSDataAutoRelease fields = obs_data_create();
|
||||||
obs_data_set_string(fields, "error", errorMessage);
|
obs_data_set_string(fields, "error", errorMessage.toUtf8().constData());
|
||||||
|
|
||||||
return SendResponse("error", fields);
|
return SendResponse("error", fields);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,15 @@ class WSRequestHandler : public QObject {
|
|||||||
std::string processIncomingMessage(std::string& textMessage);
|
std::string processIncomingMessage(std::string& textMessage);
|
||||||
bool hasField(QString name);
|
bool hasField(QString name);
|
||||||
|
|
||||||
|
HandlerResponse SendOKResponse(obs_data_t* additionalFields = nullptr);
|
||||||
|
HandlerResponse SendErrorResponse(QString errorMessage);
|
||||||
|
HandlerResponse SendErrorResponse(obs_data_t* additionalFields = nullptr);
|
||||||
|
HandlerResponse SendResponse(const char* status, obs_data_t* additionalFields = nullptr);
|
||||||
|
|
||||||
|
obs_data_t* parameters() {
|
||||||
|
return this->data;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _messageId;
|
const char* _messageId;
|
||||||
const char* _requestType;
|
const char* _requestType;
|
||||||
@ -51,11 +60,6 @@ class WSRequestHandler : public QObject {
|
|||||||
|
|
||||||
HandlerResponse processRequest(std::string& textMessage);
|
HandlerResponse processRequest(std::string& textMessage);
|
||||||
|
|
||||||
HandlerResponse SendOKResponse(obs_data_t* additionalFields = nullptr);
|
|
||||||
HandlerResponse SendErrorResponse(const char* errorMessage);
|
|
||||||
HandlerResponse SendErrorResponse(obs_data_t* additionalFields = nullptr);
|
|
||||||
HandlerResponse SendResponse(const char* status, obs_data_t* additionalFields = nullptr);
|
|
||||||
|
|
||||||
static QHash<QString, HandlerResponse(*)(WSRequestHandler*)> messageMap;
|
static QHash<QString, HandlerResponse(*)(WSRequestHandler*)> messageMap;
|
||||||
static QSet<QString> authNotRequired;
|
static QSet<QString> authNotRequired;
|
||||||
|
|
||||||
@ -160,4 +164,9 @@ class WSRequestHandler : public QObject {
|
|||||||
|
|
||||||
static HandlerResponse HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
static HandlerResponse HandleSetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
static HandlerResponse HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
static HandlerResponse HandleGetBrowserSourceProperties(WSRequestHandler* req);
|
||||||
|
|
||||||
|
static HandlerResponse HandleListOutputs(WSRequestHandler* req);
|
||||||
|
static HandlerResponse HandleGetOutputInfo(WSRequestHandler* req);
|
||||||
|
static HandlerResponse HandleStartOutput(WSRequestHandler* req);
|
||||||
|
static HandlerResponse HandleStopOutput(WSRequestHandler* req);
|
||||||
};
|
};
|
||||||
|
181
src/WSRequestHandler_Outputs.cpp
Normal file
181
src/WSRequestHandler_Outputs.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include "WSRequestHandler.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} `Output`
|
||||||
|
* @property {String} `name` Output name
|
||||||
|
* @property {String} `type` Output type/kind
|
||||||
|
* @property {int} `width` Video output width
|
||||||
|
* @property {int} `height` Video output height
|
||||||
|
* @property {Object} `flags` Output flags
|
||||||
|
* @property {int} `flags.rawValue` Raw flags value
|
||||||
|
* @property {boolean} `flags.audio` Output uses audio
|
||||||
|
* @property {boolean} `flags.video` Output uses video
|
||||||
|
* @property {boolean} `flags.encoded` Output is encoded
|
||||||
|
* @property {boolean} `flags.multiTrack` Output uses several audio tracks
|
||||||
|
* @property {boolean} `flags.service` Output uses a service
|
||||||
|
* @property {Object} `settings` Output name
|
||||||
|
* @property {boolean} `active` Output status (active or not)
|
||||||
|
* @property {boolean} `reconnecting` Output reconnection status (reconnecting or not)
|
||||||
|
* @property {double} `congestion` Output congestion
|
||||||
|
* @property {int} `totalFrames` Number of frames sent
|
||||||
|
* @property {int} `droppedFrames` Number of frames dropped
|
||||||
|
* @property {int} `totalBytes` Total bytes sent
|
||||||
|
*/
|
||||||
|
obs_data_t* getOutputInfo(obs_output_t* output)
|
||||||
|
{
|
||||||
|
if (!output) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease settings = obs_output_get_settings(output);
|
||||||
|
|
||||||
|
uint32_t rawFlags = obs_output_get_flags(output);
|
||||||
|
OBSDataAutoRelease flags = obs_data_create();
|
||||||
|
obs_data_set_int(flags, "rawValue", rawFlags);
|
||||||
|
obs_data_set_bool(flags, "audio", rawFlags & OBS_OUTPUT_AUDIO);
|
||||||
|
obs_data_set_bool(flags, "video", rawFlags & OBS_OUTPUT_VIDEO);
|
||||||
|
obs_data_set_bool(flags, "encoded", rawFlags & OBS_OUTPUT_ENCODED);
|
||||||
|
obs_data_set_bool(flags, "multiTrack", rawFlags & OBS_OUTPUT_MULTI_TRACK);
|
||||||
|
obs_data_set_bool(flags, "service", rawFlags & OBS_OUTPUT_SERVICE);
|
||||||
|
|
||||||
|
obs_data_t* data = obs_data_create();
|
||||||
|
|
||||||
|
obs_data_set_string(data, "name", obs_output_get_name(output));
|
||||||
|
obs_data_set_string(data, "type", obs_output_get_id(output));
|
||||||
|
obs_data_set_int(data, "width", obs_output_get_width(output));
|
||||||
|
obs_data_set_int(data, "height", obs_output_get_height(output));
|
||||||
|
obs_data_set_obj(data, "flags", flags);
|
||||||
|
obs_data_set_obj(data, "settings", settings);
|
||||||
|
|
||||||
|
obs_data_set_bool(data, "active", obs_output_active(output));
|
||||||
|
obs_data_set_bool(data, "reconnecting", obs_output_reconnecting(output));
|
||||||
|
obs_data_set_double(data, "congestion", obs_output_get_congestion(output));
|
||||||
|
obs_data_set_int(data, "totalFrames", obs_output_get_total_frames(output));
|
||||||
|
obs_data_set_int(data, "droppedFrames", obs_output_get_frames_dropped(output));
|
||||||
|
obs_data_set_int(data, "totalBytes", obs_output_get_total_bytes(output));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandlerResponse findOutputOrFail(WSRequestHandler* req, std::function<HandlerResponse (obs_output_t*)> callback)
|
||||||
|
{
|
||||||
|
if (!req->hasField("outputName")) {
|
||||||
|
return req->SendErrorResponse("missing request parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* outputName = obs_data_get_string(req->parameters(), "outputName");
|
||||||
|
OBSOutputAutoRelease output = obs_get_output_by_name(outputName);
|
||||||
|
if (!output) {
|
||||||
|
return req->SendErrorResponse("specified output doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List existing outputs
|
||||||
|
*
|
||||||
|
* @return {Array<Output>} `outputs` Outputs list
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name ListOutputs
|
||||||
|
* @category outputs
|
||||||
|
* @since 4.7.0
|
||||||
|
*/
|
||||||
|
HandlerResponse WSRequestHandler::HandleListOutputs(WSRequestHandler* req)
|
||||||
|
{
|
||||||
|
OBSDataArrayAutoRelease outputs = obs_data_array_create();
|
||||||
|
|
||||||
|
obs_enum_outputs([](void* param, obs_output_t* output) {
|
||||||
|
obs_data_array_t* outputs = reinterpret_cast<obs_data_array_t*>(param);
|
||||||
|
|
||||||
|
OBSDataAutoRelease outputInfo = getOutputInfo(output);
|
||||||
|
obs_data_array_push_back(outputs, outputInfo);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, outputs);
|
||||||
|
|
||||||
|
OBSDataAutoRelease fields = obs_data_create();
|
||||||
|
obs_data_set_array(fields, "outputs", outputs);
|
||||||
|
return req->SendOKResponse(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about a single output
|
||||||
|
*
|
||||||
|
* @param {String} `outputName` Output name
|
||||||
|
*
|
||||||
|
* @return {Output} `outputInfo` Output info
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name GetOutputInfo
|
||||||
|
* @category outputs
|
||||||
|
* @since 4.7.0
|
||||||
|
*/
|
||||||
|
HandlerResponse WSRequestHandler::HandleGetOutputInfo(WSRequestHandler* req)
|
||||||
|
{
|
||||||
|
return findOutputOrFail(req, [req](obs_output_t* output) {
|
||||||
|
OBSDataAutoRelease outputInfo = getOutputInfo(output);
|
||||||
|
|
||||||
|
OBSDataAutoRelease fields = obs_data_create();
|
||||||
|
obs_data_set_obj(fields, "outputInfo", outputInfo);
|
||||||
|
return req->SendOKResponse(fields);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an output
|
||||||
|
*
|
||||||
|
* @param {String} `outputName` Output name
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name StartOutput
|
||||||
|
* @category outputs
|
||||||
|
* @since 4.7.0
|
||||||
|
*/
|
||||||
|
HandlerResponse WSRequestHandler::HandleStartOutput(WSRequestHandler* req)
|
||||||
|
{
|
||||||
|
return findOutputOrFail(req, [req](obs_output_t* output) {
|
||||||
|
if (obs_output_active(output)) {
|
||||||
|
return req->SendErrorResponse("output already active");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = obs_output_start(output);
|
||||||
|
if (!success) {
|
||||||
|
QString lastError = obs_output_get_last_error(output);
|
||||||
|
QString errorMessage = QString("output start failed: %1").arg(lastError);
|
||||||
|
return req->SendErrorResponse(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return req->SendOKResponse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop an output
|
||||||
|
*
|
||||||
|
* @param {String} `outputName` Output name
|
||||||
|
* @param {boolean (optional)} `force` Force stop (default: false)
|
||||||
|
*
|
||||||
|
* @api requests
|
||||||
|
* @name StopOutput
|
||||||
|
* @category outputs
|
||||||
|
* @since 4.7.0
|
||||||
|
*/
|
||||||
|
HandlerResponse WSRequestHandler::HandleStopOutput(WSRequestHandler* req)
|
||||||
|
{
|
||||||
|
return findOutputOrFail(req, [req](obs_output_t* output) {
|
||||||
|
if (!obs_output_active(output)) {
|
||||||
|
return req->SendErrorResponse("output not active");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forceStop = obs_data_get_bool(req->data, "force");
|
||||||
|
if (forceStop) {
|
||||||
|
obs_output_force_stop(output);
|
||||||
|
} else {
|
||||||
|
obs_output_stop(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return req->SendOKResponse();
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user