diff --git a/WSEvents.cpp b/WSEvents.cpp
index 20942dc0..54f779ed 100644
--- a/WSEvents.cpp
+++ b/WSEvents.cpp
@@ -69,6 +69,9 @@ WSEvents::WSEvents(WSServer* srv) {
QTimer* statusTimer = new QTimer();
connect(statusTimer, SIGNAL(timeout()),
this, SLOT(StreamStatus()));
+ pulse = false;
+ connect(statusTimer, SIGNAL(timeout()),
+ this, SLOT(Heartbeat()));
statusTimer->start(2000); // equal to frontend's constant BITRATE_UPDATE_SECONDS
QListWidget* sceneList = Utils::GetSceneListControl();
@@ -83,6 +86,8 @@ WSEvents::WSEvents(WSServer* srv) {
QTimer::singleShot(1000, this, SLOT(deferredInitOperations()));
+ Heartbeat_active = false;
+
_streaming_active = false;
_recording_active = false;
@@ -664,6 +669,67 @@ void WSEvents::StreamStatus() {
obs_output_release(stream_output);
}
+/************************************************************************************************************
+* Heatbeat is emitted every 2 seconds, when enabled with request: SetHeartbeat *
+* *
+* @return {boolean} `pulse` Toggles between every JSON meassage as an "I am alive" indicator. *
+* @return {string (optional)} `current-profile` Current active profile. *
+* @return {string (optional)} `current-scene` Current active scene. *
+* @return {boolean (optional)} `streaming` Current streaming state. *
+* @return {int (optional)} `total-stream-time` Total time (in seconds) since the stream started. *
+* @return {int (optional)} `total-stream-bytes` Total bytes sent since the stream started. *
+* @return {int (optional)} `total-stream-frames` Total frames streamed since the stream started. *
+* @return {boolean (optional)} `recording` Current recording state. *
+* @return {int (optional)} `total-record-time` Total time (in seconds) since recording started. *
+* @return {int (optional)} `total-record-bytes` Total bytes recorded since the recording started. *
+* @return {int (optional)} `total-record-frames` Total frames recorded since the recording started. *
+* *
+* @api events *
+* @name Heartbeat *
+* @category general *
+************************************************************************ September 2017 *** by RainbowEK ***/
+void WSEvents::Heartbeat() {
+
+ if (!Heartbeat_active) return;
+
+ bool streaming_active = obs_frontend_streaming_active();
+ bool recording_active = obs_frontend_recording_active();
+ obs_data_t* data = obs_data_create();
+ obs_output_t* record_output = obs_frontend_get_recording_output();
+ obs_output_t* stream_output = obs_frontend_get_streaming_output();
+
+ pulse = !pulse;
+ obs_data_set_bool(data, "pulse", pulse);
+
+ obs_data_set_string(data, "current-profile", obs_frontend_get_current_profile());
+
+ obs_source_t* current_scene = obs_frontend_get_current_scene();
+ const char* name = obs_source_get_name(current_scene);
+ obs_source_release(current_scene);
+ obs_data_set_string(data, "current-scene", name);
+
+ obs_data_set_bool(data, "streaming", streaming_active);
+ if (streaming_active) {
+ uint64_t totalStreamTime = (os_gettime_ns() - _stream_starttime) / 1000000000;
+ obs_data_set_int(data, "total-stream-time", totalStreamTime);
+ obs_data_set_int(data, "total-stream-bytes", (uint64_t)obs_output_get_total_bytes(stream_output));
+ obs_data_set_int(data, "total-stream-frames", obs_output_get_total_frames(stream_output));
+ }
+
+ obs_data_set_bool(data, "recording", recording_active);
+ if (recording_active) {
+ uint64_t totalRecordTime = (os_gettime_ns() - _rec_starttime) / 1000000000;
+ obs_data_set_int(data, "total-record-time", totalRecordTime);
+ obs_data_set_int(data, "total-record-bytes", (uint64_t)obs_output_get_total_bytes(record_output));
+ obs_data_set_int(data, "total-record-frames", obs_output_get_total_frames(record_output));
+ }
+
+ broadcastUpdate("Heartbeat", data);
+ obs_data_release(data);
+ obs_output_release(record_output);
+ obs_output_release(stream_output);
+}
+
/**
* The active transition duration has been changed.
*
diff --git a/WSEvents.h b/WSEvents.h
index f93e0a74..68ec90ca 100644
--- a/WSEvents.h
+++ b/WSEvents.h
@@ -22,7 +22,6 @@ with this program. If not, see
#include
#include
-
#include "WSServer.h"
class WSEvents : public QObject {
@@ -41,9 +40,12 @@ class WSEvents : public QObject {
uint64_t GetRecordingTime();
const char* GetRecordingTimecode();
+ bool Heartbeat_active;
+
private slots:
void deferredInitOperations();
void StreamStatus();
+ void Heartbeat();
void TransitionDurationChanged(int ms);
void SelectedSceneChanged(
QListWidgetItem* current, QListWidgetItem* prev);
@@ -54,6 +56,8 @@ class WSEvents : public QObject {
signal_handler_t* transition_handler;
signal_handler_t* scene_handler;
+ bool pulse;
+
bool _streaming_active;
bool _recording_active;
diff --git a/WSRequestHandler.cpp b/WSRequestHandler.cpp
index 62f9b193..a14e543f 100644
--- a/WSRequestHandler.cpp
+++ b/WSRequestHandler.cpp
@@ -45,6 +45,8 @@ WSRequestHandler::WSRequestHandler(QWebSocket* client) :
messageMap["GetAuthRequired"] = WSRequestHandler::HandleGetAuthRequired;
messageMap["Authenticate"] = WSRequestHandler::HandleAuthenticate;
+ messageMap["SetHeartbeat"] = WSRequestHandler::HandleSetHeartbeat;
+
messageMap["SetCurrentScene"] = WSRequestHandler::HandleSetCurrentScene;
messageMap["GetCurrentScene"] = WSRequestHandler::HandleGetCurrentScene;
messageMap["GetSceneList"] = WSRequestHandler::HandleGetSceneList;
@@ -298,6 +300,35 @@ void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) {
}
}
+/************************************************************************************************************
+* Heatbeat update message is emitted every 2 seconds, when enabled with this request. *
+* When the Heartbeat is enabled it always sends a `pulse` to indicate that the host obs is alive. *
+* Read comment from 'void WSEvents::Heartbeat()' for the total picture. *
+* *
+* @param {boolean} `enable` Starts/Stops emitting heartbeat messages *
+* *
+* @api requests *
+* @name HandleSetHeartbeat *
+* @category general *
+************************************************************************ September 2017 *** by RainbowEK ***/
+void WSRequestHandler::HandleSetHeartbeat(WSRequestHandler* req) {
+ if (!req->hasField("enable")) {
+ req->SendErrorResponse("Heartbeat parameter missing");
+ return;
+ }
+
+ obs_data_t* response = obs_data_create();
+
+ bool keyValue = obs_data_get_bool(req->data, "enable");
+ if (keyValue) WSEvents::Instance->Heartbeat_active = true;
+ else WSEvents::Instance->Heartbeat_active = false;
+
+ obs_data_set_bool(response, "enable", keyValue);
+ req->SendOKResponse(response);
+
+ obs_data_release(response);
+}
+
/**
* Switch to the specified scene.
*
diff --git a/WSRequestHandler.h b/WSRequestHandler.h
index c6598b74..c22ccba3 100644
--- a/WSRequestHandler.h
+++ b/WSRequestHandler.h
@@ -53,6 +53,8 @@ class WSRequestHandler : public QObject {
static void HandleGetAuthRequired(WSRequestHandler* req);
static void HandleAuthenticate(WSRequestHandler* req);
+ static void HandleSetHeartbeat(WSRequestHandler* req);
+
static void HandleSetCurrentScene(WSRequestHandler* req);
static void HandleGetCurrentScene(WSRequestHandler* req);
static void HandleGetSceneList(WSRequestHandler* req);