253 lines
6.0 KiB
C
253 lines
6.0 KiB
C
/* compile with gcc -Wall -o sample-photobooth -lgphoto2 sample-photobooth.c
|
|
*
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <gphoto2/gphoto2.h>
|
|
|
|
#include "samples.h"
|
|
|
|
#define CONFIG_FILE "config.txt"
|
|
#define PREVIEW "preview.jpg"
|
|
|
|
static void errordumper(GPLogLevel level, const char *domain, const char *str, void *data) {
|
|
/* printf("%s (data %p)\n", str,data);*/
|
|
}
|
|
|
|
/* set by signal handler */
|
|
static int capture_now = 0;
|
|
static int read_config = 0;
|
|
|
|
static int
|
|
capture_to_file(Camera *camera, GPContext *context, char *fn) {
|
|
int fd, retval;
|
|
CameraFile *file;
|
|
CameraFilePath camera_file_path;
|
|
char *s, *t;
|
|
|
|
retval = gp_camera_capture(camera, GP_CAPTURE_IMAGE, &camera_file_path, context);
|
|
if (retval < GP_OK) return retval;
|
|
|
|
s = strrchr (fn, '.');
|
|
t = strrchr (camera_file_path.name, '.');
|
|
/* replace the suffix by the one sent by the camera .. for RAW capture */
|
|
if (t && s && (strlen(t+1) == 3) && (strlen(s+1) == 3)) {
|
|
strcpy (s+1, t+1);
|
|
}
|
|
|
|
fd = open (fn, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
|
if (fd == -1)
|
|
return GP_ERROR;
|
|
|
|
retval = gp_file_new_from_fd(&file, fd);
|
|
if (retval < GP_OK) {
|
|
close(fd);
|
|
unlink(fn);
|
|
return retval;
|
|
}
|
|
|
|
retval = gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name,
|
|
GP_FILE_TYPE_NORMAL, file, context);
|
|
if (retval < GP_OK) {
|
|
gp_file_free(file);
|
|
unlink(fn);
|
|
return retval;
|
|
}
|
|
|
|
retval = gp_camera_file_delete(camera, camera_file_path.folder, camera_file_path.name, context);
|
|
gp_file_free(file);
|
|
return GP_OK;
|
|
}
|
|
|
|
static void
|
|
sig_handler_capture_now (int sig_num)
|
|
{
|
|
#if !defined (WIN32)
|
|
signal (SIGUSR1, sig_handler_capture_now);
|
|
#endif
|
|
capture_now = 1;
|
|
}
|
|
|
|
static void
|
|
sig_handler_read_config (int sig_num)
|
|
{
|
|
#if !defined (WIN32)
|
|
signal (SIGUSR2, sig_handler_read_config);
|
|
#endif
|
|
read_config = 1;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv) {
|
|
Camera *camera;
|
|
int retval;
|
|
int capturecnt = 0;
|
|
GPContext *context = sample_create_context();
|
|
|
|
printf("Sample photobooth.\n");
|
|
printf("Continously stores previews in 'preview.jpg'.\n");
|
|
printf("kill -USR1 %d to take a capture.\n", getpid());
|
|
printf("kill -USR2 %d to read the 'config.txt'.\n", getpid());
|
|
printf("kill -TERM %d to finish.\n", getpid());
|
|
|
|
#if !defined (WIN32)
|
|
signal (SIGUSR1, sig_handler_capture_now);
|
|
signal (SIGUSR2, sig_handler_read_config);
|
|
#endif
|
|
|
|
gp_log_add_func(GP_LOG_ERROR, errordumper, 0);
|
|
gp_camera_new(&camera);
|
|
|
|
retval = gp_camera_init(camera, context);
|
|
if (retval != GP_OK) {
|
|
printf(" Retval: %d\n", retval);
|
|
exit (1);
|
|
}
|
|
|
|
while (1) {
|
|
CameraFile *file;
|
|
char output_file[32];
|
|
|
|
/*
|
|
* Capture a full picture on demand. Use unique filenames.
|
|
*/
|
|
if (capture_now) {
|
|
capture_now = 0;
|
|
sprintf(output_file, "image-%04d.jpg", capturecnt++);
|
|
retval = capture_to_file(camera, context, output_file);
|
|
if (retval == GP_OK)
|
|
fprintf (stderr, "captured to %s\n", output_file);
|
|
}
|
|
|
|
/*
|
|
* Read configuration changes from "config.txt".
|
|
* Expected are key=value pairs where value is the value seen in "--get-config key", e.g.
|
|
* iso=Auto
|
|
* iso=200
|
|
* shutterspeed=1/200
|
|
*/
|
|
if (read_config) {
|
|
FILE *config;
|
|
char buf[512];
|
|
|
|
read_config = 0;
|
|
|
|
config = fopen (CONFIG_FILE, "r");
|
|
while (fgets (buf, sizeof(buf), config)) {
|
|
char *s;
|
|
|
|
/* kill linefeeds */
|
|
s = strchr(buf,'\r');
|
|
if (s)
|
|
*s=0;
|
|
s = strchr(buf,'\n');
|
|
if (s)
|
|
*s=0;
|
|
|
|
s = strchr(buf,'=');
|
|
if (!s) continue;
|
|
|
|
*s=0;
|
|
retval = set_config_value_string (camera, buf, s+1, context);
|
|
if (retval < GP_OK)
|
|
fprintf (stderr, "setting configuration '%s' to '%s' failed with %d.\n", buf, s+1, retval);
|
|
else
|
|
fprintf (stderr, "changed configuration '%s' to '%s'\n", buf, s+1);
|
|
}
|
|
fclose (config);
|
|
}
|
|
|
|
/*
|
|
* Capture a preview on every loop. Save as preview.jpg.
|
|
*/
|
|
retval = gp_file_new(&file);
|
|
if (retval != GP_OK) {
|
|
fprintf(stderr,"gp_file_new: %d\n", retval);
|
|
exit(1);
|
|
}
|
|
|
|
retval = gp_camera_capture_preview(camera, file, context);
|
|
if (retval != GP_OK) {
|
|
fprintf(stderr,"gp_camera_capture_preview failed: %d\n", retval);
|
|
exit(1);
|
|
}
|
|
retval = gp_file_save(file, PREVIEW);
|
|
if (retval != GP_OK) {
|
|
fprintf(stderr,"saving preview failed: %d\n", retval);
|
|
exit(1);
|
|
}
|
|
gp_file_unref(file);
|
|
/*
|
|
* Check and drain the event queue.
|
|
* Download newly captured images.
|
|
* Ignore the rest events.
|
|
*/
|
|
while (1) {
|
|
CameraEventType evttype;
|
|
CameraFilePath *path;
|
|
void *evtdata;
|
|
int fd;
|
|
|
|
evtdata = NULL;
|
|
retval = gp_camera_wait_for_event (camera, 1, &evttype, &evtdata, context);
|
|
if (retval != GP_OK) break;
|
|
switch (evttype) {
|
|
case GP_EVENT_FILE_ADDED: {
|
|
char *t;
|
|
|
|
path = (CameraFilePath*)evtdata;
|
|
t = strrchr (path->name, '.');
|
|
if (t && (strlen(t+1) == 3)) {
|
|
sprintf(output_file, "image-%04d.%s", capturecnt++, t+1);
|
|
} else {
|
|
sprintf(output_file, "image-%04d.jpg", capturecnt++);
|
|
}
|
|
|
|
fd = open (output_file, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
|
retval = gp_file_new_from_fd(&file, fd);
|
|
retval = gp_camera_file_get(camera, path->folder, path->name,
|
|
GP_FILE_TYPE_NORMAL, file, context);
|
|
|
|
retval = gp_camera_file_delete(camera, path->folder, path->name, context);
|
|
gp_file_free(file);
|
|
free (evtdata);
|
|
fprintf (stderr, "saved to %s\n", output_file);
|
|
break;
|
|
}
|
|
case GP_EVENT_FOLDER_ADDED:
|
|
path = (CameraFilePath*)evtdata;
|
|
printf("Folder added on camera: %s / %s\n", path->folder, path->name);
|
|
free (evtdata);
|
|
break;
|
|
case GP_EVENT_CAPTURE_COMPLETE:
|
|
printf("Capture Complete.\n");
|
|
break;
|
|
case GP_EVENT_TIMEOUT:
|
|
break;
|
|
case GP_EVENT_UNKNOWN:
|
|
if (evtdata) {
|
|
printf("Unknown event: %s.\n", (char*)evtdata);
|
|
free (evtdata);
|
|
} else {
|
|
printf("Unknown event.\n");
|
|
}
|
|
break;
|
|
default:
|
|
printf("Type %d?\n", evttype);
|
|
break;
|
|
}
|
|
if (evttype == GP_EVENT_TIMEOUT)
|
|
break;
|
|
}
|
|
}
|
|
gp_camera_exit(camera, context);
|
|
return 0;
|
|
}
|