[aravis] gv_device: don't create stream object without control access.



commit cb0936ae19517198a7ce13eb18703871b983ad94
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Thu May 5 15:20:43 2011 +0200

    gv_device: don't create stream object without control access.

 src/arvgvdevice.c     |   82 +++++++++++++++++++++++++++++++--------------
 tests/arvcameratest.c |   89 ++++++++++++++++++++++++++-----------------------
 viewer/arvviewer.c    |    6 +++
 3 files changed, 109 insertions(+), 68 deletions(-)
---
diff --git a/src/arvgvdevice.c b/src/arvgvdevice.c
index 2737d1e..0525db1 100644
--- a/src/arvgvdevice.c
+++ b/src/arvgvdevice.c
@@ -37,22 +37,6 @@
 static GObjectClass *parent_class = NULL;
 static GRegex *arv_gv_device_url_regex = NULL;
 
-struct _ArvGvDevicePrivate {
-	gboolean is_controller;
-
-	void *io_data;
-
-	void *heartbeat_thread;
-	void *heartbeat_data;
-
-	ArvGc *genicam;
-
-	char *genicam_xml;
-	size_t genicam_xml_size;
-};
-
-/* Shared data (main thread - heartbeat) */
-
 typedef struct {
 	GMutex *mutex;
 
@@ -68,8 +52,24 @@ typedef struct {
 
 	unsigned int gvcp_n_retries;
 	unsigned int gvcp_timeout_ms;
+
+	gboolean is_controller;
 } ArvGvDeviceIOData;
 
+struct _ArvGvDevicePrivate {
+	ArvGvDeviceIOData *io_data;
+
+	void *heartbeat_thread;
+	void *heartbeat_data;
+
+	ArvGc *genicam;
+
+	char *genicam_xml;
+	size_t genicam_xml_size;
+};
+
+/* Shared data (main thread - heartbeat) */
+
 static gboolean
 _read_memory (ArvGvDeviceIOData *io_data, guint32 address, guint32 size, void *buffer)
 {
@@ -276,9 +276,17 @@ arv_gv_device_heartbeat_thread (void *data)
 	guint32 value;
 
 	do {
-		g_usleep (thread_data->period_us);
-		_read_register (io_data, ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, &value);
-		arv_debug ("device", "[GvDevice::Heartbeat] (%d)", value);
+		if (io_data->is_controller) {
+			g_usleep (thread_data->period_us);
+			_read_register (io_data, ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, &value);
+			arv_debug ("device", "[GvDevice::Heartbeat] (%d)", value);
+
+			if ((value & (ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL |
+				      ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_EXCLUSIVE)) == 0) {
+				arv_debug ("device", "[GvDevice::Heartbeat] Control access lost");
+				io_data->is_controller = FALSE;
+			}
+		}
 	} while (!thread_data->cancel);
 
 	return NULL;
@@ -289,11 +297,29 @@ arv_gv_device_heartbeat_thread (void *data)
 static gboolean
 arv_gv_device_take_control (ArvGvDevice *gv_device)
 {
-	gv_device->priv->is_controller = arv_device_write_register (ARV_DEVICE (gv_device),
-								    ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET,
-								    ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL);
+	guint32 value;
+
+	/* FIXME: prone to race condition error */
+
+	arv_device_read_register (ARV_DEVICE (gv_device), ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, &value);
+	if (value & (ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL | ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_EXCLUSIVE)) {
+		arv_debug ("device", "[GvDevice::take_control] Device already controlled by another user");
+		gv_device->priv->io_data->is_controller = FALSE;
+		return FALSE;
+	}
 
-	return gv_device->priv->is_controller;
+	arv_device_write_register (ARV_DEVICE (gv_device),
+				   ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET,
+				   ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL);
+	arv_device_read_register (ARV_DEVICE (gv_device), ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, &value);
+	if (value & (ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL | ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_EXCLUSIVE))
+		gv_device->priv->io_data->is_controller = TRUE;
+	else {
+		arv_debug ("device", "[GvDevice::take_control] Can't get control access");
+		gv_device->priv->io_data->is_controller = FALSE;
+	}
+
+	return gv_device->priv->io_data->is_controller;
 }
 
 static gboolean
@@ -303,7 +329,7 @@ arv_gv_device_leave_control (ArvGvDevice *gv_device)
 
 	result = arv_device_write_register (ARV_DEVICE (gv_device),
 					    ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, 0);
-	gv_device->priv->is_controller = FALSE;
+	gv_device->priv->io_data->is_controller = FALSE;
 
 	return result;
 }
@@ -491,6 +517,11 @@ arv_gv_device_create_stream (ArvDevice *device, ArvStreamCallback callback, void
 	GInetAddress *interface_address;
 	GInetAddress *device_address;
 
+	if (!io_data->is_controller) {
+		arv_debug ("device", "[GvDevice::create_stream] Can't create stream without control access");
+		return NULL;
+	}
+
 	interface_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (io_data->interface_address));
 	device_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (io_data->device_address));
 	address_bytes = g_inet_address_to_bytes (interface_address);
