8 #include <mipea/gpio.h>
12 #include "photobox_photo.h"
16 #define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
20 void pb_show_main(void);
21 void pb_show_send(void);
22 void pb_show_qr(void);
24 gboolean
pb_poll_buttton(void);
25 gboolean
pb_countdown(void);
26 void pb_takepic(void);
28 int pb_cp_dp(char *id
);
30 static GtkWidget
*img
;
31 static GtkWidget
*button_take
;
32 static GtkWidget
*label_countdown
;
34 static GtkWidget
*button_upload
;
35 static GtkWidget
*button_cancel
;
37 static GtkWidget
*qr_img
;
38 static GtkWidget
*qr_label
;
39 static GtkWidget
*qr_button_back
;
41 static const unsigned int IMG_WIDTH
= 512;
42 static const unsigned int IMG_HEIGHT
= 384;
43 static const unsigned int QR_SIZE
= 350;
45 static unsigned int button_pin
= 26;
47 int main(int argc
, char *argv
[])
49 if (pb_ph_init() != 0) {
50 fprintf(stderr
, "ERROR: pb_ph_init\n");
53 if (gpio_map() == NULL
) {
54 fprintf(stderr
, "ERROR: gpio_map\n");
57 gtk_init(&argc
, &argv
);
59 signal(SIGCHLD
, SIG_IGN
);
63 gpio_pud(button_pin
, PUD_UP
);
66 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
67 gtk_window_set_title(GTK_WINDOW(window
), "Photobox");
68 gtk_window_fullscreen(GTK_WINDOW(window
));
69 //g_signal_connect(window, "delete-event", G_CALLBACK(pb_gui_on_delete_main), NULL);
70 g_signal_connect(window
, "destroy", G_CALLBACK(pb_exit
), NULL
);
72 gtk_widget_realize(window
);
73 GdkCursor
* cursor_blank
= gdk_cursor_new(GDK_BLANK_CURSOR
);
74 gdk_window_set_cursor(gtk_widget_get_window(window
), cursor_blank
);
77 GtkWidget
*box_v
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
78 gtk_container_add(GTK_CONTAINER(window
), box_v
);
79 gtk_widget_show(box_v
);
82 GtkWidget
*box_h
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
83 gtk_box_pack_end(GTK_BOX(box_v
), box_h
, TRUE
, FALSE
, 0);
84 gtk_widget_show(box_h
);
87 img
= gtk_image_new_from_file("no_signal.png");
88 gtk_box_pack_end(GTK_BOX(box_v
), img
, TRUE
, FALSE
, 0);
90 // BUTTON: TAKE PICTURE
91 button_take
= gtk_button_new();
93 GtkWidget
*button_take_label
= gtk_label_new(NULL
);
94 gtk_label_set_markup(GTK_LABEL(button_take_label
), "<span font='50'>Bild aufnehmen</span>");
95 gtk_container_add(GTK_CONTAINER(button_take
), button_take_label
);
96 gtk_widget_show(button_take_label
);
98 gtk_box_pack_start(GTK_BOX(box_h
), button_take
, TRUE
, FALSE
, 0);
99 g_signal_connect(button_take
, "clicked", G_CALLBACK(pb_countdown
), NULL
);
102 label_countdown
= gtk_label_new(NULL
);
103 gtk_box_pack_end(GTK_BOX(box_v
), label_countdown
, TRUE
, FALSE
, 0);
106 button_upload
= gtk_button_new_with_label("Hochladen");
107 //g_signal_connect(button_upload, "clicked", G_CALLBACK(pb_exit), NULL);
108 g_signal_connect(button_upload
, "clicked", G_CALLBACK(pb_show_qr
), NULL
);
109 gtk_box_pack_start(GTK_BOX(box_h
), button_upload
, TRUE
, FALSE
, 0);
112 button_cancel
= gtk_button_new_with_label("Abbrechen");
113 //g_signal_connect(button_cancel, "clicked", G_CALLBACK(pb_exit), NULL);
114 g_signal_connect(button_cancel
, "clicked", G_CALLBACK(pb_show_main
), NULL
);
115 gtk_box_pack_start(GTK_BOX(box_h
), button_cancel
, TRUE
, FALSE
, 0);
118 qr_img
= gtk_image_new_from_file("no_signal.png");
119 gtk_box_pack_end(GTK_BOX(box_v
), qr_img
, TRUE
, FALSE
, 0);
122 qr_label
= gtk_label_new(NULL
);
123 gtk_label_set_justify(GTK_LABEL(qr_label
), GTK_JUSTIFY_CENTER
);
124 gtk_label_set_line_wrap(GTK_LABEL(qr_label
), TRUE
);
125 gtk_box_pack_end(GTK_BOX(box_v
), qr_label
, TRUE
, FALSE
, 0);
128 qr_button_back
= gtk_button_new_with_label("Zurück");
129 g_signal_connect(qr_button_back
, "clicked", G_CALLBACK(pb_show_main
), NULL
);
130 //g_signal_connect(qr_button_back, "clicked", G_CALLBACK(pb_exit), NULL);
131 gtk_box_pack_start(GTK_BOX(box_h
), qr_button_back
, TRUE
, FALSE
, 0);
134 gtk_widget_show(window
);
147 void pb_show_main(void)
149 gtk_widget_hide(img
);
150 gtk_widget_hide(button_upload
);
151 gtk_widget_hide(button_cancel
);
152 gtk_widget_hide(qr_img
);
153 gtk_widget_hide(qr_label
);
154 gtk_widget_hide(qr_button_back
);
156 gtk_widget_show(button_take
);
158 // take picture with button
159 g_idle_add(G_SOURCE_FUNC(pb_poll_buttton
), NULL
);
162 void pb_show_send(void)
164 gtk_widget_show(img
);
165 gtk_widget_show(button_upload
);
166 gtk_widget_show(button_cancel
);
168 gtk_widget_hide(label_countdown
);
171 void pb_show_qr(void)
173 gtk_widget_hide(img
);
174 gtk_widget_hide(button_upload
);
175 gtk_widget_hide(button_cancel
);
177 gtk_widget_show(qr_img
);
178 gtk_widget_show(qr_label
);
179 gtk_widget_show(qr_button_back
);
183 strftime(id
, 7, "%H%M%S", localtime(&(time_t) {time(NULL
)}));
187 // child -> copy and upload
188 if (pb_cp_dp(id
) < 0) {
189 fprintf(stderr
, "Error: pb_cp_dp\n");
194 } else if (pid
< 0) {
195 fprintf(stderr
, "FORK ERROR!!!!!\n");
196 // TODO: dont show qr
199 // url qr should point to
200 // example: https://www.dropbox.com/sh/3pq0pwednyuig86/AACx0_vjn-liY5_pP_C3nJD8a?dl=0&preview=c1b052c5.jpg
201 char url
[] = "https://www.dropbox.com/sh/3pq0pwednyuig86/AACx0_vjn-liY5_pP_C3nJD8a?dl=0&preview=xxxxxx.jpg";
202 for (unsigned int i
= 0; i
< 6; ++i
) {
207 QRcode
*qr
= QRcode_encodeString(url
, 0, QR_ECLEVEL_H
, QR_MODE_8
, 1);
209 perror("Failed to generate QR-Code");
213 unsigned int size
= qr
->width
;
215 sprintf(values
, "%d %d 2 1", size
, size
);
217 const char *xface
[3 + size
];
219 xface
[1] = "a c #ffffff";
220 xface
[2] = "b c #000000";
222 char qrcode_char
[size
][size
+ 1];
223 for (unsigned int i
= 0; i
< size
; ++i
) {
224 qrcode_char
[i
][size
] = '\0';
225 for (unsigned int j
= 0; j
< size
; ++j
) {
226 qrcode_char
[i
][j
] = qr
->data
[j
+ i
* size
] & 1 ? 'b' : 'a';
228 xface
[3 + i
] = &qrcode_char
[i
][0];
232 GdkPixbuf
*pb
= gdk_pixbuf_new_from_xpm_data(xface
);
234 pb
= gdk_pixbuf_scale_simple(pb
, QR_SIZE
, QR_SIZE
, GDK_INTERP_NEAREST
);
235 gtk_image_set_from_pixbuf((GtkImage
*)qr_img
, pb
);
238 char text
[] = "<span font='12'>QR-Code scannen oder auf <b>https://www.dropbox.com/sh/3pq0pwednyuig86/AACx0_vjn-liY5_pP_C3nJD8a</b> gehen. <small>Der Upload kann einige Minuten dauern.</small></span>";
239 gtk_label_set_markup(GTK_LABEL(qr_label
), text
);
242 gboolean
pb_poll_buttton(void)
244 if (gpio_tst(button_pin
) == 0) {
246 return G_SOURCE_REMOVE
;
248 return G_SOURCE_CONTINUE
;
252 gboolean
pb_countdown(void)
260 g_idle_remove_by_data(NULL
);
262 gtk_label_set_markup(GTK_LABEL(label_countdown
),
263 "<span font='300' color='red'>5</span>");
264 gtk_widget_hide(button_take
);
265 gtk_widget_show(label_countdown
);
267 g_timeout_add(1000, G_SOURCE_FUNC(pb_countdown
), NULL
);
268 return G_SOURCE_CONTINUE
;
271 gtk_label_set_markup(GTK_LABEL(label_countdown
),
272 "<span font='300' color='red'>4</span>");
273 return G_SOURCE_CONTINUE
;
276 gtk_label_set_markup(GTK_LABEL(label_countdown
),
277 "<span font='300' color='red'>3</span>");
278 return G_SOURCE_CONTINUE
;
281 gtk_label_set_markup(GTK_LABEL(label_countdown
),
282 "<span font='300' color='red'>2</span>");
283 return G_SOURCE_CONTINUE
;
286 gtk_label_set_markup(GTK_LABEL(label_countdown
),
287 "<span font='300' color='red'>1</span>");
288 return G_SOURCE_CONTINUE
;
291 gtk_label_set_markup(GTK_LABEL(label_countdown
),
292 "<span font='300' color='red'>0</span>");
294 // 0 zeigen bevor der anfängt zu rechnen
295 while (gtk_events_pending()) {
296 gtk_main_iteration();
302 return G_SOURCE_REMOVE
;
304 // wenn das passiert ist was schief gelaufen
305 printf("etwas ist sehr schief gelaufen\n");
306 return G_SOURCE_REMOVE
;
309 void pb_takepic(void)
311 char *fn
= "tmp.jpg";
312 if (pb_ph_capture_file(fn
) != 0) {
313 fprintf(stderr
, "ERROR: pb_ph_capture_file\n");
318 GdkPixbuf
*pb
= gdk_pixbuf_new_from_file(fn
, NULL
);
319 pb
= gdk_pixbuf_scale_simple(pb
, IMG_WIDTH
, IMG_HEIGHT
, GDK_INTERP_BILINEAR
);
320 gtk_image_set_from_pixbuf(GTK_IMAGE(img
), pb
);
324 int pb_cp_dp(char *id
)
330 char src
[] = "tmp.jpg";
331 char dest
[] = "bilder/xxxxxx.jpg";
332 char dropbox_arg
[] = "Dropbox-API-Arg: {\"path\": \"/bilder/xxxxxx.jpg\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}";
334 for (unsigned int i
= 0; i
< 6; ++i
) {
336 dropbox_arg
[i
+ 35] = id
[i
];
339 FILE *src_file
= fopen(src
, "rb");
340 if (src_file
== NULL
) {
341 perror("Error opening \"tmp.jpg\"");
344 FILE *dest_file
= fopen(dest
, "wb+");
345 if (dest_file
== NULL
) {
347 perror("Error opening destination file");
352 num_read
= fread(buffer
, 1, 4096, src_file
);
353 dest_fsize
+= num_read
;
354 if (fwrite(buffer
, 1, num_read
, dest_file
) != num_read
&& ferror(dest_file
) != 0) {
355 fprintf(stderr
, "Error writing to destination file");
358 } while(num_read
== 4096);
359 if (ferror(src_file
) != 0) {
360 fprintf(stderr
, "Error reading from \"tmp.jpg\"");
365 rewind(dest_file
); // from beginning for upload
368 curl_global_init(CURL_GLOBAL_ALL
);
369 CURL
*curl
= curl_easy_init();
371 fprintf(stderr
, "ERROR: curl_easy_init\n");
372 curl_global_cleanup();
376 struct curl_slist
*header
= NULL
;
377 header
= curl_slist_append(header
, "Authorization: Bearer " APIKEY
);
378 header
= curl_slist_append(header
, dropbox_arg
);
379 header
= curl_slist_append(header
, "Content-Type: application/octet-stream");
380 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, header
);
382 curl_easy_setopt(curl
, CURLOPT_URL
, "https://content.dropboxapi.com/2/files/upload");
384 curl_easy_setopt(curl
, CURLOPT_POST
, 1L); // post request
385 curl_easy_setopt(curl
, CURLOPT_POSTFIELDSIZE
, dest_fsize
); // file size
386 curl_easy_setopt(curl
, CURLOPT_POSTFIELDS
, NULL
); // use read callback
387 curl_easy_setopt(curl
, CURLOPT_READDATA
, dest_file
); // file pointer
388 curl_easy_setopt(curl
, CURLOPT_READFUNCTION
, NULL
); // default callback
390 curl_easy_setopt(curl
, CURLOPT_WRITEDATA
, NULL
); // disable output
392 CURLcode ret
= curl_easy_perform(curl
);
393 if (ret
!= CURLE_OK
) {
394 fprintf(stderr
, "ERROR: curl_easy_perform: %s\n", curl_easy_strerror(ret
));
398 curl_slist_free_all(header
);
399 curl_easy_cleanup(curl
);
401 curl_global_cleanup();
408 curl_slist_free_all(header
);
409 curl_easy_cleanup(curl
);
411 curl_global_cleanup();