So tired I can't write a decent commit message

This commit is contained in:
Stéphane Lepin 2016-10-17 01:14:33 +02:00
parent c23eaed283
commit f500f0f296
7 changed files with 142 additions and 38 deletions

View File

@ -18,6 +18,7 @@ set(obs-websocket_SOURCES
Utils.cpp)
set(obs-websocket_HEADERS
obs-websocket.h
WSServer.h
WSRequestHandler.h
WSEvents.h

View File

@ -1,30 +1,63 @@
#include "Utils.h"
obs_data_array_t* Utils::GetSceneItems(obs_source_t *source) {
obs_data_array *items = obs_data_array_create();
obs_scene *scene = obs_scene_from_source(source);
bool enum_scene_items(obs_scene_t *scene, obs_sceneitem_t *currentItem, void *param) {
obs_data_array_t *data = static_cast<obs_data_array *>(param);
obs_data_array_push_back(data, Utils::GetSceneItemData(currentItem));
return true;
}
/*obs_scene_item *currentItem = scene->first_item;
while (currentItem != NULL) {
obs_data_array_push_back(items, GetSceneItemData(currentItem));
currentItem = currentItem->next;
}*/
obs_data_array_t* Utils::GetSceneItems(obs_source_t *source) {
obs_data_array_t *items = obs_data_array_create();
obs_scene_t *scene = obs_scene_from_source(source);
obs_scene_enum_items(scene, enum_scene_items, items);
return items;
}
obs_data_t* Utils::GetSceneItemData(obs_scene_item *item) {
obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t *item) {
if (!item) {
return NULL;
}
vec2 pos;
obs_sceneitem_get_pos(item, &pos);
vec2 bounds;
obs_sceneitem_get_bounds(item, &bounds);
obs_data_t *data = obs_data_create();
/*obs_data_set_string(data, "name", obs_source_get_name(item->source));
obs_data_set_double(data, "x", item->pos.x);
obs_data_set_double(data, "y", item->pos.y);
obs_data_set_double(data, "cx", item->bounds.x);
obs_data_set_double(data, "cy", item->bounds.y);
obs_data_set_bool(data, "render", item->visible);*/
obs_data_set_string(data, "name", obs_source_get_name(obs_sceneitem_get_source(item)));
obs_data_set_string(data, "type", obs_source_get_id(obs_sceneitem_get_source(item)));
obs_data_set_double(data, "volume", obs_source_get_volume(obs_sceneitem_get_source(item)));
obs_data_set_double(data, "x", pos.x);
obs_data_set_double(data, "y", pos.y);
obs_data_set_double(data, "cx", bounds.x);
obs_data_set_double(data, "cy", bounds.y);
obs_data_set_bool(data, "render", obs_sceneitem_visible(item));
return data;
}
obs_data_array_t* Utils::GetScenes() {
obs_frontend_source_list sceneList = {};
obs_frontend_get_scenes(&sceneList);
obs_data_array_t* scenes = obs_data_array_create();
for (size_t i = 0; i < (&sceneList)->sources.num; i++) {
obs_source_t* scene = (&sceneList)->sources.array[i];
obs_data_array_push_back(scenes, GetSceneData(scene));
}
obs_frontend_source_list_free(&sceneList);
return scenes;
}
obs_data_t* Utils::GetSceneData(obs_source *source) {
obs_data_t* sceneData = obs_data_create();
obs_data_set_string(sceneData, "name", obs_source_get_name(source));
obs_data_set_array(sceneData, "sources", GetSceneItems(source));
return sceneData;
}

View File

@ -2,12 +2,16 @@
#define UTILS_H
#include <obs-module.h>
#include <obs-frontend-api.h>
class Utils
{
public:
static obs_data_array_t* GetSceneItems(obs_source_t* source);
static obs_data_t* GetSceneItemData(obs_scene_item *item);
static obs_data_array_t* GetScenes();
static obs_data_t* GetSceneData(obs_source *source);
};
#endif // UTILS_H

View File

@ -5,7 +5,7 @@ WSEvents::WSEvents(WSServer *server) {
obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this);
QTimer *statusTimer = new QTimer();
connect(statusTimer, SIGNAL(timeout()), this, SLOT(StreamStatus));
connect(statusTimer, SIGNAL(timeout()), this, SLOT(StreamStatus()));
statusTimer->start(1000);
}
@ -17,9 +17,14 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void *private
{
WSEvents *owner = static_cast<WSEvents *>(private_data);
// TODO : implement SourceChanged, SourceOrderChanged and RepopulateSources
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
owner->OnSceneChange();
}
else if (event == OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED) {
owner->OnSceneListChange();
}
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING) {
owner->OnStreamStarting();
}
@ -44,6 +49,9 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void *private
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) {
owner->OnRecordingStopped();
}
else if (event == OBS_FRONTEND_EVENT_EXIT) {
owner->OnExit();
}
}
void WSEvents::broadcastUpdate(const char *updateType, obs_data_t *additionalFields = NULL) {
@ -77,6 +85,10 @@ void WSEvents::OnSceneChange() {
obs_source_release(source);
}
void WSEvents::OnSceneListChange() {
broadcastUpdate("ScenesChanged");
}
void WSEvents::OnStreamStarting() {
// Implements an existing update type from bilhamil's OBS Remote
obs_data_t *data = obs_data_create();
@ -130,22 +142,21 @@ void WSEvents::OnRecordingStopped() {
broadcastUpdate("RecordingStopped");
}
// TODO : Add a timer to trigger StreamStatus
void WSEvents::StreamStatus() {
blog(LOG_INFO, "top StreamStatus");
void WSEvents::OnExit() {
// New update type specific to OBS Studio
broadcastUpdate("Exiting");
}
void WSEvents::StreamStatus() {
bool streamingActive = obs_frontend_streaming_active();
bool recordingActive = obs_frontend_recording_active();
obs_output_t *streamOutput = obs_frontend_get_streaming_output();
if (!streamOutput) {
blog(LOG_INFO, "not this time. no stream output running.");
if (!streamOutput || !streamingActive || !recordingActive) {
return;
}
uint64_t bytesPerSec = 0;
uint64_t bytesSent = obs_output_get_total_bytes(streamOutput);
uint64_t bytesSentTime = os_gettime_ns();
@ -160,22 +171,22 @@ void WSEvents::StreamStatus() {
double timePassed = double(bytesSentTime - _lastBytesSentTime) / 1000000000.0;
uint64_t bitsPerSec = bitsBetween / timePassed;
bytesPerSec = bitsPerSec / 8;
uint64_t bytesPerSec = bitsPerSec / 8;
uint64_t totalStreamTime = (os_gettime_ns() - _streamStartTime); // TODO : convert to seconds
uint64_t droppedFrames = obs_output_get_frames_dropped(streamOutput);
uint64_t totalFrames = obs_output_get_total_frames(streamOutput);
_lastBytesSent = bytesSent;
_lastBytesSentTime = bytesSentTime;
uint64_t totalStreamTime = (os_gettime_ns() - _streamStartTime) / 1000000000;
obs_data_t *data = obs_data_create();
obs_data_set_bool(data, "streaming", streamingActive);
obs_data_set_bool(data, "recording", recordingActive); // New in OBS Studio
obs_data_set_bool(data, "recording", recordingActive);
obs_data_set_bool(data, "preview-only", false); // Retrocompat with OBSRemote
obs_data_set_int(data, "bytes-per-sec", bytesPerSec);
obs_data_set_double(data, "strain", 0.0); // TODO
obs_data_set_int(data, "bytes-per-sec", bytesPerSec); // BUG : Computation seems buggy
obs_data_set_double(data, "strain", 0.0); // dafuq is strain
obs_data_set_int(data, "total-stream-time", totalStreamTime);
obs_data_set_int(data, "num-total-frames", totalFrames);
obs_data_set_int(data, "num-dropped-frames", droppedFrames);
obs_data_set_int(data, "num-total-frames", obs_output_get_total_frames(streamOutput));
obs_data_set_int(data, "num-dropped-frames", obs_output_get_frames_dropped(streamOutput));
obs_data_set_double(data, "fps", obs_get_active_fps());
broadcastUpdate("StreamStatus", data);

View File

@ -27,6 +27,7 @@ class WSEvents : public QObject
void broadcastUpdate(const char *updateType, obs_data_t *additionalFields);
void OnSceneChange();
void OnSceneListChange();
void OnStreamStarting();
void OnStreamStarted();
@ -37,6 +38,8 @@ class WSEvents : public QObject
void OnRecordingStarted();
void OnRecordingStopping();
void OnRecordingStopped();
void OnExit();
};
#endif // WSEVENTS_H

View File

@ -1,11 +1,17 @@
#include "WSRequestHandler.h"
#include "obs-websocket.h"
#include "Utils.h"
WSRequestHandler::WSRequestHandler(QWebSocket *client) {
_client = client;
messageMap["GetVersion"] = WSRequestHandler::HandleGetVersion;
messageMap["GetAuthRequired"] = WSRequestHandler::HandleGetAuthRequired;
messageMap["Authenticate"] = WSRequestHandler::HandleAuthenticate;
messageMap["SetCurrentScene"] = WSRequestHandler::HandleSetCurrentScene;
messageMap["GetCurrentScene"] = WSRequestHandler::HandleGetCurrentScene;
messageMap["GetSceneList"] = WSRequestHandler::ErrNotImplemented;
messageMap["GetSceneList"] = WSRequestHandler::HandleGetSceneList;
messageMap["SetSourceOrder"] = WSRequestHandler::ErrNotImplemented;
messageMap["SetSourceRender"] = WSRequestHandler::ErrNotImplemented;
messageMap["SetSceneItemPositionAndSize"] = WSRequestHandler::ErrNotImplemented;
@ -69,6 +75,41 @@ void WSRequestHandler::SendErrorResponse(const char *errorMessage) {
obs_data_release(response);
}
void WSRequestHandler::HandleGetVersion(WSRequestHandler *owner) {
obs_data_t *data = obs_data_create();
obs_data_set_double(data, "version", OBS_WEBSOCKET_VERSION);
owner->SendOKResponse(data);
obs_data_release(data);
}
void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler *owner) {
bool authRequired = false; // Auth isn't implemented yet
obs_data_t *data = obs_data_create();
obs_data_set_bool(data, "authRequired", authRequired);
if (authRequired) {
// Just here for protocol doc
obs_data_set_string(data, "challenge", "");
obs_data_set_string(data, "salt", "");
}
owner->SendOKResponse(data);
obs_data_release(data);
}
void WSRequestHandler::HandleAuthenticate(WSRequestHandler *owner) {
const char *auth = obs_data_get_string(owner->_requestData, "auth");
if (!auth) {
owner->SendErrorResponse("auth not specified!");
return;
}
owner->SendOKResponse();
}
void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler *owner) {
const char *sceneName = obs_data_get_string(owner->_requestData, "scene-name");
obs_source_t *source = obs_get_source_by_name(sceneName);
@ -78,7 +119,6 @@ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler *owner) {
owner->SendOKResponse();
}
else {
blog(LOG_ERROR, "[obs-websockets] requested scene '%s' doesn't exist !", sceneName);
owner->SendErrorResponse("requested scene does not exist");
}
@ -98,6 +138,16 @@ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler *owner) {
obs_source_release(source);
}
void WSRequestHandler::HandleGetSceneList(WSRequestHandler *owner) {
obs_data_t *data = obs_data_create();
obs_data_set_string(data, "current-scene", obs_source_get_name(obs_frontend_get_current_scene()));
obs_data_set_array(data, "scenes", Utils::GetScenes());
owner->SendOKResponse(data);
obs_data_release(data);
}
void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler *owner) {
obs_data_t *data = obs_data_create();
obs_data_set_bool(data, "streaming", obs_frontend_streaming_active());

View File

@ -4,8 +4,6 @@
#include <map>
#include <QtWebSockets/QWebSocket>
#include <obs-frontend-api.h>
#include "Utils.h"
#include "WSServer.h"
class WSRequestHandler
{
@ -24,10 +22,14 @@ class WSRequestHandler
void SendOKResponse(obs_data_t *additionalFields = NULL);
void SendErrorResponse(const char *errorMessage);
static void ErrNotImplemented(WSRequestHandler *owner);
static void HandleGetVersion(WSRequestHandler *owner);
static void HandleGetAuthRequired(WSRequestHandler *owner);
static void HandleAuthenticate(WSRequestHandler *owner);
static void HandleSetCurrentScene(WSRequestHandler *owner);
static void HandleGetCurrentScene(WSRequestHandler *owner);
static void HandleGetSceneList(WSRequestHandler *owner);
static void HandleGetStreamingStatus(WSRequestHandler *owner);
static void HandleStartStopStreaming(WSRequestHandler *owner);
static void HandleStartStopRecording(WSRequestHandler *owner);