obs-websocket/src/eventhandler/EventHandler.cpp

738 lines
24 KiB
C++
Raw Normal View History

2021-11-20 01:32:22 +00:00
/*
obs-websocket
Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com>
Copyright (C) 2020-2021 Kyle Manning <tt2468@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>
*/
2021-05-10 22:48:41 +00:00
#include "EventHandler.h"
2021-05-11 05:46:53 +00:00
2022-05-14 04:17:17 +00:00
EventHandler::EventHandler()
: _obsLoaded(false),
_inputVolumeMetersRef(0),
_inputActiveStateChangedRef(0),
_inputShowStateChangedRef(0),
_sceneItemTransformChangedRef(0)
2021-05-10 23:54:48 +00:00
{
blog_debug("[EventHandler::EventHandler] Setting up...");
2021-05-11 05:46:53 +00:00
obs_frontend_add_event_callback(OnFrontendEvent, this);
2021-05-11 05:46:53 +00:00
2022-05-14 04:17:17 +00:00
signal_handler_t *coreSignalHandler = obs_get_signal_handler();
2021-05-11 05:46:53 +00:00
if (coreSignalHandler) {
2022-05-14 04:17:17 +00:00
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_rename",
SourceRenamedMultiHandler, this);
} else {
2022-05-14 04:17:17 +00:00
blog(LOG_ERROR,
"[EventHandler::EventHandler] Unable to get libobs signal handler!");
2021-05-11 05:46:53 +00:00
}
blog_debug("[EventHandler::EventHandler] Finished.");
2021-05-10 23:54:48 +00:00
}
EventHandler::~EventHandler()
{
blog_debug("[EventHandler::~EventHandler] Shutting down...");
2021-05-11 05:46:53 +00:00
obs_frontend_remove_event_callback(OnFrontendEvent, this);
2021-05-11 05:46:53 +00:00
2022-05-14 04:17:17 +00:00
signal_handler_t *coreSignalHandler = obs_get_signal_handler();
2021-05-11 05:46:53 +00:00
if (coreSignalHandler) {
2022-05-14 04:17:17 +00:00
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_rename",
SourceRenamedMultiHandler, this);
} else {
2022-05-14 04:17:17 +00:00
blog(LOG_ERROR,
"[EventHandler::~EventHandler] Unable to get libobs signal handler!");
2021-05-11 05:46:53 +00:00
}
blog_debug("[EventHandler::~EventHandler] Finished.");
2021-05-10 23:54:48 +00:00
}
void EventHandler::SetBroadcastCallback(EventHandler::BroadcastCallback cb)
{
_broadcastCallback = cb;
}
void EventHandler::SetObsLoadedCallback(EventHandler::ObsLoadedCallback cb)
{
_obsLoadedCallback = cb;
}
// Function to increment refcounts for high volume event subscriptions
void EventHandler::ProcessSubscription(uint64_t eventSubscriptions)
{
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
if (_inputVolumeMetersRef.fetch_add(1) == 0) {
if (_inputVolumeMetersHandler)
2022-05-14 04:17:17 +00:00
blog(LOG_WARNING,
"[EventHandler::ProcessSubscription] Input volume meter handler already exists!");
else
2022-05-14 04:17:17 +00:00
_inputVolumeMetersHandler = std::make_unique<
Utils::Obs::VolumeMeter::Handler>(
std::bind(
&EventHandler::
HandleInputVolumeMeters,
this, std::placeholders::_1));
}
}
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) !=
0)
_inputActiveStateChangedRef++;
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) !=
0)
_inputShowStateChangedRef++;
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions &
EventSubscription::SceneItemTransformChanged) != 0)
_sceneItemTransformChangedRef++;
}
// Function to decrement refcounts for high volume event subscriptions
void EventHandler::ProcessUnsubscription(uint64_t eventSubscriptions)
{
if ((eventSubscriptions & EventSubscription::InputVolumeMeters) != 0) {
if (_inputVolumeMetersRef.fetch_sub(1) == 1)
_inputVolumeMetersHandler.reset();
}
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions & EventSubscription::InputActiveStateChanged) !=
0)
_inputActiveStateChangedRef--;
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions & EventSubscription::InputShowStateChanged) !=
0)
_inputShowStateChangedRef--;
2022-05-14 04:17:17 +00:00
if ((eventSubscriptions &
EventSubscription::SceneItemTransformChanged) != 0)
_sceneItemTransformChangedRef--;
}
// Function required in order to use default arguments
2022-05-14 04:17:17 +00:00
void EventHandler::BroadcastEvent(uint64_t requiredIntent,
std::string eventType, json eventData,
uint8_t rpcVersion)
{
if (!_broadcastCallback)
return;
_broadcastCallback(requiredIntent, eventType, eventData, rpcVersion);
}
// Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected.
2022-05-14 04:17:17 +00:00
void EventHandler::ConnectSourceSignals(
obs_source_t *source) // Applies to inputs and scenes
2021-05-11 05:46:53 +00:00
{
if (!source || obs_source_removed(source))
return;
// Disconnect all existing signals from the source to prevent multiple connections
2021-05-11 05:46:53 +00:00
DisconnectSourceSignals(source);
2022-05-14 04:17:17 +00:00
signal_handler_t *sh = obs_source_get_signal_handler(source);
2021-05-14 02:11:19 +00:00
obs_source_type sourceType = obs_source_get_type(source);
// Inputs
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
2022-05-14 04:17:17 +00:00
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_balance",
HandleInputAudioBalanceChanged, this);
signal_handler_connect(sh, "audio_sync",
HandleInputAudioSyncOffsetChanged, this);
signal_handler_connect(sh, "audio_mixers",
HandleInputAudioTracksChanged, this);
signal_handler_connect(sh, "audio_monitoring",
HandleInputAudioMonitorTypeChanged,
this);
signal_handler_connect(sh, "media_started",
HandleMediaInputPlaybackStarted, this);
signal_handler_connect(sh, "media_ended",
HandleMediaInputPlaybackEnded, this);
signal_handler_connect(sh, "media_pause",
SourceMediaPauseMultiHandler, this);
signal_handler_connect(sh, "media_play",
SourceMediaPlayMultiHandler, this);
signal_handler_connect(sh, "media_restart",
SourceMediaRestartMultiHandler, this);
signal_handler_connect(sh, "media_stopped",
SourceMediaStopMultiHandler, this);
signal_handler_connect(sh, "media_next",
SourceMediaNextMultiHandler, this);
signal_handler_connect(sh, "media_previous",
SourceMediaPreviousMultiHandler, this);
}
// Scenes
if (sourceType == OBS_SOURCE_TYPE_SCENE) {
2022-05-14 04:17:17 +00:00
signal_handler_connect(sh, "item_add", HandleSceneItemCreated,
this);
signal_handler_connect(sh, "item_remove",
HandleSceneItemRemoved, this);
signal_handler_connect(sh, "reorder",
HandleSceneItemListReindexed, this);
signal_handler_connect(sh, "item_visible",
HandleSceneItemEnableStateChanged, this);
signal_handler_connect(sh, "item_locked",
HandleSceneItemLockStateChanged, this);
signal_handler_connect(sh, "item_select",
HandleSceneItemSelected, this);
signal_handler_connect(sh, "item_transform",
HandleSceneItemTransformChanged, this);
}
// Scenes and Inputs
2022-05-14 04:17:17 +00:00
if (sourceType == OBS_SOURCE_TYPE_INPUT ||
sourceType == OBS_SOURCE_TYPE_SCENE) {
signal_handler_connect(sh, "reorder_filters",
HandleSourceFilterListReindexed, this);
signal_handler_connect(sh, "filter_add", FilterAddMultiHandler,
this);
signal_handler_connect(sh, "filter_remove",
FilterRemoveMultiHandler, this);
auto enumFilters = [](obs_source_t *, obs_source_t *filter,
void *param) {
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->ConnectSourceSignals(filter);
};
obs_source_enum_filters(source, enumFilters, this);
}
// Transitions
if (sourceType == OBS_SOURCE_TYPE_TRANSITION) {
2022-05-14 04:17:17 +00:00
signal_handler_connect(sh, "transition_start",
HandleSceneTransitionStarted, this);
signal_handler_connect(sh, "transition_stop",
HandleSceneTransitionEnded, this);
signal_handler_connect(sh, "transition_video_stop",
HandleSceneTransitionVideoEnded, this);
}
// Filters
if (sourceType == OBS_SOURCE_TYPE_FILTER) {
2022-05-14 04:17:17 +00:00
signal_handler_connect(sh, "enable",
HandleSourceFilterEnableStateChanged,
this);
signal_handler_connect(sh, "rename",
HandleSourceFilterNameChanged, this);
}
2021-05-11 05:46:53 +00:00
}
// Disconnect source signals for Inputs, Scenes, and Transitions. Filters are automatically disconnected.
2021-05-11 05:46:53 +00:00
void EventHandler::DisconnectSourceSignals(obs_source_t *source)
{
if (!source)
return;
2022-05-14 04:17:17 +00:00
signal_handler_t *sh = obs_source_get_signal_handler(source);
2021-05-14 02:11:19 +00:00
obs_source_type sourceType = obs_source_get_type(source);
// Inputs
if (sourceType == OBS_SOURCE_TYPE_INPUT) {
2022-05-14 04:17:17 +00:00
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_balance",
HandleInputAudioBalanceChanged, this);
signal_handler_disconnect(sh, "audio_sync",
HandleInputAudioSyncOffsetChanged,
this);
signal_handler_disconnect(sh, "audio_mixers",
HandleInputAudioTracksChanged, this);
signal_handler_disconnect(sh, "audio_monitoring",
HandleInputAudioMonitorTypeChanged,
this);
signal_handler_disconnect(sh, "media_started",
HandleMediaInputPlaybackStarted,
this);
signal_handler_disconnect(sh, "media_ended",
HandleMediaInputPlaybackEnded, this);
signal_handler_disconnect(sh, "media_pause",
SourceMediaPauseMultiHandler, this);
signal_handler_disconnect(sh, "media_play",
SourceMediaPlayMultiHandler, this);
signal_handler_disconnect(sh, "media_restart",
SourceMediaRestartMultiHandler, this);
signal_handler_disconnect(sh, "media_stopped",
SourceMediaStopMultiHandler, this);
signal_handler_disconnect(sh, "media_next",
SourceMediaNextMultiHandler, this);
signal_handler_disconnect(sh, "media_previous",
SourceMediaPreviousMultiHandler,
this);
}
// Scenes
if (sourceType == OBS_SOURCE_TYPE_SCENE) {
2022-05-14 04:17:17 +00:00
signal_handler_disconnect(sh, "item_add",
HandleSceneItemCreated, this);
signal_handler_disconnect(sh, "item_remove",
HandleSceneItemRemoved, this);
signal_handler_disconnect(sh, "reorder",
HandleSceneItemListReindexed, this);
signal_handler_disconnect(sh, "item_visible",
HandleSceneItemEnableStateChanged,
this);
signal_handler_disconnect(sh, "item_locked",
HandleSceneItemLockStateChanged,
this);
signal_handler_disconnect(sh, "item_select",
HandleSceneItemSelected, this);
signal_handler_disconnect(sh, "item_transform",
HandleSceneItemTransformChanged,
this);
}
// Inputs and Scenes
2022-05-14 04:17:17 +00:00
if (sourceType == OBS_SOURCE_TYPE_INPUT ||
sourceType == OBS_SOURCE_TYPE_SCENE) {
signal_handler_disconnect(sh, "reorder_filters",
HandleSourceFilterListReindexed,
this);
signal_handler_disconnect(sh, "filter_add",
FilterAddMultiHandler, this);
signal_handler_disconnect(sh, "filter_remove",
FilterRemoveMultiHandler, this);
auto enumFilters = [](obs_source_t *, obs_source_t *filter,
void *param) {
auto eventHandler = static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(filter);
};
obs_source_enum_filters(source, enumFilters, this);
}
// Transitions
if (sourceType == OBS_SOURCE_TYPE_TRANSITION) {
2022-05-14 04:17:17 +00:00
signal_handler_disconnect(sh, "transition_start",
HandleSceneTransitionStarted, this);
signal_handler_disconnect(sh, "transition_stop",
HandleSceneTransitionEnded, this);
signal_handler_disconnect(sh, "transition_video_stop",
HandleSceneTransitionVideoEnded,
this);
}
// Filters
if (sourceType == OBS_SOURCE_TYPE_FILTER) {
2022-05-14 04:17:17 +00:00
signal_handler_disconnect(sh, "enable",
HandleSourceFilterEnableStateChanged,
this);
signal_handler_disconnect(sh, "rename",
HandleSourceFilterNameChanged, this);
}
}
2022-05-14 04:17:17 +00:00
void EventHandler::OnFrontendEvent(enum obs_frontend_event event,
void *private_data)
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast<EventHandler *>(private_data);
2022-05-14 04:17:17 +00:00
if (!eventHandler->_obsLoaded.load() &&
event != OBS_FRONTEND_EVENT_FINISHED_LOADING)
return;
switch (event) {
2022-05-14 04:17:17 +00:00
// General
case OBS_FRONTEND_EVENT_FINISHED_LOADING:
blog_debug(
"[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()`
// Enumerate inputs and connect each one
{
auto enumInputs = [](void *param,
obs_source_t *source) {
auto eventHandler =
static_cast<EventHandler *>(param);
eventHandler->ConnectSourceSignals(source);
return true;
};
obs_enum_sources(enumInputs, private_data);
}
2022-05-14 04:17:17 +00:00
// Enumerate scenes and connect each one
{
auto enumScenes = [](void *param,
obs_source_t *source) {
auto eventHandler =
static_cast<EventHandler *>(param);
eventHandler->ConnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, private_data);
}
2022-05-14 04:17:17 +00:00
// Enumerate all scene transitions and connect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition =
transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
2022-05-14 04:17:17 +00:00
obs_frontend_source_list_free(&transitions);
}
2022-05-14 04:17:17 +00:00
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
if (eventHandler->_obsLoadedCallback)
eventHandler->_obsLoadedCallback();
break;
case OBS_FRONTEND_EVENT_EXIT:
eventHandler->HandleExitStarted();
blog_debug(
"[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()`
// Enumerate inputs and disconnect each one
{
auto enumInputs = [](void *param,
obs_source_t *source) {
auto eventHandler =
static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_sources(enumInputs, private_data);
}
2022-05-14 04:17:17 +00:00
// Enumerate scenes and disconnect each one
{
auto enumScenes = [](void *param,
obs_source_t *source) {
auto eventHandler =
static_cast<EventHandler *>(param);
eventHandler->DisconnectSourceSignals(source);
return true;
};
obs_enum_scenes(enumScenes, private_data);
}
2022-05-14 04:17:17 +00:00
// Enumerate all scene transitions and disconnect each one
{
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition =
transitions.sources.array[i];
eventHandler->DisconnectSourceSignals(
transition);
}
2022-05-14 04:17:17 +00:00
obs_frontend_source_list_free(&transitions);
}
2022-05-14 04:17:17 +00:00
blog_debug("[EventHandler::OnFrontendEvent] Finished.");
break;
case OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED:
eventHandler->HandleStudioModeStateChanged(true);
break;
case OBS_FRONTEND_EVENT_STUDIO_MODE_DISABLED:
eventHandler->HandleStudioModeStateChanged(false);
break;
// Config
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING: {
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
eventHandler->DisconnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
eventHandler->HandleCurrentSceneCollectionChanging();
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: {
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
}
eventHandler->HandleCurrentSceneCollectionChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
eventHandler->HandleSceneCollectionListChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGING:
eventHandler->HandleCurrentProfileChanging();
break;
case OBS_FRONTEND_EVENT_PROFILE_CHANGED:
eventHandler->HandleCurrentProfileChanged();
break;
case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED:
eventHandler->HandleProfileListChanged();
break;
2022-05-14 04:17:17 +00:00
// Scenes
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
eventHandler->HandleCurrentProgramSceneChanged();
break;
case OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED:
eventHandler->HandleCurrentPreviewSceneChanged();
break;
case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED:
eventHandler->HandleSceneListChanged();
break;
2022-05-14 04:17:17 +00:00
// Transitions
case OBS_FRONTEND_EVENT_TRANSITION_CHANGED:
eventHandler->HandleCurrentSceneTransitionChanged();
break;
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED: {
obs_frontend_source_list transitions = {};
obs_frontend_get_transitions(&transitions);
for (size_t i = 0; i < transitions.sources.num; i++) {
obs_source_t *transition = transitions.sources.array[i];
eventHandler->ConnectSourceSignals(transition);
}
obs_frontend_source_list_free(&transitions);
} break;
case OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED:
eventHandler->HandleCurrentSceneTransitionDurationChanged();
break;
// Outputs
case OBS_FRONTEND_EVENT_STREAMING_STARTING:
eventHandler->HandleStreamStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STARTED:
eventHandler->HandleStreamStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
eventHandler->HandleStreamStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
eventHandler->HandleStreamStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTING:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STARTED:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_RECORDING_PAUSED:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_PAUSED);
break;
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED:
eventHandler->HandleRecordStateChanged(
OBS_WEBSOCKET_OUTPUT_RESUMED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING:
eventHandler->HandleReplayBufferStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED:
eventHandler->HandleReplayBufferStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING:
eventHandler->HandleReplayBufferStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPING);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED:
eventHandler->HandleReplayBufferStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED:
eventHandler->HandleVirtualcamStateChanged(
OBS_WEBSOCKET_OUTPUT_STARTED);
break;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED:
eventHandler->HandleVirtualcamStateChanged(
OBS_WEBSOCKET_OUTPUT_STOPPED);
break;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
eventHandler->HandleReplayBufferSaved();
break;
default:
break;
}
2021-05-10 23:54:48 +00:00
}
2021-05-14 02:11:19 +00:00
// Only called for creation of a public source
2021-05-14 02:11:19 +00:00
void EventHandler::SourceCreatedMultiHandler(void *param, calldata_t *data)
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast<EventHandler *>(param);
// Don't react to signals until OBS has finished loading
if (!eventHandler->_obsLoaded.load())
return;
2021-05-14 02:11:19 +00:00
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
2021-05-14 02:11:19 +00:00
if (!source)
return;
eventHandler->ConnectSourceSignals(source);
switch (obs_source_get_type(source)) {
2022-05-14 04:17:17 +00:00
case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputCreated(source);
break;
case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneCreated(source);
break;
default:
break;
}
}
// Only called for destruction of a public sourcs
// Used as a fallback if an input/scene is not explicitly removed
void EventHandler::SourceDestroyedMultiHandler(void *param, calldata_t *data)
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast<EventHandler *>(param);
// We can't use any smart types here 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);
// Don't react to signals if OBS is unloading
if (!eventHandler->_obsLoaded.load())
return;
switch (obs_source_get_type(source)) {
2022-05-14 04:17:17 +00:00
case OBS_SOURCE_TYPE_INPUT:
// Only emit removed if the input has not already been removed. This is the case when removing the last scene item of an input.
if (!obs_source_removed(source))
eventHandler->HandleInputRemoved(source);
break;
case OBS_SOURCE_TYPE_SCENE:
// Only emit removed if the scene has not already been removed.
if (!obs_source_removed(source))
eventHandler->HandleSceneRemoved(source);
break;
default:
break;
2021-05-14 02:11:19 +00:00
}
}
// We prefer remove signals over destroy signals because they are more time-accurate.
// For example, if an input is "removed" but there is a dangling ref, you still want to know that it shouldn't exist, but it's not guaranteed to be destroyed.
2021-05-14 02:11:19 +00:00
void EventHandler::SourceRemovedMultiHandler(void *param, calldata_t *data)
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_obsLoaded.load())
return;
2021-05-14 02:11:19 +00:00
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
2021-05-14 02:11:19 +00:00
if (!source)
return;
switch (obs_source_get_type(source)) {
2022-05-14 04:17:17 +00:00
case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputRemoved(source);
break;
case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneRemoved(source);
break;
default:
break;
2021-05-14 02:11:19 +00:00
}
}
void EventHandler::SourceRenamedMultiHandler(void *param, calldata_t *data)
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast<EventHandler *>(param);
if (!eventHandler->_obsLoaded.load())
return;
2021-05-14 02:11:19 +00:00
obs_source_t *source = GetCalldataPointer<obs_source_t>(data, "source");
2021-05-14 02:11:19 +00:00
if (!source)
return;
std::string oldSourceName = calldata_string(data, "prev_name");
std::string sourceName = calldata_string(data, "new_name");
2021-05-14 02:11:19 +00:00
if (oldSourceName.empty() || sourceName.empty())
return;
switch (obs_source_get_type(source)) {
2022-05-14 04:17:17 +00:00
case OBS_SOURCE_TYPE_INPUT:
eventHandler->HandleInputNameChanged(source, oldSourceName,
sourceName);
break;
case OBS_SOURCE_TYPE_TRANSITION:
break;
case OBS_SOURCE_TYPE_SCENE:
eventHandler->HandleSceneNameChanged(source, oldSourceName,
sourceName);
break;
default:
break;
2021-05-14 02:11:19 +00:00
}
}