* include/gphoto2-file.h:
* include/gphoto2-library.h:
* include/gphoto2-camera.h: Support for raw data.
* libpghoto2/file.c: Adjust to above changes.
* libgphoto2/frontend.c: Kill a warning.
* libgphoto2/libgphoto-2.0.pc.in: CFlags -> Cflags
* libgphoto2/widget.c: Include gphoto2-result.h instead of gphoto2.h
* camlibs/*: Prepare support for download of raw data. Remove lots of
redundant code (people just copied & pasted the code for file_get
and file_get_preview...). I hope everything works as it did before.
* frontend/command-line/*: Prepare support for download of raw data
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@2072 67ed7778-7388-44ab-90cf-0a291f65f57c
403 lines
8.2 KiB
C
403 lines
8.2 KiB
C
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "main.h"
|
|
#include "globals.h"
|
|
#include "shell.h"
|
|
|
|
|
|
/* Valid shell commands */
|
|
shell_function func[] = {
|
|
{"cd", shell_cd, "Change to a directory on the camera", "directory"},
|
|
{"lcd", shell_lcd, "Change to a directory on the local drive", "directory"},
|
|
{"exit", shell_exit, "Exit the gPhoto shell", ""},
|
|
{"get", shell_get, "Download the file to the current directory", "[directory/]filename"},
|
|
{"get-thumbnail", shell_get_thumbnail, "Download the thumbnail to the current directory", "[directory/]filename"},
|
|
{"help", shell_help, "Displays command usage", "command"},
|
|
{"ls", shell_ls, "List the contents of the current directory", "[directory/]"},
|
|
{"q", shell_exit, "Exit the gPhoto shell", ""},
|
|
{"quit", shell_exit, "Exit the gPhoto shell", ""},
|
|
{"?", shell_help, "Displays command usage", ""},
|
|
{"", NULL}
|
|
};
|
|
|
|
/* Local globals */
|
|
char* shell_prompt_text = "gphoto: {%s} %s> ";
|
|
int shell_done = 0;
|
|
|
|
static int
|
|
shell_arg_count (char *args)
|
|
{
|
|
int x=0, in_arg=0, count=0;
|
|
|
|
while (x < strlen(args)) { /* Edge-triggered */
|
|
if ((!isspace(args[x])) && (!in_arg)) {
|
|
in_arg = 1;
|
|
count++;
|
|
}
|
|
if ((isspace(args[x])) && (in_arg))
|
|
in_arg = 0;
|
|
x++;
|
|
}
|
|
|
|
return (count);
|
|
}
|
|
|
|
static int
|
|
shell_arg (char *args, int arg_num, char *arg)
|
|
{
|
|
int x=0, y=0, in_arg=0, count=0, copy=0;
|
|
|
|
if (arg_num > shell_arg_count(args)-1)
|
|
return (GP_ERROR);
|
|
|
|
while (x < strlen(args)) { /* Edge-triggered */
|
|
if ((!isspace(args[x])) && (!in_arg)) {
|
|
in_arg = 1;
|
|
if (count == arg_num)
|
|
copy = 1;
|
|
count++;
|
|
}
|
|
if ((isspace(args[x])) && (in_arg)) {
|
|
copy = 0;
|
|
in_arg = 0;
|
|
}
|
|
|
|
if (copy) /* Copy over the chars */
|
|
arg[y++] = args[x];
|
|
x++;
|
|
}
|
|
|
|
arg[y] = 0; /* null-terminate the arg */
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_prompt (void)
|
|
{
|
|
int x, found;
|
|
char buf[1024], cmd[1024], arg[1024];
|
|
|
|
while (!shell_done) {
|
|
found=0;
|
|
if (glob_quiet) {
|
|
printf(">\n");
|
|
} else {
|
|
if (strlen(glob_cwd) > 25) {
|
|
strcpy(buf, "...");
|
|
strcat(buf, &glob_cwd[strlen(glob_cwd)-22]);
|
|
} else {
|
|
strcpy(buf, glob_cwd);
|
|
}
|
|
printf(shell_prompt_text, buf, glob_folder); /* Display prompt text */
|
|
}
|
|
fflush(stdout);
|
|
fgets(buf, 1023, stdin); /* Get the command/args */
|
|
buf[strlen(buf)-1]=0; /* Chop the newline */
|
|
|
|
/* Extract command and argument */
|
|
if (shell_arg_count(buf) > 0) {
|
|
shell_arg (buf, 0, cmd);
|
|
strcpy(arg, &buf[strlen(cmd)]);
|
|
x=-1;
|
|
while (func[++x].function) { /* Execute the associated function */
|
|
if (strcmp(cmd, func[x].command)==0) {
|
|
found = 1;
|
|
func[x].function(arg);
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
cli_error_print("Invalid command");
|
|
}
|
|
}
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
shell_get_new_folder (char *relative_path, char *cd_arg, char *new_folder)
|
|
{
|
|
/*
|
|
Find what the new folder will be based on the "cd" or "ls" argument.
|
|
This can take paths like:
|
|
"/blah", "./blah", "../blah", "/blah/hey/../doh/blah", etc...
|
|
*/
|
|
|
|
char *dir = NULL, *slash = NULL;
|
|
char tmp_folder[1024];
|
|
int append = 0, x=0;
|
|
|
|
while (isspace(cd_arg[x])) {x++;}
|
|
|
|
if (cd_arg[x] == '/') /* Check if path is relative to root */
|
|
strcpy(tmp_folder, "/");
|
|
else
|
|
strcpy(tmp_folder, relative_path);
|
|
do {
|
|
append = 1;
|
|
if (!dir) /* Get each directory individually */
|
|
dir = strtok(&cd_arg[x], "/");
|
|
else
|
|
dir = strtok(NULL, "/");
|
|
if (!dir)
|
|
break;
|
|
|
|
if (strcmp(dir, ".")==0) /* Do nothing for CWD */
|
|
append = 0;
|
|
|
|
if (strcmp(dir, "..")==0) { /* Move up a directory */
|
|
if (strcmp(tmp_folder, "/")!=0) {
|
|
slash = strrchr(tmp_folder, '/');
|
|
*slash = 0;
|
|
if (strlen(tmp_folder)==0)
|
|
strcpy(tmp_folder, "/");
|
|
}
|
|
append = 0;
|
|
}
|
|
|
|
if (append) { /* Append the dir name */
|
|
if (strcmp(tmp_folder, "/")!=0)
|
|
strcat(tmp_folder, "/");
|
|
strcat(tmp_folder, dir);
|
|
}
|
|
|
|
} while (1);
|
|
|
|
strcpy(new_folder, tmp_folder);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_lcd (char *arg)
|
|
{
|
|
char tmp_dir[1024];
|
|
int arg_count = shell_arg_count(arg);
|
|
|
|
if (!arg_count) {
|
|
if (getenv("HOME")==NULL) {
|
|
cli_error_print("Could not find home directory");
|
|
return (GP_OK);
|
|
}
|
|
strcpy(tmp_dir, getenv("HOME"));
|
|
} else {
|
|
/* shell_arg(arg, 0, arg_dir); */
|
|
shell_get_new_folder(glob_cwd, arg, tmp_dir);
|
|
}
|
|
|
|
if (chdir(tmp_dir)<0) {
|
|
cli_error_print("Could not change to local directory %s", tmp_dir);
|
|
} else {
|
|
printf("Local directory now %s\n", tmp_dir);
|
|
strcpy(glob_cwd, tmp_dir);
|
|
}
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_cd (char *arg)
|
|
{
|
|
char tmp_folder[1024];
|
|
CameraList list;
|
|
int arg_count = shell_arg_count (arg);
|
|
int res;
|
|
|
|
if (!arg_count)
|
|
return (GP_OK);
|
|
|
|
/* shell_arg(arg, 0, arg_dir); */
|
|
|
|
if (strlen (arg) > 1023) {
|
|
cli_error_print ("Folder value is too long");
|
|
return (GP_ERROR);
|
|
}
|
|
|
|
/* Get the new folder value */
|
|
shell_get_new_folder (glob_folder, arg, tmp_folder);
|
|
printf("tmp_folder=%s\n", tmp_folder);
|
|
|
|
res = gp_camera_folder_list_folders (glob_camera, tmp_folder, &list);
|
|
if (res == GP_OK)
|
|
strcpy (glob_folder, tmp_folder);
|
|
else
|
|
cli_error_print ("Folder %s does not exist", tmp_folder);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_ls (char *arg)
|
|
{
|
|
CameraList list;
|
|
char buf[1024], tmp_folder[1024];
|
|
int x, y=1, res;
|
|
int arg_count = shell_arg_count(arg);
|
|
const char *name;
|
|
|
|
if (arg_count) {
|
|
/* shell_arg(arg, 0, arg_dir); */
|
|
shell_get_new_folder (glob_folder, arg, tmp_folder);
|
|
} else {
|
|
strcpy (tmp_folder, glob_folder);
|
|
}
|
|
|
|
res = gp_camera_folder_list_folders (glob_camera, tmp_folder, &list);
|
|
if (res != GP_OK) {
|
|
if (arg_count)
|
|
cli_error_print("Folder %s does not exist", tmp_folder);
|
|
else
|
|
cli_error_print("Could not retrieve the folder list");
|
|
return (res);
|
|
}
|
|
|
|
if (glob_quiet)
|
|
printf ("%i\n", gp_list_count(&list));
|
|
|
|
for (x = 1; x <= gp_list_count (&list); x++) {
|
|
gp_list_get_name (&list, x - 1, &name);
|
|
if (glob_quiet)
|
|
printf ("%s\n", name);
|
|
else {
|
|
sprintf (buf, "%s/", name);
|
|
printf ("%-20s", buf);
|
|
if (y++ % 4 == 0)
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
res = gp_camera_folder_list_files (glob_camera, tmp_folder, &list);
|
|
if (res != GP_OK)
|
|
return (res);
|
|
|
|
if (glob_quiet)
|
|
printf("%i\n", gp_list_count(&list));
|
|
|
|
for (x = 1; x <= gp_list_count (&list); x++) {
|
|
gp_list_get_name (&list, x - 1, &name);
|
|
if (glob_quiet)
|
|
printf ("%s\n", name);
|
|
else {
|
|
printf ("%-20s", name);
|
|
if (y++ % 4 == 0)
|
|
printf("\n");
|
|
}
|
|
}
|
|
if ((!glob_quiet) && (y % 4 != 1))
|
|
printf("\n");
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
static int
|
|
shell_get_common (char *arg, CameraFileType type)
|
|
{
|
|
char tmp_folder[1024];
|
|
char *slash, *tmp_filename;
|
|
int arg_count = shell_arg_count(arg);
|
|
|
|
if (!arg_count) {
|
|
cli_error_print("No filename specified");
|
|
return (GP_ERROR);
|
|
}
|
|
|
|
if (arg_count > 1) {
|
|
cli_error_print("Too many filenames specified");
|
|
return (GP_ERROR);
|
|
}
|
|
|
|
/* shell_arg(arg, 0, arg_filename); */
|
|
|
|
if (strchr(arg, '/')) {
|
|
slash = strrchr(arg, '/');
|
|
tmp_filename = slash + 1;
|
|
*slash = 0;
|
|
if (strlen(arg)==0)
|
|
strcpy(tmp_folder, "/");
|
|
else
|
|
strcpy(tmp_folder, arg);
|
|
} else {
|
|
tmp_filename = arg;
|
|
strcpy(tmp_folder, glob_folder);
|
|
}
|
|
|
|
save_picture_to_file(tmp_folder, tmp_filename, type);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_get_thumbnail (char *arg)
|
|
{
|
|
shell_get_common (arg, GP_FILE_TYPE_PREVIEW);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_get (char *arg)
|
|
{
|
|
|
|
shell_get_common (arg, GP_FILE_TYPE_NORMAL);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_get_raw (char *arg)
|
|
{
|
|
shell_get_common (arg, GP_FILE_TYPE_RAW);
|
|
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_exit (char *arg)
|
|
{
|
|
shell_done = 1;
|
|
return (GP_OK);
|
|
}
|
|
|
|
int
|
|
shell_help (char *arg)
|
|
{
|
|
char arg_cmd[1024];
|
|
int x=0;
|
|
int arg_count = shell_arg_count (arg);
|
|
|
|
if (arg_count > 0) {
|
|
shell_arg(arg, 0, arg_cmd);
|
|
while (func[x].function) {
|
|
if (strcmp (arg_cmd, func[x].command) == 0) {
|
|
printf ("Help on \"%s\":\n\n", arg_cmd);
|
|
printf ("Usage: %s %s\n", arg_cmd,
|
|
func[x].description_arg);
|
|
printf ("Description: \n\t%s\n\n",
|
|
func[x].description);
|
|
printf ("* Arguments in brackets [] are "
|
|
"optional\n");
|
|
return (GP_OK);
|
|
}
|
|
x++;
|
|
}
|
|
cli_error_print ("Command not found in 'help'");
|
|
return (GP_OK);
|
|
}
|
|
|
|
printf ("Available commands:\n");
|
|
|
|
while (func[x].function) {
|
|
printf ("\t%-16s%s\n", func[x].command, func[x].description);
|
|
x++;
|
|
}
|
|
|
|
printf ("\nTo get help on a particular command, type in "
|
|
"'help command-name'\n\n");
|
|
|
|
return (GP_OK);
|
|
}
|