4 * This is the client-server thumbnail library, see @ref
5 * tutorial_ethumb_client.
7 * Copyright (C) 2009 by ProFUSION embedded systems
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library;
21 * if not, see <http://www.gnu.org/licenses/>.
23 * @author Rafael Antognolli <antognolli@profusion.mobi>
24 * @author Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
28 * @page tutorial_ethumb_client Client-Server Thumbnailing Tutorial
30 * @section tutorial_ethumb_client_intro Introduction
32 * Ethumb provides both in process and client-server generation
33 * methods. The advantage of the client-server method is that current
34 * process will not do the heavy operations that may block, stopping
35 * animations and other user interactions. Instead the client library
36 * will configure a local #Ethumb instance and mirrors/controls a
37 * remote process using DBus. The simple operations like most setters
38 * and getters as well as checking for thumbnail existence
39 * (ethumb_client_thumb_exists()) is done locally, while expensive
40 * (ethumb_client_generate()) are done on server and then reported
41 * back to application when it is finished (both success or failure).
43 * @section tutorial_ethumb_client_connect Connecting to Server
47 * @section tutorial_ethumb_client_generate Requesting Thumbnail Generation
51 * @section tutorial_ethumb_client_setup Setup Extra Thumbnail Parameters
55 * @section tutorial_ethumb_client_server_died Handle Server Disconnection
75 #include <sys/types.h>
79 #include <eina_safety_checks.h>
84 #include "Ethumb_Client.h"
90 #define MAX_ID 2000000
92 static int _log_dom = -1;
93 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
94 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
95 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
96 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
97 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
104 Ethumb *old_ethumb_conf;
105 E_DBus_Connection *conn;
106 E_DBus_Signal_Handler *name_owner_changed_handler;
107 E_DBus_Signal_Handler *generated_signal;
108 DBusPendingCall *pending_get_name_owner;
109 DBusPendingCall *pending_start_service_by_name;
110 const char *unique_name;
111 DBusPendingCall *pending_new;
114 Ethumb_Client_Connect_Cb cb;
116 Eina_Free_Cb free_data;
118 Eina_List *pending_add;
119 Eina_List *pending_remove;
120 Eina_List *pending_gen;
121 DBusPendingCall *pending_clear;
122 DBusPendingCall *pending_setup;
125 Ethumb_Client_Die_Cb cb;
127 Eina_Free_Cb free_data;
129 const char *object_path;
133 Eina_Bool connected : 1;
134 Eina_Bool server_started : 1;
137 struct _ethumb_pending_add
143 const char *thumb_key;
144 Ethumb_Client_Generate_Cb generated_cb;
146 Eina_Free_Cb free_data;
147 DBusPendingCall *pending_call;
148 Ethumb_Client *client;
151 struct _ethumb_pending_remove
154 Ethumb_Client_Generate_Cancel_Cb cancel_cb;
156 Eina_Free_Cb free_data;
157 DBusPendingCall *pending_call;
158 Ethumb_Client *client;
161 struct _ethumb_pending_gen
167 const char *thumb_key;
168 Ethumb_Client_Generate_Cb generated_cb;
170 Eina_Free_Cb free_data;
173 typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists;
175 struct _Ethumb_Async_Exists
179 Ethumb *dup; /* We will work on that one to prevent race and lock */
181 Eina_List *callbacks;
182 Ecore_Thread *thread;
185 struct _Ethumb_Exists
187 Ethumb_Async_Exists *parent;
188 Ethumb_Client *client;
189 Ethumb *dup; /* We don't want to loose parameters so keep them around */
191 Ethumb_Client_Thumb_Exists_Cb exists_cb;
195 static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
196 static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
197 static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
198 static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
199 static const char fdo_interface[] = "org.freedesktop.DBus";
200 static const char fdo_bus_name[] = "org.freedesktop.DBus";
201 static const char fdo_path[] = "/org/freedesktop/DBus";
203 static int _initcount = 0;
204 static Eina_Hash *_exists_request = NULL;
206 static void _ethumb_client_generated_cb(void *data, DBusMessage *msg);
207 static void _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err);
210 __dbus_callback_check_and_init(const char *file, int line, const char *function, DBusMessage *msg, DBusMessageIter *itr, DBusError *err)
214 ERR("%s:%d:%s() callback without message arguments!",
215 file, line, function);
218 ERR("%s:%d:%s() an error was reported by server: "
219 "name=\"%s\", message=\"%s\"",
220 file, line, function, err->name, err->message);
225 if (!dbus_message_iter_init(msg, itr))
227 ERR("%s:%d:%s() could not init iterator.",
228 file, line, function);
235 #define _dbus_callback_check_and_init(msg, itr, err) \
236 __dbus_callback_check_and_init(__FILE__, __LINE__, __FUNCTION__, \
240 __dbus_iter_type_check(int type, int expected, const char *expected_name)
242 if (type == expected)
245 ERR("expected type %s (%c) but got %c instead!",
246 expected_name, expected, type);
251 #define _dbus_iter_type_check(t, e) __dbus_iter_type_check(t, e, #e)
253 #define CHECK_NULL_RETURN(ptr, ...) \
258 CRITICAL("%s == NULL!", #ptr); \
259 return __VA_ARGS__; \
265 _ethumb_client_free(Ethumb_Client *client)
269 if (!client->connected)
272 EINA_LIST_FREE(client->pending_add, data)
274 struct _ethumb_pending_add *pending = data;
275 eina_stringshare_del(pending->file);
276 eina_stringshare_del(pending->key);
277 eina_stringshare_del(pending->thumb);
278 eina_stringshare_del(pending->thumb_key);
279 dbus_pending_call_cancel(pending->pending_call);
280 dbus_pending_call_unref(pending->pending_call);
281 if (pending->free_data)
282 pending->free_data(pending->data);
286 EINA_LIST_FREE(client->pending_gen, data)
288 struct _ethumb_pending_gen *pending = data;
289 eina_stringshare_del(pending->file);
290 eina_stringshare_del(pending->key);
291 eina_stringshare_del(pending->thumb);
292 eina_stringshare_del(pending->thumb_key);
293 if (pending->free_data)
294 pending->free_data(pending->data);
298 EINA_LIST_FREE(client->pending_remove, data)
300 struct _ethumb_pending_remove *pending = data;
301 dbus_pending_call_cancel(pending->pending_call);
302 dbus_pending_call_unref(pending->pending_call);
303 if (pending->free_data)
304 pending->free_data(pending->data);
308 if (client->pending_clear)
310 dbus_pending_call_cancel(client->pending_clear);
311 dbus_pending_call_unref(client->pending_clear);
315 if (client->object_path)
316 eina_stringshare_del(client->object_path);
318 if (client->pending_new)
319 dbus_pending_call_cancel(client->pending_new);
321 if (client->unique_name)
322 eina_stringshare_del(client->unique_name);
324 if (client->pending_get_name_owner)
325 dbus_pending_call_cancel(client->pending_get_name_owner);
327 if (client->pending_start_service_by_name)
328 dbus_pending_call_cancel(client->pending_start_service_by_name);
330 if (client->old_ethumb_conf)
331 ethumb_free(client->old_ethumb_conf);
333 ethumb_free(client->ethumb);
335 e_dbus_signal_handler_del(client->conn, client->name_owner_changed_handler);
336 if (client->connected)
337 e_dbus_signal_handler_del(client->conn, client->generated_signal);
338 e_dbus_connection_close(client->conn);
340 if (client->connect.free_data)
341 client->connect.free_data(client->connect.data);
342 if (client->die.free_data)
343 client->die.free_data(client->die.data);
349 _ethumb_async_delete(void *data)
351 Ethumb_Async_Exists *async = data;
353 assert(async->callbacks == NULL);
354 assert(async->thread == NULL);
356 ethumb_free(async->dup);
357 eina_stringshare_del(async->path);
363 _ethumb_client_name_owner_changed(void *data, DBusMessage *msg)
366 const char *name, *from, *to;
367 Ethumb_Client *client = data;
369 dbus_error_init(&err);
370 if (!dbus_message_get_args(msg, &err,
371 DBUS_TYPE_STRING, &name,
372 DBUS_TYPE_STRING, &from,
373 DBUS_TYPE_STRING, &to,
376 ERR("could not get NameOwnerChanged arguments: %s: %s",
377 err.name, err.message);
378 dbus_error_free(&err);
384 if (strcmp(name, _ethumb_dbus_bus_name) != 0)
387 DBG("NameOwnerChanged from=[%s] to=[%s]", from, to);
389 if (from[0] != '\0' && to[0] == '\0')
391 DBG("exit ethumbd at %s", from);
392 if (client->unique_name && strcmp(client->unique_name, from) != 0)
393 WRN("%s was not the known name %s, ignored.",
394 from, client->unique_name);
395 else if (client->unique_name)
397 ERR("server exit!!!");
400 client->die.cb(client->die.data, client);
401 client->die.cb = NULL;
403 if (client->die.free_data)
405 client->die.free_data(client->die.data);
406 client->die.free_data = NULL;
407 client->die.data = NULL;
412 DBG("unknown change from %s to %s", from, to);
416 _ethumb_client_report_connect(Ethumb_Client *client, Eina_Bool success)
418 if (!client->connect.cb)
420 ERR("already called?!");
424 client->connect.cb(client->connect.data, client, success);
425 if (client->connect.free_data)
427 client->connect.free_data(client->connect.data);
428 client->connect.free_data = NULL;
430 client->connect.cb = NULL;
431 client->connect.data = NULL;
435 _ethumb_client_new_cb(void *data, DBusMessage *msg, DBusError *error)
437 DBusMessageIter iter;
440 Ethumb_Client *client = data;
442 client->pending_new = NULL;
444 if (!_dbus_callback_check_and_init(msg, &iter, error))
446 t = dbus_message_iter_get_arg_type(&iter);
447 if (!_dbus_iter_type_check(t, DBUS_TYPE_OBJECT_PATH))
450 dbus_message_iter_get_basic(&iter, &opath);
451 if (opath[0] == '\0')
454 client->object_path = eina_stringshare_add(opath);
456 client->generated_signal = e_dbus_signal_handler_add(
457 client->conn, _ethumb_dbus_bus_name, opath,
458 _ethumb_dbus_objects_interface, "generated",
459 _ethumb_client_generated_cb, client);
461 _ethumb_client_report_connect(client, 1);
465 _ethumb_client_report_connect(client, 0);
469 _ethumb_client_call_new(Ethumb_Client *client)
473 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name, _ethumb_dbus_path,
474 _ethumb_dbus_interface, "new");
475 client->pending_new = e_dbus_message_send(client->conn, msg,
476 _ethumb_client_new_cb, -1,
478 dbus_message_unref(msg);
482 _ethumb_client_start_server_cb(void *data, DBusMessage *msg, DBusError *err)
484 Ethumb_Client *client = data;
485 DBusMessageIter iter;
489 client->pending_start_service_by_name = NULL;
491 if (!_dbus_callback_check_and_init(msg, &iter, err))
494 t = dbus_message_iter_get_arg_type(&iter);
495 if (!_dbus_iter_type_check(t, DBUS_TYPE_UINT32))
498 dbus_message_iter_get_basic(&iter, &ret);
499 if ((ret != 1) && (ret != 2))
501 ERR("Error starting Ethumbd DBus service by its name: retcode %u",
506 client->server_started = 1;
507 DBG("Ethumbd DBus service started successfully (%d), now request its name",
510 if (client->pending_get_name_owner)
512 DBG("already requesting name owner, cancel and try again");
513 dbus_pending_call_cancel(client->pending_get_name_owner);
516 client->pending_get_name_owner = e_dbus_get_name_owner
517 (client->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
519 if (!client->pending_get_name_owner)
521 ERR("could not create a get_name_owner request.");
528 ERR("failed to start Ethumbd DBus service by its name.");
529 _ethumb_client_report_connect(client, 0);
533 _ethumb_client_start_server(Ethumb_Client *client)
535 if (client->pending_start_service_by_name)
537 DBG("already pending start service by name.");
541 client->server_started = 0;
542 client->pending_start_service_by_name = e_dbus_start_service_by_name
543 (client->conn, _ethumb_dbus_bus_name, 0, _ethumb_client_start_server_cb,
545 if (!client->pending_start_service_by_name)
547 ERR("could not start service by name!");
548 _ethumb_client_report_connect(client, 0);
553 _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err)
555 DBusMessageIter iter;
557 Ethumb_Client *client = data;
560 client->pending_get_name_owner = NULL;
562 if (dbus_error_is_set(err) && (!client->server_started))
564 DBG("could not find server (%s), try to start it...", err->message);
565 _ethumb_client_start_server(client);
569 if (!_dbus_callback_check_and_init(msg, &iter, err))
572 t = dbus_message_iter_get_arg_type(&iter);
573 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
576 dbus_message_iter_get_basic(&iter, &uid);
579 ERR("no name owner!");
583 DBG("unique name = %s", uid);
584 client->unique_name = eina_stringshare_add(uid);
586 _ethumb_client_call_new(client);
587 client->connected = 1;
591 _ethumb_client_report_connect(client, 0);
595 _ethumb_client_exists_heavy(void *data, Ecore_Thread *thread __UNUSED__)
597 Ethumb_Async_Exists *async = data;
599 ethumb_thumb_hash(async->dup);
603 _ethumb_client_exists_end(void *data, Ecore_Thread *thread __UNUSED__)
605 Ethumb_Async_Exists *async = data;
608 EINA_LIST_FREE(async->callbacks, cb)
612 ethumb_thumb_hash_copy(cb->dup, async->dup);
613 tmp = cb->client->ethumb;
614 cb->client->ethumb = cb->dup;
616 cb->exists_cb((void *)cb->data,
618 ethumb_exists(cb->client->ethumb));
620 cb->client->ethumb = tmp;
621 EINA_REFCOUNT_UNREF(cb->client)
622 _ethumb_client_free(cb->client);
623 ethumb_free(cb->dup);
627 async->thread = NULL;
629 eina_hash_del(_exists_request, async->path, async);
637 * @brief Initialize the Ethumb_Client library.
639 * @return 1 or greater on success, 0 on error.
641 * This function sets up all the Ethumb_Client module dependencies. It
642 * returns 0 on failure (that is, when one of the dependency fails to
643 * initialize), otherwise it returns the number of times it has
644 * already been called.
646 * When Ethumb_Client is not used anymore, call
647 * ethumb_client_shutdown() to shut down the Ethumb_Client library.
649 * @see ethumb_client_shutdown()
650 * @see ethumb_client_connect()
651 * @see @ref tutorial_ethumb_client
654 ethumb_client_init(void)
661 fprintf(stderr, "ERROR: Could not initialize log module.\n");
664 _log_dom = eina_log_domain_register("ethumb_client", EINA_COLOR_YELLOW);
667 EINA_LOG_ERR("Could not register log domain: ethumb_client");
675 _exists_request = eina_hash_stringshared_new(_ethumb_async_delete);
681 * @brief Shut down the Ethumb_Client library.
683 * @return 0 when everything is shut down, 1 or greater if there are
684 * other users of the Ethumb_Client library pending shutdown.
686 * This function shuts down the Ethumb_Client library. It returns 0
687 * when it has been called the same number of times than
688 * ethumb_client_init(). In that case it shut down all the
689 * Ethumb_Client modules dependencies.
691 * Once this function succeeds (that is, @c 0 is returned), you must
692 * not call any of the Eina function anymore. You must call
693 * ethumb_client_init() again to use the Ethumb_Client functions
697 ethumb_client_shutdown(void)
703 /* should find a non racy solution to closing all pending exists request */
704 eina_hash_free(_exists_request);
705 _exists_request = NULL;
709 eina_log_domain_unregister(_log_dom);
716 * Connects to Ethumb server and return the client instance.
718 * This is the "constructor" of Ethumb_Client, where everything
721 * If server was down, it is tried to start it using DBus activation,
722 * then the connection is retried.
724 * This call is asynchronous and will not block, instead it will be in
725 * "not connected" state until @a connect_cb is called with either
726 * success or failure. On failure, then no methods should be
727 * called. On success you're now able to setup and then ask generation
730 * Usually you should listen for server death/disconenction with
731 * ethumb_client_on_server_die_callback_set().
733 * @param connect_cb function to call to report connection success or
734 * failure. Do not call any other ethumb_client method until
735 * this function returns. The first received parameter is the
736 * given argument @a data. Must @b not be @c NULL. This
737 * function will not be called if user explicitly calls
738 * ethumb_client_disconnect().
739 * @param data context to give back to @a connect_cb. May be @c NULL.
740 * @param free_data function used to release @a data resources, if
741 * any. May be @c NULL. If this function exists, it will be
742 * called immediately after @a connect_cb is called or if user
743 * explicitly calls ethumb_client_disconnect() before such
744 * (that is, don't rely on @a data after @a connect_cb was
747 * @return client instance or NULL if failed. If @a connect_cb is
748 * missing it returns @c NULL. If it fail for other
749 * conditions, @c NULL is also returned and @a connect_cb is
750 * called with @c success=EINA_FALSE. The client instance is
751 * not ready to be used until @a connect_cb is called.
754 ethumb_client_connect(Ethumb_Client_Connect_Cb connect_cb, const void *data, Eina_Free_Cb free_data)
756 Ethumb_Client *eclient;
758 EINA_SAFETY_ON_NULL_RETURN_VAL(connect_cb, NULL);
760 eclient = calloc(1, sizeof(*eclient));
763 ERR("could not allocate Ethumb_Client structure.");
767 eclient->old_ethumb_conf = NULL;
768 eclient->connect.cb = connect_cb;
769 eclient->connect.data = (void *)data;
770 eclient->connect.free_data = free_data;
772 eclient->ethumb = ethumb_new();
773 if (!eclient->ethumb)
775 ERR("could not create ethumb handler.");
779 eclient->conn = e_dbus_bus_get(DBUS_BUS_SESSION);
782 ERR("could not connect to session bus.");
786 eclient->name_owner_changed_handler = e_dbus_signal_handler_add(
787 eclient->conn, fdo_bus_name, fdo_path, fdo_interface,
788 "NameOwnerChanged", _ethumb_client_name_owner_changed, eclient);
790 eclient->pending_get_name_owner = e_dbus_get_name_owner(
791 eclient->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
793 if (!eclient->pending_get_name_owner)
795 ERR("could not create a get_name_owner request.");
799 EINA_REFCOUNT_INIT(eclient);
804 ethumb_free(eclient->ethumb);
808 connect_cb((void *)data, NULL, EINA_FALSE);
810 free_data((void *)data);
815 * Disconnect the client, releasing all client resources.
817 * This is the destructor of Ethumb_Client, after it's disconnected
818 * the client handle is now gone and should not be used.
820 * @param client client instance to be destroyed. Must @b not be @c
824 ethumb_client_disconnect(Ethumb_Client *client)
826 EINA_SAFETY_ON_NULL_RETURN(client);
828 EINA_REFCOUNT_UNREF(client)
829 _ethumb_client_free(client);
833 * Sets the callback to report server died.
835 * When server dies there is nothing you can do, just release
836 * resources with ethumb_client_disconnect() and probably try to
839 * Usually you should set this callback and handle this case, it does
842 * @param client the client instance to monitor. Must @b not be @c
844 * @param server_die_cb function to call back when server dies. The
845 * first parameter will be the argument @a data. May be @c
847 * @param data context to give back to @a server_die_cb. May be @c
849 * @param free_data used to release @a data resources after @a
850 * server_die_cb is called or user calls
851 * ethumb_client_disconnect().
854 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)
856 EINA_SAFETY_ON_NULL_RETURN(client);
858 if (client->die.free_data)
859 client->die.free_data(client->die.data);
861 client->die.cb = server_die_cb;
862 client->die.data = (void *)data;
863 client->die.free_data = free_data;
871 _ethumb_client_ethumb_setup_cb(void *data, DBusMessage *msg, DBusError *error)
873 DBusMessageIter iter;
875 dbus_bool_t result = 0;
876 Ethumb_Client *client = data;
878 client->pending_setup = NULL;
880 if (!_dbus_callback_check_and_init(msg, &iter, error))
883 t = dbus_message_iter_get_arg_type(&iter);
884 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
887 dbus_message_iter_get_basic(&iter, &result);
891 _ethumb_client_dbus_get_bytearray(DBusMessageIter *iter)
895 DBusMessageIter riter;
898 el_type = dbus_message_iter_get_element_type(iter);
899 if (el_type != DBUS_TYPE_BYTE)
901 ERR("not an byte array element.");
905 dbus_message_iter_recurse(iter, &riter);
906 dbus_message_iter_get_fixed_array(&riter, &result, &length);
908 if (result[0] == '\0')
911 return eina_stringshare_add(result);
915 _ethumb_client_dbus_append_bytearray(DBusMessageIter *iter, const char *string)
917 DBusMessageIter viter;
922 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &viter);
923 dbus_message_iter_append_fixed_array(&viter, DBUS_TYPE_BYTE, &string,
925 dbus_message_iter_close_container(iter, &viter);
933 * Send setup to server.
935 * This method is called automatically by ethumb_client_generate() if
936 * any property was changed. No need to call it manually.
938 * @param client client instance. Must @b not be @c NULL and client
939 * must be connected (after connected_cb is called).
942 ethumb_client_ethumb_setup(Ethumb_Client *client)
945 DBusMessageIter iter, aiter, diter, viter, vaiter;
946 Ethumb *e = client->ethumb;
948 dbus_int32_t tw, th, format, aspect, orientation, quality, compress;
951 const char *theme_file, *group, *swallow;
952 const char *directory, *category;
953 double video_time, video_start, video_interval;
954 dbus_int32_t video_ntimes, video_fps, document_page;
956 EINA_SAFETY_ON_NULL_RETURN(client);
957 EINA_SAFETY_ON_FALSE_RETURN(client->connected);
959 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
961 _ethumb_dbus_objects_interface,
963 dbus_message_iter_init_append(msg, &iter);
964 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &aiter);
969 #define _open_variant_iter(str_entry, str_type, end_iter) \
971 dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &diter); \
972 dbus_message_iter_append_basic(&diter, DBUS_TYPE_STRING, &entry); \
973 dbus_message_iter_open_container(&diter, DBUS_TYPE_VARIANT, str_type, \
976 #define _close_variant_iter(end_iter) \
977 dbus_message_iter_close_container(&diter, &end_iter); \
978 dbus_message_iter_close_container(&aiter, &diter);
983 /* starting array elements */
985 _open_variant_iter("size", "(ii)", viter);
986 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
987 ethumb_thumb_size_get(e, &tw, &th);
988 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &tw);
989 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &th);
990 dbus_message_iter_close_container(&viter, &vaiter);
991 _close_variant_iter(viter);
993 _open_variant_iter("format", "i", viter);
994 format = ethumb_thumb_format_get(e);
995 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &format);
996 _close_variant_iter(viter);
998 _open_variant_iter("aspect", "i", viter);
999 aspect = ethumb_thumb_aspect_get(e);
1000 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &aspect);
1001 _close_variant_iter(viter);
1003 _open_variant_iter("orientation", "i", viter);
1004 orientation = ethumb_thumb_orientation_get(e);
1005 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &orientation);
1006 _close_variant_iter(viter);
1008 _open_variant_iter("crop", "(dd)", viter);
1009 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
1010 ethumb_thumb_crop_align_get(e, &cx, &cy);
1012 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
1014 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
1015 dbus_message_iter_close_container(&viter, &vaiter);
1016 _close_variant_iter(viter);
1018 _open_variant_iter("quality", "i", viter);
1019 quality = ethumb_thumb_quality_get(e);
1020 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &quality);
1021 _close_variant_iter(viter);
1023 _open_variant_iter("compress", "i", viter);
1024 compress = ethumb_thumb_compress_get(e);
1025 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &compress);
1026 _close_variant_iter(viter);
1028 _open_variant_iter("frame", "(ayayay)", viter);
1029 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
1030 ethumb_frame_get(e, &theme_file, &group, &swallow);
1031 _ethumb_client_dbus_append_bytearray(&vaiter, theme_file);
1032 _ethumb_client_dbus_append_bytearray(&vaiter, group);
1033 _ethumb_client_dbus_append_bytearray(&vaiter, swallow);
1034 dbus_message_iter_close_container(&viter, &vaiter);
1035 _close_variant_iter(viter);
1037 _open_variant_iter("directory", "ay", viter);
1038 directory = ethumb_thumb_dir_path_get(e);
1039 _ethumb_client_dbus_append_bytearray(&viter, directory);
1040 _close_variant_iter(viter);
1042 _open_variant_iter("category", "ay", viter);
1043 category = ethumb_thumb_category_get(e);
1044 _ethumb_client_dbus_append_bytearray(&viter, category);
1045 _close_variant_iter(viter);
1047 _open_variant_iter("video_time", "d", viter);
1048 video_time = ethumb_video_time_get(e);
1049 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time);
1050 _close_variant_iter(viter);
1052 _open_variant_iter("video_start", "d", viter);
1053 video_start = ethumb_video_start_get(e);
1054 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start);
1055 _close_variant_iter(viter);
1057 _open_variant_iter("video_interval", "d", viter);
1058 video_interval = ethumb_video_interval_get(e);
1059 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval);
1060 _close_variant_iter(viter);
1062 _open_variant_iter("video_ntimes", "u", viter);
1063 video_ntimes = ethumb_video_ntimes_get(e);
1064 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_ntimes);
1065 _close_variant_iter(viter);
1067 _open_variant_iter("video_fps", "u", viter);
1068 video_fps = ethumb_video_fps_get(e);
1069 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_fps);
1070 _close_variant_iter(viter);
1072 _open_variant_iter("document_page", "u", viter);
1073 document_page = ethumb_document_page_get(e);
1074 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &document_page);
1075 _close_variant_iter(viter);
1077 #undef _open_variant_iter
1078 #undef _close_variant_iter
1080 dbus_message_iter_close_container(&iter, &aiter);
1082 client->pending_setup = e_dbus_message_send(client->conn, msg,
1083 _ethumb_client_ethumb_setup_cb,
1085 dbus_message_unref(msg);
1093 _ethumb_client_generated_cb(void *data, DBusMessage *msg)
1095 DBusMessageIter iter;
1096 dbus_int32_t id = -1;
1097 const char *thumb = NULL;
1098 const char *thumb_key = NULL;
1099 Ethumb_Client *client = data;
1101 dbus_bool_t success;
1104 struct _ethumb_pending_gen *pending;
1106 dbus_message_iter_init(msg, &iter);
1108 t = dbus_message_iter_get_arg_type(&iter);
1109 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1111 dbus_message_iter_get_basic(&iter, &id);
1112 dbus_message_iter_next(&iter);
1114 t = dbus_message_iter_get_arg_type(&iter);
1115 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1117 thumb = _ethumb_client_dbus_get_bytearray(&iter);
1118 dbus_message_iter_next(&iter);
1120 t = dbus_message_iter_get_arg_type(&iter);
1121 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1123 thumb_key = _ethumb_client_dbus_get_bytearray(&iter);
1124 dbus_message_iter_next(&iter);
1126 t = dbus_message_iter_get_arg_type(&iter);
1127 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1129 dbus_message_iter_get_basic(&iter, &success);
1132 l = client->pending_gen;
1136 if (pending->id == id)
1146 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1147 if (pending->generated_cb)
1148 pending->generated_cb(pending->data, client, id,
1149 pending->file, pending->key,
1150 pending->thumb, pending->thumb_key,
1152 if (pending->free_data)
1153 pending->free_data(pending->data);
1154 eina_stringshare_del(pending->file);
1155 eina_stringshare_del(pending->key);
1156 eina_stringshare_del(pending->thumb);
1157 eina_stringshare_del(pending->thumb_key);
1162 if (thumb) eina_stringshare_del(thumb);
1163 if (thumb_key) eina_stringshare_del(thumb_key);
1167 _ethumb_client_queue_add_cb(void *data, DBusMessage *msg, DBusError *error)
1169 DBusMessageIter iter;
1171 dbus_int32_t id = -1;
1172 struct _ethumb_pending_add *pending = data;
1173 struct _ethumb_pending_gen *generating;
1174 Ethumb_Client *client = pending->client;
1176 client->pending_add = eina_list_remove(client->pending_add, pending);
1178 if (!_dbus_callback_check_and_init(msg, &iter, error))
1181 t = dbus_message_iter_get_arg_type(&iter);
1182 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1185 dbus_message_iter_get_basic(&iter, &id);
1187 generating = calloc(1, sizeof(*generating));
1188 generating->id = id;
1189 generating->file = pending->file;
1190 generating->key = pending->key;
1191 generating->thumb = pending->thumb;
1192 generating->thumb_key = pending->thumb_key;
1193 generating->generated_cb = pending->generated_cb;
1194 generating->data = pending->data;
1195 generating->free_data = pending->free_data;
1196 client->pending_gen = eina_list_append(client->pending_gen, generating);
1203 _ethumb_client_queue_add(Ethumb_Client *client, const char *file, const char *key, const char *thumb, const char *thumb_key, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data)
1206 DBusMessageIter iter;
1207 struct _ethumb_pending_add *pending;
1209 pending = calloc(1, sizeof(*pending));
1210 pending->id = client->id_count;
1211 pending->file = eina_stringshare_add(file);
1212 pending->key = eina_stringshare_add(key);
1213 pending->thumb = eina_stringshare_add(thumb);
1214 pending->thumb_key = eina_stringshare_add(thumb_key);
1215 pending->generated_cb = generated_cb;
1216 pending->data = (void *)data;
1217 pending->free_data = free_data;
1218 pending->client = client;
1220 client->id_count = (client->id_count + 1) % MAX_ID;
1222 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1223 client->object_path,
1224 _ethumb_dbus_objects_interface,
1227 dbus_message_iter_init_append(msg, &iter);
1228 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &pending->id);
1229 _ethumb_client_dbus_append_bytearray(&iter, file);
1230 _ethumb_client_dbus_append_bytearray(&iter, key);
1231 _ethumb_client_dbus_append_bytearray(&iter, thumb);
1232 _ethumb_client_dbus_append_bytearray(&iter, thumb_key);
1234 pending->pending_call = e_dbus_message_send(client->conn, msg,
1235 _ethumb_client_queue_add_cb,
1237 client->pending_add = eina_list_append(client->pending_add, pending);
1238 dbus_message_unref(msg);
1244 _ethumb_client_queue_remove_cb(void *data, DBusMessage *msg, DBusError *error)
1246 DBusMessageIter iter;
1248 dbus_bool_t success = 0;
1249 struct _ethumb_pending_remove *pending = data;
1250 Ethumb_Client *client = pending->client;
1252 client->pending_remove = eina_list_remove(client->pending_remove, pending);
1254 if (!_dbus_callback_check_and_init(msg, &iter, error))
1257 t = dbus_message_iter_get_arg_type(&iter);
1258 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1261 dbus_message_iter_get_basic(&iter, &success);
1264 if (pending->cancel_cb)
1265 pending->cancel_cb(pending->data, success);
1266 if (pending->free_data)
1267 pending->free_data(pending->data);
1276 * Ask server to cancel generation of thumbnail.
1278 * @param client client instance. Must @b not be @c NULL and client
1279 * must be connected (after connected_cb is called).
1280 * @param id valid id returned by ethumb_client_generate()
1281 * @param cancel_cb function to report cancellation results.
1282 * @param data context argument to give back to @a cancel_cb. May be
1284 * @param data context to give back to @a cancel_cb. May be @c
1286 * @param free_data used to release @a data resources after @a
1287 * cancel_cb is called or user calls
1288 * ethumb_client_disconnect().
1291 ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, const void *data, Eina_Free_Cb free_data)
1294 struct _ethumb_pending_remove *pending;
1297 dbus_int32_t id32 = id;
1298 EINA_SAFETY_ON_NULL_RETURN(client);
1299 EINA_SAFETY_ON_FALSE_RETURN(id >= 0);
1301 pending = calloc(1, sizeof(*pending));
1303 pending->cancel_cb = cancel_cb;
1304 pending->data = (void *)data;
1305 pending->free_data = free_data;
1306 pending->client = client;
1308 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1309 client->object_path,
1310 _ethumb_dbus_objects_interface,
1313 dbus_message_append_args(msg, DBUS_TYPE_INT32, &id32, DBUS_TYPE_INVALID);
1314 pending->pending_call = e_dbus_message_send(client->conn, msg,
1315 _ethumb_client_queue_remove_cb,
1317 client->pending_remove = eina_list_append(client->pending_remove, pending);
1320 l = client->pending_add;
1323 struct _ethumb_pending_add *pending_add = l->data;
1324 if (pending_add->id != id32)
1329 client->pending_add = eina_list_remove_list(client->pending_add, l);
1330 eina_stringshare_del(pending_add->file);
1331 eina_stringshare_del(pending_add->key);
1332 eina_stringshare_del(pending_add->thumb);
1333 eina_stringshare_del(pending_add->thumb_key);
1334 dbus_pending_call_cancel(pending_add->pending_call);
1335 dbus_pending_call_unref(pending_add->pending_call);
1336 if (pending_add->free_data)
1337 pending_add->free_data(pending_add->data);
1346 l = client->pending_gen;
1349 struct _ethumb_pending_gen *pending_gen = l->data;
1350 if (pending_gen->id != id32)
1355 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1356 eina_stringshare_del(pending_gen->file);
1357 eina_stringshare_del(pending_gen->key);
1358 eina_stringshare_del(pending_gen->thumb);
1359 eina_stringshare_del(pending_gen->thumb_key);
1360 if (pending_gen->free_data)
1361 pending_gen->free_data(pending_gen->data);
1367 dbus_message_unref(msg);
1374 _ethumb_client_queue_clear_cb(void *data, DBusMessage *msg __UNUSED__, DBusError *error __UNUSED__)
1376 Ethumb_Client *client = data;
1378 client->pending_clear = NULL;
1386 * Ask server to cancel generation of all thumbnails.
1388 * @param client client instance. Must @b not be @c NULL and client
1389 * must be connected (after connected_cb is called).
1391 * @see ethumb_client_generate_cancel()
1394 ethumb_client_generate_cancel_all(Ethumb_Client *client)
1398 EINA_SAFETY_ON_NULL_RETURN(client);
1400 if (client->pending_clear)
1403 EINA_LIST_FREE(client->pending_add, data)
1405 struct _ethumb_pending_add *pending = data;
1406 eina_stringshare_del(pending->file);
1407 eina_stringshare_del(pending->key);
1408 eina_stringshare_del(pending->thumb);
1409 eina_stringshare_del(pending->thumb_key);
1410 dbus_pending_call_cancel(pending->pending_call);
1411 dbus_pending_call_unref(pending->pending_call);
1412 if (pending->free_data)
1413 pending->free_data(pending->data);
1417 EINA_LIST_FREE(client->pending_gen, data)
1419 struct _ethumb_pending_gen *pending = data;
1420 eina_stringshare_del(pending->file);
1421 eina_stringshare_del(pending->key);
1422 eina_stringshare_del(pending->thumb);
1423 eina_stringshare_del(pending->thumb_key);
1424 if (pending->free_data)
1425 pending->free_data(pending->data);
1429 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1430 client->object_path,
1431 _ethumb_dbus_objects_interface,
1434 client->pending_clear = e_dbus_message_send(client->conn, msg,
1435 _ethumb_client_queue_clear_cb,
1438 dbus_message_unref(msg);
1442 * Configure future requests to use FreeDesktop.Org preset.
1444 * This is a preset to provide freedesktop.org (fdo) standard
1445 * compliant thumbnails. That is, files are stored as JPEG under
1446 * ~/.thumbnails/SIZE, with size being either normal (128x128) or
1449 * @param client the client instance to use. Must @b not be @c
1450 * NULL. May be pending connected (can be called before @c
1452 * @param s size identifier, either #ETHUMB_THUMB_NORMAL (0) or
1453 * #ETHUMB_THUMB_LARGE (1).
1455 * @see ethumb_client_size_set()
1456 * @see ethumb_client_aspect_set()
1457 * @see ethumb_client_crop_align_set()
1458 * @see ethumb_client_category_set()
1459 * @see ethumb_client_dir_path_set()
1462 ethumb_client_fdo_set(Ethumb_Client *client, Ethumb_Thumb_FDO_Size s)
1464 EINA_SAFETY_ON_NULL_RETURN(client);
1466 if (!client->old_ethumb_conf)
1467 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1468 ethumb_thumb_fdo_set(client->ethumb, s);
1472 * Configure future request to use custom size.
1474 * @param client the client instance to use. Must @b not be @c
1475 * NULL. May be pending connected (can be called before @c
1477 * @param tw width, default is 128.
1478 * @param th height, default is 128.
1481 ethumb_client_size_set(Ethumb_Client *client, int tw, int th)
1483 EINA_SAFETY_ON_NULL_RETURN(client);
1485 if (!client->old_ethumb_conf)
1486 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1487 ethumb_thumb_size_set(client->ethumb, tw, th);
1491 * Retrieve future request to use custom size.
1493 * @param client the client instance to use. Must @b not be @c
1494 * NULL. May be pending connected (can be called before @c
1496 * @param tw where to return width. May be @c NULL.
1497 * @param th where to return height. May be @c NULL.
1500 ethumb_client_size_get(const Ethumb_Client *client, int *tw, int *th)
1504 EINA_SAFETY_ON_NULL_RETURN(client);
1506 ethumb_thumb_size_get(client->ethumb, tw, th);
1510 * Configure format to use for future requests.
1512 * @param client the client instance to use. Must @b not be @c
1513 * NULL. May be pending connected (can be called before @c
1515 * @param f format identifier to use, either #ETHUMB_THUMB_FDO (0),
1516 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2). Default is FDO.
1519 ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f)
1521 EINA_SAFETY_ON_NULL_RETURN(client);
1523 if (!client->old_ethumb_conf)
1524 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1525 ethumb_thumb_format_set(client->ethumb, f);
1529 * Retrieve format to use for future requests.
1531 * @param client the client instance to use. Must @b not be @c
1532 * NULL. May be pending connected (can be called before @c
1535 * @return format identifier to use, either #ETHUMB_THUMB_FDO (0),
1536 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2).
1538 EAPI Ethumb_Thumb_Format
1539 ethumb_client_format_get(const Ethumb_Client *client)
1541 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1543 return ethumb_thumb_format_get(client->ethumb);
1547 * Configure aspect mode to use.
1549 * If aspect is kept (#ETHUMB_THUMB_KEEP_ASPECT), then image will be
1550 * rescaled so the largest dimension is not bigger than it's specified
1551 * size (see ethumb_client_size_get()) and the other dimension is
1552 * resized in the same proportion. Example: size is 256x256, image is
1553 * 1000x500, resulting thumbnail is 256x128.
1555 * If aspect is ignored (#ETHUMB_THUMB_IGNORE_ASPECT), then image will
1556 * be distorted to match required thumbnail size. Example: size is
1557 * 256x256, image is 1000x500, resulting thumbnail is 256x256.
1559 * If crop is required (#ETHUMB_THUMB_CROP), then image will be
1560 * cropped so the smallest dimension is not bigger than its specified
1561 * size (see ethumb_client_size_get()) and the other dimension will
1562 * overflow, not being visible in the final image. How it will
1563 * overflow is speficied by ethumb_client_crop_align_set()
1564 * alignment. Example: size is 256x256, image is 1000x500, crop
1565 * alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
1566 * pixels from left and 250 pixels from right being lost, that is just
1567 * the 500x500 central pixels of image will be considered for scaling.
1569 * @param client the client instance to use. Must @b not be @c
1570 * NULL. May be pending connected (can be called before @c
1572 * @param a aspect mode identifier, either #ETHUMB_THUMB_KEEP_ASPECT (0),
1573 * #ETHUMB_THUMB_IGNORE_ASPECT (1) or #ETHUMB_THUMB_CROP (2).
1576 ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a)
1578 EINA_SAFETY_ON_NULL_RETURN(client);
1580 if (!client->old_ethumb_conf)
1581 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1582 ethumb_thumb_aspect_set(client->ethumb, a);
1586 * Get current aspect in use for requests.
1588 * @param client the client instance to use. Must @b not be @c
1589 * NULL. May be pending connected (can be called before @c
1592 * @return aspect in use for future requests.
1594 EAPI Ethumb_Thumb_Aspect
1595 ethumb_client_aspect_get(const Ethumb_Client *client)
1597 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1599 return ethumb_thumb_aspect_get(client->ethumb);
1603 * Configure orientation to use for future requests.
1605 * Default value is #ETHUMB_THUMB_ORIENT_ORIGINAL: metadata from the file
1606 * will be used to orient pixel data.
1608 * @param client the client instance to use. Must @b not be @c
1609 * NULL. May be pending connected (can be called before @c
1611 * @param o format identifier to use, either #ETHUMB_THUMB_ORIENT_NONE (0),
1612 * #ETHUMB_THUMB_ROTATE_90_CW (1), #ETHUMB_THUMB_ROTATE_180 (2),
1613 * #ETHUMB_THUMB_ROTATE_90_CCW (3), #ETHUMB_THUMB_FLIP_HORIZONTAL (4),
1614 * #ETHUMB_THUMB_FLIP_VERTICAL (5), #ETHUMB_THUMB_FLIP_TRANSPOSE (6),
1615 * #ETHUMB_THUMB_FLIP_TRANSVERSE (7) or #ETHUMB_THUMB_ORIENT_ORIGINAL
1616 * (8). Default is ORIGINAL.
1619 ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o)
1621 EINA_SAFETY_ON_NULL_RETURN(client);
1623 if (!client->old_ethumb_conf)
1624 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1625 ethumb_thumb_orientation_set(client->ethumb, o);
1629 * Get current orientation in use for requests.
1631 * @param client the client instance to use. Must @b not be @c
1632 * NULL. May be pending connected (can be called before @c
1635 * @return orientation in use for future requests.
1637 EAPI Ethumb_Thumb_Orientation
1638 ethumb_client_orientation_get(const Ethumb_Client *client)
1640 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1642 return ethumb_thumb_orientation_get(client->ethumb);
1646 * Configure crop alignment in use for future requests.
1648 * @param client the client instance to use. Must @b not be @c
1649 * NULL. May be pending connected (can be called before @c
1651 * @param x horizontal alignment. 0.0 means left side will be visible
1652 * or right side is being lost. 1.0 means right side will be
1653 * visible or left side is being lost. 0.5 means just center is
1654 * visible, both sides will be lost. Default is 0.5.
1655 * @param y vertical alignment. 0.0 is top visible, 1.0 is bottom
1656 * visible, 0.5 is center visible. Default is 0.5
1659 ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y)
1661 EINA_SAFETY_ON_NULL_RETURN(client);
1663 if (!client->old_ethumb_conf)
1664 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1665 ethumb_thumb_crop_align_set(client->ethumb, x, y);
1669 * Get current crop alignment in use for requests.
1671 * @param client the client instance to use. Must @b not be @c
1672 * NULL. May be pending connected (can be called before @c
1674 * @param x where to return horizontal alignment. May be @c NULL.
1675 * @param y where to return vertical alignment. May be @c NULL.
1678 ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y)
1682 EINA_SAFETY_ON_NULL_RETURN(client);
1684 ethumb_thumb_crop_align_get(client->ethumb, x, y);
1688 * Configure quality to be used in thumbnails.
1690 * @param client the client instance to use. Must @b not be @c
1691 * NULL. May be pending connected (can be called before @c
1693 * @param quality value from 0 to 100, default is 80. The effect
1694 * depends on the format being used, PNG will not use it.
1697 ethumb_client_quality_set(Ethumb_Client *client, int quality)
1699 EINA_SAFETY_ON_NULL_RETURN(client);
1701 ethumb_thumb_quality_set(client->ethumb, quality);
1705 * Get quality to be used in thumbnails.
1707 * @param client the client instance to use. Must @b not be @c
1708 * NULL. May be pending connected (can be called before @c
1711 * @return quality value from 0 to 100, default is 80. The effect
1712 * depends on the format being used, PNG will not use it.
1715 ethumb_client_quality_get(const Ethumb_Client *client)
1717 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1719 return ethumb_thumb_quality_get(client->ethumb);
1723 * Configure compression level used in requests.
1725 * @param client the client instance to use. Must @b not be @c
1726 * NULL. May be pending connected (can be called before @c
1728 * @param compress value from 0 to 9, default is 9. The effect
1729 * depends on the format being used, JPEG will not use it.
1732 ethumb_client_compress_set(Ethumb_Client *client, int compress)
1734 EINA_SAFETY_ON_NULL_RETURN(client);
1736 ethumb_thumb_compress_set(client->ethumb, compress);
1740 * Get compression level used in requests.
1742 * @param client the client instance to use. Must @b not be @c
1743 * NULL. May be pending connected (can be called before @c
1746 * @return compress value from 0 to 9, default is 9. The effect
1747 * depends on the format being used, JPEG will not use it.
1750 ethumb_client_compress_get(const Ethumb_Client *client)
1752 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1754 return ethumb_thumb_compress_get(client->ethumb);
1758 * Set frame to apply to future thumbnails.
1760 * This will create an edje object that will have image swallowed
1761 * in. This can be used to simulate Polaroid or wood frames in the
1762 * generated image. Remeber it is bad to modify the original contents
1763 * of thumbnails, but sometimes it's useful to have it composited and
1764 * avoid runtime overhead.
1766 * @param client the client instance to use. Must @b not be @c
1767 * NULL. May be pending connected (can be called before @c
1769 * @param file file path to edje.
1770 * @param group group inside edje to use.
1771 * @param swallow name of swallow part.
1773 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
1776 ethumb_client_frame_set(Ethumb_Client *client, const char *file, const char *group, const char *swallow)
1778 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1780 if (!client->old_ethumb_conf)
1781 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1782 return ethumb_frame_set(client->ethumb, file, group, swallow);
1786 * Configure where to store thumbnails in future requests.
1788 * This value will be used to generate thumbnail paths, that is, it
1789 * will be used when ethumb_client_thumb_path_set() was not called
1790 * after last ethumb_client_file_set().
1792 * Note that this is the base, a category is added to this path as a
1793 * sub directory. This is not the final directory where files are
1794 * stored, the thumbnail system will account @b category as well, see
1795 * ethumb_client_category_set().
1797 * As other options, this value will only be applied to future
1800 * @param client the client instance to use. Must @b not be @c
1801 * NULL. May be pending connected (can be called before @c
1803 * @param path base directory where to store thumbnails. Default is
1806 * @see ethumb_client_category_set()
1809 ethumb_client_dir_path_set(Ethumb_Client *client, const char *path)
1811 EINA_SAFETY_ON_NULL_RETURN(client);
1813 if (!client->old_ethumb_conf)
1814 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1815 ethumb_thumb_dir_path_set(client->ethumb, path);
1819 * Get base directory path where to store thumbnails.
1821 * @param client the client instance to use. Must @b not be @c
1822 * NULL. May be pending connected (can be called before @c
1825 * @return pointer to internal string with current path. This string
1826 * should not be modified or freed.
1828 * @see ethumb_client_dir_path_set()
1831 ethumb_client_dir_path_get(const Ethumb_Client *client)
1833 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1835 return ethumb_thumb_dir_path_get(client->ethumb);
1839 * Category directory to store thumbnails.
1841 * This value will be used to generate thumbnail paths, that is, it
1842 * will be used when ethumb_client_thumb_path_set() was not called
1843 * after last ethumb_client_file_set().
1845 * This is a sub-directory inside base directory
1846 * (ethumb_client_dir_path_set()) that creates a namespace to avoid
1847 * different options resulting in the same file.
1849 * As other options, this value will only be applied to future
1852 * @param client the client instance to use. Must @b not be @c
1853 * NULL. May be pending connected (can be called before @c
1855 * @param category category sub directory to store thumbnail. Default
1856 * is either "normal" or "large" for FDO compliant thumbnails
1857 * or WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string
1858 * or @c NULL to use auto generated names.
1860 * @see ethumb_client_dir_path_set()
1863 ethumb_client_category_set(Ethumb_Client *client, const char *category)
1865 EINA_SAFETY_ON_NULL_RETURN(client);
1867 if (!client->old_ethumb_conf)
1868 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1869 ethumb_thumb_category_set(client->ethumb, category);
1873 * Get category sub-directory where to store thumbnails.
1875 * @param client the client instance to use. Must @b not be @c
1876 * NULL. May be pending connected (can be called before @c
1879 * @return pointer to internal string with current path. This string
1880 * should not be modified or freed.
1882 * @see ethumb_client_category_set()
1885 ethumb_client_category_get(const Ethumb_Client *client)
1887 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1889 return ethumb_thumb_category_get(client->ethumb);
1893 * Set the video time (duration) in seconds.
1895 * @param client the client instance to use. Must @b not be @c
1896 * NULL. May be pending connected (can be called before @c
1898 * @param t duration (in seconds). Defaults to 3 seconds.
1901 ethumb_client_video_time_set(Ethumb_Client *client, float t)
1903 EINA_SAFETY_ON_NULL_RETURN(client);
1905 if (!client->old_ethumb_conf)
1906 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1907 ethumb_video_time_set(client->ethumb, t);
1911 * Set initial video position to start thumbnailing, in percentage.
1913 * This is useful to avoid thumbnailing the company/producer logo or
1916 * @param client the client instance to use. Must @b not be @c
1917 * NULL. May be pending connected (can be called before @c
1919 * @param start initial video positon to thumbnail, in percentage (0.0
1920 * to 1.0, inclusive). Defaults to 10% (0.1).
1923 ethumb_client_video_start_set(Ethumb_Client *client, float start)
1925 EINA_SAFETY_ON_NULL_RETURN(client);
1926 EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0);
1927 EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0);
1929 if (!client->old_ethumb_conf)
1930 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1931 ethumb_video_start_set(client->ethumb, start);
1935 * Set the video frame interval, in seconds.
1937 * This is useful for animated thumbnail and will define skip time
1938 * before going to the next frame. Note that video backends might not
1939 * be able to precisely skip that amount as it will depend on various
1940 * factors, including video encoding.
1942 * Although this seems similar to ethumb_client_video_fps_set(), this
1943 * one is the time that will be used to seek. The math is simple, for
1944 * each new frame the video position will be set to:
1945 * ((video_length * start_time) + (interval * current_frame_number)).
1947 * @param client the client instance to use. Must @b not be @c
1948 * NULL. May be pending connected (can be called before @c
1950 * @param interval time between frames, in seconds. Defaults to 0.05
1954 ethumb_client_video_interval_set(Ethumb_Client *client, float interval)
1956 EINA_SAFETY_ON_NULL_RETURN(client);
1958 if (!client->old_ethumb_conf)
1959 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1960 ethumb_video_interval_set(client->ethumb, interval);
1964 * Set the number of frames to thumbnail.
1966 * This is useful for animated thumbnail and will define how many
1967 * frames the generated file will have.
1969 * @param client the client instance to use. Must @b not be @c
1970 * NULL. May be pending connected (can be called before @c
1972 * @param ntimes number of times, must be greater than zero.
1976 ethumb_client_video_ntimes_set(Ethumb_Client *client, unsigned int ntimes)
1978 EINA_SAFETY_ON_NULL_RETURN(client);
1979 EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0);
1981 if (!client->old_ethumb_conf)
1982 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1983 ethumb_video_ntimes_set(client->ethumb, ntimes);
1987 * Set the number of frames per second to thumbnail the video.
1989 * This configures the number of times per seconds the thumbnail will
1990 * use to create thumbnails.
1992 * Although this is similar to ethumb_client_video_interval_set(), it
1993 * is the delay used between calling functions thata generates frames,
1994 * while the other is the time used to skip inside the video.
1996 * @param client the client instance to use. Must @b not be @c
1997 * NULL. May be pending connected (can be called before @c
1999 * @param fps number of frames per second to thumbnail. Must be greater
2000 * than zero. Defaults to 10.
2003 ethumb_client_video_fps_set(Ethumb_Client *client, unsigned int fps)
2005 EINA_SAFETY_ON_NULL_RETURN(client);
2006 EINA_SAFETY_ON_FALSE_RETURN(fps > 0);
2008 if (!client->old_ethumb_conf)
2009 client->old_ethumb_conf = ethumb_dup(client->ethumb);
2010 ethumb_video_fps_set(client->ethumb, fps);
2014 * Set the page number to thumbnail in paged documents.
2016 * @param client the client instance to use. Must @b not be @c
2017 * NULL. May be pending connected (can be called before @c
2019 * @param page page number, defaults to 0 (first).
2022 ethumb_client_document_page_set(Ethumb_Client *client, unsigned int page)
2024 EINA_SAFETY_ON_NULL_RETURN(client);
2026 if (!client->old_ethumb_conf)
2027 client->old_ethumb_conf = ethumb_dup(client->ethumb);
2028 ethumb_document_page_set(client->ethumb, page);
2032 * Set source file to be thumbnailed.
2034 * Calling this function has the side effect of resetting values set
2035 * with ethumb_client_thumb_path_set() or auto-generated with
2036 * ethumb_client_thumb_exists().
2038 * @param client the client instance to use. Must @b not be @c
2039 * NULL. May be pending connected (can be called before @c
2041 * @param path the filesystem path to use. May be @c NULL.
2042 * @param key the extra argument/key inside @a path to read image
2043 * from. This is only used for formats that allow multiple
2044 * resources in one file, like EET or Edje (group name).
2046 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
2049 ethumb_client_file_set(Ethumb_Client *client, const char *path, const char *key)
2051 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
2053 return ethumb_file_set(client->ethumb, path, key);
2057 * Get values set with ethumb_client_file_get()
2059 * @param client the client instance to use. Must @b not be @c
2060 * NULL. May be pending connected (can be called before @c
2062 * @param path where to return configured path. May be @c NULL. If
2063 * not @c NULL, then it will be a pointer to a stringshared
2064 * instance, but @b no references are added (do it with
2065 * eina_stringshare_ref())!
2066 * @param key where to return configured key. May be @c NULL.If not @c
2067 * NULL, then it will be a pointer to a stringshared instance,
2068 * but @b no references are added (do it with
2069 * eina_stringshare_ref())!
2072 ethumb_client_file_get(Ethumb_Client *client, const char **path, const char **key)
2074 if (path) *path = NULL;
2075 if (key) *key = NULL;
2076 EINA_SAFETY_ON_NULL_RETURN(client);
2078 ethumb_file_get(client->ethumb, path, key);
2082 * Reset previously set file to @c NULL.
2084 * @param client the client instance to use. Must @b not be @c
2085 * NULL. May be pending connected (can be called before @c
2089 ethumb_client_file_free(Ethumb_Client *client)
2091 EINA_SAFETY_ON_NULL_RETURN(client);
2093 ethumb_file_free(client->ethumb);
2097 * Set a defined path and key to store the thumbnail.
2099 * If not explicitly given, the thumbnail path will be auto-generated
2100 * by ethumb_client_thumb_exists() or server using configured
2101 * parameters like size, aspect and category.
2103 * Set these to @c NULL to forget previously given values. After
2104 * ethumb_client_file_set() these values will be reset to @c NULL.
2106 * @param client the client instance to use. Must @b not be @c
2107 * NULL. May be pending connected (can be called before @c
2109 * @param path force generated thumbnail to the exact given path. If
2110 * @c NULL, then reverts back to auto-generation.
2111 * @param key force generated thumbnail to the exact given key. If
2112 * @c NULL, then reverts back to auto-generation.
2115 ethumb_client_thumb_path_set(Ethumb_Client *client, const char *path, const char *key)
2117 EINA_SAFETY_ON_NULL_RETURN(client);
2119 ethumb_thumb_path_set(client->ethumb, path, key);
2123 * Get the configured thumbnail path.
2125 * This returns the value set with ethumb_client_thumb_path_set() or
2126 * auto-generated by ethumb_client_thumb_exists() if it was not set.
2128 * @param client the client instance to use. Must @b not be @c
2129 * NULL. May be pending connected (can be called before @c
2131 * @param path where to return configured path. May be @c NULL. If
2132 * there was no path configured with
2133 * ethumb_client_thumb_path_set() and
2134 * ethumb_client_thumb_exists() was not called, then it will
2135 * probably return @c NULL. If not @c NULL, then it will be a
2136 * pointer to a stringshared instance, but @b no references are
2137 * added (do it with eina_stringshare_ref())!
2138 * @param key where to return configured key. May be @c NULL. If
2139 * there was no key configured with
2140 * ethumb_client_thumb_key_set() and
2141 * ethumb_client_thumb_exists() was not called, then it will
2142 * probably return @c NULL. If not @c NULL, then it will be a
2143 * pointer to a stringshared instance, but @b no references are
2144 * added (do it with eina_stringshare_ref())!
2147 ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const char **key)
2149 if (path) *path = NULL;
2150 if (key) *key = NULL;
2151 EINA_SAFETY_ON_NULL_RETURN(client);
2153 ethumb_thumb_path_get(client->ethumb, path, key);
2157 * Checks whenever file already exists (locally!)
2159 * This will check locally (not calling server) if thumbnail already
2160 * exists or not, also calculating the thumbnail path. See
2161 * ethumb_client_thumb_path_get(). Path must be configured with
2162 * ethumb_client_file_set() before using it and the last set file will
2165 * @param client client instance. Must @b not be @c NULL and client
2166 * must be configured with ethumb_client_file_set().
2168 * @return @c EINA_TRUE if it exists, @c EINA_FALSE otherwise.
2170 EAPI Ethumb_Exists *
2171 ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
2173 const char *path = NULL;
2174 Ethumb_Async_Exists *async = NULL;
2175 Ethumb_Exists *cb = NULL;
2178 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
2180 ethumb_file_get(client->ethumb, &path, NULL);
2181 if (!path) goto on_error;
2183 async = eina_hash_find(_exists_request, path);
2186 async = malloc(sizeof (Ethumb_Async_Exists));
2187 if (!async) goto on_error;
2189 async->path = eina_stringshare_ref(path);
2190 async->callbacks = NULL;
2191 async->dup = ethumb_dup(client->ethumb);
2193 if (!async->dup) goto on_error;
2195 cb = malloc(sizeof (Ethumb_Exists));
2196 if (!cb) goto on_error;
2198 EINA_REFCOUNT_REF(client);
2199 cb->client = client;
2200 cb->dup = ethumb_dup(client->ethumb);
2201 cb->exists_cb = exists_cb;
2205 async->callbacks = eina_list_append(async->callbacks, cb);
2207 /* spawn a thread here */
2208 t = ecore_thread_run(_ethumb_client_exists_heavy,
2209 _ethumb_client_exists_end,
2210 _ethumb_client_exists_end,
2212 if (!t) return NULL;
2215 eina_hash_direct_add(_exists_request, async->path, async);
2220 cb = malloc(sizeof (Ethumb_Exists));
2227 EINA_REFCOUNT_REF(client);
2228 cb->client = client;
2229 cb->dup = ethumb_dup(client->ethumb);
2230 cb->exists_cb = exists_cb;
2234 async->callbacks = eina_list_append(async->callbacks, cb);
2239 exists_cb((void *)data, client, NULL, EINA_FALSE);
2243 eina_stringshare_del(async->path);
2244 if (async->dup) ethumb_free(async->dup);
2251 * Cancel an ongoing exists request.
2253 * @param exists the request to cancel.
2256 ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
2258 Ethumb_Async_Exists *async = exists->parent;
2260 async->callbacks = eina_list_remove(async->callbacks, exists);
2261 if (eina_list_count(async->callbacks) <= 0)
2262 ecore_thread_cancel(async->thread);
2264 ethumb_free(exists->dup);
2265 EINA_REFCOUNT_UNREF(exists->client)
2266 _ethumb_client_free(exists->client);
2271 * Check if an exists request was cancelled.
2273 * @param exists the request to check.
2274 * @result return EINA_TRUE if the request was cancelled.
2277 ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
2279 Ethumb_Async_Exists *async = exists->parent;
2281 if (!async) return EINA_TRUE;
2283 if (async->callbacks) return EINA_FALSE;
2285 return ecore_thread_check(async->thread);
2289 * Ask server to generate thumbnail.
2291 * This process is asynchronous and will report back from main loop
2292 * using @a generated_cb. One can cancel this request by calling
2293 * ethumb_client_generate_cancel() or
2294 * ethumb_client_generate_cancel_all(), but not that request might be
2295 * processed by server already and no generated files will be removed
2296 * if that is the case.
2298 * This will not check if file already exists, this should be done by
2299 * explicitly calling ethumb_client_thumb_exists(). That is, this
2300 * function will override any existing thumbnail.
2302 * @param client client instance. Must @b not be @c NULL and client
2303 * must be connected (after connected_cb is called).
2304 * @param generated_cb function to report generation results.
2305 * @param data context argument to give back to @a generated_cb. May
2307 * @param data context to give back to @a generate_cb. May be @c
2309 * @param free_data used to release @a data resources after @a
2310 * generated_cb is called or user calls
2311 * ethumb_client_disconnect().
2313 * @return identifier or -1 on error. If -1 is returned (error) then
2314 * @a free_data is @b not called!
2316 * @see ethumb_client_connect()
2317 * @see ethumb_client_file_set()
2318 * @see ethumb_client_thumb_exists()
2319 * @see ethumb_client_generate_cancel()
2320 * @see ethumb_client_generate_cancel_all()
2323 ethumb_client_generate(Ethumb_Client *client, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data)
2325 const char *file, *key, *thumb, *thumb_key;
2327 EINA_SAFETY_ON_NULL_RETURN_VAL(client, -1);
2328 EINA_SAFETY_ON_FALSE_RETURN_VAL(client->connected, -1);
2330 ethumb_file_get(client->ethumb, &file, &key);
2333 ERR("no file set.");
2337 ethumb_thumb_path_get(client->ethumb, &thumb, &thumb_key);
2339 if (client->old_ethumb_conf &&
2340 ethumb_cmp(client->old_ethumb_conf, client->ethumb))
2342 ethumb_client_ethumb_setup(client);
2343 ethumb_free(client->old_ethumb_conf);
2344 client->old_ethumb_conf = NULL;
2346 id = _ethumb_client_queue_add(client, file, key, thumb, thumb_key,
2347 generated_cb, data, free_data);
2352 struct _Ethumb_Client_Async
2354 Ethumb_Exists *exists;
2355 Ethumb_Client *client;
2358 Ethumb_Client_Async_Done_Cb done;
2359 Ethumb_Client_Async_Error_Cb error;
2365 static Ecore_Idler *idler[2] = { NULL, NULL };
2366 static Eina_List *pending = NULL;
2367 static Eina_List *idle_tasks[2] = { NULL, NULL };
2370 _ethumb_client_async_free(Ethumb_Client_Async *async)
2372 EINA_REFCOUNT_UNREF(async->client)
2373 _ethumb_client_free(async->client);
2374 ethumb_free(async->dup);
2379 _ethumb_client_thumb_finish(void *data,
2380 Ethumb_Client *client, int id,
2381 const char *file __UNUSED__, const char *key __UNUSED__,
2382 const char *thumb_path, const char *thumb_key,
2385 Ethumb_Client_Async *async = data;
2387 assert(async->id == id);
2391 async->done(client, thumb_path, thumb_key, (void *)async->data);
2395 async->error(client, (void *)async->data);
2398 pending = eina_list_remove(pending, async);
2399 _ethumb_client_async_free(async);
2403 _ethumb_client_thumb_generate_idler(void *data __UNUSED__)
2405 Ethumb_Client_Async *async;
2408 EINA_LIST_FOREACH_SAFE (idle_tasks[1], l1, l2, async)
2412 idle_tasks[1] = eina_list_remove_list(idle_tasks[1], l1);
2414 tmp = async->client->ethumb;
2415 async->client->ethumb = async->dup;
2417 async->id = ethumb_client_generate(async->client, _ethumb_client_thumb_finish, async, NULL);
2418 if (async->id == -1)
2420 async->error(async->client, (void *)async->data);
2421 async->client->ethumb = tmp;
2422 _ethumb_client_async_free(async);
2426 async->client->ethumb = tmp;
2429 pending = eina_list_append(pending, async);
2431 if (ecore_time_get() - ecore_loop_time_get() > ecore_animator_frametime_get() * 0.5)
2440 _ethumb_client_thumb_exists(void *data, Ethumb_Client *client, Ethumb_Exists *request, Eina_Bool exists)
2442 Ethumb_Client_Async *async = data;
2444 if (request == NULL)
2447 assert(async->exists == request);
2449 async->exists = NULL;
2450 pending = eina_list_remove(pending, async);
2454 const char *thumb_path;
2455 const char *thumb_key;
2457 ethumb_client_thumb_path_get(client, &thumb_path, &thumb_key);
2458 async->done(client, thumb_path, thumb_key, (void *)async->data);
2459 _ethumb_client_async_free(async);
2463 idle_tasks[1] = eina_list_append(idle_tasks[1], async);
2466 idler[1] = ecore_idler_add(_ethumb_client_thumb_generate_idler, NULL);
2471 _ethumb_client_thumb_exists_idler(void *data __UNUSED__)
2473 Ethumb_Client_Async *async;
2476 EINA_LIST_FOREACH_SAFE (idle_tasks[0], l1, l2, async)
2480 idle_tasks[0] = eina_list_remove_list(idle_tasks[0], l1);
2482 tmp = async->client->ethumb;
2483 async->client->ethumb = async->dup;
2485 async->exists = ethumb_client_thumb_exists(async->client, _ethumb_client_thumb_exists, async);
2488 async->error(async->client, (void *)async->data);
2489 async->client->ethumb = tmp;
2490 _ethumb_client_async_free(async);
2494 async->client->ethumb = tmp;
2496 pending = eina_list_append(pending, async);
2498 if (ecore_time_get() - ecore_loop_time_get() > ecore_animator_frametime_get() * 0.5)
2506 EAPI Ethumb_Client_Async *
2507 ethumb_client_thumb_async_get(Ethumb_Client *client,
2508 Ethumb_Client_Async_Done_Cb done,
2509 Ethumb_Client_Async_Error_Cb error,
2512 Ethumb_Client_Async *async;
2514 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
2516 async = malloc(sizeof (Ethumb_Client_Async));
2519 error(client, (void *)data);
2523 EINA_REFCOUNT_REF(client);
2524 async->client = client;
2525 async->dup = ethumb_dup(client->ethumb);
2527 async->error = error;
2529 async->exists = NULL;
2532 idle_tasks[0] = eina_list_append(idle_tasks[0], async);
2535 idler[0] = ecore_idler_add(_ethumb_client_thumb_exists_idler, NULL);
2541 ethumb_client_thumb_async_cancel(Ethumb_Client *client, Ethumb_Client_Async *request)
2545 EINA_SAFETY_ON_NULL_RETURN(client);
2546 EINA_SAFETY_ON_NULL_RETURN(request);
2548 ethumb_file_get(request->dup, &path, NULL);
2550 if (request->exists)
2552 ethumb_client_thumb_exists_cancel(request->exists);
2553 request->exists = NULL;
2555 pending = eina_list_remove(pending, request);
2557 else if (request->id != -1)
2559 Ethumb *tmp = request->client->ethumb;
2560 request->client->ethumb = request->dup;
2562 ethumb_client_generate_cancel(request->client, request->id, NULL, NULL, NULL);
2564 request->client->ethumb = tmp;
2566 pending = eina_list_remove(pending, request);
2570 idle_tasks[0] = eina_list_remove(idle_tasks[0], request);
2571 idle_tasks[1] = eina_list_remove(idle_tasks[1], request);
2574 _ethumb_client_async_free(request);