Author: post
Date: 2010-10-10 14:13:25 +0200 (Sun, 10 Oct 2010)
New Revision: 3546

Modified:
   trunk/src/rs-tethered-shooting.c
Log:
Tethered shooting: Add interval shooting, completely rewritten threading model 
and many bugs fixed.

Modified: trunk/src/rs-tethered-shooting.c
===================================================================
--- trunk/src/rs-tethered-shooting.c    2010-10-02 10:40:31 UTC (rev 3545)
+++ trunk/src/rs-tethered-shooting.c    2010-10-10 12:13:25 UTC (rev 3546)
@@ -41,6 +41,7 @@
 #endif
 #include "conf_interface.h"
 #include "gtk-helper.h"
+#include "rs-photo.h"
 
 enum
 {
@@ -49,6 +50,13 @@
   N_COLUMNS
 };
 
+enum 
+{
+       ASYNC_THREAD_TYPE_NONE,
+       ASYNC_THREAD_TYPE_MONITOR,
+       ASYNC_THREAD_TYPE_INTERVAL
+};
+
 typedef struct {
        Camera *camera;
        GPContext *context;
@@ -58,9 +66,11 @@
        GtkComboBox *camera_selector;
        GtkTextView *status_textview;
        RS_BLOB *rs;
-       GThread *monitor_thread_id;
-       GMutex *monitor_mutex;
-       gboolean keep_monitor_running;
+       GThread *async_thread_id;
+       gboolean keep_thread_running;
+       gint thread_type;
+       GtkWidget *interval_toggle_button;
+       gint interval_toggle_button_signal;
 } TetherInfo;
 
 typedef struct {
@@ -70,13 +80,15 @@
        const gchar *filename;
 } CAMERA_FILENAME;
 
-static void shutdown_monitor(TetherInfo *t);
+static void shutdown_async_thread(TetherInfo *t);
 static void closeconnection(TetherInfo *t);
+static void start_interval_shooting(GObject *entry, gpointer user_data);
 
 
 static void
 append_status_va_list(TetherInfo *t, const gchar *format, va_list args)
 {
+       gdk_threads_lock();
        gchar result_buffer[512];
        gint str_len = g_vsnprintf(result_buffer, 512, format, args);
        GtkTextIter iter;
@@ -94,6 +106,7 @@
                /* scroll to the end view */
                gtk_text_view_scroll_to_mark( GTK_TEXT_VIEW 
(t->status_textview), insert_mark, 0.0, TRUE, 0.0, 1.0); 
        }
+       gdk_threads_unlock();
 }
 
 static void
@@ -108,22 +121,25 @@
 static void
 ctx_error_func (GPContext *context, const char *format, va_list args, void 
*data)
 {
+       gdk_threads_lock();
        TetherInfo *t = (TetherInfo*)data;
        append_status (t, "*** Contexterror ***\n");
        append_status_va_list(t, format, args);
        append_status  (t, "\n");
-       shutdown_monitor(t);
-       if (t->camera)
-               closeconnection(t);
-
+       if (t->async_thread_id && t->async_thread_id != g_thread_self())
+               shutdown_async_thread(t);
+       t->keep_thread_running = FALSE;
+       gdk_threads_unlock();
 }
 
 static void
 ctx_status_func (GPContext *context, const char *format, va_list args, void 
*data)
 {
        TetherInfo *t = (TetherInfo*)data;
+       gdk_threads_lock();
        append_status_va_list(t, format, args);
        append_status  (t, "\n");
+       gdk_threads_unlock();
 }
 
 int
@@ -370,34 +386,37 @@
 }
 
 
-static void add_tags_to_photo(TetherInfo* t, const char* filename)
+static void add_tags_to_photo(TetherInfo* t, RS_PHOTO *photo)
 {
        const gchar* photo_tags = 
rs_conf_get_string("tether-tags-for-new-images");
 
        if (!photo_tags)
                return;
 
+       g_assert(photo != NULL);
+       g_assert(photo->metadata != NULL);
+
        RSLibrary *lib = rs_library_get_singleton();
-       if (t->rs->photo && t->rs->photo->metadata)
-               rs_library_add_photo_with_metadata(lib, filename, 
t->rs->photo->metadata);
-       else
-               return;
 
+       rs_library_add_photo_with_metadata(lib, photo->filename, 
photo->metadata);
+
        gchar** split_tags = g_strsplit_set(photo_tags, " .,/;:~^*|&",0);
        int i = 0;
        while (split_tags[i] != NULL)
        {
                rs_library_add_tag(lib, split_tags[i]);
-               rs_library_photo_add_tag(lib, filename, split_tags[i], FALSE);
+               rs_library_photo_add_tag(lib, photo->filename, split_tags[i], 
FALSE);
                i++;
        }
        g_strfreev(split_tags);
 }
 
 
