mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
feat(events): add "TransitionEnd" and "TransitionVideoEnd" events
Adds events for `TransitionEnd` and `TransitionVideoEnd`. `TransitionVideoEnd` is specific to Stinger transitions. It is fired when their video has actually completed playback. This is important, because `TransitionEnd` is fired at the cut point of the Stinger, which is nice to have but isn't always what the user might want. This builds on #409, and should be merged after it.
This commit is contained in:
parent
c7b49b28c2
commit
1057d765f7
@ -413,6 +413,30 @@ bool Utils::SetTransitionByName(QString transitionName) {
|
||||
}
|
||||
}
|
||||
|
||||
obs_data_t* Utils::GetTransitionData(obs_source_t* transition) {
|
||||
int duration = Utils::GetTransitionDuration(transition);
|
||||
if (duration < 0) {
|
||||
blog(LOG_WARNING, "GetTransitionData: duration is negative !");
|
||||
}
|
||||
|
||||
obs_data_t* transitionData = obs_data_create();
|
||||
obs_data_set_string(transitionData, "name", obs_source_get_name(transition));
|
||||
obs_data_set_string(transitionData, "type", obs_source_get_id(transition));
|
||||
obs_data_set_int(transitionData, "duration", duration);
|
||||
|
||||
OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A);
|
||||
if (sourceScene) {
|
||||
obs_data_set_string(transitionData, "from-scene", obs_source_get_name(sourceScene));
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition);
|
||||
if (destinationScene) {
|
||||
obs_data_set_string(transitionData, "to-scene", obs_source_get_name(destinationScene));
|
||||
}
|
||||
|
||||
return transitionData;
|
||||
}
|
||||
|
||||
QString Utils::OBSVersionString() {
|
||||
uint32_t version = obs_get_version();
|
||||
|
||||
|
@ -60,6 +60,7 @@ namespace Utils {
|
||||
int GetTransitionDuration(obs_source_t* transition);
|
||||
obs_source_t* GetTransitionFromName(QString transitionName);
|
||||
bool SetTransitionByName(QString transitionName);
|
||||
obs_data_t* GetTransitionData(obs_source_t* transition);
|
||||
|
||||
QString OBSVersionString();
|
||||
|
||||
|
@ -122,7 +122,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
|
||||
switch (event) {
|
||||
case OBS_FRONTEND_EVENT_FINISHED_LOADING:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||
@ -134,7 +134,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
owner->OnSceneCollectionChange();
|
||||
break;
|
||||
|
||||
@ -147,7 +147,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED:
|
||||
owner->hookTransitionBeginEvent();
|
||||
owner->hookTransitionPlaybackEvents();
|
||||
owner->OnTransitionListChange();
|
||||
break;
|
||||
|
||||
@ -231,7 +231,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private
|
||||
break;
|
||||
|
||||
case OBS_FRONTEND_EVENT_EXIT:
|
||||
owner->unhookTransitionBeginEvent();
|
||||
owner->unhookTransitionPlaybackEvents();
|
||||
owner->OnExit();
|
||||
break;
|
||||
}
|
||||
@ -309,6 +309,8 @@ void WSEvents::disconnectSourceSignals(obs_source_t* source) {
|
||||
signal_handler_disconnect(sh, "item_deselect", OnSceneItemDeselected, this);
|
||||
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
void WSEvents::connectFilterSignals(obs_source_t* filter) {
|
||||
@ -331,7 +333,7 @@ void WSEvents::disconnectFilterSignals(obs_source_t* filter) {
|
||||
signal_handler_disconnect(sh, "enable", OnSourceFilterVisibilityChanged, this);
|
||||
}
|
||||
|
||||
void WSEvents::hookTransitionBeginEvent() {
|
||||
void WSEvents::hookTransitionPlaybackEvents() {
|
||||
obs_frontend_source_list transitions = {};
|
||||
obs_frontend_get_transitions(&transitions);
|
||||
|
||||
@ -340,12 +342,16 @@ void WSEvents::hookTransitionBeginEvent() {
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(transition);
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_connect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_connect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
signal_handler_connect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&transitions);
|
||||
}
|
||||
|
||||
void WSEvents::unhookTransitionBeginEvent() {
|
||||
void WSEvents::unhookTransitionPlaybackEvents() {
|
||||
obs_frontend_source_list transitions = {};
|
||||
obs_frontend_get_transitions(&transitions);
|
||||
|
||||
@ -353,6 +359,8 @@ void WSEvents::unhookTransitionBeginEvent() {
|
||||
obs_source_t* transition = transitions.sources.array[i];
|
||||
signal_handler_t* sh = obs_source_get_signal_handler(transition);
|
||||
signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this);
|
||||
signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this);
|
||||
signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this);
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&transitions);
|
||||
@ -895,29 +903,62 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
int duration = Utils::GetTransitionDuration(transition);
|
||||
if (duration < 0) {
|
||||
blog(LOG_WARNING, "OnTransitionBegin: duration is negative !");
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = obs_data_create();
|
||||
obs_data_set_string(fields, "name", obs_source_get_name(transition));
|
||||
obs_data_set_string(fields, "type", obs_source_get_id(transition));
|
||||
obs_data_set_int(fields, "duration", duration);
|
||||
|
||||
OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A);
|
||||
if (sourceScene) {
|
||||
obs_data_set_string(fields, "from-scene", obs_source_get_name(sourceScene));
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition);
|
||||
if (destinationScene) {
|
||||
obs_data_set_string(fields, "to-scene", obs_source_get_name(destinationScene));
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionBegin", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A transition (other than "cut") has ended.
|
||||
*
|
||||
* @return {String} `name` Transition name.
|
||||
* @return {String} `type` Transition type.
|
||||
* @return {int} `duration` Transition duration (in milliseconds).
|
||||
* @return {String} `from-scene` Source scene of the transition
|
||||
* @return {String} `to-scene` Destination scene of the transition
|
||||
*
|
||||
* @api events
|
||||
* @name TransitionEnd
|
||||
* @category transitions
|
||||
* @since 4.8.0
|
||||
*/
|
||||
void WSEvents::OnTransitionEnd(void* param, calldata_t* data) {
|
||||
auto instance = reinterpret_cast<WSEvents*>(param);
|
||||
|
||||
OBSSource transition = calldata_get_pointer<obs_source_t>(data, "source");
|
||||
if (!transition) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionEnd", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A stinger transition has finished playing its video.
|
||||
*
|
||||
* @return {String} `name` Transition name.
|
||||
* @return {String} `type` Transition type.
|
||||
* @return {int} `duration` Transition duration (in milliseconds).
|
||||
* @return {String} `from-scene` Source scene of the transition
|
||||
* @return {String} `to-scene` Destination scene of the transition
|
||||
*
|
||||
* @api events
|
||||
* @name TransitionVideoEnd
|
||||
* @category transitions
|
||||
* @since 4.8.0
|
||||
*/
|
||||
void WSEvents::OnTransitionVideoEnd(void* param, calldata_t* data) {
|
||||
auto instance = reinterpret_cast<WSEvents*>(param);
|
||||
|
||||
OBSSource transition = calldata_get_pointer<obs_source_t>(data, "source");
|
||||
if (!transition) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease fields = Utils::GetTransitionData(transition);
|
||||
instance->broadcastUpdate("TransitionVideoEnd", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A source has been created. A source can be an input, a scene or a transition.
|
||||
*
|
||||
|
@ -43,8 +43,8 @@ public:
|
||||
void connectFilterSignals(obs_source_t* filter);
|
||||
void disconnectFilterSignals(obs_source_t* filter);
|
||||
|
||||
void hookTransitionBeginEvent();
|
||||
void unhookTransitionBeginEvent();
|
||||
void hookTransitionPlaybackEvents();
|
||||
void unhookTransitionPlaybackEvents();
|
||||
|
||||
uint64_t getStreamingTime();
|
||||
uint64_t getRecordingTime();
|
||||
@ -116,6 +116,8 @@ private:
|
||||
enum obs_frontend_event event, void* privateData);
|
||||
|
||||
static void OnTransitionBegin(void* param, calldata_t* data);
|
||||
static void OnTransitionEnd(void* param, calldata_t* data);
|
||||
static void OnTransitionVideoEnd(void* param, calldata_t* data);
|
||||
|
||||
static void OnSourceCreate(void* param, calldata_t* data);
|
||||
static void OnSourceDestroy(void* param, calldata_t* data);
|
||||
|
Loading…
x
Reference in New Issue
Block a user