summaryrefslogtreecommitdiff
path: root/src/bin/ethumb
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-15 18:10:58 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-15 18:10:58 +0000
commitd97c63e4c69d0a8c3cb29b22927b5b53c7bf46c4 (patch)
tree4309480b1cb48058bdac139f6eb14cbeaf515fd6 /src/bin/ethumb
parent028e7e9ed2ca4aad0dd04493019d495f68fa6a31 (diff)
fix directory structure: move ethumd_client out of ethumb.
it's another library, do not mix stuff as it used to be. SVN revision: 82835
Diffstat (limited to 'src/bin/ethumb')
-rw-r--r--src/bin/ethumb/ethumbd.c1803
-rw-r--r--src/bin/ethumb/ethumbd_client.c330
-rw-r--r--src/bin/ethumb/ethumbd_private.h41
-rw-r--r--src/bin/ethumb/ethumbd_slave.c770
4 files changed, 0 insertions, 2944 deletions
diff --git a/src/bin/ethumb/ethumbd.c b/src/bin/ethumb/ethumbd.c
deleted file mode 100644
index f0f0d9b44a..0000000000
--- a/src/bin/ethumb/ethumbd.c
+++ /dev/null
@@ -1,1803 +0,0 @@
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#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <limits.h>
30#include <unistd.h>
31#include <errno.h>
32
33#include <Eina.h>
34#include <Ecore_Getopt.h>
35#include <Ecore.h>
36#include <EDBus.h>
37#include <Ethumb.h>
38
39#include "ethumbd_private.h"
40
41#ifndef PATH_MAX
42#define PATH_MAX 4096
43#endif
44
45#define MAX_ID 2000000
46#define DAEMON "daemon"
47#define ODATA "odata"
48
49#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
50#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
51#define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__)
52#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
53#define CRIT(...) EINA_LOG_DOM_CRIT(_log_domain, __VA_ARGS__)
54
55static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
56static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
57static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
58static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
59
60static Eina_Prefix *_pfx = NULL;
61static int _log_domain = -1;
62
63typedef struct _Ethumbd_Setup Ethumbd_Setup;
64typedef struct _Ethumbd_Slave Ethumbd_Slave;
65typedef struct _Ethumbd_Request Ethumbd_Request;
66typedef struct _Ethumbd_Queue Ethumbd_Queue;
67typedef struct _Ethumbd_Object Ethumbd_Object;
68typedef struct _Ethumbd_Object_Data Ethumbd_Object_Data;
69typedef struct _Ethumbd Ethumbd;
70
71struct _Ethumbd_Setup
72{
73 struct
74 {
75 Eina_Bool fdo : 1;
76 Eina_Bool size : 1;
77 Eina_Bool format : 1;
78 Eina_Bool aspect : 1;
79 Eina_Bool orientation: 1;
80 Eina_Bool crop : 1;
81 Eina_Bool quality : 1;
82 Eina_Bool compress : 1;
83 Eina_Bool directory : 1;
84 Eina_Bool category : 1;
85 Eina_Bool frame : 1;
86 Eina_Bool video_time : 1;
87 Eina_Bool video_start : 1;
88 Eina_Bool video_interval : 1;
89 Eina_Bool video_ntimes : 1;
90 Eina_Bool video_fps : 1;
91 Eina_Bool document_page : 1;
92 } flags;
93 int fdo;
94 int tw, th;
95 int format;
96 int aspect;
97 int orientation;
98 float cx, cy;
99 int quality;
100 int compress;
101 const char *directory;
102 const char *category;
103 const char *theme_file;
104 const char *group;
105 const char *swallow;
106 float video_time;
107 float video_start;
108 float video_interval;
109 unsigned int video_ntimes;
110 unsigned int video_fps;
111 unsigned int document_page;
112};
113
114struct _Ethumbd_Request
115{
116 int id;
117 const char *file, *key;
118 const char *thumb, *thumb_key;
119 Ethumbd_Setup setup;
120};
121
122struct _Ethumbd_Object
123{
124 int used;
125 const char *path;
126 const char *client;
127 Eina_List *queue;
128 int nqueue;
129 int id_count;
130 int max_id;
131 int min_id;
132 EDBus_Service_Interface *iface;
133};
134
135struct _Ethumbd_Queue
136{
137 int count;
138 int max_count;
139 int nqueue;
140 int last;
141 int current;
142 Ethumbd_Object *table;
143 int *list;
144};
145
146struct _Ethumbd_Slave
147{
148 Ecore_Exe *exe;
149 char *bufcmd; // buffer to read commands from slave
150 int scmd; // size of command to read
151 int pcmd; // position in the command buffer
152};
153
154struct _Ethumbd
155{
156 EDBus_Connection *conn;
157 Ecore_Idler *idler;
158 Ethumbd_Request *processing;
159 Ethumbd_Queue queue;
160 double timeout;
161 Ecore_Timer *timeout_timer;
162 Ethumbd_Slave slave;
163
164 Ecore_Event_Handler *data_cb;
165 Ecore_Event_Handler *del_cb;
166};
167
168struct _Ethumbd_Object_Data
169{
170 int idx;
171 Ethumbd *ed;
172};
173
174const Ecore_Getopt optdesc = {
175 "ethumbd",
176 NULL,
177 PACKAGE_VERSION,
178 "(C) 2009 - ProFUSION embedded systems",
179 "LGPL v2.1 - GNU Lesser General Public License",
180 "Ethumb daemon.\n"
181 "\n"
182 "ethumbd uses the Ethumb library to create thumbnails for any "
183 "program that requests it (now just by dbus).\n",
184 0,
185 {
186 ECORE_GETOPT_STORE_DOUBLE
187 ('t', "timeout", "finish ethumbd after <timeout> seconds of no activity."),
188 ECORE_GETOPT_LICENSE('L', "license"),
189 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
190 ECORE_GETOPT_VERSION('V', "version"),
191 ECORE_GETOPT_HELP('h', "help"),
192 ECORE_GETOPT_SENTINEL
193 }
194};
195
196static EDBus_Message *_ethumb_dbus_queue_add_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
197static EDBus_Message *_ethumb_dbus_queue_remove_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
198static EDBus_Message *_ethumb_dbus_queue_clear_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
199static EDBus_Message *_ethumb_dbus_ethumb_setup_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
200static EDBus_Message *_ethumb_dbus_delete_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg);
201
202static const EDBus_Method _ethumb_dbus_objects_methods[] = {
203 {
204 "queue_add",
205 EDBUS_ARGS({"i", "id"}, {"ay", "file"}, {"ay", "key"}, {"ay", "thumb"}, {"ay", "thumb_key"}),
206 EDBUS_ARGS({"i", "queue_id"}), _ethumb_dbus_queue_add_cb, 0
207 },
208 {
209 "queue_remove", EDBUS_ARGS({"i", "queue_id"}), EDBUS_ARGS({"b", "result"}),
210 _ethumb_dbus_queue_remove_cb, 0
211 },
212 {
213 "clear_queue", NULL, NULL, _ethumb_dbus_queue_clear_cb, 0
214 },
215 {
216 "ethumb_setup", EDBUS_ARGS({"a{sv}", "array"}), EDBUS_ARGS({"b", "result"}),
217 _ethumb_dbus_ethumb_setup_cb, 0
218 },
219 {
220 "delete", NULL, NULL, _ethumb_dbus_delete_cb, 0
221 },
222 { }
223};
224
225enum
226{
227 ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED = 0,
228};
229
230static const EDBus_Signal _ethumb_dbus_objects_signals[] = {
231 [ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED] = { "generated",
232 EDBUS_ARGS({ "i", "id" }, { "ay", "paths" }, { "ay", "keys" },
233 { "b", "success" }) },
234 { }
235};
236
237static void _ethumb_dbus_generated_signal(Ethumbd *ed, int *id, const char *thumb_path, const char *thumb_key, Eina_Bool success);
238static Eina_Bool _ethumbd_slave_spawn(Ethumbd_Slave *slave, Ethumbd *ed);
239
240static Eina_Bool
241_ethumbd_timeout_cb(void *data)
242{
243 Ethumbd *ed = data;
244
245 ecore_main_loop_quit();
246 ed->timeout_timer = NULL;
247
248 return 0;
249}
250
251static void
252_ethumbd_timeout_start(Ethumbd *ed)
253{
254 if (ed->timeout < 0)
255 return;
256
257 if (!ed->timeout_timer)
258 ed->timeout_timer = ecore_timer_add(ed->timeout, _ethumbd_timeout_cb, ed);
259}
260
261static void
262_ethumbd_timeout_stop(Ethumbd *ed)
263{
264 if (!ed->timeout_timer)
265 return;
266
267 ecore_timer_del(ed->timeout_timer);
268 ed->timeout_timer = NULL;
269}
270
271static int
272_ethumb_dbus_check_id(Ethumbd_Object *eobject, int id)
273{
274 if (id < 0 || id > MAX_ID)
275 return 0;
276
277 if (eobject->min_id < eobject->max_id)
278 return id < eobject->min_id || id > eobject->max_id;
279 else if (eobject->min_id > eobject->max_id)
280 return id < eobject->min_id && id > eobject->max_id;
281 else
282 return id != eobject->max_id;
283}
284
285static void
286_ethumb_dbus_inc_max_id(Ethumbd_Object *eobject, int id)
287{
288 if (eobject->min_id < 0 && eobject->max_id < 0)
289 eobject->min_id = id;
290
291 eobject->max_id = id;
292}
293
294static void
295_ethumb_dbus_inc_min_id(Ethumbd_Object *eobject)
296{
297 Eina_List *l;
298
299 l = eobject->queue;
300 while (l)
301 {
302 Ethumbd_Request *request = l->data;
303 if (request->id >= 0)
304 {
305 eobject->min_id = request->id;
306 break;
307 }
308
309 l = l->next;
310 }
311
312 if (!l)
313 {
314 eobject->min_id = -1;
315 eobject->max_id = -1;
316 }
317}
318
319int
320_ethumbd_write_safe(Ethumbd_Slave *slave, const void *buf, ssize_t size)
321{
322
323 if (!slave->exe)
324 {
325 ERR("slave process isn't running.");
326 return 0;
327 }
328
329 ecore_exe_send(slave->exe, buf, size);
330 return 1;
331}
332
333static void
334_ethumbd_child_write_op_new(Ethumbd_Slave *slave, int idx)
335{
336 int id = ETHUMBD_OP_NEW;
337 _ethumbd_write_safe(slave, &id, sizeof(id));
338 _ethumbd_write_safe(slave, &idx, sizeof(idx));
339}
340
341static void
342_ethumbd_child_write_op_del(Ethumbd_Slave *slave, int idx)
343{
344 int id = ETHUMBD_OP_DEL;
345 _ethumbd_write_safe(slave, &id, sizeof(id));
346 _ethumbd_write_safe(slave, &idx, sizeof(idx));
347}
348
349static void
350_ethumbd_pipe_str_write(Ethumbd_Slave *slave, const char *str)
351{
352 int len;
353
354 if (str)
355 len = strlen(str) + 1;
356 else
357 len = 0;
358
359 _ethumbd_write_safe(slave, &len, sizeof(len));
360 _ethumbd_write_safe(slave, str, len);
361}
362
363static void
364_ethumbd_child_write_op_generate(Ethumbd_Slave *slave,
365 int idx, const char *path, const char *key,
366 const char *thumb_path, const char *thumb_key)
367{
368 int id = ETHUMBD_OP_GENERATE;
369
370 _ethumbd_write_safe(slave, &id, sizeof(id));
371 _ethumbd_write_safe(slave, &idx, sizeof(idx));
372
373 _ethumbd_pipe_str_write(slave, path);
374 _ethumbd_pipe_str_write(slave, key);
375 _ethumbd_pipe_str_write(slave, thumb_path);
376 _ethumbd_pipe_str_write(slave, thumb_key);
377}
378
379static void
380_generated_cb(Ethumbd *ed, Eina_Bool success, const char *thumb_path, const char *thumb_key)
381{
382 int i = ed->queue.current;
383
384 DBG("thumbnail ready at: \"%s:%s\"", thumb_path, thumb_key);
385
386 if (ed->queue.table[i].used)
387 _ethumb_dbus_generated_signal
388 (ed, &ed->processing->id, thumb_path, thumb_key, success);
389 eina_stringshare_del(ed->processing->file);
390 eina_stringshare_del(ed->processing->key);
391 eina_stringshare_del(ed->processing->thumb);
392 eina_stringshare_del(ed->processing->thumb_key);
393 free(ed->processing);
394 ed->processing = NULL;
395}
396
397static void
398_ethumbd_slave_cmd_ready(Ethumbd *ed)
399{
400 const char *bufcmd = ed->slave.bufcmd;
401 Eina_Bool success;
402 const char *thumb_path = NULL;
403 const char *thumb_key = NULL;
404 int size_path, size_key;
405
406 /* NOTE: accessing values directly on bufcmd breaks alignment
407 * as the first item is an Eina_Bool (size 1) and second is
408 * an integer (size 4, alignment 4).
409 * Thus copy to stack values before using them, to have proper alignment.
410 */
411#define READVAL(dst) \
412 memcpy(&dst, bufcmd, sizeof(dst)); \
413 bufcmd += sizeof(dst);
414
415 READVAL(success);
416
417 READVAL(size_path);
418 if (size_path)
419 {
420 thumb_path = bufcmd;
421 bufcmd += size_path;
422 }
423
424 READVAL(size_key);
425 if (size_key) thumb_key = bufcmd;
426
427#undef READVAL
428
429 _generated_cb(ed, success, thumb_path, thumb_key);
430
431 free(ed->slave.bufcmd);
432 ed->slave.bufcmd = NULL;
433 ed->slave.scmd = 0;
434}
435
436static int
437_ethumbd_slave_alloc_cmd(Ethumbd *ed, int ssize, char *sdata)
438{
439 int *scmd;
440
441 if (ed->slave.bufcmd)
442 return 0;
443
444 scmd = (int *)sdata;
445 if (ssize < (int)sizeof(*scmd)) {
446 ERR("could not read size of command.");
447 return 0;
448 }
449 ed->slave.bufcmd = malloc(*scmd);
450 ed->slave.scmd = *scmd;
451 ed->slave.pcmd = 0;
452
453 return sizeof(*scmd);
454}
455
456static Eina_Bool
457_ethumbd_slave_data_read_cb(void *data, int type EINA_UNUSED, void *event)
458{
459 Ethumbd *ed = data;
460 Ecore_Exe_Event_Data *ev = event;
461 int ssize;
462 char *sdata;
463
464 if (ev->exe != ed->slave.exe)
465 {
466 ERR("PARENT ERROR: slave != ev->exe");
467 return 0;
468 }
469
470 ssize = ev->size;
471 sdata = ev->data;
472
473 while (ssize > 0)
474 {
475 if (!ed->slave.bufcmd)
476 {
477 int n;
478 n = _ethumbd_slave_alloc_cmd(ed, ssize, sdata);
479 ssize -= n;
480 sdata += n;
481 }
482 else
483 {
484 char *bdata;
485 int nbytes;
486 bdata = ed->slave.bufcmd + ed->slave.pcmd;
487 nbytes = ed->slave.scmd - ed->slave.pcmd;
488 nbytes = ssize < nbytes ? ssize : nbytes;
489 memcpy(bdata, sdata, nbytes);
490 sdata += nbytes;
491 ssize -= nbytes;
492 ed->slave.pcmd += nbytes;
493
494 if (ed->slave.pcmd == ed->slave.scmd)
495 _ethumbd_slave_cmd_ready(ed);
496 }
497 }
498
499 return 1;
500}
501
502static Eina_Bool
503_ethumbd_slave_del_cb(void *data, int type EINA_UNUSED, void *event)
504{
505 Ethumbd *ed = data;
506 Ecore_Exe_Event_Del *ev = event;
507 int i;
508
509 if (ev->exe != ed->slave.exe)
510 return 1;
511
512 if (ev->exited)
513 ERR("slave exited with code: %d", ev->exit_code);
514 else if (ev->signalled)
515 ERR("slave exited by signal: %d", ev->exit_signal);
516
517 if (!ed->processing)
518 goto end;
519
520 i = ed->queue.current;
521 ERR("failed to generate thumbnail for: \"%s:%s\"",
522 ed->processing->file, ed->processing->key);
523
524 if (ed->queue.table[i].used)
525 _ethumb_dbus_generated_signal
526 (ed, &ed->processing->id, NULL, NULL, EINA_FALSE);
527 eina_stringshare_del(ed->processing->file);
528 eina_stringshare_del(ed->processing->key);
529 eina_stringshare_del(ed->processing->thumb);
530 eina_stringshare_del(ed->processing->thumb_key);
531 free(ed->processing);
532 ed->processing = NULL;
533
534end:
535 ed->slave.exe = NULL;
536 if (ed->slave.bufcmd)
537 free(ed->slave.bufcmd);
538
539 if (!_ethumbd_slave_spawn(&ed->slave, ed))
540 return EINA_FALSE;
541
542 /* restart all queue */
543 for (i = 0; i < ed->queue.count; ++i)
544 _ethumbd_child_write_op_new(&ed->slave, ed->queue.list[i]);
545
546 return EINA_TRUE;
547}
548
549static void
550_ethumbd_pipe_write_setup(Ethumbd_Slave *slave, int type, const void *data)
551{
552 const int *i_value;
553 const float *f_value;
554
555 _ethumbd_write_safe(slave, &type, sizeof(type));
556
557 switch (type)
558 {
559 case ETHUMBD_FDO:
560 case ETHUMBD_FORMAT:
561 case ETHUMBD_ASPECT:
562 case ETHUMBD_ORIENTATION:
563 case ETHUMBD_QUALITY:
564 case ETHUMBD_COMPRESS:
565 case ETHUMBD_SIZE_W:
566 case ETHUMBD_SIZE_H:
567 case ETHUMBD_DOCUMENT_PAGE:
568 case ETHUMBD_VIDEO_NTIMES:
569 case ETHUMBD_VIDEO_FPS:
570 i_value = data;
571 _ethumbd_write_safe(slave, i_value, sizeof(*i_value));
572 break;
573 case ETHUMBD_CROP_X:
574 case ETHUMBD_CROP_Y:
575 case ETHUMBD_VIDEO_TIME:
576 case ETHUMBD_VIDEO_START:
577 case ETHUMBD_VIDEO_INTERVAL:
578 f_value = data;
579 _ethumbd_write_safe(slave, f_value, sizeof(*f_value));
580 break;
581 case ETHUMBD_DIRECTORY:
582 case ETHUMBD_CATEGORY:
583 case ETHUMBD_FRAME_FILE:
584 case ETHUMBD_FRAME_GROUP:
585 case ETHUMBD_FRAME_SWALLOW:
586 _ethumbd_pipe_str_write(slave, data);
587 break;
588 case ETHUMBD_SETUP_FINISHED:
589 break;
590 default:
591 ERR("wrong ethumb setup parameter.");
592 }
593}
594
595static void
596_process_setup(Ethumbd *ed)
597{
598 int op_id = ETHUMBD_OP_SETUP;
599 int idx = ed->queue.current;
600
601 Ethumbd_Setup *setup = &ed->processing->setup;
602 Ethumbd_Slave *slave = &ed->slave;
603
604 _ethumbd_write_safe(slave, &op_id, sizeof(op_id));
605 _ethumbd_write_safe(slave, &idx, sizeof(idx));
606
607 if (setup->flags.fdo)
608 _ethumbd_pipe_write_setup(slave, ETHUMBD_FDO, &setup->fdo);
609 if (setup->flags.size)
610 {
611 _ethumbd_pipe_write_setup(slave, ETHUMBD_SIZE_W, &setup->tw);
612 _ethumbd_pipe_write_setup(slave, ETHUMBD_SIZE_H, &setup->th);
613 }
614 if (setup->flags.format)
615 _ethumbd_pipe_write_setup(slave, ETHUMBD_FORMAT, &setup->format);
616 if (setup->flags.aspect)
617 _ethumbd_pipe_write_setup(slave, ETHUMBD_ASPECT, &setup->aspect);
618 if (setup->flags.orientation)
619 _ethumbd_pipe_write_setup(slave, ETHUMBD_ORIENTATION, &setup->orientation);
620 if (setup->flags.crop)
621 {
622 _ethumbd_pipe_write_setup(slave, ETHUMBD_CROP_X, &setup->cx);
623 _ethumbd_pipe_write_setup(slave, ETHUMBD_CROP_Y, &setup->cy);
624 }
625 if (setup->flags.quality)
626 _ethumbd_pipe_write_setup(slave, ETHUMBD_QUALITY, &setup->quality);
627 if (setup->flags.compress)
628 _ethumbd_pipe_write_setup(slave, ETHUMBD_COMPRESS, &setup->compress);
629 if (setup->flags.directory)
630 _ethumbd_pipe_write_setup(slave, ETHUMBD_DIRECTORY, setup->directory);
631 if (setup->flags.category)
632 _ethumbd_pipe_write_setup(slave, ETHUMBD_CATEGORY, setup->category);
633 if (setup->flags.frame)
634 {
635 _ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_FILE, setup->theme_file);
636 _ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_GROUP, setup->group);
637 _ethumbd_pipe_write_setup(slave, ETHUMBD_FRAME_SWALLOW, setup->swallow);
638 }
639 if (setup->flags.video_time)
640 _ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_TIME, &setup->video_time);
641 if (setup->flags.video_start)
642 _ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_START, &setup->video_start);
643 if (setup->flags.video_interval)
644 _ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_INTERVAL,
645 &setup->video_interval);
646 if (setup->flags.video_ntimes)
647 _ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_NTIMES, &setup->video_ntimes);
648 if (setup->flags.video_fps)
649 _ethumbd_pipe_write_setup(slave, ETHUMBD_VIDEO_FPS, &setup->video_fps);
650 if (setup->flags.document_page)
651 _ethumbd_pipe_write_setup(slave, ETHUMBD_DOCUMENT_PAGE,
652 &setup->document_page);
653 _ethumbd_pipe_write_setup(slave, ETHUMBD_SETUP_FINISHED, NULL);
654
655
656 if (setup->directory) eina_stringshare_del(setup->directory);
657 if (setup->category) eina_stringshare_del(setup->category);
658 if (setup->theme_file) eina_stringshare_del(setup->theme_file);
659 if (setup->group) eina_stringshare_del(setup->group);
660 if (setup->swallow) eina_stringshare_del(setup->swallow);
661
662 free(ed->processing);
663 ed->processing = NULL;
664}
665
666static void
667_process_file(Ethumbd *ed)
668{
669 _ethumbd_child_write_op_generate
670 (&ed->slave, ed->queue.current, ed->processing->file,
671 ed->processing->key, ed->processing->thumb, ed->processing->thumb_key);
672}
673
674static int
675_get_next_on_queue(Ethumbd_Queue *queue)
676{
677 int i, idx;
678 Ethumbd_Object *eobject;
679
680 i = queue->last;
681 i++;
682 if (i >= queue->count)
683 i = 0;
684
685 idx = queue->list[i];
686 eobject = &(queue->table[idx]);
687 while (!eobject->nqueue)
688 {
689 i = (i + 1) % queue->count;
690
691 idx = queue->list[i];
692 eobject = &(queue->table[idx]);
693 }
694
695 return queue->list[i];
696}
697
698static Eina_Bool
699_process_queue_cb(void *data)
700{
701 Ethumbd_Object *eobject;
702 int i;
703 Ethumbd *ed = data;
704 Ethumbd_Queue *queue = &ed->queue;
705 Ethumbd_Request *request;
706
707 if (ed->processing)
708 return 1;
709
710 if (!queue->nqueue)
711 {
712 ed->idler = NULL;
713 if (!queue->count)
714 _ethumbd_timeout_start(ed);
715 ed->idler = NULL;
716 return 0;
717 }
718
719 i = _get_next_on_queue(queue);
720 eobject = &(queue->table[i]);
721
722 request = eina_list_data_get(eobject->queue);
723 eobject->queue = eina_list_remove_list(eobject->queue, eobject->queue);
724 ed->queue.current = i;
725 DBG("processing file: \"%s:%s\"...", request->file,
726 request->key);
727 ed->processing = request;
728
729 if (request->id < 0)
730 _process_setup(ed);
731 else
732 {
733 _process_file(ed);
734 _ethumb_dbus_inc_min_id(eobject);
735 }
736 eobject->nqueue--;
737 queue->nqueue--;
738
739 queue->last = i;
740
741 return 1;
742}
743
744static void
745_process_queue_start(Ethumbd *ed)
746{
747 if (!ed->idler)
748 ed->idler = ecore_idler_add(_process_queue_cb, ed);
749}
750
751static void
752_process_queue_stop(Ethumbd *ed)
753{
754 if (ed->idler)
755 {
756 ecore_idler_del(ed->idler);
757 ed->idler = NULL;
758 }
759}
760
761static int
762_ethumb_table_append(Ethumbd *ed)
763{
764 int i;
765 char buf[1024];
766 Ethumbd_Queue *q = &ed->queue;
767
768 if (q->count == q->max_count)
769 {
770 int new_max = q->max_count + 5;
771 int start, size;
772 void *tmp;
773
774 start = q->max_count;
775 size = new_max - q->max_count;
776
777 tmp = realloc(q->table, new_max * sizeof(Ethumbd_Object));
778 if (!tmp)
779 {
780 CRIT("could not realloc q->table to %zd bytes: %s",
781 new_max * sizeof(Ethumbd_Object), strerror(errno));
782 return -1;
783 }
784 q->table = tmp;
785 memset(&q->table[start], 0, size * sizeof(Ethumbd_Object));
786
787 tmp = realloc(q->list, new_max * sizeof(int));
788 if (!tmp)
789 {
790 CRIT("could not realloc q->list to %zd bytes: %s",
791 new_max * sizeof(int), strerror(errno));
792 return -1;
793 }
794 q->list = tmp;
795
796 q->max_count = new_max;
797 }
798
799 for (i = 0; i < q->max_count; i++)
800 {
801 if (!q->table[i].used)
802 break;
803 }
804
805 snprintf(buf, sizeof(buf), "%s/%d", _ethumb_dbus_path, i);
806 q->table[i].used = 1;
807 q->table[i].path = eina_stringshare_add(buf);
808 q->table[i].max_id = -1;
809 q->table[i].min_id = -1;
810 q->list[q->count] = i;
811 q->count++;
812 DBG("new object: %s, idx = %d, count = %d", buf, i, q->count);
813
814 return i;
815}
816
817static inline int
818_get_idx_for_path(const char *path)
819{
820 int i;
821 int n;
822 n = sscanf(path, "/org/enlightenment/Ethumb/%d", &i);
823 if (!n)
824 return -1;
825 return i;
826}
827
828static void _name_owner_changed_cb(void *context, const char *bus, const char *old_id, const char *new_id);
829
830static void
831_ethumb_table_del(Ethumbd *ed, int i)
832{
833 int j;
834 Eina_List *l;
835 Ethumbd_Queue *q = &ed->queue;
836 Ethumbd_Object_Data *odata;
837
838 eina_stringshare_del(q->table[i].path);
839
840 l = q->table[i].queue;
841 while (l)
842 {
843 Ethumbd_Request *request = l->data;
844 eina_stringshare_del(request->file);
845 eina_stringshare_del(request->key);
846 eina_stringshare_del(request->thumb);
847 eina_stringshare_del(request->thumb_key);
848 free(request);
849 l = eina_list_remove_list(l, l);
850 }
851 q->nqueue -= q->table[i].nqueue;
852
853 odata = edbus_service_object_data_del(q->table[i].iface, ODATA);
854 edbus_name_owner_changed_callback_del(ed->conn, ed->queue.table[i].client,
855 _name_owner_changed_cb, odata);
856 //this string was not been freed previously
857 eina_stringshare_del(ed->queue.table[i].client);
858 free(odata);
859 edbus_service_object_unregister(q->table[i].iface);
860
861 memset(&(q->table[i]), 0, sizeof(Ethumbd_Object));
862 for (j = 0; j < q->count; j++)
863 {
864 if (q->list[j] == i)
865 q->list[j] = q->list[q->count - 1];
866 }
867
868 q->count--;
869 _ethumbd_child_write_op_del(&ed->slave, i);
870 if (!q->count && !ed->processing)
871 _ethumbd_timeout_start(ed);
872}
873
874static void
875_ethumb_table_clear(Ethumbd *ed)
876{
877 int i;
878
879 for (i = 0; i < ed->queue.max_count; i++)
880 if (ed->queue.table[i].used)
881 _ethumb_table_del(ed, i);
882}
883
884static void
885_name_owner_changed_cb(void *context, const char *bus, const char *old_id, const char *new_id)
886{
887 Ethumbd_Object_Data *odata = context;
888 Ethumbd *ed = odata->ed;
889
890 DBG("NameOwnerChanged: name = %s, from = %s, to = %s", bus, old_id, new_id);
891 if (new_id[0])
892 return;
893 _ethumb_table_del(ed, odata->idx);
894}
895
896static const EDBus_Service_Interface_Desc client_desc = {
897 _ethumb_dbus_objects_interface, _ethumb_dbus_objects_methods,
898 _ethumb_dbus_objects_signals
899};
900
901static EDBus_Message *
902_ethumb_dbus_ethumb_new_cb(const EDBus_Service_Interface *interface, const EDBus_Message *msg)
903{
904 EDBus_Message *reply;
905 EDBus_Service_Interface *iface;
906 Ethumbd_Object_Data *odata;
907 int i;
908 const char *return_path = "";
909 const char *client;
910 Ethumbd *ed;
911
912 ed = edbus_service_object_data_get(interface, DAEMON);
913 client = edbus_message_sender_get(msg);
914 if (!client)
915 goto end_new;
916
917 i = _ethumb_table_append(ed);
918 if (i < 0)
919 goto end_new;
920
921 odata = calloc(1, sizeof(*odata));
922 odata->idx = i;
923 odata->ed = ed;
924
925 ed->queue.table[i].client = eina_stringshare_add(client);
926 return_path = ed->queue.table[i].path;
927
928 iface = edbus_service_interface_register(ed->conn, return_path, &client_desc);
929 if (!iface)
930 {
931 ERR("could not create dbus_object.");
932 free(odata);
933 return_path = "";
934 goto end_new;
935 }
936 edbus_service_object_data_set(iface, ODATA, odata);
937 ed->queue.table[i].iface = iface;
938 edbus_name_owner_changed_callback_add(ed->conn, client,
939 _name_owner_changed_cb, odata,
940 EINA_TRUE);
941 _ethumbd_child_write_op_new(&ed->slave, i);
942 _ethumbd_timeout_stop(ed);
943
944 end_new:
945 reply = edbus_message_method_return_new(msg);
946 edbus_message_arguments_append(reply, "o", return_path);
947 return reply;
948}
949
950static const EDBus_Method _ethumb_dbus_methods[] = {
951 {
952 "new", NULL, EDBUS_ARGS({"o", "path"}), _ethumb_dbus_ethumb_new_cb, 0
953 },
954 { }
955};
956
957static const char *
958_ethumb_dbus_get_bytearray(EDBus_Message_Iter *iter)
959{
960 int length;
961 const char *result;
962
963 if (!edbus_message_iter_fixed_array_get(iter, 'y', &result,
964 &length))
965 {
966 ERR("not byte array element. Signature: %s",
967 edbus_message_iter_signature_get(iter));
968 return NULL;
969 }
970
971 if ((length == 0) || (result[0] == '\0'))
972 return NULL;
973 else
974 return eina_stringshare_add_length(result, length);
975}
976
977static void
978_ethumb_dbus_append_bytearray(EDBus_Message_Iter *parent, EDBus_Message_Iter *array, const char *string)
979{
980 int i, size;
981
982 if (!string)
983 string = "";
984
985 size = strlen(string) + 1;
986 for (i = 0; i < size; i++)
987 edbus_message_iter_basic_append(array, 'y', string[i]);
988 edbus_message_iter_container_close(parent, array);
989}
990
991static EDBus_Message *
992_ethumb_dbus_queue_add_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
993{
994 EDBus_Message *reply;
995 const char *file, *key, *thumb, *thumb_key;
996 Ethumbd_Object_Data *odata;
997 Ethumbd_Object *eobject;
998 Ethumbd *ed;
999 Ethumbd_Request *request;
1000 int id = -1;
1001 EDBus_Message_Iter *file_iter, *key_iter, *thumb_iter, *thumb_key_iter;
1002
1003 if (!edbus_message_arguments_get(msg, "iayayayay", &id, &file_iter,
1004 &key_iter, &thumb_iter, &thumb_key_iter))
1005 {
1006 ERR("Error getting arguments.");
1007 goto end;
1008 }
1009 file = _ethumb_dbus_get_bytearray(file_iter);
1010 key = _ethumb_dbus_get_bytearray(key_iter);
1011 thumb = _ethumb_dbus_get_bytearray(thumb_iter);
1012 thumb_key = _ethumb_dbus_get_bytearray(thumb_key_iter);
1013
1014 if (!file)
1015 {
1016 eina_stringshare_del(key);
1017 eina_stringshare_del(thumb);
1018 eina_stringshare_del(thumb_key);
1019 ERR("no filename given.");
1020 goto end;
1021 }
1022
1023 odata = edbus_service_object_data_get(iface, ODATA);
1024 if (!odata)
1025 {
1026 eina_stringshare_del(file);
1027 eina_stringshare_del(key);
1028 eina_stringshare_del(thumb);
1029 eina_stringshare_del(thumb_key);
1030 ERR("could not get dbus_object data.");
1031 goto end;
1032 }
1033
1034 ed = odata->ed;
1035 eobject = &(ed->queue.table[odata->idx]);
1036 if (!_ethumb_dbus_check_id(eobject, id))
1037 goto end;
1038 request = calloc(1, sizeof(*request));
1039 request->id = id;
1040 request->file = file;
1041 request->key = key;
1042 request->thumb = thumb;
1043 request->thumb_key = thumb_key;
1044 eobject->queue = eina_list_append(eobject->queue, request);
1045 eobject->nqueue++;
1046 ed->queue.nqueue++;
1047 _ethumb_dbus_inc_max_id(eobject, id);
1048
1049 _process_queue_start(ed);
1050
1051end:
1052 reply = edbus_message_method_return_new(msg);
1053 edbus_message_arguments_append(reply, "i", id);
1054 return reply;
1055}
1056
1057static EDBus_Message *
1058_ethumb_dbus_queue_remove_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
1059{
1060 EDBus_Message *reply;
1061 int id;
1062 Ethumbd_Object_Data *odata;
1063 Ethumbd_Object *eobject;
1064 Ethumbd_Request *request;
1065 Ethumbd *ed;
1066 Eina_Bool r = EINA_FALSE;
1067 Eina_List *l;
1068
1069 if (!edbus_message_arguments_get(msg, "i", &id))
1070 {
1071 ERR("Error getting arguments.");
1072 goto end;
1073 }
1074 odata = edbus_service_object_data_get(iface, ODATA);
1075 if (!odata)
1076 {
1077 ERR("could not get dbus_object data.");
1078 goto end;
1079 }
1080
1081 ed = odata->ed;
1082 eobject = &ed->queue.table[odata->idx];
1083 l = eobject->queue;
1084 while (l)
1085 {
1086 request = l->data;
1087 if (id == request->id)
1088 break;
1089 l = l->next;
1090 }
1091
1092 if (l)
1093 {
1094 r = EINA_TRUE;
1095 eina_stringshare_del(request->file);
1096 eina_stringshare_del(request->key);
1097 eina_stringshare_del(request->thumb);
1098 eina_stringshare_del(request->thumb_key);
1099 free(request);
1100 eobject->queue = eina_list_remove_list(eobject->queue, l);
1101 eobject->nqueue--;
1102 ed->queue.nqueue--;
1103 _ethumb_dbus_inc_min_id(eobject);
1104 }
1105
1106 end:
1107 reply = edbus_message_method_return_new(msg);
1108 edbus_message_arguments_append(reply, "b", r);
1109 return reply;
1110}
1111
1112static EDBus_Message *
1113_ethumb_dbus_queue_clear_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
1114{
1115 Ethumbd_Object_Data *odata;
1116 Ethumbd_Object *eobject;
1117 Ethumbd *ed;
1118 Eina_List *l;
1119
1120 odata = edbus_service_object_data_get(iface, ODATA);
1121 if (!odata)
1122 {
1123 ERR("could not get dbus_object data.");
1124 goto end;
1125 }
1126
1127 ed = odata->ed;
1128 eobject = &ed->queue.table[odata->idx];
1129 l = eobject->queue;
1130 while (l)
1131 {
1132 Ethumbd_Request *request = l->data;
1133 eina_stringshare_del(request->file);
1134 eina_stringshare_del(request->key);
1135 eina_stringshare_del(request->thumb);
1136 eina_stringshare_del(request->thumb_key);
1137 free(request);
1138 l = eina_list_remove_list(l, l);
1139 }
1140 ed->queue.nqueue -= eobject->nqueue;
1141 eobject->nqueue = 0;
1142
1143 end:
1144 return edbus_message_method_return_new(msg);
1145}
1146
1147static EDBus_Message *
1148_ethumb_dbus_delete_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
1149{
1150 EDBus_Message *reply;
1151 Ethumbd_Object_Data *odata;
1152 Ethumbd *ed;
1153
1154 reply = edbus_message_method_return_new(msg);
1155
1156 odata = edbus_service_object_data_get(iface, ODATA);
1157 if (!odata)
1158 {
1159 ERR("could not get dbus_object data for del_cb.");
1160 return reply;
1161 }
1162 ed = odata->ed;
1163 _ethumb_table_del(ed, odata->idx);
1164 free(odata);
1165
1166 return reply;
1167}
1168
1169static int
1170_ethumb_dbus_fdo_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1171{
1172 int fdo;
1173
1174 if (!edbus_message_iter_arguments_get(variant, "i", &fdo))
1175 {
1176 ERR("invalid param for fdo_set.");
1177 return 0;
1178 }
1179
1180 DBG("setting fdo to: %d", fdo);
1181 request->setup.flags.fdo = 1;
1182 request->setup.fdo = fdo;
1183
1184 return 1;
1185}
1186
1187static int
1188_ethumb_dbus_size_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1189{
1190 EDBus_Message_Iter *st;
1191 int w, h;
1192
1193 if (!edbus_message_iter_arguments_get(variant, "(ii)", &st))
1194 {
1195 ERR("invalid param for size_set.");
1196 return 0;
1197 }
1198
1199 edbus_message_iter_arguments_get(st, "ii", &w, &h);
1200 DBG("setting size to: %dx%d", w, h);
1201 request->setup.flags.size = 1;
1202 request->setup.tw = w;
1203 request->setup.th = h;
1204
1205 return 1;
1206}
1207
1208static int
1209_ethumb_dbus_format_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1210{
1211 int format;
1212
1213 if (!edbus_message_iter_arguments_get(variant, "i", &format))
1214 {
1215 ERR("invalid param for format_set.");
1216 return 0;
1217 }
1218
1219 DBG("setting format to: %d", format);
1220 request->setup.flags.format = 1;
1221 request->setup.format = format;
1222
1223 return 1;
1224}
1225
1226static int
1227_ethumb_dbus_aspect_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1228{
1229 int aspect;
1230
1231 if (!edbus_message_iter_arguments_get(variant, "i", &aspect))
1232 {
1233 ERR("invalid param for aspect_set.");
1234 return 0;
1235 }
1236
1237 DBG("setting aspect to: %d", aspect);
1238 request->setup.flags.aspect = 1;
1239 request->setup.aspect = aspect;
1240
1241 return 1;
1242}
1243
1244static int
1245_ethumb_dbus_orientation_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1246{
1247 int orientation;
1248
1249 if (!edbus_message_iter_arguments_get(variant, "i", &orientation))
1250 {
1251 ERR("invalid param for orientation_set.");
1252 return 0;
1253 }
1254
1255 DBG("setting orientation to: %d", orientation);
1256 request->setup.flags.orientation = 1;
1257 request->setup.orientation = orientation;
1258
1259 return 1;
1260}
1261
1262static int
1263_ethumb_dbus_crop_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1264{
1265 EDBus_Message_Iter *st;
1266 double x, y;
1267
1268 if (!edbus_message_iter_arguments_get(variant, "(dd)", &st))
1269 {
1270 ERR("invalid param for crop_set.");
1271 return 0;
1272 }
1273
1274 edbus_message_iter_arguments_get(st, "dd", &x, &y);
1275 DBG("setting crop to: %3.2f,%3.2f", x, y);
1276 request->setup.flags.crop = 1;
1277 request->setup.cx = x;
1278 request->setup.cy = y;
1279
1280 return 1;
1281}
1282
1283static int
1284_ethumb_dbus_quality_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1285{
1286 int quality;
1287
1288 if (!edbus_message_iter_arguments_get(variant, "i", &quality))
1289 {
1290 ERR("invalid param for quality_set.");
1291 return 0;
1292 }
1293
1294 DBG("setting quality to: %d", quality);
1295 request->setup.flags.quality = 1;
1296 request->setup.quality = quality;
1297
1298 return 1;
1299}
1300
1301
1302static int
1303_ethumb_dbus_compress_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1304{
1305 int compress;
1306
1307 if (!edbus_message_iter_arguments_get(variant, "i", &compress))
1308 {
1309 ERR("invalid param for compress_set.");
1310 return 0;
1311 }
1312
1313 DBG("setting compress to: %d", compress);
1314 request->setup.flags.compress = 1;
1315 request->setup.compress = compress;
1316
1317 return 1;
1318}
1319
1320static int
1321_ethumb_dbus_frame_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1322{
1323 EDBus_Message_Iter *_struct, *file_iter, *group_iter, *swallow_iter;
1324 const char *file, *group, *swallow;
1325
1326 if (!edbus_message_iter_arguments_get(variant, "(ayayay)", &_struct))
1327 {
1328 ERR("invalid param for frame_set.");
1329 return 0;
1330 }
1331
1332 edbus_message_iter_arguments_get(_struct, "ayayay", &file_iter, &group_iter, &swallow_iter);
1333
1334 file = _ethumb_dbus_get_bytearray(file_iter);
1335 group = _ethumb_dbus_get_bytearray(group_iter);
1336 swallow = _ethumb_dbus_get_bytearray(swallow_iter);
1337 DBG("setting frame to \"%s:%s:%s\"", file, group, swallow);
1338 request->setup.flags.frame = 1;
1339 request->setup.theme_file = file;
1340 request->setup.group = group;
1341 request->setup.swallow = swallow;
1342
1343 return 1;
1344}
1345
1346static int
1347_ethumb_dbus_directory_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1348{
1349 const char *directory;
1350 EDBus_Message_Iter *array;
1351
1352 if (!edbus_message_iter_arguments_get(variant, "ay", &array))
1353 {
1354 ERR("invalid param for dir_path_set.");
1355 return 0;
1356 }
1357
1358 directory = _ethumb_dbus_get_bytearray(array);
1359 DBG("setting directory to: %s", directory);
1360 request->setup.flags.directory = 1;
1361 request->setup.directory = directory;
1362
1363 return 1;
1364}
1365
1366static int
1367_ethumb_dbus_category_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1368{
1369 const char *category;
1370 EDBus_Message_Iter *array;
1371
1372 if (!edbus_message_iter_arguments_get(variant, "ay", &array))
1373 {
1374 ERR("invalid param for category.");
1375 return 0;
1376 }
1377
1378 category = _ethumb_dbus_get_bytearray(array);
1379 DBG("setting category to: %s", category);
1380 request->setup.flags.category = 1;
1381 request->setup.category = category;
1382
1383 return 1;
1384}
1385
1386static int
1387_ethumb_dbus_video_time_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1388{
1389 double video_time;
1390
1391 if (!edbus_message_iter_arguments_get(variant, "d", &video_time))
1392 {
1393 ERR("invalid param for video_time_set.");
1394 return 0;
1395 }
1396
1397 DBG("setting video_time to: %3.2f", video_time);
1398 request->setup.flags.video_time = 1;
1399 request->setup.video_time = video_time;
1400
1401 return 1;
1402}
1403
1404static int
1405_ethumb_dbus_video_start_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1406{
1407 double video_start;
1408
1409 if (!edbus_message_iter_arguments_get(variant, "d", &video_start))
1410 {
1411 ERR("invalid param for video_start_set.");
1412 return 0;
1413 }
1414
1415 DBG("setting video_start to: %3.2f", video_start);
1416 request->setup.flags.video_start = 1;
1417 request->setup.video_start = video_start;
1418
1419 return 1;
1420}
1421
1422static int
1423_ethumb_dbus_video_interval_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1424{
1425 double video_interval;
1426
1427 if (!edbus_message_iter_arguments_get(variant, "d", &video_interval))
1428 {
1429 ERR("invalid param for video_interval_set.");
1430 return 0;
1431 }
1432 DBG("setting video_interval to: %3.2f", video_interval);
1433 request->setup.flags.video_interval = 1;
1434 request->setup.video_interval = video_interval;
1435
1436 return 1;
1437}
1438
1439static int
1440_ethumb_dbus_video_ntimes_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1441{
1442 unsigned int video_ntimes;
1443
1444 if (!edbus_message_iter_arguments_get(variant, "u", &video_ntimes))
1445 {
1446 ERR("invalid param for video_ntimes_set.");
1447 return 0;
1448 }
1449
1450 DBG("setting video_ntimes to: %3.2d", video_ntimes);
1451 request->setup.flags.video_ntimes = 1;
1452 request->setup.video_ntimes = video_ntimes;
1453
1454 return 1;
1455}
1456
1457static int
1458_ethumb_dbus_video_fps_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1459{
1460 unsigned int video_fps;
1461
1462 if (!edbus_message_iter_arguments_get(variant, "u", &video_fps))
1463 {
1464 ERR("invalid param for video_fps_set.");
1465 return 0;
1466 }
1467
1468 DBG("setting video_fps to: %3.2d", video_fps);
1469 request->setup.flags.video_fps = 1;
1470 request->setup.video_fps = video_fps;
1471
1472 return 1;
1473}
1474
1475static int
1476_ethumb_dbus_document_page_set(Ethumbd_Object *eobject EINA_UNUSED, EDBus_Message_Iter *variant, Ethumbd_Request *request)
1477{
1478 unsigned int document_page;
1479
1480 if (!edbus_message_iter_arguments_get(variant, "u", &document_page))
1481 {
1482 ERR("invalid param for document_page_set.");
1483 return 0;
1484 }
1485
1486 DBG("setting document_page to: %d", document_page);
1487 request->setup.flags.document_page = 1;
1488 request->setup.document_page = document_page;
1489
1490 return 1;
1491}
1492
1493static struct
1494{
1495 const char *option;
1496 int (*setup_func)(Ethumbd_Object *eobject, EDBus_Message_Iter *variant, Ethumbd_Request *request);
1497} _option_cbs[] = {
1498 {"fdo", _ethumb_dbus_fdo_set},
1499 {"size", _ethumb_dbus_size_set},
1500 {"format", _ethumb_dbus_format_set},
1501 {"aspect", _ethumb_dbus_aspect_set},
1502 {"orientation", _ethumb_dbus_orientation_set},
1503 {"crop", _ethumb_dbus_crop_set},
1504 {"quality", _ethumb_dbus_quality_set},
1505 {"compress", _ethumb_dbus_compress_set},
1506 {"frame", _ethumb_dbus_frame_set},
1507 {"directory", _ethumb_dbus_directory_set},
1508 {"category", _ethumb_dbus_category_set},
1509 {"video_time", _ethumb_dbus_video_time_set},
1510 {"video_start", _ethumb_dbus_video_start_set},
1511 {"video_interval", _ethumb_dbus_video_interval_set},
1512 {"video_ntimes", _ethumb_dbus_video_ntimes_set},
1513 {"video_fps", _ethumb_dbus_video_fps_set},
1514 {"document_page", _ethumb_dbus_document_page_set},
1515 {NULL, NULL}
1516};
1517
1518static int
1519_ethumb_dbus_ethumb_setup_parse_element(Ethumbd_Object *eobject, EDBus_Message_Iter *data, Ethumbd_Request *request)
1520{
1521 EDBus_Message_Iter *variant;
1522 const char *option;
1523 int i, r;
1524
1525 edbus_message_iter_arguments_get(data, "sv", &option, &variant);
1526
1527 r = 0;
1528 for (i = 0; _option_cbs[i].option; i++)
1529 if (!strcmp(_option_cbs[i].option, option))
1530 {
1531 r = 1;
1532 break;
1533 }
1534
1535 if (!r)
1536 {
1537 ERR("ethumb_setup invalid option: %s", option);
1538 return 0;
1539 }
1540
1541 return _option_cbs[i].setup_func(eobject, variant, request);
1542}
1543
1544static EDBus_Message *
1545_ethumb_dbus_ethumb_setup_cb(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
1546{
1547 EDBus_Message *reply;
1548 Ethumbd_Object_Data *odata;
1549 Ethumbd *ed;
1550 Ethumbd_Object *eobject;
1551 Ethumbd_Request *request;
1552 Eina_Bool r = EINA_FALSE;
1553 EDBus_Message_Iter *array;
1554 EDBus_Message_Iter *data;
1555
1556 if (!edbus_message_arguments_get(msg, "a{sv}", &array))
1557 {
1558 ERR("could not get dbus_object data for setup_cb.");
1559 goto end;
1560 }
1561
1562 odata = edbus_service_object_data_get(iface, ODATA);
1563 if (!odata)
1564 {
1565 ERR("could not get dbus_object data for setup_cb.");
1566 goto end;
1567 }
1568
1569 ed = odata->ed;
1570 eobject = &ed->queue.table[odata->idx];
1571
1572 request = calloc(1, sizeof(*request));
1573 request->id = -1;
1574
1575 r = EINA_TRUE;
1576 while (edbus_message_iter_get_and_next(array, 'r', &data) && r)
1577 {
1578 if (!_ethumb_dbus_ethumb_setup_parse_element(eobject, data, request))
1579 r = EINA_FALSE;
1580 }
1581
1582 eobject->queue = eina_list_append(eobject->queue, request);
1583 eobject->nqueue++;
1584 ed->queue.nqueue++;
1585
1586end:
1587 reply = edbus_message_method_return_new(msg);
1588 edbus_message_arguments_append(reply, "b", r);
1589 return reply;
1590}
1591
1592static void
1593_ethumb_dbus_generated_signal(Ethumbd *ed, int *id, const char *thumb_path, const char *thumb_key, Eina_Bool success)
1594{
1595 EDBus_Message *sig;
1596 EDBus_Service_Interface *iface;
1597 EDBus_Message_Iter *iter, *iter_path, *iter_key;
1598 int id32;
1599
1600 id32 = *id;
1601
1602 iface = ed->queue.table[ed->queue.current].iface;
1603 sig = edbus_service_signal_new(iface, ETHUMB_DBUS_OBJECTS_SIGNAL_GENERATED);
1604
1605 iter = edbus_message_iter_get(sig);
1606 edbus_message_iter_arguments_append(iter, "iay", id32, &iter_path);
1607 _ethumb_dbus_append_bytearray(iter, iter_path, thumb_path);
1608 edbus_message_iter_arguments_append(iter, "ay", &iter_key);
1609 _ethumb_dbus_append_bytearray(iter, iter_key, thumb_key);
1610 edbus_message_iter_arguments_append(iter, "b", success);
1611
1612 edbus_service_signal_send(iface, sig);
1613}
1614
1615static const EDBus_Service_Interface_Desc server_desc = {
1616 _ethumb_dbus_interface, _ethumb_dbus_methods
1617};
1618
1619static void
1620_ethumb_dbus_request_name_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
1621{
1622 EDBus_Service_Interface *iface;
1623 const char *errname, *errmsg;
1624 Ethumbd *ed = data;
1625
1626 if (edbus_message_error_get(msg, &errname, &errmsg))
1627 {
1628 ERR("request name error: %s %s", errname, errmsg);
1629 edbus_connection_unref(ed->conn);
1630 return;
1631 }
1632
1633 iface = edbus_service_interface_register(ed->conn, _ethumb_dbus_path,
1634 &server_desc);
1635 EINA_SAFETY_ON_NULL_RETURN(iface);
1636
1637 edbus_service_object_data_set(iface, DAEMON, ed);
1638
1639 _ethumbd_timeout_start(ed);
1640}
1641
1642static int
1643_ethumb_dbus_setup(Ethumbd *ed)
1644{
1645 edbus_name_request(ed->conn, _ethumb_dbus_bus_name, 0,
1646 _ethumb_dbus_request_name_cb, ed);
1647 return 1;
1648}
1649
1650static void
1651_ethumb_dbus_finish(Ethumbd *ed)
1652{
1653 _process_queue_stop(ed);
1654 _ethumb_table_clear(ed);
1655 edbus_connection_unref(ed->conn);
1656 free(ed->queue.table);
1657 free(ed->queue.list);
1658}
1659
1660static Eina_Bool
1661_ethumbd_slave_spawn(Ethumbd_Slave *slave, Ethumbd *ed)
1662{
1663 char buf[PATH_MAX];
1664
1665 slave->bufcmd = NULL;
1666 slave->scmd = 0;
1667
1668 snprintf(buf, sizeof(buf), "%s/ethumb/utils/"MODULE_ARCH"/ethumbd_slave",
1669 eina_prefix_lib_get(_pfx));
1670
1671 slave->exe = ecore_exe_pipe_run(buf,
1672 ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE, ed);
1673 if (!slave->exe)
1674 {
1675 ERR("could not create slave.");
1676 return 0;
1677 }
1678
1679 return 1;
1680}
1681
1682int
1683main(int argc, char *argv[])
1684{
1685 Eina_Bool quit_option = 0;
1686 int exit_value = 0;
1687 int arg_idx;
1688 Ethumbd ed;
1689 int child;
1690 double timeout = -1;
1691
1692 memset(&ed, 0, sizeof(ed));
1693 ecore_init();
1694 eina_init();
1695
1696 ethumb_init();
1697
1698 if (_log_domain < 0)
1699 {
1700 _log_domain = eina_log_domain_register("ethumbd", NULL);
1701 if (_log_domain < 0)
1702 {
1703 EINA_LOG_CRIT("could not register log domain 'ethumbd'");
1704 exit_value = -8;
1705 goto finish;
1706 }
1707 }
1708
1709 _pfx = eina_prefix_new(argv[0], ethumb_init,
1710 "ETHUMB", "ethumb", "checkme",
1711 PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
1712 PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
1713 if (!_pfx)
1714 {
1715 ERR("Could not get ethumb installation prefix.");
1716 exit_value = -7;
1717 goto finish;
1718 }
1719
1720 ed.data_cb = ecore_event_handler_add(ECORE_EXE_EVENT_DATA,
1721 _ethumbd_slave_data_read_cb, &ed);
1722 ed.del_cb = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
1723 _ethumbd_slave_del_cb, &ed);
1724
1725 child = _ethumbd_slave_spawn(&ed.slave, &ed);
1726 if (!child)
1727 {
1728 exit_value = -6;
1729 goto finish;
1730 }
1731
1732 if (child == 2)
1733 {
1734 exit_value = 0;
1735 goto finish;
1736 }
1737
1738 if (!edbus_init())
1739 {
1740 ERR("could not init edbus.");
1741 exit_value = -1;
1742 goto finish;
1743 }
1744
1745 Ecore_Getopt_Value values[] = {
1746 ECORE_GETOPT_VALUE_DOUBLE(timeout),
1747 ECORE_GETOPT_VALUE_BOOL(quit_option),
1748 ECORE_GETOPT_VALUE_BOOL(quit_option),
1749 ECORE_GETOPT_VALUE_BOOL(quit_option),
1750 ECORE_GETOPT_VALUE_BOOL(quit_option),
1751 ECORE_GETOPT_VALUE_NONE
1752 };
1753
1754 arg_idx = ecore_getopt_parse(&optdesc, values, argc, argv);
1755 if (arg_idx < 0)
1756 {
1757 ERR("Could not parse arguments.");
1758 exit_value = -2;
1759 goto finish;
1760 }
1761
1762 if (quit_option)
1763 goto finish;
1764
1765 ed.conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
1766 if (!ed.conn)
1767 {
1768 ERR("could not connect to session bus.");
1769 exit_value = -3;
1770 goto finish_edbus;
1771 }
1772
1773 ed.timeout = timeout;
1774
1775 if (!_ethumb_dbus_setup(&ed))
1776 {
1777 edbus_connection_unref(ed.conn);
1778 ERR("could not setup dbus connection.");
1779 exit_value = -5;
1780 goto finish_edbus;
1781 }
1782
1783 ecore_main_loop_begin();
1784 _ethumb_dbus_finish(&ed);
1785
1786 finish_edbus:
1787 if (_log_domain >= 0)
1788 {
1789 eina_log_domain_unregister(_log_domain);
1790 _log_domain = -1;
1791 }
1792
1793 edbus_shutdown();
1794 finish:
1795 if (ed.slave.exe)
1796 ecore_exe_quit(ed.slave.exe);
1797
1798 if (_pfx) eina_prefix_free(_pfx);
1799 ethumb_shutdown();
1800 eina_init();
1801 ecore_shutdown();
1802 return exit_value;
1803}
diff --git a/src/bin/ethumb/ethumbd_client.c b/src/bin/ethumb/ethumbd_client.c
deleted file mode 100644
index e81fc2e9a7..0000000000
--- a/src/bin/ethumb/ethumbd_client.c
+++ /dev/null
@@ -1,330 +0,0 @@
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#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <limits.h>
30
31#include <Eina.h>
32#include <Ecore_Getopt.h>
33#include <Ecore.h>
34#include <Ethumb_Client.h>
35
36const char *aspect_opt[] = { "keep", "ignore", "crop", NULL };
37const char *format_opt[] = { "png", "jpg", "eet", NULL };
38struct frame
39{
40 const char *file;
41 const char *group;
42 const char *swallow;
43};
44
45struct options
46{
47 Eina_Rectangle geometry;
48 unsigned int format, aspect;
49 char *format_str;
50 char *aspect_str;
51 char *directory;
52 char *category;
53 struct frame frame;
54 char *src_path;
55 char *src_key;
56 const char *thumb_path;
57 const char *thumb_key;
58 double video_time;
59 int page;
60};
61
62static unsigned char
63_ethumb_getopt_callback_frame_parse(const Ecore_Getopt *parser EINA_UNUSED, const Ecore_Getopt_Desc *desc EINA_UNUSED, const char *str, void *data EINA_UNUSED, Ecore_Getopt_Value *storage)
64{
65 struct frame *f = (struct frame *)storage->ptrp;
66 const char *tfile, *tgroup, *tswallow, *base, *sep;
67
68 base = str;
69 sep = strchr(base, ':');
70 if (!sep)
71 goto error;
72 tfile = eina_stringshare_add_length(base, sep - base);
73 base = sep + 1;
74
75 sep = strchr(base, ':');
76 if (!sep)
77 {
78 eina_stringshare_del(tfile);
79 goto error;
80 }
81 tgroup = eina_stringshare_add_length(base, sep - base);
82 base = sep + 1;
83 if (base[0] == '\0')
84 {
85 eina_stringshare_del(tfile);
86 eina_stringshare_del(tgroup);
87 goto error;
88 }
89 tswallow = eina_stringshare_add(base);
90
91 f->file = tfile;
92 f->group = tgroup;
93 f->swallow = tswallow;
94 return 1;
95
96 error:
97 fprintf(stderr,
98 "ERROR: invalid theme, not in format "
99 "'file:group:swallow_part': '%s'\n",
100 str);
101 return 0;
102}
103
104const Ecore_Getopt optdesc = {
105 "ethumbd_client",
106 NULL,
107 PACKAGE_VERSION,
108 "(C) 2009 - ProFUSION embedded systems",
109 "LGPL v2.1 - GNU Lesser General Public License",
110 "Thumbnails generator client using DBus and ethumbd.\n"
111 "\n"
112 "This program uses ethumbd server to create thumbnails from pictures. "
113 "It's an example of use and a test for ethumbd.\n",
114 0,
115 {
116 ECORE_GETOPT_CALLBACK_ARGS
117 ('s', "size", "thumbnail size expected.",
118 "WxH", ecore_getopt_callback_size_parse, NULL),
119 ECORE_GETOPT_CHOICE
120 ('f', "format", "file format to save.", format_opt),
121 ECORE_GETOPT_CHOICE
122 ('a', "aspect", "original image aspect ratio.", aspect_opt),
123 ECORE_GETOPT_STORE_STR
124 ('d', "directory", "directory to save thumbnails."),
125 ECORE_GETOPT_STORE_STR
126 ('c', "category", "thumbnails category."),
127 ECORE_GETOPT_CALLBACK_ARGS
128 ('t', "theme", "path to theme file, group and swallow part.",
129 "file:group:swallow_part", _ethumb_getopt_callback_frame_parse, NULL),
130 ECORE_GETOPT_STORE_STR
131 ('k', "key", "key inside eet file to read image from."),
132 ECORE_GETOPT_STORE_DOUBLE
133 ('v', "video_time", "time of video frame to use as thumbnail."),
134 ECORE_GETOPT_STORE_INT
135 ('p', "document_page", "document page to use as thumbnail."),
136 ECORE_GETOPT_LICENSE('L', "license"),
137 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
138 ECORE_GETOPT_VERSION('V', "version"),
139 ECORE_GETOPT_HELP('h', "help"),
140 ECORE_GETOPT_SENTINEL
141 }
142};
143
144static void
145_thumb_report(const char *mode, const char *src_path, const char *src_key, const char *thumb_path, const char *thumb_key)
146{
147 printf("%s '%s' '%s' => '%s' '%s'\n",
148 mode,
149 src_path, src_key ? src_key : "",
150 thumb_path, thumb_key ? thumb_key : "");
151}
152
153static void
154_finished_thumb(void *data EINA_UNUSED, Ethumb_Client *client EINA_UNUSED, int id EINA_UNUSED, const char *src_path, const char *src_key, const char *thumb_path, const char *thumb_key, Eina_Bool success)
155{
156 const char *mode = success ? "GENERATED" : "FAILED";
157 _thumb_report(mode, src_path, src_key, thumb_path, thumb_key);
158 ecore_main_loop_quit();
159}
160
161static void
162_exists(void *data, Ethumb_Client *c, EINA_UNUSED Ethumb_Exists *thread, Eina_Bool exists)
163{
164 struct options *opts = data;
165 const char *thumb_path, *thumb_key;
166 long id;
167
168 if (exists)
169 {
170 ethumb_client_thumb_path_get(c, &thumb_path, &thumb_key);
171 _thumb_report
172 ("EXISTS", opts->src_path, opts->src_key, thumb_path, thumb_key);
173 ecore_main_loop_quit();
174 return;
175 }
176
177 id = ethumb_client_generate(c, _finished_thumb, NULL, NULL);
178 if (id < 0)
179 {
180 fputs("ERROR: could not request thumbnail to be generated.\n", stderr);
181 ecore_main_loop_quit();
182 return;
183 }
184 printf("request id=%ld, file='%s', key='%s'\n",
185 id, opts->src_path, opts->src_key ? opts->src_key : "");
186
187}
188
189static void
190_connected(void *data, Ethumb_Client *c, Eina_Bool success)
191{
192 struct options *opts = data;
193
194 if (!success)
195 {
196 fputs("ERROR: could not connect to DBus server.\n", stderr);
197 ecore_main_loop_quit();
198 return;
199 }
200
201 fputs("connected to DBus server, setup parameters...\n", stdout);
202
203 ethumb_client_format_set(c, opts->format);
204 ethumb_client_aspect_set(c, opts->aspect);
205
206 if (opts->directory) ethumb_client_dir_path_set(c, opts->directory);
207 if (opts->category) ethumb_client_category_set(c, opts->category);
208 if (opts->geometry.w > 0 && opts->geometry.h > 0)
209 ethumb_client_size_set(c, opts->geometry.w, opts->geometry.h);
210 if (opts->frame.file)
211 ethumb_client_frame_set
212 (c, opts->frame.file, opts->frame.group, opts->frame.swallow);
213 if (opts->video_time > 0)
214 ethumb_client_video_time_set(c, opts->video_time);
215 if (opts->page > 0)
216 ethumb_client_document_page_set(c, opts->page);
217
218 if (!ethumb_client_file_set(c, opts->src_path, opts->src_key))
219 {
220 fprintf(stderr, "ERROR: could not set file '%s', key '%s'\n",
221 opts->src_path, opts->src_key ? opts->src_key : "");
222 ecore_main_loop_quit();
223 return;
224 }
225
226 ethumb_client_thumb_path_set(c, opts->thumb_path, opts->thumb_key);
227 ethumb_client_thumb_exists(c, _exists, opts);
228}
229
230int
231main(int argc, char *argv[])
232{
233 Ethumb_Client *c;
234 Eina_Bool quit_option = 0;
235 const char *format_str = NULL, *aspect_str = NULL;
236 struct options opts = {
237 {-1, -1, -1, -1},
238 0, 0,
239 NULL, NULL, NULL, NULL,
240 {NULL, NULL, NULL},
241 NULL, NULL, NULL, NULL,
242 0.0,
243 0
244 };
245 int arg_index;
246 int i, ret = 0;
247
248 ethumb_client_init();
249 ecore_init();
250
251 Ecore_Getopt_Value values[] = {
252 ECORE_GETOPT_VALUE_PTR_CAST(opts.geometry),
253 ECORE_GETOPT_VALUE_PTR_CAST(format_str),
254 ECORE_GETOPT_VALUE_PTR_CAST(aspect_str),
255 ECORE_GETOPT_VALUE_STR(opts.directory),
256 ECORE_GETOPT_VALUE_STR(opts.category),
257 ECORE_GETOPT_VALUE_PTR_CAST(opts.frame),
258 ECORE_GETOPT_VALUE_STR(opts.src_key),
259 ECORE_GETOPT_VALUE_DOUBLE(opts.video_time),
260 ECORE_GETOPT_VALUE_INT(opts.page),
261 ECORE_GETOPT_VALUE_BOOL(quit_option),
262 ECORE_GETOPT_VALUE_BOOL(quit_option),
263 ECORE_GETOPT_VALUE_BOOL(quit_option),
264 ECORE_GETOPT_VALUE_BOOL(quit_option),
265 ECORE_GETOPT_VALUE_NONE
266 };
267
268 arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
269 if ((arg_index < 0) || (arg_index == argc))
270 {
271 if (arg_index < 0)
272 fprintf(stderr, "Could not parse arguments.\n");
273 else
274 fprintf(stderr, "Missing source file to thumbnail.\n");
275
276 ret = 1;
277 goto end;
278 }
279
280 if (quit_option)
281 {
282 ret = 0;
283 goto end;
284 }
285
286 for (i = 0; i < 3; i++)
287 if (format_opt[i] == format_str)
288 {
289 opts.format = i;
290 break;
291 }
292
293 for (i = 0; i < 3; i++)
294 if (aspect_opt[i] == aspect_str)
295 {
296 opts.aspect = i;
297 break;
298 }
299
300 opts.src_path = argv[arg_index++];
301 if (arg_index < argc)
302 {
303 opts.thumb_path = argv[arg_index++];
304 if (arg_index < argc)
305 opts.thumb_key = argv[arg_index];
306 }
307
308 c = ethumb_client_connect(_connected, &opts, NULL);
309 if (!c)
310 {
311 fputs("ERROR: could not connect to server.\n", stderr);
312 ret = 2;
313 goto end;
314 }
315
316 ecore_main_loop_begin();
317 ethumb_client_disconnect(c);
318
319 end:
320 if (opts.frame.file)
321 {
322 eina_stringshare_del(opts.frame.file);
323 eina_stringshare_del(opts.frame.group);
324 eina_stringshare_del(opts.frame.swallow);
325 }
326 ecore_shutdown();
327 ethumb_client_shutdown();
328
329 return ret;
330}
diff --git a/src/bin/ethumb/ethumbd_private.h b/src/bin/ethumb/ethumbd_private.h
deleted file mode 100644
index 688eaddd6b..0000000000
--- a/src/bin/ethumb/ethumbd_private.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef __ETHUMBD_PRIVATE_H__
2#define __ETHUMBD_PRIVATE_H__ 1
3
4
5enum Ethumbd_Operations
6{
7 ETHUMBD_OP_NEW,
8 ETHUMBD_OP_GENERATE,
9 ETHUMBD_OP_SETUP,
10 ETHUMBD_OP_DEL
11};
12
13enum Ethubmd_Setup_Option
14{
15 ETHUMBD_FDO,
16 ETHUMBD_SIZE_W,
17 ETHUMBD_SIZE_H,
18 ETHUMBD_FORMAT,
19 ETHUMBD_ASPECT,
20 ETHUMBD_ORIENTATION,
21 ETHUMBD_CROP_X,
22 ETHUMBD_CROP_Y,
23 ETHUMBD_QUALITY,
24 ETHUMBD_COMPRESS,
25 ETHUMBD_DIRECTORY,
26 ETHUMBD_CATEGORY,
27 ETHUMBD_FRAME_FILE,
28 ETHUMBD_FRAME_GROUP,
29 ETHUMBD_FRAME_SWALLOW,
30 ETHUMBD_VIDEO_TIME,
31 ETHUMBD_VIDEO_START,
32 ETHUMBD_VIDEO_INTERVAL,
33 ETHUMBD_VIDEO_NTIMES,
34 ETHUMBD_VIDEO_FPS,
35 ETHUMBD_DOCUMENT_PAGE,
36 ETHUMBD_SETUP_FINISHED
37};
38
39void ethumbd_child_start(int pipein, int pipeout);
40
41#endif
diff --git a/src/bin/ethumb/ethumbd_slave.c b/src/bin/ethumb/ethumbd_slave.c
deleted file mode 100644
index b1d319a305..0000000000
--- a/src/bin/ethumb/ethumbd_slave.c
+++ /dev/null
@@ -1,770 +0,0 @@
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
27#include <stdlib.h>
28#include <unistd.h>
29#include <limits.h>
30#include <string.h>
31#include <errno.h>
32
33#include <Eina.h>
34#include <Ecore.h>
35#include <Ethumb.h>
36
37#include "ethumbd_private.h"
38
39#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
40#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
41#define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__)
42#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
43
44#define NETHUMBS 100
45
46static int _log_domain = -1;
47
48struct _Ethumbd_Child
49{
50 Ecore_Fd_Handler *fd_handler;
51 Ethumb *ethumbt[NETHUMBS];
52};
53
54
55int
56_ec_read_safe(int fd, void *buf, ssize_t size)
57{
58 ssize_t todo;
59 char *p;
60
61 todo = size;
62 p = buf;
63
64 while (todo > 0)
65 {
66 ssize_t r;
67
68 r = read(fd, p, todo);
69 if (r > 0)
70 {
71 todo -= r;
72 p += r;
73 }
74 else if (r == 0)
75 return 0;
76 else
77 {
78 if (errno == EINTR || errno == EAGAIN)
79 continue;
80 else
81 {
82 ERR("could not read from fd %d: %s",
83 fd, strerror(errno));
84 return 0;
85 }
86 }
87 }
88
89 return 1;
90}
91
92int
93_ec_write_safe(int fd, const void *buf, ssize_t size)
94{
95 ssize_t todo;
96 const char *p;
97
98 todo = size;
99 p = buf;
100
101 while (todo > 0)
102 {
103 ssize_t r;
104
105 r = write(fd, p, todo);
106 if (r > 0)
107 {
108 todo -= r;
109 p += r;
110 }
111 else if (r == 0)
112 return 0;
113 else
114 {
115 if (errno == EINTR || errno == EAGAIN)
116 continue;
117 else
118 {
119 ERR("could not write to fd %d: %s", fd, strerror(errno));
120 return 0;
121 }
122 }
123 }
124
125 return 1;
126}
127
128static int
129_ec_pipe_str_read(struct _Ethumbd_Child *ec EINA_UNUSED, char **str)
130{
131 int size;
132 int r;
133 char buf[PATH_MAX];
134
135 r = _ec_read_safe(STDIN_FILENO, &size, sizeof(size));
136 if (!r)
137 {
138 *str = NULL;
139 return 0;
140 }
141
142 if (!size)
143 {
144 *str = NULL;
145 return 1;
146 }
147
148 r = _ec_read_safe(STDIN_FILENO, buf, size);
149 if (!r)
150 {
151 *str = NULL;
152 return 0;
153 }
154
155 *str = strdup(buf);
156 return 1;
157}
158
159static struct _Ethumbd_Child *
160_ec_new(void)
161{
162 struct _Ethumbd_Child *ec = calloc(1, sizeof(*ec));
163
164 return ec;
165}
166
167static void
168_ec_free(struct _Ethumbd_Child *ec)
169{
170 int i;
171
172 if (ec->fd_handler)
173 ecore_main_fd_handler_del(ec->fd_handler);
174
175 for (i = 0; i < NETHUMBS; i++)
176 {
177 if (ec->ethumbt[i])
178 ethumb_free(ec->ethumbt[i]);
179 }
180
181 free(ec);
182}
183
184static int
185_ec_op_new(struct _Ethumbd_Child *ec)
186{
187 int r;
188 int idx;
189
190 r = _ec_read_safe(STDIN_FILENO, &idx, sizeof(idx));
191 if (!r)
192 return 0;
193
194 DBG("ethumbd new(). idx = %d", idx);
195
196 ec->ethumbt[idx] = ethumb_new();
197 return 1;
198}
199
200static int
201_ec_op_del(struct _Ethumbd_Child *ec)
202{
203 int r;
204 int idx;
205
206 r = _ec_read_safe(STDIN_FILENO, &idx, sizeof(idx));
207 if (!r)
208 return 0;
209
210 DBG("ethumbd del(). idx = %d", idx);
211
212 ethumb_free(ec->ethumbt[idx]);
213 ec->ethumbt[idx] = NULL;
214 return 1;
215}
216
217static void
218_ec_op_generated_cb(void *data EINA_UNUSED, Ethumb *e, Eina_Bool success)
219{
220 const char *thumb_path, *thumb_key;
221 int size_path, size_key, size_cmd;
222
223 DBG("thumb generated (%i)!", success);
224 ethumb_thumb_path_get(e, &thumb_path, &thumb_key);
225
226 if (!thumb_path)
227 size_path = 0;
228 else
229 size_path = strlen(thumb_path) + 1;
230
231 if (!thumb_key)
232 size_key = 0;
233 else
234 size_key = strlen(thumb_key) + 1;
235
236 size_cmd = sizeof(success) + sizeof(size_path) + size_path +
237 sizeof(size_key) + size_key;
238
239 _ec_write_safe(STDOUT_FILENO, &size_cmd, sizeof(size_cmd));
240 _ec_write_safe(STDOUT_FILENO, &success, sizeof(success));
241
242 _ec_write_safe(STDOUT_FILENO, &size_path, sizeof(size_path));
243 _ec_write_safe(STDOUT_FILENO, thumb_path, size_path);
244
245 _ec_write_safe(STDOUT_FILENO, &size_key, sizeof(size_key));
246 _ec_write_safe(STDOUT_FILENO, thumb_key, size_key);
247}
248
249static int
250_ec_op_generate(struct _Ethumbd_Child *ec)
251{
252 int idx;
253 char *path, *key, *thumb_path, *thumb_key;
254 int r;
255
256 r = _ec_read_safe(STDIN_FILENO, &idx, sizeof(idx));
257 if (!r)
258 return 0;
259
260 r = _ec_pipe_str_read(ec, &path);
261 if (!r)
262 return 0;
263 r = _ec_pipe_str_read(ec, &key);
264 if (!r)
265 return 0;
266 r = _ec_pipe_str_read(ec, &thumb_path);
267 if (!r)
268 return 0;
269 r = _ec_pipe_str_read(ec, &thumb_key);
270 if (!r)
271 return 0;
272
273 ethumb_file_set(ec->ethumbt[idx], path, key);
274 ethumb_thumb_path_set(ec->ethumbt[idx], thumb_path, thumb_key);
275
276 if (ethumb_exists(ec->ethumbt[idx]))
277 {
278 _ec_op_generated_cb(ec, ec->ethumbt[idx], EINA_TRUE);
279 }
280 else
281 {
282 ethumb_generate(ec->ethumbt[idx], _ec_op_generated_cb, ec, NULL);
283 }
284
285 free(path);
286 free(key);
287 free(thumb_path);
288 free(thumb_key);
289
290 return 1;
291}
292
293static int
294_ec_fdo_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
295{
296 int r;
297 int value;
298
299 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
300 if (!r)
301 return 0;
302 ethumb_thumb_fdo_set(e, value);
303 DBG("fdo = %d", value);
304
305 return 1;
306}
307
308static int
309_ec_size_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
310{
311 int r;
312 int w, h;
313 int type;
314
315 r = _ec_read_safe(STDIN_FILENO, &w, sizeof(w));
316 if (!r)
317 return 0;
318 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
319 if (!r)
320 return 0;
321 r = _ec_read_safe(STDIN_FILENO, &h, sizeof(h));
322 if (!r)
323 return 0;
324 ethumb_thumb_size_set(e, w, h);
325 DBG("size = %dx%d", w, h);
326
327 return 1;
328}
329
330static int
331_ec_format_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
332{
333 int r;
334 int value;
335
336 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
337 if (!r)
338 return 0;
339 ethumb_thumb_format_set(e, value);
340 DBG("format = %d", value);
341
342 return 1;
343}
344
345static int
346_ec_aspect_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
347{
348 int r;
349 int value;
350
351 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
352 if (!r)
353 return 0;
354 ethumb_thumb_aspect_set(e, value);
355 DBG("aspect = %d", value);
356
357 return 1;
358}
359
360static int
361_ec_orientation_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
362{
363 int r;
364 int value;
365
366 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
367 if (!r)
368 return 0;
369 ethumb_thumb_orientation_set(e, value);
370 DBG("orientation = %d", value);
371
372 return 1;
373}
374
375static int
376_ec_crop_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
377{
378 int r;
379 float x, y;
380 int type;
381
382 r = _ec_read_safe(STDIN_FILENO, &x, sizeof(x));
383 if (!r)
384 return 0;
385 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
386 if (!r)
387 return 0;
388 r = _ec_read_safe(STDIN_FILENO, &y, sizeof(y));
389 if (!r)
390 return 0;
391 ethumb_thumb_crop_align_set(e, x, y);
392 DBG("crop = %fx%f", x, y);
393
394 return 1;
395}
396
397static int
398_ec_quality_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
399{
400 int r;
401 int value;
402
403 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
404 if (!r)
405 return 0;
406 ethumb_thumb_quality_set(e, value);
407 DBG("quality = %d", value);
408
409 return 1;
410}
411
412static int
413_ec_compress_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
414{
415 int r;
416 int value;
417
418 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
419 if (!r)
420 return 0;
421 ethumb_thumb_compress_set(e, value);
422 DBG("compress = %d", value);
423
424 return 1;
425}
426
427static int
428_ec_frame_set(struct _Ethumbd_Child *ec, Ethumb *e)
429{
430 int r;
431 int type;
432 char *theme_file, *group, *swallow;
433
434 r = _ec_pipe_str_read(ec, &theme_file);
435 if (!r)
436 return 0;
437 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
438 if (!r)
439 return 0;
440 r = _ec_pipe_str_read(ec, &group);
441 if (!r)
442 return 0;
443 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
444 if (!r)
445 return 0;
446 r = _ec_pipe_str_read(ec, &swallow);
447 if (!r)
448 return 0;
449 DBG("frame = %s:%s:%s", theme_file, group, swallow);
450 ethumb_frame_set(e, theme_file, group, swallow);
451 free(theme_file);
452 free(group);
453 free(swallow);
454
455 return 1;
456}
457
458static int
459_ec_directory_set(struct _Ethumbd_Child *ec, Ethumb *e)
460{
461 int r;
462 char *directory;
463
464 r = _ec_pipe_str_read(ec, &directory);
465 if (!r)
466 return 0;
467 ethumb_thumb_dir_path_set(e, directory);
468 DBG("directory = %s", directory);
469 free(directory);
470
471 return 1;
472}
473
474static int
475_ec_category_set(struct _Ethumbd_Child *ec, Ethumb *e)
476{
477 int r;
478 char *category;
479
480 r = _ec_pipe_str_read(ec, &category);
481 if (!r)
482 return 0;
483 ethumb_thumb_category_set(e, category);
484 DBG("category = %s", category);
485 free(category);
486
487 return 1;
488}
489
490static int
491_ec_video_time_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
492{
493 int r;
494 float value;
495
496 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
497 if (!r)
498 return 0;
499 ethumb_video_time_set(e, value);
500 DBG("video_time = %f", value);
501
502 return 1;
503}
504
505static int
506_ec_video_start_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
507{
508 int r;
509 float value;
510
511 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
512 if (!r)
513 return 0;
514 ethumb_video_start_set(e, value);
515 DBG("video_start = %f", value);
516
517 return 1;
518}
519
520static int
521_ec_video_interval_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
522{
523 int r;
524 float value;
525
526 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
527 if (!r)
528 return 0;
529 ethumb_video_interval_set(e, value);
530 DBG("video_interval = %f", value);
531
532 return 1;
533}
534
535static int
536_ec_video_ntimes_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
537{
538 int r;
539 int value;
540
541 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
542 if (!r)
543 return 0;
544 ethumb_video_ntimes_set(e, value);
545 DBG("video_ntimes = %d", value);
546
547 return 1;
548}
549
550static int
551_ec_video_fps_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
552{
553 int r;
554 int value;
555
556 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
557 if (!r)
558 return 0;
559 ethumb_video_fps_set(e, value);
560 DBG("video_fps = %d", value);
561
562 return 1;
563}
564
565static int
566_ec_document_page_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
567{
568 int r;
569 int value;
570
571 r = _ec_read_safe(STDIN_FILENO, &value, sizeof(value));
572 if (!r)
573 return 0;
574 ethumb_document_page_set(e, value);
575 DBG("document_page = %d", value);
576
577 return 1;
578}
579
580static void
581_ec_setup_process(struct _Ethumbd_Child *ec, int idx, int type)
582{
583 Ethumb *e;
584
585 e = ec->ethumbt[idx];
586
587 switch (type)
588 {
589 case ETHUMBD_FDO:
590 _ec_fdo_set(ec, e);
591 break;
592 case ETHUMBD_SIZE_W:
593 _ec_size_set(ec, e);
594 break;
595 case ETHUMBD_FORMAT:
596 _ec_format_set(ec, e);
597 break;
598 case ETHUMBD_ASPECT:
599 _ec_aspect_set(ec, e);
600 break;
601 case ETHUMBD_ORIENTATION:
602 _ec_orientation_set(ec, e);
603 break;
604 case ETHUMBD_CROP_X:
605 _ec_crop_set(ec, e);
606 break;
607 case ETHUMBD_QUALITY:
608 _ec_quality_set(ec, e);
609 break;
610 case ETHUMBD_COMPRESS:
611 _ec_compress_set(ec, e);
612 break;
613 case ETHUMBD_FRAME_FILE:
614 _ec_frame_set(ec, e);
615 break;
616 case ETHUMBD_DIRECTORY:
617 _ec_directory_set(ec, e);
618 break;
619 case ETHUMBD_CATEGORY:
620 _ec_category_set(ec, e);
621 break;
622 case ETHUMBD_VIDEO_TIME:
623 _ec_video_time_set(ec, e);
624 break;
625 case ETHUMBD_VIDEO_START:
626 _ec_video_start_set(ec, e);
627 break;
628 case ETHUMBD_VIDEO_INTERVAL:
629 _ec_video_interval_set(ec, e);
630 break;
631 case ETHUMBD_VIDEO_NTIMES:
632 _ec_video_ntimes_set(ec, e);
633 break;
634 case ETHUMBD_VIDEO_FPS:
635 _ec_video_fps_set(ec, e);
636 break;
637 case ETHUMBD_DOCUMENT_PAGE:
638 _ec_document_page_set(ec, e);
639 break;
640 default:
641 ERR("wrong type!");
642 }
643}
644
645static int
646_ec_op_setup(struct _Ethumbd_Child *ec)
647{
648 int r;
649 int idx;
650 int type;
651
652 r = _ec_read_safe(STDIN_FILENO, &idx, sizeof(idx));
653 if (!r)
654 return 0;
655
656 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
657 if (!r)
658 return 0;
659 while (type != ETHUMBD_SETUP_FINISHED)
660 {
661 _ec_setup_process(ec, idx, type);
662 r = _ec_read_safe(STDIN_FILENO, &type, sizeof(type));
663 if (!r)
664 return 0;
665 }
666
667 return 1;
668}
669
670static Eina_Bool
671_ec_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
672{
673 struct _Ethumbd_Child *ec = data;
674 int op_id;
675 int r;
676
677 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
678 {
679 ERR("error on pipein! child exiting...");
680 ec->fd_handler = NULL;
681 ecore_main_loop_quit();
682 return 0;
683 }
684
685 r = _ec_read_safe(STDIN_FILENO, &op_id, sizeof(op_id));
686 if (!r)
687 {
688 DBG("ethumbd exited! child exiting...");
689 ec->fd_handler = NULL;
690 ecore_main_loop_quit();
691 return 0;
692 }
693
694 DBG("received op: %d", op_id);
695
696 switch (op_id)
697 {
698 case ETHUMBD_OP_NEW:
699 r = _ec_op_new(ec);
700 break;
701 case ETHUMBD_OP_GENERATE:
702 r = _ec_op_generate(ec);
703 break;
704 case ETHUMBD_OP_SETUP:
705 r = _ec_op_setup(ec);
706 break;
707 case ETHUMBD_OP_DEL:
708 r = _ec_op_del(ec);
709 break;
710 default:
711 ERR("invalid operation: %d", op_id);
712 r = 0;
713 }
714
715 if (!r)
716 {
717 ERR("ethumbd exited! child exiting...");
718 ec->fd_handler = NULL;
719 ecore_main_loop_quit();
720 }
721
722 return r;
723}
724
725static void
726_ec_setup(struct _Ethumbd_Child *ec)
727{
728 ec->fd_handler = ecore_main_fd_handler_add(
729 STDIN_FILENO, ECORE_FD_READ | ECORE_FD_ERROR,
730 _ec_fd_handler, ec, NULL, NULL);
731}
732
733int
734main(int argc EINA_UNUSED, const char *argv[] EINA_UNUSED)
735{
736 struct _Ethumbd_Child *ec;
737
738 ethumb_init();
739
740 if (_log_domain < 0)
741 {
742 _log_domain = eina_log_domain_register("ethumbd_child", NULL);
743
744 if (_log_domain < 0)
745 {
746 EINA_LOG_CRIT("could not register log domain 'ethumbd_child'");
747 ethumb_shutdown();
748 return 1;
749 }
750 }
751
752 ec = _ec_new();
753
754 _ec_setup(ec);
755
756 DBG("child started!");
757 ecore_main_loop_begin();
758 DBG("child finishing.");
759
760 _ec_free(ec);
761
762 if (_log_domain >= 0)
763 {
764 eina_log_domain_unregister(_log_domain);
765 _log_domain = -1;
766 }
767 ethumb_shutdown();
768
769 return 0;
770}