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
{
2021-11-20 09:50:49 +00:00
blog_debug ( " [EventHandler::EventHandler] Setting up... " ) ;
2021-05-11 05:46:53 +00:00
2021-05-14 08:13:27 +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-06-08 04:35:10 +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 ) ;
2021-05-14 08:13:27 +00:00
} else {
2022-06-08 04:35:10 +00:00
blog ( LOG_ERROR , " [EventHandler::EventHandler] Unable to get libobs signal handler! " ) ;
2021-05-11 05:46:53 +00:00
}
2021-11-20 09:50:49 +00:00
blog_debug ( " [EventHandler::EventHandler] Finished. " ) ;
2021-05-10 23:54:48 +00:00
}
EventHandler : : ~ EventHandler ( )
{
2021-11-20 09:50:49 +00:00
blog_debug ( " [EventHandler::~EventHandler] Shutting down... " ) ;
2021-05-11 05:46:53 +00:00
2021-05-14 08:13:27 +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-06-08 04:35:10 +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 ) ;
2021-05-14 08:13:27 +00:00
} else {
2022-06-08 04:35:10 +00:00
blog ( LOG_ERROR , " [EventHandler::~EventHandler] Unable to get libobs signal handler! " ) ;
2021-05-11 05:46:53 +00:00
}
2021-11-20 09:50:49 +00:00
blog_debug ( " [EventHandler::~EventHandler] Finished. " ) ;
2021-05-10 23:54:48 +00:00
}
2021-09-04 17:04:00 +00:00
void EventHandler : : SetBroadcastCallback ( EventHandler : : BroadcastCallback cb )
{
_broadcastCallback = cb ;
}
2021-10-02 00:34:09 +00:00
void EventHandler : : SetObsLoadedCallback ( EventHandler : : ObsLoadedCallback cb )
{
_obsLoadedCallback = cb ;
}
2021-09-04 17:04:00 +00:00
// Function to increment refcounts for high volume event subscriptions
void EventHandler : : ProcessSubscription ( uint64_t eventSubscriptions )
{
2021-11-22 11:37:56 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputVolumeMeters ) ! = 0 ) {
if ( _inputVolumeMetersRef . fetch_add ( 1 ) = = 0 ) {
if ( _inputVolumeMetersHandler )
2022-06-08 04:35:10 +00:00
blog ( LOG_WARNING , " [EventHandler::ProcessSubscription] Input volume meter handler already exists! " ) ;
2021-11-22 11:37:56 +00:00
else
2022-06-08 04:35:10 +00:00
_inputVolumeMetersHandler = std : : make_unique < Utils : : Obs : : VolumeMeter : : Handler > (
std : : bind ( & EventHandler : : HandleInputVolumeMeters , this , std : : placeholders : : _1 ) ) ;
2021-11-22 11:37:56 +00:00
}
}
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputActiveStateChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_inputActiveStateChangedRef + + ;
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputShowStateChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_inputShowStateChangedRef + + ;
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : SceneItemTransformChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_sceneItemTransformChangedRef + + ;
}
// Function to decrement refcounts for high volume event subscriptions
void EventHandler : : ProcessUnsubscription ( uint64_t eventSubscriptions )
{
2021-11-22 11:37:56 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputVolumeMeters ) ! = 0 ) {
if ( _inputVolumeMetersRef . fetch_sub ( 1 ) = = 1 )
_inputVolumeMetersHandler . reset ( ) ;
}
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputActiveStateChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_inputActiveStateChangedRef - - ;
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : InputShowStateChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_inputShowStateChangedRef - - ;
2022-06-08 04:35:10 +00:00
if ( ( eventSubscriptions & EventSubscription : : SceneItemTransformChanged ) ! = 0 )
2021-09-04 17:04:00 +00:00
_sceneItemTransformChangedRef - - ;
}
// Function required in order to use default arguments
2022-06-08 04:35:10 +00:00
void EventHandler : : BroadcastEvent ( uint64_t requiredIntent , std : : string eventType , json eventData , uint8_t rpcVersion )
2021-09-04 17:04:00 +00:00
{
if ( ! _broadcastCallback )
return ;
_broadcastCallback ( requiredIntent , eventType , eventData , rpcVersion ) ;
}
2022-03-01 22:10:34 +00:00
// Connect source signals for Inputs, Scenes, and Transitions. Filters are automatically connected.
2022-06-08 04:35:10 +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 ;
2021-06-13 07:46:42 +00:00
// 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
2021-06-13 07:46:42 +00:00
obs_source_type sourceType = obs_source_get_type ( source ) ;
2021-05-14 08:13:27 +00:00
// Inputs
2021-06-13 07:46:42 +00:00
if ( sourceType = = OBS_SOURCE_TYPE_INPUT ) {
2022-06-08 04:35:10 +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 ) ;
2021-06-13 07:46:42 +00:00
}
// Scenes
if ( sourceType = = OBS_SOURCE_TYPE_SCENE ) {
2022-06-08 04:35:10 +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 ) ;
2021-06-13 07:46:42 +00:00
}
2022-03-01 22:10:34 +00:00
// Scenes and Inputs
2022-06-08 04:35:10 +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 ) {
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-03-01 22:10:34 +00:00
eventHandler - > ConnectSourceSignals ( filter ) ;
} ;
obs_source_enum_filters ( source , enumFilters , this ) ;
}
// Transitions
if ( sourceType = = OBS_SOURCE_TYPE_TRANSITION ) {
2022-06-08 04:35:10 +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 ) ;
2022-03-01 22:10:34 +00:00
}
// Filters
if ( sourceType = = OBS_SOURCE_TYPE_FILTER ) {
2022-06-08 04:35:10 +00:00
signal_handler_connect ( sh , " enable " , HandleSourceFilterEnableStateChanged , this ) ;
signal_handler_connect ( sh , " rename " , HandleSourceFilterNameChanged , this ) ;
2022-03-01 22:10:34 +00:00
}
2021-05-11 05:46:53 +00:00
}
2021-11-19 06:24:00 +00:00
2022-03-01 22:10:34 +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
2022-03-01 22:10:34 +00:00
obs_source_type sourceType = obs_source_get_type ( source ) ;
2021-05-14 08:13:27 +00:00
// Inputs
2022-03-01 22:10:34 +00:00
if ( sourceType = = OBS_SOURCE_TYPE_INPUT ) {
2022-06-08 04:35:10 +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 ) ;
2022-03-01 22:10:34 +00:00
}
2021-06-13 07:46:42 +00:00
// Scenes
2022-03-01 22:10:34 +00:00
if ( sourceType = = OBS_SOURCE_TYPE_SCENE ) {
2022-06-08 04:35:10 +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 ) ;
2022-03-01 22:10:34 +00:00
}
2022-02-16 21:17:06 +00:00
2022-03-01 22:10:34 +00:00
// Inputs and Scenes
2022-06-08 04:35:10 +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 ) {
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-03-01 22:10:34 +00:00
eventHandler - > DisconnectSourceSignals ( filter ) ;
} ;
obs_source_enum_filters ( source , enumFilters , this ) ;
}
2022-02-16 21:17:06 +00:00
2022-03-01 22:10:34 +00:00
// Transitions
if ( sourceType = = OBS_SOURCE_TYPE_TRANSITION ) {
2022-06-08 04:35:10 +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 ) ;
2022-03-01 22:10:34 +00:00
}
2022-02-16 21:17:06 +00:00
2022-03-01 22:10:34 +00:00
// Filters
if ( sourceType = = OBS_SOURCE_TYPE_FILTER ) {
2022-06-08 04:35:10 +00:00
signal_handler_disconnect ( sh , " enable " , HandleSourceFilterEnableStateChanged , this ) ;
signal_handler_disconnect ( sh , " rename " , HandleSourceFilterNameChanged , this ) ;
2022-03-01 22:10:34 +00:00
}
2022-02-16 21:17:06 +00:00
}
2022-06-08 04:35:10 +00:00
void EventHandler : : OnFrontendEvent ( enum obs_frontend_event event , void * private_data )
2021-05-14 08:13:27 +00:00
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast < EventHandler * > ( private_data ) ;
2021-05-11 00:34:40 +00:00
2022-06-08 04:35:10 +00:00
if ( ! eventHandler - > _obsLoaded . load ( ) & & event ! = OBS_FRONTEND_EVENT_FINISHED_LOADING )
2022-03-01 22:10:34 +00:00
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
{
2022-06-08 04:35:10 +00:00
auto enumInputs = [ ] ( void * param , obs_source_t * source ) {
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-05-14 04:17:17 +00:00
eventHandler - > ConnectSourceSignals ( source ) ;
return true ;
} ;
obs_enum_sources ( enumInputs , private_data ) ;
}
2021-06-13 07:46:42 +00:00
2022-05-14 04:17:17 +00:00
// Enumerate scenes and connect each one
{
2022-06-08 04:35:10 +00:00
auto enumScenes = [ ] ( void * param , obs_source_t * source ) {
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-05-14 04:17:17 +00:00
eventHandler - > ConnectSourceSignals ( source ) ;
return true ;
} ;
obs_enum_scenes ( enumScenes , private_data ) ;
}
2021-06-13 07:46:42 +00:00
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 + + ) {
2022-06-08 04:35:10 +00:00
obs_source_t * transition = transitions . sources . array [ i ] ;
2022-05-14 04:17:17 +00:00
eventHandler - > ConnectSourceSignals ( transition ) ;
2022-03-01 22:10:34 +00:00
}
2022-05-14 04:17:17 +00:00
obs_frontend_source_list_free ( & transitions ) ;
}
2022-03-01 22:10:34 +00:00
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 ( ) ;
2022-06-08 04:35:10 +00:00
blog_debug ( " [EventHandler::OnFrontendEvent] OBS is unloading. Disabling events... " ) ;
2022-05-14 04:17:17 +00:00
// 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
{
2022-06-08 04:35:10 +00:00
auto enumInputs = [ ] ( void * param , obs_source_t * source ) {
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-05-14 04:17:17 +00:00
eventHandler - > DisconnectSourceSignals ( source ) ;
return true ;
} ;
obs_enum_sources ( enumInputs , private_data ) ;
}
2021-05-14 08:13:27 +00:00
2022-05-14 04:17:17 +00:00
// Enumerate scenes and disconnect each one
{
2022-06-08 04:35:10 +00:00
auto enumScenes = [ ] ( void * param , obs_source_t * source ) {
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2022-05-14 04:17:17 +00:00
eventHandler - > DisconnectSourceSignals ( source ) ;
return true ;
} ;
obs_enum_scenes ( enumScenes , private_data ) ;
}
2021-06-13 07:46:42 +00:00
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 + + ) {
2022-06-08 04:35:10 +00:00
obs_source_t * transition = transitions . sources . array [ i ] ;
eventHandler - > DisconnectSourceSignals ( transition ) ;
2022-02-16 21:17:06 +00:00
}
2022-05-14 04:17:17 +00:00
obs_frontend_source_list_free ( & transitions ) ;
}
2021-06-13 07:46:42 +00:00
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 ;
2021-06-13 07:46:42 +00:00
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-03-01 22:10:34 +00:00
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 :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleStreamStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_STREAMING_STARTED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleStreamStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_STREAMING_STOPPING :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleStreamStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_STREAMING_STOPPED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleStreamStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_STARTING :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_STARTED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_STOPPING :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_STOPPED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_PAUSED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_PAUSED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_RECORDING_UNPAUSED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleRecordStateChanged ( OBS_WEBSOCKET_OUTPUT_RESUMED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleReplayBufferStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleReplayBufferStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleReplayBufferStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPING ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleReplayBufferStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleVirtualcamStateChanged ( OBS_WEBSOCKET_OUTPUT_STARTED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleVirtualcamStateChanged ( OBS_WEBSOCKET_OUTPUT_STOPPED ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED :
eventHandler - > HandleReplayBufferSaved ( ) ;
break ;
default :
break ;
2021-05-11 00:34:40 +00:00
}
2021-05-10 23:54:48 +00:00
}
2021-05-14 02:11:19 +00:00
2021-06-13 07:46:42 +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 ) ;
2021-05-14 08:13:27 +00:00
2021-06-13 07:46:42 +00:00
// Don't react to signals until OBS has finished loading
2021-05-14 08:13:27 +00:00
if ( ! eventHandler - > _obsLoaded . load ( ) )
return ;
2021-05-14 02:11:19 +00:00
2021-06-13 07:46:42 +00:00
obs_source_t * source = GetCalldataPointer < obs_source_t > ( data , " source " ) ;
2021-05-14 02:11:19 +00:00
if ( ! source )
return ;
2021-05-14 08:13:27 +00:00
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 ;
2021-05-14 08:13:27 +00:00
}
}
2022-04-17 02:34:47 +00:00
// Only called for destruction of a public sourcs
// Used as a fallback if an input/scene is not explicitly removed
2021-05-14 08:13:27 +00:00
void EventHandler : : SourceDestroyedMultiHandler ( void * param , calldata_t * data )
{
2022-05-14 04:17:17 +00:00
auto eventHandler = static_cast < EventHandler * > ( param ) ;
2021-05-14 08:13:27 +00:00
2021-06-13 07:46:42 +00:00
// We can't use any smart types here because releasing the source will cause infinite recursion
2021-05-14 08:13:27 +00:00
obs_source_t * source = GetCalldataPointer < obs_source_t > ( data , " source " ) ;
if ( ! source )
return ;
// Disconnect all signals from the source
eventHandler - > DisconnectSourceSignals ( source ) ;
2021-06-13 07:46:42 +00:00
// Don't react to signals if OBS is unloading
2021-05-14 10:59:00 +00:00
if ( ! eventHandler - > _obsLoaded . load ( ) )
return ;
2021-05-14 08:13:27 +00:00
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
}
}
2022-04-17 02:34:47 +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 ) ;
2021-05-14 08:13:27 +00:00
if ( ! eventHandler - > _obsLoaded . load ( ) )
return ;
2021-05-14 02:11:19 +00:00
2021-06-13 07:46:42 +00:00
obs_source_t * source = GetCalldataPointer < obs_source_t > ( data , " source " ) ;
2021-05-14 02:11:19 +00:00
if ( ! source )
return ;
2021-05-14 08:13:27 +00:00
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 ) ;
2021-05-14 08:13:27 +00:00
if ( ! eventHandler - > _obsLoaded . load ( ) )
return ;
2021-05-14 02:11:19 +00:00
2021-06-13 07:46:42 +00:00
obs_source_t * source = GetCalldataPointer < obs_source_t > ( data , " source " ) ;
2021-05-14 02:11:19 +00:00
if ( ! source )
return ;
2021-06-13 11:50:04 +00:00
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 ;
2021-05-14 08:13:27 +00:00
switch ( obs_source_get_type ( source ) ) {
2022-05-14 04:17:17 +00:00
case OBS_SOURCE_TYPE_INPUT :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleInputNameChanged ( source , oldSourceName , sourceName ) ;
2022-05-14 04:17:17 +00:00
break ;
case OBS_SOURCE_TYPE_TRANSITION :
break ;
case OBS_SOURCE_TYPE_SCENE :
2022-06-08 04:35:10 +00:00
eventHandler - > HandleSceneNameChanged ( source , oldSourceName , sourceName ) ;
2022-05-14 04:17:17 +00:00
break ;
default :
break ;
2021-05-14 02:11:19 +00:00
}
}