mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
Implement source activation/deactivation
Now sources will be properly activated and deactivated when they are in use or not in use. Had to figure out a way to handle child sources, and children of children, just ended up implementing simple functions that parents use to signal adding/removal to help with hierarchial activation and deactivation of child sources. To prevent the source activate/deactivate callbacks from being called more than once, added an activation reference counter. The first increment will call the activate callback, and the last decrement will call the deactivate callback. Added "source-activate" and "source-deactivate" signals to the main obs signal handler, and "activate" and "deactivate" to individual source signal handlers. Also, fixed the main window so it properly selects a source when the current active scene has been changed.
This commit is contained in:
parent
14c95ac421
commit
d4f1eacc1f
|
@ -186,6 +186,9 @@ struct obs_source {
|
|||
signal_handler_t signals;
|
||||
proc_handler_t procs;
|
||||
|
||||
/* ensures activate/deactivate are only called once */
|
||||
int activate_refs;
|
||||
|
||||
/* prevents infinite recursion when enumerating sources */
|
||||
int enum_refs;
|
||||
|
||||
|
|
|
@ -298,17 +298,26 @@ void obs_scene_enum_items(obs_scene_t scene,
|
|||
obs_sceneitem_t obs_scene_add(obs_scene_t scene, obs_source_t source)
|
||||
{
|
||||
struct obs_scene_item *last;
|
||||
struct obs_scene_item *item = bzalloc(sizeof(struct obs_scene_item));
|
||||
struct obs_scene_item *item;
|
||||
struct calldata params = {0};
|
||||
|
||||
if (!scene)
|
||||
return NULL;
|
||||
|
||||
if (!source) {
|
||||
blog(LOG_WARNING, "Tried to add a NULL source to a scene");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = bzalloc(sizeof(struct obs_scene_item));
|
||||
item->source = source;
|
||||
item->visible = true;
|
||||
item->parent = scene;
|
||||
item->ref = 1;
|
||||
vec2_set(&item->scale, 1.0f, 1.0f);
|
||||
|
||||
if (source)
|
||||
obs_source_addref(source);
|
||||
obs_source_addref(source);
|
||||
obs_source_add_child(scene->source, source);
|
||||
|
||||
pthread_mutex_lock(&scene->mutex);
|
||||
|
||||
|
@ -377,11 +386,12 @@ void obs_sceneitem_remove(obs_sceneitem_t item)
|
|||
|
||||
item->removed = true;
|
||||
|
||||
obs_source_remove_child(scene->source, item->source);
|
||||
|
||||
signal_item_remove(item);
|
||||
detach_sceneitem(item);
|
||||
|
||||
if (scene)
|
||||
pthread_mutex_unlock(&scene->mutex);
|
||||
pthread_mutex_unlock(&scene->mutex);
|
||||
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
|
@ -420,8 +430,8 @@ void obs_sceneitem_setorder(obs_sceneitem_t item, enum order_movement movement)
|
|||
{
|
||||
struct obs_scene *scene = item->parent;
|
||||
|
||||
pthread_mutex_lock(&scene->mutex);
|
||||
obs_scene_addref(scene);
|
||||
pthread_mutex_lock(&scene->mutex);
|
||||
|
||||
detach_sceneitem(item);
|
||||
|
||||
|
@ -446,8 +456,8 @@ void obs_sceneitem_setorder(obs_sceneitem_t item, enum order_movement movement)
|
|||
attach_sceneitem(item, NULL);
|
||||
}
|
||||
|
||||
obs_scene_release(scene);
|
||||
pthread_mutex_unlock(&scene->mutex);
|
||||
obs_scene_release(scene);
|
||||
}
|
||||
|
||||
void obs_sceneitem_getpos(obs_sceneitem_t item, struct vec2 *pos)
|
||||
|
|
|
@ -294,16 +294,63 @@ void obs_source_update(obs_source_t source, obs_data_t settings)
|
|||
source->info.update(source->data, source->settings);
|
||||
}
|
||||
|
||||
void obs_source_activate(obs_source_t source)
|
||||
static void activate_source(obs_source_t source)
|
||||
{
|
||||
struct calldata data = {0};
|
||||
|
||||
if (source->info.activate)
|
||||
source->info.activate(source->data);
|
||||
|
||||
calldata_setptr(&data, "source", source);
|
||||
signal_handler_signal(obs->signals, "source-activate", &data);
|
||||
signal_handler_signal(source->signals, "activate", &data);
|
||||
calldata_free(&data);
|
||||
}
|
||||
|
||||
static void deactivate_source(obs_source_t source)
|
||||
{
|
||||
struct calldata data = {0};
|
||||
|
||||
if (source->info.deactivate)
|
||||
source->info.deactivate(source->data);
|
||||
|
||||
calldata_setptr(&data, "source", source);
|
||||
signal_handler_signal(obs->signals, "source-deactivate", &data);
|
||||
signal_handler_signal(source->signals, "deactivate", &data);
|
||||
calldata_free(&data);
|
||||
}
|
||||
|
||||
static void activate_tree(obs_source_t parent, obs_source_t child, void *param)
|
||||
{
|
||||
if (++child->activate_refs == 1)
|
||||
activate_source(child);
|
||||
}
|
||||
|
||||
static void deactivate_tree(obs_source_t parent, obs_source_t child,
|
||||
void *param)
|
||||
{
|
||||
if (--child->activate_refs == 0)
|
||||
deactivate_source(child);
|
||||
}
|
||||
|
||||
void obs_source_activate(obs_source_t source)
|
||||
{
|
||||
if (!source) return;
|
||||
|
||||
if (++source->activate_refs == 1) {
|
||||
activate_source(source);
|
||||
obs_source_enum_tree(source, activate_tree, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_source_deactivate(obs_source_t source)
|
||||
{
|
||||
if (source->info.deactivate)
|
||||
source->info.deactivate(source->data);
|
||||
if (!source) return;
|
||||
|
||||
if (--source->activate_refs == 0) {
|
||||
deactivate_source(source);
|
||||
obs_source_enum_tree(source, deactivate_tree, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_source_video_tick(obs_source_t source, float seconds)
|
||||
|
@ -1219,3 +1266,19 @@ void obs_source_enum_tree(obs_source_t source,
|
|||
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
void obs_source_add_child(obs_source_t parent, obs_source_t child)
|
||||
{
|
||||
if (!parent || !child) return;
|
||||
|
||||
if (parent->activate_refs > 0)
|
||||
obs_source_activate(child);
|
||||
}
|
||||
|
||||
void obs_source_remove_child(obs_source_t parent, obs_source_t child)
|
||||
{
|
||||
if (!parent || !child) return;
|
||||
|
||||
if (parent->activate_refs > 0)
|
||||
obs_source_deactivate(child);
|
||||
}
|
||||
|
|
|
@ -93,10 +93,15 @@ void obs_view_setsource(obs_view_t view, uint32_t channel,
|
|||
prev_source = view->channels[channel];
|
||||
view->channels[channel] = source;
|
||||
|
||||
if (source)
|
||||
if (source) {
|
||||
obs_source_addref(source);
|
||||
if (prev_source)
|
||||
obs_source_activate(source);
|
||||
}
|
||||
|
||||
if (prev_source) {
|
||||
obs_source_deactivate(prev_source);
|
||||
obs_source_release(prev_source);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&view->channels_mutex);
|
||||
}
|
||||
|
|
|
@ -678,10 +678,15 @@ void obs_set_output_source(uint32_t channel, obs_source_t source)
|
|||
|
||||
view->channels[channel] = source;
|
||||
|
||||
if (source)
|
||||
if (source) {
|
||||
obs_source_addref(source);
|
||||
if (prev_source)
|
||||
obs_source_activate(source);
|
||||
}
|
||||
|
||||
if (prev_source) {
|
||||
obs_source_deactivate(prev_source);
|
||||
obs_source_release(prev_source);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&view->channels_mutex);
|
||||
}
|
||||
|
|
17
libobs/obs.h
17
libobs/obs.h
|
@ -520,6 +520,9 @@ EXPORT void obs_source_enum_tree(obs_source_t source,
|
|||
obs_source_enum_proc_t enum_callback,
|
||||
void *param);
|
||||
|
||||
/** Returns true if active, false if not */
|
||||
EXPORT bool obs_source_active(obs_source_t source);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Functions used by sources */
|
||||
|
||||
|
@ -543,6 +546,20 @@ EXPORT void obs_source_process_filter(obs_source_t filter, effect_t effect,
|
|||
uint32_t width, uint32_t height, enum gs_color_format format,
|
||||
enum allow_direct_render allow_direct);
|
||||
|
||||
/**
|
||||
* Adds a child source. Must be called by parent sources on child sources
|
||||
* when the child is added. This ensures that the source is properly activated
|
||||
* if the parent is active.
|
||||
*/
|
||||
EXPORT void obs_source_add_child(obs_source_t parent, obs_source_t child);
|
||||
|
||||
/**
|
||||
* Removes a child source. Must be called by parent sources on child sources
|
||||
* when the child is removed. This ensures that the source is properly
|
||||
* deactivated if the parent is active.
|
||||
*/
|
||||
EXPORT void obs_source_remove_child(obs_source_t parent, obs_source_t child);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Scenes */
|
||||
|
|
|
@ -37,6 +37,7 @@ Q_DECLARE_METATYPE(OBSSceneItem);
|
|||
OBSBasic::OBSBasic(QWidget *parent)
|
||||
: OBSMainWindow (parent),
|
||||
outputTest (NULL),
|
||||
sceneChanging (false),
|
||||
ui (new Ui::OBSBasic)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -194,12 +195,14 @@ void OBSBasic::UpdateSceneSelection(OBSSource source)
|
|||
obs_scene_t scene = obs_scene_fromsource(source);
|
||||
const char *name = obs_source_getname(source);
|
||||
|
||||
QListWidgetItem *sel = ui->scenes->currentItem();
|
||||
QList<QListWidgetItem*> items =
|
||||
ui->scenes->findItems(QT_UTF8(name), Qt::MatchExactly);
|
||||
|
||||
if (items.contains(sel)) {
|
||||
ui->scenes->setCurrentItem(sel);
|
||||
if (items.count()) {
|
||||
sceneChanging = true;
|
||||
ui->scenes->setCurrentItem(items.first());
|
||||
sceneChanging = false;
|
||||
|
||||
UpdateSources(scene);
|
||||
}
|
||||
}
|
||||
|
@ -384,20 +387,26 @@ void OBSBasic::on_action_Save_triggered()
|
|||
/* TODO */
|
||||
}
|
||||
|
||||
void OBSBasic::on_scenes_itemChanged(QListWidgetItem *item)
|
||||
void OBSBasic::on_scenes_currentItemChanged(QListWidgetItem *current,
|
||||
QListWidgetItem *prev)
|
||||
{
|
||||
obs_source_t source = NULL;
|
||||
|
||||
if (item) {
|
||||
if (sceneChanging)
|
||||
return;
|
||||
|
||||
if (current) {
|
||||
obs_scene_t scene;
|
||||
|
||||
scene = item->data(Qt::UserRole).value<OBSScene>();
|
||||
scene = current->data(Qt::UserRole).value<OBSScene>();
|
||||
source = obs_scene_getsource(scene);
|
||||
UpdateSources(scene);
|
||||
}
|
||||
|
||||
/* TODO: allow transitions */
|
||||
obs_set_output_source(0, source);
|
||||
|
||||
UNUSED_PARAMETER(prev);
|
||||
}
|
||||
|
||||
void OBSBasic::on_scenes_customContextMenuRequested(const QPoint &pos)
|
||||
|
@ -462,10 +471,12 @@ void OBSBasic::on_actionSceneDown_triggered()
|
|||
/* TODO */
|
||||
}
|
||||
|
||||
void OBSBasic::on_sources_itemChanged(QListWidgetItem *item)
|
||||
void OBSBasic::on_sources_currentItemChanged(QListWidgetItem *current,
|
||||
QListWidgetItem *prev)
|
||||
{
|
||||
/* TODO */
|
||||
UNUSED_PARAMETER(item);
|
||||
UNUSED_PARAMETER(current);
|
||||
UNUSED_PARAMETER(prev);
|
||||
}
|
||||
|
||||
void OBSBasic::on_sources_customContextMenuRequested(const QPoint &pos)
|
||||
|
|
|
@ -32,6 +32,7 @@ class OBSBasic : public OBSMainWindow {
|
|||
private:
|
||||
std::unordered_map<obs_source_t, int> sourceSceneRefs;
|
||||
obs_output_t outputTest;
|
||||
bool sceneChanging;
|
||||
|
||||
OBSScene GetCurrentScene();
|
||||
OBSSceneItem GetCurrentSceneItem();
|
||||
|
@ -75,14 +76,16 @@ private slots:
|
|||
void on_action_New_triggered();
|
||||
void on_action_Open_triggered();
|
||||
void on_action_Save_triggered();
|
||||
void on_scenes_itemChanged(QListWidgetItem *item);
|
||||
void on_scenes_currentItemChanged(QListWidgetItem *current,
|
||||
QListWidgetItem *prev);
|
||||
void on_scenes_customContextMenuRequested(const QPoint &pos);
|
||||
void on_actionAddScene_triggered();
|
||||
void on_actionRemoveScene_triggered();
|
||||
void on_actionSceneProperties_triggered();
|
||||
void on_actionSceneUp_triggered();
|
||||
void on_actionSceneDown_triggered();
|
||||
void on_sources_itemChanged(QListWidgetItem *item);
|
||||
void on_sources_currentItemChanged(QListWidgetItem *current,
|
||||
QListWidgetItem *prev);
|
||||
void on_sources_customContextMenuRequested(const QPoint &pos);
|
||||
void on_actionAddSource_triggered();
|
||||
void on_actionRemoveSource_triggered();
|
||||
|
|
Loading…
Reference in a new issue