1 /*
2  * This program does the equivalent of:
3  * gphoto2 --wait-event-and-download
4  *
5  * compile with: gcc -Wall -o sample-tether sample-tether.c context.c -lgphoto2
6  *
7  */
8 
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <gphoto2/gphoto2.h>
17 
18 #include "samples.h"
19 
errordumper(GPLogLevel level,const char * domain,const char * str,void * data)20 static void errordumper(GPLogLevel level, const char *domain, const char *str,
21                  void *data) {
22   fprintf(stdout, "%s\n", str);
23 }
24 
25 static void
camera_tether(Camera * camera,GPContext * context)26 camera_tether(Camera *camera, GPContext *context) {
27 	int fd, retval;
28 	CameraFile *file;
29 	CameraEventType	evttype;
30 	CameraFilePath	*path;
31 	void	*evtdata;
32 
33 	printf("Tethering...\n");
34 
35 	while (1) {
36 		retval = gp_camera_wait_for_event (camera, 1000, &evttype, &evtdata, context);
37 		if (retval != GP_OK)
38 			break;
39 		switch (evttype) {
40 		case GP_EVENT_FILE_ADDED:
41 			path = (CameraFilePath*)evtdata;
42 			printf("File added on the camera: %s/%s\n", path->folder, path->name);
43 
44 			fd = open (path->name, O_CREAT | O_WRONLY | O_BINARY, 0644);
45 			retval = gp_file_new_from_fd(&file, fd);
46 			printf("  Downloading %s...\n", path->name);
47 			retval = gp_camera_file_get(camera, path->folder, path->name,
48 				     GP_FILE_TYPE_NORMAL, file, context);
49 
50 			printf("  Deleting %s on camera...\n", path->name);
51 			retval = gp_camera_file_delete(camera, path->folder, path->name, context);
52 			gp_file_free(file);
53 			free(evtdata);
54 			break;
55 		case GP_EVENT_FOLDER_ADDED:
56 			path = (CameraFilePath*)evtdata;
57 			printf("Folder added on camera: %s / %s\n", path->folder, path->name);
58 			free(evtdata);
59 			break;
60 		case GP_EVENT_FILE_CHANGED:
61 			path = (CameraFilePath*)evtdata;
62 			printf("File changed on camera: %s / %s\n", path->folder, path->name);
63 			free(evtdata);
64 			break;
65 		case GP_EVENT_CAPTURE_COMPLETE:
66 			printf("Capture Complete.\n");
67 			break;
68 		case GP_EVENT_TIMEOUT:
69 			printf("Timeout.\n");
70 			break;
71 		case GP_EVENT_UNKNOWN:
72 			if (evtdata) {
73 				printf("Unknown event: %s.\n", (char*)evtdata);
74 			} else {
75 				printf("Unknown event.\n");
76 			}
77 			break;
78 		default:
79 			printf("Type %d?\n", evttype);
80 			break;
81 		}
82 	}
83 }
84 
85 int
main(int argc,char ** argv)86 main(int argc, char **argv) {
87 	Camera	*camera;
88 	int	retval;
89 	GPContext *context = sample_create_context();
90 
91 	gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
92 	gp_camera_new(&camera);
93 
94 	/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
95 	 * init function seems to traverse the entire filesystem on the camera.  This
96 	 * is partly why it takes so long.
97 	 * (Marcus: the ptp2 driver does this by default currently.)
98 	 */
99 	printf("Camera init.  Takes about 10 seconds.\n");
100 	retval = gp_camera_init(camera, context);
101 	if (retval != GP_OK) {
102 		printf("  Retval: %d\n", retval);
103 		exit (1);
104 	}
105 
106 	camera_tether(camera, context);
107 
108 	gp_camera_exit(camera, context);
109 	return 0;
110 }
111