Author: post
Date: 2010-09-12 14:02:12 +0200 (Sun, 12 Sep 2010)
New Revision: 3524
Modified:
trunk/src/Makefile.am
trunk/src/rs-actions.c
trunk/src/rs-tethered-shooting.c
trunk/src/ui.xml
Log:
- Add "monitor" mode to tethered shooting, that will monitor your camera and
download any image you shoot.
- Tethered Shooting ENABLED in menu.
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2010-09-11 23:23:04 UTC (rev 3523)
+++ trunk/src/Makefile.am 2010-09-12 12:02:12 UTC (rev 3524)
@@ -45,7 +45,8 @@
rs-pixbuf.c rs-pixbuf.h \
rs-external-editor.c rs-external-editor.h \
rs-dir-selector.c rs-dir-selector.h \
- rs-library.c rs-library.h
+ rs-library.c rs-library.h\
+ rs-tethered-shooting.c rs-tethered-shooting.h
rawstudio_LDADD = ../librawstudio/librawstud...@[email protected] @PACKAGE_LIBS@
@LIBJPEG@ @LIBTIFF@ $(INTLLIBS)
Modified: trunk/src/rs-actions.c
===================================================================
--- trunk/src/rs-actions.c 2010-09-11 23:23:04 UTC (rev 3523)
+++ trunk/src/rs-actions.c 2010-09-12 12:02:12 UTC (rev 3524)
@@ -40,6 +40,7 @@
#include "rs-lens-db-editor.h"
#include "rs-camera-db.h"
#include "rs-toolbox.h"
+#include "rs-tethered-shooting.h"
static GtkActionGroup *core_action_group = NULL;
static GStaticMutex rs_actions_spinlock = G_STATIC_MUTEX_INIT;
@@ -1015,6 +1016,11 @@
rs_lens_db_editor();
}
+ACTION(tethered_shooting)
+{
+ rs_tethered_shooting_open(rs);
+}
+
ACTION(filter_graph)
{
rs_filter_graph(rs->filter_input);
@@ -1183,7 +1189,8 @@
{ "PreviousPhoto", GTK_STOCK_GO_BACK, _("_Previous photo"),
"<control>Left", NULL, ACTION_CB(previous_photo) },
{ "NextPhoto", GTK_STOCK_GO_FORWARD, _("_Next Photo"),
"<control>Right", NULL, ACTION_CB(next_photo) },
{ "LensDbEditor", NULL, _("_Lens Library"), "<control>L", NULL,
ACTION_CB(lens_db_editor) },
-
+ { "TetheredShooting", NULL, _("_Tethered Shooting"), NULL, NULL,
ACTION_CB(tethered_shooting) },
+
/* Batch menu */
{ "AddToBatch", GTK_STOCK_ADD, _("_Add to batch queue"), "<control>B",
NULL, ACTION_CB(add_to_batch) },
{ "AddViewToBatch", NULL, _("_Add current view to queue"), NULL, NULL,
ACTION_CB(add_view_to_batch) },
Modified: trunk/src/rs-tethered-shooting.c
===================================================================
--- trunk/src/rs-tethered-shooting.c 2010-09-11 23:23:04 UTC (rev 3523)
+++ trunk/src/rs-tethered-shooting.c 2010-09-12 12:02:12 UTC (rev 3524)
@@ -57,7 +57,9 @@
GtkComboBox *camera_selector;
GtkTextView *status_textview;
RS_BLOB *rs;
-
+ GThread *monitor_thread_id;
+ GMutex *monitor_mutex;
+ gboolean keep_monitor_running;
} TetherInfo;
typedef struct {
@@ -67,6 +69,8 @@
const gchar *filename;
} CAMERA_FILENAME;
+static void shutdown_monitor(TetherInfo *t);
+static void closeconnection(TetherInfo *t);
static void
@@ -79,7 +83,16 @@
gtk_text_buffer_insert(t->status_buffer, &iter, result_buffer, str_len);
gtk_text_buffer_get_end_iter(t->status_buffer, &iter);
if (t->status_textview)
- gtk_text_view_scroll_to_iter(t->status_textview, &iter,0.0,
FALSE, 0.0, 0.0);
+ {
+ /* get the current ( cursor )mark name */
+ GtkTextMark* insert_mark = gtk_text_buffer_get_insert
(t->status_buffer);
+
+ /* move mark and selection bound to the end */
+ gtk_text_buffer_place_cursor(t->status_buffer, &iter);
+
+ /* 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);
+ }
}
static void
@@ -98,6 +111,10 @@
append_status (t, "*** Contexterror ***\n");
append_status_va_list(t, format, args);
append_status (t, "\n");
+ shutdown_monitor(t);
+ if (t->camera)
+ closeconnection(t);
+
}
static void
@@ -236,8 +253,12 @@
#define CHECKRETVAL(A) if (A < GP_OK) {\
append_status(t, "ERROR: Gphoto2 returned error value %d\nTranslated
error message is: %s\n", A, gp_result_as_string(A));\
+ gp_camera_free (t->camera);\
+ t->camera = NULL;\
return A;}
+gpointer start_thread_monitor(gpointer _thread_info);
+
static int
enable_capture(TetherInfo *t)
{
@@ -293,7 +314,10 @@
printf("Enabling capture.\n");
retval = gp_camera_set_config(t->camera, actualrootconfig, t->context);
CHECKRETVAL(retval);
+
+ printf("Capture Enabled.\n");
append_status(t, "Capture Enabled.\n");
+
return GP_OK;
}
@@ -379,32 +403,19 @@
}
static gint
-capture_to_file(TetherInfo* t)
+transfer_file_captured(TetherInfo* t, CameraFilePath* camera_file_path)
{
+ CameraFile *canonfile;
int fd, retval;
- CameraFile *canonfile;
- CameraFilePath camera_file_path;
-
- /* Generate a temporary name */
- /* The reason for using a temporary file is that we need to read the */
- /* metadata before we can generate a filename */
+ append_status(t,"Downloading and adding image.\n");
char tmp_name[L_tmpnam];
char *tmp_name_ptr;
tmp_name_ptr = tmpnam(tmp_name);
-
+
if (NULL == tmp_name_ptr)
return -1;
- append_status(t, "Capturing.\n");
-
- /* NOP: This gets overridden in the library to /capt0000.jpg */
- strcpy(camera_file_path.folder, "/");
- strcpy(camera_file_path.name, "foo.jpg");
-
- retval = gp_camera_capture(t->camera, GP_CAPTURE_IMAGE,
&camera_file_path, t->context);
- CHECKRETVAL(retval);
-
- gchar *extension = g_strrstr(camera_file_path.name, ".");
+ char *extension = g_strrstr(camera_file_path->name, ".");
tmp_name_ptr = g_strconcat(tmp_name_ptr, extension, NULL);
fd = open(tmp_name_ptr, O_CREAT | O_WRONLY, 0644);
@@ -416,11 +427,9 @@
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);
+ 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);
+ retval = gp_camera_file_delete(t->camera, camera_file_path->folder,
camera_file_path->name, t->context);
CHECKRETVAL(retval);
gp_file_free(canonfile);
@@ -430,9 +439,59 @@
return GP_OK;
}
+static gint
+capture_to_file(TetherInfo* t)
+{
+ int retval;
+ CameraFilePath camera_file_path;
+ append_status(t, "Capturing.\n");
+ 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;
+}
+
+gpointer
+start_thread_monitor(gpointer _thread_info)
+{
+ TetherInfo *t = (TetherInfo*) _thread_info;
+ g_mutex_lock(t->monitor_mutex);
+ int retval;
+ while (t->keep_monitor_running)
+ {
+ Camera *cam = t->camera;
+ CameraEventType type;
+ void * event_data = NULL;
+ g_mutex_unlock(t->monitor_mutex);
+ retval = gp_camera_wait_for_event(cam, 100, &type, &event_data,
t->context);
+ g_mutex_lock(t->monitor_mutex);
+ 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;
+ }
+ else
+ {
+ if (type == GP_EVENT_FILE_ADDED)
+ {
+ gdk_threads_enter();
+ CameraFilePath* camera_file_path =
(CameraFilePath*)event_data;
+ transfer_file_captured(t, camera_file_path);
+ gdk_threads_leave();
+ }
+ }
+ }
+ t->keep_monitor_running = FALSE;
+ g_mutex_unlock(t->monitor_mutex);
+ return NULL;
+}
+
static void closeconnection(TetherInfo *t)
{
+ shutdown_monitor(t);
if (!t->camera)
return;
append_status(t, "Disconnecting current camera\n");
@@ -465,8 +524,9 @@
ret = gp_camera_init (t->camera, t->context);
if (ret < GP_OK) {
- append_status(t,"ERROR: Init camera returned %d.\nError text
is:%s", ret, gp_result_as_string(ret));
+ append_status(t,"ERROR: Init camera returned %d.\nError text
is:%s\n", ret, gp_result_as_string(ret));
gp_camera_free (t->camera);
+ t->camera = NULL;
return;
}
@@ -476,6 +536,7 @@
if (ret < GP_OK) {
append_status(t,"Camera failed retrieving summary.\n");
gp_camera_free (t->camera);
+ t->camera = NULL;
return;
}
append_status(t, "Summary:\n%s\n", text.text);
@@ -508,9 +569,28 @@
}
static void
+shutdown_monitor(TetherInfo *t)
+{
+ g_mutex_lock(t->monitor_mutex);
+ if (t->monitor_thread_id && t->keep_monitor_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");
+ }
+ else
+ g_mutex_unlock(t->monitor_mutex);
+}
+
+
+static void
refresh_cameralist(GObject *entry, gpointer user_data)
{
TetherInfo *t = (TetherInfo*)user_data;
+ if (t->camera)
+ closeconnection(t);
gtk_list_store_clear(t->camera_store);
int i = enumerate_cameras(t->camera_store, t->context);
append_status(t, "Found %d cameras\n", i);
@@ -542,6 +622,13 @@
connect_camera(entry, user_data);
if (!t->camera)
return;
+
+ if (t->keep_monitor_running)
+ {
+ append_status(t, "Shutting down monitor thread to enable remote
capture.\n");
+ shutdown_monitor(t);
+ }
+
capture_to_file(t);
}
@@ -556,6 +643,27 @@
}
static void
+start_monitor(GObject *entry, gpointer user_data)
+{
+ TetherInfo *t = (TetherInfo*)user_data;
+ if (!t->camera)
+ connect_camera(entry, user_data);
+ if (!t->camera)
+ return;
+ g_mutex_lock(t->monitor_mutex);
+ if (!t->monitor_thread_id || !t->keep_monitor_running)
+ {
+ t->keep_monitor_running = TRUE;
+ append_status(t, "Staring Monitor Thread.\n");
+ t->monitor_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;
@@ -571,7 +679,7 @@
GtkWidget *button;
GtkWidget* label;
- GtkBox *box;
+ GtkBox *box, *h_box;
GtkWidget *filename_hbox;
GtkWidget *filename_label;
GtkWidget *filename_chooser;
@@ -597,30 +705,66 @@
gtk_box_pack_start(box, label, FALSE, FALSE, 0);
/* Camera */
- GtkBox *camera_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
+ h_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
/* Camera selector box */
GtkWidget *camera_selector =
gtk_combo_box_new_with_model(GTK_TREE_MODEL(t->camera_store));
GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (camera_selector), cell,
TRUE);
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (camera_selector), cell,
"text", NAME_COLUMN);
- gtk_box_pack_start(camera_box, camera_selector, TRUE, TRUE, 2);
+ gtk_box_pack_start(h_box, camera_selector, TRUE, TRUE, 2);
gtk_combo_box_set_active(GTK_COMBO_BOX(camera_selector), 0);
t->camera_selector = GTK_COMBO_BOX(camera_selector);
/* Refresh / Connect buttons */
button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(refresh_cameralist), t);
- gtk_box_pack_start(camera_box, button, FALSE, FALSE, 1);
+ 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(camera_box, button, FALSE, FALSE, 1);
+ gtk_box_pack_start(h_box, button, FALSE, FALSE, 1);
/* Add this box */
- gtk_box_pack_start(box, GTK_WIDGET(camera_box), FALSE, FALSE, 5);
+ gtk_box_pack_start(box, GTK_WIDGET(h_box), FALSE, FALSE, 5);
- /* Filename template*/
+ /* "Take photo" & Monitor button */
+ h_box = GTK_BOX(gtk_hbox_new (FALSE, 0));
+ 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);
+ gtk_box_pack_start(h_box, button, FALSE, FALSE, 5);
+
+ button = gtk_button_new_with_label(_("Monitor Camera"));
+ g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(start_monitor), 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);
+
+ /* Status window */
+ label = gtk_label_new(_("Status:"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+ gtk_box_pack_start(box, label, FALSE, FALSE, 5);
+ status_window = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(status_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ /* Status text */
+ status_textview = gtk_text_view_new_with_buffer(t->status_buffer);
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(status_textview), FALSE);
+ gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(status_textview), FALSE);
+ gtk_container_add ( GTK_CONTAINER(status_window), status_textview);
+ gtk_box_pack_start(GTK_BOX(box), status_window, TRUE, FALSE, 0);
+ t->status_textview = GTK_TEXT_VIEW(status_textview);
+
+ /* Add main box */
+ gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Master Control"),
GTK_WIDGET(box), "tether_controls", TRUE), FALSE, FALSE, 0);
+
+ /* PREFERENCES */
+ box = GTK_BOX(gtk_vbox_new (FALSE, 5));
+
+ /* Filename template*/
filename = g_new0(CAMERA_FILENAME, 1);
filename_hbox = gtk_hbox_new(FALSE, 0);
filename_label = gtk_label_new(_("Filename template:"));
@@ -647,29 +791,9 @@
gtk_box_pack_start(GTK_BOX(box), example_hbox, FALSE, TRUE, 0);
update_example(filename);
- /* "Take photo" button */
- button = gtk_button_new_with_label(_("Take Photo"));
- g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(take_photo),
t);
- gtk_box_pack_start(box, button, FALSE, FALSE, 5);
+ /* Add main box */
+ gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Preferences"),
GTK_WIDGET(box), "tether_preferences", TRUE), FALSE, FALSE, 0);
- /* Status window */
- label = gtk_label_new(_("Status:"));
- gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
- gtk_box_pack_start(box, label, FALSE, FALSE, 5);
- status_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(status_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- /* Status text */
- status_textview = gtk_text_view_new_with_buffer(t->status_buffer);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(status_textview), FALSE);
- gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(status_textview), FALSE);
- gtk_container_add ( GTK_CONTAINER(status_window), status_textview);
- gtk_box_pack_start(GTK_BOX(box), status_window, TRUE, FALSE, 0);
- t->status_textview = GTK_TEXT_VIEW(status_textview);
-
- /* Add main box */
- gtk_box_pack_start(GTK_BOX(main_box), gui_box(_("Master Control"),
GTK_WIDGET(box), "tether_controls", TRUE), FALSE, FALSE, 0);
-
/* All all to window */
gtk_box_pack_start (GTK_BOX (GTK_DIALOG(t->window)->vbox),
GTK_WIDGET(main_box), TRUE, TRUE, 0);
@@ -701,8 +825,9 @@
tether_info->window = window;
tether_info->rs = rs;
tether_info->status_buffer = gtk_text_buffer_new(NULL);
-
- /* FIXME: Somehow this doesn't connect! */
+ tether_info->monitor_mutex = g_mutex_new ();
+ tether_info->keep_monitor_running = FALSE;
+ gtk_text_buffer_set_text(tether_info->status_buffer,_("Welcome to
Tethered shooting!\nMake sure your camera is not mounted.\n"),-1);
g_signal_connect(window, "response", G_CALLBACK(close_main_window),
tether_info);
/* Initialize context */
@@ -717,6 +842,6 @@
append_status(tether_info, "Found %d cameras\n", i);
build_tether_gui(tether_info);
- gtk_window_resize(GTK_WINDOW(window), 500, 600);
+ gtk_window_resize(GTK_WINDOW(window), 500, 400);
gtk_widget_show_all(GTK_WIDGET(window));
}
Modified: trunk/src/ui.xml
===================================================================
--- trunk/src/ui.xml 2010-09-11 23:23:04 UTC (rev 3523)
+++ trunk/src/ui.xml 2010-09-12 12:02:12 UTC (rev 3524)
@@ -73,6 +73,7 @@
<menuitem action="Split" />
<menuitem action="Lightsout" />
<menuitem action="LensDbEditor" />
+ <menuitem action="TetheredShooting" />
</menu>
<menu action="BatchMenu">
<menuitem action="AddToBatch" />
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit