summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-12 01:15:45 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2013-01-12 01:15:45 +0000
commit34f53151414bcdf44ec81e582b007f74da595694 (patch)
tree863058f0d94e9d39998774a375aa6d242d8714a4 /src
parentae51833bac7ba5f72bd40a96beb13081c8d573f6 (diff)
merge ethumb.
This one was a painful bitch. The edbus2 port was quite broken, mainly leaking eina_stringshare and also not adding the '\0' to the strings that are represented as bytearray (paths cannot be utf8 to avoid translations). Emotion plugin was also quite bogus and the video thumbnail as edje (animated) is not working yet due bug in Edje_Edit api -- someone needs to investigate this, seems strange. Emotion plugin also had a bug that it was deleting the object from inside object callback. Now it seems to work. Please report if it does not. SVN revision: 82675
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile_Ethumb.am171
-rw-r--r--src/bin/ethumb/ethumb.c281
-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
-rw-r--r--src/lib/edje/edje_edit.c3
-rw-r--r--src/lib/ethumb/Ethumb.h279
-rw-r--r--src/lib/ethumb/Ethumb_Plugin.h27
-rw-r--r--src/lib/ethumb/client/Ethumb_Client.h220
-rw-r--r--src/lib/ethumb/client/ethumb_client.c2251
-rw-r--r--src/lib/ethumb/ethumb.c1863
-rw-r--r--src/lib/ethumb/ethumb_private.h57
-rw-r--r--src/lib/ethumb/md5.c251
-rw-r--r--src/lib/ethumb/md5.h24
-rw-r--r--src/modules/ethumb/emotion/emotion.c484
-rw-r--r--src/modules/ethumb/emotion/placeholder.pngbin0 -> 150 bytes
-rw-r--r--src/modules/ethumb/emotion/template.edc45
-rw-r--r--src/tests/ethumb/ethumb_dbus.c124
20 files changed, 9024 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e22f4c004c..5ad8b9770c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,7 @@ include Makefile_Eeze.am
43include Makefile_EPhysics.am 43include Makefile_EPhysics.am
44include Makefile_Edje.am 44include Makefile_Edje.am
45include Makefile_Emotion.am 45include Makefile_Emotion.am
46include Makefile_Ethumb.am
46 47
47.PHONY: benchmark examples 48.PHONY: benchmark examples
48 49
diff --git a/src/Makefile_Ethumb.am b/src/Makefile_Ethumb.am
new file mode 100644
index 0000000000..3b0e15daae
--- /dev/null
+++ b/src/Makefile_Ethumb.am
@@ -0,0 +1,171 @@
1### Library
2
3lib_LTLIBRARIES += \
4lib/ethumb/libethumb.la \
5lib/ethumb/client/libethumb_client.la
6
7ETHUMB_COMMON_CPPFLAGS = \
8-I$(top_srcdir)/src/lib/eina \
9-I$(top_builddir)/src/lib/eina \
10-I$(top_srcdir)/src/lib/eo \
11-I$(top_builddir)/src/lib/eo \
12-I$(top_srcdir)/src/lib/ecore \
13-I$(top_builddir)/src/lib/ecore \
14-I$(top_srcdir)/src/lib/ecore_evas \
15-I$(top_builddir)/src/lib/ecore_evas \
16-I$(top_srcdir)/src/lib/ecore_file \
17-I$(top_builddir)/src/lib/ecore_file \
18-I$(top_srcdir)/src/lib/evas \
19-I$(top_builddir)/src/lib/evas \
20-I$(top_srcdir)/src/lib/edje \
21-I$(top_builddir)/src/lib/edje \
22-I$(top_srcdir)/src/lib/ethumb \
23-I$(top_builddir)/src/lib/ethumb \
24@EFL_COV_CFLAGS@ \
25@ETHUMB_CFLAGS@ \
26@USE_EVIL_CFLAGS@
27
28ETHUMB_COMMON_LDADD = \
29lib/eina/libeina.la \
30lib/eo/libeo.la \
31lib/ecore/libecore.la \
32lib/ecore_evas/libecore_evas.la \
33lib/ecore_file/libecore_file.la \
34lib/evas/libevas.la \
35lib/edje/libedje.la \
36@EFL_COV_LIBS@ \
37@USE_EVIL_LIBS@
38
39installed_ethumbmainheadersdir = $(includedir)/ethumb-@VMAJ@
40dist_installed_ethumbmainheaders_DATA = \
41lib/ethumb/Ethumb.h \
42lib/ethumb/client/Ethumb_Client.h
43
44# libethumb.la
45lib_ethumb_libethumb_la_SOURCES = \
46lib/ethumb/Ethumb_Plugin.h \
47lib/ethumb/ethumb_private.h \
48lib/ethumb/md5.h \
49lib/ethumb/ethumb.c \
50lib/ethumb/md5.c
51
52ETHUMB_COMMON_LIBADD = $(ETHUMB_COMMON_LDADD) @ETHUMB_LIBS@
53ETHUMB_COMMON_LDADD += @ETHUMB_LDFLAGS@
54ETHUMB_COMMON_USER_LIBADD = $(ETHUMB_COMMON_LIBADD) lib/ethumb/libethumb.la
55ETHUMB_COMMON_USER_LDADD = $(ETHUMB_COMMON_LDADD) lib/ethumb/libethumb.la
56
57lib_ethumb_libethumb_la_CPPFLAGS = \
58$(ETHUMB_COMMON_CPPFLAGS) \
59-DPACKAGE_BIN_DIR=\"$(bindir)\" \
60-DPACKAGE_LIB_DIR=\"$(libdir)\" \
61-DPACKAGE_DATA_DIR=\"$(datadir)/ethumb\" \
62-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
63-DEFL_ETHUMB_BUILD
64
65lib_ethumb_libethumb_la_LIBADD = $(ETHUMB_COMMON_LIBADD)
66lib_ethumb_libethumb_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
67
68
69# libethumb_client.la
70lib_ethumb_client_libethumb_client_la_SOURCES = \
71lib/ethumb/client/ethumb_client.c
72
73lib_ethumb_client_libethumb_client_la_CPPFLAGS = \
74$(ETHUMB_COMMON_CPPFLAGS) \
75-I$(top_srcdir)/src/lib/edbus \
76-I$(top_builddir)/src/lib/edbus \
77-I$(top_srcdir)/src/lib/ethumb/client \
78-I$(top_builddir)/src/lib/ethumb/client \
79-DEFL_ETHUMB_BUILD
80
81lib_ethumb_client_libethumb_client_la_LIBADD = \
82$(ETHUMB_COMMON_USER_LIBADD) \
83lib/edbus/libedbus2.la
84lib_ethumb_client_libethumb_client_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
85
86## Modules
87
88# Emotion
89ethumbmoduleemotiondir = $(libdir)/ethumb/modules/emotion/$(MODULE_ARCH)
90ethumbmoduleemotion_LTLIBRARIES = modules/ethumb/emotion/module.la
91modules_ethumb_emotion_module_la_SOURCES = \
92modules/ethumb/emotion/emotion.c
93modules_ethumb_emotion_module_la_CPPFLAGS = \
94$(ETHUMB_COMMON_CPPFLAGS) \
95-I$(top_srcdir)/src/lib/eet \
96-I$(top_builddir)/src/lib/eet \
97-I$(top_srcdir)/src/lib/emotion \
98-I$(top_builddir)/src/lib/emotion \
99-DPACKAGE_BIN_DIR=\"$(bindir)\" \
100-DPACKAGE_LIB_DIR=\"$(libdir)\" \
101-DPACKAGE_DATA_DIR=\"$(datadir)/ethumb\" \
102-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\"
103
104modules_ethumb_emotion_module_la_LIBADD = \
105$(ETHUMB_COMMON_USER_LIBADD) \
106lib/eet/libeet.la \
107lib/emotion/libemotion.la
108
109modules_ethumb_emotion_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
110modules_ethumb_emotion_module_la_LIBTOOLFLAGS = --tag=disable-static
111
112modules/ethumb/emotion/template.edj: modules/ethumb/emotion/template.edc modules/ethumb/emotion/placeholder.png bin/edje/edje_cc
113 @$(MKDIR_P) modules/ethumb/emotion
114 $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) -id $(srcdir)/modules/ethumb/emotion $< $@
115
116ethumbmoduleemotion_DATA = modules/ethumb/emotion/template.edj
117
118EXTRA_DIST += \
119modules/ethumb/emotion/template.edc \
120modules/ethumb/emotion/placeholder.png
121
122
123### Binary
124
125bin_PROGRAMS += \
126bin/ethumb/ethumb \
127bin/ethumb/ethumbd \
128bin/ethumb/ethumbd_client
129
130ethumbinternal_bindir=$(libdir)/ethumb/utils/$(MODULE_ARCH)
131ethumbinternal_bin_PROGRAMS = \
132bin/ethumb/ethumbd_slave
133
134bin_ethumb_ethumb_SOURCES = bin/ethumb/ethumb.c
135bin_ethumb_ethumb_CPPFLAGS = $(ETHUMB_COMMON_CPPFLAGS)
136bin_ethumb_ethumb_LDADD = $(ETHUMB_COMMON_USER_LDADD)
137
138# TODO: review why ethumd (master) links to libethumb! shouldn't
139bin_ethumb_ethumbd_SOURCES = \
140bin/ethumb/ethumbd_private.h \
141bin/ethumb/ethumbd.c
142bin_ethumb_ethumbd_CPPFLAGS = \
143$(ETHUMB_COMMON_CPPFLAGS) \
144-I$(top_srcdir)/src/lib/edbus \
145-I$(top_builddir)/src/lib/edbus \
146-DPACKAGE_BIN_DIR=\"$(bindir)\" \
147-DPACKAGE_LIB_DIR=\"$(libdir)\" \
148-DPACKAGE_DATA_DIR=\"$(datadir)/ethumb\" \
149-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\"
150bin_ethumb_ethumbd_LDADD = \
151$(ETHUMB_COMMON_USER_LDADD) \
152lib/edbus/libedbus2.la
153
154bin_ethumb_ethumbd_client_SOURCES = \
155bin/ethumb/ethumbd_client.c
156bin_ethumb_ethumbd_client_CPPFLAGS = \
157$(ETHUMB_COMMON_CPPFLAGS) \
158-I$(top_srcdir)/src/lib/edbus \
159-I$(top_builddir)/src/lib/edbus \
160-I$(top_srcdir)/src/lib/ethumb/client \
161-I$(top_builddir)/src/lib/ethumb/client
162bin_ethumb_ethumbd_client_LDADD = \
163$(ETHUMB_COMMON_USER_LDADD) \
164lib/ethumb/client/libethumb_client.la \
165lib/edbus/libedbus2.la
166
167bin_ethumb_ethumbd_slave_SOURCES = \
168bin/ethumb/ethumbd_private.h \
169bin/ethumb/ethumbd_slave.c
170bin_ethumb_ethumbd_slave_CPPFLAGS = $(ETHUMB_COMMON_CPPFLAGS)
171bin_ethumb_ethumbd_slave_LDADD = $(ETHUMB_COMMON_USER_LDADD)
diff --git a/src/bin/ethumb/ethumb.c b/src/bin/ethumb/ethumb.c
new file mode 100644
index 0000000000..27d50df69e
--- /dev/null
+++ b/src/bin/ethumb/ethumb.c
@@ -0,0 +1,281 @@
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.h>
33#include <Ecore_Getopt.h>
34#include <Ethumb.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
45static unsigned char
46_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)
47{
48 struct frame *f = (struct frame *)storage->ptrp;
49 const char *tfile, *tgroup, *tswallow, *base, *sep;
50
51 base = str;
52 sep = strchr(base, ':');
53 if (!sep)
54 goto error;
55 tfile = eina_stringshare_add_length(base, sep - base);
56 base = sep + 1;
57
58 sep = strchr(base, ':');
59 if (!sep)
60 {
61 eina_stringshare_del(tfile);
62 goto error;
63 }
64 tgroup = eina_stringshare_add_length(base, sep - base);
65 base = sep + 1;
66 if (base[0] == '\0')
67 {
68 eina_stringshare_del(tfile);
69 eina_stringshare_del(tgroup);
70 goto error;
71 }
72 tswallow = eina_stringshare_add(base);
73
74 f->file = tfile;
75 f->group = tgroup;
76 f->swallow = tswallow;
77 return 1;
78
79 error:
80 fprintf(stderr,
81 "ERROR: invalid theme, not in format "
82 "'file:group:swallow_part': '%s'\n",
83 str);
84 return 0;
85}
86
87const Ecore_Getopt optdesc = {
88 "ethumb",
89 NULL,
90 PACKAGE_VERSION,
91 "(C) 2009 - ProFUSION embedded systems",
92 "LGPL v2.1 - GNU Lesser General Public License",
93 "Thumbnails generator.\n"
94 "\n"
95 "This program uses ethumb to create thumbnails from pictures. "
96 "It's an example of use and a test for ethumb.\n",
97 0,
98 {
99 ECORE_GETOPT_CALLBACK_ARGS
100 ('s', "size", "thumbnail size expected.",
101 "WxH", ecore_getopt_callback_size_parse, NULL),
102 ECORE_GETOPT_CHOICE
103 ('f', "format", "file format to save.", format_opt),
104 ECORE_GETOPT_CHOICE
105 ('a', "aspect", "original image aspect ratio.", aspect_opt),
106 ECORE_GETOPT_STORE_STR
107 ('d', "directory", "directory to save thumbnails."),
108 ECORE_GETOPT_STORE_STR
109 ('c', "category", "thumbnails category."),
110 ECORE_GETOPT_CALLBACK_ARGS
111 ('t', "theme", "path to theme file, group and swallow part.",
112 "file:group:swallow_part", _ethumb_getopt_callback_frame_parse, NULL),
113 ECORE_GETOPT_STORE_STR
114 ('k', "key", "key inside eet file to read image from."),
115 ECORE_GETOPT_STORE_DOUBLE
116 ('v', "video_time", "time of video frame to use as thumbnail."),
117 ECORE_GETOPT_STORE_INT
118 ('p', "document_page", "document page to use as thumbnail."),
119 ECORE_GETOPT_LICENSE('L', "license"),
120 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
121 ECORE_GETOPT_VERSION('V', "version"),
122 ECORE_GETOPT_HELP('h', "help"),
123 ECORE_GETOPT_SENTINEL
124 }
125};
126
127static void
128_thumb_report(const char *mode, Ethumb *e)
129{
130 const char *ap, *ak, *gp, *gk;
131 ethumb_file_get(e, &ap, &ak);
132 ethumb_thumb_path_get(e, &gp, &gk);
133 printf("%s '%s' '%s' => '%s' '%s'\n",
134 mode, ap, ak ? ak : "", gp, gk ? gk : "");
135}
136
137static void
138_finished_thumb( void *data EINA_UNUSED, Ethumb *e, Eina_Bool success)
139{
140 const char *mode = success ? "GENERATED" : "FAILED";
141 _thumb_report(mode, e);
142 ecore_main_loop_quit();
143}
144
145int
146main(int argc, char *argv[])
147{
148 Ethumb *e;
149 Eina_Bool quit_option = 0;
150 Eina_Rectangle geometry = {-1, -1, -1, -1};
151 unsigned int format = 0, aspect = 0;
152 char *format_str = NULL;
153 char *aspect_str = NULL;
154 char *directory = NULL;
155 char *category = NULL;
156 char *src_key = NULL;
157 struct frame frame = {NULL, NULL, NULL};
158 const char *thumb_path = NULL;
159 const char *thumb_key = NULL;
160 double video_time = 0;
161 int page = 0;
162 int arg_index;
163 int i;
164
165 int r = 1;
166
167 ethumb_init();
168 ecore_init();
169
170 Ecore_Getopt_Value values[] = {
171 ECORE_GETOPT_VALUE_PTR_CAST(geometry),
172 ECORE_GETOPT_VALUE_PTR_CAST(format_str),
173 ECORE_GETOPT_VALUE_PTR_CAST(aspect_str),
174 ECORE_GETOPT_VALUE_STR(directory),
175 ECORE_GETOPT_VALUE_STR(category),
176 ECORE_GETOPT_VALUE_PTR_CAST(frame),
177 ECORE_GETOPT_VALUE_STR(src_key),
178 ECORE_GETOPT_VALUE_DOUBLE(video_time),
179 ECORE_GETOPT_VALUE_INT(page),
180 ECORE_GETOPT_VALUE_BOOL(quit_option),
181 ECORE_GETOPT_VALUE_BOOL(quit_option),
182 ECORE_GETOPT_VALUE_BOOL(quit_option),
183 ECORE_GETOPT_VALUE_BOOL(quit_option),
184 ECORE_GETOPT_VALUE_NONE
185 };
186
187 arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
188 if (arg_index < 0)
189 {
190 fprintf(stderr, "Could not parse arguments.\n");
191 if (frame.file)
192 {
193 eina_stringshare_del(frame.file);
194 eina_stringshare_del(frame.group);
195 eina_stringshare_del(frame.swallow);
196 }
197 ecore_shutdown();
198 ethumb_shutdown();
199 return -1;
200 }
201
202 if (quit_option)
203 {
204 if (frame.file)
205 {
206 eina_stringshare_del(frame.file);
207 eina_stringshare_del(frame.group);
208 eina_stringshare_del(frame.swallow);
209 }
210 ecore_shutdown();
211 ethumb_shutdown();
212 return 0;
213 }
214
215 for (i = 0; i < 3; i++)
216 if (format_opt[i] == format_str)
217 {
218 format = i;
219 break;
220 }
221
222 for (i = 0; i < 3; i++)
223 if (aspect_opt[i] == aspect_str)
224 {
225 aspect = i;
226 break;
227 }
228
229 e = ethumb_new();
230
231 ethumb_thumb_format_set(e, format);
232 ethumb_thumb_aspect_set(e, aspect);
233 if (directory) ethumb_thumb_dir_path_set(e, directory);
234 if (category) ethumb_thumb_category_set(e, category);
235 if (geometry.w > 0 && geometry.h > 0)
236 ethumb_thumb_size_set(e, geometry.w, geometry.h);
237 if (frame.file)
238 {
239 ethumb_frame_set(e, frame.file, frame.group, frame.swallow);
240 eina_stringshare_del(frame.file);
241 eina_stringshare_del(frame.group);
242 eina_stringshare_del(frame.swallow);
243 }
244 if (video_time > 0)
245 ethumb_video_time_set(e, video_time);
246 if (page > 0)
247 ethumb_document_page_set(e, page);
248
249 if (r && arg_index < argc)
250 r = ethumb_file_set(e, argv[arg_index++], src_key);
251 else
252 r = 0;
253 if (r && arg_index < argc)
254 thumb_path = argv[arg_index++];
255 if (r && arg_index < argc)
256 thumb_key = argv[arg_index];
257
258 if (r)
259 {
260 ethumb_thumb_path_set(e, thumb_path, thumb_key);
261 if (ethumb_exists(e))
262 {
263 _thumb_report("EXISTS", e);
264 quit_option = 1;
265 r = 1;
266 }
267 else
268 r = ethumb_generate(e, _finished_thumb, NULL, NULL);
269 }
270
271 if (r && !quit_option)
272 ecore_main_loop_begin();
273
274 ethumb_file_free(e);
275 ethumb_free(e);
276
277 ecore_shutdown();
278 ethumb_shutdown();
279
280 return !r;
281}
diff --git a/src/bin/ethumb/ethumbd.c b/src/bin/ethumb/ethumbd.c
new file mode 100644
index 0000000000..f0f0d9b44a
--- /dev/null
+++ b/src/bin/ethumb/ethumbd.c
@@ -0,0 +1,1803 @@
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
new file mode 100644
index 0000000000..e81fc2e9a7
--- /dev/null
+++ b/src/bin/ethumb/ethumbd_client.c
@@ -0,0 +1,330 @@
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
new file mode 100644
index 0000000000..688eaddd6b
--- /dev/null
+++ b/src/bin/ethumb/ethumbd_private.h
@@ -0,0 +1,41 @@
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
new file mode 100644
index 0000000000..b1d319a305
--- /dev/null
+++ b/src/bin/ethumb/ethumbd_slave.c
@@ -0,0 +1,770 @@
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}
diff --git a/src/lib/edje/edje_edit.c b/src/lib/edje/edje_edit.c
index dea54665f5..9361f23929 100644
--- a/src/lib/edje/edje_edit.c
+++ b/src/lib/edje/edje_edit.c
@@ -4749,7 +4749,8 @@ edje_edit_image_data_add(Evas_Object *obj, const char *name, int id)
4749 if ((unsigned int) id >= ed->file->image_dir->entries_count) return EINA_FALSE; 4749 if ((unsigned int) id >= ed->file->image_dir->entries_count) return EINA_FALSE;
4750 4750
4751 de = ed->file->image_dir->entries + id; 4751 de = ed->file->image_dir->entries + id;
4752 eina_stringshare_replace(&de->entry, name); 4752 _edje_if_string_free(ed, de->entry);
4753 de->entry = eina_stringshare_add(name);
4753 de->source_type = 1; 4754 de->source_type = 1;
4754 de->source_param = 1; 4755 de->source_param = 1;
4755 4756
diff --git a/src/lib/ethumb/Ethumb.h b/src/lib/ethumb/Ethumb.h
new file mode 100644
index 0000000000..fd4dff708a
--- /dev/null
+++ b/src/lib/ethumb/Ethumb.h
@@ -0,0 +1,279 @@
1#ifndef __ETHUMB_H__
2#define __ETHUMB_H__ 1
3
4#include <Eina.h>
5
6#ifdef EAPI
7# undef EAPI
8#endif
9
10#ifdef _WIN32
11# ifdef EFL_ETHUMB_BUILD
12# ifdef DLL_EXPORT
13# define EAPI __declspec(dllexport)
14# else
15# define EAPI
16# endif /* ! DLL_EXPORT */
17# else
18# define EAPI __declspec(dllimport)
19# endif /* ! EFL_ETHUMB_BUILD */
20#else
21# ifdef __GNUC__
22# if __GNUC__ >= 4
23# define EAPI __attribute__ ((visibility("default")))
24# else
25# define EAPI
26# endif
27# else
28# define EAPI
29# endif
30#endif /* ! _WIN32 */
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36#define ETHUMB_VERSION_MAJOR 1
37#define ETHUMB_VERSION_MINOR 8
38
39 typedef struct _Ethumb_Version
40 {
41 int major;
42 int minor;
43 int micro;
44 int revision;
45 } Ethumb_Version;
46
47 EAPI extern Ethumb_Version *ethumb_version;
48
49/**
50 * @page ethumb_main Ethumb
51 *
52 * @date 2009 (created)
53 *
54 * @section toc Table of Contents
55 *
56 * @li @ref ethumb_main_intro
57 * @li @ref ethumb_main_compiling
58 * @li @ref ethumb_main_next_steps
59 *
60 * @section ethumb_main_intro Introduction
61 *
62 * Ethumb will use @ref Evas to generate thumbnail images of given
63 * files. The API allows great customization of the generated files
64 * and also helps compling to FreeDesktop.Org Thumbnail Specification
65 * (http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html)
66 *
67 * However, thumbnailing can be an expensive process that will impact
68 * your application experience, blocking animations and user
69 * interaction during the generation. Another problem is that one
70 * should try to cache the thumbnails in a place that other
71 * applications can benefit from the file.
72 *
73 * @ref Ethumb_Client exists to solve this. It will communicate with a
74 * server using standard D-Bus protocol. The server will use @ref
75 * Ethumb itself to generate the thumbnail images and cache them using
76 * FreeDesktop.Org standard. It is recommended that most applications
77 * use @ref Ethumb_Client instead of @ref Ethumb directly.
78 *
79 * @section ethumb_main_compiling How to compile
80 *
81 * Ethumb is a library your application links to. The procedure for
82 * this is very simple. Note that usually you want the D-Bus client
83 * library. You simply have to compile your application with the
84 * appropriate compiler flags that the @c pkg-config script
85 * outputs. For example:
86 *
87 * Compiling C or C++ files into object files:
88 *
89 * @verbatim
90 gcc -c -o main.o main.c `pkg-config --cflags ethumb_client`
91 @endverbatim
92 *
93 * Linking object files into a binary executable:
94 *
95 * @verbatim
96 gcc -o my_application main.o `pkg-config --libs ethumb_client`
97 @endverbatim
98 *
99 * See @ref pkgconfig
100 *
101 * @section ethumb_main_next_steps Next Steps
102 *
103 * After you understood what Ethumb is and installed it in your system
104 * you should proceed understanding the programming interface.
105 *
106 * Recommended reading:
107 *
108 * @li @ref Ethumb_Client to generate thumbnails using a server
109 * (recommended).
110 * @li @ref Ethumb to generate thumbnails in the local process.
111 *
112 */
113
114/**
115 * @defgroup Ethumb Ethumb
116 *
117 * @{
118 */
119/**
120 * @defgroup Ethumb_Basics Ethumb Basics
121 *
122 * Functions that all users must know of to use Ethumb.
123 *
124 * @{
125 */
126
127/**
128 * @brief thumbnailer handle.
129 *
130 * The handle is returned by ethumb_new() and destroyed by ethumb_free().
131 */
132typedef struct _Ethumb Ethumb;
133
134/**
135 * @brief reports results of ethumb_generate().
136 *
137 * @param data extra context given to ethumb_generate().
138 * @param e handle of the current thumbnailer.
139 * @param success @c EINA_TRUE if generated or @c EINA_FALSE on errors.
140 */
141typedef void (*Ethumb_Generate_Cb)(void *data, Ethumb *e, Eina_Bool success);
142
143EAPI int ethumb_init(void);
144EAPI int ethumb_shutdown(void);
145
146EAPI Ethumb * ethumb_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
147EAPI void ethumb_free(Ethumb *e);
148
149/**
150 * @}
151 */
152
153/**
154 * @defgroup Ethumb_Setup Ethumb Fine Tune Setup
155 *
156 * How to fine tune thumbnail generation, setting size, aspect,
157 * frames, quality and so on.
158 *
159 * @{
160 */
161
162EAPI Eina_Bool ethumb_frame_set(Ethumb *e, const char *theme_file, const char *group, const char *swallow) EINA_ARG_NONNULL(1);
163EAPI void ethumb_frame_get(const Ethumb *e, const char **theme_file, const char **group, const char **swallow) EINA_ARG_NONNULL(1);
164
165EAPI void ethumb_thumb_dir_path_set(Ethumb *e, const char *path) EINA_ARG_NONNULL(1);
166EAPI const char *ethumb_thumb_dir_path_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
167
168EAPI void ethumb_thumb_category_set(Ethumb *e, const char *category) EINA_ARG_NONNULL(1);
169EAPI const char *ethumb_thumb_category_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
170
171EAPI void ethumb_thumb_path_set(Ethumb *e, const char *path, const char *key) EINA_ARG_NONNULL(1);
172EAPI void ethumb_thumb_path_get(Ethumb *e, const char **path, const char **key) EINA_ARG_NONNULL(1);
173EAPI void ethumb_thumb_hash(Ethumb *e) EINA_ARG_NONNULL(1);
174EAPI void ethumb_thumb_hash_copy(Ethumb *dst, const Ethumb *src) EINA_ARG_NONNULL(1, 2);
175
176typedef enum _Ethumb_Thumb_FDO_Size
177{
178 ETHUMB_THUMB_NORMAL, /**< 128x128 as defined by FreeDesktop.Org standard */
179 ETHUMB_THUMB_LARGE /**< 256x256 as defined by FreeDesktop.Org standard */
180} Ethumb_Thumb_FDO_Size;
181
182typedef enum _Ethumb_Thumb_Format
183{
184 ETHUMB_THUMB_FDO, /**< PNG as defined by FreeDesktop.Org standard */
185 ETHUMB_THUMB_JPEG, /**< JPEGs are often smaller and faster to read/write */
186 ETHUMB_THUMB_EET /**< EFL's own storage system, supports key parameter */
187} Ethumb_Thumb_Format;
188
189typedef enum _Ethumb_Thumb_Aspect
190{
191 ETHUMB_THUMB_KEEP_ASPECT, /**< keep original proportion between width and height */
192 ETHUMB_THUMB_IGNORE_ASPECT, /**< ignore aspect and foce it to match thumbnail's width and height */
193 ETHUMB_THUMB_CROP /**< keep aspect but crop (cut) the largest dimension */
194} Ethumb_Thumb_Aspect;
195
196typedef enum _Ethumb_Thumb_Orientation
197{
198 ETHUMB_THUMB_ORIENT_NONE, /**< keep orientation as pixel data is */
199 ETHUMB_THUMB_ROTATE_90_CW, /**< rotate 90° clockwise */
200 ETHUMB_THUMB_ROTATE_180, /**< rotate 180° */
201 ETHUMB_THUMB_ROTATE_90_CCW, /**< rotate 90° counter-clockwise */
202 ETHUMB_THUMB_FLIP_HORIZONTAL, /**< flip horizontally */
203 ETHUMB_THUMB_FLIP_VERTICAL, /**< flip vertically */
204 ETHUMB_THUMB_FLIP_TRANSPOSE, /**< transpose */
205 ETHUMB_THUMB_FLIP_TRANSVERSE, /**< transverse */
206 ETHUMB_THUMB_ORIENT_ORIGINAL /**< use orientation from metadata (EXIF-only currently) */
207} Ethumb_Thumb_Orientation;
208
209EAPI void ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s) EINA_ARG_NONNULL(1);
210
211EAPI void ethumb_thumb_size_set(Ethumb *e, int tw, int th) EINA_ARG_NONNULL(1);
212EAPI void ethumb_thumb_size_get(const Ethumb *e, int *tw, int *th) EINA_ARG_NONNULL(1);
213
214EAPI void ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) EINA_ARG_NONNULL(1);
215EAPI Ethumb_Thumb_Format ethumb_thumb_format_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
216
217EAPI void ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) EINA_ARG_NONNULL(1);
218EAPI Ethumb_Thumb_Aspect ethumb_thumb_aspect_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
219
220EAPI void ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o) EINA_ARG_NONNULL(1);
221EAPI Ethumb_Thumb_Orientation ethumb_thumb_orientation_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
222
223EAPI void ethumb_thumb_crop_align_set(Ethumb *e, float x, float y) EINA_ARG_NONNULL(1);
224EAPI void ethumb_thumb_crop_align_get(const Ethumb *e, float *x, float *y) EINA_ARG_NONNULL(1);
225
226EAPI void ethumb_thumb_quality_set(Ethumb *e, int quality) EINA_ARG_NONNULL(1);
227EAPI int ethumb_thumb_quality_get(const Ethumb *e) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
228
229EAPI void ethumb_thumb_compress_set(Ethumb *e, int compress) EINA_ARG_NONNULL(1);
230EAPI int ethumb_thumb_compress_get(const Ethumb *e) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
231
232EAPI void ethumb_video_start_set(Ethumb *e, float start) EINA_ARG_NONNULL(1);
233EAPI float ethumb_video_start_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
234EAPI void ethumb_video_time_set(Ethumb *e, float time) EINA_ARG_NONNULL(1);
235EAPI float ethumb_video_time_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
236EAPI void ethumb_video_interval_set(Ethumb *e, float interval) EINA_ARG_NONNULL(1);
237EAPI float ethumb_video_interval_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
238EAPI void ethumb_video_ntimes_set(Ethumb *e, unsigned int ntimes) EINA_ARG_NONNULL(1);
239EAPI unsigned int ethumb_video_ntimes_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
240EAPI void ethumb_video_fps_set(Ethumb *e, unsigned int fps) EINA_ARG_NONNULL(1);
241EAPI unsigned int ethumb_video_fps_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
242
243
244EAPI void ethumb_document_page_set(Ethumb *e, unsigned int page) EINA_ARG_NONNULL(1);
245EAPI unsigned int ethumb_document_page_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
246/**
247 * @}
248 */
249
250/**
251 * @addtogroup Ethumb_Basics Ethumb Basics
252 * @{
253 */
254EAPI Eina_Bool ethumb_file_set(Ethumb *e, const char *path, const char *key) EINA_ARG_NONNULL(1, 2);
255EAPI void ethumb_file_get(const Ethumb *e, const char **path, const char **key) EINA_ARG_NONNULL(1);
256EAPI void ethumb_file_free(Ethumb *e) EINA_ARG_NONNULL(1);
257
258EAPI Eina_Bool ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, const void *data, Eina_Free_Cb free_data) EINA_ARG_NONNULL(1, 2);
259EAPI Eina_Bool ethumb_exists(Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
260
261EAPI Ethumb *ethumb_dup(const Ethumb *e) EINA_ARG_NONNULL(1);
262EAPI Eina_Bool ethumb_cmp(const Ethumb *e1, const Ethumb *e2) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
263EAPI int ethumb_hash(const void *key, int key_length) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
264EAPI int ethumb_key_cmp(const void *key1, int key1_length,
265 const void *key2, int key2_length) EINA_ARG_NONNULL(1, 3) EINA_WARN_UNUSED_RESULT EINA_PURE;
266EAPI unsigned int ethumb_length(const void *key) EINA_PURE EINA_WARN_UNUSED_RESULT;
267
268 /**
269 * @}
270 */
271
272/**
273 * @}
274 */
275
276#ifdef __cplusplus
277}
278#endif
279#endif /* __ETHUMB_H__ */
diff --git a/src/lib/ethumb/Ethumb_Plugin.h b/src/lib/ethumb/Ethumb_Plugin.h
new file mode 100644
index 0000000000..3eb6f020cd
--- /dev/null
+++ b/src/lib/ethumb/Ethumb_Plugin.h
@@ -0,0 +1,27 @@
1#ifndef _ETHUMB_PLUGIN_H_
2#define _ETHUMB_PLUGIN_H_
3
4#include <Evas.h>
5#include <Ecore_Evas.h>
6#include <Ethumb.h>
7
8typedef struct _Ethumb_Plugin Ethumb_Plugin;
9
10struct _Ethumb_Plugin
11{
12 const char **extensions;
13 void *(*thumb_generate)(Ethumb *);
14 void (*thumb_cancel)(Ethumb *, void *);
15};
16
17EAPI void ethumb_calculate_aspect_from_ratio(Ethumb *e, float ia, int *w, int *h);
18EAPI void ethumb_calculate_aspect(Ethumb *e, int iw, int ih, int *w, int *h);
19EAPI void ethumb_calculate_fill_from_ratio(Ethumb *e, float ia, int *fx, int *fy, int *fw, int *fh);
20EAPI void ethumb_calculate_fill(Ethumb *e, int iw, int ih, int *fx, int *fy, int *fw, int *fh);
21EAPI Eina_Bool ethumb_plugin_image_resize(Ethumb *e, int w, int h);
22EAPI Eina_Bool ethumb_image_save(Ethumb *e);
23EAPI void ethumb_finished_callback_call(Ethumb *e, int result);
24EAPI Evas * ethumb_evas_get(const Ethumb *e);
25EAPI Ecore_Evas * ethumb_ecore_evas_get(const Ethumb *e);
26
27#endif /* _ETHUMB_PLUGIN_H_ */
diff --git a/src/lib/ethumb/client/Ethumb_Client.h b/src/lib/ethumb/client/Ethumb_Client.h
new file mode 100644
index 0000000000..3c3f95d87e
--- /dev/null
+++ b/src/lib/ethumb/client/Ethumb_Client.h
@@ -0,0 +1,220 @@
1#ifndef __ETHUMB_CLIENT_H__
2#define __ETHUMB_CLIENT_H__ 1
3
4#include <Ethumb.h>
5
6#ifdef EAPI
7# undef EAPI
8#endif
9
10#ifdef _WIN32
11# ifdef EFL_ETHUMB_CLIENT_BUILD
12# ifdef DLL_EXPORT
13# define EAPI __declspec(dllexport)
14# else
15# define EAPI
16# endif /* ! DLL_EXPORT */
17# else
18# define EAPI __declspec(dllimport)
19# endif /* ! EFL_ETHUMB_CLIENT_BUILD */
20#else
21# ifdef __GNUC__
22# if __GNUC__ >= 4
23# define EAPI __attribute__ ((visibility("default")))
24# else
25# define EAPI
26# endif
27# else
28# define EAPI
29# endif
30#endif /* ! _WIN32 */
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36/**
37 * @defgroup Ethumb_Client Ethumb Client
38 * @ingroup Ethumb
39 *
40 * @{
41 */
42
43/**
44 * @defgroup Ethumb_Client_Basics Ethumb Client Basics
45 *
46 * Functions that all users must know of to use Ethumb_Client.
47 *
48 * @{
49 */
50
51/**
52 * @brief client handle.
53 *
54 * The client handle is created by ethumb_client_connect() and
55 * destroyed by ethumb_client_disconnect(). The connection and
56 * requests are asynchronous and callbacks should be used to report
57 * both success and failure of calls.
58 */
59typedef struct _Ethumb_Client Ethumb_Client;
60
61/**
62 * @brief client exists request handle.
63 *
64 * The exists request handle is created by ethumb_client_thumb_exists(),
65 * automatically destroyed when it end and cancelled when requested by
66 * ethumb_client_thumb_exists_cancel().
67 */
68typedef struct _Ethumb_Exists Ethumb_Exists;
69
70/**
71 * @brief reports results of ethumb_client_connect()
72 *
73 * @param data extra context given to ethumb_client_connect().
74 * @param client handle of the current connection to server.
75 * @param success @c EINA_TRUE if connected or @c EINA_FALSE if it was
76 * not possible.
77 */
78typedef void (*Ethumb_Client_Connect_Cb)(void *data, Ethumb_Client *client, Eina_Bool success);
79
80/**
81 * @brief reports server connection ended.
82 *
83 * Functions of this type may be called if they are set with
84 * ethumb_client_on_server_die_callback_set().
85 *
86 * @param data extra context given to ethumb_client_on_server_die_callback_set().
87 * @param client handle of the current connection to server.
88 */
89typedef void (*Ethumb_Client_Die_Cb)(void *data, Ethumb_Client *client);
90
91/**
92 * @brief reports results of ethumb_client_generate().
93 *
94 * @param data extra context given to ethumb_client_generate().
95 * @param client handle of the current connection to server.
96 * @param id identifier returned by ethumb_client_generate().
97 * @param file path set with ethumb_client_file_set().
98 * @param key value set with ethumb_client_file_set() or @c NULL.
99 * @param thumb_path where thumbnail was stored, either set with
100 * ethumb_client_thumb_path_set() or automatically calculated
101 * using parameters.
102 * @param thumb_key key inside thumb_path where thumbnail was stored or @c NULL.
103 * @param success @c EINA_TRUE if generated or @c EINA_FALSE on errors.
104 */
105typedef void (*Ethumb_Client_Generate_Cb)(void *data, Ethumb_Client *client, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success);
106
107/**
108 * @brief report results of ethumb_client_thumb_exists().
109 *
110 * @param client handle of the current connection to server.
111 * @param exists EINA_TRUE if the thumbnail exists.
112 * @param data extra context given to ethumb_client_thumb_exists().
113 *
114 * During the execution of the callback the state of the @p client is
115 * temporarily realy restored to what it was when the call to
116 * ethumb_client_thumb_exists() was done.
117 */
118typedef void (*Ethumb_Client_Thumb_Exists_Cb)(void *data, Ethumb_Client *client, Ethumb_Exists *thread, Eina_Bool exists);
119
120/**
121 * @brief reports results of ethumb_client_generate_cancel()
122 *
123 * @param data extra context given to ethumb_client_generate_cancel()
124 * @param client handle of the current connection to server.
125 */
126typedef void (*Ethumb_Client_Generate_Cancel_Cb)(void *data, Eina_Bool success);
127
128EAPI int ethumb_client_init(void);
129EAPI int ethumb_client_shutdown(void);
130
131EAPI Ethumb_Client *ethumb_client_connect(Ethumb_Client_Connect_Cb connect_cb, const void *data, Eina_Free_Cb free_data);
132EAPI void ethumb_client_disconnect(Ethumb_Client *client);
133EAPI void ethumb_client_on_server_die_callback_set(Ethumb_Client *client, Ethumb_Client_Die_Cb server_die_cb, const void *data, Eina_Free_Cb free_data);
134
135/**
136 * @}
137 */
138
139/**
140 * @defgroup Ethumb_Client_Setup Ethumb Client Fine Tune Setup
141 *
142 * How to fine tune thumbnail generation, setting size, aspect, orientation,
143 * frames, quality and so on.
144 *
145 * @{
146 */
147
148EAPI void ethumb_client_fdo_set(Ethumb_Client *client, Ethumb_Thumb_FDO_Size s);
149EAPI void ethumb_client_size_set(Ethumb_Client *client, int tw, int th);
150EAPI void ethumb_client_size_get(const Ethumb_Client *client, int *tw, int *th);
151EAPI void ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f);
152EAPI Ethumb_Thumb_Format ethumb_client_format_get(const Ethumb_Client *client);
153EAPI void ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a);
154EAPI Ethumb_Thumb_Aspect ethumb_client_aspect_get(const Ethumb_Client *client);
155EAPI void ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o);
156EAPI Ethumb_Thumb_Orientation ethumb_client_orientation_get(const Ethumb_Client *client);
157EAPI void ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y);
158EAPI void ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y);
159EAPI void ethumb_client_quality_set(Ethumb_Client *client, int quality);
160EAPI int ethumb_client_quality_get(const Ethumb_Client *client);
161EAPI void ethumb_client_compress_set(Ethumb_Client *client, int compress);
162EAPI int ethumb_client_compress_get(const Ethumb_Client *client);
163EAPI Eina_Bool ethumb_client_frame_set(Ethumb_Client *client, const char *file, const char *group, const char *swallow);
164EAPI void ethumb_client_dir_path_set(Ethumb_Client *client, const char *path);
165EAPI const char * ethumb_client_dir_path_get(const Ethumb_Client *client);
166EAPI void ethumb_client_category_set(Ethumb_Client *client, const char *category);
167EAPI const char * ethumb_client_category_get(const Ethumb_Client *client);
168EAPI void ethumb_client_video_time_set(Ethumb_Client *client, float time);
169EAPI void ethumb_client_video_start_set(Ethumb_Client *client, float start);
170EAPI void ethumb_client_video_interval_set(Ethumb_Client *client, float interval);
171EAPI void ethumb_client_video_ntimes_set(Ethumb_Client *client, unsigned int ntimes);
172EAPI void ethumb_client_video_fps_set(Ethumb_Client *client, unsigned int fps);
173EAPI void ethumb_client_document_page_set(Ethumb_Client *client, unsigned int page);