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
74 #include <sys/types.h>
78 #include <eina_safety_checks.h>
83 #include "Ethumb_Client.h"
89 #define MAX_ID 2000000
91 static int _log_dom = -1;
92 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
93 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
94 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
95 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
96 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
103 Ethumb *old_ethumb_conf;
104 E_DBus_Connection *conn;
105 E_DBus_Signal_Handler *name_owner_changed_handler;
106 E_DBus_Signal_Handler *generated_signal;
107 DBusPendingCall *pending_get_name_owner;
108 DBusPendingCall *pending_start_service_by_name;
109 const char *unique_name;
110 DBusPendingCall *pending_new;
112 Ethumb_Client_Connect_Cb cb;
114 Eina_Free_Cb free_data;
116 Eina_List *pending_add;
117 Eina_List *pending_remove;
118 Eina_List *pending_gen;
119 DBusPendingCall *pending_clear;
120 DBusPendingCall *pending_setup;
122 Ethumb_Client_Die_Cb cb;
124 Eina_Free_Cb free_data;
126 const char *object_path;
130 Eina_Bool connected : 1;
131 Eina_Bool server_started : 1;
134 struct _ethumb_pending_add
140 const char *thumb_key;
141 Ethumb_Client_Generate_Cb generated_cb;
143 Eina_Free_Cb free_data;
144 DBusPendingCall *pending_call;
145 Ethumb_Client *client;
148 struct _ethumb_pending_remove
151 Ethumb_Client_Generate_Cancel_Cb cancel_cb;
153 Eina_Free_Cb free_data;
154 DBusPendingCall *pending_call;
155 Ethumb_Client *client;
158 struct _ethumb_pending_gen
164 const char *thumb_key;
165 Ethumb_Client_Generate_Cb generated_cb;
167 Eina_Free_Cb free_data;
170 typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists;
172 struct _Ethumb_Async_Exists
176 Ethumb *dup; /* We will work on that one to prevent race and lock */
178 Eina_List *callbacks;
179 Ecore_Thread *thread;
182 struct _Ethumb_Exists
184 Ethumb_Async_Exists *parent;
185 Ethumb_Client *client;
186 Ethumb *dup; /* We don't want to loose parameters so keep them around */
188 Ethumb_Client_Thumb_Exists_Cb exists_cb;
192 static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
193 static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
194 static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
195 static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
196 static const char fdo_interface[] = "org.freedesktop.DBus";
197 static const char fdo_bus_name[] = "org.freedesktop.DBus";
198 static const char fdo_path[] = "/org/freedesktop/DBus";
200 static int _initcount = 0;
201 static Eina_Hash *_exists_request = NULL;
203 static void _ethumb_client_generated_cb(void *data, DBusMessage *msg);
204 static void _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err);
207 __dbus_callback_check_and_init(const char *file, int line, const char *function, DBusMessage *msg, DBusMessageIter *itr, DBusError *err)
211 ERR("%s:%d:%s() callback without message arguments!",
212 file, line, function);
215 ERR("%s:%d:%s() an error was reported by server: "
216 "name=\"%s\", message=\"%s\"",
217 file, line, function, err->name, err->message);
222 if (!dbus_message_iter_init(msg, itr))
224 ERR("%s:%d:%s() could not init iterator.",
225 file, line, function);
232 #define _dbus_callback_check_and_init(msg, itr, err) \
233 __dbus_callback_check_and_init(__FILE__, __LINE__, __FUNCTION__, \
237 __dbus_iter_type_check(int type, int expected, const char *expected_name)
239 if (type == expected)
242 ERR("expected type %s (%c) but got %c instead!",
243 expected_name, expected, type);
247 #define _dbus_iter_type_check(t, e) __dbus_iter_type_check(t, e, #e)
249 #define CHECK_NULL_RETURN(ptr, ...) \
254 CRITICAL("%s == NULL!", #ptr); \
255 return __VA_ARGS__; \
261 _ethumb_client_free(Ethumb_Client *client)
265 if (!client->connected)
268 EINA_LIST_FREE(client->pending_add, data)
270 struct _ethumb_pending_add *pending = data;
271 eina_stringshare_del(pending->file);
272 eina_stringshare_del(pending->key);
273 eina_stringshare_del(pending->thumb);
274 eina_stringshare_del(pending->thumb_key);
275 dbus_pending_call_cancel(pending->pending_call);
276 dbus_pending_call_unref(pending->pending_call);
277 if (pending->free_data)
278 pending->free_data(pending->data);
282 EINA_LIST_FREE(client->pending_gen, data)
284 struct _ethumb_pending_gen *pending = data;
285 eina_stringshare_del(pending->file);
286 eina_stringshare_del(pending->key);
287 eina_stringshare_del(pending->thumb);
288 eina_stringshare_del(pending->thumb_key);
289 if (pending->free_data)
290 pending->free_data(pending->data);
294 EINA_LIST_FREE(client->pending_remove, data)
296 struct _ethumb_pending_remove *pending = data;
297 dbus_pending_call_cancel(pending->pending_call);
298 dbus_pending_call_unref(pending->pending_call);
299 if (pending->free_data)
300 pending->free_data(pending->data);
304 if (client->pending_clear)
306 dbus_pending_call_cancel(client->pending_clear);
307 dbus_pending_call_unref(client->pending_clear);
311 if (client->object_path)
312 eina_stringshare_del(client->object_path);
314 if (client->pending_new)
315 dbus_pending_call_cancel(client->pending_new);
317 if (client->unique_name)
318 eina_stringshare_del(client->unique_name);
320 if (client->pending_get_name_owner)
321 dbus_pending_call_cancel(client->pending_get_name_owner);
323 if (client->pending_start_service_by_name)
324 dbus_pending_call_cancel(client->pending_start_service_by_name);
326 if (client->old_ethumb_conf)
327 ethumb_free(client->old_ethumb_conf);
329 ethumb_free(client->ethumb);
331 e_dbus_signal_handler_del(client->conn, client->name_owner_changed_handler);
332 if (client->connected)
333 e_dbus_signal_handler_del(client->conn, client->generated_signal);
334 e_dbus_connection_close(client->conn);
336 if (client->connect.free_data)
337 client->connect.free_data(client->connect.data);
338 if (client->die.free_data)
339 client->die.free_data(client->die.data);
345 _ethumb_async_delete(void *data)
347 Ethumb_Async_Exists *async = data;
349 assert(async->callbacks == NULL);
350 assert(async->thread == NULL);
352 ethumb_free(async->dup);
353 eina_stringshare_del(async->path);
359 _ethumb_client_name_owner_changed(void *data, DBusMessage *msg)
362 const char *name, *from, *to;
363 Ethumb_Client *client = data;
365 dbus_error_init(&err);
366 if (!dbus_message_get_args(msg, &err,
367 DBUS_TYPE_STRING, &name,
368 DBUS_TYPE_STRING, &from,
369 DBUS_TYPE_STRING, &to,
372 ERR("could not get NameOwnerChanged arguments: %s: %s",
373 err.name, err.message);
374 dbus_error_free(&err);
380 if (strcmp(name, _ethumb_dbus_bus_name) != 0)
383 DBG("NameOwnerChanged from=[%s] to=[%s]", from, to);
385 if (from[0] != '\0' && to[0] == '\0')
387 DBG("exit ethumbd at %s", from);
388 if (client->unique_name && strcmp(client->unique_name, from) != 0)
389 WRN("%s was not the known name %s, ignored.",
390 from, client->unique_name);
391 else if(client->unique_name)
393 ERR("server exit!!!");
396 client->die.cb(client->die.data, client);
397 client->die.cb = NULL;
399 if (client->die.free_data)
401 client->die.free_data(client->die.data);
402 client->die.free_data = NULL;
403 client->die.data = NULL;
408 DBG("unknown change from %s to %s", from, to);
412 _ethumb_client_report_connect(Ethumb_Client *client, Eina_Bool success)
414 if (!client->connect.cb)
416 ERR("already called?!");
420 client->connect.cb(client->connect.data, client, success);
421 if (client->connect.free_data)
423 client->connect.free_data(client->connect.data);
424 client->connect.free_data = NULL;
426 client->connect.cb = NULL;
427 client->connect.data = NULL;
431 _ethumb_client_new_cb(void *data, DBusMessage *msg, DBusError *error)
433 DBusMessageIter iter;
436 Ethumb_Client *client = data;
438 client->pending_new = NULL;
440 if (!_dbus_callback_check_and_init(msg, &iter, error))
442 t = dbus_message_iter_get_arg_type(&iter);
443 if (!_dbus_iter_type_check(t, DBUS_TYPE_OBJECT_PATH))
446 dbus_message_iter_get_basic(&iter, &opath);
447 if (opath[0] == '\0')
450 client->object_path = eina_stringshare_add(opath);
452 client->generated_signal = e_dbus_signal_handler_add(
453 client->conn, _ethumb_dbus_bus_name, opath,
454 _ethumb_dbus_objects_interface, "generated",
455 _ethumb_client_generated_cb, client);
457 _ethumb_client_report_connect(client, 1);
461 _ethumb_client_report_connect(client, 0);
465 _ethumb_client_call_new(Ethumb_Client *client)
469 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name, _ethumb_dbus_path,
470 _ethumb_dbus_interface, "new");
471 client->pending_new = e_dbus_message_send(client->conn, msg,
472 _ethumb_client_new_cb, -1,
474 dbus_message_unref(msg);
478 _ethumb_client_start_server_cb(void *data, DBusMessage *msg, DBusError *err)
480 Ethumb_Client *client = data;
481 DBusMessageIter iter;
485 client->pending_start_service_by_name = NULL;
487 if (!_dbus_callback_check_and_init(msg, &iter, err))
490 t = dbus_message_iter_get_arg_type(&iter);
491 if (!_dbus_iter_type_check(t, DBUS_TYPE_UINT32))
494 dbus_message_iter_get_basic(&iter, &ret);
495 if ((ret != 1) && (ret != 2))
497 ERR("Error starting Ethumbd DBus service by its name: retcode %u",
502 client->server_started = 1;
503 DBG("Ethumbd DBus service started successfully (%d), now request its name",
506 if (client->pending_get_name_owner)
508 DBG("already requesting name owner, cancel and try again");
509 dbus_pending_call_cancel(client->pending_get_name_owner);
512 client->pending_get_name_owner = e_dbus_get_name_owner
513 (client->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
515 if (!client->pending_get_name_owner)
517 ERR("could not create a get_name_owner request.");
524 ERR("failed to start Ethumbd DBus service by its name.");
525 _ethumb_client_report_connect(client, 0);
529 _ethumb_client_start_server(Ethumb_Client *client)
531 if (client->pending_start_service_by_name)
533 DBG("already pending start service by name.");
537 client->server_started = 0;
538 client->pending_start_service_by_name = e_dbus_start_service_by_name
539 (client->conn, _ethumb_dbus_bus_name, 0, _ethumb_client_start_server_cb,
541 if (!client->pending_start_service_by_name)
543 ERR("could not start service by name!");
544 _ethumb_client_report_connect(client, 0);
549 _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err)
551 DBusMessageIter iter;
553 Ethumb_Client *client = data;
556 client->pending_get_name_owner = NULL;
558 if (dbus_error_is_set(err) && (!client->server_started))
560 DBG("could not find server (%s), try to start it...", err->message);
561 _ethumb_client_start_server(client);
565 if (!_dbus_callback_check_and_init(msg, &iter, err))
568 t = dbus_message_iter_get_arg_type(&iter);
569 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
572 dbus_message_iter_get_basic(&iter, &uid);
575 ERR("no name owner!");
579 DBG("unique name = %s", uid);
580 client->unique_name = eina_stringshare_add(uid);
582 _ethumb_client_call_new(client);
583 client->connected = 1;
587 _ethumb_client_report_connect(client, 0);
591 _ethumb_client_exists_heavy(void *data, Ecore_Thread *thread __UNUSED__)
593 Ethumb_Async_Exists *async = data;
595 ethumb_thumb_hash(async->dup);
599 _ethumb_client_exists_end(void *data, Ecore_Thread *thread __UNUSED__)
601 Ethumb_Async_Exists *async = data;
604 EINA_LIST_FREE(async->callbacks, cb)
608 ethumb_thumb_hash_copy(cb->dup, async->dup);
609 tmp = cb->client->ethumb;
610 cb->client->ethumb = cb->dup;
612 cb->exists_cb(cb->client, cb,
613 ethumb_exists(cb->client->ethumb),
616 cb->client->ethumb = tmp;
617 EINA_REFCOUNT_UNREF(cb->client)
618 _ethumb_client_free(cb->client);
619 ethumb_free(cb->dup);
623 async->thread = NULL;
625 eina_hash_del(_exists_request, async->path, async);
633 * @brief Initialize the Ethumb_Client library.
635 * @return 1 or greater on success, 0 on error.
637 * This function sets up all the Ethumb_Client module dependencies. It
638 * returns 0 on failure (that is, when one of the dependency fails to
639 * initialize), otherwise it returns the number of times it has
640 * already been called.
642 * When Ethumb_Client is not used anymore, call
643 * ethumb_client_shutdown() to shut down the Ethumb_Client library.
645 * @see ethumb_client_shutdown()
646 * @see ethumb_client_connect()
647 * @see @ref tutorial_ethumb_client
650 ethumb_client_init(void)
657 fprintf(stderr, "ERROR: Could not initialize log module.\n");
660 _log_dom = eina_log_domain_register("ethumb_client", EINA_COLOR_YELLOW);
663 EINA_LOG_ERR("Could not register log domain: ethumb_client");
671 _exists_request = eina_hash_stringshared_new(_ethumb_async_delete);
677 * @brief Shut down the Ethumb_Client library.
679 * @return 0 when everything is shut down, 1 or greater if there are
680 * other users of the Ethumb_Client library pending shutdown.
682 * This function shuts down the Ethumb_Client library. It returns 0
683 * when it has been called the same number of times than
684 * ethumb_client_init(). In that case it shut down all the
685 * Ethumb_Client modules dependencies.
687 * Once this function succeeds (that is, @c 0 is returned), you must
688 * not call any of the Eina function anymore. You must call
689 * ethumb_client_init() again to use the Ethumb_Client functions
693 ethumb_client_shutdown(void)
699 /* should find a non racy solution to closing all pending exists request */
700 eina_hash_free(_exists_request);
701 _exists_request = NULL;
705 eina_log_domain_unregister(_log_dom);
712 * Connects to Ethumb server and return the client instance.
714 * This is the "constructor" of Ethumb_Client, where everything
717 * If server was down, it is tried to start it using DBus activation,
718 * then the connection is retried.
720 * This call is asynchronous and will not block, instead it will be in
721 * "not connected" state until @a connect_cb is called with either
722 * success or failure. On failure, then no methods should be
723 * called. On success you're now able to setup and then ask generation
726 * Usually you should listen for server death/disconenction with
727 * ethumb_client_on_server_die_callback_set().
729 * @param connect_cb function to call to report connection success or
730 * failure. Do not call any other ethumb_client method until
731 * this function returns. The first received parameter is the
732 * given argument @a data. Must @b not be @c NULL. This
733 * function will not be called if user explicitly calls
734 * ethumb_client_disconnect().
735 * @param data context to give back to @a connect_cb. May be @c NULL.
736 * @param free_data function used to release @a data resources, if
737 * any. May be @c NULL. If this function exists, it will be
738 * called immediately after @a connect_cb is called or if user
739 * explicitly calls ethumb_client_disconnect() before such
740 * (that is, don't rely on @a data after @a connect_cb was
743 * @return client instance or NULL if failed. If @a connect_cb is
744 * missing it returns @c NULL. If it fail for other
745 * conditions, @c NULL is also returned and @a connect_cb is
746 * called with @c success=EINA_FALSE. The client instance is
747 * not ready to be used until @a connect_cb is called.
750 ethumb_client_connect(Ethumb_Client_Connect_Cb connect_cb, const void *data, Eina_Free_Cb free_data)
752 Ethumb_Client *eclient;
754 EINA_SAFETY_ON_NULL_RETURN_VAL(connect_cb, NULL);
756 eclient = calloc(1, sizeof(*eclient));
759 ERR("could not allocate Ethumb_Client structure.");
763 eclient->old_ethumb_conf = NULL;
764 eclient->connect.cb = connect_cb;
765 eclient->connect.data = (void *)data;
766 eclient->connect.free_data = free_data;
768 eclient->ethumb = ethumb_new();
769 if (!eclient->ethumb)
771 ERR("could not create ethumb handler.");
775 eclient->conn = e_dbus_bus_get(DBUS_BUS_SESSION);
778 ERR("could not connect to session bus.");
782 eclient->name_owner_changed_handler = e_dbus_signal_handler_add(
783 eclient->conn, fdo_bus_name, fdo_path, fdo_interface,
784 "NameOwnerChanged", _ethumb_client_name_owner_changed, eclient);
786 eclient->pending_get_name_owner = e_dbus_get_name_owner(
787 eclient->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
789 if (!eclient->pending_get_name_owner)
791 ERR("could not create a get_name_owner request.");
795 EINA_REFCOUNT_INIT(eclient);
800 ethumb_free(eclient->ethumb);
804 connect_cb((void *)data, NULL, EINA_FALSE);
806 free_data((void *)data);
811 * Disconnect the client, releasing all client resources.
813 * This is the destructor of Ethumb_Client, after it's disconnected
814 * the client handle is now gone and should not be used.
816 * @param client client instance to be destroyed. Must @b not be @c
820 ethumb_client_disconnect(Ethumb_Client *client)
822 EINA_SAFETY_ON_NULL_RETURN(client);
824 EINA_REFCOUNT_UNREF(client)
825 _ethumb_client_free(client);
829 * Sets the callback to report server died.
831 * When server dies there is nothing you can do, just release
832 * resources with ethumb_client_disconnect() and probably try to
835 * Usually you should set this callback and handle this case, it does
838 * @param client the client instance to monitor. Must @b not be @c
840 * @param server_die_cb function to call back when server dies. The
841 * first parameter will be the argument @a data. May be @c
843 * @param data context to give back to @a server_die_cb. May be @c
845 * @param free_data used to release @a data resources after @a
846 * server_die_cb is called or user calls
847 * ethumb_client_disconnect().
850 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)
852 EINA_SAFETY_ON_NULL_RETURN(client);
854 if (client->die.free_data)
855 client->die.free_data(client->die.data);
857 client->die.cb = server_die_cb;
858 client->die.data = (void *)data;
859 client->die.free_data = free_data;
867 _ethumb_client_ethumb_setup_cb(void *data, DBusMessage *msg, DBusError *error)
869 DBusMessageIter iter;
871 dbus_bool_t result = 0;
872 Ethumb_Client *client = data;
874 client->pending_setup = NULL;
876 if (!_dbus_callback_check_and_init(msg, &iter, error))
879 t = dbus_message_iter_get_arg_type(&iter);
880 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
883 dbus_message_iter_get_basic(&iter, &result);
887 _ethumb_client_dbus_get_bytearray(DBusMessageIter *iter)
891 DBusMessageIter riter;
894 el_type = dbus_message_iter_get_element_type(iter);
895 if (el_type != DBUS_TYPE_BYTE)
897 ERR("not an byte array element.");
901 dbus_message_iter_recurse(iter, &riter);
902 dbus_message_iter_get_fixed_array(&riter, &result, &length);
904 if (result[0] == '\0')
907 return eina_stringshare_add(result);
911 _ethumb_client_dbus_append_bytearray(DBusMessageIter *iter, const char *string)
913 DBusMessageIter viter;
918 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &viter);
919 dbus_message_iter_append_fixed_array(&viter, DBUS_TYPE_BYTE, &string,
921 dbus_message_iter_close_container(iter, &viter);
929 * Send setup to server.
931 * This method is called automatically by ethumb_client_generate() if
932 * any property was changed. No need to call it manually.
934 * @param client client instance. Must @b not be @c NULL and client
935 * must be connected (after connected_cb is called).
938 ethumb_client_ethumb_setup(Ethumb_Client *client)
941 DBusMessageIter iter, aiter, diter, viter, vaiter;
942 Ethumb *e = client->ethumb;
944 dbus_int32_t tw, th, format, aspect, orientation, quality, compress;
947 const char *theme_file, *group, *swallow;
948 const char *directory, *category;
949 double video_time, video_start, video_interval;
950 dbus_int32_t video_ntimes, video_fps, document_page;
952 EINA_SAFETY_ON_NULL_RETURN(client);
953 EINA_SAFETY_ON_FALSE_RETURN(client->connected);
955 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
957 _ethumb_dbus_objects_interface,
959 dbus_message_iter_init_append(msg, &iter);
960 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &aiter);
965 #define _open_variant_iter(str_entry, str_type, end_iter) \
967 dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &diter); \
968 dbus_message_iter_append_basic(&diter, DBUS_TYPE_STRING, &entry); \
969 dbus_message_iter_open_container(&diter, DBUS_TYPE_VARIANT, str_type, \
972 #define _close_variant_iter(end_iter) \
973 dbus_message_iter_close_container(&diter, &end_iter); \
974 dbus_message_iter_close_container(&aiter, &diter);
979 /* starting array elements */
981 _open_variant_iter("size", "(ii)", viter);
982 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
983 ethumb_thumb_size_get(e, &tw, &th);
984 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &tw);
985 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &th);
986 dbus_message_iter_close_container(&viter, &vaiter);
987 _close_variant_iter(viter);
989 _open_variant_iter("format", "i", viter);
990 format = ethumb_thumb_format_get(e);
991 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &format);
992 _close_variant_iter(viter);
994 _open_variant_iter("aspect", "i", viter);
995 aspect = ethumb_thumb_aspect_get(e);
996 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &aspect);
997 _close_variant_iter(viter);
999 _open_variant_iter("orientation", "i", viter);
1000 orientation = ethumb_thumb_orientation_get(e);
1001 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &orientation);
1002 _close_variant_iter(viter);
1004 _open_variant_iter("crop", "(dd)", viter);
1005 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
1006 ethumb_thumb_crop_align_get(e, &cx, &cy);
1008 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
1010 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
1011 dbus_message_iter_close_container(&viter, &vaiter);
1012 _close_variant_iter(viter);
1014 _open_variant_iter("quality", "i", viter);
1015 quality = ethumb_thumb_quality_get(e);
1016 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &quality);
1017 _close_variant_iter(viter);
1019 _open_variant_iter("compress", "i", viter);
1020 compress = ethumb_thumb_compress_get(e);
1021 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &compress);
1022 _close_variant_iter(viter);
1024 _open_variant_iter("frame", "(ayayay)", viter);
1025 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
1026 ethumb_frame_get(e, &theme_file, &group, &swallow);
1027 _ethumb_client_dbus_append_bytearray(&vaiter, theme_file);
1028 _ethumb_client_dbus_append_bytearray(&vaiter, group);
1029 _ethumb_client_dbus_append_bytearray(&vaiter, swallow);
1030 dbus_message_iter_close_container(&viter, &vaiter);
1031 _close_variant_iter(viter);
1033 _open_variant_iter("directory", "ay", viter);
1034 directory = ethumb_thumb_dir_path_get(e);
1035 _ethumb_client_dbus_append_bytearray(&viter, directory);
1036 _close_variant_iter(viter);
1038 _open_variant_iter("category", "ay", viter);
1039 category = ethumb_thumb_category_get(e);
1040 _ethumb_client_dbus_append_bytearray(&viter, category);
1041 _close_variant_iter(viter);
1043 _open_variant_iter("video_time", "d", viter);
1044 video_time = ethumb_video_time_get(e);
1045 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time);
1046 _close_variant_iter(viter);
1048 _open_variant_iter("video_start", "d", viter);
1049 video_start = ethumb_video_start_get(e);
1050 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start);
1051 _close_variant_iter(viter);
1053 _open_variant_iter("video_interval", "d", viter);
1054 video_interval = ethumb_video_interval_get(e);
1055 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval);
1056 _close_variant_iter(viter);
1058 _open_variant_iter("video_ntimes", "u", viter);
1059 video_ntimes = ethumb_video_ntimes_get(e);
1060 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_ntimes);
1061 _close_variant_iter(viter);
1063 _open_variant_iter("video_fps", "u", viter);
1064 video_fps = ethumb_video_fps_get(e);
1065 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_fps);
1066 _close_variant_iter(viter);
1068 _open_variant_iter("document_page", "u", viter);
1069 document_page = ethumb_document_page_get(e);
1070 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &document_page);
1071 _close_variant_iter(viter);
1073 #undef _open_variant_iter
1074 #undef _close_variant_iter
1076 dbus_message_iter_close_container(&iter, &aiter);
1078 client->pending_setup = e_dbus_message_send(client->conn, msg,
1079 _ethumb_client_ethumb_setup_cb,
1081 dbus_message_unref(msg);
1089 _ethumb_client_generated_cb(void *data, DBusMessage *msg)
1091 DBusMessageIter iter;
1092 dbus_int32_t id = -1;
1093 const char *thumb = NULL;
1094 const char *thumb_key = NULL;
1095 Ethumb_Client *client = data;
1097 dbus_bool_t success;
1100 struct _ethumb_pending_gen *pending;
1102 dbus_message_iter_init(msg, &iter);
1104 t = dbus_message_iter_get_arg_type(&iter);
1105 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1107 dbus_message_iter_get_basic(&iter, &id);
1108 dbus_message_iter_next(&iter);
1110 t = dbus_message_iter_get_arg_type(&iter);
1111 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1113 thumb = _ethumb_client_dbus_get_bytearray(&iter);
1114 dbus_message_iter_next(&iter);
1116 t = dbus_message_iter_get_arg_type(&iter);
1117 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1119 thumb_key = _ethumb_client_dbus_get_bytearray(&iter);
1120 dbus_message_iter_next(&iter);
1122 t = dbus_message_iter_get_arg_type(&iter);
1123 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1125 dbus_message_iter_get_basic(&iter, &success);
1128 l = client->pending_gen;
1132 if (pending->id == id)
1142 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1143 if (pending->generated_cb)
1144 pending->generated_cb(pending->data, client, id,
1145 pending->file, pending->key,
1146 pending->thumb, pending->thumb_key,
1148 if (pending->free_data)
1149 pending->free_data(pending->data);
1150 eina_stringshare_del(pending->file);
1151 eina_stringshare_del(pending->key);
1152 eina_stringshare_del(pending->thumb);
1153 eina_stringshare_del(pending->thumb_key);
1158 if (thumb) eina_stringshare_del(thumb);
1159 if (thumb_key) eina_stringshare_del(thumb_key);
1163 _ethumb_client_queue_add_cb(void *data, DBusMessage *msg, DBusError *error)
1165 DBusMessageIter iter;
1167 dbus_int32_t id = -1;
1168 struct _ethumb_pending_add *pending = data;
1169 struct _ethumb_pending_gen *generating;
1170 Ethumb_Client *client = pending->client;
1172 client->pending_add = eina_list_remove(client->pending_add, pending);
1174 if (!_dbus_callback_check_and_init(msg, &iter, error))
1177 t = dbus_message_iter_get_arg_type(&iter);
1178 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1181 dbus_message_iter_get_basic(&iter, &id);
1183 generating = calloc(1, sizeof(*generating));
1184 generating->id = id;
1185 generating->file = pending->file;
1186 generating->key = pending->key;
1187 generating->thumb = pending->thumb;
1188 generating->thumb_key = pending->thumb_key;
1189 generating->generated_cb = pending->generated_cb;
1190 generating->data = pending->data;
1191 generating->free_data = pending->free_data;
1192 client->pending_gen = eina_list_append(client->pending_gen, generating);
1199 _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)
1202 DBusMessageIter iter;
1203 struct _ethumb_pending_add *pending;
1205 pending = calloc(1, sizeof(*pending));
1206 pending->id = client->id_count;
1207 pending->file = eina_stringshare_add(file);
1208 pending->key = eina_stringshare_add(key);
1209 pending->thumb = eina_stringshare_add(thumb);
1210 pending->thumb_key = eina_stringshare_add(thumb_key);
1211 pending->generated_cb = generated_cb;
1212 pending->data = (void *)data;
1213 pending->free_data = free_data;
1214 pending->client = client;
1216 client->id_count = (client->id_count + 1) % MAX_ID;
1218 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1219 client->object_path,
1220 _ethumb_dbus_objects_interface,
1223 dbus_message_iter_init_append(msg, &iter);
1224 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &pending->id);
1225 _ethumb_client_dbus_append_bytearray(&iter, file);
1226 _ethumb_client_dbus_append_bytearray(&iter, key);
1227 _ethumb_client_dbus_append_bytearray(&iter, thumb);
1228 _ethumb_client_dbus_append_bytearray(&iter, thumb_key);
1230 pending->pending_call = e_dbus_message_send(client->conn, msg,
1231 _ethumb_client_queue_add_cb,
1233 client->pending_add = eina_list_append(client->pending_add, pending);
1234 dbus_message_unref(msg);
1240 _ethumb_client_queue_remove_cb(void *data, DBusMessage *msg, DBusError *error)
1242 DBusMessageIter iter;
1244 dbus_bool_t success = 0;
1245 struct _ethumb_pending_remove *pending = data;
1246 Ethumb_Client *client = pending->client;
1248 client->pending_remove = eina_list_remove(client->pending_remove, pending);
1250 if (!_dbus_callback_check_and_init(msg, &iter, error))
1253 t = dbus_message_iter_get_arg_type(&iter);
1254 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1257 dbus_message_iter_get_basic(&iter, &success);
1260 if (pending->cancel_cb)
1261 pending->cancel_cb(pending->data, success);
1262 if (pending->free_data)
1263 pending->free_data(pending->data);
1271 * Ask server to cancel generation of thumbnail.
1273 * @param client client instance. Must @b not be @c NULL and client
1274 * must be connected (after connected_cb is called).
1275 * @param id valid id returned by ethumb_client_generate()
1276 * @param cancel_cb function to report cancellation results.
1277 * @param data context argument to give back to @a cancel_cb. May be
1279 * @param data context to give back to @a cancel_cb. May be @c
1281 * @param free_data used to release @a data resources after @a
1282 * cancel_cb is called or user calls
1283 * ethumb_client_disconnect().
1286 ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, const void *data, Eina_Free_Cb free_data)
1289 struct _ethumb_pending_remove *pending;
1292 dbus_int32_t id32 = id;
1293 EINA_SAFETY_ON_NULL_RETURN(client);
1294 EINA_SAFETY_ON_FALSE_RETURN(id >= 0);
1296 pending = calloc(1, sizeof(*pending));
1298 pending->cancel_cb = cancel_cb;
1299 pending->data = (void *)data;
1300 pending->free_data = free_data;
1301 pending->client = client;
1303 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1304 client->object_path,
1305 _ethumb_dbus_objects_interface,
1308 dbus_message_append_args(msg, DBUS_TYPE_INT32, &id32, DBUS_TYPE_INVALID);
1309 pending->pending_call = e_dbus_message_send(client->conn, msg,
1310 _ethumb_client_queue_remove_cb,
1312 client->pending_remove = eina_list_append(client->pending_remove, pending);
1315 l = client->pending_add;
1318 struct _ethumb_pending_add *pending_add = l->data;
1319 if (pending_add->id != id32)
1324 client->pending_add = eina_list_remove_list(client->pending_add, l);
1325 eina_stringshare_del(pending_add->file);
1326 eina_stringshare_del(pending_add->key);
1327 eina_stringshare_del(pending_add->thumb);
1328 eina_stringshare_del(pending_add->thumb_key);
1329 dbus_pending_call_cancel(pending_add->pending_call);
1330 dbus_pending_call_unref(pending_add->pending_call);
1331 if (pending_add->free_data)
1332 pending_add->free_data(pending_add->data);
1341 l = client->pending_gen;
1344 struct _ethumb_pending_gen *pending_gen = l->data;
1345 if (pending_gen->id != id32)
1350 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1351 eina_stringshare_del(pending_gen->file);
1352 eina_stringshare_del(pending_gen->key);
1353 eina_stringshare_del(pending_gen->thumb);
1354 eina_stringshare_del(pending_gen->thumb_key);
1355 if (pending_gen->free_data)
1356 pending_gen->free_data(pending_gen->data);
1362 dbus_message_unref(msg);
1369 _ethumb_client_queue_clear_cb(void *data, DBusMessage *msg __UNUSED__, DBusError *error __UNUSED__)
1371 Ethumb_Client *client = data;
1373 client->pending_clear = NULL;
1380 * Ask server to cancel generation of all thumbnails.
1382 * @param client client instance. Must @b not be @c NULL and client
1383 * must be connected (after connected_cb is called).
1385 * @see ethumb_client_generate_cancel()
1388 ethumb_client_generate_cancel_all(Ethumb_Client *client)
1392 EINA_SAFETY_ON_NULL_RETURN(client);
1394 if (client->pending_clear)
1397 EINA_LIST_FREE(client->pending_add, data)
1399 struct _ethumb_pending_add *pending = data;
1400 eina_stringshare_del(pending->file);
1401 eina_stringshare_del(pending->key);
1402 eina_stringshare_del(pending->thumb);
1403 eina_stringshare_del(pending->thumb_key);
1404 dbus_pending_call_cancel(pending->pending_call);
1405 dbus_pending_call_unref(pending->pending_call);
1406 if (pending->free_data)
1407 pending->free_data(pending->data);
1411 EINA_LIST_FREE(client->pending_gen, data)
1413 struct _ethumb_pending_gen *pending = data;
1414 eina_stringshare_del(pending->file);
1415 eina_stringshare_del(pending->key);
1416 eina_stringshare_del(pending->thumb);
1417 eina_stringshare_del(pending->thumb_key);
1418 if (pending->free_data)
1419 pending->free_data(pending->data);
1423 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1424 client->object_path,
1425 _ethumb_dbus_objects_interface,
1428 client->pending_clear = e_dbus_message_send(client->conn, msg,
1429 _ethumb_client_queue_clear_cb,
1432 dbus_message_unref(msg);
1436 * Configure future requests to use FreeDesktop.Org preset.
1438 * This is a preset to provide freedesktop.org (fdo) standard
1439 * compliant thumbnails. That is, files are stored as JPEG under
1440 * ~/.thumbnails/SIZE, with size being either normal (128x128) or
1443 * @param client the client instance to use. Must @b not be @c
1444 * NULL. May be pending connected (can be called before @c
1446 * @param s size identifier, either #ETHUMB_THUMB_NORMAL (0) or
1447 * #ETHUMB_THUMB_LARGE (1).
1449 * @see ethumb_client_size_set()
1450 * @see ethumb_client_aspect_set()
1451 * @see ethumb_client_crop_align_set()
1452 * @see ethumb_client_category_set()
1453 * @see ethumb_client_dir_path_set()
1456 ethumb_client_fdo_set(Ethumb_Client *client, Ethumb_Thumb_FDO_Size s)
1458 EINA_SAFETY_ON_NULL_RETURN(client);
1460 if (!client->old_ethumb_conf)
1461 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1462 ethumb_thumb_fdo_set(client->ethumb, s);
1466 * Configure future request to use custom size.
1468 * @param client the client instance to use. Must @b not be @c
1469 * NULL. May be pending connected (can be called before @c
1471 * @param tw width, default is 128.
1472 * @param th height, default is 128.
1475 ethumb_client_size_set(Ethumb_Client *client, int tw, int th)
1477 EINA_SAFETY_ON_NULL_RETURN(client);
1479 if (!client->old_ethumb_conf)
1480 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1481 ethumb_thumb_size_set(client->ethumb, tw, th);
1485 * Retrieve future request to use custom size.
1487 * @param client the client instance to use. Must @b not be @c
1488 * NULL. May be pending connected (can be called before @c
1490 * @param tw where to return width. May be @c NULL.
1491 * @param th where to return height. May be @c NULL.
1494 ethumb_client_size_get(const Ethumb_Client *client, int *tw, int *th)
1498 EINA_SAFETY_ON_NULL_RETURN(client);
1500 ethumb_thumb_size_get(client->ethumb, tw, th);
1504 * Configure format to use for future requests.
1506 * @param client the client instance to use. Must @b not be @c
1507 * NULL. May be pending connected (can be called before @c
1509 * @param f format identifier to use, either #ETHUMB_THUMB_FDO (0),
1510 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2). Default is FDO.
1513 ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f)
1515 EINA_SAFETY_ON_NULL_RETURN(client);
1517 if (!client->old_ethumb_conf)
1518 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1519 ethumb_thumb_format_set(client->ethumb, f);
1523 * Retrieve format to use for future requests.
1525 * @param client the client instance to use. Must @b not be @c
1526 * NULL. May be pending connected (can be called before @c
1529 * @return format identifier to use, either #ETHUMB_THUMB_FDO (0),
1530 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2).
1532 EAPI Ethumb_Thumb_Format
1533 ethumb_client_format_get(const Ethumb_Client *client)
1535 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1537 return ethumb_thumb_format_get(client->ethumb);
1541 * Configure aspect mode to use.
1543 * If aspect is kept (#ETHUMB_THUMB_KEEP_ASPECT), then image will be
1544 * rescaled so the largest dimension is not bigger than it's specified
1545 * size (see ethumb_client_size_get()) and the other dimension is
1546 * resized in the same proportion. Example: size is 256x256, image is
1547 * 1000x500, resulting thumbnail is 256x128.
1549 * If aspect is ignored (#ETHUMB_THUMB_IGNORE_ASPECT), then image will
1550 * be distorted to match required thumbnail size. Example: size is
1551 * 256x256, image is 1000x500, resulting thumbnail is 256x256.
1553 * If crop is required (#ETHUMB_THUMB_CROP), then image will be
1554 * cropped so the smallest dimension is not bigger than its specified
1555 * size (see ethumb_client_size_get()) and the other dimension will
1556 * overflow, not being visible in the final image. How it will
1557 * overflow is speficied by ethumb_client_crop_align_set()
1558 * alignment. Example: size is 256x256, image is 1000x500, crop
1559 * alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
1560 * pixels from left and 250 pixels from right being lost, that is just
1561 * the 500x500 central pixels of image will be considered for scaling.
1563 * @param client the client instance to use. Must @b not be @c
1564 * NULL. May be pending connected (can be called before @c
1566 * @param a aspect mode identifier, either #ETHUMB_THUMB_KEEP_ASPECT (0),
1567 * #ETHUMB_THUMB_IGNORE_ASPECT (1) or #ETHUMB_THUMB_CROP (2).
1570 ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a)
1572 EINA_SAFETY_ON_NULL_RETURN(client);
1574 if (!client->old_ethumb_conf)
1575 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1576 ethumb_thumb_aspect_set(client->ethumb, a);
1580 * Get current aspect in use for requests.
1582 * @param client the client instance to use. Must @b not be @c
1583 * NULL. May be pending connected (can be called before @c
1586 * @return aspect in use for future requests.
1588 EAPI Ethumb_Thumb_Aspect
1589 ethumb_client_aspect_get(const Ethumb_Client *client)
1591 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1593 return ethumb_thumb_aspect_get(client->ethumb);
1597 * Configure orientation to use for future requests.
1599 * Default value is #ETHUMB_THUMB_ORIENT_ORIGINAL: metadata from the file
1600 * will be used to orient pixel data.
1602 * @param client the client instance to use. Must @b not be @c
1603 * NULL. May be pending connected (can be called before @c
1605 * @param f format identifier to use, either #ETHUMB_THUMB_ORIENT_NONE (0),
1606 * #ETHUMB_THUMB_ROTATE_90_CW (1), #ETHUMB_THUMB_ROTATE_180 (2),
1607 * #ETHUMB_THUMB_ROTATE_90_CCW (3), #ETHUMB_THUMB_FLIP_HORIZONTAL (4),
1608 * #ETHUMB_THUMB_FLIP_VERTICAL (5), #ETHUMB_THUMB_FLIP_TRANSPOSE (6),
1609 * #ETHUMB_THUMB_FLIP_TRANSVERSE (7) or #ETHUMB_THUMB_ORIENT_ORIGINAL
1610 * (8). Default is ORIGINAL.
1613 ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o)
1615 EINA_SAFETY_ON_NULL_RETURN(client);
1617 if (!client->old_ethumb_conf)
1618 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1619 ethumb_thumb_orientation_set(client->ethumb, o);
1623 * Get current orientation in use for requests.
1625 * @param client the client instance to use. Must @b not be @c
1626 * NULL. May be pending connected (can be called before @c
1629 * @return orientation in use for future requests.
1631 EAPI Ethumb_Thumb_Orientation
1632 ethumb_client_orientation_get(const Ethumb_Client *client)
1634 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1636 return ethumb_thumb_orientation_get(client->ethumb);
1640 * Configure crop alignment in use for future requests.
1642 * @param client the client instance to use. Must @b not be @c
1643 * NULL. May be pending connected (can be called before @c
1645 * @param x horizontal alignment. 0.0 means left side will be visible
1646 * or right side is being lost. 1.0 means right side will be
1647 * visible or left side is being lost. 0.5 means just center is
1648 * visible, both sides will be lost. Default is 0.5.
1649 * @param y vertical alignment. 0.0 is top visible, 1.0 is bottom
1650 * visible, 0.5 is center visible. Default is 0.5
1653 ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y)
1655 EINA_SAFETY_ON_NULL_RETURN(client);
1657 if (!client->old_ethumb_conf)
1658 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1659 ethumb_thumb_crop_align_set(client->ethumb, x, y);
1663 * Get current crop alignment in use for requests.
1665 * @param client the client instance to use. Must @b not be @c
1666 * NULL. May be pending connected (can be called before @c
1668 * @param x where to return horizontal alignment. May be @c NULL.
1669 * @param y where to return vertical alignment. May be @c NULL.
1672 ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y)
1676 EINA_SAFETY_ON_NULL_RETURN(client);
1678 ethumb_thumb_crop_align_get(client->ethumb, x, y);
1682 * Configure quality to be used in thumbnails.
1684 * @param client the client instance to use. Must @b not be @c
1685 * NULL. May be pending connected (can be called before @c
1687 * @param quality value from 0 to 100, default is 80. The effect
1688 * depends on the format being used, PNG will not use it.
1691 ethumb_client_quality_set(Ethumb_Client *client, int quality)
1693 EINA_SAFETY_ON_NULL_RETURN(client);
1695 ethumb_thumb_quality_set(client->ethumb, quality);
1699 * Get quality to be used in thumbnails.
1701 * @param client the client instance to use. Must @b not be @c
1702 * NULL. May be pending connected (can be called before @c
1705 * @return quality value from 0 to 100, default is 80. The effect
1706 * depends on the format being used, PNG will not use it.
1709 ethumb_client_quality_get(const Ethumb_Client *client)
1711 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1713 return ethumb_thumb_quality_get(client->ethumb);
1717 * Configure compression level used in requests.
1719 * @param client the client instance to use. Must @b not be @c
1720 * NULL. May be pending connected (can be called before @c
1722 * @param compress value from 0 to 9, default is 9. The effect
1723 * depends on the format being used, JPEG will not use it.
1726 ethumb_client_compress_set(Ethumb_Client *client, int compress)
1728 EINA_SAFETY_ON_NULL_RETURN(client);
1730 ethumb_thumb_compress_set(client->ethumb, compress);
1734 * Get compression level used in requests.
1736 * @param client the client instance to use. Must @b not be @c
1737 * NULL. May be pending connected (can be called before @c
1740 * @return compress value from 0 to 9, default is 9. The effect
1741 * depends on the format being used, JPEG will not use it.
1744 ethumb_client_compress_get(const Ethumb_Client *client)
1746 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1748 return ethumb_thumb_compress_get(client->ethumb);
1752 * Set frame to apply to future thumbnails.
1754 * This will create an edje object that will have image swallowed
1755 * in. This can be used to simulate Polaroid or wood frames in the
1756 * generated image. Remeber it is bad to modify the original contents
1757 * of thumbnails, but sometimes it's useful to have it composited and
1758 * avoid runtime overhead.
1760 * @param client the client instance to use. Must @b not be @c
1761 * NULL. May be pending connected (can be called before @c
1763 * @param file file path to edje.
1764 * @param group group inside edje to use.
1765 * @param swallow name of swallow part.
1768 ethumb_client_frame_set(Ethumb_Client *client, const char *file, const char *group, const char *swallow)
1770 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1772 if (!client->old_ethumb_conf)
1773 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1774 return ethumb_frame_set(client->ethumb, file, group, swallow);
1778 * Configure where to store thumbnails in future requests.
1780 * This value will be used to generate thumbnail paths, that is, it
1781 * will be used when ethumb_client_thumb_path_set() was not called
1782 * after last ethumb_client_file_set().
1784 * Note that this is the base, a category is added to this path as a
1785 * sub directory. This is not the final directory where files are
1786 * stored, the thumbnail system will account @b category as well, see
1787 * ethumb_client_category_set().
1789 * As other options, this value will only be applied to future
1792 * @param client the client instance to use. Must @b not be @c
1793 * NULL. May be pending connected (can be called before @c
1795 * @param path base directory where to store thumbnails. Default is
1798 * @see ethumb_client_category_set()
1801 ethumb_client_dir_path_set(Ethumb_Client *client, const char *path)
1803 EINA_SAFETY_ON_NULL_RETURN(client);
1805 if (!client->old_ethumb_conf)
1806 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1807 ethumb_thumb_dir_path_set(client->ethumb, path);
1811 * Get base directory path where to store thumbnails.
1813 * @param client the client instance to use. Must @b not be @c
1814 * NULL. May be pending connected (can be called before @c
1817 * @return pointer to internal string with current path. This string
1818 * should not be modified or freed.
1820 * @see ethumb_client_dir_path_set()
1823 ethumb_client_dir_path_get(const Ethumb_Client *client)
1825 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1827 return ethumb_thumb_dir_path_get(client->ethumb);
1831 * Category directory to store thumbnails.
1833 * This value will be used to generate thumbnail paths, that is, it
1834 * will be used when ethumb_client_thumb_path_set() was not called
1835 * after last ethumb_client_file_set().
1837 * This is a sub-directory inside base directory
1838 * (ethumb_client_dir_path_set()) that creates a namespace to avoid
1839 * different options resulting in the same file.
1841 * As other options, this value will only be applied to future
1844 * @param client the client instance to use. Must @b not be @c
1845 * NULL. May be pending connected (can be called before @c
1847 * @param category category sub directory to store thumbnail. Default
1848 * is either "normal" or "large" for FDO compliant thumbnails
1849 * or WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string
1850 * or @c NULL to use auto generated names.
1852 * @see ethumb_client_dir_path_set()
1855 ethumb_client_category_set(Ethumb_Client *client, const char *category)
1857 EINA_SAFETY_ON_NULL_RETURN(client);
1859 if (!client->old_ethumb_conf)
1860 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1861 ethumb_thumb_category_set(client->ethumb, category);
1865 * Get category sub-directory where to store thumbnails.
1867 * @param client the client instance to use. Must @b not be @c
1868 * NULL. May be pending connected (can be called before @c
1871 * @return pointer to internal string with current path. This string
1872 * should not be modified or freed.
1874 * @see ethumb_client_category_set()
1877 ethumb_client_category_get(const Ethumb_Client *client)
1879 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1881 return ethumb_thumb_category_get(client->ethumb);
1885 * Set the video time (duration) in seconds.
1887 * @param client the client instance to use. Must @b not be @c
1888 * NULL. May be pending connected (can be called before @c
1890 * @param t duration (in seconds). Defaults to 3 seconds.
1893 ethumb_client_video_time_set(Ethumb_Client *client, float t)
1895 EINA_SAFETY_ON_NULL_RETURN(client);
1897 if (!client->old_ethumb_conf)
1898 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1899 ethumb_video_time_set(client->ethumb, t);
1903 * Set initial video position to start thumbnailing, in percentage.
1905 * This is useful to avoid thumbnailing the company/producer logo or
1908 * @param client the client instance to use. Must @b not be @c
1909 * NULL. May be pending connected (can be called before @c
1911 * @param start initial video positon to thumbnail, in percentage (0.0
1912 * to 1.0, inclusive). Defaults to 10% (0.1).
1915 ethumb_client_video_start_set(Ethumb_Client *client, float start)
1917 EINA_SAFETY_ON_NULL_RETURN(client);
1918 EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0);
1919 EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0);
1921 if (!client->old_ethumb_conf)
1922 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1923 ethumb_video_start_set(client->ethumb, start);
1927 * Set the video frame interval, in seconds.
1929 * This is useful for animated thumbnail and will define skip time
1930 * before going to the next frame. Note that video backends might not
1931 * be able to precisely skip that amount as it will depend on various
1932 * factors, including video encoding.
1934 * Although this seems similar to ethumb_client_video_fps_set(), this
1935 * one is the time that will be used to seek. The math is simple, for
1936 * each new frame the video position will be set to:
1937 * ((video_length * start_time) + (interval * current_frame_number)).
1939 * @param client the client instance to use. Must @b not be @c
1940 * NULL. May be pending connected (can be called before @c
1942 * @param interval time between frames, in seconds. Defaults to 0.05
1946 ethumb_client_video_interval_set(Ethumb_Client *client, float interval)
1948 EINA_SAFETY_ON_NULL_RETURN(client);
1950 if (!client->old_ethumb_conf)
1951 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1952 ethumb_video_interval_set(client->ethumb, interval);
1956 * Set the number of frames to thumbnail.
1958 * This is useful for animated thumbnail and will define how many
1959 * frames the generated file will have.
1961 * @param client the client instance to use. Must @b not be @c
1962 * NULL. May be pending connected (can be called before @c
1964 * @param ntimes number of times, must be greater than zero.
1968 ethumb_client_video_ntimes_set(Ethumb_Client *client, unsigned int ntimes)
1970 EINA_SAFETY_ON_NULL_RETURN(client);
1971 EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0);
1973 if (!client->old_ethumb_conf)
1974 client->old_ethumb_conf = ethumb_dup(client->ethumb);
1975 ethumb_video_ntimes_set(client->ethumb, ntimes);
1979 * Set the number of frames per second to thumbnail the video.
1981 * This configures the number of times per seconds the thumbnail will
1982 * use to create thumbnails.
1984 * Although this is similar to ethumb_client_video_interval_set(), it
1985 * is the delay used between calling functions thata generates frames,
1986 * while the other is the time used to skip inside the video.
1988 * @param client the client instance to use. Must @b not be @c
1989 * NULL. May be pending connected (can be called before @c
1991 * @param fps number of frames per second to thumbnail. Must be greater
1992 * than zero. Defaults to 10.
1995 ethumb_client_video_fps_set(Ethumb_Client *client, unsigned int fps)
1997 EINA_SAFETY_ON_NULL_RETURN(client);
1998 EINA_SAFETY_ON_FALSE_RETURN(fps > 0);
2000 if (!client->old_ethumb_conf)
2001 client->old_ethumb_conf = ethumb_dup(client->ethumb);
2002 ethumb_video_fps_set(client->ethumb, fps);
2006 * Set the page number to thumbnail in paged documents.
2008 * @param client the client instance to use. Must @b not be @c
2009 * NULL. May be pending connected (can be called before @c
2011 * @param page page number, defaults to 0 (first).
2014 ethumb_client_document_page_set(Ethumb_Client *client, unsigned int page)
2016 EINA_SAFETY_ON_NULL_RETURN(client);
2018 if (!client->old_ethumb_conf)
2019 client->old_ethumb_conf = ethumb_dup(client->ethumb);
2020 ethumb_document_page_set(client->ethumb, page);
2024 * Set source file to be thumbnailed.
2026 * Calling this function has the side effect of resetting values set
2027 * with ethumb_client_thumb_path_set() or auto-generated with
2028 * ethumb_client_thumb_exists().
2030 * @param client the client instance to use. Must @b not be @c
2031 * NULL. May be pending connected (can be called before @c
2033 * @param path the filesystem path to use. May be @c NULL.
2034 * @param key the extra argument/key inside @a path to read image
2035 * from. This is only used for formats that allow multiple
2036 * resources in one file, like EET or Edje (group name).
2038 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
2041 ethumb_client_file_set(Ethumb_Client *client, const char *path, const char *key)
2043 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
2045 return ethumb_file_set(client->ethumb, path, key);
2049 * Get values set with ethumb_client_file_get()
2051 * @param client the client instance to use. Must @b not be @c
2052 * NULL. May be pending connected (can be called before @c
2054 * @param path where to return configured path. May be @c NULL. If
2055 * not @c NULL, then it will be a pointer to a stringshared
2056 * instance, but @b no references are added (do it with
2057 * eina_stringshare_ref())!
2058 * @param key where to return configured key. May be @c NULL.If not @c
2059 * NULL, then it will be a pointer to a stringshared instance,
2060 * but @b no references are added (do it with
2061 * eina_stringshare_ref())!
2064 ethumb_client_file_get(Ethumb_Client *client, const char **path, const char **key)
2066 if (path) *path = NULL;
2067 if (key) *key = NULL;
2068 EINA_SAFETY_ON_NULL_RETURN(client);
2070 ethumb_file_get(client->ethumb, path, key);
2074 * Reset previously set file to @c NULL.
2076 * @param client the client instance to use. Must @b not be @c
2077 * NULL. May be pending connected (can be called before @c
2081 ethumb_client_file_free(Ethumb_Client *client)
2083 EINA_SAFETY_ON_NULL_RETURN(client);
2085 ethumb_file_free(client->ethumb);
2089 * Set a defined path and key to store the thumbnail.
2091 * If not explicitly given, the thumbnail path will be auto-generated
2092 * by ethumb_client_thumb_exists() or server using configured
2093 * parameters like size, aspect and category.
2095 * Set these to @c NULL to forget previously given values. After
2096 * ethumb_client_file_set() these values will be reset to @c NULL.
2098 * @param client the client instance to use. Must @b not be @c
2099 * NULL. May be pending connected (can be called before @c
2101 * @param path force generated thumbnail to the exact given path. If
2102 * @c NULL, then reverts back to auto-generation.
2103 * @param key force generated thumbnail to the exact given key. If
2104 * @c NULL, then reverts back to auto-generation.
2107 ethumb_client_thumb_path_set(Ethumb_Client *client, const char *path, const char *key)
2109 EINA_SAFETY_ON_NULL_RETURN(client);
2111 ethumb_thumb_path_set(client->ethumb, path, key);
2115 * Get the configured thumbnail path.
2117 * This returns the value set with ethumb_client_thumb_path_set() or
2118 * auto-generated by ethumb_client_thumb_exists() if it was not set.
2120 * @param client the client instance to use. Must @b not be @c
2121 * NULL. May be pending connected (can be called before @c
2123 * @param path where to return configured path. May be @c NULL. If
2124 * there was no path configured with
2125 * ethumb_client_thumb_path_set() and
2126 * ethumb_client_thumb_exists() was not called, then it will
2127 * probably return @c NULL. If not @c NULL, then it will be a
2128 * pointer to a stringshared instance, but @b no references are
2129 * added (do it with eina_stringshare_ref())!
2130 * @param key where to return configured key. May be @c NULL. If
2131 * there was no key configured with
2132 * ethumb_client_thumb_key_set() and
2133 * ethumb_client_thumb_exists() was not called, then it will
2134 * probably return @c NULL. If not @c NULL, then it will be a
2135 * pointer to a stringshared instance, but @b no references are
2136 * added (do it with eina_stringshare_ref())!
2139 ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const char **key)
2141 if (path) *path = NULL;
2142 if (key) *key = NULL;
2143 EINA_SAFETY_ON_NULL_RETURN(client);
2145 ethumb_thumb_path_get(client->ethumb, path, key);
2149 * Checks whenever file already exists (locally!)
2151 * This will check locally (not calling server) if thumbnail already
2152 * exists or not, also calculating the thumbnail path. See
2153 * ethumb_client_thumb_path_get(). Path must be configured with
2154 * ethumb_client_file_set() before using it and the last set file will
2157 * @param client client instance. Must @b not be @c NULL and client
2158 * must be configured with ethumb_client_file_set().
2160 * @return @c EINA_TRUE if it exists, @c EINA_FALSE otherwise.
2162 EAPI Ethumb_Exists *
2163 ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
2165 const char *path = NULL;
2166 Ethumb_Async_Exists *async = NULL;
2167 Ethumb_Exists *cb = NULL;
2170 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
2172 ethumb_file_get(client->ethumb, &path, NULL);
2173 if (!path) goto on_error;
2175 async = eina_hash_find(_exists_request, path);
2178 async = malloc(sizeof (Ethumb_Async_Exists));
2179 if (!async) goto on_error;
2181 async->path = eina_stringshare_ref(path);
2182 async->callbacks = NULL;
2183 async->dup = ethumb_dup(client->ethumb);
2185 if (!async->dup) goto on_error;
2187 cb = malloc(sizeof (Ethumb_Exists));
2188 if (!cb) goto on_error;
2190 EINA_REFCOUNT_REF(client);
2191 cb->client = client;
2192 cb->dup = ethumb_dup(client->ethumb);
2193 cb->exists_cb = exists_cb;
2197 async->callbacks = eina_list_append(async->callbacks, cb);
2199 /* spawn a thread here */
2200 t = ecore_thread_run(_ethumb_client_exists_heavy,
2201 _ethumb_client_exists_end,
2202 _ethumb_client_exists_end,
2204 if (!t) return NULL;
2207 eina_hash_direct_add(_exists_request, async->path, async);
2212 cb = malloc(sizeof (Ethumb_Exists));
2219 EINA_REFCOUNT_REF(client);
2220 cb->client = client;
2221 cb->dup = ethumb_dup(client->ethumb);
2222 cb->exists_cb = exists_cb;
2226 async->callbacks = eina_list_append(async->callbacks, cb);
2231 exists_cb(client, NULL, EINA_FALSE, (void*) data);
2235 eina_stringshare_del(async->path);
2236 if (async->dup) ethumb_free(async->dup);
2243 * Cancel an ongoing exists request.
2245 * @param exists the request to cancel.
2248 ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
2250 Ethumb_Async_Exists *async = exists->parent;
2252 async->callbacks = eina_list_remove(async->callbacks, exists);
2253 if (eina_list_count(async->callbacks) <= 0)
2254 ecore_thread_cancel(async->thread);
2256 ethumb_free(exists->dup);
2257 EINA_REFCOUNT_UNREF(exists->client)
2258 _ethumb_client_free(exists->client);
2263 * Check if an exists request was cancelled.
2265 * @param exists the request to check.
2266 * @result return EINA_TRUE if the request was cancelled.
2269 ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
2271 Ethumb_Async_Exists *async = exists->parent;
2273 if (!async) return EINA_TRUE;
2275 if (async->callbacks) return EINA_FALSE;
2277 return ecore_thread_check(async->thread);
2281 * Ask server to generate thumbnail.
2283 * This process is asynchronous and will report back from main loop
2284 * using @a generated_cb. One can cancel this request by calling
2285 * ethumb_client_generate_cancel() or
2286 * ethumb_client_generate_cancel_all(), but not that request might be
2287 * processed by server already and no generated files will be removed
2288 * if that is the case.
2290 * This will not check if file already exists, this should be done by
2291 * explicitly calling ethumb_client_thumb_exists(). That is, this
2292 * function will override any existing thumbnail.
2294 * @param client client instance. Must @b not be @c NULL and client
2295 * must be connected (after connected_cb is called).
2296 * @param generated_cb function to report generation results.
2297 * @param data context argument to give back to @a generated_cb. May
2299 * @param data context to give back to @a generate_cb. May be @c
2301 * @param free_data used to release @a data resources after @a
2302 * generated_cb is called or user calls
2303 * ethumb_client_disconnect().
2305 * @return identifier or -1 on error. If -1 is returned (error) then
2306 * @a free_data is @b not called!
2308 * @see ethumb_client_connect()
2309 * @see ethumb_client_file_set()
2310 * @see ethumb_client_thumb_exists()
2311 * @see ethumb_client_generate_cancel()
2312 * @see ethumb_client_generate_cancel_all()
2315 ethumb_client_generate(Ethumb_Client *client, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data)
2317 const char *file, *key, *thumb, *thumb_key;
2319 EINA_SAFETY_ON_NULL_RETURN_VAL(client, -1);
2320 EINA_SAFETY_ON_FALSE_RETURN_VAL(client->connected, -1);
2322 ethumb_file_get(client->ethumb, &file, &key);
2325 ERR("no file set.");
2329 ethumb_thumb_path_get(client->ethumb, &thumb, &thumb_key);
2331 if (client->old_ethumb_conf &&
2332 ethumb_cmp(client->old_ethumb_conf, client->ethumb))
2334 ethumb_client_ethumb_setup(client);
2335 ethumb_free(client->old_ethumb_conf);
2336 client->old_ethumb_conf = NULL;
2338 id = _ethumb_client_queue_add(client, file, key, thumb, thumb_key,
2339 generated_cb, data, free_data);