diff options
author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2012-03-05 16:12:53 +0100 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2012-03-05 16:12:53 +0100 |
commit | 0483c86add2f496021560b82476d22e2497006be (patch) | |
tree | d0fbdd2f09760bf6719443cdceff6e53ee57ae1f | |
parent | 13acd5530fa2a6689b0a6a3ffa278d58c1428fe1 (diff) | |
download | uca-0483c86add2f496021560b82476d22e2497006be.tar.gz uca-0483c86add2f496021560b82476d22e2497006be.tar.bz2 uca-0483c86add2f496021560b82476d22e2497006be.tar.xz uca-0483c86add2f496021560b82476d22e2497006be.zip |
Complete async xfer infrastructure
-rw-r--r-- | src/cameras/uca-mock-camera.c | 67 | ||||
-rw-r--r-- | src/uca-camera.c | 28 | ||||
-rw-r--r-- | src/uca-camera.h | 7 | ||||
-rw-r--r-- | test/test-mock.c | 35 |
4 files changed, 129 insertions, 8 deletions
diff --git a/src/cameras/uca-mock-camera.c b/src/cameras/uca-mock-camera.c index 8dacf5d..b1c325e 100644 --- a/src/cameras/uca-mock-camera.c +++ b/src/cameras/uca-mock-camera.c @@ -59,23 +59,84 @@ struct _UcaMockCameraPrivate { guint framerate; guint16 *dummy_data; + gboolean thread_running; + + GThread *grab_thread; GValueArray *binnings; }; +/** + * uca_mock_camera_new: + * @error: Location for error + * + * Create a new #UcaMockCamera object. + * + * Returns: A newly created #UcaMockCamera object + */ UcaMockCamera *uca_mock_camera_new(GError **error) { UcaMockCamera *camera = g_object_new(UCA_TYPE_MOCK_CAMERA, NULL); return camera; } +static gpointer mock_grab_func(gpointer data) +{ + UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); + g_return_val_if_fail(UCA_IS_MOCK_CAMERA(mock_camera), NULL); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(mock_camera); + UcaCamera *camera = UCA_CAMERA(mock_camera); + const gulong sleep_time = G_USEC_PER_SEC / priv->framerate; + + while (priv->thread_running) { + camera->grab_func(NULL, camera->user_data); + g_usleep(sleep_time); + } + + return NULL; +} + static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + /* + * In case asynchronous transfer is requested, we start a new thread that + * invokes the grab callback, otherwise nothing will be done here. + */ + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + gboolean transfer_async = FALSE; + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + GError *tmp_error = NULL; + priv->thread_running = TRUE; + priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); + + if (tmp_error != NULL) { + priv->thread_running = FALSE; + g_propagate_error(error, tmp_error); + } + } } static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + gboolean transfer_async = FALSE; + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } } static void uca_mock_camera_grab(UcaCamera *camera, gpointer data, GError **error) @@ -145,6 +206,11 @@ static void uca_mock_camera_finalize(GObject *object) { UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + if (priv->thread_running) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } + g_free(priv->dummy_data); g_value_array_free(priv->binnings); @@ -185,6 +251,7 @@ static void uca_mock_camera_init(UcaMockCamera *self) self->priv->width = 640; self->priv->height = 480; self->priv->dummy_data = (guint16 *) g_malloc0(self->priv->width * self->priv->height); + self->priv->grab_thread = NULL; self->priv->binnings = g_value_array_new(1); GValue val = {0}; diff --git a/src/uca-camera.c b/src/uca-camera.c index 88b6ddd..ac04b86 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -64,7 +64,16 @@ static GParamSpec *camera_properties[N_PROPERTIES] = { NULL, }; static void uca_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_TRANSFER_ASYNCHRONOUSLY: + priv->transfer_async = g_value_get_boolean(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } } static void uca_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) @@ -76,6 +85,10 @@ static void uca_camera_get_property(GObject *object, guint property_id, GValue * g_value_set_boolean(value, priv->is_recording); break; + case PROP_TRANSFER_ASYNCHRONOUSLY: + g_value_set_boolean(value, priv->transfer_async); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -180,6 +193,8 @@ static void uca_camera_class_init(UcaCameraClass *klass) static void uca_camera_init(UcaCamera *camera) { + camera->grab_func = NULL; + camera->priv = UCA_CAMERA_GET_PRIVATE(camera); camera->priv->is_recording = FALSE; camera->priv->transfer_async = FALSE; @@ -230,6 +245,12 @@ void uca_camera_start_recording(UcaCamera *camera, GError **error) return; } + if (camera->priv->transfer_async && (camera->grab_func == NULL)) { + g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NO_GRAB_FUNC, + "No grab callback function set"); + return; + } + GError *tmp_error = NULL; (*klass->start_recording)(camera, &tmp_error); @@ -280,9 +301,10 @@ void uca_camera_stop_recording(UcaCamera *camera, GError **error) * * Set the grab function that is called whenever a frame is readily transfered. */ -void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func) +void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data) { - /* TODO: implement */ + camera->grab_func = func; + camera->user_data = user_data; } void uca_camera_grab(UcaCamera *camera, gpointer data, GError **error) diff --git a/src/uca-camera.h b/src/uca-camera.h index dc5901a..0370466 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -30,7 +30,8 @@ #define UCA_CAMERA_ERROR uca_camera_error_quark() typedef enum { UCA_CAMERA_ERROR_RECORDING, - UCA_CAMERA_ERROR_NOT_RECORDING + UCA_CAMERA_ERROR_NOT_RECORDING, + UCA_CAMERA_ERROR_NO_GRAB_FUNC } UcaCameraError; typedef struct _UcaCamera UcaCamera; @@ -51,6 +52,8 @@ struct _UcaCamera { GObject parent; UcaCameraGrabFunc grab_func; + gpointer user_data; + UcaCameraPrivate *priv; }; @@ -74,7 +77,7 @@ struct _UcaCameraClass { void uca_camera_start_recording(UcaCamera *camera, GError **error); void uca_camera_stop_recording(UcaCamera *camera, GError **error); void uca_camera_grab(UcaCamera *camera, gpointer data, GError **error); -void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func); +void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data); GType uca_camera_get_type(void); diff --git a/test/test-mock.c b/test/test-mock.c index 5831951..5340166 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -32,14 +32,14 @@ static void test_recording(Fixture *fixture, gconstpointer data) UcaCamera *camera = UCA_CAMERA(fixture->camera); uca_camera_stop_recording(camera, &error); - g_assert(error != NULL); + g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING); g_error_free(error); error = NULL; uca_camera_start_recording(camera, &error); - g_assert(error == NULL); + g_assert_no_error(error); uca_camera_stop_recording(camera, &error); - g_assert(error == NULL); + g_assert_no_error(error); } static void test_recording_signal(Fixture *fixture, gconstpointer data) @@ -57,6 +57,34 @@ static void test_recording_signal(Fixture *fixture, gconstpointer data) g_assert(success == TRUE); } +static void grab_func(gpointer data, gpointer user_data) +{ + gboolean *success = (gboolean *) user_data; + *success = TRUE; +} + +static void test_recording_async(Fixture *fixture, gconstpointer data) +{ + UcaCamera *camera = UCA_CAMERA(fixture->camera); + + gboolean success = FALSE; + uca_camera_set_grab_func(camera, grab_func, &success); + + g_object_set(G_OBJECT(camera), + "framerate", 10, + "transfer-asynchronously", TRUE, + NULL); + + GError *error = NULL; + uca_camera_start_recording(camera, &error); + g_assert_no_error(error); + + g_usleep(G_USEC_PER_SEC / 8); + + uca_camera_stop_recording(camera, &error); + g_assert_no_error(error); +} + static void test_recording_property(Fixture *fixture, gconstpointer data) { UcaCamera *camera = UCA_CAMERA(fixture->camera); @@ -124,6 +152,7 @@ int main(int argc, char *argv[]) g_test_add("/recording", Fixture, NULL, fixture_setup, test_recording, fixture_teardown); g_test_add("/recording/signal", Fixture, NULL, fixture_setup, test_recording_signal, fixture_teardown); + g_test_add("/recording/asynchronous", Fixture, NULL, fixture_setup, test_recording_async, fixture_teardown); g_test_add("/properties/base", Fixture, NULL, fixture_setup, test_base_properties, fixture_teardown); g_test_add("/properties/recording", Fixture, NULL, fixture_setup, test_recording_property, fixture_teardown); g_test_add("/properties/binnings", Fixture, NULL, fixture_setup, test_binnings_properties, fixture_teardown); |