summaryrefslogtreecommitdiffstats
path: root/gui/control.c
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@gmail.com>2013-04-11 08:53:29 +0200
committerMatthias Vogelgesang <matthias.vogelgesang@gmail.com>2013-04-11 08:54:12 +0200
commit06d5b3438f682307db06074ce9709b949a9aa846 (patch)
tree99dbeeab1eeab0d890ad1a32842ffb3540c782c5 /gui/control.c
parent1cb1a541bedd4e17085ab8ce04d0f5b2fc4d8d1d (diff)
downloaduca-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.c662
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;
-}