Files
libgphoto2/frontends/command-line/main.c
Lutz Mueller 25b9808904 2001-11-21 Lutz M�ller <urc8@rz.uni-karlsruhe.de>
I quote from an e-mail: "You (Lutz) should remove the code you added
        that broke (at least) two of the supported 'libgphoto2' camera
        libraries!!!" *sigh*.

        * conigure.in: Add a --with-multi option and a warning that people
          who use it will run into troubles with digita and dc240 and that
          people who don't use it will run into troubles when using Nautilus
          or Konqueror for browsing their camera.


git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@3140 67ed7778-7388-44ab-90cf-0a291f65f57c
2001-11-21 19:07:53 +00:00

1317 lines
37 KiB
C

/* $Id$ */
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#ifndef WIN32
#include <signal.h>
#endif
#include "main.h"
#include "actions.h"
#include "foreach.h"
#include "interface.h"
#include "options.h"
#include "range.h"
#include "shell.h"
#if HAVE_CDK
#include "gphoto2-cmd-config.h"
#endif
#if HAVE_AA
#include "gphoto2-cmd-capture.h"
#endif
#include "gphoto2-port-info-list.h"
#include "gphoto2-port-log.h"
#include "gphoto2-setting.h"
#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
# define _(String) dgettext (PACKAGE, String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define N_(String) (String)
#endif
#define CHECK_RESULT(result) {int r = (result); if (r < 0) return (r);}
/* Takes the current globals, and sets up the gPhoto lib with them */
static int set_globals (void);
/* Command-line option
-----------------------------------------------------------------------
this is funky and may look a little scary, but sounded cool to do.
it makes sense since this is just a wrapper for a functional/flow-based
library.
AFTER NOTE: whoah. gnome does something like this. cool deal :)
When the program starts it calls (in order):
1) verify_options() to make sure all options are valid,
and that any options needing an argument have one (or if they
need an argument, they don't have one).
2) (optional) option_is_present() to see if a particular option was
typed in the command-line. This can be used to set up something
before the next step.
3) execute_options() to actually parse the command-line and execute
the command-line options in order.
This might sound a little complex, but makes adding options REALLY easy,
and it is very flexible.
How to add a command-line option:
*/
/* 1) Add a forward-declaration here */
/* ----------------------------------------------------------------- */
/* Use the OPTION_CALLBACK(function) macro. */
OPTION_CALLBACK(abilities);
#if HAVE_CDK
OPTION_CALLBACK(config);
#endif
OPTION_CALLBACK(help);
OPTION_CALLBACK(version);
OPTION_CALLBACK(shell);
OPTION_CALLBACK(list_cameras);
OPTION_CALLBACK(print_usb_usermap);
OPTION_CALLBACK(auto_detect);
OPTION_CALLBACK(list_ports);
OPTION_CALLBACK(filename);
OPTION_CALLBACK(port);
OPTION_CALLBACK(speed);
OPTION_CALLBACK(model);
OPTION_CALLBACK(quiet);
OPTION_CALLBACK(debug);
OPTION_CALLBACK(use_folder);
OPTION_CALLBACK(recurse);
OPTION_CALLBACK(use_stdout);
OPTION_CALLBACK(use_stdout_size);
OPTION_CALLBACK(list_folders);
OPTION_CALLBACK(list_files);
OPTION_CALLBACK(num_pictures);
OPTION_CALLBACK(get_picture);
OPTION_CALLBACK(get_all_pictures);
OPTION_CALLBACK(get_thumbnail);
OPTION_CALLBACK(get_all_thumbnails);
OPTION_CALLBACK(get_raw_data);
OPTION_CALLBACK(get_all_raw_data);
OPTION_CALLBACK(get_audio_data);
OPTION_CALLBACK(get_all_audio_data);
OPTION_CALLBACK(delete_picture);
OPTION_CALLBACK(delete_all_pictures);
OPTION_CALLBACK(upload_picture);
OPTION_CALLBACK(capture_image);
OPTION_CALLBACK(capture_preview);
OPTION_CALLBACK(capture_movie);
OPTION_CALLBACK(capture_sound);
OPTION_CALLBACK(summary);
OPTION_CALLBACK(manual);
OPTION_CALLBACK(about);
OPTION_CALLBACK(make_dir);
OPTION_CALLBACK(remove_dir);
/* 2) Add an entry in the option table */
/* ----------------------------------------------------------------- */
/* Format for option is: */
/* {"short", "long", "argument", "description", callback_function, required}, */
/* if it is just a flag, set the argument to "". */
/* Order is important! Options are exec'd in the order in the table! */
Option option[] = {
/* Settings needed for formatting output */
{"", "debug", "", "Turn on debugging", debug, 0},
{"q", "quiet", "", "Quiet output (default=verbose)",quiet, 0},
/* Display and die actions */
{"v", "version", "", "Display version and exit", version, 0},
{"h", "help", "", "Displays this help screen", help, 0},
{"", "list-cameras", "", "List supported camera models", list_cameras, 0},
{"", "print-usb-usermap", "", "Create output for usb.usermap", print_usb_usermap, 0},
{"", "list-ports", "", "List supported port devices", list_ports, 0},
{"", "stdout", "", "Send file to stdout", use_stdout, 0},
{"", "stdout-size", "", "Print filesize before data", use_stdout_size,0},
{"", "auto-detect", "", "List auto-detected cameras", auto_detect, 0},
/* Settings needed for camera functions */
{"" , "port", "path", "Specify port device", port, 0},
{"" , "speed", "speed", "Specify serial transfer speed",speed, 0},
{"" , "camera", "model", "Specify camera model", model, 0},
{"" , "filename", "filename", "Specify a filename", filename, 0},
/* Actions that depend on settings */
{"a", "abilities", "", "Display camera abilities", abilities, 0},
{"f", "folder", "folder", "Specify camera folder (default=\"/\")",use_folder,0},
{"R", "recurse", "", "Recursively descend through folders",recurse, 0},
{"l", "list-folders", "", "List folders in folder", list_folders, 0},
{"L", "list-files", "", "List files in folder", list_files, 0},
{"m", "mkdir", N_("name"), N_("Create a directory"), make_dir, 0},
{"r", "rmdir", N_("name"), N_("Remove a directory"), remove_dir, 0},
{"n", "num-images", "", "Display number of pictures", num_pictures, 0},
{"p", "get-image", "range", "Get pictures given in range", get_picture, 0},
{"P", "get-all-images","", "Get all pictures from folder", get_all_pictures,0},
{"t", "get-thumbnail", "range", "Get thumbnails given in range",get_thumbnail, 0},
{"T", "get-all-thumbnails","", "Get all thumbnails from folder",get_all_thumbnails,0},
{"r", "get-raw-data", "range", "Get raw data given in range", get_raw_data, 0},
{"", "get-all-raw-data", "", "Get all raw data from folder", get_all_raw_data, 0},
{"", "get-audio-data", "range", N_("Get audio data given in range"), get_audio_data, 0},
{"", "get-all-audio-data", "", N_("Get all audio data from folder"), get_all_audio_data, 0},
{"d", "delete-picture", "range", N_("Delete pictures given in range"), delete_picture, 0},
{"D", "delete-all-images","", N_("Delete all pictures in folder"), delete_all_pictures,0},
{"u", "upload-image", "filename", N_("Upload a picture to camera"), upload_picture, 0},
{"" , "capture-preview", "", N_("Capture a quick preview"), capture_preview, 0},
{"" , "capture-image", "", N_("Capture an image"), capture_image, 0},
{"" , "capture-movie", "", N_("Capture a movie "), capture_movie, 0},
{"" , "capture-sound", "", N_("Capture an audio clip"), capture_sound, 0},
#if HAVE_CDK
{"" , "config", "", "Configure", config, 0},
#endif
{"", "summary", "", "Summary of camera status", summary, 0},
{"", "manual", "", "Camera driver manual", manual, 0},
{"", "about", "", "About the camera driver", about, 0},
{"", "shell", "", "gPhoto shell", shell, 0},
/* End of list */
{"" , "", "", "", NULL, 0}
};
/* 3) Add any necessary global variables */
/* ----------------------------------------------------------------- */
/* Most flags will set options, like choosing a port, camera model, */
/* etc... */
int glob_option_count;
char glob_port[128];
char glob_model[64];
char glob_folder[1024];
char glob_owd[1024];
char glob_cwd[1024];
int glob_speed;
int glob_num=1;
Camera *glob_camera=NULL;
int glob_debug;
int glob_shell=0;
int glob_quiet=0;
int glob_filename_override=0;
int glob_recurse=0;
char glob_filename[128];
int glob_stdout=0;
int glob_stdout_size=0;
/* 4) Finally, add your callback function. */
/* ----------------------------------------------------------------- */
/* The callback function is passed "char *arg" to the argument of */
/* command-line option. It must return GP_OK or GP_ERROR. */
/* Again, use the OPTION_CALLBACK(function) macro. */
/* glob_debug is set if the user types in the "--debug" flag. Use */
/* cli_debug_print(char *format, ...) to display debug output. Use */
/* cli_error_print(char *format, ...) to display error output. */
OPTION_CALLBACK(help) {
cli_debug_print("Displaying usage");
usage();
exit(EXIT_SUCCESS);
return GP_OK;
}
OPTION_CALLBACK(version) {
cli_debug_print("Displaying version");
print_version();
exit(EXIT_SUCCESS);
return GP_OK;
}
OPTION_CALLBACK(use_stdout) {
glob_quiet = 1; /* implied */
glob_stdout = 1;
return GP_OK;
}
OPTION_CALLBACK(use_stdout_size)
{
glob_stdout_size = 1;
use_stdout(arg);
return GP_OK;
}
OPTION_CALLBACK (auto_detect)
{
int x, count;
CameraList list;
CameraAbilitiesList *al;
GPPortInfoList *il;
const char *name, *value;
gp_abilities_list_new (&al);
gp_abilities_list_load (al);
gp_port_info_list_new (&il);
gp_port_info_list_load (il);
gp_abilities_list_detect (al, il, &list);
gp_abilities_list_free (al);
gp_port_info_list_free (il);
CHECK_RESULT (count = gp_list_count (&list));
printf("%-30s %-16s\n", "Model", "Port");
printf("----------------------------------------------------------\n");
for (x = 0; x < count; x++) {
CHECK_RESULT (gp_list_get_name (&list, x, &name));
CHECK_RESULT (gp_list_get_value (&list, x, &value));
printf("%-30s %-16s\n", name, value);
}
return GP_OK;
}
OPTION_CALLBACK (abilities)
{
int x = 0;
CameraAbilitiesList *al;
CameraAbilities abilities;
if (!strlen (glob_model)) {
cli_error_print (_("You need to specify a camera model"));
return (GP_ERROR_BAD_PARAMETERS);
}
CHECK_RESULT (gp_abilities_list_new (&al));
CHECK_RESULT (gp_abilities_list_load (al));
CHECK_RESULT (x = gp_abilities_list_lookup_model (al, glob_model));
CHECK_RESULT (gp_abilities_list_get_abilities (al, x, &abilities));
CHECK_RESULT (gp_abilities_list_free (al));
/* Output a parsing friendly abilities table. Split on ":" */
printf("Abilities for camera: : %s\n",
abilities.model);
printf("Serial port support : %s\n",
(abilities.port & GP_PORT_SERIAL)? "yes":"no");
printf("USB support : %s\n",
(abilities.port & GP_PORT_USB)? "yes":"no");
if (abilities.speed[0] != 0) {
printf("Transfer speeds supported :\n");
x = 0;
do {
printf(" : %i\n", abilities.speed[x]);
x++;
} while (abilities.speed[x]!=0);
}
printf("Capture choices :\n");
if (abilities.operations & GP_OPERATION_CAPTURE_IMAGE)
printf(" : Image\n");
if (abilities.operations & GP_OPERATION_CAPTURE_VIDEO)
printf(" : Video\n");
if (abilities.operations & GP_OPERATION_CAPTURE_AUDIO)
printf(" : Audio\n");
if (abilities.operations & GP_OPERATION_CAPTURE_PREVIEW)
printf(" : Preview\n");
printf("Configuration support : %s\n",
abilities.operations & GP_OPERATION_CONFIG? "yes":"no");
printf("Delete files on camera support : %s\n",
abilities.file_operations & GP_FILE_OPERATION_DELETE? "yes":"no");
printf("File preview (thumbnail) support : %s\n",
abilities.file_operations & GP_FILE_OPERATION_PREVIEW? "yes":"no");
printf("File upload support : %s\n",
abilities.folder_operations & GP_FOLDER_OPERATION_PUT_FILE? "yes":"no");
return (GP_OK);
}
OPTION_CALLBACK(list_cameras) {
int x, n;
CameraAbilitiesList *al;
CameraAbilities a;
cli_debug_print("Listing Cameras");
CHECK_RESULT (gp_abilities_list_new (&al));
CHECK_RESULT (gp_abilities_list_load (al));
CHECK_RESULT (n = gp_abilities_list_count (al));
if (glob_quiet)
printf ("%i\n", n);
else {
printf (_("Number of supported cameras: %i\n"), n);
printf (_("Supported cameras:\n"));
}
for (x = 0; x < n; x++) {
CHECK_RESULT (gp_abilities_list_get_abilities (al, x, &a));
if (glob_quiet)
printf("%s\n", a.model);
else
switch (a.status) {
case GP_DRIVER_STATUS_TESTING:
printf ("\t\"%s\" (TESTING)\n", a.model);
break;
case GP_DRIVER_STATUS_EXPERIMENTAL:
printf ("\t\"%s\" (EXPERIMENTAL)\n", a.model);
break;
default:
case GP_DRIVER_STATUS_PRODUCTION:
printf ("\t\"%s\"\n", a.model);
break;
}
}
CHECK_RESULT (gp_abilities_list_free (al));
return (GP_OK);
}
/* print_usb_usermap
*
* Print out lines that can be included into usb.usermap
* - for all cams supported by our instance of libgphoto2.
*
* written after list_cameras
*/
OPTION_CALLBACK(print_usb_usermap) {
int x, n;
CameraAbilitiesList *al;
CameraAbilities a;
cli_debug_print("Listing Cameras");
CHECK_RESULT (gp_abilities_list_new (&al));
CHECK_RESULT (gp_abilities_list_load (al));
CHECK_RESULT (n = gp_abilities_list_count (al));
for (x = 0; x < n; x++) {
CHECK_RESULT (gp_abilities_list_get_abilities (al, x, &a));
if (a.usb_vendor && a.usb_product) {
printf (GP_USB_HOTPLUG_SCRIPT " "
"0x0000 0x%04x 0x%04x 0x0000 "
"0x0000 0x00 0x00 "
"0x00 0x00 0x00 "
"0x00 0x00000000\n",
a.usb_vendor, a.usb_product);
}
}
CHECK_RESULT (gp_abilities_list_free (al));
return (GP_OK);
}
OPTION_CALLBACK(list_ports)
{
GPPortInfoList *list;
GPPortInfo info;
int x, count, result;
CHECK_RESULT (gp_port_info_list_new (&list));
result = gp_port_info_list_load (list);
if (result < 0) {
gp_port_info_list_free (list);
return (result);
}
count = gp_port_info_list_count (list);
if (count < 0) {
gp_port_info_list_free (list);
return (count);
}
if (!glob_quiet) {
printf("Devices found: %i\n", count);
printf("Path Description\n"
"--------------------------------------------------------------\n");
} else
printf("%i\n", count);
/* Now list the ports */
for (x = 0; x < count; x++) {
result = gp_port_info_list_get_info (list, x, &info);
if (result < 0) {
gp_port_info_list_free (list);
return (result);
}
printf ("%-32s %-32s\n", info.path, info.name);
}
return (GP_OK);
}
OPTION_CALLBACK(filename)
{
cli_debug_print("Setting filename to %s", arg);
strcpy (glob_filename, arg);
glob_filename_override = 1;
return (GP_OK);
}
OPTION_CALLBACK(port)
{
cli_debug_print("Setting port to %s", arg);
strcpy (glob_port, arg);
if (strchr(glob_port, ':') == NULL) {
/* User didn't specify the port type; try to guess it */
gp_log (GP_LOG_DEBUG, "main", "Ports must look like "
"'serial:/dev/ttyS0' or 'usb:', but '%s' is missing a colon "
"so I am going to guess what you mean.",
glob_port);
if (strcmp(arg, "usb") == 0) {
/* User forgot the colon; add it for him */
strcpy (glob_port, "usb:");
} else if (strncmp(arg, "/dev/", 5) == 0) {
/* Probably a serial port like /dev/ttyS0 */
strcpy (glob_port, "serial:");
strncat (glob_port, arg, sizeof(glob_port)-7);
} else if (strncmp(arg, "/proc/", 6) == 0) {
/* Probably a USB port like /proc/bus/usb/001 */
strcpy (glob_port, "usb:");
strncat (glob_port, arg, sizeof(glob_port)-4);
}
cli_debug_print("Guessed port name. Using port '%s' from now on.",
glob_port);
}
return (GP_OK);
}
OPTION_CALLBACK(speed)
{
cli_debug_print("Setting speed to %s", arg);
glob_speed = atoi (arg);
return (GP_OK);
}
OPTION_CALLBACK(model)
{
cli_debug_print("Setting camera model to %s", arg);
strcpy (glob_model, arg);
return (GP_OK);
}
static void
debug_func (GPLogLevel level, const char *domain, const char *format,
va_list args, void *data)
{
if (level == GP_LOG_ERROR)
fprintf (stderr, "%s(ERROR): ", domain);
else
fprintf (stderr, "%s(%i): ", domain, level);
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
}
OPTION_CALLBACK (debug)
{
glob_debug = GP_DEBUG_HIGH;
cli_debug_print(PACKAGE " " VERSION ": " "Turning on debug mode");
gp_log_add_func (GP_LOG_ALL, debug_func, NULL);
return (GP_OK);
}
OPTION_CALLBACK(quiet)
{
cli_debug_print("Setting to quiet mode");
glob_quiet=1;
return (GP_OK);
}
OPTION_CALLBACK(shell)
{
cli_debug_print("Entering shell mode");
CHECK_RESULT (set_globals ());
glob_shell = 1;
return (shell_prompt ());
}
OPTION_CALLBACK (use_folder)
{
cli_debug_print("Setting folder to %s", arg);
strcpy (glob_folder, arg);
return (GP_OK);
}
OPTION_CALLBACK (recurse)
{
cli_debug_print("Setting recursive mode");
glob_recurse = 1;
return (GP_OK);
}
OPTION_CALLBACK (list_folders)
{
CHECK_RESULT (set_globals ());
return for_each_subfolder (glob_folder, print_folder, NULL, glob_recurse);
}
#if HAVE_CDK
OPTION_CALLBACK(config)
{
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_cmd_config (glob_camera));
return (GP_OK);
}
#endif
OPTION_CALLBACK (list_files)
{
CHECK_RESULT (set_globals());
CHECK_RESULT (for_each_image (glob_folder, print_picture_action, 0));
if (!glob_recurse)
return (GP_OK);
return for_each_subfolder(glob_folder, for_each_image, print_picture_action, glob_recurse);
}
OPTION_CALLBACK (num_pictures)
{
int count;
CameraList list;
cli_debug_print ("Counting pictures");
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_folder_list_files (glob_camera, glob_folder,
&list));
CHECK_RESULT (count = gp_list_count (&list));
if (glob_quiet)
printf ("%i\n", count);
else
printf ("Number of pictures in folder %s: %i\n",
glob_folder, count);
return (GP_OK);
}
static int
save_camera_file_to_file (CameraFile *file, CameraFileType type)
{
char ofile[1024], ofolder[1024], buf[1024], c[1024];
int result;
char *f;
const char *name;
/* Determine the folder and filename */
strcpy (ofile, "");
strcpy (ofolder, "");
if (glob_filename_override) {
if (strchr (glob_filename, '/')) { /* Check if they specified an output dir */
f = strrchr(glob_filename, '/');
strcpy(buf, f+1); /* Get the filename */
sprintf(ofile, buf, glob_num++);
*f = 0;
strcpy(ofolder, glob_filename); /* Get the folder */
strcat(ofolder, "/");
*f = '/';
} else { /* If not, subst and set */
sprintf(ofile, glob_filename, glob_num++);
}
} else {
gp_file_get_name (file, &name);
strcat (ofile, name);
gp_log (GP_LOG_DEBUG, "gphoto2", "Using filename '%s'...",
ofile);
}
switch (type) {
case GP_FILE_TYPE_PREVIEW:
snprintf (buf, sizeof (buf), "%sthumb_%s", ofolder, ofile);
break;
case GP_FILE_TYPE_NORMAL:
snprintf (buf, sizeof (buf), "%s%s", ofolder, ofile);
break;
case GP_FILE_TYPE_RAW:
snprintf (buf, sizeof (buf), "%sraw_%s", ofolder, ofile);
break;
case GP_FILE_TYPE_AUDIO:
snprintf (buf, sizeof (buf), "%saudio_%s", ofolder, ofile);
break;
default:
return (GP_ERROR_NOT_SUPPORTED);
}
if (!glob_quiet) {
while (GP_SYSTEM_IS_FILE(buf)) {
if (glob_quiet)
break;
do {
printf("File %s exists. Overwrite? [y|n] ",buf);
fflush(stdout);
fgets(c, 1023, stdin);
} while ((c[0]!='y')&&(c[0]!='Y')&&
(c[0]!='n')&&(c[0]!='N'));
if ((c[0]=='y') || (c[0]=='Y'))
break;
do {
printf("Specify new filename? [y|n] ");
fflush(stdout);
fgets(c, 1023, stdin);
} while ((c[0]!='y')&&(c[0]!='Y')&&
(c[0]!='n')&&(c[0]!='N'));
if (!((c[0]=='y') || (c[0]=='Y')))
return (GP_OK);
printf("Enter new filename: ");
fflush(stdout);
fgets(buf, 1023, stdin);
buf[strlen(buf)-1]=0;
}
printf("Saving file as %s\n", buf);
}
if ((result = gp_file_save(file, buf)) != GP_OK)
cli_error_print("Can not save file as %s", buf);
return (result);
}
int
save_picture_to_file (const char *folder, const char *filename,
CameraFileType type)
{
int res;
CameraFile *file;
CHECK_RESULT (gp_file_new (&file));
CHECK_RESULT (gp_camera_file_get (glob_camera, folder, filename, type,
file));
if (glob_stdout) {
const char *data;
long int size;
CHECK_RESULT (gp_file_get_data_and_size (file, &data, &size));
if (glob_stdout_size)
printf ("%li\n", size);
fwrite (data, sizeof(char), size, stdout);
gp_file_free (file);
return (GP_OK);
}
res = save_camera_file_to_file (file, type);
gp_file_free (file);
return (res);
}
/*
get_picture_common() - parse range, download specified images, or their
thumbnails according to thumbnail argument, and save to files.
*/
int
get_picture_common(char *arg, CameraFileType type )
{
cli_debug_print("Getting %s", arg);
CHECK_RESULT (set_globals ());
if (strchr(arg, '.'))
return (save_picture_to_file(glob_folder, arg, type));
switch (type) {
case GP_FILE_TYPE_PREVIEW:
return for_each_image_in_range (glob_folder, arg, save_thumbnail_action, 0);
case GP_FILE_TYPE_NORMAL:
return for_each_image_in_range (glob_folder, arg, save_picture_action, 0);
case GP_FILE_TYPE_RAW:
return for_each_image_in_range (glob_folder, arg, save_raw_action, 0);
case GP_FILE_TYPE_AUDIO:
return for_each_image_in_range (glob_folder, arg, save_audio_action, 0);
default:
return (GP_ERROR_NOT_SUPPORTED);
}
}
OPTION_CALLBACK (get_picture)
{
return get_picture_common(arg, GP_FILE_TYPE_NORMAL);
}
OPTION_CALLBACK (get_all_pictures)
{
cli_debug_print("Getting all pictures");
CHECK_RESULT (set_globals ());
CHECK_RESULT (for_each_image (glob_folder, save_picture_action, 0));
if (!glob_recurse)
return (GP_OK);
return for_each_subfolder(glob_folder, for_each_image, save_picture_action, glob_recurse);
}
OPTION_CALLBACK (get_thumbnail)
{
return (get_picture_common(arg, GP_FILE_TYPE_PREVIEW));
}
OPTION_CALLBACK(get_all_thumbnails)
{
cli_debug_print("Getting all thumbnails");
CHECK_RESULT (set_globals ());
CHECK_RESULT (for_each_image (glob_folder, save_thumbnail_action, 0));
if (!glob_recurse)
return (GP_OK);
return for_each_subfolder(glob_folder, for_each_image, save_thumbnail_action, glob_recurse);
}
OPTION_CALLBACK (get_raw_data)
{
return (get_picture_common(arg, GP_FILE_TYPE_RAW));
}
OPTION_CALLBACK (get_all_raw_data)
{
CHECK_RESULT (set_globals ());
CHECK_RESULT (for_each_image (glob_folder, save_raw_action, 0));
if (!glob_recurse)
return (GP_OK);
return for_each_subfolder(glob_folder, for_each_image, save_raw_action, glob_recurse);
}
OPTION_CALLBACK (get_audio_data)
{
return (get_picture_common (arg, GP_FILE_TYPE_AUDIO));
}
OPTION_CALLBACK (get_all_audio_data)
{
CHECK_RESULT (set_globals ());
CHECK_RESULT (for_each_image (glob_folder, save_audio_action, 0));
if (!glob_recurse)
return (GP_OK);
return for_each_subfolder (glob_folder, for_each_image, save_audio_action, glob_recurse);
}
OPTION_CALLBACK (delete_picture)
{
cli_debug_print("Deleting picture(s) %s", arg);
CHECK_RESULT (set_globals ());
return for_each_image_in_range(glob_folder, arg, delete_picture_action, 1);
}
OPTION_CALLBACK (delete_all_pictures)
{
cli_debug_print("Deleting all pictures");
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_folder_delete_all (glob_camera, glob_folder));
return (GP_OK);
}
OPTION_CALLBACK (upload_picture)
{
CameraFile *file;
int res;
cli_debug_print("Uploading picture");
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_file_new (&file));
res = gp_file_open (file, arg);
if (res < 0) {
gp_file_unref (file);
return (res);
}
res = gp_camera_folder_put_file (glob_camera, glob_folder, file);
gp_file_unref (file);
return (res);
}
OPTION_CALLBACK (make_dir)
{
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_folder_make_dir (glob_camera,
glob_folder, arg));
return (GP_OK);
}
OPTION_CALLBACK (remove_dir)
{
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_folder_remove_dir (glob_camera,
glob_folder, arg));
return (GP_OK);
}
static int
capture_generic (CameraCaptureType type, char *name)
{
CameraFilePath path;
char *pathsep;
int result;
CHECK_RESULT (set_globals ());
result = gp_camera_capture (glob_camera, type, &path);
if (result != GP_OK) {
cli_error_print("Could not capture.");
return (result);
}
if (strcmp(path.folder, "/") == 0)
pathsep = "";
else
pathsep = "/";
if (glob_quiet)
printf ("%s%s%s\n", path.folder, pathsep, path.name);
else
printf ("New file is in location %s%s%s on the camera\n",
path.folder, pathsep, path.name);
return (GP_OK);
}
OPTION_CALLBACK (capture_image)
{
return (capture_generic (GP_CAPTURE_IMAGE, arg));
}
OPTION_CALLBACK (capture_movie)
{
return (capture_generic (GP_CAPTURE_MOVIE, arg));
}
OPTION_CALLBACK (capture_sound)
{
return (capture_generic (GP_CAPTURE_SOUND, arg));
}
OPTION_CALLBACK (capture_preview)
{
CameraFile *file;
int result;
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_file_new (&file));
#if HAVE_AA
result = gp_cmd_capture_preview (glob_camera, file);
#else
result = gp_camera_capture_preview (glob_camera, file);
#endif
if (result < 0) {
gp_file_free (file);
return (result);
}
result = save_camera_file_to_file (file, GP_FILE_TYPE_NORMAL);
if (result < 0) {
gp_file_free (file);
return (result);
}
gp_file_free (file);
return (GP_OK);
}
OPTION_CALLBACK(summary)
{
CameraText buf;
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_get_summary (glob_camera, &buf));
printf("Camera Summary:\n%s\n", buf.text);
return (GP_OK);
}
OPTION_CALLBACK (manual)
{
CameraText buf;
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_get_manual (glob_camera, &buf));
printf ("Camera Manual:\n%s\n", buf.text);
return (GP_OK);
}
OPTION_CALLBACK (about)
{
CameraText buf;
CHECK_RESULT (set_globals ());
CHECK_RESULT (gp_camera_get_about (glob_camera, &buf));
printf ("About the library:\n%s\n", buf.text);
return (GP_OK);
}
/* Set/init global variables */
/* ------------------------------------------------------------ */
static int
set_globals (void)
{
CameraList list;
CameraAbilitiesList *al;
GPPortInfoList *il;
GPPortInfo info;
CameraAbilities abilities;
int model = -1, port = -1, count;
const char *name, *value;
static int initialized = 0;
if (initialized)
return (GP_OK);
initialized = 1;
/* takes all the settings and sets up the gphoto lib */
cli_debug_print ("Setting globals...");
CHECK_RESULT (gp_camera_new (&glob_camera));
CHECK_RESULT (gp_abilities_list_new (&al));
CHECK_RESULT (gp_abilities_list_load (al));
CHECK_RESULT (gp_port_info_list_new (&il));
CHECK_RESULT (gp_port_info_list_load (il));
/* Model? */
if (!strcmp ("", glob_model)) {
CHECK_RESULT (gp_abilities_list_detect (al, il, &list));
count = gp_list_count (&list);
CHECK_RESULT (count);
if (count == 1) {
/* Exactly one camera detected */
CHECK_RESULT (gp_list_get_name (&list, 0, &name));
CHECK_RESULT (gp_list_get_value (&list, 0, &value));
model = gp_abilities_list_lookup_model (al, name);
CHECK_RESULT (model);
port = gp_port_info_list_lookup_path (il, value);
CHECK_RESULT (port);
} else if (!count) {
/* No camera detected. Have a look at the settings */
gp_setting_get ("gphoto2", "model", glob_model);
model = gp_abilities_list_lookup_model (al, glob_model);
if (model < 0) {
cli_error_print (_("Please specify a model."));
return (GP_ERROR_MODEL_NOT_FOUND);
}
} else {
/* More than one camera detected */
//FIXME: Let the user choose from the list!
CHECK_RESULT (gp_list_get_name (&list, 0, &name));
CHECK_RESULT (gp_list_get_value (&list, 0, &value));
model = gp_abilities_list_lookup_model (al, name);
CHECK_RESULT (model);
port = gp_port_info_list_lookup_path (il, value);
CHECK_RESULT (port);
}
} else {
model = gp_abilities_list_lookup_model (al, glob_model);
CHECK_RESULT (model);
}
CHECK_RESULT (gp_abilities_list_get_abilities (al, model, &abilities));
CHECK_RESULT (gp_camera_set_abilities (glob_camera, abilities));
gp_setting_set ("gphoto2", "model", abilities.model);
/* Port? */
if (strcmp (glob_model, "Directory Browse") && (port < 0)) {
if (strcmp ("", glob_port)) {
port = gp_port_info_list_lookup_path (il, glob_port);
switch (port) {
case GP_ERROR_UNKNOWN_PORT:
cli_error_print (_("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:')."), glob_port);
default:
break;
}
CHECK_RESULT (port);
} else {
/* Let's have a look at the settings */
gp_setting_get ("gphoto2", "port", glob_port);
port = gp_port_info_list_lookup_path (il, glob_port);
if (port < 0) {
cli_error_print (_("Please specify a port."));
return (GP_ERROR_UNKNOWN_PORT);
}
}
}
/* We set the port not in case of "Directory Browse" */
if (strcmp (glob_model, "Directory Browse")) {
CHECK_RESULT (gp_port_info_list_get_info (il, port, &info));
CHECK_RESULT (gp_camera_set_port_info (glob_camera, info));
gp_setting_set ("gphoto2", "port", info.path);
}
gp_abilities_list_free (al);
gp_port_info_list_free (il);
/*
* Setting of speed only makes sense for serial ports. gphoto2
* knows that and will complain if we try to set the speed for
* ports other than serial ones. Because we are paranoid here and
* check every single error message returned by gphoto2, we need
* to make sure that we have a serial port.
*/
if (!strncmp (glob_port, "serial:", 7))
CHECK_RESULT (gp_camera_set_port_speed (glob_camera, glob_speed));
gp_camera_set_status_func (glob_camera, status_func, NULL);
gp_camera_set_progress_func (glob_camera, progress_func, NULL);
gp_camera_set_message_func (glob_camera, message_func, NULL);
return (GP_OK);
}
static int
init_globals (void)
{
glob_option_count = 0;
strcpy (glob_model, "");
strcpy (glob_port, "");
strcpy (glob_filename, "gphoto");
strcpy (glob_folder, "/");
if (!getcwd (glob_owd, 1023))
strcpy (glob_owd, "./");
strcpy (glob_cwd, glob_owd);
glob_camera = NULL;
glob_speed = 0;
glob_debug = 0;
glob_quiet = 0;
glob_filename_override = 0;
glob_recurse = 0;
return GP_OK;
}
/* Misc functions */
/* ------------------------------------------------------------------ */
void
cli_debug_print (char *format, ...)
{
va_list pvar;
if (glob_debug) {
fprintf(stderr, "cli: ");
va_start(pvar, format);
vfprintf(stderr, format, pvar);
va_end(pvar);
fprintf(stderr, "\n");
}
}
void
cli_error_print (char *format, ...)
{
va_list pvar;
fprintf(stderr, "ERROR: ");
va_start(pvar, format);
vfprintf(stderr, format, pvar);
va_end(pvar);
fprintf(stderr, "\n");
}
static void
signal_exit (int signo)
{
if (!glob_quiet)
printf("\nExiting gPhoto...\n");
/* If we've got a camera, unref it */
if (glob_camera) {
gp_camera_unref (glob_camera);
glob_camera = NULL;
}
if (strlen(glob_owd)>0)
chdir(glob_owd);
exit (EXIT_SUCCESS);
}
/* Main :) */
/* -------------------------------------------------------------------- */
int
main (int argc, char **argv)
{
int result;
/* For translation */
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, GPHOTO2_LOCALEDIR);
textdomain (PACKAGE);
/* Initialize the globals */
init_globals();
signal(SIGINT, signal_exit);
/* Count the number of command-line options we have */
while ((strlen(option[glob_option_count].short_id)>0) ||
(strlen(option[glob_option_count].long_id)>0)) {
glob_option_count++;
}
/* Peek ahead: Turn on quiet if they gave the flag */
if (option_is_present("q", argc, argv)==GP_OK)
glob_quiet=1;
/* Peek ahead: Check to see if we need to turn on debugging output */
if (option_is_present("debug", argc, argv)==GP_OK)
glob_debug=GP_DEBUG_HIGH;
#ifdef OS2 /*check if environment is set otherwise quit*/
if(CAMLIBS==NULL)
{
printf("gPhoto2 for OS/2 requires you to set the enviroment value CAMLIBS \
to the location of the camera libraries. \
e.g. SET CAMLIBS=C:\\GPHOTO2\\CAM\n");
exit(EXIT_FAILURE);
}
#endif
#ifdef OS2 /*check if environment is set otherwise quit*/
if(IOLIBS==NULL)
{
printf("gPhoto2 for OS/2 requires you to set the enviroment value IOLIBS \
to the location of the io libraries. \
e.g. SET IOLIBS=C:\\GPHOTO2\\IOLIB\n");
exit(EXIT_FAILURE);
}
#endif
/* Peek ahead: Make sure we were called correctly */
if ((argc == 1)||(verify_options(argc, argv) != GP_OK)) {
if (!glob_quiet)
usage();
exit(EXIT_FAILURE);
}
gp_camera_set_error (glob_camera, NULL);
result = execute_options(argc, argv);
if (result < 0) {
printf (_("*** Error ('%s') ***\n"),
_(gp_result_as_string (result)));
printf (_("The following message is the last internal error "
"message.\n"
"This message may currently still be unrelated to "
"the real error:\n\n"
"%s\n\n"), _(gp_camera_get_error (glob_camera)));
if (!glob_debug)
printf (_("For debugging messages, please use the "
"--debug option.\n"));
exit (EXIT_FAILURE);
}
#ifdef OS2
// printf("\nErrors occuring beyond this point are 'expected' on OS/2\ninvestigation pending\n");
#endif
/* Unref existing cameras */
if (glob_camera) {
gp_camera_unref (glob_camera);
glob_camera = NULL;
}
return (EXIT_SUCCESS);
}