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