소스 검색

linux-v4l2: Replace custom udev callbacks

Use the signal system provided by obs instead of the custom callback
implementation. This reduces the amount of code and complexity.
fryshorts 10 년 전
부모
커밋
4bf7a7b61e
3개의 변경된 파일66개의 추가작업 그리고 112개의 파일을 삭제
  1. 19 7
      plugins/linux-v4l2/v4l2-input.c
  2. 40 65
      plugins/linux-v4l2/v4l2-udev.c
  3. 7 40
      plugins/linux-v4l2/v4l2-udev.h

+ 19 - 7
plugins/linux-v4l2/v4l2-input.c

@@ -80,7 +80,6 @@ struct v4l2_data {
 	obs_source_t *source;
 	pthread_t thread;
 	os_event_t *event;
-	void *udev;
 
 	int_fast32_t dev;
 	int width;
@@ -674,12 +673,15 @@ static bool resolution_selected(obs_properties_t *props, obs_property_t *p,
  * If everything went fine we can start capturing again when the device is
  * reconnected
  */
-static void device_added(const char *dev, void *vptr)
+static void device_added(void *vptr, calldata_t *calldata)
 {
 	V4L2_DATA(vptr);
 
 	obs_source_update_properties(data->source);
 
+	const char *dev;
+	calldata_get_string(calldata, "device", &dev);
+
 	if (strcmp(data->device_id, dev))
 		return;
 
@@ -692,12 +694,15 @@ static void device_added(const char *dev, void *vptr)
  *
  * We stop recording here so we don't block the device node
  */
-static void device_removed(const char *dev, void *vptr)
+static void device_removed(void *vptr, calldata_t *calldata)
 {
 	V4L2_DATA(vptr);
 
 	obs_source_update_properties(data->source);
 
+	const char *dev;
+	calldata_get_string(calldata, "device", &dev);
+
 	if (strcmp(data->device_id, dev))
 		return;
 
@@ -790,7 +795,12 @@ static void v4l2_destroy(void *vptr)
 		bfree(data->device_id);
 
 #if HAVE_UDEV
-	v4l2_unref_udev(data->udev);
+	signal_handler_t *sh = v4l2_get_udev_signalhandler();
+
+	signal_handler_disconnect(sh, "device_added", device_added, data);
+	signal_handler_disconnect(sh, "device_removed", device_removed, data);
+
+	v4l2_unref_udev();
 #endif
 
 	bfree(data);
@@ -946,9 +956,11 @@ static void *v4l2_create(obs_data_t *settings, obs_source_t *source)
 	v4l2_update(data, settings);
 
 #if HAVE_UDEV
-	data->udev = v4l2_init_udev();
-	v4l2_set_device_added_callback(data->udev, &device_added, data);
-	v4l2_set_device_removed_callback(data->udev, &device_removed, data);
+	v4l2_init_udev();
+	signal_handler_t *sh = v4l2_get_udev_signalhandler();
+
+	signal_handler_connect(sh, "device_added", &device_added, data);
+	signal_handler_connect(sh, "device_removed", &device_removed, data);
 #endif
 
 	return data;

+ 40 - 65
plugins/linux-v4l2/v4l2-udev.c

@@ -23,9 +23,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "v4l2-udev.h"
 
-#define UDEV_DATA(voidptr) struct v4l2_udev_mon_t *m \
-		= (struct v4l2_udev_mon_t *) voidptr;
-
 /** udev action enum */
 enum udev_action {
 	UDEV_ACTION_ADDED,
@@ -33,14 +30,10 @@ enum udev_action {
 	UDEV_ACTION_UNKNOWN
 };
 
-/** monitor object holding the callbacks */
-struct v4l2_udev_mon_t {
-	/* data for the device added callback */
-	void *dev_added_userdata;
-	v4l2_device_added_cb dev_added_cb;
-	/* data for the device removed callback */
-	void *dev_removed_userdata;
-	v4l2_device_removed_cb dev_removed_cb;
+static const char *udev_signals[] = {
+	"void device_added(string device)",
+	"void device_removed(string device)",
+	NULL
 };
 
 /* global data */
@@ -50,7 +43,7 @@ static pthread_mutex_t udev_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_t udev_thread;
 static os_event_t *udev_event;
 
-static DARRAY(struct v4l2_udev_mon_t) udev_clients;
+static signal_handler_t *udev_signalhandler = NULL;
 
 /**
  * udev gives us the device action as string, so we convert it here ...
@@ -76,35 +69,36 @@ static enum udev_action udev_action_to_enum(const char *action)
  *
  * @param dev udev device that had an event occuring
  */
-static inline void udev_call_callbacks(struct udev_device *dev)
+static inline void udev_signal_event(struct udev_device *dev)
 {
 	const char *node;
 	enum udev_action action;
+	struct calldata data;
 
 	pthread_mutex_lock(&udev_mutex);
 
 	node   = udev_device_get_devnode(dev);
 	action = udev_action_to_enum(udev_device_get_action(dev));
 
-	for (size_t idx = 0; idx < udev_clients.num; idx++) {
-		struct v4l2_udev_mon_t *c = &udev_clients.array[idx];
-
-		switch (action) {
-		case UDEV_ACTION_ADDED:
-			if (!c->dev_added_cb)
-				continue;
-			c->dev_added_cb(node, c->dev_added_userdata);
-			break;
-		case UDEV_ACTION_REMOVED:
-			if (!c->dev_removed_cb)
-				continue;
-			c->dev_removed_cb(node, c->dev_removed_userdata);
-			break;
-		default:
-			break;
-		}
+	calldata_init(&data);
+
+	calldata_set_string(&data, "device", node);
+
+	switch (action) {
+	case UDEV_ACTION_ADDED:
+		signal_handler_signal(udev_signalhandler,
+				"device_added", &data);
+		break;
+	case UDEV_ACTION_REMOVED:
+		signal_handler_signal(udev_signalhandler,
+				"device_removed", &data);
+		break;
+	default:
+		break;
 	}
 
+	calldata_free(&data);
+
 	pthread_mutex_unlock(&udev_mutex);
 }
 
@@ -146,7 +140,7 @@ static void *udev_event_thread(void *vptr)
 		if (!dev)
 			continue;
 
-		udev_call_callbacks(dev);
+		udev_signal_event(dev);
 
 		udev_device_unref(dev);
 	}
@@ -157,10 +151,8 @@ static void *udev_event_thread(void *vptr)
 	return NULL;
 }
 
-void *v4l2_init_udev(void)
+void v4l2_init_udev(void)
 {
-	struct v4l2_udev_mon_t *ret = NULL;
-
 	pthread_mutex_lock(&udev_mutex);
 
 	/* set up udev */
@@ -170,55 +162,38 @@ void *v4l2_init_udev(void)
 		if (pthread_create(&udev_thread, NULL, udev_event_thread,
 				NULL) != 0)
 			goto fail;
-		da_init(udev_clients);
+
+		udev_signalhandler = signal_handler_create();
+		if (!udev_signalhandler)
+			goto fail;
+		signal_handler_add_array(udev_signalhandler, udev_signals);
+
 	}
 	udev_refs++;
 
-	/* create monitor object */
-	ret = da_push_back_new(udev_clients);
 fail:
 	pthread_mutex_unlock(&udev_mutex);
-	return ret;
 }
 
-void v4l2_unref_udev(void *monitor)
+void v4l2_unref_udev(void)
 {
-	UDEV_DATA(monitor);
 	pthread_mutex_lock(&udev_mutex);
 
-	/* clean up monitor object */
-	da_erase_item(udev_clients, m);
-
 	/* unref udev monitor */
-	udev_refs--;
-	if (udev_refs == 0) {
+	if (udev_refs && --udev_refs == 0) {
 		os_event_signal(udev_event);
 		pthread_join(udev_thread, NULL);
 		os_event_destroy(udev_event);
-		da_free(udev_clients);
+
+		if (udev_signalhandler)
+			signal_handler_destroy(udev_signalhandler);
+		udev_signalhandler = NULL;
 	}
 
 	pthread_mutex_unlock(&udev_mutex);
 }
 
-void v4l2_set_device_added_callback(void *monitor, v4l2_device_added_cb cb,
-		void *userdata)
+signal_handler_t *v4l2_get_udev_signalhandler(void)
 {
-	UDEV_DATA(monitor);
-	if (!m)
-		return;
-
-	m->dev_added_cb = cb;
-	m->dev_added_userdata = userdata;
-}
-
-void v4l2_set_device_removed_callback(void *monitor, v4l2_device_removed_cb cb,
-		void *userdata)
-{
-	UDEV_DATA(monitor);
-	if (!m)
-		return;
-
-	m->dev_removed_cb = cb;
-	m->dev_removed_userdata = userdata;
+	return udev_signalhandler;
 }

+ 7 - 40
plugins/linux-v4l2/v4l2-udev.h

@@ -19,61 +19,28 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <inttypes.h>
 
+#include <callback/signal.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * Initialize udev system to watch for device events
- *
- * @return monitor object, or NULL on error
  */
-void *v4l2_init_udev(void);
+void v4l2_init_udev(void);
 
 /**
  * Unref the udev system
- *
- * This will also remove any registered callbacks if there are any
- *
- * @param monitor monitor object
- */
-void v4l2_unref_udev(void *monitor);
-
-/**
- * Callback when a device was added.
- *
- * @param dev device node of the device that was added
- * @param userdata pointer to userdata specified when registered
- */
-typedef void (*v4l2_device_added_cb)(const char *dev, void *userdata);
-
-/**
- * Callback when a device was removed.
- *
- * @param dev device node of the device that was removed
- * @param userdata pointer to userdata specified when registered
- */
-typedef void (*v4l2_device_removed_cb)(const char *dev, void *userdata);
-
-/**
- * Register the device added callback
- *
- * @param monitor monitor object
- * @param cb the function that should be called
- * @param userdata pointer to userdata that should be passed to the callback
  */
-void v4l2_set_device_added_callback(void *monitor, v4l2_device_added_cb cb,
-		void *userdata);
+void v4l2_unref_udev(void);
 
 /**
- * Register the device remove callback
+ * Get signal handler
  *
- * @param monitor monitor object
- * @param cb the function that should be called
- * @param userdata pointer to userdata that should be passed to the callback
+ * @return signal handler for udev events
  */
-void v4l2_set_device_removed_callback(void *monitor, v4l2_device_removed_cb cb,
-		void *userdata);
+signal_handler_t *v4l2_get_udev_signalhandler(void);
 
 #ifdef __cplusplus
 }