Browse Source

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.
jp9000 12 years ago
parent
commit
37ed83acec
4 changed files with 54 additions and 49 deletions
  1. 2 2
      libobs/obs-scene.c
  2. 7 13
      libobs/obs-source.c
  3. 34 27
      obs/window-basic-main.cpp
  4. 11 7
      obs/window-basic-main.hpp

+ 2 - 2
libobs/obs-scene.c

@@ -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);

+ 7 - 13
libobs/obs-source.c

@@ -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;
-
-	assert(source != NULL);
-	if (!source)
-		return 0;
+	int refs = 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;
 }

+ 34 - 27
obs/window-basic-main.cpp

@@ -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 */

+ 11 - 7
obs/window-basic-main.hpp

@@ -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);