diff options
author | Matthias Vogelgesang <matthias.vogelgesang@gmail.com> | 2013-04-11 08:53:29 +0200 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@gmail.com> | 2013-04-11 08:54:12 +0200 |
commit | 06d5b3438f682307db06074ce9709b949a9aa846 (patch) | |
tree | 99dbeeab1eeab0d890ad1a32842ffb3540c782c5 /gui/control.c | |
parent | 1cb1a541bedd4e17085ab8ce04d0f5b2fc4d8d1d (diff) | |
download | uca-06d5b3438f682307db06074ce9709b949a9aa846.tar.gz uca-06d5b3438f682307db06074ce9709b949a9aa846.tar.bz2 uca-06d5b3438f682307db06074ce9709b949a9aa846.tar.xz uca-06d5b3438f682307db06074ce9709b949a9aa846.zip |
Move binaries to bin and make ring buffer a lib
Diffstat (limited to 'gui/control.c')
-rw-r--r-- | gui/control.c | 662 |
1 files changed, 0 insertions, 662 deletions
diff --git a/gui/control.c b/gui/control.c deleted file mode 100644 index c177f07..0000000 --- a/gui/control.c +++ /dev/null @@ -1,662 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (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 <glib/gprintf.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#include <math.h> - -#include "config.h" -#include "ring-buffer.h" -#include "uca-camera.h" -#include "uca-plugin-manager.h" -#include "egg-property-tree-view.h" -#include "egg-histogram-view.h" - -typedef enum { - IDLE, - RUNNING, - RECORDING -} State; - -typedef struct { - UcaCamera *camera; - GtkWidget *main_window; - GdkPixbuf *pixbuf; - GtkWidget *image; - GtkWidget *start_button; - GtkWidget *stop_button; - GtkWidget *record_button; - GtkWidget *download_button; - GtkComboBox *zoom_box; - - GtkDialog *download_dialog; - GtkProgressBar *download_progressbar; - GtkWidget *download_close_button; - GtkAdjustment *download_adjustment; - - GtkWidget *histogram_view; - GtkToggleButton *histogram_button; - GtkAdjustment *frame_slider; - - RingBuffer *buffer; - guchar *pixels; - gint display_width, display_height; - gdouble zoom_factor; - State state; - gboolean data_in_camram; - - gint timestamp; - gint width, height; - gint pixel_size; -} ThreadData; - -static UcaPluginManager *plugin_manager; -static gsize mem_size = 2048; - -static void -convert_grayscale_to_rgb (ThreadData *data, gpointer buffer) -{ - gdouble min; - gdouble max; - gdouble factor; - guint8 *output; - gint i = 0; - gint stride; - - egg_histogram_get_visible_range (EGG_HISTOGRAM_VIEW (data->histogram_view), &min, &max); - factor = 255.0 / (max - min); - output = data->pixels; - stride = (gint) 1 / data->zoom_factor; - - if (data->pixel_size == 1) { - guint8 *input = (guint8 *) buffer; - - for (gint y = 0; y < data->display_height; y++) { - gint offset = y * stride * data->width; - - for (gint x = 0; x < data->display_width; x++, offset += stride) { - gdouble dval = (input[offset] - min) * factor; - guchar val = (guchar) CLAMP(dval, 0.0, 255.0); - - output[i++] = val; - output[i++] = val; - output[i++] = val; - } - } - } - else if (data->pixel_size == 2) { - guint16 *input = (guint16 *) buffer; - - for (gint y = 0; y < data->display_height; y++) { - gint offset = y * stride * data->width; - - for (gint x = 0; x < data->display_width; x++, offset += stride) { - gdouble dval = (input[offset] - min) * factor; - guchar val = (guchar) CLAMP(dval, 0.0, 255.0); - - output[i++] = val; - output[i++] = val; - output[i++] = val; - } - } - } -} - -static void -update_pixbuf (ThreadData *data) -{ - gdk_flush (); - gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); - gtk_widget_queue_draw_area (data->image, 0, 0, data->display_width, data->display_height); - - if (gtk_toggle_button_get_active (data->histogram_button)) - gtk_widget_queue_draw (data->histogram_view); -} - -static void -update_pixbuf_dimensions (ThreadData *data) -{ - if (data->pixbuf != NULL) - g_object_unref (data->pixbuf); - - data->display_width = (gint) data->width * data->zoom_factor; - data->display_height = (gint) data->height * data->zoom_factor; - data->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, data->display_width, data->display_height); - data->pixels = gdk_pixbuf_get_pixels (data->pixbuf); - gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), data->pixbuf); -} - -static void -print_and_free_error (GError **error) -{ - g_printerr ("%s\n", (*error)->message); - g_error_free (*error); - *error = NULL; -} - -static gpointer -preview_frames (void *args) -{ - ThreadData *data = (ThreadData *) args; - gint counter = 0; - GError *error = NULL;; - - while (data->state == RUNNING) { - gpointer buffer; - - buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_trigger (data->camera, &error); - uca_camera_grab (data->camera, buffer, &error); - - if (error == NULL) { - convert_grayscale_to_rgb (data, buffer); - - gdk_threads_enter (); - update_pixbuf (data); - gdk_threads_leave (); - - counter++; - } - else - print_and_free_error (&error); - } - return NULL; -} - -static gpointer -record_frames (gpointer args) -{ - ThreadData *data; - gpointer buffer; - guint n_frames = 0; - GError *error = NULL; - - data = (ThreadData *) args; - ring_buffer_reset (data->buffer); - - while (data->state == RECORDING) { - buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_grab (data->camera, buffer, NULL); - - if (error == NULL) { - ring_buffer_proceed (data->buffer); - n_frames++; - } - else - print_and_free_error (&error); - } - - n_frames = ring_buffer_get_num_blocks (data->buffer); - - gdk_threads_enter (); - gtk_adjustment_set_upper (data->frame_slider, n_frames - 1); - gtk_adjustment_set_value (data->frame_slider, n_frames - 1); - gdk_threads_leave (); - - return NULL; -} - -gboolean -on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - return FALSE; -} - -void -on_destroy (GtkWidget *widget, ThreadData *data) -{ - data->state = IDLE; - g_object_unref (data->camera); - ring_buffer_free (data->buffer); - - gtk_main_quit (); -} - -static void -set_tool_button_state (ThreadData *data) -{ - gtk_widget_set_sensitive (data->start_button, - data->state == IDLE); - gtk_widget_set_sensitive (data->stop_button, - data->state == RUNNING || data->state == RECORDING); - gtk_widget_set_sensitive (data->record_button, - data->state == IDLE); - gtk_widget_set_sensitive (data->download_button, - data->data_in_camram); - gtk_widget_set_sensitive (GTK_WIDGET (data->zoom_box), - data->state == IDLE); -} - -static void -update_current_frame (ThreadData *data) -{ - gpointer buffer; - gint index; - - index = (gint) gtk_adjustment_get_value (data->frame_slider); - buffer = ring_buffer_get_pointer (data->buffer, index); - convert_grayscale_to_rgb (data, buffer); - update_pixbuf (data); -} - -static void -on_frame_slider_changed (GtkAdjustment *adjustment, ThreadData *data) -{ - if (data->state == IDLE) - update_current_frame (data); -} - -static void -on_start_button_clicked (GtkWidget *widget, ThreadData *data) -{ - GError *error = NULL; - - uca_camera_start_recording (data->camera, &error); - - if (error != NULL) { - g_printerr ("Failed to start recording: %s\n", error->message); - return; - } - - data->state = RUNNING; - set_tool_button_state (data); - - if (!g_thread_create (preview_frames, data, FALSE, &error)) { - g_printerr ("Failed to create thread: %s\n", error->message); - data->state = IDLE; - set_tool_button_state (data); - } -} - -static void -on_stop_button_clicked (GtkWidget *widget, ThreadData *data) -{ - GError *error = NULL; - - g_object_get (data->camera, "has-camram-recording", &data->data_in_camram, NULL); - data->state = IDLE; - set_tool_button_state (data); - uca_camera_stop_recording (data->camera, &error); - - if (error != NULL) - g_printerr ("Failed to stop: %s\n", error->message); - -} - -static void -on_record_button_clicked (GtkWidget *widget, ThreadData *data) -{ - GError *error = NULL; - - uca_camera_start_recording (data->camera, &error); - - if (error != NULL) { - g_printerr ("Failed to start recording: %s\n", error->message); - } - - data->timestamp = (int) time (0); - data->state = RECORDING; - set_tool_button_state (data); - - if (!g_thread_create (record_frames, data, FALSE, &error)) { - g_printerr ("Failed to create thread: %s\n", error->message); - data->state = IDLE; - set_tool_button_state (data); - } -} - -static gpointer -download_frames (ThreadData *data) -{ - gpointer buffer; - guint n_frames; - guint current_frame = 1; - GError *error = NULL; - - g_object_get (data->camera, "recorded-frames", &n_frames, NULL); - gdk_threads_enter (); - gtk_widget_set_sensitive (data->download_close_button, FALSE); - gtk_adjustment_set_upper (data->download_adjustment, n_frames); - gdk_threads_leave (); - - uca_camera_start_readout (data->camera, &error); - - if (error != NULL) { - g_printerr ("Failed to start read out of camera memory: %s\n", error->message); - return NULL; - } - - ring_buffer_reset (data->buffer); - - while (error == NULL) { - buffer = ring_buffer_get_current_pointer (data->buffer); - uca_camera_grab (data->camera, buffer, &error); - ring_buffer_proceed (data->buffer); - gdk_threads_enter (); - gtk_adjustment_set_value (data->download_adjustment, current_frame++); - gdk_threads_leave (); - } - - if (error->code == UCA_CAMERA_ERROR_END_OF_STREAM) { - guint n_frames = ring_buffer_get_num_blocks (data->buffer); - - gtk_adjustment_set_upper (data->frame_slider, n_frames - 1); - gtk_adjustment_set_value (data->frame_slider, n_frames - 1); - } - else - g_printerr ("Error while reading out frames: %s\n", error->message); - - g_error_free (error); - error = NULL; - - uca_camera_stop_readout (data->camera, &error); - - if (error != NULL) - g_printerr ("Failed to stop reading out of camera memory: %s\n", error->message); - - gdk_threads_enter (); - gtk_widget_set_sensitive (data->download_close_button, TRUE); - gdk_threads_leave (); - - return NULL; -} - -static void -on_download_button_clicked (GtkWidget *widget, ThreadData *data) -{ - GError *error = NULL; - - if (!g_thread_create ((GThreadFunc) download_frames, data, FALSE, &error)) { - g_printerr ("Failed to create thread: %s\n", error->message); - } - - gtk_widget_set_sensitive (data->main_window, FALSE); - gtk_window_set_modal (GTK_WINDOW (data->download_dialog), TRUE); - gtk_dialog_run (data->download_dialog); - gtk_widget_hide (GTK_WIDGET (data->download_dialog)); - gtk_window_set_modal (GTK_WINDOW (data->download_dialog), FALSE); - gtk_widget_set_sensitive (data->main_window, TRUE); - gtk_window_set_modal (GTK_WINDOW (data->download_dialog), TRUE); -} - -static void -on_histogram_changed (EggHistogramView *view, ThreadData *data) -{ - if (data->state == IDLE) - update_current_frame (data); -} - -static void -on_zoom_changed (GtkComboBox *widget, ThreadData *data) -{ - GtkTreeModel *model; - GtkTreeIter iter; - gdouble factor; - - enum { - DISPLAY_COLUMN, - FACTOR_COLUMN - }; - - model = gtk_combo_box_get_model (widget); - gtk_combo_box_get_active_iter (widget, &iter); - gtk_tree_model_get (model, &iter, FACTOR_COLUMN, &factor, -1); - - data->zoom_factor = factor; - update_pixbuf_dimensions (data); -} - -static void -on_roi_width_changed (GObject *object, GParamSpec *pspec, ThreadData *data) -{ - g_object_get (object, "roi-width", &data->width, NULL); - update_pixbuf_dimensions (data); -} - -static void -on_roi_height_changed (GObject *object, GParamSpec *pspec, ThreadData *data) -{ - g_object_get (object, "roi-height", &data->height, NULL); - update_pixbuf_dimensions (data); -} - -static void -create_main_window (GtkBuilder *builder, const gchar* camera_name) -{ - static ThreadData td; - UcaCamera *camera; - GtkWidget *window; - GtkWidget *image; - GtkWidget *histogram_view; - GtkWidget *property_tree_view; - GdkPixbuf *pixbuf; - GtkBox *histogram_box; - GtkContainer *property_window; - GtkAdjustment *max_bin_adjustment; - RingBuffer *ring_buffer; - gsize image_size; - guint n_frames; - guint bits_per_sample; - guint pixel_size; - guint width, height; - GError *error = NULL; - - camera = uca_plugin_manager_get_camera (plugin_manager, camera_name, &error, NULL); - - if ((camera == NULL) || (error != NULL)) { - g_error ("%s\n", error->message); - gtk_main_quit (); - } - - g_object_get (camera, - "roi-width", &width, - "roi-height", &height, - "sensor-bitdepth", &bits_per_sample, - NULL); - - g_signal_connect (camera, "notify::roi-width", (GCallback) on_roi_width_changed, &td); - g_signal_connect (camera, "notify::roi-height", (GCallback) on_roi_height_changed, &td); - - histogram_view = egg_histogram_view_new (); - property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); - property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "property-window")); - image = GTK_WIDGET (gtk_builder_get_object (builder, "image")); - histogram_box = GTK_BOX (gtk_builder_get_object (builder, "histogram-box")); - window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); - max_bin_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "max-bin-value-adjustment")); - - td.zoom_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "zoom-box")); - td.start_button = GTK_WIDGET (gtk_builder_get_object (builder, "start-button")); - td.stop_button = GTK_WIDGET (gtk_builder_get_object (builder, "stop-button")); - td.record_button = GTK_WIDGET (gtk_builder_get_object (builder, "record-button")); - td.download_button = GTK_WIDGET (gtk_builder_get_object (builder, "download-button")); - td.histogram_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "histogram-checkbutton")); - td.frame_slider = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "frames-adjustment")); - - td.download_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "download-dialog")); - td.download_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "download-adjustment")); - td.download_close_button = GTK_WIDGET (gtk_builder_get_object (builder, "download-close-button")); - - /* Set initial data */ - pixel_size = bits_per_sample > 8 ? 2 : 1; - image_size = pixel_size * width * height; - n_frames = mem_size * 1024 * 1024 / image_size; - ring_buffer = ring_buffer_new (image_size, n_frames); - - egg_histogram_view_set_data (EGG_HISTOGRAM_VIEW (histogram_view), - ring_buffer_get_current_pointer (ring_buffer), - width * height, bits_per_sample, 256); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); - gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); - - gtk_adjustment_set_value (max_bin_adjustment, pow (2, bits_per_sample) - 1); - - g_message ("Allocated memory for %d frames", n_frames); - - td.pixel_size = pixel_size; - td.image = image; - td.pixbuf = NULL; - td.pixels = NULL; - td.buffer = ring_buffer; - td.state = IDLE; - td.camera = camera; - td.width = td.display_width = width; - td.height = td.display_height = height; - td.zoom_factor = 1.0; - td.histogram_view = histogram_view; - td.data_in_camram = FALSE; - td.main_window = window; - - update_pixbuf_dimensions (&td); - set_tool_button_state (&td); - - /* Hook up signals */ - g_object_bind_property (gtk_builder_get_object (builder, "min-bin-value-adjustment"), "value", - td.histogram_view, "minimum-bin-value", - G_BINDING_DEFAULT); - - g_object_bind_property (max_bin_adjustment, "value", - td.histogram_view, "maximum-bin-value", - G_BINDING_DEFAULT); - - g_signal_connect (td.frame_slider, "value-changed", G_CALLBACK (on_frame_slider_changed), &td); - g_signal_connect (td.start_button, "clicked", G_CALLBACK (on_start_button_clicked), &td); - g_signal_connect (td.stop_button, "clicked", G_CALLBACK (on_stop_button_clicked), &td); - g_signal_connect (td.record_button, "clicked", G_CALLBACK (on_record_button_clicked), &td); - g_signal_connect (td.download_button, "clicked", G_CALLBACK (on_download_button_clicked), &td); - g_signal_connect (td.zoom_box, "changed", G_CALLBACK (on_zoom_changed), &td); - g_signal_connect (histogram_view, "changed", G_CALLBACK (on_histogram_changed), &td); - g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), &td); - - /* Layout */ - gtk_container_add (property_window, property_tree_view); - gtk_box_pack_start (histogram_box, td.histogram_view, TRUE, TRUE, 6); - - gtk_widget_show_all (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, "proceed-button")); - 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[]) -{ - GtkBuilder *builder; - GOptionContext *context; - GError *error = NULL; - - static GOptionEntry entries[] = - { - { "mem-size", 'm', 0, G_OPTION_ARG_INT, &mem_size, "Memory in megabytes to allocate for frame storage", "M" }, - { NULL } - }; - - context = g_option_context_new ("- control libuca cameras"); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_add_group (context, gtk_get_option_group (TRUE)); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_print ("Option parsing failed: %s\n", error->message); - return 1; - } - - g_thread_init (NULL); - gdk_threads_init (); - gtk_init (&argc, &argv); - - builder = gtk_builder_new (); - - if (!gtk_builder_add_from_file (builder, CONTROL_GLADE_PATH, &error)) { - g_print ("Could not load UI file: %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; -} |