mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
EventHandler: General, Config, Scenes, Inputs
This commit is contained in:
parent
c8eac893f2
commit
45d62e5ce0
@ -78,6 +78,7 @@ set(obs-websocket_SOURCES
|
|||||||
src/eventhandler/EventHandler_General.cpp
|
src/eventhandler/EventHandler_General.cpp
|
||||||
src/eventhandler/EventHandler_Config.cpp
|
src/eventhandler/EventHandler_Config.cpp
|
||||||
src/eventhandler/EventHandler_Scenes.cpp
|
src/eventhandler/EventHandler_Scenes.cpp
|
||||||
|
src/eventhandler/EventHandler_Inputs.cpp
|
||||||
src/requesthandler/RequestHandler.cpp
|
src/requesthandler/RequestHandler.cpp
|
||||||
src/requesthandler/RequestHandler_General.cpp
|
src/requesthandler/RequestHandler_General.cpp
|
||||||
src/requesthandler/rpc/Request.cpp
|
src/requesthandler/rpc/Request.cpp
|
||||||
@ -97,7 +98,7 @@ set(obs-websocket_HEADERS
|
|||||||
src/WebSocketProtocol.h
|
src/WebSocketProtocol.h
|
||||||
src/WebSocketSession.h
|
src/WebSocketSession.h
|
||||||
src/eventhandler/EventHandler.h
|
src/eventhandler/EventHandler.h
|
||||||
src/eventhandler/types/EventSubscriptions.h
|
src/eventhandler/types/EventSubscription.h
|
||||||
src/requesthandler/RequestHandler.h
|
src/requesthandler/RequestHandler.h
|
||||||
src/requesthandler/rpc/Request.h
|
src/requesthandler/rpc/Request.h
|
||||||
src/requesthandler/rpc/RequestResult.h
|
src/requesthandler/rpc/RequestResult.h
|
||||||
|
@ -247,7 +247,7 @@ enum WebSocketCloseCode {
|
|||||||
|
|
||||||
#### EventSubscriptions Enum
|
#### EventSubscriptions Enum
|
||||||
```cpp
|
```cpp
|
||||||
enum EventSubscriptions {
|
enum EventSubscription {
|
||||||
// Set subscriptions to 0 to disable all events
|
// Set subscriptions to 0 to disable all events
|
||||||
None = 0,
|
None = 0,
|
||||||
// Receive events in the `General` category
|
// Receive events in the `General` category
|
||||||
@ -344,7 +344,7 @@ Authentication is not required
|
|||||||
"authentication": string(optional),
|
"authentication": string(optional),
|
||||||
"ignoreInvalidMessages": bool(optional) = false,
|
"ignoreInvalidMessages": bool(optional) = false,
|
||||||
"ignoreNonFatalRequestChecks": bool(optional) = false,
|
"ignoreNonFatalRequestChecks": bool(optional) = false,
|
||||||
"eventSubscriptions": number(optional) = (EventSubscriptions::All)
|
"eventSubscriptions": number(optional) = (EventSubscription::All)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- `rpcVersion` is the version number that the client would like the obs-websocket server to use.
|
- `rpcVersion` is the version number that the client would like the obs-websocket server to use.
|
||||||
@ -397,7 +397,7 @@ Authentication is not required
|
|||||||
{
|
{
|
||||||
"ignoreInvalidMessages": bool(optional) = false,
|
"ignoreInvalidMessages": bool(optional) = false,
|
||||||
"ignoreNonFatalRequestChecks": bool(optional) = false,
|
"ignoreNonFatalRequestChecks": bool(optional) = false,
|
||||||
"eventSubscriptions": number(optional) = (EventSubscriptions::All)
|
"eventSubscriptions": number(optional) = (EventSubscription::All)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- Only the listed parameters may be changed after initial identification. To change a parameter not listed, you must reconnect to the obs-websocket server.
|
- Only the listed parameters may be changed after initial identification. To change a parameter not listed, you must reconnect to the obs-websocket server.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "WebSocketServer.h"
|
#include "WebSocketServer.h"
|
||||||
#include "WebSocketProtocol.h"
|
#include "WebSocketProtocol.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "eventhandler/types/EventSubscription.h"
|
||||||
|
|
||||||
#include "plugin-macros.generated.h"
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
@ -236,7 +237,7 @@ void WebSocketServer::BroadcastEvent(uint64_t requiredIntent, std::string eventT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (_debugEnabled)
|
if (_debugEnabled && (EventSubscription::All & requiredIntent) != 0) // Don't log high volume events
|
||||||
blog(LOG_INFO, "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", eventMessage.dump(2).c_str());
|
blog(LOG_INFO, "[WebSocketServer::BroadcastEvent] Outgoing event:\n%s", eventMessage.dump(2).c_str());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "WebSocketSession.h"
|
#include "WebSocketSession.h"
|
||||||
#include "eventhandler/types/EventSubscriptions.h"
|
#include "eventhandler/types/EventSubscription.h"
|
||||||
|
|
||||||
#include "plugin-macros.generated.h"
|
#include "plugin-macros.generated.h"
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ WebSocketSession::WebSocketSession() :
|
|||||||
_isIdentified(false),
|
_isIdentified(false),
|
||||||
_ignoreInvalidMessages(false),
|
_ignoreInvalidMessages(false),
|
||||||
_ignoreNonFatalRequestChecks(false),
|
_ignoreNonFatalRequestChecks(false),
|
||||||
_eventSubscriptions(EventSubscriptions::All)
|
_eventSubscriptions(EventSubscription::All)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,32 +4,32 @@
|
|||||||
|
|
||||||
std::string GetCalldataString(const calldata_t *data, const char* name)
|
std::string GetCalldataString(const calldata_t *data, const char* name)
|
||||||
{
|
{
|
||||||
const char* value = nullptr;
|
const char* value = calldata_string(data, name);
|
||||||
calldata_get_string(data, name, &value);
|
if (!value)
|
||||||
|
return "";
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHandler::EventHandler(WebSocketServerPtr webSocketServer) :
|
EventHandler::EventHandler(WebSocketServerPtr webSocketServer) :
|
||||||
_webSocketServer(webSocketServer)
|
_webSocketServer(webSocketServer),
|
||||||
|
_obsLoaded(false)
|
||||||
{
|
{
|
||||||
blog(LOG_INFO, "[EventHandler::EventHandler] Setting up event handlers...");
|
blog(LOG_INFO, "[EventHandler::EventHandler] Setting up event handlers...");
|
||||||
|
|
||||||
_cpuUsageInfo = os_cpu_usage_info_start();
|
_cpuUsageInfo = os_cpu_usage_info_start();
|
||||||
|
|
||||||
obs_frontend_add_event_callback(EventHandler::OnFrontendEvent, this);
|
obs_frontend_add_event_callback(OnFrontendEvent, this);
|
||||||
|
|
||||||
signal_handler_t* coreSignalHandler = obs_get_signal_handler();
|
signal_handler_t* coreSignalHandler = obs_get_signal_handler();
|
||||||
if (coreSignalHandler) {
|
if (coreSignalHandler) {
|
||||||
signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
signal_handler_connect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
||||||
|
signal_handler_connect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
|
||||||
signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
signal_handler_connect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
||||||
|
signal_handler_connect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
|
||||||
|
} else {
|
||||||
|
blog(LOG_ERROR, "[EventHandler::EventHandler] Unable to get libobs signal handler!");
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_enum_sources([](void* param, obs_source_t* source) {
|
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
|
||||||
eventHandler->ConnectSourceSignals(source);
|
|
||||||
return true;
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
blog(LOG_INFO, "[EventHandler::EventHandler] Finished.");
|
blog(LOG_INFO, "[EventHandler::EventHandler] Finished.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,24 +39,22 @@ EventHandler::~EventHandler()
|
|||||||
|
|
||||||
os_cpu_usage_info_destroy(_cpuUsageInfo);
|
os_cpu_usage_info_destroy(_cpuUsageInfo);
|
||||||
|
|
||||||
obs_frontend_remove_event_callback(EventHandler::OnFrontendEvent, this);
|
obs_frontend_remove_event_callback(OnFrontendEvent, this);
|
||||||
|
|
||||||
signal_handler_t* coreSignalHandler = obs_get_signal_handler();
|
signal_handler_t* coreSignalHandler = obs_get_signal_handler();
|
||||||
if (coreSignalHandler) {
|
if (coreSignalHandler) {
|
||||||
signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceCreatedMultiHandler, this);
|
signal_handler_disconnect(coreSignalHandler, "source_create", SourceCreatedMultiHandler, this);
|
||||||
|
signal_handler_disconnect(coreSignalHandler, "source_destroy", SourceDestroyedMultiHandler, this);
|
||||||
signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
signal_handler_disconnect(coreSignalHandler, "source_remove", SourceRemovedMultiHandler, this);
|
||||||
|
signal_handler_disconnect(coreSignalHandler, "source_rename", SourceRenamedMultiHandler, this);
|
||||||
|
} else {
|
||||||
|
blog(LOG_ERROR, "[EventHandler::~EventHandler] Unable to get libobs signal handler!");
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_enum_sources([](void* param, obs_source_t* source) {
|
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
|
||||||
eventHandler->DisconnectSourceSignals(source);
|
|
||||||
return true;
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
blog(LOG_INFO, "[EventHandler::~EventHandler] Finished.");
|
blog(LOG_INFO, "[EventHandler::~EventHandler] Finished.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::ConnectSourceSignals(obs_source_t *source)
|
void EventHandler::ConnectSourceSignals(obs_source_t *source) // These signals are only reliably connected to inputs.
|
||||||
{
|
{
|
||||||
if (!source || obs_source_removed(source))
|
if (!source || obs_source_removed(source))
|
||||||
return;
|
return;
|
||||||
@ -65,7 +63,15 @@ void EventHandler::ConnectSourceSignals(obs_source_t *source)
|
|||||||
|
|
||||||
signal_handler_t* sh = obs_source_get_signal_handler(source);
|
signal_handler_t* sh = obs_source_get_signal_handler(source);
|
||||||
|
|
||||||
signal_handler_connect(sh, "rename", SourceRenamedMultiHandler, this);
|
// Inputs
|
||||||
|
signal_handler_connect(sh, "activate", HandleInputActiveStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "show", HandleInputShowStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "hide", HandleInputShowStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "mute", HandleInputMuteStateChanged, this);
|
||||||
|
signal_handler_connect(sh, "volume", HandleInputVolumeChanged, this);
|
||||||
|
signal_handler_connect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
||||||
|
signal_handler_connect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
||||||
@ -75,16 +81,54 @@ void EventHandler::DisconnectSourceSignals(obs_source_t *source)
|
|||||||
|
|
||||||
signal_handler_t* sh = obs_source_get_signal_handler(source);
|
signal_handler_t* sh = obs_source_get_signal_handler(source);
|
||||||
|
|
||||||
signal_handler_disconnect(sh, "rename", SourceRenamedMultiHandler, this);
|
// Inputs
|
||||||
|
signal_handler_disconnect(sh, "activate", HandleInputActiveStateChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "deactivate", HandleInputActiveStateChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "show", HandleInputShowStateChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "hide", HandleInputShowStateChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "mute", HandleInputMuteStateChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "volume", HandleInputVolumeChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "audio_sync", HandleInputAudioSyncOffsetChanged, this);
|
||||||
|
signal_handler_disconnect(sh, "audio_mixers", HandleInputAudioTracksChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_data) {
|
void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_data)
|
||||||
|
{
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(private_data);
|
auto eventHandler = reinterpret_cast<EventHandler*>(private_data);
|
||||||
|
|
||||||
|
if (!eventHandler->_obsLoaded.load()) {
|
||||||
|
if (event == OBS_FRONTEND_EVENT_FINISHED_LOADING) {
|
||||||
|
blog(LOG_INFO, "[EventHandler::OnFrontendEvent] OBS has finished loading. Connecting final handlers and enabling events...");
|
||||||
|
// Connect source signals and enable events only after OBS has fully loaded (to reduce extra logging).
|
||||||
|
eventHandler->_obsLoaded.store(true);
|
||||||
|
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::EventHandler()`
|
||||||
|
obs_enum_sources([](void* param, obs_source_t* source) {
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
eventHandler->ConnectSourceSignals(source);
|
||||||
|
return true;
|
||||||
|
}, private_data);
|
||||||
|
blog(LOG_INFO, "[EventHandler::OnFrontendEvent] Finished.");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
// General
|
// General
|
||||||
case OBS_FRONTEND_EVENT_EXIT:
|
case OBS_FRONTEND_EVENT_EXIT:
|
||||||
eventHandler->HandleExitStarted();
|
eventHandler->HandleExitStarted();
|
||||||
|
|
||||||
|
blog(LOG_INFO, "[EventHandler::OnFrontendEvent] OBS is unloading. Disabling events...");
|
||||||
|
// Disconnect source signals and disable events when OBS starts unloading (to reduce extra logging).
|
||||||
|
eventHandler->_obsLoaded.store(false);
|
||||||
|
// In the case that plugins become hotloadable, this will have to go back into `EventHandler::~EventHandler()`
|
||||||
|
obs_enum_sources([](void* param, obs_source_t* source) {
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
eventHandler->DisconnectSourceSignals(source);
|
||||||
|
return true;
|
||||||
|
}, private_data);
|
||||||
|
blog(LOG_INFO, "[EventHandler::OnFrontendEvent] Finished.");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED:
|
case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED:
|
||||||
eventHandler->HandleStudioModeStateChanged(true);
|
eventHandler->HandleStudioModeStateChanged(true);
|
||||||
@ -163,17 +207,53 @@ void EventHandler::OnFrontendEvent(enum obs_frontend_event event, void *private_
|
|||||||
|
|
||||||
void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
|
void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
|
||||||
{
|
{
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(data);
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
if (!eventHandler->_obsLoaded.load())
|
||||||
|
return;
|
||||||
|
|
||||||
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
if (!source)
|
if (!source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obs_source_type sourceType = obs_source_get_type(source);
|
// Connect all signals from the source
|
||||||
switch (sourceType) {
|
eventHandler->ConnectSourceSignals(source);
|
||||||
|
|
||||||
|
switch (obs_source_get_type(source)) {
|
||||||
case OBS_SOURCE_TYPE_INPUT:
|
case OBS_SOURCE_TYPE_INPUT:
|
||||||
|
eventHandler->HandleInputCreated(source);
|
||||||
|
break;
|
||||||
|
case OBS_SOURCE_TYPE_FILTER:
|
||||||
|
break;
|
||||||
|
case OBS_SOURCE_TYPE_TRANSITION:
|
||||||
|
break;
|
||||||
|
case OBS_SOURCE_TYPE_SCENE:
|
||||||
eventHandler->HandleSceneCreated(source);
|
eventHandler->HandleSceneCreated(source);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
if (!eventHandler->_obsLoaded.load())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We can't use any smart types because releasing the source will cause infinite recursion
|
||||||
|
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Disconnect all signals from the source
|
||||||
|
eventHandler->DisconnectSourceSignals(source);
|
||||||
|
|
||||||
|
switch (obs_source_get_type(source)) {
|
||||||
|
case OBS_SOURCE_TYPE_INPUT:
|
||||||
|
eventHandler->HandleInputRemoved(source); // We have to call `InputRemoved` with source_destroy because source_removed is not called when a source is *only* destroyed
|
||||||
|
break;
|
||||||
case OBS_SOURCE_TYPE_FILTER:
|
case OBS_SOURCE_TYPE_FILTER:
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_TRANSITION:
|
case OBS_SOURCE_TYPE_TRANSITION:
|
||||||
@ -187,22 +267,24 @@ void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
|
|||||||
|
|
||||||
void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
|
void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
|
||||||
{
|
{
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(data);
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
if (!eventHandler->_obsLoaded.load())
|
||||||
|
return;
|
||||||
|
|
||||||
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
if (!source)
|
if (!source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obs_source_type sourceType = obs_source_get_type(source);
|
switch (obs_source_get_type(source)) {
|
||||||
switch (sourceType) {
|
|
||||||
case OBS_SOURCE_TYPE_INPUT:
|
case OBS_SOURCE_TYPE_INPUT:
|
||||||
eventHandler->HandleSceneRemoved(source);
|
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_FILTER:
|
case OBS_SOURCE_TYPE_FILTER:
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_TRANSITION:
|
case OBS_SOURCE_TYPE_TRANSITION:
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_SCENE:
|
case OBS_SOURCE_TYPE_SCENE:
|
||||||
|
eventHandler->HandleSceneRemoved(source);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -211,27 +293,30 @@ void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
|
|||||||
|
|
||||||
void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
|
void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
|
||||||
{
|
{
|
||||||
auto eventHandler = reinterpret_cast<EventHandler*>(data);
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
if (!eventHandler->_obsLoaded.load())
|
||||||
|
return;
|
||||||
|
|
||||||
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
if (!source)
|
if (!source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string oldSourceName = GetCalldataString(data, "old_name");
|
std::string oldSourceName = GetCalldataString(data, "prev_name");
|
||||||
std::string sourceName = GetCalldataString(data, "new_name");
|
std::string sourceName = GetCalldataString(data, "new_name");
|
||||||
if (oldSourceName.empty() || sourceName.empty())
|
if (oldSourceName.empty() || sourceName.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obs_source_type sourceType = obs_source_get_type(source);
|
switch (obs_source_get_type(source)) {
|
||||||
switch (sourceType) {
|
|
||||||
case OBS_SOURCE_TYPE_INPUT:
|
case OBS_SOURCE_TYPE_INPUT:
|
||||||
eventHandler->HandleSceneNameChanged(source, oldSourceName, sourceName);
|
eventHandler->HandleInputNameChanged(source, oldSourceName, sourceName);
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_FILTER:
|
case OBS_SOURCE_TYPE_FILTER:
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_TRANSITION:
|
case OBS_SOURCE_TYPE_TRANSITION:
|
||||||
break;
|
break;
|
||||||
case OBS_SOURCE_TYPE_SCENE:
|
case OBS_SOURCE_TYPE_SCENE:
|
||||||
|
eventHandler->HandleSceneNameChanged(source, oldSourceName, sourceName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "../obs-websocket.h"
|
#include "../obs-websocket.h"
|
||||||
#include "../WebSocketServer.h"
|
#include "../WebSocketServer.h"
|
||||||
#include "types/EventSubscriptions.h"
|
#include "types/EventSubscription.h"
|
||||||
|
|
||||||
template <typename T> T* GetCalldataPointer(const calldata_t *data, const char* name) {
|
template <typename T> T* GetCalldataPointer(const calldata_t *data, const char* name) {
|
||||||
void* ptr = nullptr;
|
void* ptr = nullptr;
|
||||||
@ -26,6 +26,8 @@ class EventHandler
|
|||||||
WebSocketServerPtr _webSocketServer;
|
WebSocketServerPtr _webSocketServer;
|
||||||
os_cpu_usage_info_t *_cpuUsageInfo;
|
os_cpu_usage_info_t *_cpuUsageInfo;
|
||||||
|
|
||||||
|
std::atomic<bool> _obsLoaded;
|
||||||
|
|
||||||
void ConnectSourceSignals(obs_source_t *source);
|
void ConnectSourceSignals(obs_source_t *source);
|
||||||
void DisconnectSourceSignals(obs_source_t *source);
|
void DisconnectSourceSignals(obs_source_t *source);
|
||||||
|
|
||||||
@ -34,11 +36,13 @@ class EventHandler
|
|||||||
|
|
||||||
// Signal handler: libobs
|
// Signal handler: libobs
|
||||||
static void SourceCreatedMultiHandler(void *param, calldata_t *data);
|
static void SourceCreatedMultiHandler(void *param, calldata_t *data);
|
||||||
|
static void SourceDestroyedMultiHandler(void *param, calldata_t *data);
|
||||||
static void SourceRemovedMultiHandler(void *param, calldata_t *data);
|
static void SourceRemovedMultiHandler(void *param, calldata_t *data);
|
||||||
|
|
||||||
// Signal handler: source
|
// Signal handler: source
|
||||||
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
|
static void SourceRenamedMultiHandler(void *param, calldata_t *data);
|
||||||
|
|
||||||
|
|
||||||
// General
|
// General
|
||||||
void HandleExitStarted();
|
void HandleExitStarted();
|
||||||
void HandleStudioModeStateChanged(bool enabled);
|
void HandleStudioModeStateChanged(bool enabled);
|
||||||
@ -56,4 +60,15 @@ class EventHandler
|
|||||||
void HandleCurrentSceneChanged();
|
void HandleCurrentSceneChanged();
|
||||||
void HandleCurrentPreviewSceneChanged();
|
void HandleCurrentPreviewSceneChanged();
|
||||||
void HandleSceneListReindexed();
|
void HandleSceneListReindexed();
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
void HandleInputCreated(obs_source_t *source);
|
||||||
|
void HandleInputRemoved(obs_source_t *source);
|
||||||
|
void HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName);
|
||||||
|
static void HandleInputActiveStateChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleInputShowStateChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleInputMuteStateChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleInputVolumeChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data); // Direct callback
|
||||||
|
static void HandleInputAudioTracksChanged(void *param, calldata_t *data); // Direct callback
|
||||||
};
|
};
|
||||||
|
@ -4,20 +4,28 @@
|
|||||||
|
|
||||||
void EventHandler::HandleCurrentSceneCollectionChanged()
|
void EventHandler::HandleCurrentSceneCollectionChanged()
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["sceneCollectionName"] = obs_frontend_get_current_scene_collection();
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Config, "CurrentSceneCollectionChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleSceneCollectionListChanged()
|
void EventHandler::HandleSceneCollectionListChanged()
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["sceneCollections"] = Utils::Obs::ListHelper::GetSceneCollectionList();
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Config, "SceneCollectionListChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleCurrentProfileChanged()
|
void EventHandler::HandleCurrentProfileChanged()
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["profileName"] = obs_frontend_get_current_profile();
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Config, "CurrentProfileChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleProfileListChanged()
|
void EventHandler::HandleProfileListChanged()
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["profiles"] = Utils::Obs::ListHelper::GetProfileList();
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Config, "ProfileListChanged", eventData);
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
void EventHandler::HandleExitStarted()
|
void EventHandler::HandleExitStarted()
|
||||||
{
|
{
|
||||||
_webSocketServer->BroadcastEvent(EventSubscriptions::General, "ExitStarted");
|
_webSocketServer->BroadcastEvent(EventSubscription::General, "ExitStarted");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleStudioModeStateChanged(bool enabled)
|
void EventHandler::HandleStudioModeStateChanged(bool enabled)
|
||||||
{
|
{
|
||||||
json eventData;
|
json eventData;
|
||||||
eventData["studioModeEnabled"] = enabled;
|
eventData["studioModeEnabled"] = enabled;
|
||||||
_webSocketServer->BroadcastEvent(EventSubscriptions::General, "StudioModeStateChanged", eventData);
|
_webSocketServer->BroadcastEvent(EventSubscription::General, "StudioModeStateChanged", eventData);
|
||||||
}
|
}
|
||||||
|
151
src/eventhandler/EventHandler_Inputs.cpp
Normal file
151
src/eventhandler/EventHandler_Inputs.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include "EventHandler.h"
|
||||||
|
|
||||||
|
#include "../plugin-macros.generated.h"
|
||||||
|
|
||||||
|
void EventHandler::HandleInputCreated(obs_source_t *source)
|
||||||
|
{
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputCreated", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputRemoved(obs_source_t *source)
|
||||||
|
{
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputRemoved", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputNameChanged(obs_source_t *source, std::string oldInputName, std::string inputName)
|
||||||
|
{
|
||||||
|
json eventData;
|
||||||
|
eventData["oldInputName"] = oldInputName;
|
||||||
|
eventData["inputName"] = inputName;
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputNameChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputActiveStateChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["videoActive"] = obs_source_active(source);
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputActiveStateChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputShowStateChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["videoShowing"] = obs_source_showing(source);
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputShowStateChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputMuteStateChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["inputMuted"] = obs_source_muted(source);
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputMuteStateChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputVolumeChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Volume must be grabbed from the calldata. Running obs_source_get_volume() will return the previous value.
|
||||||
|
double inputVolumeMul = 0;
|
||||||
|
if (!calldata_get_float(data, "volume", &inputVolumeMul))
|
||||||
|
return;
|
||||||
|
|
||||||
|
double inputVolumeDb = obs_mul_to_db(inputVolumeMul);
|
||||||
|
if (inputVolumeDb == -INFINITY)
|
||||||
|
inputVolumeDb = -100;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["inputVolumeMul"] = inputVolumeMul;
|
||||||
|
eventData["inputVolumeDb"] = inputVolumeDb;
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputVolumeChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputAudioSyncOffsetChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long long inputAudioSyncOffset = 0;
|
||||||
|
if (!calldata_get_int(data, "offset", &inputAudioSyncOffset))
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["inputAudioSyncOffset"] = inputAudioSyncOffset / 1000000;
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputAudioSyncOffsetChanged", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventHandler::HandleInputAudioTracksChanged(void *param, calldata_t *data)
|
||||||
|
{
|
||||||
|
auto eventHandler = reinterpret_cast<EventHandler*>(param);
|
||||||
|
|
||||||
|
OBSSource source = GetCalldataPointer<obs_source_t>(data, "source");
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
long long tracks;
|
||||||
|
if (!calldata_get_int(data, "mixers", &tracks)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
json inputAudioTracks;
|
||||||
|
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||||
|
inputAudioTracks[std::to_string(i + 1)] = (bool)((1 << i) & tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["inputName"] = obs_source_get_name(source);
|
||||||
|
eventData["inputAudioTracks"] = inputAudioTracks;
|
||||||
|
eventHandler->_webSocketServer->BroadcastEvent(EventSubscription::Inputs, "InputAudioTracksChanged", eventData);
|
||||||
|
}
|
@ -4,30 +4,51 @@
|
|||||||
|
|
||||||
void EventHandler::HandleSceneCreated(obs_source_t *source)
|
void EventHandler::HandleSceneCreated(obs_source_t *source)
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["sceneName"] = obs_source_get_name(source);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "SceneCreated", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleSceneRemoved(obs_source_t *source)
|
void EventHandler::HandleSceneRemoved(obs_source_t *source)
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["sceneName"] = obs_source_get_name(source);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "SceneRemoved", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName)
|
void EventHandler::HandleSceneNameChanged(obs_source_t *source, std::string oldSceneName, std::string sceneName)
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["oldSceneName"] = oldSceneName;
|
||||||
|
eventData["sceneName"] = sceneName;
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "SceneNameChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleCurrentSceneChanged()
|
void EventHandler::HandleCurrentSceneChanged()
|
||||||
{
|
{
|
||||||
;
|
OBSSourceAutoRelease currentScene = obs_frontend_get_current_scene();
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["sceneName"] = obs_source_get_name(currentScene);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "CurrentSceneChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleCurrentPreviewSceneChanged()
|
void EventHandler::HandleCurrentPreviewSceneChanged()
|
||||||
{
|
{
|
||||||
;
|
OBSSourceAutoRelease currentPreviewScene = obs_frontend_get_current_preview_scene();
|
||||||
|
|
||||||
|
// This event may be called when OBS is not in studio mode, however retreiving the source while not in studio mode will return null.
|
||||||
|
if (!currentPreviewScene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json eventData;
|
||||||
|
eventData["sceneName"] = obs_source_get_name(currentPreviewScene);
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "CurrentPreviewSceneChanged", eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandler::HandleSceneListReindexed()
|
void EventHandler::HandleSceneListReindexed()
|
||||||
{
|
{
|
||||||
;
|
json eventData;
|
||||||
|
eventData["scenes"] = Utils::Obs::ListHelper::GetSceneList();
|
||||||
|
_webSocketServer->BroadcastEvent(EventSubscription::Scenes, "SceneListReindexed", eventData);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace EventSubscriptions {
|
namespace EventSubscription {
|
||||||
enum EventSubscriptions {
|
enum EventSubscription {
|
||||||
// Set subscriptions to 0 to disable all events
|
// Set subscriptions to 0 to disable all events
|
||||||
None = 0,
|
None = 0,
|
||||||
// Receive events in the `General` category
|
// Receive events in the `General` category
|
||||||
@ -24,5 +24,7 @@ namespace EventSubscriptions {
|
|||||||
MediaInputs = (1 << 8),
|
MediaInputs = (1 << 8),
|
||||||
// Receive all event categories
|
// Receive all event categories
|
||||||
All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs),
|
All = (General | Config | Scenes | Inputs | Transitions | Filters | Outputs | SceneItems | MediaInputs),
|
||||||
|
// InputVolumeMeters event (high-volume)
|
||||||
|
InputVolumeMeters = (1 << 9),
|
||||||
};
|
};
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user