-static void
+static RS_PHOTO*
 add_file_to_store(TetherInfo* t, const char* tmp_name) 
 {
+       RSMetadata *metadata;
+       RS_PHOTO *photo;
        gchar *lwd;
        gchar* org_template = rs_conf_get_string("tether-export-filename");
        lwd = rs_conf_get_string(CONF_LWD);
@@ -411,20 +430,37 @@
        GFile* src = g_file_new_for_path(tmp_name);
        GFile* dst = g_file_new_for_path(filename);
 
+       gdk_threads_unlock();
        if (!g_file_move(src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, 
NULL))
        {
+               gdk_threads_lock();
                append_status(t, "Moving file to current directory failed!\n");
-               return;
+               return NULL;
        }
        g_object_unref(src);
        g_object_unref(dst);
+       gdk_threads_lock();
 
        rs_store_set_iconview_size(t->rs->store, 
rs_store_get_iconview_size(t->rs->store)+1);
        rs_store_load_file(t->rs->store, filename);
-       if (!rs_store_set_selected_name(t->rs->store, filename, TRUE))
-               append_status(t, "Could not open image!\n");
-       else if (t->rs->photo)
-               add_tags_to_photo(t, filename);
+
+       photo = rs_photo_new();
+       photo->filename = g_strdup(filename);
+
+               /* Make sure we rotate this right */
+       gdk_threads_unlock();
+       metadata = rs_metadata_new_from_file(photo->filename);
+       add_tags_to_photo(t, photo);
+       gdk_threads_lock();
+
+       gboolean open_image = TRUE;
+       rs_conf_get_boolean_with_default("tether-open-image", &open_image, 
TRUE);
+       if (open_image)
+       {
+               if (!rs_store_set_selected_name(t->rs->store, filename, TRUE))
+                       append_status(t, "Could not open image!\n");
+       }
+       return photo;
 }
 
 #define RS_NUM_SETTINGS 3
@@ -440,7 +476,7 @@
        tmp_name_ptr = tmpnam(tmp_name);
 
        if (NULL == tmp_name_ptr)
-               return -1;
+               return GP_ERROR;
 
        char *extension = g_strrstr(camera_file_path->name, ".");
        tmp_name_ptr = g_strconcat(tmp_name_ptr, extension, NULL);
@@ -449,15 +485,17 @@
        if (fd == -1)
        {
                append_status(t,"Could not open temporary file on disk for 
writing");
-               return -1;
+               return GP_ERROR;
        }
 
+       gdk_threads_unlock();
        retval = gp_file_new_from_fd(&canonfile, fd);
        CHECKRETVAL(retval);
        retval = gp_camera_file_get(t->camera, camera_file_path->folder, 
camera_file_path->name, GP_FILE_TYPE_NORMAL, canonfile, t->context);
        CHECKRETVAL(retval);
        retval = gp_camera_file_delete(t->camera, camera_file_path->folder, 
camera_file_path->name, t->context);
        CHECKRETVAL(retval);
+       gdk_threads_lock();
 
        /* Copy settings */
        gboolean copy_settings = TRUE;
@@ -476,14 +514,17 @@
                copy_settings = FALSE;
 
        gp_file_free(canonfile);
-       add_file_to_store(t, tmp_name_ptr);
+       RS_PHOTO *photo = add_file_to_store(t, tmp_name_ptr);
 
+       if (!photo)
+               return GP_ERROR;
+
        /* Paste settings */
-       if (copy_settings && t->rs->photo)
+       if (copy_settings && photo)
        {
                for (i = 0; i < RS_NUM_SETTINGS; i++)
                {
-                       rs_settings_copy(settings_buffer[i], MASK_ALL, 
t->rs->photo->settings[i]);
+                       rs_settings_copy(settings_buffer[i], MASK_ALL, 
photo->settings[i]);
                        g_object_unref(settings_buffer[i]);
                }
        }
@@ -492,6 +533,7 @@
        if (minimize)
                gtk_window_iconify(GTK_WINDOW(t->window));
 
+       g_object_unref(photo);
        g_free(tmp_name_ptr);
        return GP_OK;
 }
