1 /* compile with gcc -Wall -o sample-photobooth -lgphoto2 sample-photobooth.c
2 *
3 */
4
5 #include <stdlib.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <gphoto2/gphoto2.h>
14
15 #include "samples.h"
16
17 #define CONFIG_FILE "config.txt"
18 #define PREVIEW "preview.jpg"
19
errordumper(GPLogLevel level,const char * domain,const char * str,void * data)20 static void errordumper(GPLogLevel level, const char *domain, const char *str, void *data) {
21 /* printf("%s (data %p)\n", str,data);*/
22 }
23
24 /* set by signal handler */
25 static int capture_now = 0;
26 static int read_config = 0;
27
28 static int
capture_to_file(Camera * camera,GPContext * context,char * fn)29 capture_to_file(Camera *camera, GPContext *context, char *fn) {
30 int fd, retval;
31 CameraFile *file;
32 CameraFilePath camera_file_path;
33 char *s, *t;
34
35 retval = gp_camera_capture(camera, GP_CAPTURE_IMAGE, &camera_file_path, context);
36 if (retval < GP_OK) return retval;
37
38 s = strrchr (fn, '.');
39 t = strrchr (camera_file_path.name, '.');
40 /* replace the suffix by the one sent by the camera .. for RAW capture */
41 if (t && s && (strlen(t+1) == 3) && (strlen(s+1) == 3)) {
42 strcpy (s+1, t+1);
43 }
44
45 fd = open (fn, O_CREAT | O_WRONLY | O_BINARY, 0644);
46 if (fd == -1)
47 return GP_ERROR;
48
49 retval = gp_file_new_from_fd(&file, fd);
50 if (retval < GP_OK) {
51 close(fd);
52 unlink(fn);
53 return retval;
54 }
55
56 retval = gp_camera_file_get(camera, camera_file_path.folder, camera_file_path.name,
57 GP_FILE_TYPE_NORMAL, file, context);
58 if (retval < GP_OK) {
59 gp_file_free(file);
60 unlink(fn);
61 return retval;
62 }
63
64 retval = gp_camera_file_delete(camera, camera_file_path.folder, camera_file_path.name, context);
65 gp_file_free(file);
66 return GP_OK;
67 }
68
69 static void
sig_handler_capture_now(int sig_num)70 sig_handler_capture_now (int sig_num)
71 {
72 #if !defined (WIN32)
73 signal (SIGUSR1, sig_handler_capture_now);
74 #endif
75 capture_now = 1;
76 }
77
78 static void
sig_handler_read_config(int sig_num)79 sig_handler_read_config (int sig_num)
80 {
81 #if !defined (WIN32)
82 signal (SIGUSR2, sig_handler_read_config);
83 #endif
84 read_config = 1;
85 }
86
87 int
main(int argc,char ** argv)88 main(int argc, char **argv) {
89 Camera *camera;
90 int retval;
91 int capturecnt = 0;
92 GPContext *context = sample_create_context();
93
94 printf("Sample photobooth.\n");
95 printf("Continuously stores previews in 'preview.jpg'.\n");
96 printf("kill -USR1 %d to take a capture.\n", getpid());
97 printf("kill -USR2 %d to read the 'config.txt'.\n", getpid());
98 printf("kill -TERM %d to finish.\n", getpid());
99
100 #if !defined (WIN32)
101 signal (SIGUSR1, sig_handler_capture_now);
102 signal (SIGUSR2, sig_handler_read_config);
103 #endif
104
105 gp_log_add_func(GP_LOG_ERROR, errordumper, 0);
106 gp_camera_new(&camera);
107
108 retval = gp_camera_init(camera, context);
109 if (retval != GP_OK) {
110 printf(" Retval: %d\n", retval);
111 exit (1);
112 }
113
114 while (1) {
115 CameraFile *file;
116 char output_file[32];
117
118 /*
119 * Capture a full picture on demand. Use unique filenames.
120 */
121 if (capture_now) {
122 capture_now = 0;
123 sprintf(output_file, "image-%04d.jpg", capturecnt++);
124 retval = capture_to_file(camera, context, output_file);
125 if (retval == GP_OK)
126 fprintf (stderr, "captured to %s\n", output_file);
127 }
128
129 /*
130 * Read configuration changes from "config.txt".
131 * Expected are key=value pairs where value is the value seen in "--get-config key", e.g.
132 * iso=Auto
133 * iso=200
134 * shutterspeed=1/200
135 */
136 if (read_config) {
137 FILE *config;
138 char buf[512];
139
140 read_config = 0;
141
142 config = fopen (CONFIG_FILE, "r");
143 while (fgets (buf, sizeof(buf), config)) {
144 char *s;
145
146 /* kill linefeeds */
147 s = strchr(buf,'\r');
148 if (s)
149 *s=0;
150 s = strchr(buf,'\n');
151 if (s)
152 *s=0;
153
154 s = strchr(buf,'=');
155 if (!s) continue;
156
157 *s=0;
158 retval = set_config_value_string (camera, buf, s+1, context);
159 if (retval < GP_OK)
160 fprintf (stderr, "setting configuration '%s' to '%s' failed with %d.\n", buf, s+1, retval);
161 else
162 fprintf (stderr, "changed configuration '%s' to '%s'\n", buf, s+1);
163 }
164 fclose (config);
165 }
166
167 /*
168 * Capture a preview on every loop. Save as preview.jpg.
169 */
170 retval = gp_file_new(&file);
171 if (retval != GP_OK) {
172 fprintf(stderr,"gp_file_new: %d\n", retval);
173 exit(1);
174 }
175
176 retval = gp_camera_capture_preview(camera, file, context);
177 if (retval != GP_OK) {
178 fprintf(stderr,"gp_camera_capture_preview failed: %d\n", retval);
179 exit(1);
180 }
181 retval = gp_file_save(file, PREVIEW);
182 if (retval != GP_OK) {
183 fprintf(stderr,"saving preview failed: %d\n", retval);
184 exit(1);
185 }
186 gp_file_unref(file);
187 /*
188 * Check and drain the event queue.
189 * Download newly captured images.
190 * Ignore the rest events.
191 */
192 while (1) {
193 CameraEventType evttype;
194 CameraFilePath *path;
195 void *evtdata;
196 int fd;
197
198 evtdata = NULL;
199 retval = gp_camera_wait_for_event (camera, 1, &evttype, &evtdata, context);
200 if (retval != GP_OK) break;
201 switch (evttype) {
202 case GP_EVENT_FILE_ADDED: {
203 char *t;
204
205 path = (CameraFilePath*)evtdata;
206 t = strrchr (path->name, '.');
207 if (t && (strlen(t+1) == 3)) {
208 sprintf(output_file, "image-%04d.%s", capturecnt++, t+1);
209 } else {
210 sprintf(output_file, "image-%04d.jpg", capturecnt++);
211 }
212
213 fd = open (output_file, O_CREAT | O_WRONLY | O_BINARY, 0644);
214 retval = gp_file_new_from_fd(&file, fd);
215 retval = gp_camera_file_get(camera, path->folder, path->name,
216 GP_FILE_TYPE_NORMAL, file, context);
217
218 retval = gp_camera_file_delete(camera, path->folder, path->name, context);
219 gp_file_free(file);
220 free (evtdata);
221 fprintf (stderr, "saved to %s\n", output_file);
222 break;
223 }
224 case GP_EVENT_FILE_CHANGED:
225 path = (CameraFilePath*)evtdata;
226 printf("File changed on camera: %s / %s\n", path->folder, path->name);
227 free (evtdata);
228 break;
229 case GP_EVENT_FOLDER_ADDED:
230 path = (CameraFilePath*)evtdata;
231 printf("Folder added on camera: %s / %s\n", path->folder, path->name);
232 free (evtdata);
233 break;
234 case GP_EVENT_CAPTURE_COMPLETE:
235 printf("Capture Complete.\n");
236 break;
237 case GP_EVENT_TIMEOUT:
238 break;
239 case GP_EVENT_UNKNOWN:
240 if (evtdata) {
241 printf("Unknown event: %s.\n", (char*)evtdata);
242 free (evtdata);
243 } else {
244 printf("Unknown event.\n");
245 }
246 break;
247 default:
248 printf("Type %d?\n", evttype);
249 break;
250 }
251 if (evttype == GP_EVENT_TIMEOUT)
252 break;
253 }
254 }
255 gp_camera_exit(camera, context);
256 return 0;
257 }
258