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