Use QMetaObject::invokeMethod in libobs callbacks

Doing this ensures Qt thread safety when adding/removing sources and
scenes, because it will defer the function call to the main thread.
This commit is contained in:
jp9000 2014-02-02 17:03:55 -07:00
parent cfa62354cd
commit 37ed83acec
4 changed files with 54 additions and 49 deletions

View file

@ -314,14 +314,14 @@ static void obs_sceneitem_destroy(obs_sceneitem_t item)
int obs_sceneitem_addref(obs_sceneitem_t item)
{
return ++item->ref;
return item ? ++item->ref : 0;
}
int obs_sceneitem_release(obs_sceneitem_t item)
{
int ref = 0;
if (item ) {
if (item) {
ref = --item->ref;
if (!ref)
obs_sceneitem_destroy(item);

View file

@ -221,24 +221,18 @@ static void obs_source_destroy(obs_source_t source)
int obs_source_addref(obs_source_t source)
{
assert(source != NULL);
if (!source)
return 0;
return ++source->refs;
return source ? ++source->refs : 0;
}
int obs_source_release(obs_source_t source)
{
int refs;
int refs = 0;
assert(source != NULL);
if (!source)
return 0;
refs = --source->refs;
if (refs == 0)
obs_source_destroy(source);
if (source) {
refs = --source->refs;
if (refs == 0)
obs_source_destroy(source);
}
return refs;
}

View file

@ -63,11 +63,8 @@ void OBSBasic::OBSInit()
/* TODO: this is a test */
obs_load_module("test-input");
#ifdef _WIN32
/* HACK: fixes a windows qt bug with native widgets with native
* repaint */
/* HACK: fixes a qt bug with native widgets with native repaint */
ui->previewContainer->repaint();
#endif
}
OBSBasic::~OBSBasic()
@ -91,7 +88,22 @@ OBSSceneItem OBSBasic::GetCurrentSceneItem()
return item ? item->data(Qt::UserRole).value<OBSSceneItem>() : nullptr;
}
void OBSBasic::AddScene(obs_source_t source)
void OBSBasic::UpdateSources(OBSScene scene)
{
ui->sources->clear();
obs_scene_enum_items(scene,
[] (obs_scene_t scene, obs_sceneitem_t item, void *p)
{
OBSBasic *window = static_cast<OBSBasic*>(p);
window->AddSceneItem(item);
return true;
}, this);
}
/* Qt callbacks for invokeMethod */
void OBSBasic::AddScene(OBSSource source)
{
const char *name = obs_source_getname(source);
obs_scene_t scene = obs_scene_fromsource(source);
@ -106,7 +118,7 @@ void OBSBasic::AddScene(obs_source_t source)
this);
}
void OBSBasic::RemoveScene(obs_source_t source)
void OBSBasic::RemoveScene(OBSSource source)
{
const char *name = obs_source_getname(source);
@ -121,7 +133,7 @@ void OBSBasic::RemoveScene(obs_source_t source)
}
}
void OBSBasic::AddSceneItem(obs_sceneitem_t item)
void OBSBasic::AddSceneItem(OBSSceneItem item)
{
obs_scene_t scene = obs_sceneitem_getscene(item);
obs_source_t source = obs_sceneitem_getsource(item);
@ -138,7 +150,7 @@ void OBSBasic::AddSceneItem(obs_sceneitem_t item)
sourceSceneRefs[source] = sourceSceneRefs[source] + 1;
}
void OBSBasic::RemoveSceneItem(obs_sceneitem_t item)
void OBSBasic::RemoveSceneItem(OBSSceneItem item)
{
obs_scene_t scene = obs_sceneitem_getscene(item);
@ -163,20 +175,7 @@ void OBSBasic::RemoveSceneItem(obs_sceneitem_t item)
}
}
void OBSBasic::UpdateSources(obs_scene_t scene)
{
ui->sources->clear();
obs_scene_enum_items(scene,
[] (obs_scene_t scene, obs_sceneitem_t item, void *p)
{
OBSBasic *window = static_cast<OBSBasic*>(p);
window->AddSceneItem(item);
return true;
}, this);
}
void OBSBasic::UpdateSceneSelection(obs_source_t source)
void OBSBasic::UpdateSceneSelection(OBSSource source)
{
if (source) {
obs_source_type type;
@ -208,7 +207,8 @@ void OBSBasic::SceneItemAdded(void *data, calldata_t params)
obs_scene_t scene = (obs_scene_t)calldata_ptr(params, "scene");
obs_sceneitem_t item = (obs_sceneitem_t)calldata_ptr(params, "item");
window->AddSceneItem(item);
QMetaObject::invokeMethod(window, "AddSceneItem",
Q_ARG(OBSSceneItem, OBSSceneItem(item)));
}
void OBSBasic::SceneItemRemoved(void *data, calldata_t params)
@ -218,7 +218,8 @@ void OBSBasic::SceneItemRemoved(void *data, calldata_t params)
obs_scene_t scene = (obs_scene_t)calldata_ptr(params, "scene");
obs_sceneitem_t item = (obs_sceneitem_t)calldata_ptr(params, "item");
window->RemoveSceneItem(item);
QMetaObject::invokeMethod(window, "RemoveSceneItem",
Q_ARG(OBSSceneItem, OBSSceneItem(item)));
}
void OBSBasic::SourceAdded(void *data, calldata_t params)
@ -229,7 +230,9 @@ void OBSBasic::SourceAdded(void *data, calldata_t params)
obs_source_gettype(source, &type, NULL);
if (type == SOURCE_SCENE)
static_cast<OBSBasic*>(data)->AddScene(source);
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
"AddScene",
Q_ARG(OBSSource, OBSSource(source)));
}
void OBSBasic::SourceRemoved(void *data, calldata_t params)
@ -240,7 +243,9 @@ void OBSBasic::SourceRemoved(void *data, calldata_t params)
obs_source_gettype(source, &type, NULL);
if (type == SOURCE_SCENE)
static_cast<OBSBasic*>(data)->RemoveScene(source);
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
"RemoveScene",
Q_ARG(OBSSource, OBSSource(source)));
}
void OBSBasic::ChannelChanged(void *data, calldata_t params)
@ -249,7 +254,9 @@ void OBSBasic::ChannelChanged(void *data, calldata_t params)
uint32_t channel = calldata_uint32(params, "channel");
if (channel == 0)
static_cast<OBSBasic*>(data)->UpdateSceneSelection(source);
QMetaObject::invokeMethod(static_cast<OBSBasic*>(data),
"UpdateSceneSelection",
Q_ARG(OBSSource, OBSSource(source)));
}
/* Main class functions */

View file

@ -32,15 +32,19 @@ class OBSBasic : public OBSMainWindow {
private:
std::unordered_map<obs_source_t, int> sourceSceneRefs;
OBSScene GetCurrentScene();
OBSScene GetCurrentScene();
OBSSceneItem GetCurrentSceneItem();
void AddSceneItem(obs_sceneitem_t item);
void RemoveSceneItem(obs_sceneitem_t item);
void AddScene(obs_source_t scene);
void RemoveScene(obs_source_t scene);
void UpdateSources(obs_scene_t scene);
void UpdateSceneSelection(obs_source_t source);
void UpdateSources(OBSScene scene);
private slots:
void AddSceneItem(OBSSceneItem item);
void RemoveSceneItem(OBSSceneItem item);
void AddScene(OBSSource source);
void RemoveScene(OBSSource source);
void UpdateSceneSelection(OBSSource source);
private:
/* OBS Callbacks */
static void SceneItemAdded(void *data, calldata_t params);
static void SceneItemRemoved(void *data, calldata_t params);