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 E_DBus_Connection *conn;
104 E_DBus_Signal_Handler *name_owner_changed_handler;
105 E_DBus_Signal_Handler *generated_signal;
106 DBusPendingCall *pending_get_name_owner;
107 DBusPendingCall *pending_start_service_by_name;
108 const char *unique_name;
109 DBusPendingCall *pending_new;
111 Ethumb_Client_Connect_Cb cb;
113 Eina_Free_Cb free_data;
115 Eina_List *pending_add;
116 Eina_List *pending_remove;
117 Eina_List *pending_gen;
118 DBusPendingCall *pending_clear;
119 DBusPendingCall *pending_setup;
121 Ethumb_Client_Die_Cb cb;
123 Eina_Free_Cb free_data;
125 const char *object_path;
129 Eina_Bool ethumb_dirty : 1;
130 Eina_Bool connected : 1;
131 Eina_Bool server_started : 1;
132 Eina_Bool delete_me : 1;
135 struct _ethumb_pending_add
141 const char *thumb_key;
142 Ethumb_Client_Generate_Cb generated_cb;
144 Eina_Free_Cb free_data;
145 DBusPendingCall *pending_call;
146 Ethumb_Client *client;
149 struct _ethumb_pending_remove
152 Ethumb_Client_Generate_Cancel_Cb cancel_cb;
154 Eina_Free_Cb free_data;
155 DBusPendingCall *pending_call;
156 Ethumb_Client *client;
159 struct _ethumb_pending_gen
165 const char *thumb_key;
166 Ethumb_Client_Generate_Cb generated_cb;
168 Eina_Free_Cb free_data;
171 typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists;
173 struct _Ethumb_Async_Exists
176 Ethumb_Client *source;
178 Ethumb_Client_Thumb_Exists_Cb exists_cb;
181 Ecore_Thread *thread;
184 Eina_Bool exists : 1;
187 static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
188 static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
189 static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
190 static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
191 static const char fdo_interface[] = "org.freedesktop.DBus";
192 static const char fdo_bus_name[] = "org.freedesktop.DBus";
193 static const char fdo_path[] = "/org/freedesktop/DBus";
195 static int _initcount = 0;
197 static void _ethumb_client_generated_cb(void *data, DBusMessage *msg);
198 static void _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err);
201 __dbus_callback_check_and_init(const char *file, int line, const char *function, DBusMessage *msg, DBusMessageIter *itr, DBusError *err)
205 ERR("%s:%d:%s() callback without message arguments!",
206 file, line, function);
209 ERR("%s:%d:%s() an error was reported by server: "
210 "name=\"%s\", message=\"%s\"",
211 file, line, function, err->name, err->message);
216 if (!dbus_message_iter_init(msg, itr))
218 ERR("%s:%d:%s() could not init iterator.",
219 file, line, function);
226 #define _dbus_callback_check_and_init(msg, itr, err) \
227 __dbus_callback_check_and_init(__FILE__, __LINE__, __FUNCTION__, \
231 __dbus_iter_type_check(int type, int expected, const char *expected_name)
233 if (type == expected)
236 ERR("expected type %s (%c) but got %c instead!",
237 expected_name, expected, type);
241 #define _dbus_iter_type_check(t, e) __dbus_iter_type_check(t, e, #e)
243 #define CHECK_NULL_RETURN(ptr, ...) \
248 CRITICAL("%s == NULL!", #ptr); \
249 return __VA_ARGS__; \
255 _ethumb_client_name_owner_changed(void *data, DBusMessage *msg)
258 const char *name, *from, *to;
259 Ethumb_Client *client = data;
261 dbus_error_init(&err);
262 if (!dbus_message_get_args(msg, &err,
263 DBUS_TYPE_STRING, &name,
264 DBUS_TYPE_STRING, &from,
265 DBUS_TYPE_STRING, &to,
268 ERR("could not get NameOwnerChanged arguments: %s: %s",
269 err.name, err.message);
270 dbus_error_free(&err);
276 if (strcmp(name, _ethumb_dbus_bus_name) != 0)
279 DBG("NameOwnerChanged from=[%s] to=[%s]", from, to);
281 if (from[0] != '\0' && to[0] == '\0')
283 DBG("exit ethumbd at %s", from);
284 if (client->unique_name && strcmp(client->unique_name, from) != 0)
285 WRN("%s was not the known name %s, ignored.",
286 from, client->unique_name);
287 else if(client->unique_name)
289 ERR("server exit!!!");
292 client->die.cb(client->die.data, client);
293 client->die.cb = NULL;
295 if (client->die.free_data)
297 client->die.free_data(client->die.data);
298 client->die.free_data = NULL;
299 client->die.data = NULL;
304 DBG("unknown change from %s to %s", from, to);
308 _ethumb_client_report_connect(Ethumb_Client *client, Eina_Bool success)
310 if (!client->connect.cb)
312 ERR("already called?!");
316 client->connect.cb(client->connect.data, client, success);
317 if (client->connect.free_data)
319 client->connect.free_data(client->connect.data);
320 client->connect.free_data = NULL;
322 client->connect.cb = NULL;
323 client->connect.data = NULL;
327 _ethumb_client_new_cb(void *data, DBusMessage *msg, DBusError *error)
329 DBusMessageIter iter;
332 Ethumb_Client *client = data;
334 client->pending_new = NULL;
336 if (!_dbus_callback_check_and_init(msg, &iter, error))
338 t = dbus_message_iter_get_arg_type(&iter);
339 if (!_dbus_iter_type_check(t, DBUS_TYPE_OBJECT_PATH))
342 dbus_message_iter_get_basic(&iter, &opath);
343 if (opath[0] == '\0')
346 client->object_path = eina_stringshare_add(opath);
348 client->generated_signal = e_dbus_signal_handler_add(
349 client->conn, _ethumb_dbus_bus_name, opath,
350 _ethumb_dbus_objects_interface, "generated",
351 _ethumb_client_generated_cb, client);
353 _ethumb_client_report_connect(client, 1);
357 _ethumb_client_report_connect(client, 0);
361 _ethumb_client_call_new(Ethumb_Client *client)
365 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name, _ethumb_dbus_path,
366 _ethumb_dbus_interface, "new");
367 client->pending_new = e_dbus_message_send(client->conn, msg,
368 _ethumb_client_new_cb, -1,
370 dbus_message_unref(msg);
374 _ethumb_client_start_server_cb(void *data, DBusMessage *msg, DBusError *err)
376 Ethumb_Client *client = data;
377 DBusMessageIter iter;
381 client->pending_start_service_by_name = NULL;
383 if (!_dbus_callback_check_and_init(msg, &iter, err))
386 t = dbus_message_iter_get_arg_type(&iter);
387 if (!_dbus_iter_type_check(t, DBUS_TYPE_UINT32))
390 dbus_message_iter_get_basic(&iter, &ret);
391 if ((ret != 1) && (ret != 2))
393 ERR("Error starting Ethumbd DBus service by its name: retcode %u",
398 client->server_started = 1;
399 DBG("Ethumbd DBus service started successfully (%d), now request its name",
402 if (client->pending_get_name_owner)
404 DBG("already requesting name owner, cancel and try again");
405 dbus_pending_call_cancel(client->pending_get_name_owner);
408 client->pending_get_name_owner = e_dbus_get_name_owner
409 (client->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
411 if (!client->pending_get_name_owner)
413 ERR("could not create a get_name_owner request.");
420 ERR("failed to start Ethumbd DBus service by its name.");
421 _ethumb_client_report_connect(client, 0);
425 _ethumb_client_start_server(Ethumb_Client *client)
427 if (client->pending_start_service_by_name)
429 DBG("already pending start service by name.");
433 client->server_started = 0;
434 client->pending_start_service_by_name = e_dbus_start_service_by_name
435 (client->conn, _ethumb_dbus_bus_name, 0, _ethumb_client_start_server_cb,
437 if (!client->pending_start_service_by_name)
439 ERR("could not start service by name!");
440 _ethumb_client_report_connect(client, 0);
445 _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err)
447 DBusMessageIter iter;
449 Ethumb_Client *client = data;
452 client->pending_get_name_owner = NULL;
454 if (dbus_error_is_set(err) && (!client->server_started))
456 DBG("could not find server (%s), try to start it...", err->message);
457 _ethumb_client_start_server(client);
461 if (!_dbus_callback_check_and_init(msg, &iter, err))
464 t = dbus_message_iter_get_arg_type(&iter);
465 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
468 dbus_message_iter_get_basic(&iter, &uid);
471 ERR("no name owner!");
475 DBG("unique name = %s", uid);
476 client->unique_name = eina_stringshare_add(uid);
478 _ethumb_client_call_new(client);
479 client->connected = 1;
483 _ethumb_client_report_connect(client, 0);
487 _ethumb_client_exists_heavy(void *data, Ecore_Thread *thread)
489 Ethumb_Async_Exists *async = data;
491 async->exists = ethumb_exists(async->dup);
495 _ethumb_client_exists_end(void *data, Ecore_Thread *thread)
497 Ethumb_Async_Exists *async = data;
498 Ethumb *tmp = async->source->ethumb;
500 async->source->ethumb = async->dup;
501 async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup);
502 async->exists_cb(async->source, (Ethumb_Exists*) async, async->exists, (void*) async->data);
503 async->source->ethumb = tmp;
505 ethumb_free(async->dup);
506 async->source->refcount--;
508 if (async->source->delete_me == EINA_TRUE)
509 ethumb_client_disconnect(async->source);
515 _ethumb_client_exists_cancel(void *data, Ecore_Thread *thread)
517 Ethumb_Async_Exists *async = data;
518 Ethumb *tmp = async->source->ethumb;
520 async->source->ethumb = async->dup;
521 async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup);
522 async->exists_cb(async->source, (Ethumb_Exists*) async, EINA_FALSE, (void*) async->data);
523 async->source->ethumb = tmp;
525 ethumb_free(async->dup);
526 async->source->refcount--;
528 if (async->source->delete_me == EINA_TRUE)
529 ethumb_client_disconnect(async->source);
539 * @brief Initialize the Ethumb_Client library.
541 * @return 1 or greater on success, 0 on error.
543 * This function sets up all the Ethumb_Client module dependencies. It
544 * returns 0 on failure (that is, when one of the dependency fails to
545 * initialize), otherwise it returns the number of times it has
546 * already been called.
548 * When Ethumb_Client is not used anymore, call
549 * ethumb_client_shutdown() to shut down the Ethumb_Client library.
551 * @see ethumb_client_shutdown()
552 * @see ethumb_client_connect()
553 * @see @ref tutorial_ethumb_client
556 ethumb_client_init(void)
563 fprintf(stderr, "ERROR: Could not initialize log module.\n");
566 _log_dom = eina_log_domain_register("ethumb_client", EINA_COLOR_YELLOW);
569 EINA_LOG_ERR("Could not register log domain: ethumb_client");
581 * @brief Shut down the Ethumb_Client library.
583 * @return 0 when everything is shut down, 1 or greater if there are
584 * other users of the Ethumb_Client library pending shutdown.
586 * This function shuts down the Ethumb_Client library. It returns 0
587 * when it has been called the same number of times than
588 * ethumb_client_init(). In that case it shut down all the
589 * Ethumb_Client modules dependencies.
591 * Once this function succeeds (that is, @c 0 is returned), you must
592 * not call any of the Eina function anymore. You must call
593 * ethumb_client_init() again to use the Ethumb_Client functions
597 ethumb_client_shutdown(void)
605 eina_log_domain_unregister(_log_dom);
612 * Connects to Ethumb server and return the client instance.
614 * This is the "constructor" of Ethumb_Client, where everything
617 * If server was down, it is tried to start it using DBus activation,
618 * then the connection is retried.
620 * This call is asynchronous and will not block, instead it will be in
621 * "not connected" state until @a connect_cb is called with either
622 * success or failure. On failure, then no methods should be
623 * called. On success you're now able to setup and then ask generation
626 * Usually you should listen for server death/disconenction with
627 * ethumb_client_on_server_die_callback_set().
629 * @param connect_cb function to call to report connection success or
630 * failure. Do not call any other ethumb_client method until
631 * this function returns. The first received parameter is the
632 * given argument @a data. Must @b not be @c NULL. This
633 * function will not be called if user explicitly calls
634 * ethumb_client_disconnect().
635 * @param data context to give back to @a connect_cb. May be @c NULL.
636 * @param free_data function used to release @a data resources, if
637 * any. May be @c NULL. If this function exists, it will be
638 * called immediately after @a connect_cb is called or if user
639 * explicitly calls ethumb_client_disconnect() before such
640 * (that is, don't rely on @a data after @a connect_cb was
643 * @return client instance or NULL if failed. If @a connect_cb is
644 * missing it returns @c NULL. If it fail for other
645 * conditions, @c NULL is also returned and @a connect_cb is
646 * called with @c success=EINA_FALSE. The client instance is
647 * not ready to be used until @a connect_cb is called.
650 ethumb_client_connect(Ethumb_Client_Connect_Cb connect_cb, const void *data, Eina_Free_Cb free_data)
652 Ethumb_Client *eclient;
654 EINA_SAFETY_ON_NULL_RETURN_VAL(connect_cb, NULL);
656 eclient = calloc(1, sizeof(*eclient));
659 ERR("could not allocate Ethumb_Client structure.");
663 eclient->connect.cb = connect_cb;
664 eclient->connect.data = (void *)data;
665 eclient->connect.free_data = free_data;
667 eclient->ethumb = ethumb_new();
668 if (!eclient->ethumb)
670 ERR("could not create ethumb handler.");
674 eclient->conn = e_dbus_bus_get(DBUS_BUS_SESSION);
677 ERR("could not connect to session bus.");
681 eclient->name_owner_changed_handler = e_dbus_signal_handler_add(
682 eclient->conn, fdo_bus_name, fdo_path, fdo_interface,
683 "NameOwnerChanged", _ethumb_client_name_owner_changed, eclient);
685 eclient->pending_get_name_owner = e_dbus_get_name_owner(
686 eclient->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
688 if (!eclient->pending_get_name_owner)
690 ERR("could not create a get_name_owner request.");
697 ethumb_free(eclient->ethumb);
701 connect_cb((void *)data, NULL, EINA_FALSE);
703 free_data((void *)data);
708 * Disconnect the client, releasing all client resources.
710 * This is the destructor of Ethumb_Client, after it's disconnected
711 * the client handle is now gone and should not be used.
713 * @param client client instance to be destroyed. Must @b not be @c
717 ethumb_client_disconnect(Ethumb_Client *client)
721 EINA_SAFETY_ON_NULL_RETURN(client);
723 client->delete_me = EINA_TRUE;
724 if (client->refcount > 0)
727 if (!client->connected)
730 EINA_LIST_FREE(client->pending_add, data)
732 struct _ethumb_pending_add *pending = data;
733 eina_stringshare_del(pending->file);
734 eina_stringshare_del(pending->key);
735 eina_stringshare_del(pending->thumb);
736 eina_stringshare_del(pending->thumb_key);
737 dbus_pending_call_cancel(pending->pending_call);
738 dbus_pending_call_unref(pending->pending_call);
739 if (pending->free_data)
740 pending->free_data(pending->data);
744 EINA_LIST_FREE(client->pending_gen, data)
746 struct _ethumb_pending_gen *pending = data;
747 eina_stringshare_del(pending->file);
748 eina_stringshare_del(pending->key);
749 eina_stringshare_del(pending->thumb);
750 eina_stringshare_del(pending->thumb_key);
751 if (pending->free_data)
752 pending->free_data(pending->data);
756 EINA_LIST_FREE(client->pending_remove, data)
758 struct _ethumb_pending_remove *pending = data;
759 dbus_pending_call_cancel(pending->pending_call);
760 dbus_pending_call_unref(pending->pending_call);
761 if (pending->free_data)
762 pending->free_data(pending->data);
766 if (client->pending_clear)
768 dbus_pending_call_cancel(client->pending_clear);
769 dbus_pending_call_unref(client->pending_clear);
773 if (client->object_path)
774 eina_stringshare_del(client->object_path);
776 if (client->pending_new)
777 dbus_pending_call_cancel(client->pending_new);
779 if (client->unique_name)
780 eina_stringshare_del(client->unique_name);
782 if (client->pending_get_name_owner)
783 dbus_pending_call_cancel(client->pending_get_name_owner);
785 if (client->pending_start_service_by_name)
786 dbus_pending_call_cancel(client->pending_start_service_by_name);
788 ethumb_free(client->ethumb);
790 e_dbus_signal_handler_del(client->conn, client->name_owner_changed_handler);
791 if (client->connected)
792 e_dbus_signal_handler_del(client->conn, client->generated_signal);
793 e_dbus_connection_close(client->conn);
795 if (client->connect.free_data)
796 client->connect.free_data(client->connect.data);
797 if (client->die.free_data)
798 client->die.free_data(client->die.data);
804 * Sets the callback to report server died.
806 * When server dies there is nothing you can do, just release
807 * resources with ethumb_client_disconnect() and probably try to
810 * Usually you should set this callback and handle this case, it does
813 * @param client the client instance to monitor. Must @b not be @c
815 * @param server_die_cb function to call back when server dies. The
816 * first parameter will be the argument @a data. May be @c
818 * @param data context to give back to @a server_die_cb. May be @c
820 * @param free_data used to release @a data resources after @a
821 * server_die_cb is called or user calls
822 * ethumb_client_disconnect().
825 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)
827 EINA_SAFETY_ON_NULL_RETURN(client);
829 if (client->die.free_data)
830 client->die.free_data(client->die.data);
832 client->die.cb = server_die_cb;
833 client->die.data = (void *)data;
834 client->die.free_data = free_data;
842 _ethumb_client_ethumb_setup_cb(void *data, DBusMessage *msg, DBusError *error)
844 DBusMessageIter iter;
846 dbus_bool_t result = 0;
847 Ethumb_Client *client = data;
849 client->pending_setup = NULL;
851 if (!_dbus_callback_check_and_init(msg, &iter, error))
854 t = dbus_message_iter_get_arg_type(&iter);
855 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
858 dbus_message_iter_get_basic(&iter, &result);
862 _ethumb_client_dbus_get_bytearray(DBusMessageIter *iter)
866 DBusMessageIter riter;
869 el_type = dbus_message_iter_get_element_type(iter);
870 if (el_type != DBUS_TYPE_BYTE)
872 ERR("not an byte array element.");
876 dbus_message_iter_recurse(iter, &riter);
877 dbus_message_iter_get_fixed_array(&riter, &result, &length);
879 if (result[0] == '\0')
882 return eina_stringshare_add(result);
886 _ethumb_client_dbus_append_bytearray(DBusMessageIter *iter, const char *string)
888 DBusMessageIter viter;
893 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &viter);
894 dbus_message_iter_append_fixed_array(&viter, DBUS_TYPE_BYTE, &string,
896 dbus_message_iter_close_container(iter, &viter);
904 * Send setup to server.
906 * This method is called automatically by ethumb_client_generate() if
907 * any property was changed. No need to call it manually.
909 * @param client client instance. Must @b not be @c NULL and client
910 * must be connected (after connected_cb is called).
913 ethumb_client_ethumb_setup(Ethumb_Client *client)
916 DBusMessageIter iter, aiter, diter, viter, vaiter;
917 Ethumb *e = client->ethumb;
919 dbus_int32_t tw, th, format, aspect, orientation, quality, compress;
922 const char *theme_file, *group, *swallow;
923 const char *directory, *category;
924 double video_time, video_start, video_interval;
925 dbus_int32_t video_ntimes, video_fps, document_page;
927 EINA_SAFETY_ON_NULL_RETURN(client);
928 EINA_SAFETY_ON_FALSE_RETURN(client->connected);
929 client->ethumb_dirty = 0;
931 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
933 _ethumb_dbus_objects_interface,
935 dbus_message_iter_init_append(msg, &iter);
936 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &aiter);
941 #define _open_variant_iter(str_entry, str_type, end_iter) \
943 dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &diter); \
944 dbus_message_iter_append_basic(&diter, DBUS_TYPE_STRING, &entry); \
945 dbus_message_iter_open_container(&diter, DBUS_TYPE_VARIANT, str_type, \
948 #define _close_variant_iter(end_iter) \
949 dbus_message_iter_close_container(&diter, &end_iter); \
950 dbus_message_iter_close_container(&aiter, &diter);
955 /* starting array elements */
957 _open_variant_iter("size", "(ii)", viter);
958 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
959 ethumb_thumb_size_get(e, &tw, &th);
960 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &tw);
961 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &th);
962 dbus_message_iter_close_container(&viter, &vaiter);
963 _close_variant_iter(viter);
965 _open_variant_iter("format", "i", viter);
966 format = ethumb_thumb_format_get(e);
967 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &format);
968 _close_variant_iter(viter);
970 _open_variant_iter("aspect", "i", viter);
971 aspect = ethumb_thumb_aspect_get(e);
972 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &aspect);
973 _close_variant_iter(viter);
975 _open_variant_iter("orientation", "i", viter);
976 orientation = ethumb_thumb_orientation_get(e);
977 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &orientation);
978 _close_variant_iter(viter);
980 _open_variant_iter("crop", "(dd)", viter);
981 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
982 ethumb_thumb_crop_align_get(e, &cx, &cy);
984 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
986 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
987 dbus_message_iter_close_container(&viter, &vaiter);
988 _close_variant_iter(viter);
990 _open_variant_iter("quality", "i", viter);
991 quality = ethumb_thumb_quality_get(e);
992 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &quality);
993 _close_variant_iter(viter);
995 _open_variant_iter("compress", "i", viter);
996 compress = ethumb_thumb_compress_get(e);
997 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &compress);
998 _close_variant_iter(viter);
1000 _open_variant_iter("frame", "(ayayay)", viter);
1001 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
1002 ethumb_frame_get(e, &theme_file, &group, &swallow);
1003 _ethumb_client_dbus_append_bytearray(&vaiter, theme_file);
1004 _ethumb_client_dbus_append_bytearray(&vaiter, group);
1005 _ethumb_client_dbus_append_bytearray(&vaiter, swallow);
1006 dbus_message_iter_close_container(&viter, &vaiter);
1007 _close_variant_iter(viter);
1009 _open_variant_iter("directory", "ay", viter);
1010 directory = ethumb_thumb_dir_path_get(e);
1011 _ethumb_client_dbus_append_bytearray(&viter, directory);
1012 _close_variant_iter(viter);
1014 _open_variant_iter("category", "ay", viter);
1015 category = ethumb_thumb_category_get(e);
1016 _ethumb_client_dbus_append_bytearray(&viter, category);
1017 _close_variant_iter(viter);
1019 _open_variant_iter("video_time", "d", viter);
1020 video_time = ethumb_video_time_get(e);
1021 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time);
1022 _close_variant_iter(viter);
1024 _open_variant_iter("video_start", "d", viter);
1025 video_start = ethumb_video_start_get(e);
1026 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start);
1027 _close_variant_iter(viter);
1029 _open_variant_iter("video_interval", "d", viter);
1030 video_interval = ethumb_video_interval_get(e);
1031 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval);
1032 _close_variant_iter(viter);
1034 _open_variant_iter("video_ntimes", "u", viter);
1035 video_ntimes = ethumb_video_ntimes_get(e);
1036 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_ntimes);
1037 _close_variant_iter(viter);
1039 _open_variant_iter("video_fps", "u", viter);
1040 video_fps = ethumb_video_fps_get(e);
1041 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_fps);
1042 _close_variant_iter(viter);
1044 _open_variant_iter("document_page", "u", viter);
1045 document_page = ethumb_document_page_get(e);
1046 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &document_page);
1047 _close_variant_iter(viter);
1049 #undef _open_variant_iter
1050 #undef _close_variant_iter
1052 dbus_message_iter_close_container(&iter, &aiter);
1054 client->pending_setup = e_dbus_message_send(client->conn, msg,
1055 _ethumb_client_ethumb_setup_cb,
1057 dbus_message_unref(msg);
1065 _ethumb_client_generated_cb(void *data, DBusMessage *msg)
1067 DBusMessageIter iter;
1068 dbus_int32_t id = -1;
1069 const char *thumb = NULL;
1070 const char *thumb_key = NULL;
1071 Ethumb_Client *client = data;
1073 dbus_bool_t success;
1076 struct _ethumb_pending_gen *pending;
1078 dbus_message_iter_init(msg, &iter);
1080 t = dbus_message_iter_get_arg_type(&iter);
1081 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1083 dbus_message_iter_get_basic(&iter, &id);
1084 dbus_message_iter_next(&iter);
1086 t = dbus_message_iter_get_arg_type(&iter);
1087 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1089 thumb = _ethumb_client_dbus_get_bytearray(&iter);
1090 dbus_message_iter_next(&iter);
1092 t = dbus_message_iter_get_arg_type(&iter);
1093 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1095 thumb_key = _ethumb_client_dbus_get_bytearray(&iter);
1096 dbus_message_iter_next(&iter);
1098 t = dbus_message_iter_get_arg_type(&iter);
1099 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1101 dbus_message_iter_get_basic(&iter, &success);
1104 l = client->pending_gen;
1108 if (pending->id == id)
1118 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1119 pending->generated_cb(pending->data, client, id,
1120 pending->file, pending->key,
1121 pending->thumb, pending->thumb_key,
1123 if (pending->free_data)
1124 pending->free_data(pending->data);
1125 eina_stringshare_del(pending->file);
1126 eina_stringshare_del(pending->key);
1127 eina_stringshare_del(pending->thumb);
1128 eina_stringshare_del(pending->thumb_key);
1133 if (thumb) eina_stringshare_del(thumb);
1134 if (thumb_key) eina_stringshare_del(thumb_key);
1138 _ethumb_client_queue_add_cb(void *data, DBusMessage *msg, DBusError *error)
1140 DBusMessageIter iter;
1142 dbus_int32_t id = -1;
1143 struct _ethumb_pending_add *pending = data;
1144 struct _ethumb_pending_gen *generating;
1145 Ethumb_Client *client = pending->client;
1147 client->pending_add = eina_list_remove(client->pending_add, pending);
1149 if (!_dbus_callback_check_and_init(msg, &iter, error))
1152 t = dbus_message_iter_get_arg_type(&iter);
1153 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1156 dbus_message_iter_get_basic(&iter, &id);
1158 generating = calloc(1, sizeof(*generating));
1159 generating->id = id;
1160 generating->file = pending->file;
1161 generating->key = pending->key;
1162 generating->thumb = pending->thumb;
1163 generating->thumb_key = pending->thumb_key;
1164 generating->generated_cb = pending->generated_cb;
1165 generating->data = pending->data;
1166 generating->free_data = pending->free_data;
1167 client->pending_gen = eina_list_append(client->pending_gen, generating);
1174 _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)
1177 DBusMessageIter iter;
1178 struct _ethumb_pending_add *pending;
1180 pending = calloc(1, sizeof(*pending));
1181 pending->id = client->id_count;
1182 pending->file = eina_stringshare_add(file);
1183 pending->key = eina_stringshare_add(key);
1184 pending->thumb = eina_stringshare_add(thumb);
1185 pending->thumb_key = eina_stringshare_add(thumb_key);
1186 pending->generated_cb = generated_cb;
1187 pending->data = (void *)data;
1188 pending->free_data = free_data;
1189 pending->client = client;
1191 client->id_count = (client->id_count + 1) % MAX_ID;
1193 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1194 client->object_path,
1195 _ethumb_dbus_objects_interface,
1198 dbus_message_iter_init_append(msg, &iter);
1199 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &pending->id);
1200 _ethumb_client_dbus_append_bytearray(&iter, file);
1201 _ethumb_client_dbus_append_bytearray(&iter, key);
1202 _ethumb_client_dbus_append_bytearray(&iter, thumb);
1203 _ethumb_client_dbus_append_bytearray(&iter, thumb_key);
1205 pending->pending_call = e_dbus_message_send(client->conn, msg,
1206 _ethumb_client_queue_add_cb,
1208 client->pending_add = eina_list_append(client->pending_add, pending);
1209 dbus_message_unref(msg);
1215 _ethumb_client_queue_remove_cb(void *data, DBusMessage *msg, DBusError *error)
1217 DBusMessageIter iter;
1219 dbus_bool_t success = 0;
1220 struct _ethumb_pending_remove *pending = data;
1221 Ethumb_Client *client = pending->client;
1223 client->pending_remove = eina_list_remove(client->pending_remove, pending);
1225 if (!_dbus_callback_check_and_init(msg, &iter, error))
1228 t = dbus_message_iter_get_arg_type(&iter);
1229 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1232 dbus_message_iter_get_basic(&iter, &success);
1235 if (pending->cancel_cb)
1236 pending->cancel_cb(pending->data, success);
1237 if (pending->free_data)
1238 pending->free_data(pending->data);
1246 * Ask server to cancel generation of thumbnail.
1248 * @param client client instance. Must @b not be @c NULL and client
1249 * must be connected (after connected_cb is called).
1250 * @param id valid id returned by ethumb_client_generate()
1251 * @param cancel_cb function to report cancellation results.
1252 * @param data context argument to give back to @a cancel_cb. May be
1254 * @param data context to give back to @a cancel_cb. May be @c
1256 * @param free_data used to release @a data resources after @a
1257 * cancel_cb is called or user calls
1258 * ethumb_client_disconnect().
1261 ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, const void *data, Eina_Free_Cb free_data)
1264 struct _ethumb_pending_remove *pending;
1267 dbus_int32_t id32 = id;
1268 EINA_SAFETY_ON_NULL_RETURN(client);
1269 EINA_SAFETY_ON_FALSE_RETURN(id >= 0);
1271 pending = calloc(1, sizeof(*pending));
1273 pending->cancel_cb = cancel_cb;
1274 pending->data = (void *)data;
1275 pending->free_data = free_data;
1276 pending->client = client;
1278 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1279 client->object_path,
1280 _ethumb_dbus_objects_interface,
1283 dbus_message_append_args(msg, DBUS_TYPE_INT32, &id32, DBUS_TYPE_INVALID);
1284 pending->pending_call = e_dbus_message_send(client->conn, msg,
1285 _ethumb_client_queue_remove_cb,
1287 client->pending_remove = eina_list_append(client->pending_remove, pending);
1290 l = client->pending_add;
1293 struct _ethumb_pending_add *pending_add = l->data;
1294 if (pending_add->id != id32)
1299 client->pending_add = eina_list_remove_list(client->pending_add, l);
1300 eina_stringshare_del(pending_add->file);
1301 eina_stringshare_del(pending_add->key);
1302 eina_stringshare_del(pending_add->thumb);
1303 eina_stringshare_del(pending_add->thumb_key);
1304 dbus_pending_call_cancel(pending_add->pending_call);
1305 dbus_pending_call_unref(pending_add->pending_call);
1306 if (pending_add->free_data)
1307 pending_add->free_data(pending_add->data);
1316 l = client->pending_gen;
1319 struct _ethumb_pending_gen *pending_gen = l->data;
1320 if (pending_gen->id != id32)
1325 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1326 eina_stringshare_del(pending_gen->file);
1327 eina_stringshare_del(pending_gen->key);
1328 eina_stringshare_del(pending_gen->thumb);
1329 eina_stringshare_del(pending_gen->thumb_key);
1330 if (pending_gen->free_data)
1331 pending_gen->free_data(pending_gen->data);
1337 dbus_message_unref(msg);
1344 _ethumb_client_queue_clear_cb(void *data, DBusMessage *msg __UNUSED__, DBusError *error __UNUSED__)
1346 Ethumb_Client *client = data;
1348 client->pending_clear = NULL;
1355 * Ask server to cancel generation of all thumbnails.
1357 * @param client client instance. Must @b not be @c NULL and client
1358 * must be connected (after connected_cb is called).
1360 * @see ethumb_client_generate_cancel()
1363 ethumb_client_generate_cancel_all(Ethumb_Client *client)
1367 EINA_SAFETY_ON_NULL_RETURN(client);
1369 if (client->pending_clear)
1372 EINA_LIST_FREE(client->pending_add, data)
1374 struct _ethumb_pending_add *pending = data;
1375 eina_stringshare_del(pending->file);
1376 eina_stringshare_del(pending->key);
1377 eina_stringshare_del(pending->thumb);
1378 eina_stringshare_del(pending->thumb_key);
1379 dbus_pending_call_cancel(pending->pending_call);
1380 dbus_pending_call_unref(pending->pending_call);
1381 if (pending->free_data)
1382 pending->free_data(pending->data);
1386 EINA_LIST_FREE(client->pending_gen, data)
1388 struct _ethumb_pending_gen *pending = data;
1389 eina_stringshare_del(pending->file);
1390 eina_stringshare_del(pending->key);
1391 eina_stringshare_del(pending->thumb);
1392 eina_stringshare_del(pending->thumb_key);
1393 if (pending->free_data)
1394 pending->free_data(pending->data);
1398 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1399 client->object_path,
1400 _ethumb_dbus_objects_interface,
1403 client->pending_clear = e_dbus_message_send(client->conn, msg,
1404 _ethumb_client_queue_clear_cb,
1407 dbus_message_unref(msg);
1411 * Configure future requests to use FreeDesktop.Org preset.
1413 * This is a preset to provide freedesktop.org (fdo) standard
1414 * compliant thumbnails. That is, files are stored as JPEG under
1415 * ~/.thumbnails/SIZE, with size being either normal (128x128) or
1418 * @param client the client instance to use. Must @b not be @c
1419 * NULL. May be pending connected (can be called before @c
1421 * @param s size identifier, either #ETHUMB_THUMB_NORMAL (0) or
1422 * #ETHUMB_THUMB_LARGE (1).
1424 * @see ethumb_client_size_set()
1425 * @see ethumb_client_aspect_set()
1426 * @see ethumb_client_crop_align_set()
1427 * @see ethumb_client_category_set()
1428 * @see ethumb_client_dir_path_set()
1431 ethumb_client_fdo_set(Ethumb_Client *client, Ethumb_Thumb_FDO_Size s)
1433 EINA_SAFETY_ON_NULL_RETURN(client);
1435 client->ethumb_dirty = 1;
1436 ethumb_thumb_fdo_set(client->ethumb, s);
1440 * Configure future request to use custom size.
1442 * @param client the client instance to use. Must @b not be @c
1443 * NULL. May be pending connected (can be called before @c
1445 * @param tw width, default is 128.
1446 * @param th height, default is 128.
1449 ethumb_client_size_set(Ethumb_Client *client, int tw, int th)
1451 EINA_SAFETY_ON_NULL_RETURN(client);
1453 client->ethumb_dirty = 1;
1454 ethumb_thumb_size_set(client->ethumb, tw, th);
1458 * Retrieve future request to use custom size.
1460 * @param client the client instance to use. Must @b not be @c
1461 * NULL. May be pending connected (can be called before @c
1463 * @param tw where to return width. May be @c NULL.
1464 * @param th where to return height. May be @c NULL.
1467 ethumb_client_size_get(const Ethumb_Client *client, int *tw, int *th)
1471 EINA_SAFETY_ON_NULL_RETURN(client);
1473 ethumb_thumb_size_get(client->ethumb, tw, th);
1477 * Configure format to use for future requests.
1479 * @param client the client instance to use. Must @b not be @c
1480 * NULL. May be pending connected (can be called before @c
1482 * @param f format identifier to use, either #ETHUMB_THUMB_FDO (0),
1483 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2). Default is FDO.
1486 ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f)
1488 EINA_SAFETY_ON_NULL_RETURN(client);
1490 client->ethumb_dirty = 1;
1491 ethumb_thumb_format_set(client->ethumb, f);
1495 * Retrieve format to use for future requests.
1497 * @param client the client instance to use. Must @b not be @c
1498 * NULL. May be pending connected (can be called before @c
1501 * @return format identifier to use, either #ETHUMB_THUMB_FDO (0),
1502 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2).
1504 EAPI Ethumb_Thumb_Format
1505 ethumb_client_format_get(const Ethumb_Client *client)
1507 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1509 return ethumb_thumb_format_get(client->ethumb);
1513 * Configure aspect mode to use.
1515 * If aspect is kept (#ETHUMB_THUMB_KEEP_ASPECT), then image will be
1516 * rescaled so the largest dimension is not bigger than it's specified
1517 * size (see ethumb_client_size_get()) and the other dimension is
1518 * resized in the same proportion. Example: size is 256x256, image is
1519 * 1000x500, resulting thumbnail is 256x128.
1521 * If aspect is ignored (#ETHUMB_THUMB_IGNORE_ASPECT), then image will
1522 * be distorted to match required thumbnail size. Example: size is
1523 * 256x256, image is 1000x500, resulting thumbnail is 256x256.
1525 * If crop is required (#ETHUMB_THUMB_CROP), then image will be
1526 * cropped so the smallest dimension is not bigger than its specified
1527 * size (see ethumb_client_size_get()) and the other dimension will
1528 * overflow, not being visible in the final image. How it will
1529 * overflow is speficied by ethumb_client_crop_align_set()
1530 * alignment. Example: size is 256x256, image is 1000x500, crop
1531 * alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
1532 * pixels from left and 250 pixels from right being lost, that is just
1533 * the 500x500 central pixels of image will be considered for scaling.
1535 * @param client the client instance to use. Must @b not be @c
1536 * NULL. May be pending connected (can be called before @c
1538 * @param a aspect mode identifier, either #ETHUMB_THUMB_KEEP_ASPECT (0),
1539 * #ETHUMB_THUMB_IGNORE_ASPECT (1) or #ETHUMB_THUMB_CROP (2).
1542 ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a)
1544 EINA_SAFETY_ON_NULL_RETURN(client);
1546 client->ethumb_dirty = 1;
1547 ethumb_thumb_aspect_set(client->ethumb, a);
1551 * Get current aspect in use for requests.
1553 * @param client the client instance to use. Must @b not be @c
1554 * NULL. May be pending connected (can be called before @c
1557 * @return aspect in use for future requests.
1559 EAPI Ethumb_Thumb_Aspect
1560 ethumb_client_aspect_get(const Ethumb_Client *client)
1562 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1564 return ethumb_thumb_aspect_get(client->ethumb);
1568 * Configure orientation to use for future requests.
1570 * Default value is #ETHUMB_THUMB_ORIENT_ORIGINAL: metadata from the file
1571 * will be used to orient pixel data.
1573 * @param client the client instance to use. Must @b not be @c
1574 * NULL. May be pending connected (can be called before @c
1576 * @param f format identifier to use, either #ETHUMB_THUMB_ORIENT_NONE (0),
1577 * #ETHUMB_THUMB_ROTATE_90_CW (1), #ETHUMB_THUMB_ROTATE_180 (2),
1578 * #ETHUMB_THUMB_ROTATE_90_CCW (3), #ETHUMB_THUMB_FLIP_HORIZONTAL (4),
1579 * #ETHUMB_THUMB_FLIP_VERTICAL (5), #ETHUMB_THUMB_FLIP_TRANSPOSE (6),
1580 * #ETHUMB_THUMB_FLIP_TRANSVERSE (7) or #ETHUMB_THUMB_ORIENT_ORIGINAL
1581 * (8). Default is ORIGINAL.
1584 ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o)
1586 EINA_SAFETY_ON_NULL_RETURN(client);
1588 client->ethumb_dirty = 1;
1589 ethumb_thumb_orientation_set(client->ethumb, o);
1593 * Get current orientation in use for requests.
1595 * @param client the client instance to use. Must @b not be @c
1596 * NULL. May be pending connected (can be called before @c
1599 * @return orientation in use for future requests.
1601 EAPI Ethumb_Thumb_Orientation
1602 ethumb_client_orientation_get(const Ethumb_Client *client)
1604 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1606 return ethumb_thumb_orientation_get(client->ethumb);
1610 * Configure crop alignment in use for future requests.
1612 * @param client the client instance to use. Must @b not be @c
1613 * NULL. May be pending connected (can be called before @c
1615 * @param x horizontal alignment. 0.0 means left side will be visible
1616 * or right side is being lost. 1.0 means right side will be
1617 * visible or left side is being lost. 0.5 means just center is
1618 * visible, both sides will be lost. Default is 0.5.
1619 * @param y vertical alignment. 0.0 is top visible, 1.0 is bottom
1620 * visible, 0.5 is center visible. Default is 0.5
1623 ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y)
1625 EINA_SAFETY_ON_NULL_RETURN(client);
1627 client->ethumb_dirty = 1;
1628 ethumb_thumb_crop_align_set(client->ethumb, x, y);
1632 * Get current crop alignment in use for requests.
1634 * @param client the client instance to use. Must @b not be @c
1635 * NULL. May be pending connected (can be called before @c
1637 * @param x where to return horizontal alignment. May be @c NULL.
1638 * @param y where to return vertical alignment. May be @c NULL.
1641 ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y)
1645 EINA_SAFETY_ON_NULL_RETURN(client);
1647 ethumb_thumb_crop_align_get(client->ethumb, x, y);
1651 * Configure quality to be used in thumbnails.
1653 * @param client the client instance to use. Must @b not be @c
1654 * NULL. May be pending connected (can be called before @c
1656 * @param quality value from 0 to 100, default is 80. The effect
1657 * depends on the format being used, PNG will not use it.
1660 ethumb_client_quality_set(Ethumb_Client *client, int quality)
1662 EINA_SAFETY_ON_NULL_RETURN(client);
1664 ethumb_thumb_quality_set(client->ethumb, quality);
1668 * Get quality to be used in thumbnails.
1670 * @param client the client instance to use. Must @b not be @c
1671 * NULL. May be pending connected (can be called before @c
1674 * @return quality value from 0 to 100, default is 80. The effect
1675 * depends on the format being used, PNG will not use it.
1678 ethumb_client_quality_get(const Ethumb_Client *client)
1680 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1682 return ethumb_thumb_quality_get(client->ethumb);
1686 * Configure compression level used in requests.
1688 * @param client the client instance to use. Must @b not be @c
1689 * NULL. May be pending connected (can be called before @c
1691 * @param compress value from 0 to 9, default is 9. The effect
1692 * depends on the format being used, JPEG will not use it.
1695 ethumb_client_compress_set(Ethumb_Client *client, int compress)
1697 EINA_SAFETY_ON_NULL_RETURN(client);
1699 ethumb_thumb_compress_set(client->ethumb, compress);
1703 * Get compression level used in requests.
1705 * @param client the client instance to use. Must @b not be @c
1706 * NULL. May be pending connected (can be called before @c
1709 * @return compress value from 0 to 9, default is 9. The effect
1710 * depends on the format being used, JPEG will not use it.
1713 ethumb_client_compress_get(const Ethumb_Client *client)
1715 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1717 return ethumb_thumb_compress_get(client->ethumb);
1721 * Set frame to apply to future thumbnails.
1723 * This will create an edje object that will have image swallowed
1724 * in. This can be used to simulate Polaroid or wood frames in the
1725 * generated image. Remeber it is bad to modify the original contents
1726 * of thumbnails, but sometimes it's useful to have it composited and
1727 * avoid runtime overhead.
1729 * @param client the client instance to use. Must @b not be @c
1730 * NULL. May be pending connected (can be called before @c
1732 * @param file file path to edje.
1733 * @param group group inside edje to use.
1734 * @param swallow name of swallow part.
1737 ethumb_client_frame_set(Ethumb_Client *client, const char *file, const char *group, const char *swallow)
1739 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1741 client->ethumb_dirty = 1;
1742 return ethumb_frame_set(client->ethumb, file, group, swallow);
1746 * Configure where to store thumbnails in future requests.
1748 * This value will be used to generate thumbnail paths, that is, it
1749 * will be used when ethumb_client_thumb_path_set() was not called
1750 * after last ethumb_client_file_set().
1752 * Note that this is the base, a category is added to this path as a
1753 * sub directory. This is not the final directory where files are
1754 * stored, the thumbnail system will account @b category as well, see
1755 * ethumb_client_category_set().
1757 * As other options, this value will only be applied to future
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 path base directory where to store thumbnails. Default is
1766 * @see ethumb_client_category_set()
1769 ethumb_client_dir_path_set(Ethumb_Client *client, const char *path)
1771 EINA_SAFETY_ON_NULL_RETURN(client);
1773 client->ethumb_dirty = 1;
1774 ethumb_thumb_dir_path_set(client->ethumb, path);
1778 * Get base directory path where to store thumbnails.
1780 * @param client the client instance to use. Must @b not be @c
1781 * NULL. May be pending connected (can be called before @c
1784 * @return pointer to internal string with current path. This string
1785 * should not be modified or freed.
1787 * @see ethumb_client_dir_path_set()
1790 ethumb_client_dir_path_get(const Ethumb_Client *client)
1792 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1794 return ethumb_thumb_dir_path_get(client->ethumb);
1798 * Category directory to store thumbnails.
1800 * This value will be used to generate thumbnail paths, that is, it
1801 * will be used when ethumb_client_thumb_path_set() was not called
1802 * after last ethumb_client_file_set().
1804 * This is a sub-directory inside base directory
1805 * (ethumb_client_dir_path_set()) that creates a namespace to avoid
1806 * different options resulting in the same file.
1808 * As other options, this value will only be applied to future
1811 * @param client the client instance to use. Must @b not be @c
1812 * NULL. May be pending connected (can be called before @c
1814 * @param category category sub directory to store thumbnail. Default
1815 * is either "normal" or "large" for FDO compliant thumbnails
1816 * or WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string
1817 * or @c NULL to use auto generated names.
1819 * @see ethumb_client_dir_path_set()
1822 ethumb_client_category_set(Ethumb_Client *client, const char *category)
1824 EINA_SAFETY_ON_NULL_RETURN(client);
1826 client->ethumb_dirty = 1;
1827 ethumb_thumb_category_set(client->ethumb, category);
1831 * Get category sub-directory where to store thumbnails.
1833 * @param client the client instance to use. Must @b not be @c
1834 * NULL. May be pending connected (can be called before @c
1837 * @return pointer to internal string with current path. This string
1838 * should not be modified or freed.
1840 * @see ethumb_client_category_set()
1843 ethumb_client_category_get(const Ethumb_Client *client)
1845 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1847 return ethumb_thumb_category_get(client->ethumb);
1851 * Set the video time (duration) in seconds.
1853 * @param client the client instance to use. Must @b not be @c
1854 * NULL. May be pending connected (can be called before @c
1856 * @param t duration (in seconds). Defaults to 3 seconds.
1859 ethumb_client_video_time_set(Ethumb_Client *client, float t)
1861 EINA_SAFETY_ON_NULL_RETURN(client);
1863 client->ethumb_dirty = 1;
1864 ethumb_video_time_set(client->ethumb, t);
1868 * Set initial video position to start thumbnailing, in percentage.
1870 * This is useful to avoid thumbnailing the company/producer logo or
1873 * @param client the client instance to use. Must @b not be @c
1874 * NULL. May be pending connected (can be called before @c
1876 * @param start initial video positon to thumbnail, in percentage (0.0
1877 * to 1.0, inclusive). Defaults to 10% (0.1).
1880 ethumb_client_video_start_set(Ethumb_Client *client, float start)
1882 EINA_SAFETY_ON_NULL_RETURN(client);
1883 EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0);
1884 EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0);
1886 client->ethumb_dirty = 1;
1887 ethumb_video_start_set(client->ethumb, start);
1891 * Set the video frame interval, in seconds.
1893 * This is useful for animated thumbnail and will define skip time
1894 * before going to the next frame. Note that video backends might not
1895 * be able to precisely skip that amount as it will depend on various
1896 * factors, including video encoding.
1898 * Although this seems similar to ethumb_client_video_fps_set(), this
1899 * one is the time that will be used to seek. The math is simple, for
1900 * each new frame the video position will be set to:
1901 * ((video_length * start_time) + (interval * current_frame_number)).
1903 * @param client the client instance to use. Must @b not be @c
1904 * NULL. May be pending connected (can be called before @c
1906 * @param interval time between frames, in seconds. Defaults to 0.05
1910 ethumb_client_video_interval_set(Ethumb_Client *client, float interval)
1912 EINA_SAFETY_ON_NULL_RETURN(client);
1914 client->ethumb_dirty = 1;
1915 ethumb_video_interval_set(client->ethumb, interval);
1919 * Set the number of frames to thumbnail.
1921 * This is useful for animated thumbnail and will define how many
1922 * frames the generated file will have.
1924 * @param client the client instance to use. Must @b not be @c
1925 * NULL. May be pending connected (can be called before @c
1927 * @param ntimes number of times, must be greater than zero.
1931 ethumb_client_video_ntimes_set(Ethumb_Client *client, unsigned int ntimes)
1933 EINA_SAFETY_ON_NULL_RETURN(client);
1934 EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0);
1936 client->ethumb_dirty = 1;
1937 ethumb_video_ntimes_set(client->ethumb, ntimes);
1941 * Set the number of frames per second to thumbnail the video.
1943 * This configures the number of times per seconds the thumbnail will
1944 * use to create thumbnails.
1946 * Although this is similar to ethumb_client_video_interval_set(), it
1947 * is the delay used between calling functions thata generates frames,
1948 * while the other is the time used to skip inside the video.
1950 * @param client the client instance to use. Must @b not be @c
1951 * NULL. May be pending connected (can be called before @c
1953 * @param fps number of frames per second to thumbnail. Must be greater
1954 * than zero. Defaults to 10.
1957 ethumb_client_video_fps_set(Ethumb_Client *client, unsigned int fps)
1959 EINA_SAFETY_ON_NULL_RETURN(client);
1960 EINA_SAFETY_ON_FALSE_RETURN(fps > 0);
1962 client->ethumb_dirty = 1;
1963 ethumb_video_fps_set(client->ethumb, fps);
1967 * Set the page number to thumbnail in paged documents.
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 page page number, defaults to 0 (first).
1975 ethumb_client_document_page_set(Ethumb_Client *client, unsigned int page)
1977 EINA_SAFETY_ON_NULL_RETURN(client);
1979 client->ethumb_dirty = 1;
1980 ethumb_document_page_set(client->ethumb, page);
1984 * Set source file to be thumbnailed.
1986 * Calling this function has the side effect of resetting values set
1987 * with ethumb_client_thumb_path_set() or auto-generated with
1988 * ethumb_client_thumb_exists().
1990 * @param client the client instance to use. Must @b not be @c
1991 * NULL. May be pending connected (can be called before @c
1993 * @param path the filesystem path to use. May be @c NULL.
1994 * @param key the extra argument/key inside @a path to read image
1995 * from. This is only used for formats that allow multiple
1996 * resources in one file, like EET or Edje (group name).
1998 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
2001 ethumb_client_file_set(Ethumb_Client *client, const char *path, const char *key)
2003 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
2005 return ethumb_file_set(client->ethumb, path, key);
2009 * Get values set with ethumb_client_file_get()
2011 * @param client the client instance to use. Must @b not be @c
2012 * NULL. May be pending connected (can be called before @c
2014 * @param path where to return configured path. May be @c NULL. If
2015 * not @c NULL, then it will be a pointer to a stringshared
2016 * instance, but @b no references are added (do it with
2017 * eina_stringshare_ref())!
2018 * @param key where to return configured key. May be @c NULL.If not @c
2019 * NULL, then it will be a pointer to a stringshared instance,
2020 * but @b no references are added (do it with
2021 * eina_stringshare_ref())!
2024 ethumb_client_file_get(Ethumb_Client *client, const char **path, const char **key)
2026 if (path) *path = NULL;
2027 if (key) *key = NULL;
2028 EINA_SAFETY_ON_NULL_RETURN(client);
2030 ethumb_file_get(client->ethumb, path, key);
2034 * Reset previously set file to @c NULL.
2036 * @param client the client instance to use. Must @b not be @c
2037 * NULL. May be pending connected (can be called before @c
2041 ethumb_client_file_free(Ethumb_Client *client)
2043 EINA_SAFETY_ON_NULL_RETURN(client);
2045 ethumb_file_free(client->ethumb);
2049 * Set a defined path and key to store the thumbnail.
2051 * If not explicitly given, the thumbnail path will be auto-generated
2052 * by ethumb_client_thumb_exists() or server using configured
2053 * parameters like size, aspect and category.
2055 * Set these to @c NULL to forget previously given values. After
2056 * ethumb_client_file_set() these values will be reset to @c NULL.
2058 * @param client the client instance to use. Must @b not be @c
2059 * NULL. May be pending connected (can be called before @c
2061 * @param path force generated thumbnail to the exact given path. If
2062 * @c NULL, then reverts back to auto-generation.
2063 * @param key force generated thumbnail to the exact given key. If
2064 * @c NULL, then reverts back to auto-generation.
2067 ethumb_client_thumb_path_set(Ethumb_Client *client, const char *path, const char *key)
2069 EINA_SAFETY_ON_NULL_RETURN(client);
2071 ethumb_thumb_path_set(client->ethumb, path, key);
2075 * Get the configured thumbnail path.
2077 * This returns the value set with ethumb_client_thumb_path_set() or
2078 * auto-generated by ethumb_client_thumb_exists() if it was not set.
2080 * @param client the client instance to use. Must @b not be @c
2081 * NULL. May be pending connected (can be called before @c
2083 * @param path where to return configured path. May be @c NULL. If
2084 * there was no path configured with
2085 * ethumb_client_thumb_path_set() and
2086 * ethumb_client_thumb_exists() was not called, then it will
2087 * probably return @c NULL. If not @c NULL, then it will be a
2088 * pointer to a stringshared instance, but @b no references are
2089 * added (do it with eina_stringshare_ref())!
2090 * @param key where to return configured key. May be @c NULL. If
2091 * there was no key configured with
2092 * ethumb_client_thumb_key_set() and
2093 * ethumb_client_thumb_exists() was not called, then it will
2094 * probably return @c NULL. If not @c NULL, then it will be a
2095 * pointer to a stringshared instance, but @b no references are
2096 * added (do it with eina_stringshare_ref())!
2099 ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const char **key)
2101 if (path) *path = NULL;
2102 if (key) *key = NULL;
2103 EINA_SAFETY_ON_NULL_RETURN(client);
2105 ethumb_thumb_path_get(client->ethumb, path, key);
2109 * Checks whenever file already exists (locally!)
2111 * This will check locally (not calling server) if thumbnail already
2112 * exists or not, also calculating the thumbnail path. See
2113 * ethumb_client_thumb_path_get(). Path must be configured with
2114 * ethumb_client_file_set() before using it and the last set file will
2117 * @param client client instance. Must @b not be @c NULL and client
2118 * must be configured with ethumb_client_file_set().
2120 * @return @c EINA_TRUE if it exists, @c EINA_FALSE otherwise.
2122 EAPI Ethumb_Exists *
2123 ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
2125 Ethumb_Async_Exists *async;
2127 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
2129 async = malloc(sizeof (Ethumb_Async_Exists));
2132 exists_cb(client, NULL, EINA_FALSE, (void*) data);
2136 async->dup = ethumb_dup(client->ethumb);
2137 async->source = client;
2138 async->source->refcount++;
2139 async->exists_cb = exists_cb;
2141 async->exists = EINA_FALSE;
2143 async->refcount = 1;
2144 async->thread = ecore_thread_run(_ethumb_client_exists_heavy,
2145 _ethumb_client_exists_end,
2146 _ethumb_client_exists_cancel,
2149 return (Ethumb_Exists*) async;
2153 * Cancel an ongoing exists request.
2155 * @param exists the request to cancel.
2158 ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
2160 Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
2164 if (async->refcount > 0) return ;
2166 ecore_thread_cancel(async->thread);
2170 * Check if an exists request was cancelled.
2172 * @param exists the request to check.
2173 * @result return EINA_TRUE if the request was cancelled.
2176 ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
2178 Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
2180 if (!async) return EINA_TRUE;
2182 return ecore_thread_check(async->thread);
2186 * Ask server to generate thumbnail.
2188 * This process is asynchronous and will report back from main loop
2189 * using @a generated_cb. One can cancel this request by calling
2190 * ethumb_client_generate_cancel() or
2191 * ethumb_client_generate_cancel_all(), but not that request might be
2192 * processed by server already and no generated files will be removed
2193 * if that is the case.
2195 * This will not check if file already exists, this should be done by
2196 * explicitly calling ethumb_client_thumb_exists(). That is, this
2197 * function will override any existing thumbnail.
2199 * @param client client instance. Must @b not be @c NULL and client
2200 * must be connected (after connected_cb is called).
2201 * @param generated_cb function to report generation results.
2202 * @param data context argument to give back to @a generated_cb. May
2204 * @param data context to give back to @a generate_cb. May be @c
2206 * @param free_data used to release @a data resources after @a
2207 * generated_cb is called or user calls
2208 * ethumb_client_disconnect().
2210 * @return identifier or -1 on error. If -1 is returned (error) then
2211 * @a free_data is @b not called!
2213 * @see ethumb_client_connect()
2214 * @see ethumb_client_file_set()
2215 * @see ethumb_client_thumb_exists()
2216 * @see ethumb_client_generate_cancel()
2217 * @see ethumb_client_generate_cancel_all()
2220 ethumb_client_generate(Ethumb_Client *client, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data)
2222 const char *file, *key, *thumb, *thumb_key;
2224 EINA_SAFETY_ON_NULL_RETURN_VAL(client, -1);
2225 EINA_SAFETY_ON_FALSE_RETURN_VAL(client->connected, -1);
2227 ethumb_file_get(client->ethumb, &file, &key);
2230 ERR("no file set.");
2234 ethumb_thumb_path_get(client->ethumb, &thumb, &thumb_key);
2236 if (client->ethumb_dirty)
2237 ethumb_client_ethumb_setup(client);
2238 id = _ethumb_client_queue_add(client, file, key, thumb, thumb_key,
2239 generated_cb, data, free_data);