[aravis] gv_device: don't create stream object without control access.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aravis] gv_device: don't create stream object without control access.
- Date: Thu, 5 May 2011 13:21:10 +0000 (UTC)
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]