1 /*
2  */
3 
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/time.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <gphoto2/gphoto2.h>
14 
15 #include "samples.h"
16 
17 static void
errordumper(GPLogLevel level,const char * domain,const char * str,void * data)18 errordumper(GPLogLevel level, const char *domain, const char *str, void *data) {
19 	fprintf(stderr, "%s\n", str);
20 }
21 
22 static struct queue_entry {
23 	CameraFilePath	path;
24 	int offset;
25 } *queue = NULL;
26 static int nrofqueue=0;
27 static int nrdownloads=0;
28 
29 static const char *buffer;
30 
31 static int
wait_event_and_download(Camera * camera,int waittime,GPContext * context)32 wait_event_and_download (Camera *camera, int waittime, GPContext *context) {
33 	CameraEventType	evtype;
34 	CameraFilePath	*path;
35 	void		*data;
36 	int		retval;
37         struct timeval	start, curtime;
38 
39         gettimeofday (&start, NULL);
40 	data = NULL;
41 	if (nrofqueue)
42 		waittime = 10; /* just drain the event queue */
43 
44 	while (1) {
45 		int timediff;
46 
47 	        gettimeofday (&curtime, NULL);
48 
49 		timediff = ((curtime.tv_sec - start.tv_sec)*1000)+((curtime.tv_usec - start.tv_usec)/1000);
50 		if (timediff >= waittime)
51 			break;
52 
53 		retval = gp_camera_wait_for_event(camera, waittime - timediff, &evtype, &data, context);
54 		if (retval != GP_OK) {
55 			fprintf (stderr, "return from waitevent in trigger sample with %d\n", retval);
56 			return retval;
57 		}
58 		path = data;
59 		switch (evtype) {
60 		case GP_EVENT_CAPTURE_COMPLETE:
61 			fprintf (stderr, "wait for event CAPTURE_COMPLETE\n");
62 			break;
63 		case GP_EVENT_UNKNOWN:
64 		case GP_EVENT_TIMEOUT:
65 			break;
66 		case GP_EVENT_FOLDER_ADDED:
67 			fprintf (stderr, "wait for event FOLDER_ADDED\n");
68 			free(data);
69 			break;
70 		case GP_EVENT_FILE_CHANGED:
71 			fprintf (stderr, "wait for event FILE_CHANGED\n");
72 			free(data);
73 			break;
74 		case GP_EVENT_FILE_ADDED:
75 			fprintf (stderr, "File %s / %s added to queue.\n", path->folder, path->name);
76 			if (nrofqueue) {
77 				struct queue_entry *q;
78 				q = realloc(queue, sizeof(struct queue_entry)*(nrofqueue+1));
79 				if (!q) return GP_ERROR_NO_MEMORY;
80 				queue = q;
81 			} else {
82 				queue = malloc (sizeof(struct queue_entry));
83 				if (!queue) return GP_ERROR_NO_MEMORY;
84 			}
85 			memcpy (&queue[nrofqueue].path, path, sizeof(CameraFilePath));
86 			queue[nrofqueue].offset = 0;
87 			nrofqueue++;
88 			free(data);
89 			break;
90 		}
91 	}
92 	if (nrofqueue) {
93 		unsigned long	size;
94 		int		fd;
95 		struct stat	stbuf;
96 		CameraFile	*file;
97 
98 		retval = gp_file_new(&file);
99 
100 		fprintf(stderr,"camera getfile of %s / %s\n",
101 			queue[0].path.folder,
102 			queue[0].path.name
103 		);
104 		retval = gp_camera_file_get(camera, queue[0].path.folder, queue[0].path.name,
105 			GP_FILE_TYPE_NORMAL, file, context);
106 		if (retval != GP_OK) {
107 			fprintf (stderr,"gp_camera_file_get failed: %d\n", retval);
108 			gp_file_free (file);
109 			return retval;
110 		}
111 
112 		/* buffer is returned as pointer, not as a copy */
113 		retval = gp_file_get_data_and_size (file, &buffer, &size);
114 
115 		if (retval != GP_OK) {
116 			fprintf (stderr,"gp_file_get_data_and_size failed: %d\n", retval);
117 			gp_file_free (file);
118 			return retval;
119 		}
120 		if (-1 == stat(queue[0].path.name, &stbuf))
121 			fd = creat(queue[0].path.name, 0644);
122 		else
123 			fd = open(queue[0].path.name, O_RDWR | O_BINARY, 0644);
124 		if (fd == -1) {
125 			perror(queue[0].path.name);
126 			return GP_ERROR;
127 		}
128 		if (-1 == lseek(fd, 0, SEEK_SET))
129 			perror("lseek");
130 		if (-1 == write (fd, buffer, size))
131 			perror("write");
132 		close (fd);
133 
134 		gp_file_free (file); /* Note: this invalidates buffer. */
135 
136 		fprintf(stderr,"ending download %d, deleting file.\n", nrdownloads);
137 		retval = gp_camera_file_delete(camera, queue[0].path.folder, queue[0].path.name, context);
138 		memmove(&queue[0],&queue[1],sizeof(queue[0])*(nrofqueue-1));
139 		nrofqueue--;
140 	}
141 	return GP_OK;
142 }
143 
144 int
main(int argc,char ** argv)145 main(int argc, char **argv) {
146 	Camera		*camera;
147 	int		retval, nrcapture = 0;
148 	struct timeval	tval;
149 	GPContext 	*context = sample_create_context();
150 
151 	gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
152 	/*gp_log_add_func(GP_LOG_DATA, errordumper, NULL); */
153 	gp_camera_new(&camera);
154 
155 	retval = gp_camera_init(camera, context);
156 	if (retval != GP_OK) {
157 		printf("gp_camera_init: %d\n", retval);
158 		exit (1);
159 	}
160 	while (1) {
161 		if ((time(NULL) & 1) == 1)  {
162 			fprintf(stderr,"triggering capture %d\n", ++nrcapture);
163 			retval = gp_camera_trigger_capture (camera, context);
164 			if ((retval != GP_OK) && (retval != GP_ERROR) && (retval != GP_ERROR_CAMERA_BUSY)) {
165 				fprintf(stderr,"triggering capture had error %d\n", retval);
166 				break;
167 			}
168 			fprintf (stderr, "done triggering\n");
169 		}
170 		/*fprintf(stderr,"waiting for events\n");*/
171 		retval = wait_event_and_download(camera, 100, context);
172 		if (retval != GP_OK)
173 			break;
174 		/*fprintf(stderr,"end waiting for events\n");*/
175 		gettimeofday (&tval, NULL);
176 		fprintf(stderr,"loop is at %d.%06d\n", (int)tval.tv_sec,(int)tval.tv_usec);
177 	}
178 	gp_camera_exit(camera, context);
179 	return 0;
180 }
181