Author: post Date: 2010-08-25 20:10:44 +0200 (Wed, 25 Aug 2010) New Revision: 3514
Added: trunk/src/rs-tethered-shooting.c trunk/src/rs-tethered-shooting.h Log: Add (un-activated) tethered shooting code to repository. Added: trunk/src/rs-tethered-shooting.c =================================================================== --- trunk/src/rs-tethered-shooting.c (rev 0) +++ trunk/src/rs-tethered-shooting.c 2010-08-25 18:10:44 UTC (rev 3514) @@ -0,0 +1,436 @@ +/* + * * Copyright (C) 2006-2010 Anders Brander <[email protected]>, + * * Anders Kvist <[email protected]> and Klaus Post <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * The following functions is more or less grabbed from UFraw: + * lens_set(), lens_menu_select(), ptr_array_insert_sorted(), + * ptr_array_find_sorted(), ptr_array_insert_index() and lens_menu_fill() + */ + +#include <rawstudio.h> +#include <glib.h> +#include <gtk/gtk.h> +#include <string.h> +#include <config.h> +#include <gettext.h> +#include "rs-tethered-shooting.h" +#include <gphoto2/gphoto2-camera.h> +#include <stdlib.h> +#include <fcntl.h> +#include "filename.h" +#include <rs-store.h> +#ifdef WITH_GCONF +#include <gconf/gconf-client.h> +#endif +#include "conf_interface.h" + +typedef struct { + Camera *camera; + GPContext *context; + GtkWidget *window; + RS_BLOB *rs; +} TetherInfo; + +static TetherInfo *tether_info = NULL; + +static void +ctx_error_func (GPContext *context, const char *format, va_list args, void *data) +{ + fprintf (stderr, "\n"); + fprintf (stderr, "*** Contexterror *** \n"); + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); +} + +static void +ctx_status_func (GPContext *context, const char *format, va_list args, void *data) +{ + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + fflush (stderr); +} + +int +enumerate_cameras(CameraList *list, GPContext *context) { + int ret, i; + CameraList *xlist = NULL; + GPPortInfoList *portinfolist = NULL; + CameraAbilitiesList *abilities = NULL; + + ret = gp_list_new (&xlist); + if (ret < GP_OK) goto out; + if (!portinfolist) { + /* Load all the port drivers we have... */ + ret = gp_port_info_list_new (&portinfolist); + if (ret < GP_OK) goto out; + ret = gp_port_info_list_load (portinfolist); + if (ret < 0) goto out; + ret = gp_port_info_list_count (portinfolist); + if (ret < 0) goto out; + } + /* Load all the camera drivers we have... */ + ret = gp_abilities_list_new (&abilities); + if (ret < GP_OK) goto out; + ret = gp_abilities_list_load (abilities, context); + if (ret < GP_OK) goto out; + + /* ... and autodetect the currently attached cameras. */ + ret = gp_abilities_list_detect (abilities, portinfolist, xlist, context); + if (ret < GP_OK) goto out; + + /* Filter out the "usb:" entry */ + ret = gp_list_count (xlist); + if (ret < GP_OK) goto out; + for (i=0;i<ret;i++) { + const char *name, *value; + + gp_list_get_name (xlist, i, &name); + gp_list_get_value (xlist, i, &value); + if (!strcmp ("usb:",value)) continue; + gp_list_append (list, name, value); + } +out: + gp_list_free (xlist); + return gp_list_count(list); +} + +/* + * This function looks up a label or key entry of + * a configuration widget. + * The functions descend recursively, so you can just + * specify the last component. + */ + +static int +_lookup_widget(CameraWidget*widget, const char *key, CameraWidget **child) { + int ret; + ret = gp_widget_get_child_by_name (widget, key, child); + if (ret < GP_OK) + ret = gp_widget_get_child_by_label (widget, key, child); + return ret; +} + +/* Gets a string configuration value. + * This can be: + * - A Text widget + * - The current selection of a Radio Button choice + * - The current selection of a Menu choice + * + * Sample (for Canons eg): + * get_config_value_string (camera, "owner", &ownerstr, context); + */ +static int +get_config_value_string (Camera *camera, const char *key, char **str, GPContext *context) { + CameraWidget *widget = NULL, *child = NULL; + CameraWidgetType type; + int ret; + char *val; + + ret = gp_camera_get_config (camera, &widget, context); + if (ret < GP_OK) { + fprintf (stderr, "camera_get_config failed: %d\n", ret); + return ret; + } + ret = _lookup_widget (widget, key, &child); + if (ret < GP_OK) { + fprintf (stderr, "lookup widget failed: %d\n", ret); + goto out; + } + + /* This type check is optional, if you know what type the label + * has already. If you are not sure, better check. */ + ret = gp_widget_get_type (child, &type); + if (ret < GP_OK) { + fprintf (stderr, "widget get type failed: %d\n", ret); + goto out; + } + switch (type) { + case GP_WIDGET_MENU: + case GP_WIDGET_RADIO: + case GP_WIDGET_TEXT: + break; + default: + fprintf (stderr, "widget has bad type %d\n", type); + ret = GP_ERROR_BAD_PARAMETERS; + goto out; + } + + /* This is the actual query call. Note that we just + * a pointer reference to the string, not a copy... */ + ret = gp_widget_get_value (child, &val); + if (ret < GP_OK) { + fprintf (stderr, "could not query widget value: %d\n", ret); + goto out; + } + /* Create a new copy for our caller. */ + *str = strdup (val); +out: + gp_widget_free (widget); + return ret; +} + +static int +open_camera (Camera ** camera, const char *model, const char *port) { + int ret, m, p; + CameraAbilities a; + GPPortInfo pi; + GPPortInfoList *portinfolist = NULL; + CameraAbilitiesList *abilities = NULL; + + ret = gp_camera_new (camera); + if (ret < GP_OK) return ret; + + /* First lookup the model / driver */ + m = gp_abilities_list_lookup_model (abilities, model); + if (m < GP_OK) return ret; + ret = gp_abilities_list_get_abilities (abilities, m, &a); + if (ret < GP_OK) return ret; + ret = gp_camera_set_abilities (*camera, a); + if (ret < GP_OK) return ret; + + /* Then associate the camera with the specified port */ + p = gp_port_info_list_lookup_path (portinfolist, port); + if (ret < GP_OK) return ret; + switch (p) { + case GP_ERROR_UNKNOWN_PORT: + fprintf (stderr, "The port you specified " + "('%s') can not be found. Please " + "specify one of the ports found by " + "'gphoto2 --list-ports' and make " + "sure the spelling is correct " + "(i.e. with prefix 'serial:' or 'usb:').", + port); + break; + default: + break; + } + if (ret < GP_OK) return ret; + ret = gp_port_info_list_get_info (portinfolist, p, &pi); + if (ret < GP_OK) return ret; + ret = gp_camera_set_port_info (*camera, pi); + if (ret < GP_OK) return ret; + return GP_OK; +} + + +static void enable_capture(TetherInfo *t) { + int retval; + + printf("Get root config.\n"); + CameraWidget *rootconfig; // okay, not really + CameraWidget *actualrootconfig; + + retval = gp_camera_get_config(t->camera, &rootconfig, t->context); + actualrootconfig = rootconfig; + + printf("Get main config.\n"); + CameraWidget *child; + retval = gp_widget_get_child_by_name(rootconfig, "main", &child); + + printf("Get settings config.\n"); + rootconfig = child; + retval = gp_widget_get_child_by_name(rootconfig, "settings", &child); + + printf("Get capture config.\n"); + rootconfig = child; + retval = gp_widget_get_child_by_name(rootconfig, "capture", &child); + + CameraWidget *capture = child; + + const char *widgetinfo; + gp_widget_get_name(capture, &widgetinfo); + printf("config name: %s\n", widgetinfo ); + + const char *widgetlabel; + gp_widget_get_label(capture, &widgetlabel); + printf("config label: %s\n", widgetlabel); + + int widgetid; + gp_widget_get_id(capture, &widgetid); + printf("config id: %d\n", widgetid); + + CameraWidgetType widgettype; + gp_widget_get_type(capture, &widgettype); + printf("config type: %d == %d \n", widgettype, GP_WIDGET_TOGGLE); + + int one=1; + retval = gp_widget_set_value(capture, &one); + + printf("Enabling capture.\n"); + retval = gp_camera_set_config(t->camera, actualrootconfig, t->context); +} + +static void +add_file_to_store(TetherInfo* t, const char* tmp_name) +{ + gchar *lwd; + lwd = rs_conf_get_string(CONF_LWD); + GString *filename_template = g_string_new(lwd); + g_string_append(filename_template, G_DIR_SEPARATOR_S); + g_string_append(filename_template, "Rawstudio_%2c.cr2"); + gchar* filename = filename_parse(g_string_free(filename_template, FALSE),tmp_name, 0); + + GFile* src = g_file_new_for_path(tmp_name); + GFile* dst = g_file_new_for_path(filename); + + if (!g_file_move(src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL)) + { + printf("Move failed!\n"); + return; + } + g_object_unref(src); + g_object_unref(dst); + + rs_store_load_file(t->rs->store, filename); + if (!rs_store_set_selected_name(t->rs->store, filename, TRUE)) + printf("Could not open image!\n"); +} + +static void +capture_to_file(TetherInfo* t) +{ + 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 */ + char tmp_name[L_tmpnam]; + char *tmp_name_ptr; + tmp_name_ptr = tmpnam(tmp_name); + + if (NULL == tmp_name_ptr) + return; + + printf("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); + printf(" Retval: %d\n", retval); + + fd = open(tmp_name_ptr, O_CREAT | O_WRONLY, 0644); + retval = gp_file_new_from_fd(&canonfile, fd); + 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_delete(t->camera, camera_file_path.folder, camera_file_path.name, + t->context); + + gp_file_free(canonfile); + add_file_to_store(t, tmp_name_ptr); +} + + +static void closeconnection(TetherInfo *t) +{ + gp_camera_exit (t->camera, t->context); + gp_camera_free (t->camera); +} + +static void initcamera(TetherInfo *t) +{ + gint ret; + t->context = gp_context_new(); + gp_context_set_error_func (t->context, ctx_error_func, NULL); + gp_context_set_status_func (t->context, ctx_status_func, NULL); + + CameraList* list; + ret = gp_list_new(&list); + int i = enumerate_cameras(list, t->context); + + printf("Found %d cameras\n", i); + if (i < 1) + return; + + /* This call will autodetect cameras, take the + * first one from the list and use it. It will ignore + * any others... See the *multi* examples on how to + * detect and use more than the first one. + */ + const char *name, *value; + + gp_list_get_name (list, 0, &name); + gp_list_get_value (list, 0, &value); + + ret = open_camera(&t->camera, name, value); + if (ret < GP_OK) + fprintf(stderr,"Camera %s on port %s failed to open\n", name, value); + + ret = gp_camera_init (t->camera, t->context); + if (ret < GP_OK) { + printf("After init:returned %d.\n", ret); + gp_camera_free (t->camera); + return; + } + + CameraText text; + /* Simple query the camera summary text */ + ret = gp_camera_get_summary (t->camera, &text, t->context); + if (ret < GP_OK) { + printf("Camera failed retrieving summary.\n"); + gp_camera_free (t->camera); + return; + } + printf("Summary:\n%s\n", text.text); + + char *owner; + /* Simple query of a string configuration variable. */ + ret = get_config_value_string (t->camera, "owner", &owner, t->context); + if (ret >= GP_OK) { + printf("Owner: %s\n", owner); + free(owner); + } +} + +void +rs_tethered_shooting_open(RS_BLOB *rs) +{ + GtkWidget *window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(window), _("Rawstudio Tethered Shooting")); + gtk_dialog_set_has_separator (GTK_DIALOG(window), FALSE); + g_signal_connect_swapped(window, "delete_event", + G_CALLBACK (gtk_widget_destroy), window); + g_signal_connect_swapped(window, "response", + G_CALLBACK (gtk_widget_destroy), window); + + gtk_window_resize(GTK_WINDOW(window), 400, 400); + +// GtkWidget *frame = gtk_frame_new(""); +// gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), frame, TRUE, TRUE, 0); + + GtkWidget *button_close = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + gtk_dialog_add_action_widget (GTK_DIALOG (window), button_close, GTK_RESPONSE_CLOSE); + + gtk_widget_show_all(GTK_WIDGET(window)); + + if (tether_info == NULL) + { + tether_info = g_malloc0(sizeof(TetherInfo)); + } + tether_info->window = window; + tether_info->rs = rs; + initcamera(tether_info); + enable_capture(tether_info); + capture_to_file(tether_info); + closeconnection(tether_info); +} Added: trunk/src/rs-tethered-shooting.h =================================================================== --- trunk/src/rs-tethered-shooting.h (rev 0) +++ trunk/src/rs-tethered-shooting.h 2010-08-25 18:10:44 UTC (rev 3514) @@ -0,0 +1,27 @@ +/* + * * Copyright (C) 2006-2010 Anders Brander <[email protected]>, + * * Anders Kvist <[email protected]> and Klaus Post <[email protected]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef RS_TETHERED_SHOOTING_H +#define RS_TETHERED_SHOOTING_H + +#include "application.h" + +extern void rs_tethered_shooting_open(RS_BLOB* rs); + +#endif /* RS_TETHERED_SHOOTING_H */ _______________________________________________ Rawstudio-commit mailing list [email protected] http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit
