mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Lots of changes. Big update !
This commit is contained in:
parent
68a56672fc
commit
cda7aed26e
@ -12,10 +12,16 @@ find_package(Qt5WebSockets REQUIRED)
|
||||
|
||||
set(obs-websocket_SOURCES
|
||||
obs-websocket.cpp
|
||||
WSServer.cpp)
|
||||
WSServer.cpp
|
||||
WSRequestHandler.cpp
|
||||
WSEvents.cpp
|
||||
Utils.cpp)
|
||||
|
||||
set(obs-websocket_HEADERS
|
||||
WSServer.h)
|
||||
WSServer.h
|
||||
WSRequestHandler.h
|
||||
WSEvents.h
|
||||
Utils.h)
|
||||
|
||||
add_library(obs-websocket MODULE
|
||||
${obs-websocket_SOURCES}
|
||||
|
30
Utils.cpp
Normal file
30
Utils.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#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);
|
||||
|
||||
/*obs_scene_item *currentItem = scene->first_item;
|
||||
while (currentItem != NULL) {
|
||||
obs_data_array_push_back(items, GetSceneItemData(currentItem));
|
||||
currentItem = currentItem->next;
|
||||
}*/
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
obs_data_t* Utils::GetSceneItemData(obs_scene_item *item) {
|
||||
if (!item) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);*/
|
||||
|
||||
return data;
|
||||
}
|
13
Utils.h
Normal file
13
Utils.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <obs-module.h>
|
||||
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static obs_data_array_t* GetSceneItems(obs_source_t* source);
|
||||
static obs_data_t* GetSceneItemData(obs_scene_item *item);
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
182
WSEvents.cpp
Normal file
182
WSEvents.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
#include "WSEvents.h"
|
||||
|
||||
WSEvents::WSEvents(WSServer *server) {
|
||||
_srv = server;
|
||||
obs_frontend_add_event_callback(WSEvents::FrontendEventHandler, this);
|
||||
|
||||
QTimer *statusTimer = new QTimer();
|
||||
connect(statusTimer, SIGNAL(timeout()), this, SLOT(StreamStatus));
|
||||
statusTimer->start(1000);
|
||||
}
|
||||
|
||||
WSEvents::~WSEvents() {
|
||||
obs_frontend_remove_event_callback(WSEvents::FrontendEventHandler, this);
|
||||
}
|
||||
|
||||
void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void *private_data)
|
||||
{
|
||||
WSEvents *owner = static_cast<WSEvents *>(private_data);
|
||||
|
||||
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
|
||||
owner->OnSceneChange();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTING) {
|
||||
owner->OnStreamStarting();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) {
|
||||
owner->OnStreamStarted();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING) {
|
||||
owner->OnStreamStopping();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED) {
|
||||
owner->OnStreamStopped();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) {
|
||||
owner->OnRecordingStarting();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) {
|
||||
owner->OnRecordingStarted();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTING) {
|
||||
owner->OnRecordingStarting();
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) {
|
||||
owner->OnRecordingStopped();
|
||||
}
|
||||
}
|
||||
|
||||
void WSEvents::broadcastUpdate(const char *updateType, obs_data_t *additionalFields = NULL) {
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
obs_data_t *update = obs_data_create();
|
||||
|
||||
obs_data_set_string(update, "update-type", updateType);
|
||||
if (additionalFields != NULL) {
|
||||
obs_data_apply(update, additionalFields);
|
||||
}
|
||||
|
||||
_srv->broadcast(obs_data_get_json(update));
|
||||
|
||||
obs_data_release(update);
|
||||
}
|
||||
|
||||
void WSEvents::OnSceneChange() {
|
||||
// Implements an existing update type from bilhamil's OBS Remote
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
obs_data_t *data = obs_data_create();
|
||||
obs_data_set_string(data, "scene-name", name);
|
||||
|
||||
broadcastUpdate("SwitchScenes", data);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void WSEvents::OnStreamStarting() {
|
||||
// Implements an existing update type from bilhamil's OBS Remote
|
||||
obs_data_t *data = obs_data_create();
|
||||
obs_data_set_bool(data, "preview-only", false);
|
||||
|
||||
broadcastUpdate("StreamStarting", data);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void WSEvents::OnStreamStarted() {
|
||||
// New update type specific to OBS Studio
|
||||
_streamStartTime = os_gettime_ns();
|
||||
_lastBytesSent = 0;
|
||||
broadcastUpdate("StreamStarted");
|
||||
}
|
||||
|
||||
void WSEvents::OnStreamStopping() {
|
||||
// Implements an existing update type from bilhamil's OBS Remote
|
||||
obs_data_t *data = obs_data_create();
|
||||
obs_data_set_bool(data, "preview-only", false);
|
||||
|
||||
broadcastUpdate("StreamStopping", data);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void WSEvents::OnStreamStopped() {
|
||||
// New update type specific to OBS Studio
|
||||
_streamStartTime = 0;
|
||||
broadcastUpdate("StreamStopped");
|
||||
}
|
||||
|
||||
void WSEvents::OnRecordingStarting() {
|
||||
// New update type specific to OBS Studio
|
||||
broadcastUpdate("RecordingStarting");
|
||||
}
|
||||
|
||||
void WSEvents::OnRecordingStarted() {
|
||||
// New update type specific to OBS Studio
|
||||
broadcastUpdate("RecordingStarted");
|
||||
}
|
||||
|
||||
void WSEvents::OnRecordingStopping() {
|
||||
// New update type specific to OBS Studio
|
||||
broadcastUpdate("RecordingStopping");
|
||||
}
|
||||
|
||||
void WSEvents::OnRecordingStopped() {
|
||||
// New update type specific to OBS Studio
|
||||
broadcastUpdate("RecordingStopped");
|
||||
}
|
||||
|
||||
// TODO : Add a timer to trigger StreamStatus
|
||||
void WSEvents::StreamStatus() {
|
||||
blog(LOG_INFO, "top 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.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t bytesPerSec = 0;
|
||||
|
||||
uint64_t bytesSent = obs_output_get_total_bytes(streamOutput);
|
||||
uint64_t bytesSentTime = os_gettime_ns();
|
||||
|
||||
if (bytesSent < _lastBytesSent) {
|
||||
bytesSent = 0;
|
||||
}
|
||||
if (bytesSent == 0) {
|
||||
_lastBytesSent = 0;
|
||||
}
|
||||
|
||||
uint64_t bitsBetween = (bytesSent - _lastBytesSent) * 8;
|
||||
double timePassed = double(bytesSentTime - _lastBytesSentTime) / 1000000000.0;
|
||||
|
||||
uint64_t bitsPerSec = bitsBetween / timePassed;
|
||||
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);
|
||||
|
||||
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, "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, "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_double(data, "fps", obs_get_active_fps());
|
||||
|
||||
broadcastUpdate("StreamStatus", data);
|
||||
|
||||
obs_data_release(data);
|
||||
}
|
42
WSEvents.h
Normal file
42
WSEvents.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef WSEVENTS_H
|
||||
#define WSEVENTS_H
|
||||
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
#include <QTimer>
|
||||
#include <obs-frontend-api.h>
|
||||
#include <util/platform.h>
|
||||
#include "WSServer.h"
|
||||
|
||||
class WSEvents : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WSEvents(WSServer *server);
|
||||
~WSEvents();
|
||||
static void FrontendEventHandler(enum obs_frontend_event event, void *private_data);
|
||||
|
||||
private Q_SLOTS:
|
||||
void StreamStatus();
|
||||
|
||||
private:
|
||||
WSServer *_srv;
|
||||
uint64_t _streamStartTime;
|
||||
uint64_t _lastBytesSent;
|
||||
uint64_t _lastBytesSentTime;
|
||||
void broadcastUpdate(const char *updateType, obs_data_t *additionalFields);
|
||||
|
||||
void OnSceneChange();
|
||||
|
||||
void OnStreamStarting();
|
||||
void OnStreamStarted();
|
||||
void OnStreamStopping();
|
||||
void OnStreamStopped();
|
||||
|
||||
void OnRecordingStarting();
|
||||
void OnRecordingStarted();
|
||||
void OnRecordingStopping();
|
||||
void OnRecordingStopped();
|
||||
};
|
||||
|
||||
#endif // WSEVENTS_H
|
132
WSRequestHandler.cpp
Normal file
132
WSRequestHandler.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "WSRequestHandler.h"
|
||||
|
||||
WSRequestHandler::WSRequestHandler(QWebSocket *client) {
|
||||
_client = client;
|
||||
|
||||
messageMap["SetCurrentScene"] = WSRequestHandler::HandleSetCurrentScene;
|
||||
messageMap["GetCurrentScene"] = WSRequestHandler::HandleGetCurrentScene;
|
||||
messageMap["GetSceneList"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["SetSourceOrder"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["SetSourceRender"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["SetSceneItemPositionAndSize"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["GetStreamingStatus"] = WSRequestHandler::HandleGetStreamingStatus;
|
||||
messageMap["StartStopStreaming"] = WSRequestHandler::HandleStartStopStreaming;
|
||||
messageMap["StartStopRecording"] = WSRequestHandler::HandleStartStopRecording;
|
||||
messageMap["ToggleMute"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["GetVolumes"] = WSRequestHandler::ErrNotImplemented;
|
||||
messageMap["SetVolume"] = WSRequestHandler::ErrNotImplemented;
|
||||
}
|
||||
|
||||
void WSRequestHandler::handleMessage(const char *message) {
|
||||
_requestData = obs_data_create_from_json(message);
|
||||
if (!_requestData) {
|
||||
blog(LOG_ERROR, "[obs-websockets] invalid JSON payload for '%s'", message);
|
||||
SendErrorResponse("invalid JSON payload");
|
||||
return;
|
||||
}
|
||||
|
||||
_requestType = obs_data_get_string(_requestData, "request-type");
|
||||
_messageId = obs_data_get_int(_requestData, "message-id");
|
||||
|
||||
void (*handlerFunc)(WSRequestHandler*) = (messageMap[_requestType]);
|
||||
|
||||
if (handlerFunc != NULL) {
|
||||
handlerFunc(this);
|
||||
}
|
||||
else {
|
||||
SendErrorResponse("invalid request type");
|
||||
}
|
||||
}
|
||||
|
||||
WSRequestHandler::~WSRequestHandler() {
|
||||
if (_requestData != NULL) {
|
||||
obs_data_release(_requestData);
|
||||
}
|
||||
}
|
||||
|
||||
void WSRequestHandler::SendOKResponse(obs_data_t *additionalFields) {
|
||||
obs_data_t *response = obs_data_create();
|
||||
obs_data_set_string(response, "status", "ok");
|
||||
obs_data_set_int(response, "message-id", _messageId);
|
||||
|
||||
if (additionalFields != NULL) {
|
||||
obs_data_apply(response, additionalFields);
|
||||
}
|
||||
|
||||
_client->sendTextMessage(obs_data_get_json(response));
|
||||
|
||||
obs_data_release(response);
|
||||
}
|
||||
|
||||
void WSRequestHandler::SendErrorResponse(const char *errorMessage) {
|
||||
obs_data_t *response = obs_data_create();
|
||||
obs_data_set_string(response, "status", "error");
|
||||
obs_data_set_string(response, "error", errorMessage);
|
||||
obs_data_set_int(response, "message-id", _messageId);
|
||||
|
||||
_client->sendTextMessage(obs_data_get_json(response));
|
||||
|
||||
obs_data_release(response);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (source) {
|
||||
obs_frontend_set_current_scene(source);
|
||||
owner->SendOKResponse();
|
||||
}
|
||||
else {
|
||||
blog(LOG_ERROR, "[obs-websockets] requested scene '%s' doesn't exist !", sceneName);
|
||||
owner->SendErrorResponse("requested scene does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler *owner) {
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
obs_data_t *data = obs_data_create();
|
||||
obs_data_set_string(data, "name", name);
|
||||
obs_data_set_array(data, "sources", Utils::GetSceneItems(source));
|
||||
|
||||
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());
|
||||
obs_data_set_bool(data, "recording", obs_frontend_recording_active());
|
||||
obs_data_set_bool(data, "preview-only", false);
|
||||
|
||||
owner->SendOKResponse(data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler *owner) {
|
||||
if (obs_frontend_streaming_active()) {
|
||||
obs_frontend_streaming_stop();
|
||||
}
|
||||
else {
|
||||
obs_frontend_streaming_start();
|
||||
}
|
||||
|
||||
owner->SendOKResponse();
|
||||
}
|
||||
|
||||
void WSRequestHandler::HandleStartStopRecording(WSRequestHandler *owner) {
|
||||
if (obs_frontend_recording_active()) {
|
||||
obs_frontend_recording_stop();
|
||||
}
|
||||
else {
|
||||
obs_frontend_recording_start();
|
||||
}
|
||||
|
||||
owner->SendOKResponse();
|
||||
}
|
||||
|
||||
void WSRequestHandler::ErrNotImplemented(WSRequestHandler *owner) {
|
||||
owner->SendErrorResponse("not implemented");
|
||||
}
|
36
WSRequestHandler.h
Normal file
36
WSRequestHandler.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef WSREQUESTHANDLER_H
|
||||
#define WSREQUESTHANDLER_H
|
||||
|
||||
#include <map>
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
#include <obs-frontend-api.h>
|
||||
#include "Utils.h"
|
||||
#include "WSServer.h"
|
||||
|
||||
class WSRequestHandler
|
||||
{
|
||||
public:
|
||||
explicit WSRequestHandler(QWebSocket *client);
|
||||
~WSRequestHandler();
|
||||
void handleMessage(const char* message);
|
||||
|
||||
private:
|
||||
QWebSocket *_client;
|
||||
long _messageId;
|
||||
const char *_requestType;
|
||||
obs_data_t *_requestData;
|
||||
|
||||
std::map<std::string, void(*)(WSRequestHandler*)> messageMap;
|
||||
|
||||
void SendOKResponse(obs_data_t *additionalFields = NULL);
|
||||
void SendErrorResponse(const char *errorMessage);
|
||||
|
||||
static void ErrNotImplemented(WSRequestHandler *owner);
|
||||
static void HandleSetCurrentScene(WSRequestHandler *owner);
|
||||
static void HandleGetCurrentScene(WSRequestHandler *owner);
|
||||
static void HandleGetStreamingStatus(WSRequestHandler *owner);
|
||||
static void HandleStartStopStreaming(WSRequestHandler *owner);
|
||||
static void HandleStartStopRecording(WSRequestHandler *owner);
|
||||
};
|
||||
|
||||
#endif // WSPROTOCOL_H
|
27
WSServer.cpp
27
WSServer.cpp
@ -1,4 +1,5 @@
|
||||
#include "WSServer.h"
|
||||
#include "WSRequestHandler.h"
|
||||
#include <QtWebSockets/QWebSocketServer>
|
||||
#include <QtWebSockets/QWebSocket>
|
||||
#include <QtCore/QDebug>
|
||||
@ -53,29 +54,9 @@ void WSServer::processTextMessage(QString textMessage) {
|
||||
const char *msg = textMessage.toLocal8Bit();
|
||||
blog(LOG_INFO, "[obs-websockets] new message : %s", msg);
|
||||
|
||||
obs_data_t *request = obs_data_create_from_json(msg);
|
||||
if (!request) {
|
||||
blog(LOG_ERROR, "[obs-websockets] invalid JSON payload for '%s'", msg);
|
||||
}
|
||||
|
||||
const char *requestType = obs_data_get_string(request, "request");
|
||||
if (strcmp(requestType, "scene_change") == 0) {
|
||||
const char *sceneName = obs_data_get_string(request, "switch_to");
|
||||
|
||||
blog(LOG_INFO, "[obs-websockets] processing scene change request to %s", sceneName);
|
||||
|
||||
obs_source_t *source = obs_get_source_by_name(sceneName);
|
||||
|
||||
if (source) {
|
||||
obs_frontend_set_current_scene(source);
|
||||
}
|
||||
else {
|
||||
blog(LOG_ERROR, "[obs-websockets] requested scene '%s' doesn't exist !", sceneName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
obs_data_release(request);
|
||||
WSRequestHandler *handler = new WSRequestHandler(pSender);
|
||||
handler->handleMessage(msg);
|
||||
delete handler;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,66 +1,26 @@
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
#include "WSEvents.h"
|
||||
#include "WSServer.h"
|
||||
|
||||
OBS_DECLARE_MODULE()
|
||||
OBS_MODULE_USE_DEFAULT_LOCALE("obs-websocket", "en-US")
|
||||
|
||||
WSEvents *eventHandler;
|
||||
WSServer *server;
|
||||
|
||||
void obs_frontend_callback(enum obs_frontend_event event, void *)
|
||||
{
|
||||
bool sendMessage = false;
|
||||
obs_data_t *announce = obs_data_create();
|
||||
|
||||
if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
|
||||
obs_source_t *source = obs_frontend_get_current_scene();
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
obs_data_set_string(announce, "type", "scene_changed");
|
||||
obs_data_set_string(announce, "name", name);
|
||||
sendMessage = true;
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) {
|
||||
obs_data_set_string(announce, "type", "streaming_started");
|
||||
sendMessage = true;
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPED) {
|
||||
obs_data_set_string(announce, "type", "streaming_stopped");
|
||||
sendMessage = true;
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) {
|
||||
obs_data_set_string(announce, "type", "recording_started");
|
||||
sendMessage = true;
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPED) {
|
||||
obs_data_set_string(announce, "type", "recording_stopped");
|
||||
sendMessage = true;
|
||||
}
|
||||
else if (event == OBS_FRONTEND_EVENT_EXIT) {
|
||||
obs_data_set_string(announce, "type", "exiting");
|
||||
sendMessage = true;
|
||||
}
|
||||
|
||||
if (sendMessage && server) {
|
||||
const char *message = obs_data_get_json(announce);
|
||||
server->broadcast(message);
|
||||
}
|
||||
|
||||
obs_data_release(announce);
|
||||
}
|
||||
|
||||
bool obs_module_load(void)
|
||||
{
|
||||
blog(LOG_INFO, "[obs-websockets] you can haz websockets");
|
||||
|
||||
server = new WSServer(8080);
|
||||
obs_frontend_add_event_callback(obs_frontend_callback, nullptr);
|
||||
|
||||
eventHandler = new WSEvents(server);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void obs_module_unload()
|
||||
{
|
||||
|
||||
blog(LOG_INFO, "[obs-websockets] goodbye !");
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user