From 3a45434834999e1ac7c7a99cdaa644d939b859b0 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 25 Sep 2012 18:18:23 +0200 Subject: Move tools from test/ to tools/ directory --- test/CMakeLists.txt | 57 +--- test/benchmark.c | 267 --------------- test/control.c | 350 ------------------- test/control.glade | 302 ----------------- test/egg-property-cell-renderer.c | 594 --------------------------------- test/egg-property-cell-renderer.h | 55 --- test/egg-property-tree-view.c | 114 ------- test/egg-property-tree-view.h | 54 --- test/grab-async.c | 138 -------- test/grab.c | 160 --------- test/perf-overhead.c | 181 ---------- test/test-all.c | 214 ------------ tools/CMakeLists.txt | 20 +- tools/benchmark.c | 267 +++++++++++++++ tools/grab-async.c | 138 ++++++++ tools/grab.c | 160 +++++++++ tools/gui/control.c | 350 +++++++++++++++++++ tools/gui/control.glade | 302 +++++++++++++++++ tools/gui/egg-property-cell-renderer.c | 594 +++++++++++++++++++++++++++++++++ tools/gui/egg-property-cell-renderer.h | 55 +++ tools/gui/egg-property-tree-view.c | 113 +++++++ tools/gui/egg-property-tree-view.h | 54 +++ tools/perf-overhead.c | 181 ++++++++++ 23 files changed, 2233 insertions(+), 2487 deletions(-) delete mode 100644 test/benchmark.c delete mode 100644 test/control.c delete mode 100644 test/control.glade delete mode 100644 test/egg-property-cell-renderer.c delete mode 100644 test/egg-property-cell-renderer.h delete mode 100644 test/egg-property-tree-view.c delete mode 100644 test/egg-property-tree-view.h delete mode 100644 test/grab-async.c delete mode 100644 test/grab.c delete mode 100644 test/perf-overhead.c delete mode 100644 test/test-all.c create mode 100644 tools/benchmark.c create mode 100644 tools/grab-async.c create mode 100644 tools/grab.c create mode 100644 tools/gui/control.c create mode 100644 tools/gui/control.glade create mode 100644 tools/gui/egg-property-cell-renderer.c create mode 100644 tools/gui/egg-property-cell-renderer.h create mode 100644 tools/gui/egg-property-tree-view.c create mode 100644 tools/gui/egg-property-tree-view.h create mode 100644 tools/perf-overhead.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0f46c32..b579d1b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,12 +5,10 @@ add_definitions("--std=c99 -Wall") # --- Find packages and libraries --------------------------------------------- find_package(PkgConfig) -pkg_check_modules(GTK2 gtk+-2.0>=2.22) -pkg_check_modules(GTHREAD2 gthread-2.0) pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/control.glade ${CMAKE_CURRENT_BINARY_DIR}) +set(libs uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) # --- Build targets ----------------------------------------------------------- include_directories( @@ -20,59 +18,10 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../src ) -if (HAVE_PYLON_CAMERA) - set(GENICAM_ROOT $ENV{PYLON_ROOT}/genicam) - # check for 32/64 bit - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PYLON_LIB_DIRS $ENV{PYLON_ROOT}/lib64 $ENV{PYLON_ROOT}/bin ${GENICAM_ROOT}/bin/Linux64_x64 - ${GENICAM_ROOT}/bin/Linux64_x64/GenApi/Generic) - else() - set(PYLON_LIB_DIRS $ENV{PYLON_ROOT}/lib64 $ENV{PYLON_ROOT}/bin ${GENICAM_ROOT}/bin/Linux32_i86 - ${GENICAM_ROOT}/bin/Linux32_i86/GenApi/Generic) - endif() - link_directories(${PYLON_LIB_DIRS} ${LIBPYLONCAM_LIBDIR}) -endif() - -add_executable(grab grab.c) -add_executable(grab-async grab-async.c) -add_executable(benchmark benchmark.c) -add_executable(perf perf-overhead.c) - -target_link_libraries(benchmark uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) -target_link_libraries(grab uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) -target_link_libraries(grab-async uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) -target_link_libraries(perf uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) - -if (GTK2_FOUND) - include_directories(${GTK2_INCLUDE_DIRS}) - - add_executable(control - control.c - egg-property-cell-renderer.c - egg-property-tree-view.c) - - target_link_libraries(control uca - ${GTK2_LIBRARIES} ${GTHREAD2_LIBRARIES}) - - install(TARGETS control - RUNTIME DESTINATION bin) - - install(FILES control.glade - DESTINATION share/libuca) -endif() - if (HAVE_MOCK_CAMERA) add_executable(test-mock test-mock.c) - - target_link_libraries(test-mock - uca - ${GLIB2_LIBRARIES} - ${GOBJECT2_LIBRARIES}) + target_link_libraries(test-mock ${libs}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gtester.xsl - ${CMAKE_CURRENT_BINARY_DIR}/gtester.xsl) + ${CMAKE_CURRENT_BINARY_DIR}/gtester.xsl) endif() - -#add_executable(test-all test-all.c) -#target_link_libraries(test-all uca -# ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) diff --git a/test/benchmark.c b/test/benchmark.c deleted file mode 100644 index ef99fd1..0000000 --- a/test/benchmark.c +++ /dev/null @@ -1,267 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include "uca-camera.h" -#include "uca-plugin-manager.h" - -typedef void (*GrabFrameFunc) (UcaCamera *camera, gpointer buffer, guint n_frames); - -static UcaCamera *camera = NULL; - -static void -sigint_handler(int signal) -{ - g_print ("Closing down libuca\n"); - uca_camera_stop_recording (camera, NULL); - g_object_unref (camera); - exit (signal); -} - -static void -print_usage (void) -{ - GList *types; - UcaPluginManager *manager; - - manager = uca_plugin_manager_new (); - g_print ("Usage: benchmark [ "); - types = uca_plugin_manager_get_available_cameras (manager); - - if (types == NULL) { - g_print ("] -- no camera plugin found\n"); - return; - } - - for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { - gchar *name = (gchar *) it->data; - if (g_list_next (it) == NULL) - g_print ("%s ]\n", name); - else - g_print ("%s, ", name); - } -} - -static void -log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user) -{ - gsize n_written; - GError *error = NULL; - GIOChannel *channel = user; - -#if GLIB_CHECK_VERSION(2, 26, 0) - GTimeZone *tz; - GDateTime *date_time; - gchar *new_message; - - tz = g_time_zone_new_local (); - date_time = g_date_time_new_now (tz); - - new_message = g_strdup_printf ("[%s] %s\n", - g_date_time_format (date_time, "%FT%H:%M:%S%z"), message); - - g_time_zone_unref (tz); - g_date_time_unref (date_time); - - g_io_channel_write_chars (channel, new_message, strlen (new_message), &n_written, &error); - g_assert_no_error (error); - g_free (new_message); -#else - g_io_channel_write_chars (channel, message, strlen (message), &n_written, &error); - g_assert_no_error (error); -#endif - - g_io_channel_flush (channel, &error); - g_assert_no_error (error); -} - -static void -grab_frames_sync (UcaCamera *camera, gpointer buffer, guint n_frames) -{ - GError *error = NULL; - - uca_camera_start_recording (camera, &error); - - for (guint i = 0; i < n_frames; i++) { - uca_camera_grab(camera, &buffer, &error); - - if (error != NULL) { - g_warning ("Error grabbing frame %02i/%i: `%s'", i, n_frames, error->message); - g_error_free (error); - error = NULL; - } - } - - uca_camera_stop_recording (camera, &error); -} - -static void -grab_callback (gpointer data, gpointer user_data) -{ - guint *n_acquired_frames = user_data; - *n_acquired_frames += 1; -} - -static void -grab_frames_async (UcaCamera *camera, gpointer buffer, guint n_frames) -{ - GError *error = NULL; - guint n_acquired_frames = 0; - - uca_camera_set_grab_func (camera, grab_callback, &n_acquired_frames); - uca_camera_start_recording (camera, &error); - - /* - * Behold! Spinlooping is probably a bad idea but nowadays single core - * machines are relatively rare. - */ - while (n_acquired_frames < n_frames) - ; - - uca_camera_stop_recording (camera, &error); - -} - -static void -benchmark_method (UcaCamera *camera, gpointer buffer, GrabFrameFunc func, guint n_runs, guint n_frames, guint n_bytes) -{ - GTimer *timer; - gdouble fps; - gdouble bandwidth; - gdouble total_time = 0.0; - GError *error = NULL; - - g_print ("%-10i%-10i", n_frames, n_runs); - timer = g_timer_new (); - g_assert_no_error (error); - - for (guint run = 0; run < n_runs; run++) { - g_message ("Start run %i of %i", run, n_runs); - g_timer_start (timer); - - func (camera, buffer, n_frames); - - g_timer_stop (timer); - total_time += g_timer_elapsed (timer, NULL); - } - - g_assert_no_error (error); - - fps = n_runs * n_frames / total_time; - bandwidth = n_bytes * fps / 1024 / 1024; - g_print ("%-16.2f%-16.2f\n", fps, bandwidth); - - g_timer_destroy (timer); -} - -static void -benchmark (UcaCamera *camera) -{ - const guint n_runs = 3; - const guint n_frames = 100; - - guint sensor_width; - guint sensor_height; - guint roi_width; - guint roi_height; - guint bits; - guint n_bytes_per_pixel; - guint n_bytes; - gdouble exposure = 0.00001; - gpointer buffer; - - g_object_set (G_OBJECT (camera), - "exposure-time", exposure, - NULL); - - g_object_get (G_OBJECT (camera), - "sensor-width", &sensor_width, - "sensor-height", &sensor_height, - "sensor-bitdepth", &bits, - "roi-width", &roi_width, - "roi-height", &roi_height, - "exposure-time", &exposure, - NULL); - - g_print ("# --- General information ---\n"); - g_print ("# Sensor size: %ix%i\n", sensor_width, sensor_height); - g_print ("# ROI size: %ix%i\n", roi_width, roi_height); - g_print ("# Exposure time: %fs\n", exposure); - - /* Synchronous frame acquisition */ - g_print ("# %-10s%-10s%-10s%-16s%-16s\n", "type", "n_frames", "n_runs", "frames/s", "MiB/s"); - g_print (" %-10s", "sync"); - - g_message ("Start synchronous benchmark"); - - n_bytes_per_pixel = bits > 8 ? 2 : 1; - n_bytes = roi_width * roi_height * n_bytes_per_pixel; - buffer = g_malloc0(n_bytes); - - benchmark_method (camera, buffer, grab_frames_sync, n_runs, n_frames, n_bytes); - - /* Asynchronous frame acquisition */ - g_object_set (G_OBJECT(camera), - "transfer-asynchronously", TRUE, - NULL); - - g_message ("Start asynchronous benchmark"); - g_print (" %-10s", "async"); - - benchmark_method (camera, buffer, grab_frames_async, n_runs, n_frames, n_bytes); - - g_free (buffer); -} - -int -main (int argc, char *argv[]) -{ - UcaPluginManager *manager; - GIOChannel *log_channel; - GError *error = NULL; - - (void) signal (SIGINT, sigint_handler); - g_type_init(); - - if (argc < 2) { - print_usage(); - return 1; - } - - log_channel = g_io_channel_new_file ("error.log", "a+", &error); - g_assert_no_error (error); - g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); - - manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); - - if (camera == NULL) { - g_error ("Initialization: %s", error->message); - return 1; - } - - benchmark (camera); - - g_object_unref (camera); - g_io_channel_shutdown (log_channel, TRUE, &error); - g_assert_no_error (error); - - return 0; -} diff --git a/test/control.c b/test/control.c deleted file mode 100644 index 5a7b702..0000000 --- a/test/control.c +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "uca-camera.h" -#include "uca-plugin-manager.h" -#include "egg-property-tree-view.h" - - -typedef struct { - gboolean running; - gboolean store; - - guchar *buffer, *pixels; - GdkPixbuf *pixbuf; - GtkWidget *image; - GtkTreeModel *property_model; - UcaCamera *camera; - - GtkStatusbar *statusbar; - guint statusbar_context_id; - - int timestamp; - int width; - int height; - int pixel_size; -} ThreadData; - -enum { - COLUMN_NAME = 0, - COLUMN_VALUE, - COLUMN_EDITABLE, - NUM_COLUMNS -}; - -static UcaPluginManager *plugin_manager; - -static void -convert_8bit_to_rgb (guchar *output, guchar *input, int width, int height) -{ - for (int i = 0, j = 0; i < width*height; i++) { - output[j++] = input[i]; - output[j++] = input[i]; - output[j++] = input[i]; - } -} - -static void -convert_16bit_to_rgb (guchar *output, guchar *input, int width, int height) -{ - guint16 *in = (guint16 *) input; - guint16 min = G_MAXUINT16, max = 0; - gfloat spread = 0.0f; - - for (int i = 0; i < width * height; i++) { - guint16 v = in[i]; - if (v < min) - min = v; - if (v > max) - max = v; - } - - spread = (gfloat) max - min; - - if (spread > 0.0f) { - for (int i = 0, j = 0; i < width*height; i++) { - guchar val = (guint8) (((in[i] - min) / spread) * 255.0f); - output[j++] = val; - output[j++] = val; - output[j++] = val; - } - } -} - -static void * -grab_thread (void *args) -{ - ThreadData *data = (ThreadData *) args; - gchar filename[FILENAME_MAX] = {0,}; - gint counter = 0; - - while (data->running) { - uca_camera_grab (data->camera, (gpointer) &data->buffer, NULL); - - if (data->store) { - snprintf (filename, FILENAME_MAX, "frame-%i-%08i.raw", data->timestamp, counter++); - FILE *fp = fopen (filename, "wb"); - fwrite (data->buffer, data->width*data->height, data->pixel_size, fp); - fclose (fp); - } - - /* FIXME: We should actually check if this is really a new frame and - * just do nothing if it is an already displayed one. */ - if (data->pixel_size == 1) - convert_8bit_to_rgb (data->pixels, data->buffer, data->width, data->height); - else if (data->pixel_size == 2) { - convert_16bit_to_rgb (data->pixels, data->buffer, data->width, data->height); - } - - gdk_threads_enter (); - gdk_flush (); - gtk_image_clear (GTK_IMAGE (data->image)); - gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); - gtk_widget_queue_draw_area (data->image, 0, 0, data->width, data->height); - gdk_threads_leave (); - } - return NULL; -} - -gboolean -on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - return FALSE; -} - -void -on_destroy (GtkWidget *widget, gpointer data) -{ - ThreadData *td = (ThreadData *) data; - td->running = FALSE; - g_object_unref (td->camera); - gtk_main_quit (); -} - -static void -on_toolbutton_run_clicked (GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - - if (data->running) - return; - - GError *error = NULL; - data->running = TRUE; - - uca_camera_start_recording (data->camera, &error); - - if (error != NULL) { - g_printerr ("Failed to start recording: %s\n", error->message); - return; - } - - if (!g_thread_create (grab_thread, data, FALSE, &error)) { - g_printerr ("Failed to create thread: %s\n", error->message); - return; - } -} - -static void -on_toolbutton_stop_clicked (GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - data->running = FALSE; - data->store = FALSE; - GError *error = NULL; - uca_camera_stop_recording (data->camera, &error); - - if (error != NULL) - g_printerr ("Failed to stop: %s\n", error->message); -} - -static void -on_toolbutton_record_clicked (GtkWidget *widget, gpointer args) -{ - ThreadData *data = (ThreadData *) args; - data->timestamp = (int) time (0); - data->store = TRUE; - GError *error = NULL; - - gtk_statusbar_push (data->statusbar, data->statusbar_context_id, "Recording..."); - - if (data->running != TRUE) { - data->running = TRUE; - uca_camera_start_recording (data->camera, &error); - - if (!g_thread_create (grab_thread, data, FALSE, &error)) - g_printerr ("Failed to create thread: %s\n", error->message); - } -} - -static void -create_main_window (GtkBuilder *builder, const gchar* camera_name) -{ - static ThreadData td; - - GError *error = NULL; - UcaCamera *camera = uca_plugin_manager_new_camera (plugin_manager, camera_name, &error); - - if ((camera == NULL) || (error != NULL)) { - g_error ("%s\n", error->message); - gtk_main_quit (); - } - - guint bits_per_sample; - g_object_get (camera, - "roi-width", &td.width, - "roi-height", &td.height, - "sensor-bitdepth", &bits_per_sample, - NULL); - - GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); - GtkWidget *image = GTK_WIDGET (gtk_builder_get_object (builder, "image")); - GtkWidget *property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); - GtkContainer *scrolled_property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "scrolledwindow2")); - - gtk_container_add (scrolled_property_window, property_tree_view); - gtk_widget_show_all (GTK_WIDGET (scrolled_property_window)); - - GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); - gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); - - td.pixel_size = bits_per_sample > 8 ? 2 : 1; - td.image = image; - td.pixbuf = pixbuf; - td.buffer = (guchar *) g_malloc (td.pixel_size * td.width * td.height); - td.pixels = gdk_pixbuf_get_pixels (pixbuf); - td.running = FALSE; - td.statusbar = GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar")); - td.statusbar_context_id = gtk_statusbar_get_context_id (td.statusbar, "Recording Information"); - td.store = FALSE; - td.camera = camera; - td.property_model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "camera-properties")); - - g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); - g_signal_connect (gtk_builder_get_object (builder, "toolbutton_run"), - "clicked", G_CALLBACK (on_toolbutton_run_clicked), &td); - g_signal_connect (gtk_builder_get_object (builder, "toolbutton_stop"), - "clicked", G_CALLBACK (on_toolbutton_stop_clicked), &td); - g_signal_connect (gtk_builder_get_object (builder, "toolbutton_record"), - "clicked", G_CALLBACK (on_toolbutton_record_clicked), &td); - - gtk_widget_show (image); - gtk_widget_show (window); -} - -static void -on_button_proceed_clicked (GtkWidget *widget, gpointer data) -{ - GtkBuilder *builder = GTK_BUILDER (data); - GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); - GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); - GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); - - GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); - GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL); - GtkTreeIter iter; - - gtk_widget_destroy (choice_window); - gboolean valid = gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), &iter, selected_rows->data); - - if (valid) { - gchar *data; - gtk_tree_model_get (GTK_TREE_MODEL (list_store), &iter, 0, &data, -1); - create_main_window (builder, data); - g_free (data); - } - - g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL); - g_list_free (selected_rows); -} - -static void -on_treeview_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data) -{ - if (event->keyval == GDK_KEY_Return) - gtk_widget_grab_focus (GTK_WIDGET (data)); -} - -static void -create_choice_window (GtkBuilder *builder) -{ - GList *camera_types = uca_plugin_manager_get_available_cameras (plugin_manager); - - GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); - GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); - GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); - GtkButton *proceed_button = GTK_BUTTON (gtk_builder_get_object (builder, "button-proceed")); - GtkTreeIter iter; - - for (GList *it = g_list_first (camera_types); it != NULL; it = g_list_next (it)) { - gtk_list_store_append (list_store, &iter); - gtk_list_store_set (list_store, &iter, 0, g_strdup ((gchar *) it->data), -1); - } - - gboolean valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter); - - if (valid) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); - gtk_tree_selection_unselect_all (selection); - gtk_tree_selection_select_path (selection, gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter)); - } - - g_signal_connect (proceed_button, "clicked", G_CALLBACK (on_button_proceed_clicked), builder); - g_signal_connect (treeview, "key-press-event", G_CALLBACK (on_treeview_keypress), proceed_button); - gtk_widget_show_all (GTK_WIDGET (choice_window)); - - g_list_foreach (camera_types, (GFunc) g_free, NULL); - g_list_free (camera_types); -} - -int -main (int argc, char *argv[]) -{ - GError *error = NULL; - - g_thread_init (NULL); - gdk_threads_init (); - gtk_init (&argc, &argv); - - GtkBuilder *builder = gtk_builder_new (); - - if (!gtk_builder_add_from_file (builder, CONTROL_GLADE_PATH, &error)) { - g_print ("Error: %s\n", error->message); - return 1; - } - - plugin_manager = uca_plugin_manager_new (); - create_choice_window (builder); - gtk_builder_connect_signals (builder, NULL); - - gdk_threads_enter (); - gtk_main (); - gdk_threads_leave (); - - g_object_unref (plugin_manager); - return 0; -} diff --git a/test/control.glade b/test/control.glade deleted file mode 100644 index d7ba2fc..0000000 --- a/test/control.glade +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Camera Control - 1024 - 768 - - - - True - - - True - - - True - _File - True - - - True - - - gtk-new - True - True - True - - - - - gtk-open - True - True - True - - - - - gtk-save - True - True - True - - - - - gtk-save-as - True - True - True - - - - - True - - - - - gtk-quit - True - True - True - - - - - - - - - - True - _Help - True - - - True - - - gtk-about - True - True - True - - - - - - - - - False - 0 - - - - - True - - - True - Run - True - gtk-media-play - - - False - True - - - - - True - Record - True - gtk-media-record - - - False - True - - - - - True - Stop - True - gtk-media-stop - - - False - True - - - - - False - 1 - - - - - True - True - 6 - - - 300 - True - True - automatic - automatic - - - True - queue - - - True - gtk-missing-image - - - - - - - True - False - - - - - True - True - automatic - automatic - - - - - - True - True - - - - - 2 - - - - - True - 2 - - - False - 3 - - - - - - - 65535 - 1 - 65535 - 1 - 10 - - - 6 - - - True - 2 - - - True - True - camera-types - - - Choose camera - - - - 0 - - - - - - - 0 - - - - - True - 6 - end - - - gtk-quit - True - True - True - True - - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - - - False - False - 1 - - - - - False - 6 - 1 - - - - - - diff --git a/test/egg-property-cell-renderer.c b/test/egg-property-cell-renderer.c deleted file mode 100644 index 9df5cc3..0000000 --- a/test/egg-property-cell-renderer.c +++ /dev/null @@ -1,594 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include "egg-property-cell-renderer.h" - -G_DEFINE_TYPE (EggPropertyCellRenderer, egg_property_cell_renderer, GTK_TYPE_CELL_RENDERER) - -#define EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererPrivate)) - - -struct _EggPropertyCellRendererPrivate -{ - GObject *object; - GtkListStore *list_store; - GtkCellRenderer *renderer; - GtkCellRenderer *text_renderer; - GtkCellRenderer *spin_renderer; - GtkCellRenderer *toggle_renderer; - GtkCellRenderer *combo_renderer; - GHashTable *combo_models; -}; - -enum -{ - PROP_0, - PROP_PROP_NAME, - N_PROPERTIES -}; - -enum -{ - COMBO_COLUMN_VALUE_NAME, - COMBO_COLUMN_VALUE, - N_COMBO_COLUMNS -}; - -static GParamSpec *egg_property_cell_renderer_properties[N_PROPERTIES] = { NULL, }; - -GtkCellRenderer * -egg_property_cell_renderer_new (GObject *object, - GtkListStore *list_store) -{ - EggPropertyCellRenderer *renderer; - - renderer = EGG_PROPERTY_CELL_RENDERER (g_object_new (EGG_TYPE_PROPERTY_CELL_RENDERER, NULL)); - renderer->priv->object = object; - renderer->priv->list_store = list_store; - return GTK_CELL_RENDERER (renderer); -} - -static GParamSpec * -get_pspec_from_object (GObject *object, const gchar *prop_name) -{ - GObjectClass *oclass = G_OBJECT_GET_CLASS (object); - return g_object_class_find_property (oclass, prop_name); -} - -static void -get_string_double_repr (GObject *object, const gchar *prop_name, gchar **text, gdouble *number) -{ - GParamSpec *pspec; - GValue from = { 0 }; - GValue to_string = { 0 }; - GValue to_double = { 0 }; - - pspec = get_pspec_from_object (object, prop_name); - g_value_init (&from, pspec->value_type); - g_value_init (&to_string, G_TYPE_STRING); - g_value_init (&to_double, G_TYPE_DOUBLE); - g_object_get_property (object, prop_name, &from); - - if (g_value_transform (&from, &to_string)) - *text = g_strdup (g_value_get_string (&to_string)); - else - g_warning ("Could not convert from %s gchar*\n", g_type_name (pspec->value_type)); - - if (g_value_transform (&from, &to_double)) - *number = g_value_get_double (&to_double); - else - g_warning ("Could not convert from %s to gdouble\n", g_type_name (pspec->value_type)); -} - -static void -clear_adjustment (GObject *object) -{ - GtkAdjustment *adjustment; - - g_object_get (object, - "adjustment", &adjustment, - NULL); - - if (adjustment) - g_object_unref (adjustment); - - g_object_set (object, - "adjustment", NULL, - NULL); -} - -static void -egg_property_cell_renderer_set_renderer (EggPropertyCellRenderer *renderer, - const gchar *prop_name) -{ - EggPropertyCellRendererPrivate *priv; - GParamSpec *pspec; - gchar *text = NULL; - gdouble number; - - priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); - pspec = get_pspec_from_object (priv->object, prop_name); - - /* - * Set this renderers mode, so that any actions can be forwarded to our - * child renderers. - */ - switch (pspec->value_type) { - /* toggle renderers */ - case G_TYPE_BOOLEAN: - priv->renderer = priv->toggle_renderer; - g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); - break; - - /* spin renderers */ - case G_TYPE_FLOAT: - case G_TYPE_DOUBLE: - priv->renderer = priv->spin_renderer; - g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); - g_object_set (priv->renderer, "digits", 5, NULL); - break; - - case G_TYPE_INT: - case G_TYPE_UINT: - case G_TYPE_LONG: - case G_TYPE_ULONG: - case G_TYPE_INT64: - case G_TYPE_UINT64: - priv->renderer = priv->spin_renderer; - g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); - g_object_set (priv->renderer, "digits", 0, NULL); - break; - - /* text renderers */ - case G_TYPE_POINTER: - case G_TYPE_STRING: - priv->renderer = priv->text_renderer; - g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); - break; - - /* combo renderers */ - default: - if (G_TYPE_IS_ENUM (pspec->value_type)) { - priv->renderer = priv->combo_renderer; - g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); - } - break; - } - - /* - * Set the content from the objects property. - */ - switch (pspec->value_type) { - case G_TYPE_BOOLEAN: - { - gboolean val; - - g_object_get (priv->object, prop_name, &val, NULL); - g_object_set (priv->renderer, - "active", val, - "activatable", pspec->flags & G_PARAM_WRITABLE ? TRUE : FALSE, - NULL); - break; - } - - case G_TYPE_INT: - case G_TYPE_UINT: - case G_TYPE_LONG: - case G_TYPE_ULONG: - case G_TYPE_INT64: - case G_TYPE_UINT64: - case G_TYPE_FLOAT: - case G_TYPE_DOUBLE: - get_string_double_repr (priv->object, prop_name, &text, &number); - break; - - case G_TYPE_STRING: - g_object_get (priv->object, prop_name, &text, NULL); - break; - - case G_TYPE_POINTER: - { - gpointer val; - - g_object_get (priv->object, prop_name, &val, NULL); - text = g_strdup_printf ("0x%x", GPOINTER_TO_INT (val)); - } - break; - - default: - if (G_TYPE_IS_ENUM (pspec->value_type)) { - GParamSpecEnum *pspec_enum; - GEnumClass *enum_class; - GtkTreeModel *combo_model; - GtkTreeIter iter; - gint value; - - g_object_get (priv->object, prop_name, &value, NULL); - - pspec_enum = G_PARAM_SPEC_ENUM (pspec); - enum_class = pspec_enum->enum_class; - combo_model = g_hash_table_lookup (priv->combo_models, prop_name); - - if (combo_model == NULL) { - combo_model = GTK_TREE_MODEL (gtk_list_store_new (N_COMBO_COLUMNS, G_TYPE_STRING, G_TYPE_INT)); - g_hash_table_insert (priv->combo_models, g_strdup (prop_name), combo_model); - - for (guint i = 0; i < enum_class->n_values; i++) { - gtk_list_store_append (GTK_LIST_STORE (combo_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (combo_model), &iter, - COMBO_COLUMN_VALUE_NAME, enum_class->values[i].value_name, - COMBO_COLUMN_VALUE, enum_class->values[i].value, - -1); - } - } - - - for (guint i = 0; i < enum_class->n_values; i++) { - if (enum_class->values[i].value == value) - text = g_strdup (enum_class->values[i].value_name); - } - - g_object_set (priv->renderer, - "model", combo_model, - "text-column", 0, - NULL); - } - break; - } - - if (pspec->flags & G_PARAM_WRITABLE) { - if (GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) - g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); - else - g_object_set (priv->renderer, "foreground", "#000000", NULL); - - if (GTK_IS_CELL_RENDERER_TEXT (priv->renderer)) { - g_object_set (priv->renderer, - "editable", TRUE, - "mode", GTK_CELL_RENDERER_MODE_EDITABLE, - NULL); - } - - if (GTK_IS_CELL_RENDERER_SPIN (priv->renderer)) { - GtkObject *adjustment = NULL; - -#define gtk_typed_adjustment_new(type, pspec, val, step_inc, page_inc) \ - gtk_adjustment_new (val, ((type *) pspec)->minimum, ((type *) pspec)->maximum, step_inc, page_inc, 0) - - switch (pspec->value_type) { - case G_TYPE_INT: - adjustment = gtk_typed_adjustment_new (GParamSpecInt, pspec, number, 1, 10); - break; - case G_TYPE_UINT: - adjustment = gtk_typed_adjustment_new (GParamSpecUInt, pspec, number, 1, 10); - break; - case G_TYPE_LONG: - adjustment = gtk_typed_adjustment_new (GParamSpecLong, pspec, number, 1, 10); - break; - case G_TYPE_ULONG: - adjustment = gtk_typed_adjustment_new (GParamSpecULong, pspec, number, 1, 10); - break; - case G_TYPE_INT64: - adjustment = gtk_typed_adjustment_new (GParamSpecInt64, pspec, number, 1, 10); - break; - case G_TYPE_UINT64: - adjustment = gtk_typed_adjustment_new (GParamSpecUInt64, pspec, number, 1, 10); - break; - case G_TYPE_FLOAT: - adjustment = gtk_typed_adjustment_new (GParamSpecFloat, pspec, number, 0.05, 10); - break; - case G_TYPE_DOUBLE: - adjustment = gtk_typed_adjustment_new (GParamSpecDouble, pspec, number, 0.05, 10); - break; - } - - clear_adjustment (G_OBJECT (priv->renderer)); - g_object_set (priv->renderer, "adjustment", adjustment, NULL); - } - } - else { - g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); - - if (!GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) - g_object_set (priv->renderer, "foreground", "#aaaaaa", NULL); - } - - if (text != NULL) { - g_object_set (priv->renderer, "text", text, NULL); - g_free (text); - } -} - -static gchar * -get_prop_name_from_tree_model (GtkTreeModel *model, const gchar *path) -{ - GtkTreeIter iter; - gchar *prop_name = NULL; - - /* TODO: don't assume column 0 to contain the prop name */ - if (gtk_tree_model_get_iter_from_string (model, &iter, path)) - gtk_tree_model_get (model, &iter, 0, &prop_name, -1); - - return prop_name; -} - -static void -egg_property_cell_renderer_toggle_cb (GtkCellRendererToggle *renderer, - gchar *path, - gpointer user_data) -{ - EggPropertyCellRendererPrivate *priv; - gchar *prop_name; - - priv = (EggPropertyCellRendererPrivate *) user_data; - prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); - - if (prop_name != NULL) { - gboolean activated; - - g_object_get (priv->object, prop_name, &activated, NULL); - g_object_set (priv->object, prop_name, !activated, NULL); - g_free (prop_name); - } -} - -static void -egg_property_cell_renderer_text_edited_cb (GtkCellRendererText *renderer, - gchar *path, - gchar *new_text, - gpointer user_data) -{ - EggPropertyCellRendererPrivate *priv; - gchar *prop_name; - - priv = (EggPropertyCellRendererPrivate *) user_data; - prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); - - if (prop_name != NULL) { - g_object_set (priv->object, prop_name, new_text, NULL); - g_free (prop_name); - } -} - -static void -egg_property_cell_renderer_spin_edited_cb (GtkCellRendererText *renderer, - gchar *path, - gchar *new_text, - gpointer user_data) -{ - EggPropertyCellRendererPrivate *priv; - gchar *prop_name; - - priv = (EggPropertyCellRendererPrivate *) user_data; - prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); - - if (prop_name != NULL) { - GParamSpec *pspec; - GValue from = { 0 }; - GValue to = { 0 }; - - pspec = get_pspec_from_object (priv->object, prop_name); - - g_value_init (&from, G_TYPE_DOUBLE); - g_value_init (&to, pspec->value_type); - g_value_set_double (&from, strtod (new_text, NULL)); - - if (g_value_transform (&from, &to)) - g_object_set_property (priv->object, prop_name, &to); - else - g_warning ("Could not transform %s to %s\n", - g_value_get_string (&from), g_type_name (pspec->value_type)); - - g_free (prop_name); - } -} - -static void -egg_property_cell_renderer_changed_cb (GtkCellRendererCombo *combo, - gchar *path, - GtkTreeIter *new_iter, - gpointer user_data) -{ - EggPropertyCellRendererPrivate *priv; - gchar *prop_name; - - priv = (EggPropertyCellRendererPrivate *) user_data; - prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); - - if (prop_name != NULL) { - GtkTreeModel *combo_model; - gchar *value_name; - gint value; - - combo_model = g_hash_table_lookup (priv->combo_models, prop_name); - - gtk_tree_model_get (combo_model, new_iter, - COMBO_COLUMN_VALUE_NAME, &value_name, - COMBO_COLUMN_VALUE, &value, - -1); - - g_object_set (priv->object, prop_name, value, NULL); - g_free (value_name); - g_free (prop_name); - } -} - -static void -egg_property_cell_renderer_get_size (GtkCellRenderer *cell, - GtkWidget *widget, - GdkRectangle *cell_area, - gint *x_offset, - gint *y_offset, - gint *width, - gint *height) -{ - - EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); - gtk_cell_renderer_get_size (priv->renderer, widget, cell_area, x_offset, y_offset, width, height); -} - -static void -egg_property_cell_renderer_render (GtkCellRenderer *cell, - GdkDrawable *window, - GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - GtkCellRendererState flags) -{ - EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); - gtk_cell_renderer_render (priv->renderer, window, widget, background_area, cell_area, expose_area, flags); -} - -static gboolean -egg_property_cell_renderer_activate (GtkCellRenderer *cell, - GdkEvent *event, - GtkWidget *widget, - const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GtkCellRendererState flags) -{ - EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); - return gtk_cell_renderer_activate (priv->renderer, event, widget, path, background_area, cell_area, flags); -} - -static GtkCellEditable * -egg_property_cell_renderer_start_editing (GtkCellRenderer *cell, - GdkEvent *event, - GtkWidget *widget, - const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GtkCellRendererState flags) -{ - EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); - return gtk_cell_renderer_start_editing (priv->renderer, event, widget, path, background_area, cell_area, flags); -} - -static void -egg_property_cell_renderer_dispose (GObject *object) -{ - EggPropertyCellRenderer *renderer = EGG_PROPERTY_CELL_RENDERER (object); - g_hash_table_destroy (renderer->priv->combo_models); -} - -static void -egg_property_cell_renderer_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); - EggPropertyCellRenderer *renderer = EGG_PROPERTY_CELL_RENDERER (object); - - switch (property_id) { - case PROP_PROP_NAME: - egg_property_cell_renderer_set_renderer (renderer, g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - return; - } -} - -static void -egg_property_cell_renderer_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); - - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - return; - } -} - -static void -egg_property_cell_renderer_class_init (EggPropertyCellRendererClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkCellRendererClass *cellrenderer_class = GTK_CELL_RENDERER_CLASS (klass); - - gobject_class->set_property = egg_property_cell_renderer_set_property; - gobject_class->get_property = egg_property_cell_renderer_get_property; - gobject_class->dispose = egg_property_cell_renderer_dispose; - - cellrenderer_class->render = egg_property_cell_renderer_render; - cellrenderer_class->get_size = egg_property_cell_renderer_get_size; - cellrenderer_class->activate = egg_property_cell_renderer_activate; - cellrenderer_class->start_editing = egg_property_cell_renderer_start_editing; - - egg_property_cell_renderer_properties[PROP_PROP_NAME] = - g_param_spec_string("prop-name", - "Property name", "Property name", "", - G_PARAM_READWRITE); - - g_object_class_install_property(gobject_class, PROP_PROP_NAME, egg_property_cell_renderer_properties[PROP_PROP_NAME]); - - g_type_class_add_private (klass, sizeof (EggPropertyCellRendererPrivate)); -} - -static void -egg_property_cell_renderer_init (EggPropertyCellRenderer *renderer) -{ - EggPropertyCellRendererPrivate *priv; - - renderer->priv = priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); - - priv->text_renderer = gtk_cell_renderer_text_new (); - priv->spin_renderer = gtk_cell_renderer_spin_new (); - priv->toggle_renderer = gtk_cell_renderer_toggle_new (); - priv->combo_renderer = gtk_cell_renderer_combo_new (); - priv->renderer = priv->text_renderer; - priv->combo_models = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - - g_object_set (priv->text_renderer, - "editable", TRUE, - NULL); - - g_object_set (priv->spin_renderer, - "editable", TRUE, - NULL); - - g_object_set (priv->toggle_renderer, - "xalign", 0.0f, - "activatable", TRUE, - "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, - NULL); - - g_object_set (priv->combo_renderer, - "has-entry", FALSE, - NULL); - - g_signal_connect (priv->spin_renderer, "edited", - G_CALLBACK (egg_property_cell_renderer_spin_edited_cb), priv); - - g_signal_connect (priv->text_renderer, "edited", - G_CALLBACK (egg_property_cell_renderer_text_edited_cb), NULL); - - g_signal_connect (priv->toggle_renderer, "toggled", - G_CALLBACK (egg_property_cell_renderer_toggle_cb), priv); - - g_signal_connect (priv->combo_renderer, "changed", - G_CALLBACK (egg_property_cell_renderer_changed_cb), priv); -} diff --git a/test/egg-property-cell-renderer.h b/test/egg-property-cell-renderer.h deleted file mode 100644 index d4dbe02..0000000 --- a/test/egg-property-cell-renderer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef EGG_PROPERTY_CELL_RENDERER_H -#define EGG_PROPERTY_CELL_RENDERER_H - -#include - -G_BEGIN_DECLS - -#define EGG_TYPE_PROPERTY_CELL_RENDERER (egg_property_cell_renderer_get_type()) -#define EGG_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRenderer)) -#define EGG_IS_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER)) -#define EGG_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) -#define EGG_IS_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_CELL_RENDERER)) -#define EGG_PROPERTY_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) - -typedef struct _EggPropertyCellRenderer EggPropertyCellRenderer; -typedef struct _EggPropertyCellRendererClass EggPropertyCellRendererClass; -typedef struct _EggPropertyCellRendererPrivate EggPropertyCellRendererPrivate; - -struct _EggPropertyCellRenderer -{ - GtkCellRenderer parent_instance; - - /*< private >*/ - EggPropertyCellRendererPrivate *priv; -}; - -struct _EggPropertyCellRendererClass -{ - GtkCellRendererClass parent_class; -}; - -GType egg_property_cell_renderer_get_type (void); -GtkCellRenderer* egg_property_cell_renderer_new (GObject *object, - GtkListStore *list_store); - -G_END_DECLS - -#endif diff --git a/test/egg-property-tree-view.c b/test/egg-property-tree-view.c deleted file mode 100644 index f4ed2fb..0000000 --- a/test/egg-property-tree-view.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - - -#include "egg-property-tree-view.h" -#include "egg-property-cell-renderer.h" - -G_DEFINE_TYPE (EggPropertyTreeView, egg_property_tree_view, GTK_TYPE_TREE_VIEW) - -#define EGG_PROPERTY_TREE_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewPrivate)) - -struct _EggPropertyTreeViewPrivate -{ - GtkListStore *list_store; -}; - -enum -{ - COLUMN_PROP_NAME, - COLUMN_PROP_ROW, - COLUMN_PROP_ADJUSTMENT, - N_COLUMNS -}; - -static void -egg_property_tree_view_populate_model_with_properties (GtkListStore *model, GObject *object) -{ - GParamSpec **pspecs; - GObjectClass *oclass; - guint n_properties; - GtkTreeIter iter; - - oclass = G_OBJECT_GET_CLASS (object); - pspecs = g_object_class_list_properties (oclass, &n_properties); - - for (guint i = 0; i < n_properties; i++) { - if (pspecs[i]->flags & G_PARAM_READABLE) { - GtkObject *adjustment; - - adjustment = gtk_adjustment_new (5, 0, 1000, 1, 10, 0); - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - COLUMN_PROP_NAME, pspecs[i]->name, - COLUMN_PROP_ROW, FALSE, - COLUMN_PROP_ADJUSTMENT, adjustment, - -1); - } - } - - g_free (pspecs); -} - -GtkWidget * -egg_property_tree_view_new (GObject *object) -{ - EggPropertyTreeView *property_tree_view; - GtkTreeView *tree_view; - GtkTreeViewColumn *prop_column, *value_column; - GtkCellRenderer *prop_renderer, *value_renderer; - GtkListStore *list_store; - - property_tree_view = EGG_PROPERTY_TREE_VIEW (g_object_new (EGG_TYPE_PROPERTY_TREE_VIEW, NULL)); - list_store = property_tree_view->priv->list_store; - tree_view = GTK_TREE_VIEW (property_tree_view); - - egg_property_tree_view_populate_model_with_properties (list_store, object); - gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store)); - - prop_renderer = gtk_cell_renderer_text_new (); - prop_column = gtk_tree_view_column_new_with_attributes ("Property", prop_renderer, - "text", COLUMN_PROP_NAME, - NULL); - - value_renderer = egg_property_cell_renderer_new (object, list_store); - value_column = gtk_tree_view_column_new_with_attributes ("Value", value_renderer, - "prop-name", COLUMN_PROP_NAME, - NULL); - - gtk_tree_view_append_column (tree_view, prop_column); - gtk_tree_view_append_column (tree_view, value_column); - - return GTK_WIDGET (tree_view); -} - -static void -egg_property_tree_view_class_init (EggPropertyTreeViewClass *klass) -{ - g_type_class_add_private (klass, sizeof (EggPropertyTreeViewPrivate)); -} - -static void -egg_property_tree_view_init (EggPropertyTreeView *tree_view) -{ - EggPropertyTreeViewPrivate *priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); - - tree_view->priv = priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); - priv->list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, GTK_TYPE_ADJUSTMENT); -} - diff --git a/test/egg-property-tree-view.h b/test/egg-property-tree-view.h deleted file mode 100644 index e8fd0fe..0000000 --- a/test/egg-property-tree-view.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#ifndef EGG_PROPERTY_TREE_VIEW_H -#define EGG_PROPERTY_TREE_VIEW_H - -#include - -G_BEGIN_DECLS - -#define EGG_TYPE_PROPERTY_TREE_VIEW (egg_property_tree_view_get_type()) -#define EGG_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeView)) -#define EGG_IS_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_TREE_VIEW)) -#define EGG_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) -#define EGG_IS_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_TREE_VIEW)) -#define EGG_PROPERTY_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) - -typedef struct _EggPropertyTreeView EggPropertyTreeView; -typedef struct _EggPropertyTreeViewClass EggPropertyTreeViewClass; -typedef struct _EggPropertyTreeViewPrivate EggPropertyTreeViewPrivate; - -struct _EggPropertyTreeView -{ - GtkTreeView parent_instance; - - /*< private >*/ - EggPropertyTreeViewPrivate *priv; -}; - -struct _EggPropertyTreeViewClass -{ - GtkTreeViewClass parent_class; -}; - -GType egg_property_tree_view_get_type (void) G_GNUC_CONST; -GtkWidget* egg_property_tree_view_new (GObject *object); - -G_END_DECLS - -#endif diff --git a/test/grab-async.c b/test/grab-async.c deleted file mode 100644 index 6132829..0000000 --- a/test/grab-async.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include "uca-plugin-manager.h" -#include "uca-camera.h" - -static UcaCamera *camera = NULL; - -typedef struct { - guint roi_width; - guint roi_height; - guint counter; -} CallbackData; - -static void -sigint_handler(int signal) -{ - printf("Closing down libuca\n"); - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - exit(signal); -} - -static void -grab_callback(gpointer data, gpointer user_data) -{ - CallbackData *cbd = (CallbackData *) user_data; - gchar *filename = g_strdup_printf("frame-%04i.raw", cbd->counter++); - FILE *fp = fopen(filename, "wb"); - - fwrite(data, sizeof(guint16), cbd->roi_width * cbd->roi_height, fp); - g_print("."); - fclose(fp); - g_free(filename); -} - -static void -print_usage (void) -{ - GList *types; - UcaPluginManager *manager; - - manager = uca_plugin_manager_new (); - g_print ("Usage: benchmark [ "); - types = uca_plugin_manager_get_available_cameras (manager); - - if (types == NULL) { - g_print ("] -- no camera plugin found\n"); - return; - } - - for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { - gchar *name = (gchar *) it->data; - if (g_list_next (it) == NULL) - g_print ("%s ]\n", name); - else - g_print ("%s, ", name); - } -} - -int -main(int argc, char *argv[]) -{ - CallbackData cbd; - guint sensor_width, sensor_height; - gchar *name; - UcaPluginManager *manager; - GError *error = NULL; - (void) signal(SIGINT, sigint_handler); - - g_type_init(); - - if (argc < 2) { - print_usage(); - return 1; - } - - manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); - - if (camera == NULL) { - g_print("Error during initialization: %s\n", error->message); - return 1; - } - - g_object_get(G_OBJECT(camera), - "name", &name, - "sensor-width", &sensor_width, - "sensor-height", &sensor_height, - NULL); - - g_object_set(G_OBJECT(camera), - "roi-x0", 0, - "roi-y0", 0, - "roi-width", sensor_width, - "roi-height", sensor_height, - "transfer-asynchronously", TRUE, - NULL); - - g_object_get(G_OBJECT(camera), - "roi-width", &cbd.roi_width, - "roi-height", &cbd.roi_height, - NULL); - - g_print("Camera: %s\n", name); - g_free(name); - - g_print("Start asynchronous recording\n"); - cbd.counter = 0; - uca_camera_set_grab_func(camera, grab_callback, &cbd); - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - g_usleep(2 * G_USEC_PER_SEC); - - g_print(" done\n"); - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - - return error != NULL ? 1 : 0; -} diff --git a/test/grab.c b/test/grab.c deleted file mode 100644 index e507d69..0000000 --- a/test/grab.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include "uca-plugin-manager.h" -#include "uca-camera.h" - -static UcaCamera *camera = NULL; - -static void sigint_handler(int signal) -{ - printf("Closing down libuca\n"); - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - exit(signal); -} - -static void -print_usage (void) -{ - GList *types; - UcaPluginManager *manager; - - manager = uca_plugin_manager_new (); - g_print ("Usage: benchmark [ "); - types = uca_plugin_manager_get_available_cameras (manager); - - if (types == NULL) { - g_print ("] -- no camera plugin found\n"); - return; - } - - for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { - gchar *name = (gchar *) it->data; - if (g_list_next (it) == NULL) - g_print ("%s ]\n", name); - else - g_print ("%s, ", name); - } -} - -int main(int argc, char *argv[]) -{ - UcaPluginManager *manager; - GError *error = NULL; - (void) signal(SIGINT, sigint_handler); - - guint sensor_width, sensor_height; - guint roi_width, roi_height, roi_x, roi_y, roi_width_multiplier, roi_height_multiplier; - guint bits; - gchar *name; - - g_type_init(); - - if (argc < 2) { - print_usage(); - return 1; - } - - manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); - - if (camera == NULL) { - g_print("Error during initialization: %s\n", error->message); - return 1; - } - - g_object_get(G_OBJECT(camera), - "sensor-width", &sensor_width, - "sensor-height", &sensor_height, - "name", &name, - NULL); - - g_object_set(G_OBJECT(camera), - "exposure-time", 0.001, - "roi-x0", 0, - "roi-y0", 0, - "roi-width", 1000, - "roi-height", sensor_height, - NULL); - - g_object_get(G_OBJECT(camera), - "roi-width", &roi_width, - "roi-height", &roi_height, - "roi-width-multiplier", &roi_width_multiplier, - "roi-height-multiplier", &roi_height_multiplier, - "roi-x0", &roi_x, - "roi-y0", &roi_y, - "sensor-bitdepth", &bits, - NULL); - - g_print("Camera: %s\n", name); - g_free(name); - - g_print("Sensor: %ix%i px\n", sensor_width, sensor_height); - g_print("ROI: %ix%i @ (%i, %i), steps: %i, %i\n", - roi_width, roi_height, roi_x, roi_y, roi_width_multiplier, roi_height_multiplier); - - const int pixel_size = bits == 8 ? 1 : 2; - gpointer buffer = g_malloc0(roi_width * roi_height * pixel_size); - gchar filename[FILENAME_MAX]; - GTimer *timer = g_timer_new(); - - for (int i = 0; i < 1; i++) { - gint counter = 0; - g_print("Start recording\n"); - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - while (counter < 5) { - g_print(" grab frame ... "); - g_timer_start(timer); - uca_camera_grab(camera, &buffer, &error); - - if (error != NULL) { - g_print("\nError: %s\n", error->message); - goto cleanup; - } - - g_timer_stop(timer); - g_print("done (took %3.5fs)\n", g_timer_elapsed(timer, NULL)); - - snprintf(filename, FILENAME_MAX, "frame-%08i.raw", counter++); - FILE *fp = fopen(filename, "wb"); - fwrite(buffer, roi_width * roi_height, pixel_size, fp); - fclose(fp); - g_usleep(2 * G_USEC_PER_SEC); - } - - g_print("Stop recording\n"); - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - } - - g_timer_destroy(timer); - -cleanup: - uca_camera_stop_recording(camera, NULL); - g_object_unref(camera); - g_free(buffer); - - return error != NULL ? 1 : 0; -} diff --git a/test/perf-overhead.c b/test/perf-overhead.c deleted file mode 100644 index f8bdcbd..0000000 --- a/test/perf-overhead.c +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - -#include -#include -#include -#include -#include -#include "uca-plugin-manager.h" -#include "uca-camera.h" - -#define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ - __FILE__, __LINE__);} - -typedef struct { - guint counter; - gsize size; - gpointer destination; -} thread_data; - -static UcaCamera *camera = NULL; - -static void -sigint_handler (int signal) -{ - printf ("Closing down libuca\n"); - uca_camera_stop_recording (camera, NULL); - g_object_unref (camera); - exit (signal); -} - -static void -print_usage (void) -{ - GList *types; - UcaPluginManager *manager; - - manager = uca_plugin_manager_new (); - g_print ("Usage: benchmark [ "); - types = uca_plugin_manager_get_available_cameras (manager); - - if (types == NULL) { - g_print ("] -- no camera plugin found\n"); - return; - } - - for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { - gchar *name = (gchar *) it->data; - if (g_list_next (it) == NULL) - g_print ("%s ]\n", name); - else - g_print ("%s, ", name); - } -} - -static void -test_synchronous_operation (UcaCamera *camera) -{ - GError *error = NULL; - guint width, height, bits; - g_object_get (G_OBJECT (camera), - "sensor-width", &width, - "sensor-height", &height, - "sensor-bitdepth", &bits, - NULL); - - const int pixel_size = bits == 8 ? 1 : 2; - const gsize size = width * height * pixel_size; - const guint n_trials = 10000; - gpointer buffer = g_malloc0(size); - - uca_camera_start_recording (camera, &error); - GTimer *timer = g_timer_new (); - - for (guint n = 0; n < n_trials; n++) - uca_camera_grab (camera, &buffer, &error); - - gdouble total_time = g_timer_elapsed (timer, NULL); - g_timer_stop (timer); - - g_print ("Synchronous data transfer\n"); - g_print (" Bandwidth: %3.2f MB/s\n", size * n_trials / 1024. / 1024. / total_time); - g_print (" Throughput: %3.2f frames/s\n", n_trials / total_time); - - uca_camera_stop_recording (camera, &error); - g_free (buffer); - g_timer_destroy (timer); -} - -static void -grab_func (gpointer data, gpointer user_data) -{ - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - - thread_data *d = (thread_data *) user_data; - g_memmove (d->destination, data, d->size); - g_static_mutex_lock (&mutex); - d->counter++; - g_static_mutex_unlock (&mutex); -} - -static void -test_asynchronous_operation (UcaCamera *camera) -{ - GError *error = NULL; - guint width, height, bits; - - g_object_get (G_OBJECT (camera), - "sensor-width", &width, - "sensor-height", &height, - "sensor-bitdepth", &bits, - NULL); - - const guint pixel_size = bits == 8 ? 1 : 2; - - thread_data d = { - .counter = 0, - .size = width * height * pixel_size, - .destination = g_malloc0(width * height * pixel_size) - }; - - g_object_set (G_OBJECT (camera), - "transfer-asynchronously", TRUE, - NULL); - - uca_camera_set_grab_func (camera, &grab_func, &d); - uca_camera_start_recording (camera, &error); - g_usleep (G_USEC_PER_SEC); - uca_camera_stop_recording (camera, &error); - - g_print ("Asynchronous data transfer\n"); - g_print (" Bandwidth: %3.2f MB/s\n", d.size * d.counter / 1024. / 1024.); - g_print (" Throughput: %i frames/s\n", d.counter); - - g_free (d.destination); -} - -int -main (int argc, char *argv[]) -{ - UcaPluginManager *manager; - GError *error = NULL; - (void) signal (SIGINT, sigint_handler); - - g_type_init (); - if (argc < 2) { - print_usage (); - return 1; - } - - manager = uca_plugin_manager_new (); - camera = uca_plugin_manager_new_camera (manager, argv[1], &error); - - if (camera == NULL) { - g_print ("Error during initialization: %s\n", error->message); - return 1; - } - - test_synchronous_operation (camera); - g_print ("\n"); - test_asynchronous_operation (camera); - - g_object_unref (camera); - g_object_unref (manager); - - return error != NULL ? 1 : 0; -} diff --git a/test/test-all.c b/test/test-all.c deleted file mode 100644 index 9526d4f..0000000 --- a/test/test-all.c +++ /dev/null @@ -1,214 +0,0 @@ - -#include -#include "uca-camera.h" -#include "cameras/uca-mock-camera.h" - -typedef struct { - UcaCamera *camera; -} Fixture; - -typedef void (*UcaFixtureFunc) (Fixture *fixture, gconstpointer data); - -static void fixture_setup(Fixture *fixture, gconstpointer data) -{ - const gchar *type = (gchar *) data; - GError *error = NULL; - fixture->camera = uca_camera_new(type, &error); - g_assert_no_error(error); - g_assert(fixture->camera); -} - -static void fixture_teardown(Fixture *fixture, gconstpointer data) -{ - g_object_unref(fixture->camera); -} - -static void on_property_change(gpointer instance, GParamSpec *pspec, gpointer user_data) -{ - gboolean *success = (gboolean *) user_data; - *success = TRUE; -} - -static void test_factory() -{ - GError *error = NULL; - UcaCamera *camera = uca_camera_new("fox994m3a0yxmy", &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_FOUND); - g_assert(camera == NULL); -} - -static void test_recording(Fixture *fixture, gconstpointer data) -{ - GError *error = NULL; - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - uca_camera_stop_recording(camera, &error); - g_assert_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING); - g_error_free(error); - - error = NULL; - gboolean success = FALSE; - g_signal_connect(G_OBJECT(camera), "notify::is-recording", - (GCallback) on_property_change, &success); - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - g_assert(success == TRUE); - - success = FALSE; - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - 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); - - gfloat max_frame_rate = 1.0f; - g_object_get(G_OBJECT(camera), - "sensor-max-frame-rate", &max_frame_rate, - NULL); - g_assert(max_frame_rate != 0.0f); - - g_object_set(G_OBJECT(camera), - "transfer-asynchronously", TRUE, - NULL); - - GError *error = NULL; - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - const gulong sleep_time = G_USEC_PER_SEC / ((gulong) (max_frame_rate / 2.0f)); - g_usleep(sleep_time); - - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); - g_assert(success == TRUE); -} - -static void test_recording_grab(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - GError *error = NULL; - gpointer frame = NULL; - - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - - uca_camera_grab(camera, &frame, &error); - g_assert_no_error(error); - g_assert(frame != NULL); - - 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); - - gboolean is_recording = FALSE; - uca_camera_start_recording(camera, NULL); - g_object_get(G_OBJECT(camera), - "is-recording", &is_recording, - NULL); - g_assert(is_recording == TRUE); - - uca_camera_stop_recording(camera, NULL); - g_object_get(G_OBJECT(camera), - "is-recording", &is_recording, - NULL); - g_assert(is_recording == FALSE); -} - -static void test_base_properties(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - guint n_properties = 0; - GParamSpec **properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(camera), &n_properties); - GValue val = {0}; - - for (guint i = 0; i < n_properties; i++) { - g_value_init(&val, properties[i]->value_type); - g_object_get_property(G_OBJECT(camera), properties[i]->name, &val); - g_value_unset(&val); - } - - g_free(properties); -} - -static void test_binnings_properties(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); - - GValueArray *array = NULL; - g_object_get(G_OBJECT(camera), - "sensor-horizontal-binnings", &array, - NULL); - - GValue *value = g_value_array_get_nth(array, 0); - g_assert(value != NULL); - g_assert(g_value_get_uint(value) == 1); -} - - -int main(int argc, char *argv[]) -{ - g_type_init(); - g_test_init(&argc, &argv, NULL); - g_test_bug_base("http://ufo.kit.edu/ufo/ticket"); - - g_test_add_func("/factory", test_factory); - - gchar **types = NULL; - types = argc > 1 ? argv + 1 : uca_camera_get_types(); - - /* - * paths and test_funcs MUST correspond! - */ - static const gchar *paths[] = { - "/recording", - "/recording/grab", - "/recording/asynchronous", - "/properties/base", - "/properties/recording", - "/properties/binnings", - NULL - }; - - static UcaFixtureFunc test_funcs[] = { - test_recording, - test_recording_grab, - test_recording_async, - test_base_properties, - test_recording_property, - test_binnings_properties, - }; - - for (guint i = 0; i < g_strv_length(types); i++) { - guint j = 0; - - while (paths[j] != NULL) { - gchar *new_path = g_strdup_printf("/%s%s", types[i], paths[j]); - g_test_add(new_path, Fixture, types[i], fixture_setup, test_funcs[j], fixture_teardown); - g_free(new_path); - j++; - } - } - - gint result = g_test_run(); - - if (argc == 1) - g_strfreev(types); - - return result; -} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 957fdbf..0e4d28e 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -16,9 +16,21 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../src ) +set(libs uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) + add_executable(gen-doc gen-doc.c) +target_link_libraries(gen-doc ${libs}) -target_link_libraries(gen-doc uca - ${GLIB2_LIBRARIES} - ${GOBJECT2_LIBRARIES} - ) +add_executable(grab grab.c) +target_link_libraries(grab ${libs}) + +add_executable(grab-async grab-async.c) +target_link_libraries(grab-async ${libs}) + +add_executable(benchmark benchmark.c) +target_link_libraries(benchmark ${libs}) + +add_executable(perf perf-overhead.c) +target_link_libraries(perf ${libs}) + +add_subdirectory(gui) diff --git a/tools/benchmark.c b/tools/benchmark.c new file mode 100644 index 0000000..ef99fd1 --- /dev/null +++ b/tools/benchmark.c @@ -0,0 +1,267 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-plugin-manager.h" + +typedef void (*GrabFrameFunc) (UcaCamera *camera, gpointer buffer, guint n_frames); + +static UcaCamera *camera = NULL; + +static void +sigint_handler(int signal) +{ + g_print ("Closing down libuca\n"); + uca_camera_stop_recording (camera, NULL); + g_object_unref (camera); + exit (signal); +} + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +static void +log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user) +{ + gsize n_written; + GError *error = NULL; + GIOChannel *channel = user; + +#if GLIB_CHECK_VERSION(2, 26, 0) + GTimeZone *tz; + GDateTime *date_time; + gchar *new_message; + + tz = g_time_zone_new_local (); + date_time = g_date_time_new_now (tz); + + new_message = g_strdup_printf ("[%s] %s\n", + g_date_time_format (date_time, "%FT%H:%M:%S%z"), message); + + g_time_zone_unref (tz); + g_date_time_unref (date_time); + + g_io_channel_write_chars (channel, new_message, strlen (new_message), &n_written, &error); + g_assert_no_error (error); + g_free (new_message); +#else + g_io_channel_write_chars (channel, message, strlen (message), &n_written, &error); + g_assert_no_error (error); +#endif + + g_io_channel_flush (channel, &error); + g_assert_no_error (error); +} + +static void +grab_frames_sync (UcaCamera *camera, gpointer buffer, guint n_frames) +{ + GError *error = NULL; + + uca_camera_start_recording (camera, &error); + + for (guint i = 0; i < n_frames; i++) { + uca_camera_grab(camera, &buffer, &error); + + if (error != NULL) { + g_warning ("Error grabbing frame %02i/%i: `%s'", i, n_frames, error->message); + g_error_free (error); + error = NULL; + } + } + + uca_camera_stop_recording (camera, &error); +} + +static void +grab_callback (gpointer data, gpointer user_data) +{ + guint *n_acquired_frames = user_data; + *n_acquired_frames += 1; +} + +static void +grab_frames_async (UcaCamera *camera, gpointer buffer, guint n_frames) +{ + GError *error = NULL; + guint n_acquired_frames = 0; + + uca_camera_set_grab_func (camera, grab_callback, &n_acquired_frames); + uca_camera_start_recording (camera, &error); + + /* + * Behold! Spinlooping is probably a bad idea but nowadays single core + * machines are relatively rare. + */ + while (n_acquired_frames < n_frames) + ; + + uca_camera_stop_recording (camera, &error); + +} + +static void +benchmark_method (UcaCamera *camera, gpointer buffer, GrabFrameFunc func, guint n_runs, guint n_frames, guint n_bytes) +{ + GTimer *timer; + gdouble fps; + gdouble bandwidth; + gdouble total_time = 0.0; + GError *error = NULL; + + g_print ("%-10i%-10i", n_frames, n_runs); + timer = g_timer_new (); + g_assert_no_error (error); + + for (guint run = 0; run < n_runs; run++) { + g_message ("Start run %i of %i", run, n_runs); + g_timer_start (timer); + + func (camera, buffer, n_frames); + + g_timer_stop (timer); + total_time += g_timer_elapsed (timer, NULL); + } + + g_assert_no_error (error); + + fps = n_runs * n_frames / total_time; + bandwidth = n_bytes * fps / 1024 / 1024; + g_print ("%-16.2f%-16.2f\n", fps, bandwidth); + + g_timer_destroy (timer); +} + +static void +benchmark (UcaCamera *camera) +{ + const guint n_runs = 3; + const guint n_frames = 100; + + guint sensor_width; + guint sensor_height; + guint roi_width; + guint roi_height; + guint bits; + guint n_bytes_per_pixel; + guint n_bytes; + gdouble exposure = 0.00001; + gpointer buffer; + + g_object_set (G_OBJECT (camera), + "exposure-time", exposure, + NULL); + + g_object_get (G_OBJECT (camera), + "sensor-width", &sensor_width, + "sensor-height", &sensor_height, + "sensor-bitdepth", &bits, + "roi-width", &roi_width, + "roi-height", &roi_height, + "exposure-time", &exposure, + NULL); + + g_print ("# --- General information ---\n"); + g_print ("# Sensor size: %ix%i\n", sensor_width, sensor_height); + g_print ("# ROI size: %ix%i\n", roi_width, roi_height); + g_print ("# Exposure time: %fs\n", exposure); + + /* Synchronous frame acquisition */ + g_print ("# %-10s%-10s%-10s%-16s%-16s\n", "type", "n_frames", "n_runs", "frames/s", "MiB/s"); + g_print (" %-10s", "sync"); + + g_message ("Start synchronous benchmark"); + + n_bytes_per_pixel = bits > 8 ? 2 : 1; + n_bytes = roi_width * roi_height * n_bytes_per_pixel; + buffer = g_malloc0(n_bytes); + + benchmark_method (camera, buffer, grab_frames_sync, n_runs, n_frames, n_bytes); + + /* Asynchronous frame acquisition */ + g_object_set (G_OBJECT(camera), + "transfer-asynchronously", TRUE, + NULL); + + g_message ("Start asynchronous benchmark"); + g_print (" %-10s", "async"); + + benchmark_method (camera, buffer, grab_frames_async, n_runs, n_frames, n_bytes); + + g_free (buffer); +} + +int +main (int argc, char *argv[]) +{ + UcaPluginManager *manager; + GIOChannel *log_channel; + GError *error = NULL; + + (void) signal (SIGINT, sigint_handler); + g_type_init(); + + if (argc < 2) { + print_usage(); + return 1; + } + + log_channel = g_io_channel_new_file ("error.log", "a+", &error); + g_assert_no_error (error); + g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, log_channel); + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + + if (camera == NULL) { + g_error ("Initialization: %s", error->message); + return 1; + } + + benchmark (camera); + + g_object_unref (camera); + g_io_channel_shutdown (log_channel, TRUE, &error); + g_assert_no_error (error); + + return 0; +} diff --git a/tools/grab-async.c b/tools/grab-async.c new file mode 100644 index 0000000..6132829 --- /dev/null +++ b/tools/grab-async.c @@ -0,0 +1,138 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include "uca-plugin-manager.h" +#include "uca-camera.h" + +static UcaCamera *camera = NULL; + +typedef struct { + guint roi_width; + guint roi_height; + guint counter; +} CallbackData; + +static void +sigint_handler(int signal) +{ + printf("Closing down libuca\n"); + uca_camera_stop_recording(camera, NULL); + g_object_unref(camera); + exit(signal); +} + +static void +grab_callback(gpointer data, gpointer user_data) +{ + CallbackData *cbd = (CallbackData *) user_data; + gchar *filename = g_strdup_printf("frame-%04i.raw", cbd->counter++); + FILE *fp = fopen(filename, "wb"); + + fwrite(data, sizeof(guint16), cbd->roi_width * cbd->roi_height, fp); + g_print("."); + fclose(fp); + g_free(filename); +} + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +int +main(int argc, char *argv[]) +{ + CallbackData cbd; + guint sensor_width, sensor_height; + gchar *name; + UcaPluginManager *manager; + GError *error = NULL; + (void) signal(SIGINT, sigint_handler); + + g_type_init(); + + if (argc < 2) { + print_usage(); + return 1; + } + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + + if (camera == NULL) { + g_print("Error during initialization: %s\n", error->message); + return 1; + } + + g_object_get(G_OBJECT(camera), + "name", &name, + "sensor-width", &sensor_width, + "sensor-height", &sensor_height, + NULL); + + g_object_set(G_OBJECT(camera), + "roi-x0", 0, + "roi-y0", 0, + "roi-width", sensor_width, + "roi-height", sensor_height, + "transfer-asynchronously", TRUE, + NULL); + + g_object_get(G_OBJECT(camera), + "roi-width", &cbd.roi_width, + "roi-height", &cbd.roi_height, + NULL); + + g_print("Camera: %s\n", name); + g_free(name); + + g_print("Start asynchronous recording\n"); + cbd.counter = 0; + uca_camera_set_grab_func(camera, grab_callback, &cbd); + uca_camera_start_recording(camera, &error); + g_assert_no_error(error); + g_usleep(2 * G_USEC_PER_SEC); + + g_print(" done\n"); + uca_camera_stop_recording(camera, NULL); + g_object_unref(camera); + + return error != NULL ? 1 : 0; +} diff --git a/tools/grab.c b/tools/grab.c new file mode 100644 index 0000000..1f5c917 --- /dev/null +++ b/tools/grab.c @@ -0,0 +1,160 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include "uca-plugin-manager.h" +#include "uca-camera.h" + +static UcaCamera *camera = NULL; + +static void sigint_handler(int signal) +{ + printf("Closing down libuca\n"); + uca_camera_stop_recording(camera, NULL); + g_object_unref(camera); + exit(signal); +} + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +int main(int argc, char *argv[]) +{ + UcaPluginManager *manager; + GError *error = NULL; + (void) signal(SIGINT, sigint_handler); + + guint sensor_width, sensor_height; + guint roi_width, roi_height, roi_x, roi_y, roi_width_multiplier, roi_height_multiplier; + guint bits; + gchar *name; + + g_type_init(); + + if (argc < 2) { + print_usage(); + return 1; + } + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + + if (camera == NULL) { + g_print("Error during initialization: %s\n", error->message); + return 1; + } + + g_object_get(G_OBJECT(camera), + "sensor-width", &sensor_width, + "sensor-height", &sensor_height, + "name", &name, + NULL); + + g_object_set(G_OBJECT(camera), + "exposure-time", 0.001, + "roi-x0", 0, + "roi-y0", 0, + "roi-width", 1000, + "roi-height", sensor_height, + NULL); + + g_object_get(G_OBJECT(camera), + "roi-width", &roi_width, + "roi-height", &roi_height, + "roi-width-multiplier", &roi_width_multiplier, + "roi-height-multiplier", &roi_height_multiplier, + "roi-x0", &roi_x, + "roi-y0", &roi_y, + "sensor-bitdepth", &bits, + NULL); + + g_print("Camera: %s\n", name); + g_free(name); + + g_print("Sensor: %ix%i px\n", sensor_width, sensor_height); + g_print("ROI: %ix%i @ (%i, %i), steps: %i, %i\n", + roi_width, roi_height, roi_x, roi_y, roi_width_multiplier, roi_height_multiplier); + + const int pixel_size = bits == 8 ? 1 : 2; + gpointer buffer = g_malloc0(roi_width * roi_height * pixel_size); + gchar filename[FILENAME_MAX]; + GTimer *timer = g_timer_new(); + + for (int i = 0; i < 1; i++) { + gint counter = 0; + g_print("Start recording\n"); + uca_camera_start_recording(camera, &error); + g_assert_no_error(error); + + while (counter < 5) { + g_print(" grab frame ... "); + g_timer_start(timer); + uca_camera_grab(camera, &buffer, &error); + + if (error != NULL) { + g_print("\nError: %s\n", error->message); + goto cleanup; + } + + g_timer_stop(timer); + g_print("done (took %3.5fs)\n", g_timer_elapsed(timer, NULL)); + + snprintf(filename, FILENAME_MAX, "frame-%08i.raw", counter++); + FILE *fp = fopen(filename, "wb"); + fwrite(buffer, roi_width * roi_height, pixel_size, fp); + fclose(fp); + g_usleep(2 * G_USEC_PER_SEC); + } + + g_print("Stop recording\n"); + uca_camera_stop_recording(camera, &error); + g_assert_no_error(error); + } + + g_timer_destroy(timer); + +cleanup: + uca_camera_stop_recording(camera, NULL); + g_object_unref(camera); + g_free(buffer); + + return error != NULL ? 1 : 0; +} diff --git a/tools/gui/control.c b/tools/gui/control.c new file mode 100644 index 0000000..75b3cde --- /dev/null +++ b/tools/gui/control.c @@ -0,0 +1,350 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "uca-camera.h" +#include "uca-plugin-manager.h" +#include "egg-property-tree-view.h" + + +typedef struct { + gboolean running; + gboolean store; + + guchar *buffer, *pixels; + GdkPixbuf *pixbuf; + GtkWidget *image; + GtkTreeModel *property_model; + UcaCamera *camera; + + GtkStatusbar *statusbar; + guint statusbar_context_id; + + int timestamp; + int width; + int height; + int pixel_size; +} ThreadData; + +enum { + COLUMN_NAME = 0, + COLUMN_VALUE, + COLUMN_EDITABLE, + NUM_COLUMNS +}; + +static UcaPluginManager *plugin_manager; + +static void +convert_8bit_to_rgb (guchar *output, guchar *input, int width, int height) +{ + for (int i = 0, j = 0; i < width*height; i++) { + output[j++] = input[i]; + output[j++] = input[i]; + output[j++] = input[i]; + } +} + +static void +convert_16bit_to_rgb (guchar *output, guchar *input, int width, int height) +{ + guint16 *in = (guint16 *) input; + guint16 min = G_MAXUINT16, max = 0; + gfloat spread = 0.0f; + + for (int i = 0; i < width * height; i++) { + guint16 v = in[i]; + if (v < min) + min = v; + if (v > max) + max = v; + } + + spread = (gfloat) max - min; + + if (spread > 0.0f) { + for (int i = 0, j = 0; i < width*height; i++) { + guchar val = (guint8) (((in[i] - min) / spread) * 255.0f); + output[j++] = val; + output[j++] = val; + output[j++] = val; + } + } +} + +static void * +grab_thread (void *args) +{ + ThreadData *data = (ThreadData *) args; + gchar filename[FILENAME_MAX] = {0,}; + gint counter = 0; + + while (data->running) { + uca_camera_grab (data->camera, (gpointer) &data->buffer, NULL); + + if (data->store) { + snprintf (filename, FILENAME_MAX, "frame-%i-%08i.raw", data->timestamp, counter++); + FILE *fp = fopen (filename, "wb"); + fwrite (data->buffer, data->width*data->height, data->pixel_size, fp); + fclose (fp); + } + + /* FIXME: We should actually check if this is really a new frame and + * just do nothing if it is an already displayed one. */ + if (data->pixel_size == 1) + convert_8bit_to_rgb (data->pixels, data->buffer, data->width, data->height); + else if (data->pixel_size == 2) { + convert_16bit_to_rgb (data->pixels, data->buffer, data->width, data->height); + } + + gdk_threads_enter (); + gdk_flush (); + gtk_image_clear (GTK_IMAGE (data->image)); + gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); + gtk_widget_queue_draw_area (data->image, 0, 0, data->width, data->height); + gdk_threads_leave (); + } + return NULL; +} + +gboolean +on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + return FALSE; +} + +void +on_destroy (GtkWidget *widget, gpointer data) +{ + ThreadData *td = (ThreadData *) data; + td->running = FALSE; + g_object_unref (td->camera); + gtk_main_quit (); +} + +static void +on_toolbutton_run_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + + if (data->running) + return; + + GError *error = NULL; + data->running = TRUE; + + uca_camera_start_recording (data->camera, &error); + + if (error != NULL) { + g_printerr ("Failed to start recording: %s\n", error->message); + return; + } + + if (!g_thread_create (grab_thread, data, FALSE, &error)) { + g_printerr ("Failed to create thread: %s\n", error->message); + return; + } +} + +static void +on_toolbutton_stop_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + data->running = FALSE; + data->store = FALSE; + GError *error = NULL; + uca_camera_stop_recording (data->camera, &error); + + if (error != NULL) + g_printerr ("Failed to stop: %s\n", error->message); +} + +static void +on_toolbutton_record_clicked (GtkWidget *widget, gpointer args) +{ + ThreadData *data = (ThreadData *) args; + data->timestamp = (int) time (0); + data->store = TRUE; + GError *error = NULL; + + gtk_statusbar_push (data->statusbar, data->statusbar_context_id, "Recording..."); + + if (data->running != TRUE) { + data->running = TRUE; + uca_camera_start_recording (data->camera, &error); + + if (!g_thread_create (grab_thread, data, FALSE, &error)) + g_printerr ("Failed to create thread: %s\n", error->message); + } +} + +static void +create_main_window (GtkBuilder *builder, const gchar* camera_name) +{ + static ThreadData td; + + GError *error = NULL; + UcaCamera *camera = uca_plugin_manager_new_camera (plugin_manager, camera_name, &error); + + if ((camera == NULL) || (error != NULL)) { + g_error ("%s\n", error->message); + gtk_main_quit (); + } + + guint bits_per_sample; + g_object_get (camera, + "roi-width", &td.width, + "roi-height", &td.height, + "sensor-bitdepth", &bits_per_sample, + NULL); + + GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); + GtkWidget *image = GTK_WIDGET (gtk_builder_get_object (builder, "image")); + GtkWidget *property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); + GtkContainer *scrolled_property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "scrolledwindow2")); + + gtk_container_add (scrolled_property_window, property_tree_view); + gtk_widget_show_all (GTK_WIDGET (scrolled_property_window)); + + GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); + + td.pixel_size = bits_per_sample > 8 ? 2 : 1; + td.image = image; + td.pixbuf = pixbuf; + td.buffer = (guchar *) g_malloc (td.pixel_size * td.width * td.height); + td.pixels = gdk_pixbuf_get_pixels (pixbuf); + td.running = FALSE; + td.statusbar = GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar")); + td.statusbar_context_id = gtk_statusbar_get_context_id (td.statusbar, "Recording Information"); + td.store = FALSE; + td.camera = camera; + td.property_model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "camera-properties")); + + g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_run"), + "clicked", G_CALLBACK (on_toolbutton_run_clicked), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_stop"), + "clicked", G_CALLBACK (on_toolbutton_stop_clicked), &td); + g_signal_connect (gtk_builder_get_object (builder, "toolbutton_record"), + "clicked", G_CALLBACK (on_toolbutton_record_clicked), &td); + + gtk_widget_show (image); + gtk_widget_show (window); +} + +static void +on_button_proceed_clicked (GtkWidget *widget, gpointer data) +{ + GtkBuilder *builder = GTK_BUILDER (data); + GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); + GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); + GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); + + GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); + GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL); + GtkTreeIter iter; + + gtk_widget_destroy (choice_window); + gboolean valid = gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), &iter, selected_rows->data); + + if (valid) { + gchar *data; + gtk_tree_model_get (GTK_TREE_MODEL (list_store), &iter, 0, &data, -1); + create_main_window (builder, data); + g_free (data); + } + + g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected_rows); +} + +static void +on_treeview_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_KEY_Return) + gtk_widget_grab_focus (GTK_WIDGET (data)); +} + +static void +create_choice_window (GtkBuilder *builder) +{ + GList *camera_types = uca_plugin_manager_get_available_cameras (plugin_manager); + + GtkWidget *choice_window = GTK_WIDGET (gtk_builder_get_object (builder, "choice-window")); + GtkTreeView *treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview-cameras")); + GtkListStore *list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "camera-types")); + GtkButton *proceed_button = GTK_BUTTON (gtk_builder_get_object (builder, "button-proceed")); + GtkTreeIter iter; + + for (GList *it = g_list_first (camera_types); it != NULL; it = g_list_next (it)) { + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, 0, g_strdup ((gchar *) it->data), -1); + } + + gboolean valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter); + + if (valid) { + GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_path (selection, gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter)); + } + + g_signal_connect (proceed_button, "clicked", G_CALLBACK (on_button_proceed_clicked), builder); + g_signal_connect (treeview, "key-press-event", G_CALLBACK (on_treeview_keypress), proceed_button); + gtk_widget_show_all (GTK_WIDGET (choice_window)); + + g_list_foreach (camera_types, (GFunc) g_free, NULL); + g_list_free (camera_types); +} + +int +main (int argc, char *argv[]) +{ + GError *error = NULL; + + g_thread_init (NULL); + gdk_threads_init (); + gtk_init (&argc, &argv); + + GtkBuilder *builder = gtk_builder_new (); + + if (!gtk_builder_add_from_file (builder, CONTROL_GLADE_PATH, &error)) { + g_print ("Error: %s\n", error->message); + return 1; + } + + plugin_manager = uca_plugin_manager_new (); + create_choice_window (builder); + gtk_builder_connect_signals (builder, NULL); + + gdk_threads_enter (); + gtk_main (); + gdk_threads_leave (); + + g_object_unref (plugin_manager); + return 0; +} diff --git a/tools/gui/control.glade b/tools/gui/control.glade new file mode 100644 index 0000000..d7ba2fc --- /dev/null +++ b/tools/gui/control.glade @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + Camera Control + 1024 + 768 + + + + True + + + True + + + True + _File + True + + + True + + + gtk-new + True + True + True + + + + + gtk-open + True + True + True + + + + + gtk-save + True + True + True + + + + + gtk-save-as + True + True + True + + + + + True + + + + + gtk-quit + True + True + True + + + + + + + + + + True + _Help + True + + + True + + + gtk-about + True + True + True + + + + + + + + + False + 0 + + + + + True + + + True + Run + True + gtk-media-play + + + False + True + + + + + True + Record + True + gtk-media-record + + + False + True + + + + + True + Stop + True + gtk-media-stop + + + False + True + + + + + False + 1 + + + + + True + True + 6 + + + 300 + True + True + automatic + automatic + + + True + queue + + + True + gtk-missing-image + + + + + + + True + False + + + + + True + True + automatic + automatic + + + + + + True + True + + + + + 2 + + + + + True + 2 + + + False + 3 + + + + + + + 65535 + 1 + 65535 + 1 + 10 + + + 6 + + + True + 2 + + + True + True + camera-types + + + Choose camera + + + + 0 + + + + + + + 0 + + + + + True + 6 + end + + + gtk-quit + True + True + True + True + + + + False + False + 0 + + + + + gtk-ok + True + True + True + True + + + False + False + 1 + + + + + False + 6 + 1 + + + + + + diff --git a/tools/gui/egg-property-cell-renderer.c b/tools/gui/egg-property-cell-renderer.c new file mode 100644 index 0000000..9df5cc3 --- /dev/null +++ b/tools/gui/egg-property-cell-renderer.c @@ -0,0 +1,594 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include "egg-property-cell-renderer.h" + +G_DEFINE_TYPE (EggPropertyCellRenderer, egg_property_cell_renderer, GTK_TYPE_CELL_RENDERER) + +#define EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererPrivate)) + + +struct _EggPropertyCellRendererPrivate +{ + GObject *object; + GtkListStore *list_store; + GtkCellRenderer *renderer; + GtkCellRenderer *text_renderer; + GtkCellRenderer *spin_renderer; + GtkCellRenderer *toggle_renderer; + GtkCellRenderer *combo_renderer; + GHashTable *combo_models; +}; + +enum +{ + PROP_0, + PROP_PROP_NAME, + N_PROPERTIES +}; + +enum +{ + COMBO_COLUMN_VALUE_NAME, + COMBO_COLUMN_VALUE, + N_COMBO_COLUMNS +}; + +static GParamSpec *egg_property_cell_renderer_properties[N_PROPERTIES] = { NULL, }; + +GtkCellRenderer * +egg_property_cell_renderer_new (GObject *object, + GtkListStore *list_store) +{ + EggPropertyCellRenderer *renderer; + + renderer = EGG_PROPERTY_CELL_RENDERER (g_object_new (EGG_TYPE_PROPERTY_CELL_RENDERER, NULL)); + renderer->priv->object = object; + renderer->priv->list_store = list_store; + return GTK_CELL_RENDERER (renderer); +} + +static GParamSpec * +get_pspec_from_object (GObject *object, const gchar *prop_name) +{ + GObjectClass *oclass = G_OBJECT_GET_CLASS (object); + return g_object_class_find_property (oclass, prop_name); +} + +static void +get_string_double_repr (GObject *object, const gchar *prop_name, gchar **text, gdouble *number) +{ + GParamSpec *pspec; + GValue from = { 0 }; + GValue to_string = { 0 }; + GValue to_double = { 0 }; + + pspec = get_pspec_from_object (object, prop_name); + g_value_init (&from, pspec->value_type); + g_value_init (&to_string, G_TYPE_STRING); + g_value_init (&to_double, G_TYPE_DOUBLE); + g_object_get_property (object, prop_name, &from); + + if (g_value_transform (&from, &to_string)) + *text = g_strdup (g_value_get_string (&to_string)); + else + g_warning ("Could not convert from %s gchar*\n", g_type_name (pspec->value_type)); + + if (g_value_transform (&from, &to_double)) + *number = g_value_get_double (&to_double); + else + g_warning ("Could not convert from %s to gdouble\n", g_type_name (pspec->value_type)); +} + +static void +clear_adjustment (GObject *object) +{ + GtkAdjustment *adjustment; + + g_object_get (object, + "adjustment", &adjustment, + NULL); + + if (adjustment) + g_object_unref (adjustment); + + g_object_set (object, + "adjustment", NULL, + NULL); +} + +static void +egg_property_cell_renderer_set_renderer (EggPropertyCellRenderer *renderer, + const gchar *prop_name) +{ + EggPropertyCellRendererPrivate *priv; + GParamSpec *pspec; + gchar *text = NULL; + gdouble number; + + priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); + pspec = get_pspec_from_object (priv->object, prop_name); + + /* + * Set this renderers mode, so that any actions can be forwarded to our + * child renderers. + */ + switch (pspec->value_type) { + /* toggle renderers */ + case G_TYPE_BOOLEAN: + priv->renderer = priv->toggle_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + break; + + /* spin renderers */ + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + priv->renderer = priv->spin_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + g_object_set (priv->renderer, "digits", 5, NULL); + break; + + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_INT64: + case G_TYPE_UINT64: + priv->renderer = priv->spin_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + g_object_set (priv->renderer, "digits", 0, NULL); + break; + + /* text renderers */ + case G_TYPE_POINTER: + case G_TYPE_STRING: + priv->renderer = priv->text_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + break; + + /* combo renderers */ + default: + if (G_TYPE_IS_ENUM (pspec->value_type)) { + priv->renderer = priv->combo_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + } + break; + } + + /* + * Set the content from the objects property. + */ + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + { + gboolean val; + + g_object_get (priv->object, prop_name, &val, NULL); + g_object_set (priv->renderer, + "active", val, + "activatable", pspec->flags & G_PARAM_WRITABLE ? TRUE : FALSE, + NULL); + break; + } + + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_INT64: + case G_TYPE_UINT64: + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + get_string_double_repr (priv->object, prop_name, &text, &number); + break; + + case G_TYPE_STRING: + g_object_get (priv->object, prop_name, &text, NULL); + break; + + case G_TYPE_POINTER: + { + gpointer val; + + g_object_get (priv->object, prop_name, &val, NULL); + text = g_strdup_printf ("0x%x", GPOINTER_TO_INT (val)); + } + break; + + default: + if (G_TYPE_IS_ENUM (pspec->value_type)) { + GParamSpecEnum *pspec_enum; + GEnumClass *enum_class; + GtkTreeModel *combo_model; + GtkTreeIter iter; + gint value; + + g_object_get (priv->object, prop_name, &value, NULL); + + pspec_enum = G_PARAM_SPEC_ENUM (pspec); + enum_class = pspec_enum->enum_class; + combo_model = g_hash_table_lookup (priv->combo_models, prop_name); + + if (combo_model == NULL) { + combo_model = GTK_TREE_MODEL (gtk_list_store_new (N_COMBO_COLUMNS, G_TYPE_STRING, G_TYPE_INT)); + g_hash_table_insert (priv->combo_models, g_strdup (prop_name), combo_model); + + for (guint i = 0; i < enum_class->n_values; i++) { + gtk_list_store_append (GTK_LIST_STORE (combo_model), &iter); + gtk_list_store_set (GTK_LIST_STORE (combo_model), &iter, + COMBO_COLUMN_VALUE_NAME, enum_class->values[i].value_name, + COMBO_COLUMN_VALUE, enum_class->values[i].value, + -1); + } + } + + + for (guint i = 0; i < enum_class->n_values; i++) { + if (enum_class->values[i].value == value) + text = g_strdup (enum_class->values[i].value_name); + } + + g_object_set (priv->renderer, + "model", combo_model, + "text-column", 0, + NULL); + } + break; + } + + if (pspec->flags & G_PARAM_WRITABLE) { + if (GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) + g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + else + g_object_set (priv->renderer, "foreground", "#000000", NULL); + + if (GTK_IS_CELL_RENDERER_TEXT (priv->renderer)) { + g_object_set (priv->renderer, + "editable", TRUE, + "mode", GTK_CELL_RENDERER_MODE_EDITABLE, + NULL); + } + + if (GTK_IS_CELL_RENDERER_SPIN (priv->renderer)) { + GtkObject *adjustment = NULL; + +#define gtk_typed_adjustment_new(type, pspec, val, step_inc, page_inc) \ + gtk_adjustment_new (val, ((type *) pspec)->minimum, ((type *) pspec)->maximum, step_inc, page_inc, 0) + + switch (pspec->value_type) { + case G_TYPE_INT: + adjustment = gtk_typed_adjustment_new (GParamSpecInt, pspec, number, 1, 10); + break; + case G_TYPE_UINT: + adjustment = gtk_typed_adjustment_new (GParamSpecUInt, pspec, number, 1, 10); + break; + case G_TYPE_LONG: + adjustment = gtk_typed_adjustment_new (GParamSpecLong, pspec, number, 1, 10); + break; + case G_TYPE_ULONG: + adjustment = gtk_typed_adjustment_new (GParamSpecULong, pspec, number, 1, 10); + break; + case G_TYPE_INT64: + adjustment = gtk_typed_adjustment_new (GParamSpecInt64, pspec, number, 1, 10); + break; + case G_TYPE_UINT64: + adjustment = gtk_typed_adjustment_new (GParamSpecUInt64, pspec, number, 1, 10); + break; + case G_TYPE_FLOAT: + adjustment = gtk_typed_adjustment_new (GParamSpecFloat, pspec, number, 0.05, 10); + break; + case G_TYPE_DOUBLE: + adjustment = gtk_typed_adjustment_new (GParamSpecDouble, pspec, number, 0.05, 10); + break; + } + + clear_adjustment (G_OBJECT (priv->renderer)); + g_object_set (priv->renderer, "adjustment", adjustment, NULL); + } + } + else { + g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); + + if (!GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) + g_object_set (priv->renderer, "foreground", "#aaaaaa", NULL); + } + + if (text != NULL) { + g_object_set (priv->renderer, "text", text, NULL); + g_free (text); + } +} + +static gchar * +get_prop_name_from_tree_model (GtkTreeModel *model, const gchar *path) +{ + GtkTreeIter iter; + gchar *prop_name = NULL; + + /* TODO: don't assume column 0 to contain the prop name */ + if (gtk_tree_model_get_iter_from_string (model, &iter, path)) + gtk_tree_model_get (model, &iter, 0, &prop_name, -1); + + return prop_name; +} + +static void +egg_property_cell_renderer_toggle_cb (GtkCellRendererToggle *renderer, + gchar *path, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + gboolean activated; + + g_object_get (priv->object, prop_name, &activated, NULL); + g_object_set (priv->object, prop_name, !activated, NULL); + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_text_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + g_object_set (priv->object, prop_name, new_text, NULL); + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_spin_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + GParamSpec *pspec; + GValue from = { 0 }; + GValue to = { 0 }; + + pspec = get_pspec_from_object (priv->object, prop_name); + + g_value_init (&from, G_TYPE_DOUBLE); + g_value_init (&to, pspec->value_type); + g_value_set_double (&from, strtod (new_text, NULL)); + + if (g_value_transform (&from, &to)) + g_object_set_property (priv->object, prop_name, &to); + else + g_warning ("Could not transform %s to %s\n", + g_value_get_string (&from), g_type_name (pspec->value_type)); + + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_changed_cb (GtkCellRendererCombo *combo, + gchar *path, + GtkTreeIter *new_iter, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + GtkTreeModel *combo_model; + gchar *value_name; + gint value; + + combo_model = g_hash_table_lookup (priv->combo_models, prop_name); + + gtk_tree_model_get (combo_model, new_iter, + COMBO_COLUMN_VALUE_NAME, &value_name, + COMBO_COLUMN_VALUE, &value, + -1); + + g_object_set (priv->object, prop_name, value, NULL); + g_free (value_name); + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ + + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + gtk_cell_renderer_get_size (priv->renderer, widget, cell_area, x_offset, y_offset, width, height); +} + +static void +egg_property_cell_renderer_render (GtkCellRenderer *cell, + GdkDrawable *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + gtk_cell_renderer_render (priv->renderer, window, widget, background_area, cell_area, expose_area, flags); +} + +static gboolean +egg_property_cell_renderer_activate (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + return gtk_cell_renderer_activate (priv->renderer, event, widget, path, background_area, cell_area, flags); +} + +static GtkCellEditable * +egg_property_cell_renderer_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + return gtk_cell_renderer_start_editing (priv->renderer, event, widget, path, background_area, cell_area, flags); +} + +static void +egg_property_cell_renderer_dispose (GObject *object) +{ + EggPropertyCellRenderer *renderer = EGG_PROPERTY_CELL_RENDERER (object); + g_hash_table_destroy (renderer->priv->combo_models); +} + +static void +egg_property_cell_renderer_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); + EggPropertyCellRenderer *renderer = EGG_PROPERTY_CELL_RENDERER (object); + + switch (property_id) { + case PROP_PROP_NAME: + egg_property_cell_renderer_set_renderer (renderer, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + } +} + +static void +egg_property_cell_renderer_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + } +} + +static void +egg_property_cell_renderer_class_init (EggPropertyCellRendererClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cellrenderer_class = GTK_CELL_RENDERER_CLASS (klass); + + gobject_class->set_property = egg_property_cell_renderer_set_property; + gobject_class->get_property = egg_property_cell_renderer_get_property; + gobject_class->dispose = egg_property_cell_renderer_dispose; + + cellrenderer_class->render = egg_property_cell_renderer_render; + cellrenderer_class->get_size = egg_property_cell_renderer_get_size; + cellrenderer_class->activate = egg_property_cell_renderer_activate; + cellrenderer_class->start_editing = egg_property_cell_renderer_start_editing; + + egg_property_cell_renderer_properties[PROP_PROP_NAME] = + g_param_spec_string("prop-name", + "Property name", "Property name", "", + G_PARAM_READWRITE); + + g_object_class_install_property(gobject_class, PROP_PROP_NAME, egg_property_cell_renderer_properties[PROP_PROP_NAME]); + + g_type_class_add_private (klass, sizeof (EggPropertyCellRendererPrivate)); +} + +static void +egg_property_cell_renderer_init (EggPropertyCellRenderer *renderer) +{ + EggPropertyCellRendererPrivate *priv; + + renderer->priv = priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); + + priv->text_renderer = gtk_cell_renderer_text_new (); + priv->spin_renderer = gtk_cell_renderer_spin_new (); + priv->toggle_renderer = gtk_cell_renderer_toggle_new (); + priv->combo_renderer = gtk_cell_renderer_combo_new (); + priv->renderer = priv->text_renderer; + priv->combo_models = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + + g_object_set (priv->text_renderer, + "editable", TRUE, + NULL); + + g_object_set (priv->spin_renderer, + "editable", TRUE, + NULL); + + g_object_set (priv->toggle_renderer, + "xalign", 0.0f, + "activatable", TRUE, + "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, + NULL); + + g_object_set (priv->combo_renderer, + "has-entry", FALSE, + NULL); + + g_signal_connect (priv->spin_renderer, "edited", + G_CALLBACK (egg_property_cell_renderer_spin_edited_cb), priv); + + g_signal_connect (priv->text_renderer, "edited", + G_CALLBACK (egg_property_cell_renderer_text_edited_cb), NULL); + + g_signal_connect (priv->toggle_renderer, "toggled", + G_CALLBACK (egg_property_cell_renderer_toggle_cb), priv); + + g_signal_connect (priv->combo_renderer, "changed", + G_CALLBACK (egg_property_cell_renderer_changed_cb), priv); +} diff --git a/tools/gui/egg-property-cell-renderer.h b/tools/gui/egg-property-cell-renderer.h new file mode 100644 index 0000000..d4dbe02 --- /dev/null +++ b/tools/gui/egg-property-cell-renderer.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef EGG_PROPERTY_CELL_RENDERER_H +#define EGG_PROPERTY_CELL_RENDERER_H + +#include + +G_BEGIN_DECLS + +#define EGG_TYPE_PROPERTY_CELL_RENDERER (egg_property_cell_renderer_get_type()) +#define EGG_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRenderer)) +#define EGG_IS_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER)) +#define EGG_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) +#define EGG_IS_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_CELL_RENDERER)) +#define EGG_PROPERTY_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) + +typedef struct _EggPropertyCellRenderer EggPropertyCellRenderer; +typedef struct _EggPropertyCellRendererClass EggPropertyCellRendererClass; +typedef struct _EggPropertyCellRendererPrivate EggPropertyCellRendererPrivate; + +struct _EggPropertyCellRenderer +{ + GtkCellRenderer parent_instance; + + /*< private >*/ + EggPropertyCellRendererPrivate *priv; +}; + +struct _EggPropertyCellRendererClass +{ + GtkCellRendererClass parent_class; +}; + +GType egg_property_cell_renderer_get_type (void); +GtkCellRenderer* egg_property_cell_renderer_new (GObject *object, + GtkListStore *list_store); + +G_END_DECLS + +#endif diff --git a/tools/gui/egg-property-tree-view.c b/tools/gui/egg-property-tree-view.c new file mode 100644 index 0000000..52d1e10 --- /dev/null +++ b/tools/gui/egg-property-tree-view.c @@ -0,0 +1,113 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + + +#include "egg-property-tree-view.h" +#include "egg-property-cell-renderer.h" + +G_DEFINE_TYPE (EggPropertyTreeView, egg_property_tree_view, GTK_TYPE_TREE_VIEW) + +#define EGG_PROPERTY_TREE_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewPrivate)) + +struct _EggPropertyTreeViewPrivate +{ + GtkListStore *list_store; +}; + +enum +{ + COLUMN_PROP_NAME, + COLUMN_PROP_ROW, + COLUMN_PROP_ADJUSTMENT, + N_COLUMNS +}; + +static void +egg_property_tree_view_populate_model_with_properties (GtkListStore *model, GObject *object) +{ + GParamSpec **pspecs; + GObjectClass *oclass; + guint n_properties; + GtkTreeIter iter; + + oclass = G_OBJECT_GET_CLASS (object); + pspecs = g_object_class_list_properties (oclass, &n_properties); + + for (guint i = 0; i < n_properties; i++) { + if (pspecs[i]->flags & G_PARAM_READABLE) { + GtkObject *adjustment; + + adjustment = gtk_adjustment_new (5, 0, 1000, 1, 10, 0); + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + COLUMN_PROP_NAME, pspecs[i]->name, + COLUMN_PROP_ROW, FALSE, + COLUMN_PROP_ADJUSTMENT, adjustment, + -1); + } + } + + g_free (pspecs); +} + +GtkWidget * +egg_property_tree_view_new (GObject *object) +{ + EggPropertyTreeView *property_tree_view; + GtkTreeView *tree_view; + GtkTreeViewColumn *prop_column, *value_column; + GtkCellRenderer *prop_renderer, *value_renderer; + GtkListStore *list_store; + + property_tree_view = EGG_PROPERTY_TREE_VIEW (g_object_new (EGG_TYPE_PROPERTY_TREE_VIEW, NULL)); + list_store = property_tree_view->priv->list_store; + tree_view = GTK_TREE_VIEW (property_tree_view); + + egg_property_tree_view_populate_model_with_properties (list_store, object); + gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store)); + + prop_renderer = gtk_cell_renderer_text_new (); + prop_column = gtk_tree_view_column_new_with_attributes ("Property", prop_renderer, + "text", COLUMN_PROP_NAME, + NULL); + + value_renderer = egg_property_cell_renderer_new (object, list_store); + value_column = gtk_tree_view_column_new_with_attributes ("Value", value_renderer, + "prop-name", COLUMN_PROP_NAME, + NULL); + + gtk_tree_view_append_column (tree_view, prop_column); + gtk_tree_view_append_column (tree_view, value_column); + + return GTK_WIDGET (tree_view); +} + +static void +egg_property_tree_view_class_init (EggPropertyTreeViewClass *klass) +{ + g_type_class_add_private (klass, sizeof (EggPropertyTreeViewPrivate)); +} + +static void +egg_property_tree_view_init (EggPropertyTreeView *tree_view) +{ + EggPropertyTreeViewPrivate *priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); + + tree_view->priv = priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); + priv->list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, GTK_TYPE_ADJUSTMENT); +} diff --git a/tools/gui/egg-property-tree-view.h b/tools/gui/egg-property-tree-view.h new file mode 100644 index 0000000..e8fd0fe --- /dev/null +++ b/tools/gui/egg-property-tree-view.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef EGG_PROPERTY_TREE_VIEW_H +#define EGG_PROPERTY_TREE_VIEW_H + +#include + +G_BEGIN_DECLS + +#define EGG_TYPE_PROPERTY_TREE_VIEW (egg_property_tree_view_get_type()) +#define EGG_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeView)) +#define EGG_IS_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_TREE_VIEW)) +#define EGG_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) +#define EGG_IS_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_TREE_VIEW)) +#define EGG_PROPERTY_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) + +typedef struct _EggPropertyTreeView EggPropertyTreeView; +typedef struct _EggPropertyTreeViewClass EggPropertyTreeViewClass; +typedef struct _EggPropertyTreeViewPrivate EggPropertyTreeViewPrivate; + +struct _EggPropertyTreeView +{ + GtkTreeView parent_instance; + + /*< private >*/ + EggPropertyTreeViewPrivate *priv; +}; + +struct _EggPropertyTreeViewClass +{ + GtkTreeViewClass parent_class; +}; + +GType egg_property_tree_view_get_type (void) G_GNUC_CONST; +GtkWidget* egg_property_tree_view_new (GObject *object); + +G_END_DECLS + +#endif diff --git a/tools/perf-overhead.c b/tools/perf-overhead.c new file mode 100644 index 0000000..f8bdcbd --- /dev/null +++ b/tools/perf-overhead.c @@ -0,0 +1,181 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include +#include +#include +#include +#include +#include "uca-plugin-manager.h" +#include "uca-camera.h" + +#define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ + __FILE__, __LINE__);} + +typedef struct { + guint counter; + gsize size; + gpointer destination; +} thread_data; + +static UcaCamera *camera = NULL; + +static void +sigint_handler (int signal) +{ + printf ("Closing down libuca\n"); + uca_camera_stop_recording (camera, NULL); + g_object_unref (camera); + exit (signal); +} + +static void +print_usage (void) +{ + GList *types; + UcaPluginManager *manager; + + manager = uca_plugin_manager_new (); + g_print ("Usage: benchmark [ "); + types = uca_plugin_manager_get_available_cameras (manager); + + if (types == NULL) { + g_print ("] -- no camera plugin found\n"); + return; + } + + for (GList *it = g_list_first (types); it != NULL; it = g_list_next (it)) { + gchar *name = (gchar *) it->data; + if (g_list_next (it) == NULL) + g_print ("%s ]\n", name); + else + g_print ("%s, ", name); + } +} + +static void +test_synchronous_operation (UcaCamera *camera) +{ + GError *error = NULL; + guint width, height, bits; + g_object_get (G_OBJECT (camera), + "sensor-width", &width, + "sensor-height", &height, + "sensor-bitdepth", &bits, + NULL); + + const int pixel_size = bits == 8 ? 1 : 2; + const gsize size = width * height * pixel_size; + const guint n_trials = 10000; + gpointer buffer = g_malloc0(size); + + uca_camera_start_recording (camera, &error); + GTimer *timer = g_timer_new (); + + for (guint n = 0; n < n_trials; n++) + uca_camera_grab (camera, &buffer, &error); + + gdouble total_time = g_timer_elapsed (timer, NULL); + g_timer_stop (timer); + + g_print ("Synchronous data transfer\n"); + g_print (" Bandwidth: %3.2f MB/s\n", size * n_trials / 1024. / 1024. / total_time); + g_print (" Throughput: %3.2f frames/s\n", n_trials / total_time); + + uca_camera_stop_recording (camera, &error); + g_free (buffer); + g_timer_destroy (timer); +} + +static void +grab_func (gpointer data, gpointer user_data) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + thread_data *d = (thread_data *) user_data; + g_memmove (d->destination, data, d->size); + g_static_mutex_lock (&mutex); + d->counter++; + g_static_mutex_unlock (&mutex); +} + +static void +test_asynchronous_operation (UcaCamera *camera) +{ + GError *error = NULL; + guint width, height, bits; + + g_object_get (G_OBJECT (camera), + "sensor-width", &width, + "sensor-height", &height, + "sensor-bitdepth", &bits, + NULL); + + const guint pixel_size = bits == 8 ? 1 : 2; + + thread_data d = { + .counter = 0, + .size = width * height * pixel_size, + .destination = g_malloc0(width * height * pixel_size) + }; + + g_object_set (G_OBJECT (camera), + "transfer-asynchronously", TRUE, + NULL); + + uca_camera_set_grab_func (camera, &grab_func, &d); + uca_camera_start_recording (camera, &error); + g_usleep (G_USEC_PER_SEC); + uca_camera_stop_recording (camera, &error); + + g_print ("Asynchronous data transfer\n"); + g_print (" Bandwidth: %3.2f MB/s\n", d.size * d.counter / 1024. / 1024.); + g_print (" Throughput: %i frames/s\n", d.counter); + + g_free (d.destination); +} + +int +main (int argc, char *argv[]) +{ + UcaPluginManager *manager; + GError *error = NULL; + (void) signal (SIGINT, sigint_handler); + + g_type_init (); + if (argc < 2) { + print_usage (); + return 1; + } + + manager = uca_plugin_manager_new (); + camera = uca_plugin_manager_new_camera (manager, argv[1], &error); + + if (camera == NULL) { + g_print ("Error during initialization: %s\n", error->message); + return 1; + } + + test_synchronous_operation (camera); + g_print ("\n"); + test_asynchronous_operation (camera); + + g_object_unref (camera); + g_object_unref (manager); + + return error != NULL ? 1 : 0; +} -- cgit v1.2.3