mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Protocol: add Replay Buffer Events and Requests (#104)
This commit is contained in:
@ -65,6 +65,18 @@ if(WIN32)
|
||||
message(FATAL_ERROR "Could not find OBS Frontend API\'s library !")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(ARCH_NAME "64bit")
|
||||
set(OBS_BUILDDIR_ARCH "build64")
|
||||
else()
|
||||
set(ARCH_NAME "32bit")
|
||||
set(OBS_BUILDDIR_ARCH "build32")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
"${LIBOBS_INCLUDE_DIR}/../${OBS_BUILDDIR_ARCH}/UI"
|
||||
)
|
||||
|
||||
target_link_libraries(obs-websocket
|
||||
"${OBS_FRONTEND_LIB}")
|
||||
|
||||
@ -84,14 +96,6 @@ if(WIN32)
|
||||
# The "release" folder has a structure similar OBS' one on Windows
|
||||
set(RELEASE_DIR "${PROJECT_SOURCE_DIR}/release")
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(ARCH_NAME "64bit")
|
||||
set(OBS_BUILDDIR_ARCH "build64")
|
||||
else()
|
||||
set(ARCH_NAME "32bit")
|
||||
set(OBS_BUILDDIR_ARCH "build32")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET obs-websocket POST_BUILD
|
||||
COMMAND if $<CONFIG:Release>==1 (
|
||||
"${CMAKE_COMMAND}" -E make_directory
|
||||
|
52
Utils.cpp
52
Utils.cpp
@ -473,3 +473,55 @@ QString* Utils::ParseDataToQueryString(obs_data_t* data) {
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
obs_hotkey_t* Utils::FindHotkeyByName(const char* name) {
|
||||
struct current_search {
|
||||
const char* query;
|
||||
obs_hotkey_t* result;
|
||||
};
|
||||
|
||||
current_search search;
|
||||
search.query = name;
|
||||
search.result = nullptr;
|
||||
|
||||
obs_enum_hotkeys([](void* data, obs_hotkey_id id, obs_hotkey_t* hotkey) {
|
||||
current_search* search = static_cast<current_search*>(data);
|
||||
|
||||
const char* hk_name = obs_hotkey_get_name(hotkey);
|
||||
if (strcmp(hk_name, search->query) == 0) {
|
||||
search->result = hotkey;
|
||||
blog(LOG_INFO, "Utils::FindHotkeyByName: found %s", hk_name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, &search);
|
||||
|
||||
return search.result;
|
||||
}
|
||||
|
||||
bool Utils::ReplayBufferEnabled() {
|
||||
config_t* profile = obs_frontend_get_profile_config();
|
||||
const char* outputMode = config_get_string(profile, "Output", "Mode");
|
||||
|
||||
if (strcmp(outputMode, "Simple") == 0) {
|
||||
return config_get_bool(profile, "SimpleOutput", "RecRB");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Utils::RPHotkeySet() {
|
||||
obs_output_t* rp_output = obs_frontend_get_replay_buffer_output();
|
||||
|
||||
obs_data_t *hotkeys = obs_hotkeys_save_output(rp_output);
|
||||
obs_data_array_t *bindings = obs_data_get_array(hotkeys,
|
||||
"ReplayBuffer.Save");
|
||||
|
||||
size_t count = obs_data_array_count(bindings);
|
||||
|
||||
obs_data_array_release(bindings);
|
||||
obs_data_release(hotkeys);
|
||||
obs_output_release(rp_output);
|
||||
|
||||
return (count > 0);
|
||||
}
|
||||
|
3
Utils.h
3
Utils.h
@ -78,6 +78,9 @@ class Utils {
|
||||
static bool SetRecordingFolder(const char* path);
|
||||
|
||||
static QString* ParseDataToQueryString(obs_data_t * data);
|
||||
static obs_hotkey_t* FindHotkeyByName(const char* name);
|
||||
static bool ReplayBufferEnabled();
|
||||
static bool RPHotkeySet();
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
||||
|
56
WSEvents.cpp
56
WSEvents.cpp
@ -164,6 +164,18 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
owner->_recording_active = false;
|
||||
owner->OnRecordingStopped();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING) {
|
||||
owner->OnReplayStarting();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED) {
|
||||
owner->OnReplayStarted();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING) {
|
||||
owner->OnReplayStopping();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED) {
|
||||
owner->OnReplayStopped();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_EXIT) {
|
||||
owner->OnExit();
|
||||
}
|
||||
@ -500,6 +512,50 @@ void WSEvents::OnRecordingStopped() {
|
||||
broadcastUpdate("RecordingStopped");
|
||||
}
|
||||
|
||||
/**
|
||||
* A request to start the replay buffer has been issued.
|
||||
*
|
||||
* @api events
|
||||
* @name ReplayStarting
|
||||
* @category replay buffer
|
||||
*/
|
||||
void WSEvents::OnReplayStarting() {
|
||||
broadcastUpdate("ReplayStarting");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replay Buffer started successfully
|
||||
*
|
||||
* @api events
|
||||
* @name ReplayStarted
|
||||
* @category replay buffer
|
||||
*/
|
||||
void WSEvents::OnReplayStarted() {
|
||||
broadcastUpdate("ReplayStarted");
|
||||
}
|
||||
|
||||
/**
|
||||
* A request to start the replay buffer has been issued.
|
||||
*
|
||||
* @api events
|
||||
* @name ReplayStopping
|
||||
* @category replay buffer
|
||||
*/
|
||||
void WSEvents::OnReplayStopping() {
|
||||
broadcastUpdate("ReplayStopping");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replay Buffer stopped successfully
|
||||
*
|
||||
* @api events
|
||||
* @name ReplayStopped
|
||||
* @category replay buffer
|
||||
*/
|
||||
void WSEvents::OnReplayStopped() {
|
||||
broadcastUpdate("ReplayStopped");
|
||||
}
|
||||
|
||||
/**
|
||||
* OBS is exiting.
|
||||
*
|
||||
|
@ -87,6 +87,11 @@ class WSEvents : public QObject {
|
||||
void OnRecordingStopping();
|
||||
void OnRecordingStopped();
|
||||
|
||||
void OnReplayStarting();
|
||||
void OnReplayStarted();
|
||||
void OnReplayStopping();
|
||||
void OnReplayStopped();
|
||||
|
||||
void OnExit();
|
||||
|
||||
static void OnTransitionBegin(void* param, calldata_t* data);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <obs-data.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "WSEvents.h"
|
||||
@ -63,6 +64,11 @@ WSRequestHandler::WSRequestHandler(QWebSocket* client) :
|
||||
messageMap["StartRecording"] = WSRequestHandler::HandleStartRecording;
|
||||
messageMap["StopRecording"] = WSRequestHandler::HandleStopRecording;
|
||||
|
||||
messageMap["StartStopReplayBuffer"] = WSRequestHandler::HandleStartStopReplayBuffer;
|
||||
messageMap["StartReplayBuffer"] = WSRequestHandler::HandleStartReplayBuffer;
|
||||
messageMap["StopReplayBuffer"] = WSRequestHandler::HandleStopReplayBuffer;
|
||||
messageMap["SaveReplayBuffer"] = WSRequestHandler::HandleSaveReplayBuffer;
|
||||
|
||||
messageMap["SetRecordingFolder"] = WSRequestHandler::HandleSetRecordingFolder;
|
||||
messageMap["GetRecordingFolder"] = WSRequestHandler::HandleGetRecordingFolder;
|
||||
|
||||
@ -644,6 +650,98 @@ void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the Replay Buffer on/off.
|
||||
*
|
||||
* @api requests
|
||||
* @name StartStopReplayBuffer
|
||||
* @category replay buffer
|
||||
*/
|
||||
void WSRequestHandler::HandleStartStopReplayBuffer(WSRequestHandler* req) {
|
||||
if (obs_frontend_replay_buffer_active()) {
|
||||
obs_frontend_replay_buffer_stop();
|
||||
} else {
|
||||
if (!Utils::RPHotkeySet()) {
|
||||
req->SendErrorResponse("replay buffer hotkey not set");
|
||||
return;
|
||||
}
|
||||
obs_frontend_replay_buffer_start();
|
||||
}
|
||||
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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (!Utils::RPHotkeySet()) {
|
||||
req->SendErrorResponse("replay buffer hotkey not set");
|
||||
return;
|
||||
}
|
||||
|
||||
obs_frontend_replay_buffer_start();
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void WSRequestHandler::HandleSaveReplayBuffer(WSRequestHandler* req) {
|
||||
if (!obs_frontend_replay_buffer_active()) {
|
||||
req->SendErrorResponse("replay buffer not active");
|
||||
return;
|
||||
}
|
||||
|
||||
obs_hotkey_t* hk = Utils::FindHotkeyByName("ReplayBuffer.Save");
|
||||
if (hk) {
|
||||
obs_hotkey_trigger_routed_callback(obs_hotkey_get_id(hk), true);
|
||||
req->SendOKResponse();
|
||||
} else {
|
||||
req->SendErrorResponse("failed to save replay buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all transitions available in the frontend's dropdown menu.
|
||||
*
|
||||
@ -1638,7 +1736,7 @@ void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) {
|
||||
/**
|
||||
* Get the path of the current recording folder.
|
||||
*
|
||||
* @return {Stsring} `rec-folder` Path of the recording folder.
|
||||
* @return {String} `rec-folder` Path of the recording folder.
|
||||
*
|
||||
* @api requests
|
||||
* @name GetRecordingFolder
|
||||
|
@ -71,6 +71,11 @@ class WSRequestHandler : public QObject {
|
||||
static void HandleStartRecording(WSRequestHandler* req);
|
||||
static void HandleStopRecording(WSRequestHandler* req);
|
||||
|
||||
static void HandleStartStopReplayBuffer(WSRequestHandler* req);
|
||||
static void HandleStartReplayBuffer(WSRequestHandler* req);
|
||||
static void HandleStopReplayBuffer(WSRequestHandler* req);
|
||||
static void HandleSaveReplayBuffer(WSRequestHandler* req);
|
||||
|
||||
static void HandleSetRecordingFolder(WSRequestHandler* req);
|
||||
static void HandleGetRecordingFolder(WSRequestHandler* req);
|
||||
|
||||
|
Reference in New Issue
Block a user