Welcome Ethumb, it's ready to get out of PROTO.
[framework/uifw/ethumb.git] / src / bin / ethumbd_child.c
1 /**
2  * @file
3  *
4  * Copyright (C) 2009 by ProFUSION embedded systems
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,  but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  *
21  * @author Rafael Antognolli <antognolli@profusion.mobi>
22  */
23
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <limits.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include <Ecore.h>
31 #include <Ethumb.h>
32 #include <Eina.h>
33
34 #include "ethumbd_private.h"
35
36 #define DBG(...) EINA_LOG_DBG(__VA_ARGS__)
37 #define INF(...) EINA_LOG_INFO(__VA_ARGS__)
38 #define WRN(...) EINA_LOG_WARN(__VA_ARGS__)
39 #define ERR(...) EINA_LOG_ERR(__VA_ARGS__)
40
41 #define NETHUMBS 100
42
43 struct _Ethumbd_Child
44 {
45    Ecore_Fd_Handler *fd_handler;
46    Ethumb *ethumbt[NETHUMBS];
47    int pipein, pipeout;
48 };
49
50
51 int
52 _ec_read_safe(int fd, void *buf, ssize_t size)
53 {
54    ssize_t todo;
55    char *p;
56
57    todo = size;
58    p = buf;
59
60    while (todo > 0)
61      {
62         ssize_t r;
63
64         r = read(fd, p, todo);
65         if (r > 0)
66           {
67              todo -= r;
68              p += r;
69           }
70         else if (r == 0)
71           return 0;
72         else
73           {
74              if (errno == EINTR || errno == EAGAIN)
75                continue;
76              else
77                {
78                   ERR("could not read from fd %d: %s",
79                       fd, strerror(errno));
80                   return 0;
81                }
82           }
83      }
84
85    return 1;
86 }
87
88 int
89 _ec_write_safe(int fd, const void *buf, ssize_t size)
90 {
91    ssize_t todo;
92    const char *p;
93
94    todo = size;
95    p = buf;
96
97    while (todo > 0)
98      {
99         ssize_t r;
100
101         r = write(fd, p, todo);
102         if (r > 0)
103           {
104              todo -= r;
105              p += r;
106           }
107         else if (r == 0)
108           return 0;
109         else
110           {
111              if (errno == EINTR || errno == EAGAIN)
112                continue;
113              else
114                {
115                   ERR("could not write to fd %d: %s", fd, strerror(errno));
116                   return 0;
117                }
118           }
119      }
120
121    return 1;
122 }
123
124 static int
125 _ec_pipe_str_read(struct _Ethumbd_Child *ec, char **str)
126 {
127    int size;
128    int r;
129    char buf[PATH_MAX];
130
131    r = _ec_read_safe(ec->pipein, &size, sizeof(size));
132    if (!r)
133      {
134         *str = NULL;
135         return 0;
136      }
137
138    if (!size)
139      {
140         *str = NULL;
141         return 1;
142      }
143
144    r = _ec_read_safe(ec->pipein, buf, size);
145    if (!r)
146      {
147         *str = NULL;
148         return 0;
149      }
150
151    *str = strdup(buf);
152    return 1;
153 }
154
155 static void
156 _ec_pipe_str_write(struct _Ethumbd_Child *ec, const char *str)
157 {
158    int size;
159
160    if (!str)
161      size = 0;
162    else
163      size = strlen(str) + 1;
164
165    _ec_write_safe(ec->pipeout, &size, sizeof(size));
166    _ec_write_safe(ec->pipeout, str, size);
167 }
168
169 static struct _Ethumbd_Child *
170 _ec_new(int pipein, int pipeout)
171 {
172    struct _Ethumbd_Child *ec = calloc(1, sizeof(*ec));
173
174    ec->pipein = pipein;
175    ec->pipeout = pipeout;
176
177    return ec;
178 }
179
180 static void
181 _ec_free(struct _Ethumbd_Child *ec)
182 {
183    int i;
184
185    if (ec->fd_handler)
186      ecore_main_fd_handler_del(ec->fd_handler);
187
188    for (i = 0; i < NETHUMBS; i++)
189      {
190         if (ec->ethumbt[i])
191           ethumb_free(ec->ethumbt[i]);
192      }
193
194    free(ec);
195 }
196
197 static int
198 _ec_op_new(struct _Ethumbd_Child *ec)
199 {
200    int r;
201    int index;
202
203    r = _ec_read_safe(ec->pipein, &index, sizeof(index));
204    if (!r)
205      return 0;
206
207    DBG("ethumbd new(). index = %d\n", index);
208
209    ec->ethumbt[index] = ethumb_new();
210    return 1;
211 }
212
213 static int
214 _ec_op_del(struct _Ethumbd_Child *ec)
215 {
216    int r;
217    int index;
218
219    r = _ec_read_safe(ec->pipein, &index, sizeof(index));
220    if (!r)
221      return 0;
222
223    DBG("ethumbd del(). index = %d\n", index);
224
225    ethumb_free(ec->ethumbt[index]);
226    ec->ethumbt[index] = NULL;
227    return 1;
228 }
229
230 static void
231 _ec_op_generated_cb(void *data, Ethumb *e, Eina_Bool success)
232 {
233    struct _Ethumbd_Child *ec = data;
234    const char *thumb_path, *thumb_key;
235
236    DBG("thumb generated!\n");
237    ethumb_thumb_path_get(e, &thumb_path, &thumb_key);
238    _ec_write_safe(ec->pipeout, &success, sizeof(success));
239
240    _ec_pipe_str_write(ec, thumb_path);
241    _ec_pipe_str_write(ec, thumb_key);
242 }
243
244 static int
245 _ec_op_generate(struct _Ethumbd_Child *ec)
246 {
247    int index;
248    char *path, *key, *thumb_path, *thumb_key;
249    int r;
250
251    r = _ec_read_safe(ec->pipein, &index, sizeof(index));
252    if (!r)
253      return 0;
254
255    r = _ec_pipe_str_read(ec, &path);
256    if (!r)
257      return 0;
258    r = _ec_pipe_str_read(ec, &key);
259    if (!r)
260      return 0;
261    r = _ec_pipe_str_read(ec, &thumb_path);
262    if (!r)
263      return 0;
264    r = _ec_pipe_str_read(ec, &thumb_key);
265    if (!r)
266      return 0;
267
268    ethumb_file_set(ec->ethumbt[index], path, key);
269    ethumb_thumb_path_set(ec->ethumbt[index], thumb_path, thumb_key);
270    ethumb_generate(ec->ethumbt[index], _ec_op_generated_cb, ec, NULL);
271
272    free(path);
273    free(key);
274    free(thumb_path);
275    free(thumb_key);
276
277    return 1;
278 }
279
280 static int
281 _ec_fdo_set(struct _Ethumbd_Child *ec, Ethumb *e)
282 {
283    int r;
284    int value;
285
286    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
287    if (!r)
288      return 0;
289    ethumb_thumb_fdo_set(e, value);
290    DBG("fdo = %d\n", value);
291
292    return 1;
293 }
294
295 static int
296 _ec_size_set(struct _Ethumbd_Child *ec, Ethumb *e)
297 {
298    int r;
299    int w, h;
300    int type;
301
302    r = _ec_read_safe(ec->pipein, &w, sizeof(w));
303    if (!r)
304      return 0;
305    r = _ec_read_safe(ec->pipein, &type, sizeof(type));
306    if (!r)
307      return 0;
308    r = _ec_read_safe(ec->pipein, &h, sizeof(h));
309    if (!r)
310      return 0;
311    ethumb_thumb_size_set(e, w, h);
312    DBG("size = %dx%d\n", w, h);
313
314    return 1;
315 }
316
317 static int
318 _ec_format_set(struct _Ethumbd_Child *ec, Ethumb *e)
319 {
320    int r;
321    int value;
322
323    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
324    if (!r)
325      return 0;
326    ethumb_thumb_format_set(e, value);
327    DBG("format = %d\n", value);
328
329    return 1;
330 }
331
332 static int
333 _ec_aspect_set(struct _Ethumbd_Child *ec, Ethumb *e)
334 {
335    int r;
336    int value;
337
338    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
339    if (!r)
340      return 0;
341    ethumb_thumb_aspect_set(e, value);
342    DBG("aspect = %d\n", value);
343
344    return 1;
345 }
346
347 static int
348 _ec_crop_set(struct _Ethumbd_Child *ec, Ethumb *e)
349 {
350    int r;
351    float x, y;
352    int type;
353
354    r = _ec_read_safe(ec->pipein, &x, sizeof(x));
355    if (!r)
356      return 0;
357    r = _ec_read_safe(ec->pipein, &type, sizeof(type));
358    if (!r)
359      return 0;
360    r = _ec_read_safe(ec->pipein, &y, sizeof(y));
361    if (!r)
362      return 0;
363    ethumb_thumb_crop_align_set(e, x, y);
364    DBG("crop = %fx%f\n", x, y);
365
366    return 1;
367 }
368
369 static int
370 _ec_quality_set(struct _Ethumbd_Child *ec, Ethumb *e)
371 {
372    int r;
373    int value;
374
375    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
376    if (!r)
377      return 0;
378    ethumb_thumb_quality_set(e, value);
379    DBG("quality = %d\n", value);
380
381    return 1;
382 }
383
384 static int
385 _ec_compress_set(struct _Ethumbd_Child *ec, Ethumb *e)
386 {
387    int r;
388    int value;
389
390    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
391    if (!r)
392      return 0;
393    ethumb_thumb_compress_set(e, value);
394    DBG("compress = %d\n", value);
395
396    return 1;
397 }
398
399 static int
400 _ec_frame_set(struct _Ethumbd_Child *ec, Ethumb *e)
401 {
402    int r;
403    int type;
404    char *theme_file, *group, *swallow;
405
406    r = _ec_pipe_str_read(ec, &theme_file);
407    if (!r)
408      return 0;
409    r = _ec_read_safe(ec->pipein, &type, sizeof(type));
410    if (!r)
411      return 0;
412    r = _ec_pipe_str_read(ec, &group);
413    if (!r)
414      return 0;
415    r = _ec_read_safe(ec->pipein, &type, sizeof(type));
416    if (!r)
417      return 0;
418    r = _ec_pipe_str_read(ec, &swallow);
419    if (!r)
420      return 0;
421    DBG("frame = %s:%s:%s\n", theme_file, group, swallow);
422    ethumb_frame_set(e, theme_file, group, swallow);
423    free(theme_file);
424    free(group);
425    free(swallow);
426
427    return 1;
428 }
429
430 static int
431 _ec_directory_set(struct _Ethumbd_Child *ec, Ethumb *e)
432 {
433    int r;
434    char *directory;
435
436    r = _ec_pipe_str_read(ec, &directory);
437    if (!r)
438      return 0;
439    ethumb_thumb_dir_path_set(e, directory);
440    DBG("directory = %s\n", directory);
441    free(directory);
442
443    return 1;
444 }
445
446 static int
447 _ec_category_set(struct _Ethumbd_Child *ec, Ethumb *e)
448 {
449    int r;
450    char *category;
451
452    r = _ec_pipe_str_read(ec, &category);
453    if (!r)
454      return 0;
455    ethumb_thumb_category_set(e, category);
456    DBG("category = %s\n", category);
457    free(category);
458
459    return 1;
460 }
461
462 static int
463 _ec_video_time_set(struct _Ethumbd_Child *ec, Ethumb *e)
464 {
465    int r;
466    float value;
467
468    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
469    if (!r)
470      return 0;
471    ethumb_video_time_set(e, value);
472    DBG("video_time = %f\n", value);
473
474    return 1;
475 }
476
477 static int
478 _ec_video_start_set(struct _Ethumbd_Child *ec, Ethumb *e)
479 {
480    int r;
481    float value;
482
483    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
484    if (!r)
485      return 0;
486    ethumb_video_start_set(e, value);
487    DBG("video_start = %f\n", value);
488
489    return 1;
490 }
491
492 static int
493 _ec_video_interval_set(struct _Ethumbd_Child *ec, Ethumb *e)
494 {
495    int r;
496    float value;
497
498    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
499    if (!r)
500      return 0;
501    ethumb_video_interval_set(e, value);
502    DBG("video_interval = %f\n", value);
503
504    return 1;
505 }
506
507 static int
508 _ec_video_ntimes_set(struct _Ethumbd_Child *ec, Ethumb *e)
509 {
510    int r;
511    int value;
512
513    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
514    if (!r)
515      return 0;
516    ethumb_video_ntimes_set(e, value);
517    DBG("video_ntimes = %d\n", value);
518
519    return 1;
520 }
521
522 static int
523 _ec_video_fps_set(struct _Ethumbd_Child *ec, Ethumb *e)
524 {
525    int r;
526    int value;
527
528    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
529    if (!r)
530      return 0;
531    ethumb_video_fps_set(e, value);
532    DBG("video_fps = %d\n", value);
533
534    return 1;
535 }
536
537 static int
538 _ec_document_page_set(struct _Ethumbd_Child *ec, Ethumb *e)
539 {
540    int r;
541    int value;
542
543    r = _ec_read_safe(ec->pipein, &value, sizeof(value));
544    if (!r)
545      return 0;
546    ethumb_document_page_set(e, value);
547    DBG("document_page = %d\n", value);
548
549    return 1;
550 }
551
552 static void
553 _ec_setup_process(struct _Ethumbd_Child *ec, int index, int type)
554 {
555    Ethumb *e;
556
557    e = ec->ethumbt[index];
558
559    switch (type)
560      {
561       case ETHUMBD_FDO:
562          _ec_fdo_set(ec, e);
563          break;
564       case ETHUMBD_SIZE_W:
565          _ec_size_set(ec, e);
566          break;
567       case ETHUMBD_FORMAT:
568          _ec_format_set(ec, e);
569          break;
570       case ETHUMBD_ASPECT:
571          _ec_aspect_set(ec, e);
572          break;
573       case ETHUMBD_CROP_X:
574          _ec_crop_set(ec, e);
575          break;
576       case ETHUMBD_QUALITY:
577          _ec_quality_set(ec, e);
578          break;
579       case ETHUMBD_COMPRESS:
580          _ec_compress_set(ec, e);
581          break;
582       case ETHUMBD_FRAME_FILE:
583          _ec_frame_set(ec, e);
584          break;
585       case ETHUMBD_DIRECTORY:
586          _ec_directory_set(ec, e);
587          break;
588       case ETHUMBD_CATEGORY:
589          _ec_category_set(ec, e);
590          break;
591       case ETHUMBD_VIDEO_TIME:
592          _ec_video_time_set(ec, e);
593          break;
594       case ETHUMBD_VIDEO_START:
595          _ec_video_start_set(ec, e);
596          break;
597       case ETHUMBD_VIDEO_INTERVAL:
598          _ec_video_interval_set(ec, e);
599          break;
600       case ETHUMBD_VIDEO_NTIMES:
601          _ec_video_ntimes_set(ec, e);
602          break;
603       case ETHUMBD_VIDEO_FPS:
604          _ec_video_fps_set(ec, e);
605          break;
606       case ETHUMBD_DOCUMENT_PAGE:
607          _ec_document_page_set(ec, e);
608          break;
609       default:
610          ERR("wrong type!\n");
611      }
612 }
613
614 static int
615 _ec_op_setup(struct _Ethumbd_Child *ec)
616 {
617    int r;
618    int index;
619    int type;
620
621    r = _ec_read_safe(ec->pipein, &index, sizeof(index));
622    if (!r)
623      return 0;
624
625    r = _ec_read_safe(ec->pipein, &type, sizeof(type));
626    if (!r)
627      return 0;
628    while (type != ETHUMBD_SETUP_FINISHED)
629      {
630         _ec_setup_process(ec, index, type);
631         r = _ec_read_safe(ec->pipein, &type, sizeof(type));
632         if (!r)
633           return 0;
634      }
635
636    return 1;
637 }
638
639 static int
640 _ec_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
641 {
642    struct _Ethumbd_Child *ec = data;
643    int op_id;
644    int r;
645
646    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
647      {
648         ERR("error on pipein! child exiting...\n");
649         ec->fd_handler = NULL;
650         ecore_main_loop_quit();
651         return 0;
652      }
653
654    r = _ec_read_safe(ec->pipein, &op_id, sizeof(op_id));
655    if (!r)
656      {
657         DBG("ethumbd exited! child exiting...\n");
658         ec->fd_handler = NULL;
659         ecore_main_loop_quit();
660         return 0;
661      }
662
663    DBG("received op: %d\n", op_id);
664
665    r = 1;
666    switch (op_id)
667      {
668       case ETHUMBD_OP_NEW:
669          r = _ec_op_new(ec);
670          break;
671       case ETHUMBD_OP_GENERATE:
672          r = _ec_op_generate(ec);
673          break;
674       case ETHUMBD_OP_SETUP:
675          r = _ec_op_setup(ec);
676          break;
677       case ETHUMBD_OP_DEL:
678          r = _ec_op_del(ec);
679          break;
680       default:
681          ERR("invalid operation: %d\n", op_id);
682          r = 0;
683      }
684
685    if (!r)
686      {
687         ERR("ethumbd exited! child exiting...\n");
688         ec->fd_handler = NULL;
689         ecore_main_loop_quit();
690      }
691
692    return r;
693 }
694
695 static void
696 _ec_setup(struct _Ethumbd_Child *ec)
697 {
698    ec->fd_handler = ecore_main_fd_handler_add(
699       ec->pipein, ECORE_FD_READ | ECORE_FD_ERROR,
700       _ec_fd_handler, ec, NULL, NULL);
701 }
702
703 void
704 ethumbd_child_start(int pipein, int pipeout)
705 {
706    struct _Ethumbd_Child *ec;
707
708    ethumb_init();
709
710    ec = _ec_new(pipein, pipeout);
711
712    _ec_setup(ec);
713
714    DBG("child started!\n");
715    ecore_main_loop_begin();
716    DBG("child finishing.\n");
717
718    _ec_free(ec);
719
720    ethumb_shutdown();
721 }