@@ -594,7 +625,7 @@ arv_gv_device_new (GInetAddress *interface_address, GInetAddress *device_address
 
 	gv_device = g_object_new (ARV_TYPE_GV_DEVICE, NULL);
 
-	io_data = g_new (ArvGvDeviceIOData, 1);
+	io_data = g_new0 (ArvGvDeviceIOData, 1);
 
 	io_data->mutex = g_mutex_new ();
 	io_data->packet_count = 0;
@@ -613,7 +644,6 @@ arv_gv_device_new (GInetAddress *interface_address, GInetAddress *device_address
 	io_data->poll_in_event.events =  G_IO_IN;
 	io_data->poll_in_event.revents = 0;
 
-
 	gv_device->priv->io_data = io_data;
 
 	arv_gv_device_load_genicam (gv_device);
diff --git a/tests/arvcameratest.c b/tests/arvcameratest.c
index cd3db93..45db418 100644
--- a/tests/arvcameratest.c
+++ b/tests/arvcameratest.c
@@ -211,68 +211,73 @@ main (int argc, char **argv)
 		g_printf ("gain                = %d dB\n", gain);
 
 		stream = arv_camera_create_stream (camera, NULL, NULL);
-		if (ARV_IS_GV_STREAM (stream)) {
-			if (arv_option_auto_socket_buffer)
+		if (stream != NULL) {
+			if (ARV_IS_GV_STREAM (stream)) {
+				if (arv_option_auto_socket_buffer)
+					g_object_set (stream,
+						      "socket-buffer", ARV_GV_STREAM_SOCKET_BUFFER_AUTO,
+						      "socket-buffer-size", 0,
+						      NULL);
+				if (arv_option_no_packet_resend)
+					g_object_set (stream,
+						      "packet-resend", ARV_GV_STREAM_PACKET_RESEND_NEVER,
+						      NULL);
 				g_object_set (stream,
-					      "socket-buffer", ARV_GV_STREAM_SOCKET_BUFFER_AUTO,
-					      "socket-buffer-size", 0,
+					      "packet-timeout", (unsigned) arv_option_packet_timeout * 1000,
+					      "frame-retention", (unsigned) arv_option_frame_retention * 1000,
 					      NULL);
-			if (arv_option_no_packet_resend)
-				g_object_set (stream,
-					      "packet-resend", ARV_GV_STREAM_PACKET_RESEND_NEVER,
-					      NULL);
-			g_object_set (stream,
-				      "packet-timeout", (unsigned) arv_option_packet_timeout * 1000,
-				      "frame-retention", (unsigned) arv_option_frame_retention * 1000,
-				      NULL);
-		}
+			}
+
+			for (i = 0; i < 50; i++)
+				arv_stream_push_buffer (stream, arv_buffer_new (payload, NULL));
 
-		for (i = 0; i < 50; i++)
-			arv_stream_push_buffer (stream, arv_buffer_new (payload, NULL));
+			arv_camera_set_acquisition_mode (camera, ARV_ACQUISITION_MODE_CONTINUOUS);
 
-		arv_camera_set_acquisition_mode (camera, ARV_ACQUISITION_MODE_CONTINUOUS);
+			if (arv_option_frequency > 0.0)
+				arv_camera_set_frame_rate (camera, arv_option_frequency);
 
-		if (arv_option_frequency > 0.0)
-			arv_camera_set_frame_rate (camera, arv_option_frequency);
+			if (arv_option_trigger != NULL)
+				arv_camera_set_trigger (camera, arv_option_trigger);
 
-		if (arv_option_trigger != NULL)
-			arv_camera_set_trigger (camera, arv_option_trigger);
+			if (arv_option_software_trigger > 0.0) {
+				arv_camera_set_trigger (camera, "Software");
+				software_trigger_source = g_timeout_add ((double) (0.5 + 1000.0 /
+										   arv_option_software_trigger),
+									 emit_software_trigger, camera);
+			}
 
-		if (arv_option_software_trigger > 0.0) {
-			arv_camera_set_trigger (camera, "Software");
-			software_trigger_source = g_timeout_add ((double) (0.5 + 1000.0 / arv_option_software_trigger),
-								 emit_software_trigger, camera);
-		}
+			arv_camera_start_acquisition (camera);
 
-		arv_camera_start_acquisition (camera);
+			g_signal_connect (stream, "new-buffer", G_CALLBACK (new_buffer_cb), &data);
+			arv_stream_set_emit_signals (stream, TRUE);
 
-		g_signal_connect (stream, "new-buffer", G_CALLBACK (new_buffer_cb), &data);
-		arv_stream_set_emit_signals (stream, TRUE);
+			g_timeout_add_seconds (1, periodic_task_cb, &data);
 
-		g_timeout_add_seconds (1, periodic_task_cb, &data);
+			data.main_loop = g_main_loop_new (NULL, FALSE);
 
-		data.main_loop = g_main_loop_new (NULL, FALSE);
+			old_sigint_handler = signal (SIGINT, set_cancel);
 
-		old_sigint_handler = signal (SIGINT, set_cancel);
+			g_main_loop_run (data.main_loop);
 
-		g_main_loop_run (data.main_loop);
+			if (software_trigger_source > 0)
+				g_source_remove (software_trigger_source);
 
-		if (software_trigger_source > 0)
-			g_source_remove (software_trigger_source);
+			signal (SIGINT, old_sigint_handler);
 
-		signal (SIGINT, old_sigint_handler);
+			g_main_loop_unref (data.main_loop);
 
-		g_main_loop_unref (data.main_loop);
+			arv_stream_get_statistics (stream, &n_completed_buffers, &n_failures, &n_underruns);
 
-		arv_stream_get_statistics (stream, &n_completed_buffers, &n_failures, &n_underruns);
+			g_printf ("Completed buffers = %Lu\n", (unsigned long long) n_completed_buffers);
+			g_printf ("Failures          = %Lu\n", (unsigned long long) n_failures);
+			g_printf ("Underruns         = %Lu\n", (unsigned long long) n_underruns);
 
-		g_printf ("Completed buffers = %Lu\n", (unsigned long long) n_completed_buffers);
-		g_printf ("Failures          = %Lu\n", (unsigned long long) n_failures);
-		g_printf ("Underruns         = %Lu\n", (unsigned long long) n_underruns);
+			arv_camera_stop_acquisition (camera);
 
-		arv_camera_stop_acquisition (camera);
+			g_object_unref (stream);
+		} else
+			g_printf ("Can't create stream thread (check if the device is not already used)\n");
 
-		g_object_unref (stream);
 		g_object_unref (camera);
 	} else
 		g_printf ("No camera found\n");
diff --git a/viewer/arvviewer.c b/viewer/arvviewer.c
index 5458ff7..b3cd3d2 100644
--- a/viewer/arvviewer.c
+++ b/viewer/arvviewer.c
@@ -367,6 +367,12 @@ arv_viewer_select_camera_cb (GtkComboBox *combo_box, ArvViewer *viewer)
 	g_free (camera_id);
 
 	viewer->stream = arv_camera_create_stream (viewer->camera, NULL, NULL);
+	if (viewer->stream == NULL) {
+		g_object_unref (viewer->camera);
+		viewer->camera = NULL;
+		return;
+	}
+
 	if (ARV_IS_GV_STREAM (viewer->stream)) {
 		if (arv_viewer_option_auto_socket_buffer)
 			g_object_set (viewer->stream,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]