mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
code: split WSRequestHandler into several code/compile units
This commit is contained in:
parent
2c2d61d908
commit
b764b4d0e5
@ -20,6 +20,16 @@ set(obs-websocket_SOURCES
|
||||
src/obs-websocket.cpp
|
||||
src/WSServer.cpp
|
||||
src/WSRequestHandler.cpp
|
||||
src/WSRequestHandler_General.cpp
|
||||
src/WSRequestHandler_Profiles.cpp
|
||||
src/WSRequestHandler_Recording.cpp
|
||||
src/WSRequestHandler_ReplayBuffer.cpp
|
||||
src/WSRequestHandler_SceneCollections.cpp
|
||||
src/WSRequestHandler_Scenes.cpp
|
||||
src/WSRequestHandler_Sources.cpp
|
||||
src/WSRequestHandler_Streaming.cpp
|
||||
src/WSRequestHandler_StudioMode.cpp
|
||||
src/WSRequestHandler_Transitions.cpp
|
||||
src/WSEvents.cpp
|
||||
src/Config.cpp
|
||||
src/Utils.cpp
|
||||
|
@ -47,6 +47,6 @@ const processComments = comments => {
|
||||
return sorted;
|
||||
};
|
||||
|
||||
const files = glob.sync("./../*.@(cpp|h)");
|
||||
const files = glob.sync("./../src/*.@(cpp|h)");
|
||||
const comments = processComments(parseFiles(files));
|
||||
fs.writeFileSync('./generated/comments.json', JSON.stringify(comments, null, 2));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#define WSREQUESTHANDLER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QWebSocket>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
|
126
src/WSRequestHandler_General.cpp
Normal file
126
src/WSRequestHandler_General.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include <QString>
|
||||
|
||||
#include "Config.h"
|
||||
#include "Utils.h"
|
||||
#include "WSEvents.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Returns the latest version of the plugin and the API.
|
||||
*
|
||||
* @return {double} `version` OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility.
|
||||
* @return {String} `obs-websocket-version` obs-websocket plugin version.
|
||||
* @return {String} `obs-studio-version` OBS Studio program version.
|
||||
* @return {String|Array} `available-requests` List of available request types.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetVersion
|
||||
* @category general
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) {
|
||||
QString obsVersion = Utils::OBSVersionString();
|
||||
|
||||
QList<QString> names = req->messageMap.keys();
|
||||
names.sort(Qt::CaseInsensitive);
|
||||
|
||||
// (Palakis) OBS' data arrays only support object arrays, so I improvised.
|
||||
QString requests;
|
||||
requests += names.takeFirst();
|
||||
for (QString reqName : names) {
|
||||
requests += ("," + reqName);
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION);
|
||||
obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8());
|
||||
obs_data_set_string(data, "available-requests", requests.toUtf8());
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the client if authentication is required. If so, returns authentication parameters `challenge`
|
||||
* and `salt` (see "Authentication" for more information).
|
||||
*
|
||||
* @return {boolean} `authRequired` Indicates whether authentication is required.
|
||||
* @return {String (optional)} `challenge`
|
||||
* @return {String (optional)} `salt`
|
||||
*
|
||||
* @api requests
|
||||
* @name GetAuthRequired
|
||||
* @category general
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) {
|
||||
bool authRequired = Config::Current()->AuthRequired;
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "authRequired", authRequired);
|
||||
|
||||
if (authRequired) {
|
||||
obs_data_set_string(data, "challenge",
|
||||
Config::Current()->SessionChallenge.toUtf8());
|
||||
obs_data_set_string(data, "salt",
|
||||
Config::Current()->Salt.toUtf8());
|
||||
}
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to authenticate the client to the server.
|
||||
*
|
||||
* @param {String} `auth` Response to the auth challenge (see "Authentication" for more information).
|
||||
*
|
||||
* @api requests
|
||||
* @name Authenticate
|
||||
* @category general
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
|
||||
if (!req->hasField("auth")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
QString auth = obs_data_get_string(req->data, "auth");
|
||||
if (auth.isEmpty()) {
|
||||
req->SendErrorResponse("auth not specified!");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((req->_client->property(PROP_AUTHENTICATED).toBool() == false)
|
||||
&& Config::Current()->CheckAuth(auth))
|
||||
{
|
||||
req->_client->setProperty(PROP_AUTHENTICATED, true);
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("Authentication Failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable sending of the Heartbeat event
|
||||
*
|
||||
* @param {boolean} `enable` Starts/Stops emitting heartbeat messages
|
||||
*
|
||||
* @api requests
|
||||
* @name SetHeartbeat
|
||||
* @category general
|
||||
*/
|
||||
void WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
|
||||
if (!req->hasField("enable")) {
|
||||
req->SendErrorResponse("Heartbeat <enable> parameter missing");
|
||||
return;
|
||||
}
|
||||
|
||||
WSEvents::Instance->HeartbeatIsActive =
|
||||
obs_data_get_bool(req->data, "enable");
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_bool(response, "enable",
|
||||
WSEvents::Instance->HeartbeatIsActive);
|
||||
req->SendOKResponse(response);
|
||||
}
|
67
src/WSRequestHandler_Profiles.cpp
Normal file
67
src/WSRequestHandler_Profiles.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Set the currently active profile.
|
||||
*
|
||||
* @param {String} `profile-name` Name of the desired profile.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetCurrentProfile
|
||||
* @category profiles
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) {
|
||||
if (!req->hasField("profile-name")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
QString profileName = obs_data_get_string(req->data, "profile-name");
|
||||
if (!profileName.isEmpty()) {
|
||||
// TODO : check if profile exists
|
||||
obs_frontend_set_current_profile(profileName.toUtf8());
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("invalid request parameters");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the current profile.
|
||||
*
|
||||
* @return {String} `profile-name` Name of the currently active profile.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetCurrentProfile
|
||||
* @category profiles
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) {
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "profile-name",
|
||||
obs_frontend_get_current_profile());
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of available profiles.
|
||||
*
|
||||
* @return {Object|Array} `profiles` List of available profiles.
|
||||
*
|
||||
* @api requests
|
||||
* @name ListProfiles
|
||||
* @category profiles
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) {
|
||||
OBSDataArrayAutoRelease profiles = Utils::GetProfiles();
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_array(response, "profiles", profiles);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
100
src/WSRequestHandler_Recording.cpp
Normal file
100
src/WSRequestHandler_Recording.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Toggle recording on or off.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStopRecording
|
||||
* @category recording
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) {
|
||||
if (obs_frontend_recording_active())
|
||||
obs_frontend_recording_stop();
|
||||
else
|
||||
obs_frontend_recording_start();
|
||||
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording.
|
||||
* Will return an `error` if recording is already active.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartRecording
|
||||
* @category recording
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStartRecording(WSRequestHandler* req) {
|
||||
if (obs_frontend_recording_active() == false) {
|
||||
obs_frontend_recording_start();
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("recording already active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording.
|
||||
* Will return an `error` if recording is not active.
|
||||
*
|
||||
* @api requests
|
||||
* @name StopRecording
|
||||
* @category recording
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) {
|
||||
if (obs_frontend_recording_active() == true) {
|
||||
obs_frontend_recording_stop();
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("recording not active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current recording folder.
|
||||
*
|
||||
* @param {String} `rec-folder` Path of the recording folder.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetRecordingFolder
|
||||
* @category recording
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) {
|
||||
if (!req->hasField("rec-folder")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* newRecFolder = obs_data_get_string(req->data, "rec-folder");
|
||||
bool success = Utils::SetRecordingFolder(newRecFolder);
|
||||
if (success)
|
||||
req->SendOKResponse();
|
||||
else
|
||||
req->SendErrorResponse("invalid request parameters");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of the current recording folder.
|
||||
*
|
||||
* @return {String} `rec-folder` Path of the recording folder.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetRecordingFolder
|
||||
* @category recording
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) {
|
||||
const char* recFolder = Utils::GetRecordingFolder();
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "rec-folder", recFolder);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
92
src/WSRequestHandler_ReplayBuffer.cpp
Normal file
92
src/WSRequestHandler_ReplayBuffer.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Toggle the Replay Buffer on/off.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStopReplayBuffer
|
||||
* @category replay buffer
|
||||
* @since 4.2.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler* req) {
|
||||
if (obs_frontend_replay_buffer_active()) {
|
||||
obs_frontend_replay_buffer_stop();
|
||||
} else {
|
||||
Utils::StartReplayBuffer();
|
||||
}
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording into the Replay Buffer.
|
||||
* Will return an `error` if the Replay Buffer is already active or if the
|
||||
* "Save Replay Buffer" hotkey is not set in OBS' settings.
|
||||
* Setting this hotkey is mandatory, even when triggering saves only
|
||||
* through obs-websocket.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartReplayBuffer
|
||||
* @category replay buffer
|
||||
* @since 4.2.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStartReplayBuffer(WSRequestHandler* req) {
|
||||
if (!Utils::ReplayBufferEnabled()) {
|
||||
req->SendErrorResponse("replay buffer disabled in settings");
|
||||
return;
|
||||
}
|
||||
|
||||
if (obs_frontend_replay_buffer_active() == true) {
|
||||
req->SendErrorResponse("replay buffer already active");
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::StartReplayBuffer();
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording into the Replay Buffer.
|
||||
* Will return an `error` if the Replay Buffer is not active.
|
||||
*
|
||||
* @api requests
|
||||
* @name StopReplayBuffer
|
||||
* @category replay buffer
|
||||
* @since 4.2.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStopReplayBuffer(WSRequestHandler* req) {
|
||||
if (obs_frontend_replay_buffer_active() == true) {
|
||||
obs_frontend_replay_buffer_stop();
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("replay buffer not active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save and flush the contents of the Replay Buffer to disk. This is
|
||||
* basically the same as triggering the "Save Replay Buffer" hotkey.
|
||||
* Will return an `error` if the Replay Buffer is not active.
|
||||
*
|
||||
* @api requests
|
||||
* @name SaveReplayBuffer
|
||||
* @category replay buffer
|
||||
* @since 4.2.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) {
|
||||
if (!obs_frontend_replay_buffer_active()) {
|
||||
req->SendErrorResponse("replay buffer not active");
|
||||
return;
|
||||
}
|
||||
|
||||
OBSOutputAutoRelease replayOutput = obs_frontend_get_replay_buffer_output();
|
||||
|
||||
calldata_t cd = { 0 };
|
||||
proc_handler_t* ph = obs_output_get_proc_handler(replayOutput);
|
||||
proc_handler_call(ph, "save", &cd);
|
||||
calldata_free(&cd);
|
||||
|
||||
req->SendOKResponse();
|
||||
}
|
57
src/WSRequestHandler_SceneCollections.cpp
Normal file
57
src/WSRequestHandler_SceneCollections.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Change the active scene collection.
|
||||
*
|
||||
* @param {String} `sc-name` Name of the desired scene collection.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetCurrentSceneCollection
|
||||
* @category scene collections
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) {
|
||||
if (!req->hasField("sc-name")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
QString sceneCollection = obs_data_get_string(req->data, "sc-name");
|
||||
if (!sceneCollection.isEmpty()) {
|
||||
// TODO : Check if specified profile exists and if changing is allowed
|
||||
obs_frontend_set_current_scene_collection(sceneCollection.toUtf8());
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("invalid request parameters");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the current scene collection.
|
||||
*
|
||||
* @return {String} `sc-name` Name of the currently active scene collection.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetCurrentSceneCollection
|
||||
* @category scene collections
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) {
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "sc-name",
|
||||
obs_frontend_get_current_scene_collection());
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
void WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) {
|
||||
OBSDataArrayAutoRelease sceneCollections = Utils::GetSceneCollections();
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_array(response, "scene-collections", sceneCollections);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
76
src/WSRequestHandler_Scenes.cpp
Normal file
76
src/WSRequestHandler_Scenes.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Switch to the specified scene.
|
||||
*
|
||||
* @param {String} `scene-name` Name of the scene to switch to.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetCurrentScene
|
||||
* @category scenes
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
|
||||
if (!req->hasField("scene-name")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* sceneName = obs_data_get_string(req->data, "scene-name");
|
||||
OBSSourceAutoRelease source = obs_get_source_by_name(sceneName);
|
||||
|
||||
if (source) {
|
||||
obs_frontend_set_current_scene(source);
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("requested scene does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current scene's name and source items.
|
||||
*
|
||||
* @return {String} `name` Name of the currently active scene.
|
||||
* @return {Source|Array} `sources` Ordered list of the current scene's source items.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetCurrentScene
|
||||
* @category scenes
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) {
|
||||
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
||||
OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(currentScene);
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "name", obs_source_get_name(currentScene));
|
||||
obs_data_set_array(data, "sources", sceneItems);
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of scenes in the currently active profile.
|
||||
*
|
||||
* @return {String} `current-scene` Name of the currently active scene.
|
||||
* @return {Scene|Array} `scenes` Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information).
|
||||
*
|
||||
* @api requests
|
||||
* @name GetSceneList
|
||||
* @category scenes
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) {
|
||||
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
||||
OBSDataArrayAutoRelease scenes = Utils::GetScenes();
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "current-scene",
|
||||
obs_source_get_name(currentScene));
|
||||
obs_data_set_array(data, "scenes", scenes);
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
1537
src/WSRequestHandler_Sources.cpp
Normal file
1537
src/WSRequestHandler_Sources.cpp
Normal file
File diff suppressed because it is too large
Load Diff
288
src/WSRequestHandler_Streaming.cpp
Normal file
288
src/WSRequestHandler_Streaming.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
#include "WSEvents.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
#define STREAM_SERVICE_ID "websocket_custom_service"
|
||||
|
||||
/**
|
||||
* Get current streaming and recording status.
|
||||
*
|
||||
* @return {boolean} `streaming` Current streaming status.
|
||||
* @return {boolean} `recording` Current recording status.
|
||||
* @return {String (optional)} `stream-timecode` Time elapsed since streaming started (only present if currently streaming).
|
||||
* @return {String (optional)} `rec-timecode` Time elapsed since recording started (only present if currently recording).
|
||||
* @return {boolean} `preview-only` Always false. Retrocompatibility with OBSRemote.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetStreamingStatus
|
||||
* @category streaming
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) {
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "streaming", obs_frontend_streaming_active());
|
||||
obs_data_set_bool(data, "recording", obs_frontend_recording_active());
|
||||
obs_data_set_bool(data, "preview-only", false);
|
||||
|
||||
const char* tc = nullptr;
|
||||
if (obs_frontend_streaming_active()) {
|
||||
tc = WSEvents::Instance->GetStreamingTimecode();
|
||||
obs_data_set_string(data, "stream-timecode", tc);
|
||||
bfree((void*)tc);
|
||||
}
|
||||
|
||||
if (obs_frontend_recording_active()) {
|
||||
tc = WSEvents::Instance->GetRecordingTimecode();
|
||||
obs_data_set_string(data, "rec-timecode", tc);
|
||||
bfree((void*)tc);
|
||||
}
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle streaming on or off.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStopStreaming
|
||||
* @category streaming
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) {
|
||||
if (obs_frontend_streaming_active())
|
||||
HandleStopStreaming(req);
|
||||
else
|
||||
HandleStartStreaming(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start streaming.
|
||||
* Will return an `error` if streaming is already active.
|
||||
*
|
||||
* @param {Object (optional)} `stream` Special stream configuration. Please note: these won't be saved to OBS' configuration.
|
||||
* @param {String (optional)} `stream.type` If specified ensures the type of stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the `settings` object or an error will occur when starting the stream.
|
||||
* @param {Object (optional)} `stream.metadata` Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the streaming. May be any String, Numeric, or Boolean field.
|
||||
* @param {Object (optional)} `stream.settings` Settings for the stream.
|
||||
* @param {String (optional)} `stream.settings.server` The publish URL.
|
||||
* @param {String (optional)} `stream.settings.key` The publish key of the stream.
|
||||
* @param {boolean (optional)} `stream.settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`.
|
||||
* @param {String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStreaming
|
||||
* @category streaming
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) {
|
||||
if (obs_frontend_streaming_active() == false) {
|
||||
OBSService configuredService = obs_frontend_get_streaming_service();
|
||||
OBSService newService = nullptr;
|
||||
|
||||
// TODO: fix service memory leak
|
||||
|
||||
if (req->hasField("stream")) {
|
||||
OBSDataAutoRelease streamData = obs_data_get_obj(req->data, "stream");
|
||||
OBSDataAutoRelease newSettings = obs_data_get_obj(streamData, "settings");
|
||||
OBSDataAutoRelease newMetadata = obs_data_get_obj(streamData, "metadata");
|
||||
|
||||
OBSDataAutoRelease csHotkeys =
|
||||
obs_hotkeys_save_service(configuredService);
|
||||
|
||||
QString currentType = obs_service_get_type(configuredService);
|
||||
QString newType = obs_data_get_string(streamData, "type");
|
||||
if (newType.isEmpty() || newType.isNull()) {
|
||||
newType = currentType;
|
||||
}
|
||||
|
||||
//Supporting adding metadata parameters to key query string
|
||||
QString query = Utils::ParseDataToQueryString(newMetadata);
|
||||
if (!query.isEmpty()
|
||||
&& obs_data_has_user_value(newSettings, "key"))
|
||||
{
|
||||
const char* key = obs_data_get_string(newSettings, "key");
|
||||
int keylen = strlen(key);
|
||||
|
||||
bool hasQuestionMark = false;
|
||||
for (int i = 0; i < keylen; i++) {
|
||||
if (key[i] == '?') {
|
||||
hasQuestionMark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasQuestionMark) {
|
||||
query.prepend('&');
|
||||
} else {
|
||||
query.prepend('?');
|
||||
}
|
||||
|
||||
query.prepend(key);
|
||||
obs_data_set_string(newSettings, "key", query.toUtf8());
|
||||
}
|
||||
|
||||
if (newType == currentType) {
|
||||
// Service type doesn't change: apply settings to current service
|
||||
|
||||
// By doing this, you can send a request to the websocket
|
||||
// that only contains settings you want to change, instead of
|
||||
// having to do a get and then change them
|
||||
|
||||
OBSDataAutoRelease currentSettings = obs_service_get_settings(configuredService);
|
||||
OBSDataAutoRelease updatedSettings = obs_data_create();
|
||||
|
||||
obs_data_apply(updatedSettings, currentSettings); //first apply the existing settings
|
||||
obs_data_apply(updatedSettings, newSettings); //then apply the settings from the request should they exist
|
||||
|
||||
newService = obs_service_create(
|
||||
newType.toUtf8(), STREAM_SERVICE_ID,
|
||||
updatedSettings, csHotkeys);
|
||||
}
|
||||
else {
|
||||
// Service type changed: override service settings
|
||||
newService = obs_service_create(
|
||||
newType.toUtf8(), STREAM_SERVICE_ID,
|
||||
newSettings, csHotkeys);
|
||||
}
|
||||
|
||||
obs_frontend_set_streaming_service(newService);
|
||||
}
|
||||
|
||||
obs_frontend_streaming_start();
|
||||
|
||||
// Stream settings provided in StartStreaming are not persisted to disk
|
||||
if (newService != nullptr) {
|
||||
obs_frontend_set_streaming_service(configuredService);
|
||||
}
|
||||
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("streaming already active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop streaming.
|
||||
* Will return an `error` if streaming is not active.
|
||||
*
|
||||
* @api requests
|
||||
* @name StopStreaming
|
||||
* @category streaming
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) {
|
||||
if (obs_frontend_streaming_active() == true) {
|
||||
obs_frontend_streaming_stop();
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("streaming not active");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets one or more attributes of the current streaming server settings. Any options not passed will remain unchanged. Returns the updated settings in response. If 'type' is different than the current streaming service type, all settings are required. Returns the full settings of the stream (the same as GetStreamSettings).
|
||||
*
|
||||
* @param {String} `type` The type of streaming service configuration, usually `rtmp_custom` or `rtmp_common`.
|
||||
* @param {Object} `settings` The actual settings of the stream.
|
||||
* @param {String (optional)} `settings.server` The publish URL.
|
||||
* @param {String (optional)} `settings.key` The publish key.
|
||||
* @param {boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.
|
||||
* @param {String (optional)} `settings.username` The username for the streaming service.
|
||||
* @param {String (optional)} `settings.password` The password for the streaming service.
|
||||
* @param {boolean} `save` Persist the settings to disk.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetStreamSettings
|
||||
* @category streaming
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) {
|
||||
OBSService service = obs_frontend_get_streaming_service();
|
||||
|
||||
OBSDataAutoRelease requestSettings = obs_data_get_obj(req->data, "settings");
|
||||
if (!requestSettings) {
|
||||
req->SendErrorResponse("'settings' are required'");
|
||||
return;
|
||||
}
|
||||
|
||||
QString serviceType = obs_service_get_type(service);
|
||||
QString requestedType = obs_data_get_string(req->data, "type");
|
||||
|
||||
if (requestedType != nullptr && requestedType != serviceType) {
|
||||
OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service);
|
||||
service = obs_service_create(
|
||||
requestedType.toUtf8(), STREAM_SERVICE_ID, requestSettings, hotkeys);
|
||||
} else {
|
||||
// If type isn't changing, we should overlay the settings we got
|
||||
// to the existing settings. By doing so, you can send a request that
|
||||
// only contains the settings you want to change, instead of having to
|
||||
// do a get and then change them
|
||||
|
||||
OBSDataAutoRelease existingSettings = obs_service_get_settings(service);
|
||||
OBSDataAutoRelease newSettings = obs_data_create();
|
||||
|
||||
// Apply existing settings
|
||||
obs_data_apply(newSettings, existingSettings);
|
||||
// Then apply the settings from the request
|
||||
obs_data_apply(newSettings, requestSettings);
|
||||
|
||||
obs_service_update(service, newSettings);
|
||||
}
|
||||
|
||||
//if save is specified we should immediately save the streaming service
|
||||
if (obs_data_get_bool(req->data, "save")) {
|
||||
obs_frontend_save_streaming_service();
|
||||
}
|
||||
|
||||
OBSDataAutoRelease serviceSettings = obs_service_get_settings(service);
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "type", requestedType.toUtf8());
|
||||
obs_data_set_obj(response, "settings", serviceSettings);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current streaming server settings.
|
||||
*
|
||||
* @return {String} `type` The type of streaming service configuration. Possible values: 'rtmp_custom' or 'rtmp_common'.
|
||||
* @return {Object} `settings` Stream settings object.
|
||||
* @return {String} `settings.server` The publish URL.
|
||||
* @return {String} `settings.key` The publish key of the stream.
|
||||
* @return {boolean} `settings.use-auth` Indicates whether audentication should be used when connecting to the streaming server.
|
||||
* @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
||||
* @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetStreamSettings
|
||||
* @category streaming
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) {
|
||||
OBSService service = obs_frontend_get_streaming_service();
|
||||
|
||||
const char* serviceType = obs_service_get_type(service);
|
||||
OBSDataAutoRelease settings = obs_service_get_settings(service);
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "type", serviceType);
|
||||
obs_data_set_obj(response, "settings", settings);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current streaming server settings to disk.
|
||||
*
|
||||
* @api requests
|
||||
* @name SaveStreamSettings
|
||||
* @category streaming
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) {
|
||||
obs_frontend_save_streaming_service();
|
||||
req->SendOKResponse();
|
||||
}
|
173
src/WSRequestHandler_StudioMode.cpp
Normal file
173
src/WSRequestHandler_StudioMode.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* Indicates if Studio Mode is currently enabled.
|
||||
*
|
||||
* @return {boolean} `studio-mode` Indicates if Studio Mode is enabled.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetStudioModeStatus
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) {
|
||||
bool previewActive = obs_frontend_preview_program_mode_active();
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_bool(response, "studio-mode", previewActive);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the currently previewed scene and its list of sources.
|
||||
* Will return an `error` if Studio Mode is not enabled.
|
||||
*
|
||||
* @return {String} `name` The name of the active preview scene.
|
||||
* @return {Source|Array} `sources`
|
||||
*
|
||||
* @api requests
|
||||
* @name GetPreviewScene
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) {
|
||||
if (!obs_frontend_preview_program_mode_active()) {
|
||||
req->SendErrorResponse("studio mode not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease scene = obs_frontend_get_current_preview_scene();
|
||||
OBSDataArrayAutoRelease sceneItems = Utils::GetSceneItems(scene);
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "name", obs_source_get_name(scene));
|
||||
obs_data_set_array(data, "sources", sceneItems);
|
||||
|
||||
req->SendOKResponse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active preview scene.
|
||||
* Will return an `error` if Studio Mode is not enabled.
|
||||
*
|
||||
* @param {String} `scene-name` The name of the scene to preview.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetPreviewScene
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) {
|
||||
if (!obs_frontend_preview_program_mode_active()) {
|
||||
req->SendErrorResponse("studio mode not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!req->hasField("scene-name")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* scene_name = obs_data_get_string(req->data, "scene-name");
|
||||
OBSSourceAutoRelease scene = Utils::GetSceneFromNameOrCurrent(scene_name);
|
||||
|
||||
if (scene) {
|
||||
obs_frontend_set_current_preview_scene(scene);
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("specified scene doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitions the currently previewed scene to the main output.
|
||||
* Will return an `error` if Studio Mode is not enabled.
|
||||
*
|
||||
* @param {Object (optional)} `with-transition` Change the active transition before switching scenes. Defaults to the active transition.
|
||||
* @param {String} `with-transition.name` Name of the transition.
|
||||
* @param {int (optional)} `with-transition.duration` Transition duration (in milliseconds).
|
||||
*
|
||||
* @api requests
|
||||
* @name TransitionToProgram
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) {
|
||||
if (!obs_frontend_preview_program_mode_active()) {
|
||||
req->SendErrorResponse("studio mode not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->hasField("with-transition")) {
|
||||
OBSDataAutoRelease transitionInfo =
|
||||
obs_data_get_obj(req->data, "with-transition");
|
||||
|
||||
if (obs_data_has_user_value(transitionInfo, "name")) {
|
||||
QString transitionName =
|
||||
obs_data_get_string(transitionInfo, "name");
|
||||
if (transitionName.isEmpty()) {
|
||||
req->SendErrorResponse("invalid request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = Utils::SetTransitionByName(transitionName);
|
||||
if (!success) {
|
||||
req->SendErrorResponse("specified transition doesn't exist");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (obs_data_has_user_value(transitionInfo, "duration")) {
|
||||
int transitionDuration =
|
||||
obs_data_get_int(transitionInfo, "duration");
|
||||
Utils::SetTransitionDuration(transitionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
Utils::TransitionToProgram();
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables Studio Mode.
|
||||
*
|
||||
* @api requests
|
||||
* @name EnableStudioMode
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) {
|
||||
obs_frontend_set_preview_program_mode(true);
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables Studio Mode.
|
||||
*
|
||||
* @api requests
|
||||
* @name DisableStudioMode
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) {
|
||||
obs_frontend_set_preview_program_mode(false);
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles Studio Mode.
|
||||
*
|
||||
* @api requests
|
||||
* @name ToggleStudioMode
|
||||
* @category studio mode
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) {
|
||||
bool previewProgramMode = obs_frontend_preview_program_mode_active();
|
||||
obs_frontend_set_preview_program_mode(!previewProgramMode);
|
||||
req->SendOKResponse();
|
||||
}
|
126
src/WSRequestHandler_Transitions.cpp
Normal file
126
src/WSRequestHandler_Transitions.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include <QString>
|
||||
#include "Utils.h"
|
||||
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
/**
|
||||
* List of all transitions available in the frontend's dropdown menu.
|
||||
*
|
||||
* @return {String} `current-transition` Name of the currently active transition.
|
||||
* @return {Object|Array} `transitions` List of transitions.
|
||||
* @return {String} `transitions[].name` Name of the transition.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetTransitionList
|
||||
* @category transitions
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) {
|
||||
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
||||
obs_frontend_source_list transitionList = {};
|
||||
obs_frontend_get_transitions(&transitionList);
|
||||
|
||||
OBSDataArrayAutoRelease transitions = obs_data_array_create();
|
||||
for (size_t i = 0; i < transitionList.sources.num; i++) {
|
||||
OBSSource transition = transitionList.sources.array[i];
|
||||
|
||||
OBSDataAutoRelease obj = obs_data_create();
|
||||
obs_data_set_string(obj, "name", obs_source_get_name(transition));
|
||||
obs_data_array_push_back(transitions, obj);
|
||||
}
|
||||
obs_frontend_source_list_free(&transitionList);
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "current-transition",
|
||||
obs_source_get_name(currentTransition));
|
||||
obs_data_set_array(response, "transitions", transitions);
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the currently selected transition in the frontend's dropdown menu.
|
||||
*
|
||||
* @return {String} `name` Name of the selected transition.
|
||||
* @return {int (optional)} `duration` Transition duration (in milliseconds) if supported by the transition.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetCurrentTransition
|
||||
* @category transitions
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) {
|
||||
OBSSourceAutoRelease currentTransition = obs_frontend_get_current_transition();
|
||||
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_string(response, "name",
|
||||
obs_source_get_name(currentTransition));
|
||||
|
||||
if (!obs_transition_fixed(currentTransition))
|
||||
obs_data_set_int(response, "duration", Utils::GetTransitionDuration());
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active transition.
|
||||
*
|
||||
* @param {String} `transition-name` The name of the transition.
|
||||
*
|
||||
* @api requests
|
||||
* @name SetCurrentTransition
|
||||
* @category transitions
|
||||
* @since 0.3
|
||||
*/
|
||||
void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) {
|
||||
if (!req->hasField("transition-name")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = obs_data_get_string(req->data, "transition-name");
|
||||
bool success = Utils::SetTransitionByName(name);
|
||||
if (success)
|
||||
req->SendOKResponse();
|
||||
else
|
||||
req->SendErrorResponse("requested transition does not exist");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the duration of the currently selected transition if supported.
|
||||
*
|
||||
* @param {int} `duration` Desired duration of the transition (in milliseconds).
|
||||
*
|
||||
* @api requests
|
||||
* @name SetTransitionDuration
|
||||
* @category transitions
|
||||
* @since 4.0.0
|
||||
*/
|
||||
void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) {
|
||||
if (!req->hasField("duration")) {
|
||||
req->SendErrorResponse("missing request parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
int ms = obs_data_get_int(req->data, "duration");
|
||||
Utils::SetTransitionDuration(ms);
|
||||
req->SendOKResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the currently selected transition if supported.
|
||||
*
|
||||
* @return {int} `transition-duration` Duration of the current transition (in milliseconds).
|
||||
*
|
||||
* @api requests
|
||||
* @name GetTransitionDuration
|
||||
* @category transitions
|
||||
* @since 4.1.0
|
||||
*/
|
||||
void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) {
|
||||
OBSDataAutoRelease response = obs_data_create();
|
||||
obs_data_set_int(response, "transition-duration",
|
||||
Utils::GetTransitionDuration());
|
||||
|
||||
req->SendOKResponse(response);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user