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