@@ -508,49 +550,125 @@
        retval = gp_camera_capture(t->camera, GP_CAPTURE_IMAGE, 
&camera_file_path, t->context);
        CHECKRETVAL(retval);
        retval = transfer_file_captured(t, &camera_file_path);
-       return GP_OK;
+       return retval;
 }
 
+/* 
+ * Threads are purely synchronized by gdk_threads_lock/unlock
+ * Whenever they are idle, or doing heavy non-gui processing or IO, 
+ * the lock is released.
+*/
+
 gpointer
 start_thread_monitor(gpointer _thread_info)
 {
        TetherInfo *t = (TetherInfo*) _thread_info;
-       g_mutex_lock(t->monitor_mutex);
+       gdk_threads_enter();
        int retval;
-       while (t->keep_monitor_running)
+       while (t->keep_thread_running)
        {
                Camera *cam = t->camera;
                CameraEventType type;
                void * event_data = NULL;
-               g_mutex_unlock(t->monitor_mutex);
+               if (NULL == cam)
+               {
+                       t->keep_thread_running = FALSE;
+                       continue;
+               }
+               gdk_threads_leave();
                retval = gp_camera_wait_for_event(cam, 100, &type, &event_data, 
t->context);
-               g_mutex_lock(t->monitor_mutex);
+               gdk_threads_enter();
+
                if (retval < GP_OK)
                {
-                       gdk_threads_enter();
-                       append_status(t, "Monitor recieved error %d, while 
waiting for camera.\nError text is: %s", retval, gp_result_as_string(retval));
-                       gdk_threads_leave();
-                       t->keep_monitor_running = FALSE;
+                       append_status(t, "Monitor recieved error %d, while 
waiting for camera.\nError text is: %s\n", retval, gp_result_as_string(retval));
+                       t->keep_thread_running = FALSE;
                }
                else
                {
                        if (type == GP_EVENT_FILE_ADDED)
                        {
-                               gdk_threads_enter();
                                CameraFilePath* camera_file_path = 
(CameraFilePath*)event_data;
-                               transfer_file_captured(t, camera_file_path);
+                               retval = transfer_file_captured(t, 
camera_file_path);
+                               if (retval < GP_OK)
+                               {
+                                       append_status(t, "Recieved error %d, 
while downloading image from camera.\nError text is: %s\n", retval, 
gp_result_as_string(retval));
+                                       t->keep_thread_running = FALSE;
+                               }
+                               else
+                                       append_status(t, "File Downloaded 
Succesfully.\n");
+                       }
+               }
+       }
+       append_status(t, "Camera monitor shutting down.\n");
+       gdk_threads_leave();
+       t->thread_type = ASYNC_THREAD_TYPE_NONE;
+       return NULL;
+}
+
+gpointer
+start_thread_interval(gpointer _thread_info)
+{
+       TetherInfo *t = (TetherInfo*) _thread_info;
+       gdk_threads_enter();
+       int retval;
+       GTimer* capture_timer = g_timer_new();
+       while (t->keep_thread_running)
+       {
+               retval = capture_to_file(t);
+               if (retval < GP_OK)
+               {
+                       append_status(t, "Recieved error %d, while capturing 
image.\nError text is: %s\n", retval, gp_result_as_string(retval));
+                       t->keep_thread_running = FALSE;
+               }
+               if (t->keep_thread_running)
+               {
+                       gdouble interval = 10.0;
+                       rs_conf_get_double("tether-interval-interval", 
&interval);
+
+                       gboolean take_next = g_timer_elapsed(capture_timer, 
NULL) > interval;
+
+                       if (take_next)
+                               append_status(t, "Warning: It took longer time 
to capture the image than the set interval\nIt took %.1f seconds to download 
the image.\nConsider increasing the interval.\n", 
g_timer_elapsed(capture_timer, NULL) + 0.1);
+
+                       append_status(t, "Waiting for next image.\n");
+
+                       while (t->keep_thread_running && !take_next)
+                       {
+                               if (g_timer_elapsed(capture_timer, NULL) > 
interval)
+                                       take_next = TRUE;
+                               else
+                               {
+                                       gdk_threads_leave();
+                                       /* Sleep 100ms */
+                                       g_usleep(100*1000);
+                                       gdk_threads_enter();
+                               }
+                       }
+                       g_timer_reset(capture_timer);
+                       
+                       if (t->keep_thread_running)
+                       {
+                               GTK_CATCHUP();
                                gdk_threads_leave();
+                               /* Sleep 10ms, just to let GUI become 
responsive */
+                               g_usleep(10*1000);
+                               gdk_threads_enter();
                        }
                }
        }
-       t->keep_monitor_running = FALSE;
-       g_mutex_unlock(t->monitor_mutex);
+       g_signal_handler_disconnect(G_OBJECT(t->interval_toggle_button), 
t->interval_toggle_button_signal);
+       t->interval_toggle_button_signal =  
g_signal_connect(G_OBJECT(t->interval_toggle_button), "clicked", 
G_CALLBACK(start_interval_shooting), t);
+       gtk_button_set_label(GTK_BUTTON(t->interval_toggle_button), _("Start 
Shooting"));
+       append_status(t, "Interval shooting shutting down.\n");
+       gdk_threads_leave();
+       g_timer_destroy(capture_timer);
+       t->thread_type = ASYNC_THREAD_TYPE_NONE;
        return NULL;
 }
 
 static void closeconnection(TetherInfo *t)
 {
-       shutdown_monitor(t);
        if (!t->camera)
                return;
        append_status(t, "Disconnecting current camera\n");
@@ -609,20 +727,19 @@
        g_free(final);
 }
 
+/* When entering this, we must have gdk locked */
 static void
-shutdown_monitor(TetherInfo *t)
+shutdown_async_thread(TetherInfo *t)
 {
-       g_mutex_lock(t->monitor_mutex);
-       if (t->monitor_thread_id && t->keep_monitor_running)
+       if (t->async_thread_id && t->keep_thread_running)
        {
-               t->keep_monitor_running = FALSE;
-               g_mutex_unlock(t->monitor_mutex);
-               g_thread_join(t->monitor_thread_id);
-               t->monitor_thread_id = NULL;
-               append_status(t, "Monitor shut down\n");
+               t->keep_thread_running = FALSE;
+               gdk_threads_leave();
+               g_thread_join(t->async_thread_id);
+               gdk_threads_enter();
+               t->async_thread_id = NULL;
+               append_status(t, "Shutting down async thread\n");
        }
-       else 
-               g_mutex_unlock(t->monitor_mutex);
 }
 
 
@@ -630,6 +747,7 @@
 refresh_cameralist(GObject *entry, gpointer user_data)
 {
        TetherInfo *t = (TetherInfo*)user_data;
+       shutdown_async_thread(t);
        if (t->camera)
                closeconnection(t);
        gtk_list_store_clear(t->camera_store);
@@ -646,6 +764,7 @@
 connect_camera(GObject *entry, gpointer user_data)
 {
        TetherInfo *t = (TetherInfo*)user_data;
+       shutdown_async_thread(t);
        if (t->camera)
                closeconnection(t);
        GtkTreeIter iter;
@@ -659,18 +778,24 @@
 take_photo(GObject *entry, gpointer user_data)
 {
        TetherInfo *t = (TetherInfo*)user_data;
+       gint ret_val;
        if (!t->camera)
                connect_camera(entry, user_data);
        if (!t->camera)
                return;
 
-       if (t->keep_monitor_running)
+       if (t->keep_thread_running)
        {
-               append_status(t, "Shutting down monitor thread to enable remote 
capture.\n");
-               shutdown_monitor(t);
+               append_status(t, "Shutting down running thread to enable remote 
capture.\n");
+               shutdown_async_thread(t);
        }
 
-       capture_to_file(t);
+       ret_val = capture_to_file(t);
+       if (ret_val < GP_OK)
+       {
+               append_status(t, "Recieved error %d, while capturing 
image.\nError text is: %s\n", ret_val, gp_result_as_string(ret_val));
+               closeconnection(t);
+       }
 }
 
 static void
@@ -680,14 +805,18 @@
        rs_conf_set_string("tether-tags-for-new-images", tags);
 }
 
+static void
+spin_button_entry_changed(GtkEntry *entry, gpointer user_data)
+{
+       gdouble value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(entry));
+       rs_conf_set_double(user_data, value);
+}
 
 static void
 filename_entry_changed(GtkEntry *entry, gpointer user_data)
 {
        CAMERA_FILENAME *filename = (CAMERA_FILENAME *) user_data;
-
        filename->filename = gtk_entry_get_text(entry);
-
        update_example(filename);
 }
 
@@ -699,23 +828,29 @@
                connect_camera(entry, user_data);
        if (!t->camera)
                return;
-       g_mutex_lock(t->monitor_mutex);
-       if (!t->monitor_thread_id || !t->keep_monitor_running)
+
+       if ((t->async_thread_id || t->keep_thread_running) && t->thread_type != 
ASYNC_THREAD_TYPE_MONITOR)
        {
-               t->keep_monitor_running = TRUE;
+               append_status(t, "Shutting down already running thread.\n");
+               shutdown_async_thread(t);
+       }
+       if (!t->async_thread_id || !t->keep_thread_running)
+       {
+               t->keep_thread_running = TRUE;
                append_status(t, "Staring Monitor Thread.\n");
-               t->monitor_thread_id = g_thread_create(start_thread_monitor, t, 
TRUE, NULL);
+               t->thread_type = ASYNC_THREAD_TYPE_MONITOR;
+               t->async_thread_id = g_thread_create(start_thread_monitor, t, 
TRUE, NULL);
        }
        else
                append_status(t, "Monitor Thread already running.\n");
 
-       g_mutex_unlock(t->monitor_mutex);
 }
 
 static void
 close_main_window(GtkEntry *entry, gint response_id, gpointer user_data)
 {
        TetherInfo *t = (TetherInfo*)user_data;
+       shutdown_async_thread(t);
        if (t->camera)
                closeconnection(t);
        gp_context_unref(t->context);
@@ -723,6 +858,51 @@
 }
 
 static void 
+stop_interval_shooting(GObject *entry, gpointer user_data)
+{
+       TetherInfo *t = (TetherInfo*)user_data;
+       if (t->keep_thread_running && t->thread_type == 
ASYNC_THREAD_TYPE_INTERVAL)
+       {
+               append_status(t, "Shutting down interval capture thread.\n");
+               shutdown_async_thread(t);
+       }
+}
+
+static void 
+disconnect_camera_action(GObject *entry, gpointer user_data)
+{
+       TetherInfo *t = (TetherInfo*)user_data;
+       if (!t->camera)
+       {
+               append_status(t, "No camera connected.\n");
+               return;
+       }
+       shutdown_async_thread(t);
+       closeconnection(t);
+}
+
+static void 
+start_interval_shooting(GObject *entry, gpointer user_data)
+{
+       TetherInfo *t = (TetherInfo*)user_data;
+       if (!t->camera)
+               connect_camera(entry, user_data);
+       if (!t->camera)
+               return;
+       if (t->keep_thread_running)
+               shutdown_async_thread(t);
+
+       t->thread_type = ASYNC_THREAD_TYPE_INTERVAL;
+       t->keep_thread_running = TRUE;
+       append_status(t, "Staring Interval Shooting Thread.\n");
+       g_signal_handler_disconnect(G_OBJECT(t->interval_toggle_button), 
t->interval_toggle_button_signal);
+       t->interval_toggle_button_signal = 
g_signal_connect(G_OBJECT(t->interval_toggle_button), "clicked", 
G_CALLBACK(stop_interval_shooting), t);
+       gtk_button_set_label(GTK_BUTTON(t->interval_toggle_button), _("Stop 
Shooting"));
+       GTK_CATCHUP();
+       t->async_thread_id = g_thread_create(start_thread_interval, t, TRUE, 
NULL);
+}
+
+static void 
 build_tether_gui(TetherInfo *t)
 {
 
@@ -743,6 +923,7 @@
        GtkWidget *status_window;
        GtkWidget *status_textview;
        GtkWidget *tags_entry;
+       GtkWidget *number_spin;
 
        /* A box to hold everything */
        GtkBox *main_box = GTK_BOX(gtk_vbox_new (FALSE, 7));
@@ -772,15 +953,15 @@
        g_signal_connect(G_OBJECT(button), "clicked", 
G_CALLBACK(refresh_cameralist), t);
        gtk_box_pack_start(h_box, button, FALSE, FALSE, 1);
 
-       button = gtk_button_new_from_stock(GTK_STOCK_CONNECT);
-       g_signal_connect(G_OBJECT(button), "clicked", 
G_CALLBACK(connect_camera), t);
-       gtk_box_pack_start(h_box, button, FALSE, FALSE, 1);
-
        /* Add this box */
        gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 5);
 
        /* "Take photo" & Monitor button */
        h_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
+       button = gtk_button_new_from_stock(GTK_STOCK_CONNECT);
+       g_signal_connect(G_OBJECT(button), "clicked", 
G_CALLBACK(connect_camera), t);
+       gtk_box_pack_start(h_box, button, FALSE, FALSE, 1);
+
        button = gtk_button_new_with_label(_("Take Photo"));
        g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(take_photo), 
t);
        gtk_button_set_alignment (GTK_BUTTON(button), 0.0, 0.5);
@@ -791,6 +972,11 @@
        gtk_button_set_alignment (GTK_BUTTON(button), 0.0, 0.5);
        gtk_box_pack_start(h_box, button, FALSE, FALSE, 5);
 
+       button = gtk_button_new_with_label(_("Disconnect Camera"));
+       g_signal_connect(G_OBJECT(button), "clicked", 
G_CALLBACK(disconnect_camera_action), t);
+       gtk_button_set_alignment (GTK_BUTTON(button), 0.0, 0.5);
+       gtk_box_pack_start(h_box, button, FALSE, FALSE, 5);
+
        /* Add this box */
        gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 5);
 
@@ -857,6 +1043,33 @@
        /* Add filename& tags box */
        gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Filename &amp; Tags"), 
GTK_WIDGET(box), "tether_filename_tags", TRUE), FALSE, FALSE, 0);
 
+       /* INTERVAL SHOOTING */
+       box = GTK_BOX(gtk_vbox_new (FALSE, 2));
+
+       h_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
+
+       button = gtk_button_new_with_label(_("Start Shooting"));
+       t->interval_toggle_button_signal = g_signal_connect(G_OBJECT(button), 
"clicked", G_CALLBACK(start_interval_shooting), t);
+       gtk_button_set_alignment (GTK_BUTTON(button), 0.0, 0.5);
+       gtk_box_pack_start(h_box, button, FALSE, FALSE, 5);
+       t->interval_toggle_button = button;
+       gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 3);
+
+       label = gtk_label_new(_("Seconds between each shot:"));
+       gtk_box_pack_start(h_box, label, FALSE, FALSE, 4);
+       number_spin = gtk_spin_button_new_with_range(1.0, 24.0*60*60, 0.2);
+       gdouble interval = 10.0;
+       rs_conf_get_double("tether-interval-interval", &interval);
+       gtk_spin_button_set_value (GTK_SPIN_BUTTON(number_spin), interval);
+       g_signal_connect(number_spin, "changed", 
G_CALLBACK(spin_button_entry_changed), "tether-interval-interval");
+       gtk_box_pack_start(h_box, number_spin, FALSE, FALSE, 3);
+       gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 3);
+
+
+       /* Add interval shooting box */
+       gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Interval Shooting"), 
GTK_WIDGET(box), "tether_interval_shooting_box", TRUE), FALSE, FALSE, 0);
+
+
        /* PREFERENCES */
        box = GTK_BOX(gtk_vbox_new (FALSE, 5));
 
@@ -868,9 +1081,14 @@
        check_button = checkbox_from_conf("tether-copy-current-settings", 
_("Copy settings from active to new image"), FALSE);
        gtk_button_set_alignment (GTK_BUTTON(check_button), 0.0, 0.5);
        gtk_box_pack_start(h_box, check_button, FALSE, FALSE, 5);
-       
        gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 5);
 
+       h_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
+       check_button = checkbox_from_conf("tether-open-image", _("Open new 
images after capture"), TRUE);
+       gtk_button_set_alignment (GTK_BUTTON(check_button), 0.0, 0.5);
+       gtk_box_pack_start(h_box, check_button, FALSE, FALSE, 3);
+       gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 5);
+
        /* Add preferences box */
        gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Preferences"), 
GTK_WIDGET(box), "tether_preferences", TRUE), FALSE, FALSE, 0);
 
@@ -906,8 +1124,9 @@
        tether_info->window = window;
        tether_info->rs = rs;
        tether_info->status_buffer = gtk_text_buffer_new(NULL);
-       tether_info->monitor_mutex = g_mutex_new ();
-       tether_info->keep_monitor_running = FALSE;
+       tether_info->keep_thread_running = FALSE;
+       tether_info->thread_type = ASYNC_THREAD_TYPE_NONE;
+
        gtk_text_buffer_set_text(tether_info->status_buffer,_("Welcome to 
Tethered shooting!\nMake sure your camera is NOT mounted in your operating 
system.\n"),-1);
        g_signal_connect(window, "response", G_CALLBACK(close_main_window), 
tether_info);
 


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to