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>
82 #include "Ethumb_Client.h"
88 #define MAX_ID 2000000
90 static int _log_dom = -1;
91 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
92 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
93 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
94 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
95 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
102 E_DBus_Connection *conn;
103 E_DBus_Signal_Handler *name_owner_changed_handler;
104 E_DBus_Signal_Handler *generated_signal;
105 DBusPendingCall *pending_get_name_owner;
106 DBusPendingCall *pending_start_service_by_name;
107 const char *unique_name;
108 DBusPendingCall *pending_new;
110 Ethumb_Client_Connect_Cb cb;
112 Eina_Free_Cb free_data;
114 Eina_List *pending_add;
115 Eina_List *pending_remove;
116 Eina_List *pending_gen;
117 DBusPendingCall *pending_clear;
118 DBusPendingCall *pending_setup;
120 Ethumb_Client_Die_Cb cb;
122 Eina_Free_Cb free_data;
124 const char *object_path;
126 Eina_Bool ethumb_dirty : 1;
127 Eina_Bool connected : 1;
128 Eina_Bool server_started : 1;
131 struct _ethumb_pending_add
137 const char *thumb_key;
138 Ethumb_Client_Generate_Cb generated_cb;
140 Eina_Free_Cb free_data;
141 DBusPendingCall *pending_call;
142 Ethumb_Client *client;
145 struct _ethumb_pending_remove
148 Ethumb_Client_Generate_Cancel_Cb cancel_cb;
150 Eina_Free_Cb free_data;
151 DBusPendingCall *pending_call;
152 Ethumb_Client *client;
155 struct _ethumb_pending_gen
161 const char *thumb_key;
162 Ethumb_Client_Generate_Cb generated_cb;
164 Eina_Free_Cb free_data;
167 static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
168 static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
169 static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
170 static const char _ethumb_dbus_path[] = "/org/enlightenment/Ethumb";
171 static const char fdo_interface[] = "org.freedesktop.DBus";
172 static const char fdo_bus_name[] = "org.freedesktop.DBus";
173 static const char fdo_path[] = "/org/freedesktop/DBus";
175 static int _initcount = 0;
177 static void _ethumb_client_generated_cb(void *data, DBusMessage *msg);
178 static void _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err);
181 __dbus_callback_check_and_init(const char *file, int line, const char *function, DBusMessage *msg, DBusMessageIter *itr, DBusError *err)
185 ERR("%s:%d:%s() callback without message arguments!",
186 file, line, function);
189 ERR("%s:%d:%s() an error was reported by server: "
190 "name=\"%s\", message=\"%s\"",
191 file, line, function, err->name, err->message);
196 if (!dbus_message_iter_init(msg, itr))
198 ERR("%s:%d:%s() could not init iterator.",
199 file, line, function);
206 #define _dbus_callback_check_and_init(msg, itr, err) \
207 __dbus_callback_check_and_init(__FILE__, __LINE__, __FUNCTION__, \
211 __dbus_iter_type_check(int type, int expected, const char *expected_name)
213 if (type == expected)
216 ERR("expected type %s (%c) but got %c instead!",
217 expected_name, expected, type);
221 #define _dbus_iter_type_check(t, e) __dbus_iter_type_check(t, e, #e)
223 #define CHECK_NULL_RETURN(ptr, ...) \
228 CRITICAL("%s == NULL!", #ptr); \
229 return __VA_ARGS__; \
235 _ethumb_client_name_owner_changed(void *data, DBusMessage *msg)
238 const char *name, *from, *to;
239 Ethumb_Client *client = data;
241 dbus_error_init(&err);
242 if (!dbus_message_get_args(msg, &err,
243 DBUS_TYPE_STRING, &name,
244 DBUS_TYPE_STRING, &from,
245 DBUS_TYPE_STRING, &to,
248 ERR("could not get NameOwnerChanged arguments: %s: %s",
249 err.name, err.message);
250 dbus_error_free(&err);
256 if (strcmp(name, _ethumb_dbus_bus_name) != 0)
259 DBG("NameOwnerChanged from=[%s] to=[%s]", from, to);
261 if (from[0] != '\0' && to[0] == '\0')
263 DBG("exit ethumbd at %s", from);
264 if (client->unique_name && strcmp(client->unique_name, from) != 0)
265 WRN("%s was not the known name %s, ignored.",
266 from, client->unique_name);
267 else if(client->unique_name)
269 ERR("server exit!!!");
272 client->die.cb(client->die.data, client);
273 client->die.cb = NULL;
275 if (client->die.free_data)
277 client->die.free_data(client->die.data);
278 client->die.free_data = NULL;
279 client->die.data = NULL;
284 DBG("unknown change from %s to %s", from, to);
288 _ethumb_client_report_connect(Ethumb_Client *client, Eina_Bool success)
290 if (!client->connect.cb)
292 ERR("already called?!");
296 client->connect.cb(client->connect.data, client, success);
297 if (client->connect.free_data)
299 client->connect.free_data(client->connect.data);
300 client->connect.free_data = NULL;
302 client->connect.cb = NULL;
303 client->connect.data = NULL;
307 _ethumb_client_new_cb(void *data, DBusMessage *msg, DBusError *error)
309 DBusMessageIter iter;
312 Ethumb_Client *client = data;
314 client->pending_new = NULL;
316 if (!_dbus_callback_check_and_init(msg, &iter, error))
318 t = dbus_message_iter_get_arg_type(&iter);
319 if (!_dbus_iter_type_check(t, DBUS_TYPE_OBJECT_PATH))
322 dbus_message_iter_get_basic(&iter, &opath);
323 if (opath[0] == '\0')
326 client->object_path = eina_stringshare_add(opath);
328 client->generated_signal = e_dbus_signal_handler_add(
329 client->conn, _ethumb_dbus_bus_name, opath,
330 _ethumb_dbus_objects_interface, "generated",
331 _ethumb_client_generated_cb, client);
333 _ethumb_client_report_connect(client, 1);
337 _ethumb_client_report_connect(client, 0);
341 _ethumb_client_call_new(Ethumb_Client *client)
345 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name, _ethumb_dbus_path,
346 _ethumb_dbus_interface, "new");
347 client->pending_new = e_dbus_message_send(client->conn, msg,
348 _ethumb_client_new_cb, -1,
350 dbus_message_unref(msg);
354 _ethumb_client_start_server_cb(void *data, DBusMessage *msg, DBusError *err)
356 Ethumb_Client *client = data;
357 DBusMessageIter iter;
361 client->pending_start_service_by_name = NULL;
363 if (!_dbus_callback_check_and_init(msg, &iter, err))
366 t = dbus_message_iter_get_arg_type(&iter);
367 if (!_dbus_iter_type_check(t, DBUS_TYPE_UINT32))
370 dbus_message_iter_get_basic(&iter, &ret);
371 if ((ret != 1) && (ret != 2))
373 ERR("Error starting Ethumbd DBus service by its name: retcode %u",
378 client->server_started = 1;
379 DBG("Ethumbd DBus service started successfully (%d), now request its name",
382 if (client->pending_get_name_owner)
384 DBG("already requesting name owner, cancel and try again");
385 dbus_pending_call_cancel(client->pending_get_name_owner);
388 client->pending_get_name_owner = e_dbus_get_name_owner
389 (client->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
391 if (!client->pending_get_name_owner)
393 ERR("could not create a get_name_owner request.");
400 ERR("failed to start Ethumbd DBus service by its name.");
401 _ethumb_client_report_connect(client, 0);
405 _ethumb_client_start_server(Ethumb_Client *client)
407 if (client->pending_start_service_by_name)
409 DBG("already pending start service by name.");
413 client->server_started = 0;
414 client->pending_start_service_by_name = e_dbus_start_service_by_name
415 (client->conn, _ethumb_dbus_bus_name, 0, _ethumb_client_start_server_cb,
417 if (!client->pending_start_service_by_name)
419 ERR("could not start service by name!");
420 _ethumb_client_report_connect(client, 0);
425 _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err)
427 DBusMessageIter iter;
429 Ethumb_Client *client = data;
432 client->pending_get_name_owner = NULL;
434 if (dbus_error_is_set(err) && (!client->server_started))
436 DBG("could not find server (%s), try to start it...", err->message);
437 _ethumb_client_start_server(client);
441 if (!_dbus_callback_check_and_init(msg, &iter, err))
444 t = dbus_message_iter_get_arg_type(&iter);
445 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
448 dbus_message_iter_get_basic(&iter, &uid);
451 ERR("no name owner!");
455 DBG("unique name = %s", uid);
456 client->unique_name = eina_stringshare_add(uid);
458 _ethumb_client_call_new(client);
459 client->connected = 1;
463 _ethumb_client_report_connect(client, 0);
471 * @brief Initialize the Ethumb_Client library.
473 * @return 1 or greater on success, 0 on error.
475 * This function sets up all the Ethumb_Client module dependencies. It
476 * returns 0 on failure (that is, when one of the dependency fails to
477 * initialize), otherwise it returns the number of times it has
478 * already been called.
480 * When Ethumb_Client is not used anymore, call
481 * ethumb_client_shutdown() to shut down the Ethumb_Client library.
483 * @see ethumb_client_shutdown()
484 * @see ethumb_client_connect()
485 * @see @ref tutorial_ethumb_client
488 ethumb_client_init(void)
495 fprintf(stderr, "ERROR: Could not initialize log module.\n");
498 _log_dom = eina_log_domain_register("ethumb_client", EINA_COLOR_YELLOW);
501 EINA_LOG_ERR("Could not register log domain: ethumb_client");
513 * @brief Shut down the Ethumb_Client library.
515 * @return 0 when everything is shut down, 1 or greater if there are
516 * other users of the Ethumb_Client library pending shutdown.
518 * This function shuts down the Ethumb_Client library. It returns 0
519 * when it has been called the same number of times than
520 * ethumb_client_init(). In that case it shut down all the
521 * Ethumb_Client modules dependencies.
523 * Once this function succeeds (that is, @c 0 is returned), you must
524 * not call any of the Eina function anymore. You must call
525 * ethumb_client_init() again to use the Ethumb_Client functions
529 ethumb_client_shutdown(void)
537 eina_log_domain_unregister(_log_dom);
544 * Connects to Ethumb server and return the client instance.
546 * This is the "constructor" of Ethumb_Client, where everything
549 * If server was down, it is tried to start it using DBus activation,
550 * then the connection is retried.
552 * This call is asynchronous and will not block, instead it will be in
553 * "not connected" state until @a connect_cb is called with either
554 * success or failure. On failure, then no methods should be
555 * called. On success you're now able to setup and then ask generation
558 * Usually you should listen for server death/disconenction with
559 * ethumb_client_on_server_die_callback_set().
561 * @param connect_cb function to call to report connection success or
562 * failure. Do not call any other ethumb_client method until
563 * this function returns. The first received parameter is the
564 * given argument @a data. Must @b not be @c NULL. This
565 * function will not be called if user explicitly calls
566 * ethumb_client_disconnect().
567 * @param data context to give back to @a connect_cb. May be @c NULL.
568 * @param free_data function used to release @a data resources, if
569 * any. May be @c NULL. If this function exists, it will be
570 * called immediately after @a connect_cb is called or if user
571 * explicitly calls ethumb_client_disconnect() before such
572 * (that is, don't rely on @a data after @a connect_cb was
575 * @return client instance or NULL if failed. If @a connect_cb is
576 * missing it returns @c NULL. If it fail for other
577 * conditions, @c NULL is also returned and @a connect_cb is
578 * called with @c success=EINA_FALSE. The client instance is
579 * not ready to be used until @a connect_cb is called.
582 ethumb_client_connect(Ethumb_Client_Connect_Cb connect_cb, const void *data, Eina_Free_Cb free_data)
584 Ethumb_Client *eclient;
586 EINA_SAFETY_ON_NULL_RETURN_VAL(connect_cb, NULL);
588 eclient = calloc(1, sizeof(*eclient));
591 ERR("could not allocate Ethumb_Client structure.");
595 eclient->connect.cb = connect_cb;
596 eclient->connect.data = (void *)data;
597 eclient->connect.free_data = free_data;
599 eclient->ethumb = ethumb_new();
600 if (!eclient->ethumb)
602 ERR("could not create ethumb handler.");
606 eclient->conn = e_dbus_bus_get(DBUS_BUS_SESSION);
609 ERR("could not connect to session bus.");
613 eclient->name_owner_changed_handler = e_dbus_signal_handler_add(
614 eclient->conn, fdo_bus_name, fdo_path, fdo_interface,
615 "NameOwnerChanged", _ethumb_client_name_owner_changed, eclient);
617 eclient->pending_get_name_owner = e_dbus_get_name_owner(
618 eclient->conn, _ethumb_dbus_bus_name, _ethumb_client_get_name_owner,
620 if (!eclient->pending_get_name_owner)
622 ERR("could not create a get_name_owner request.");
629 ethumb_free(eclient->ethumb);
633 connect_cb((void *)data, NULL, EINA_FALSE);
635 free_data((void *)data);
640 * Disconnect the client, releasing all client resources.
642 * This is the destructor of Ethumb_Client, after it's disconnected
643 * the client handle is now gone and should not be used.
645 * @param client client instance to be destroyed. Must @b not be @c
649 ethumb_client_disconnect(Ethumb_Client *client)
653 EINA_SAFETY_ON_NULL_RETURN(client);
655 if (!client->connected)
658 EINA_LIST_FREE(client->pending_add, data)
660 struct _ethumb_pending_add *pending = data;
661 eina_stringshare_del(pending->file);
662 eina_stringshare_del(pending->key);
663 eina_stringshare_del(pending->thumb);
664 eina_stringshare_del(pending->thumb_key);
665 dbus_pending_call_cancel(pending->pending_call);
666 dbus_pending_call_unref(pending->pending_call);
667 if (pending->free_data)
668 pending->free_data(pending->data);
672 EINA_LIST_FREE(client->pending_gen, data)
674 struct _ethumb_pending_gen *pending = data;
675 eina_stringshare_del(pending->file);
676 eina_stringshare_del(pending->key);
677 eina_stringshare_del(pending->thumb);
678 eina_stringshare_del(pending->thumb_key);
679 if (pending->free_data)
680 pending->free_data(pending->data);
684 EINA_LIST_FREE(client->pending_remove, data)
686 struct _ethumb_pending_remove *pending = data;
687 dbus_pending_call_cancel(pending->pending_call);
688 dbus_pending_call_unref(pending->pending_call);
689 if (pending->free_data)
690 pending->free_data(pending->data);
694 if (client->pending_clear)
696 dbus_pending_call_cancel(client->pending_clear);
697 dbus_pending_call_unref(client->pending_clear);
701 if (client->object_path)
702 eina_stringshare_del(client->object_path);
704 if (client->pending_new)
705 dbus_pending_call_cancel(client->pending_new);
707 if (client->unique_name)
708 eina_stringshare_del(client->unique_name);
710 if (client->pending_get_name_owner)
711 dbus_pending_call_cancel(client->pending_get_name_owner);
713 if (client->pending_start_service_by_name)
714 dbus_pending_call_cancel(client->pending_start_service_by_name);
716 ethumb_free(client->ethumb);
718 e_dbus_signal_handler_del(client->conn, client->name_owner_changed_handler);
719 if (client->connected)
720 e_dbus_signal_handler_del(client->conn, client->generated_signal);
721 e_dbus_connection_close(client->conn);
723 if (client->connect.free_data)
724 client->connect.free_data(client->connect.data);
725 if (client->die.free_data)
726 client->die.free_data(client->die.data);
732 * Sets the callback to report server died.
734 * When server dies there is nothing you can do, just release
735 * resources with ethumb_client_disconnect() and probably try to
738 * Usually you should set this callback and handle this case, it does
741 * @param client the client instance to monitor. Must @b not be @c
743 * @param server_die_cb function to call back when server dies. The
744 * first parameter will be the argument @a data. May be @c
746 * @param data context to give back to @a server_die_cb. May be @c
748 * @param free_data used to release @a data resources after @a
749 * server_die_cb is called or user calls
750 * ethumb_client_disconnect().
753 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)
755 EINA_SAFETY_ON_NULL_RETURN(client);
757 if (client->die.free_data)
758 client->die.free_data(client->die.data);
760 client->die.cb = server_die_cb;
761 client->die.data = (void *)data;
762 client->die.free_data = free_data;
770 _ethumb_client_ethumb_setup_cb(void *data, DBusMessage *msg, DBusError *error)
772 DBusMessageIter iter;
774 dbus_bool_t result = 0;
775 Ethumb_Client *client = data;
777 client->pending_setup = NULL;
779 if (!_dbus_callback_check_and_init(msg, &iter, error))
782 t = dbus_message_iter_get_arg_type(&iter);
783 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
786 dbus_message_iter_get_basic(&iter, &result);
790 _ethumb_client_dbus_get_bytearray(DBusMessageIter *iter)
794 DBusMessageIter riter;
797 el_type = dbus_message_iter_get_element_type(iter);
798 if (el_type != DBUS_TYPE_BYTE)
800 ERR("not an byte array element.");
804 dbus_message_iter_recurse(iter, &riter);
805 dbus_message_iter_get_fixed_array(&riter, &result, &length);
807 if (result[0] == '\0')
810 return eina_stringshare_add(result);
814 _ethumb_client_dbus_append_bytearray(DBusMessageIter *iter, const char *string)
816 DBusMessageIter viter;
821 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &viter);
822 dbus_message_iter_append_fixed_array(&viter, DBUS_TYPE_BYTE, &string,
824 dbus_message_iter_close_container(iter, &viter);
832 * Send setup to server.
834 * This method is called automatically by ethumb_client_generate() if
835 * any property was changed. No need to call it manually.
837 * @param client client instance. Must @b not be @c NULL and client
838 * must be connected (after connected_cb is called).
841 ethumb_client_ethumb_setup(Ethumb_Client *client)
844 DBusMessageIter iter, aiter, diter, viter, vaiter;
845 Ethumb *e = client->ethumb;
847 dbus_int32_t tw, th, format, aspect, orientation, quality, compress;
850 const char *theme_file, *group, *swallow;
851 const char *directory, *category;
852 double video_time, video_start, video_interval;
853 dbus_int32_t video_ntimes, video_fps, document_page;
855 EINA_SAFETY_ON_NULL_RETURN(client);
856 EINA_SAFETY_ON_FALSE_RETURN(client->connected);
857 client->ethumb_dirty = 0;
859 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
861 _ethumb_dbus_objects_interface,
863 dbus_message_iter_init_append(msg, &iter);
864 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &aiter);
869 #define _open_variant_iter(str_entry, str_type, end_iter) \
871 dbus_message_iter_open_container(&aiter, DBUS_TYPE_DICT_ENTRY, NULL, &diter); \
872 dbus_message_iter_append_basic(&diter, DBUS_TYPE_STRING, &entry); \
873 dbus_message_iter_open_container(&diter, DBUS_TYPE_VARIANT, str_type, \
876 #define _close_variant_iter(end_iter) \
877 dbus_message_iter_close_container(&diter, &end_iter); \
878 dbus_message_iter_close_container(&aiter, &diter);
883 /* starting array elements */
885 _open_variant_iter("size", "(ii)", viter);
886 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
887 ethumb_thumb_size_get(e, &tw, &th);
888 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &tw);
889 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_INT32, &th);
890 dbus_message_iter_close_container(&viter, &vaiter);
891 _close_variant_iter(viter);
893 _open_variant_iter("format", "i", viter);
894 format = ethumb_thumb_format_get(e);
895 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &format);
896 _close_variant_iter(viter);
898 _open_variant_iter("aspect", "i", viter);
899 aspect = ethumb_thumb_aspect_get(e);
900 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &aspect);
901 _close_variant_iter(viter);
903 _open_variant_iter("orientation", "i", viter);
904 orientation = ethumb_thumb_orientation_get(e);
905 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &orientation);
906 _close_variant_iter(viter);
908 _open_variant_iter("crop", "(dd)", viter);
909 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
910 ethumb_thumb_crop_align_get(e, &cx, &cy);
912 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
914 dbus_message_iter_append_basic(&vaiter, DBUS_TYPE_DOUBLE, &t);
915 dbus_message_iter_close_container(&viter, &vaiter);
916 _close_variant_iter(viter);
918 _open_variant_iter("quality", "i", viter);
919 quality = ethumb_thumb_quality_get(e);
920 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &quality);
921 _close_variant_iter(viter);
923 _open_variant_iter("compress", "i", viter);
924 compress = ethumb_thumb_compress_get(e);
925 dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &compress);
926 _close_variant_iter(viter);
928 _open_variant_iter("frame", "(ayayay)", viter);
929 dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
930 ethumb_frame_get(e, &theme_file, &group, &swallow);
931 _ethumb_client_dbus_append_bytearray(&vaiter, theme_file);
932 _ethumb_client_dbus_append_bytearray(&vaiter, group);
933 _ethumb_client_dbus_append_bytearray(&vaiter, swallow);
934 dbus_message_iter_close_container(&viter, &vaiter);
935 _close_variant_iter(viter);
937 _open_variant_iter("directory", "ay", viter);
938 directory = ethumb_thumb_dir_path_get(e);
939 _ethumb_client_dbus_append_bytearray(&viter, directory);
940 _close_variant_iter(viter);
942 _open_variant_iter("category", "ay", viter);
943 category = ethumb_thumb_category_get(e);
944 _ethumb_client_dbus_append_bytearray(&viter, category);
945 _close_variant_iter(viter);
947 _open_variant_iter("video_time", "d", viter);
948 video_time = ethumb_video_time_get(e);
949 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time);
950 _close_variant_iter(viter);
952 _open_variant_iter("video_start", "d", viter);
953 video_start = ethumb_video_start_get(e);
954 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start);
955 _close_variant_iter(viter);
957 _open_variant_iter("video_interval", "d", viter);
958 video_interval = ethumb_video_interval_get(e);
959 dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval);
960 _close_variant_iter(viter);
962 _open_variant_iter("video_ntimes", "u", viter);
963 video_ntimes = ethumb_video_ntimes_get(e);
964 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_ntimes);
965 _close_variant_iter(viter);
967 _open_variant_iter("video_fps", "u", viter);
968 video_fps = ethumb_video_fps_get(e);
969 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &video_fps);
970 _close_variant_iter(viter);
972 _open_variant_iter("document_page", "u", viter);
973 document_page = ethumb_document_page_get(e);
974 dbus_message_iter_append_basic(&viter, DBUS_TYPE_UINT32, &document_page);
975 _close_variant_iter(viter);
977 #undef _open_variant_iter
978 #undef _close_variant_iter
980 dbus_message_iter_close_container(&iter, &aiter);
982 client->pending_setup = e_dbus_message_send(client->conn, msg,
983 _ethumb_client_ethumb_setup_cb,
985 dbus_message_unref(msg);
993 _ethumb_client_generated_cb(void *data, DBusMessage *msg)
995 DBusMessageIter iter;
996 dbus_int32_t id = -1;
997 const char *thumb = NULL;
998 const char *thumb_key = NULL;
999 Ethumb_Client *client = data;
1001 dbus_bool_t success;
1004 struct _ethumb_pending_gen *pending;
1006 dbus_message_iter_init(msg, &iter);
1008 t = dbus_message_iter_get_arg_type(&iter);
1009 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1011 dbus_message_iter_get_basic(&iter, &id);
1012 dbus_message_iter_next(&iter);
1014 t = dbus_message_iter_get_arg_type(&iter);
1015 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1017 thumb = _ethumb_client_dbus_get_bytearray(&iter);
1018 dbus_message_iter_next(&iter);
1020 t = dbus_message_iter_get_arg_type(&iter);
1021 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1023 thumb_key = _ethumb_client_dbus_get_bytearray(&iter);
1024 dbus_message_iter_next(&iter);
1026 t = dbus_message_iter_get_arg_type(&iter);
1027 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1029 dbus_message_iter_get_basic(&iter, &success);
1032 l = client->pending_gen;
1036 if (pending->id == id)
1046 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1047 pending->generated_cb(pending->data, client, id,
1048 pending->file, pending->key,
1049 pending->thumb, pending->thumb_key,
1051 if (pending->free_data)
1052 pending->free_data(pending->data);
1053 eina_stringshare_del(pending->file);
1054 eina_stringshare_del(pending->key);
1055 eina_stringshare_del(pending->thumb);
1056 eina_stringshare_del(pending->thumb_key);
1061 if (thumb) eina_stringshare_del(thumb);
1062 if (thumb_key) eina_stringshare_del(thumb_key);
1066 _ethumb_client_queue_add_cb(void *data, DBusMessage *msg, DBusError *error)
1068 DBusMessageIter iter;
1070 dbus_int32_t id = -1;
1071 struct _ethumb_pending_add *pending = data;
1072 struct _ethumb_pending_gen *generating;
1073 Ethumb_Client *client = pending->client;
1075 client->pending_add = eina_list_remove(client->pending_add, pending);
1077 if (!_dbus_callback_check_and_init(msg, &iter, error))
1080 t = dbus_message_iter_get_arg_type(&iter);
1081 if (!_dbus_iter_type_check(t, DBUS_TYPE_INT32))
1084 dbus_message_iter_get_basic(&iter, &id);
1086 generating = calloc(1, sizeof(*generating));
1087 generating->id = id;
1088 generating->file = pending->file;
1089 generating->key = pending->key;
1090 generating->thumb = pending->thumb;
1091 generating->thumb_key = pending->thumb_key;
1092 generating->generated_cb = pending->generated_cb;
1093 generating->data = pending->data;
1094 generating->free_data = pending->free_data;
1095 client->pending_gen = eina_list_append(client->pending_gen, generating);
1102 _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)
1105 DBusMessageIter iter;
1106 struct _ethumb_pending_add *pending;
1108 pending = calloc(1, sizeof(*pending));
1109 pending->id = client->id_count;
1110 pending->file = eina_stringshare_add(file);
1111 pending->key = eina_stringshare_add(key);
1112 pending->thumb = eina_stringshare_add(thumb);
1113 pending->thumb_key = eina_stringshare_add(thumb_key);
1114 pending->generated_cb = generated_cb;
1115 pending->data = (void *)data;
1116 pending->free_data = free_data;
1117 pending->client = client;
1119 client->id_count = (client->id_count + 1) % MAX_ID;
1121 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1122 client->object_path,
1123 _ethumb_dbus_objects_interface,
1126 dbus_message_iter_init_append(msg, &iter);
1127 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &pending->id);
1128 _ethumb_client_dbus_append_bytearray(&iter, file);
1129 _ethumb_client_dbus_append_bytearray(&iter, key);
1130 _ethumb_client_dbus_append_bytearray(&iter, thumb);
1131 _ethumb_client_dbus_append_bytearray(&iter, thumb_key);
1133 pending->pending_call = e_dbus_message_send(client->conn, msg,
1134 _ethumb_client_queue_add_cb,
1136 client->pending_add = eina_list_append(client->pending_add, pending);
1137 dbus_message_unref(msg);
1143 _ethumb_client_queue_remove_cb(void *data, DBusMessage *msg, DBusError *error)
1145 DBusMessageIter iter;
1147 dbus_bool_t success = 0;
1148 struct _ethumb_pending_remove *pending = data;
1149 Ethumb_Client *client = pending->client;
1151 client->pending_remove = eina_list_remove(client->pending_remove, pending);
1153 if (!_dbus_callback_check_and_init(msg, &iter, error))
1156 t = dbus_message_iter_get_arg_type(&iter);
1157 if (!_dbus_iter_type_check(t, DBUS_TYPE_BOOLEAN))
1160 dbus_message_iter_get_basic(&iter, &success);
1163 if (pending->cancel_cb)
1164 pending->cancel_cb(pending->data, success);
1165 if (pending->free_data)
1166 pending->free_data(pending->data);
1174 * Ask server to cancel generation of thumbnail.
1176 * @param client client instance. Must @b not be @c NULL and client
1177 * must be connected (after connected_cb is called).
1178 * @param id valid id returned by ethumb_client_generate()
1179 * @param cancel_cb function to report cancellation results.
1180 * @param data context argument to give back to @a cancel_cb. May be
1182 * @param data context to give back to @a cancel_cb. May be @c
1184 * @param free_data used to release @a data resources after @a
1185 * cancel_cb is called or user calls
1186 * ethumb_client_disconnect().
1189 ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, const void *data, Eina_Free_Cb free_data)
1192 struct _ethumb_pending_remove *pending;
1195 dbus_int32_t id32 = id;
1196 EINA_SAFETY_ON_NULL_RETURN(client);
1197 EINA_SAFETY_ON_FALSE_RETURN(id >= 0);
1199 pending = calloc(1, sizeof(*pending));
1201 pending->cancel_cb = cancel_cb;
1202 pending->data = (void *)data;
1203 pending->free_data = free_data;
1204 pending->client = client;
1206 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1207 client->object_path,
1208 _ethumb_dbus_objects_interface,
1211 dbus_message_append_args(msg, DBUS_TYPE_INT32, &id32, DBUS_TYPE_INVALID);
1212 pending->pending_call = e_dbus_message_send(client->conn, msg,
1213 _ethumb_client_queue_remove_cb,
1215 client->pending_remove = eina_list_append(client->pending_remove, pending);
1218 l = client->pending_add;
1221 struct _ethumb_pending_add *pending = l->data;
1222 if (pending->id != id32)
1227 client->pending_add = eina_list_remove_list(client->pending_add, l);
1228 eina_stringshare_del(pending->file);
1229 eina_stringshare_del(pending->key);
1230 eina_stringshare_del(pending->thumb);
1231 eina_stringshare_del(pending->thumb_key);
1232 dbus_pending_call_cancel(pending->pending_call);
1233 dbus_pending_call_unref(pending->pending_call);
1234 if (pending->free_data)
1235 pending->free_data(pending->data);
1244 l = client->pending_gen;
1247 struct _ethumb_pending_gen *pending = l->data;
1248 if (pending->id != id32)
1253 client->pending_gen = eina_list_remove_list(client->pending_gen, l);
1254 eina_stringshare_del(pending->file);
1255 eina_stringshare_del(pending->key);
1256 eina_stringshare_del(pending->thumb);
1257 eina_stringshare_del(pending->thumb_key);
1258 if (pending->free_data)
1259 pending->free_data(pending->data);
1265 dbus_message_unref(msg);
1272 _ethumb_client_queue_clear_cb(void *data, DBusMessage *msg __UNUSED__, DBusError *error __UNUSED__)
1274 Ethumb_Client *client = data;
1276 client->pending_clear = NULL;
1283 * Ask server to cancel generation of all thumbnails.
1285 * @param client client instance. Must @b not be @c NULL and client
1286 * must be connected (after connected_cb is called).
1288 * @see ethumb_client_generate_cancel()
1291 ethumb_client_generate_cancel_all(Ethumb_Client *client)
1295 EINA_SAFETY_ON_NULL_RETURN(client);
1297 if (client->pending_clear)
1300 EINA_LIST_FREE(client->pending_add, data)
1302 struct _ethumb_pending_add *pending = data;
1303 eina_stringshare_del(pending->file);
1304 eina_stringshare_del(pending->key);
1305 eina_stringshare_del(pending->thumb);
1306 eina_stringshare_del(pending->thumb_key);
1307 dbus_pending_call_cancel(pending->pending_call);
1308 dbus_pending_call_unref(pending->pending_call);
1309 if (pending->free_data)
1310 pending->free_data(pending->data);
1314 EINA_LIST_FREE(client->pending_gen, data)
1316 struct _ethumb_pending_gen *pending = data;
1317 eina_stringshare_del(pending->file);
1318 eina_stringshare_del(pending->key);
1319 eina_stringshare_del(pending->thumb);
1320 eina_stringshare_del(pending->thumb_key);
1321 if (pending->free_data)
1322 pending->free_data(pending->data);
1326 msg = dbus_message_new_method_call(_ethumb_dbus_bus_name,
1327 client->object_path,
1328 _ethumb_dbus_objects_interface,
1331 client->pending_clear = e_dbus_message_send(client->conn, msg,
1332 _ethumb_client_queue_clear_cb,
1335 dbus_message_unref(msg);
1339 * Configure future requests to use FreeDesktop.Org preset.
1341 * This is a preset to provide freedesktop.org (fdo) standard
1342 * compliant thumbnails. That is, files are stored as JPEG under
1343 * ~/.thumbnails/SIZE, with size being either normal (128x128) or
1346 * @param client the client instance to use. Must @b not be @c
1347 * NULL. May be pending connected (can be called before @c
1349 * @param s size identifier, either #ETHUMB_THUMB_NORMAL (0) or
1350 * #ETHUMB_THUMB_LARGE (1).
1352 * @see ethumb_client_size_set()
1353 * @see ethumb_client_aspect_set()
1354 * @see ethumb_client_crop_align_set()
1355 * @see ethumb_client_category_set()
1356 * @see ethumb_client_dir_path_set()
1359 ethumb_client_fdo_set(Ethumb_Client *client, Ethumb_Thumb_FDO_Size s)
1361 EINA_SAFETY_ON_NULL_RETURN(client);
1363 client->ethumb_dirty = 1;
1364 ethumb_thumb_fdo_set(client->ethumb, s);
1368 * Configure future request to use custom size.
1370 * @param client the client instance to use. Must @b not be @c
1371 * NULL. May be pending connected (can be called before @c
1373 * @param tw width, default is 128.
1374 * @param th height, default is 128.
1377 ethumb_client_size_set(Ethumb_Client *client, int tw, int th)
1379 EINA_SAFETY_ON_NULL_RETURN(client);
1381 client->ethumb_dirty = 1;
1382 ethumb_thumb_size_set(client->ethumb, tw, th);
1386 * Retrieve future request to use custom size.
1388 * @param client the client instance to use. Must @b not be @c
1389 * NULL. May be pending connected (can be called before @c
1391 * @param tw where to return width. May be @c NULL.
1392 * @param th where to return height. May be @c NULL.
1395 ethumb_client_size_get(const Ethumb_Client *client, int *tw, int *th)
1399 EINA_SAFETY_ON_NULL_RETURN(client);
1401 ethumb_thumb_size_get(client->ethumb, tw, th);
1405 * Configure format to use for future requests.
1407 * @param client the client instance to use. Must @b not be @c
1408 * NULL. May be pending connected (can be called before @c
1410 * @param f format identifier to use, either #ETHUMB_THUMB_FDO (0),
1411 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2). Default is FDO.
1414 ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f)
1416 EINA_SAFETY_ON_NULL_RETURN(client);
1418 client->ethumb_dirty = 1;
1419 ethumb_thumb_format_set(client->ethumb, f);
1423 * Retrieve format to use for future requests.
1425 * @param client the client instance to use. Must @b not be @c
1426 * NULL. May be pending connected (can be called before @c
1429 * @return format identifier to use, either #ETHUMB_THUMB_FDO (0),
1430 * #ETHUMB_THUMB_JPEG (1) or #ETHUMB_THUMB_EET (2).
1432 EAPI Ethumb_Thumb_Format
1433 ethumb_client_format_get(const Ethumb_Client *client)
1435 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1437 return ethumb_thumb_format_get(client->ethumb);
1441 * Configure aspect mode to use.
1443 * If aspect is kept (#ETHUMB_THUMB_KEEP_ASPECT), then image will be
1444 * rescaled so the largest dimension is not bigger than it's specified
1445 * size (see ethumb_client_size_get()) and the other dimension is
1446 * resized in the same proportion. Example: size is 256x256, image is
1447 * 1000x500, resulting thumbnail is 256x128.
1449 * If aspect is ignored (#ETHUMB_THUMB_IGNORE_ASPECT), then image will
1450 * be distorted to match required thumbnail size. Example: size is
1451 * 256x256, image is 1000x500, resulting thumbnail is 256x256.
1453 * If crop is required (#ETHUMB_THUMB_CROP), then image will be
1454 * cropped so the smallest dimension is not bigger than its specified
1455 * size (see ethumb_client_size_get()) and the other dimension will
1456 * overflow, not being visible in the final image. How it will
1457 * overflow is speficied by ethumb_client_crop_align_set()
1458 * alignment. Example: size is 256x256, image is 1000x500, crop
1459 * alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
1460 * pixels from left and 250 pixels from right being lost, that is just
1461 * the 500x500 central pixels of image will be considered for scaling.
1463 * @param client the client instance to use. Must @b not be @c
1464 * NULL. May be pending connected (can be called before @c
1466 * @param a aspect mode identifier, either #ETHUMB_THUMB_KEEP_ASPECT (0),
1467 * #ETHUMB_THUMB_IGNORE_ASPECT (1) or #ETHUMB_THUMB_CROP (2).
1470 ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a)
1472 EINA_SAFETY_ON_NULL_RETURN(client);
1474 client->ethumb_dirty = 1;
1475 ethumb_thumb_aspect_set(client->ethumb, a);
1479 * Get current aspect in use for requests.
1481 * @param client the client instance to use. Must @b not be @c
1482 * NULL. May be pending connected (can be called before @c
1485 * @return aspect in use for future requests.
1487 EAPI Ethumb_Thumb_Aspect
1488 ethumb_client_aspect_get(const Ethumb_Client *client)
1490 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1492 return ethumb_thumb_aspect_get(client->ethumb);
1496 * Configure orientation to use for future requests.
1498 * Default value is #ETHUMB_THUMB_ORIENT_ORIGINAL: metadata from the file
1499 * will be used to orient pixel data.
1501 * @param client the client instance to use. Must @b not be @c
1502 * NULL. May be pending connected (can be called before @c
1504 * @param f format identifier to use, either #ETHUMB_THUMB_ORIENT_NONE (0),
1505 * #ETHUMB_THUMB_ROTATE_90_CW (1), #ETHUMB_THUMB_ROTATE_180 (2),
1506 * #ETHUMB_THUMB_ROTATE_90_CCW (3), #ETHUMB_THUMB_FLIP_HORIZONTAL (4),
1507 * #ETHUMB_THUMB_FLIP_VERTICAL (5), #ETHUMB_THUMB_FLIP_TRANSPOSE (6),
1508 * #ETHUMB_THUMB_FLIP_TRANSVERSE (7) or #ETHUMB_THUMB_ORIENT_ORIGINAL
1509 * (8). Default is ORIGINAL.
1512 ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o)
1514 EINA_SAFETY_ON_NULL_RETURN(client);
1516 client->ethumb_dirty = 1;
1517 ethumb_thumb_orientation_set(client->ethumb, o);
1521 * Get current orientation in use for requests.
1523 * @param client the client instance to use. Must @b not be @c
1524 * NULL. May be pending connected (can be called before @c
1527 * @return orientation in use for future requests.
1529 EAPI Ethumb_Thumb_Orientation
1530 ethumb_client_orientation_get(const Ethumb_Client *client)
1532 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1534 return ethumb_thumb_orientation_get(client->ethumb);
1538 * Configure crop alignment in use for future requests.
1540 * @param client the client instance to use. Must @b not be @c
1541 * NULL. May be pending connected (can be called before @c
1543 * @param x horizontal alignment. 0.0 means left side will be visible
1544 * or right side is being lost. 1.0 means right side will be
1545 * visible or left side is being lost. 0.5 means just center is
1546 * visible, both sides will be lost. Default is 0.5.
1547 * @param y vertical alignment. 0.0 is top visible, 1.0 is bottom
1548 * visible, 0.5 is center visible. Default is 0.5
1551 ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y)
1553 EINA_SAFETY_ON_NULL_RETURN(client);
1555 client->ethumb_dirty = 1;
1556 ethumb_thumb_crop_align_set(client->ethumb, x, y);
1560 * Get current crop alignment in use for requests.
1562 * @param client the client instance to use. Must @b not be @c
1563 * NULL. May be pending connected (can be called before @c
1565 * @param x where to return horizontal alignment. May be @c NULL.
1566 * @param y where to return vertical alignment. May be @c NULL.
1569 ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y)
1573 EINA_SAFETY_ON_NULL_RETURN(client);
1575 ethumb_thumb_crop_align_get(client->ethumb, x, y);
1579 * Configure quality to be used in thumbnails.
1581 * @param client the client instance to use. Must @b not be @c
1582 * NULL. May be pending connected (can be called before @c
1584 * @param quality value from 0 to 100, default is 80. The effect
1585 * depends on the format being used, PNG will not use it.
1588 ethumb_client_quality_set(Ethumb_Client *client, int quality)
1590 EINA_SAFETY_ON_NULL_RETURN(client);
1592 ethumb_thumb_quality_set(client->ethumb, quality);
1596 * Get quality to be used in thumbnails.
1598 * @param client the client instance to use. Must @b not be @c
1599 * NULL. May be pending connected (can be called before @c
1602 * @return quality value from 0 to 100, default is 80. The effect
1603 * depends on the format being used, PNG will not use it.
1606 ethumb_client_quality_get(const Ethumb_Client *client)
1608 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1610 return ethumb_thumb_quality_get(client->ethumb);
1614 * Configure compression level used in requests.
1616 * @param client the client instance to use. Must @b not be @c
1617 * NULL. May be pending connected (can be called before @c
1619 * @param compress value from 0 to 9, default is 9. The effect
1620 * depends on the format being used, JPEG will not use it.
1623 ethumb_client_compress_set(Ethumb_Client *client, int compress)
1625 EINA_SAFETY_ON_NULL_RETURN(client);
1627 ethumb_thumb_compress_set(client->ethumb, compress);
1631 * Get compression level used in requests.
1633 * @param client the client instance to use. Must @b not be @c
1634 * NULL. May be pending connected (can be called before @c
1637 * @return compress value from 0 to 9, default is 9. The effect
1638 * depends on the format being used, JPEG will not use it.
1641 ethumb_client_compress_get(const Ethumb_Client *client)
1643 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1645 return ethumb_thumb_compress_get(client->ethumb);
1649 * Set frame to apply to future thumbnails.
1651 * This will create an edje object that will have image swallowed
1652 * in. This can be used to simulate Polaroid or wood frames in the
1653 * generated image. Remeber it is bad to modify the original contents
1654 * of thumbnails, but sometimes it's useful to have it composited and
1655 * avoid runtime overhead.
1657 * @param client the client instance to use. Must @b not be @c
1658 * NULL. May be pending connected (can be called before @c
1660 * @param file file path to edje.
1661 * @param group group inside edje to use.
1662 * @param swallow name of swallow part.
1665 ethumb_client_frame_set(Ethumb_Client *client, const char *file, const char *group, const char *swallow)
1667 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1669 client->ethumb_dirty = 1;
1670 return ethumb_frame_set(client->ethumb, file, group, swallow);
1674 * Configure where to store thumbnails in future requests.
1676 * This value will be used to generate thumbnail paths, that is, it
1677 * will be used when ethumb_client_thumb_path_set() was not called
1678 * after last ethumb_client_file_set().
1680 * Note that this is the base, a category is added to this path as a
1681 * sub directory. This is not the final directory where files are
1682 * stored, the thumbnail system will account @b category as well, see
1683 * ethumb_client_category_set().
1685 * As other options, this value will only be applied to future
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 path base directory where to store thumbnails. Default is
1694 * @see ethumb_client_category_set()
1697 ethumb_client_dir_path_set(Ethumb_Client *client, const char *path)
1699 EINA_SAFETY_ON_NULL_RETURN(client);
1701 client->ethumb_dirty = 1;
1702 ethumb_thumb_dir_path_set(client->ethumb, path);
1706 * Get base directory path where to store thumbnails.
1708 * @param client the client instance to use. Must @b not be @c
1709 * NULL. May be pending connected (can be called before @c
1712 * @return pointer to internal string with current path. This string
1713 * should not be modified or freed.
1715 * @see ethumb_client_dir_path_set()
1718 ethumb_client_dir_path_get(const Ethumb_Client *client)
1720 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1722 return ethumb_thumb_dir_path_get(client->ethumb);
1726 * Category directory to store thumbnails.
1728 * This value will be used to generate thumbnail paths, that is, it
1729 * will be used when ethumb_client_thumb_path_set() was not called
1730 * after last ethumb_client_file_set().
1732 * This is a sub-directory inside base directory
1733 * (ethumb_client_dir_path_set()) that creates a namespace to avoid
1734 * different options resulting in the same file.
1736 * As other options, this value will only be applied to future
1739 * @param client the client instance to use. Must @b not be @c
1740 * NULL. May be pending connected (can be called before @c
1742 * @param category category sub directory to store thumbnail. Default
1743 * is either "normal" or "large" for FDO compliant thumbnails
1744 * or WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string
1745 * or @c NULL to use auto generated names.
1747 * @see ethumb_client_dir_path_set()
1750 ethumb_client_category_set(Ethumb_Client *client, const char *category)
1752 EINA_SAFETY_ON_NULL_RETURN(client);
1754 client->ethumb_dirty = 1;
1755 ethumb_thumb_category_set(client->ethumb, category);
1759 * Get category sub-directory where to store thumbnails.
1761 * @param client the client instance to use. Must @b not be @c
1762 * NULL. May be pending connected (can be called before @c
1765 * @return pointer to internal string with current path. This string
1766 * should not be modified or freed.
1768 * @see ethumb_client_category_set()
1771 ethumb_client_category_get(const Ethumb_Client *client)
1773 EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
1775 return ethumb_thumb_category_get(client->ethumb);
1779 * Set the video time (duration) in seconds.
1781 * @param client the client instance to use. Must @b not be @c
1782 * NULL. May be pending connected (can be called before @c
1784 * @param time duration (in seconds). Defaults to 3 seconds.
1787 ethumb_client_video_time_set(Ethumb_Client *client, float time)
1789 EINA_SAFETY_ON_NULL_RETURN(client);
1791 client->ethumb_dirty = 1;
1792 ethumb_video_time_set(client->ethumb, time);
1796 * Set initial video position to start thumbnailing, in percentage.
1798 * This is useful to avoid thumbnailing the company/producer logo or
1801 * @param client the client instance to use. Must @b not be @c
1802 * NULL. May be pending connected (can be called before @c
1804 * @param start initial video positon to thumbnail, in percentage (0.0
1805 * to 1.0, inclusive). Defaults to 10% (0.1).
1808 ethumb_client_video_start_set(Ethumb_Client *client, float start)
1810 EINA_SAFETY_ON_NULL_RETURN(client);
1811 EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0);
1812 EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0);
1814 client->ethumb_dirty = 1;
1815 ethumb_video_start_set(client->ethumb, start);
1819 * Set the video frame interval, in seconds.
1821 * This is useful for animated thumbnail and will define skip time
1822 * before going to the next frame. Note that video backends might not
1823 * be able to precisely skip that amount as it will depend on various
1824 * factors, including video encoding.
1826 * Although this seems similar to ethumb_client_video_fps_set(), this
1827 * one is the time that will be used to seek. The math is simple, for
1828 * each new frame the video position will be set to:
1829 * ((video_length * start_time) + (interval * current_frame_number)).
1831 * @param client the client instance to use. Must @b not be @c
1832 * NULL. May be pending connected (can be called before @c
1834 * @param interval time between frames, in seconds. Defaults to 0.05
1838 ethumb_client_video_interval_set(Ethumb_Client *client, float interval)
1840 EINA_SAFETY_ON_NULL_RETURN(client);
1842 client->ethumb_dirty = 1;
1843 ethumb_video_interval_set(client->ethumb, interval);
1847 * Set the number of frames to thumbnail.
1849 * This is useful for animated thumbnail and will define how many
1850 * frames the generated file will have.
1852 * @param client the client instance to use. Must @b not be @c
1853 * NULL. May be pending connected (can be called before @c
1855 * @param ntimes number of times, must be greater than zero.
1859 ethumb_client_video_ntimes_set(Ethumb_Client *client, unsigned int ntimes)
1861 EINA_SAFETY_ON_NULL_RETURN(client);
1862 EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0);
1864 client->ethumb_dirty = 1;
1865 ethumb_video_ntimes_set(client->ethumb, ntimes);
1869 * Set the number of frames per second to thumbnail the video.
1871 * This configures the number of times per seconds the thumbnail will
1872 * use to create thumbnails.
1874 * Although this is similar to ethumb_client_video_interval_set(), it
1875 * is the delay used between calling functions thata generates frames,
1876 * while the other is the time used to skip inside the video.
1878 * @param client the client instance to use. Must @b not be @c
1879 * NULL. May be pending connected (can be called before @c
1881 * @param fps number of frames per second to thumbnail. Must be greater
1882 * than zero. Defaults to 10.
1885 ethumb_client_video_fps_set(Ethumb_Client *client, unsigned int fps)
1887 EINA_SAFETY_ON_NULL_RETURN(client);
1888 EINA_SAFETY_ON_FALSE_RETURN(fps > 0);
1890 client->ethumb_dirty = 1;
1891 ethumb_video_fps_set(client->ethumb, fps);
1895 * Set the page number to thumbnail in paged documents.
1897 * @param client the client instance to use. Must @b not be @c
1898 * NULL. May be pending connected (can be called before @c
1900 * @param page page number, defaults to 0 (first).
1903 ethumb_client_document_page_set(Ethumb_Client *client, unsigned int page)
1905 EINA_SAFETY_ON_NULL_RETURN(client);
1907 client->ethumb_dirty = 1;
1908 ethumb_document_page_set(client->ethumb, page);
1912 * Set source file to be thumbnailed.
1914 * Calling this function has the side effect of resetting values set
1915 * with ethumb_client_thumb_path_set() or auto-generated with
1916 * ethumb_client_thumb_exists().
1918 * @param client the client instance to use. Must @b not be @c
1919 * NULL. May be pending connected (can be called before @c
1921 * @param path the filesystem path to use. May be @c NULL.
1922 * @param key the extra argument/key inside @a path to read image
1923 * from. This is only used for formats that allow multiple
1924 * resources in one file, like EET or Edje (group name).
1926 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
1929 ethumb_client_file_set(Ethumb_Client *client, const char *path, const char *key)
1931 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1933 return ethumb_file_set(client->ethumb, path, key);
1937 * Get values set with ethumb_client_file_get()
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 path where to return configured path. May be @c NULL. If
1943 * not @c NULL, then it will be a pointer to a stringshared
1944 * instance, but @b no references are added (do it with
1945 * eina_stringshare_ref())!
1946 * @param key where to return configured key. May be @c NULL.If not @c
1947 * NULL, then it will be a pointer to a stringshared instance,
1948 * but @b no references are added (do it with
1949 * eina_stringshare_ref())!
1952 ethumb_client_file_get(Ethumb_Client *client, const char **path, const char **key)
1954 if (path) *path = NULL;
1955 if (key) *key = NULL;
1956 EINA_SAFETY_ON_NULL_RETURN(client);
1958 ethumb_file_get(client->ethumb, path, key);
1962 * Reset previously set file to @c NULL.
1964 * @param client the client instance to use. Must @b not be @c
1965 * NULL. May be pending connected (can be called before @c
1969 ethumb_client_file_free(Ethumb_Client *client)
1971 EINA_SAFETY_ON_NULL_RETURN(client);
1973 ethumb_file_free(client->ethumb);
1977 * Set a defined path and key to store the thumbnail.
1979 * If not explicitly given, the thumbnail path will be auto-generated
1980 * by ethumb_client_thumb_exists() or server using configured
1981 * parameters like size, aspect and category.
1983 * Set these to @c NULL to forget previously given values. After
1984 * ethumb_client_file_set() these values will be reset to @c NULL.
1986 * @param client the client instance to use. Must @b not be @c
1987 * NULL. May be pending connected (can be called before @c
1989 * @param path force generated thumbnail to the exact given path. If
1990 * @c NULL, then reverts back to auto-generation.
1991 * @param key force generated thumbnail to the exact given key. If
1992 * @c NULL, then reverts back to auto-generation.
1995 ethumb_client_thumb_path_set(Ethumb_Client *client, const char *path, const char *key)
1997 EINA_SAFETY_ON_NULL_RETURN(client);
1999 ethumb_thumb_path_set(client->ethumb, path, key);
2003 * Get the configured thumbnail path.
2005 * This returns the value set with ethumb_client_thumb_path_set() or
2006 * auto-generated by ethumb_client_thumb_exists() if it was not set.
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 path where to return configured path. May be @c NULL. If
2012 * there was no path configured with
2013 * ethumb_client_thumb_path_set() and
2014 * ethumb_client_thumb_exists() was not called, then it will
2015 * probably return @c NULL. If not @c NULL, then it will be a
2016 * pointer to a stringshared instance, but @b no references are
2017 * added (do it with eina_stringshare_ref())!
2018 * @param key where to return configured key. May be @c NULL. If
2019 * there was no key configured with
2020 * ethumb_client_thumb_key_set() and
2021 * ethumb_client_thumb_exists() was not called, then it will
2022 * probably return @c NULL. If not @c NULL, then it will be a
2023 * pointer to a stringshared instance, but @b no references are
2024 * added (do it with eina_stringshare_ref())!
2027 ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const char **key)
2029 if (path) *path = NULL;
2030 if (key) *key = NULL;
2031 EINA_SAFETY_ON_NULL_RETURN(client);
2033 ethumb_thumb_path_get(client->ethumb, path, key);
2037 * Checks whenever file already exists (locally!)
2039 * This will check locally (not calling server) if thumbnail already
2040 * exists or not, also calculating the thumbnail path. See
2041 * ethumb_client_thumb_path_get(). Path must be configured with
2042 * ethumb_client_file_set() before using it and the last set file will
2045 * @param client client instance. Must @b not be @c NULL and client
2046 * must be configured with ethumb_client_file_set().
2048 * @return @c EINA_TRUE if it exists, @c EINA_FALSE otherwise.
2051 ethumb_client_thumb_exists(Ethumb_Client *client)
2053 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
2055 return ethumb_exists(client->ethumb);
2059 * Ask server to generate thumbnail.
2061 * This process is asynchronous and will report back from main loop
2062 * using @a generated_cb. One can cancel this request by calling
2063 * ethumb_client_generate_cancel() or
2064 * ethumb_client_generate_cancel_all(), but not that request might be
2065 * processed by server already and no generated files will be removed
2066 * if that is the case.
2068 * This will not check if file already exists, this should be done by
2069 * explicitly calling ethumb_client_thumb_exists(). That is, this
2070 * function will override any existing thumbnail.
2072 * @param client client instance. Must @b not be @c NULL and client
2073 * must be connected (after connected_cb is called).
2074 * @param generated_cb function to report generation results.
2075 * @param data context argument to give back to @a generated_cb. May
2077 * @param data context to give back to @a generate_cb. May be @c
2079 * @param free_data used to release @a data resources after @a
2080 * generated_cb is called or user calls
2081 * ethumb_client_disconnect().
2083 * @return identifier or -1 on error. If -1 is returned (error) then
2084 * @a free_data is @b not called!
2086 * @see ethumb_client_connect()
2087 * @see ethumb_client_file_set()
2088 * @see ethumb_client_thumb_exists()
2089 * @see ethumb_client_generate_cancel()
2090 * @see ethumb_client_generate_cancel_all()
2093 ethumb_client_generate(Ethumb_Client *client, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data)
2095 const char *file, *key, *thumb, *thumb_key;
2097 EINA_SAFETY_ON_NULL_RETURN_VAL(client, -1);
2098 EINA_SAFETY_ON_FALSE_RETURN_VAL(client->connected, -1);
2100 ethumb_file_get(client->ethumb, &file, &key);
2103 ERR("no file set.");
2107 ethumb_thumb_path_get(client->ethumb, &thumb, &thumb_key);
2109 if (client->ethumb_dirty)
2110 ethumb_client_ethumb_setup(client);
2111 id = _ethumb_client_queue_add(client, file, key, thumb, thumb_key,
2112 generated_cb, data, free_data);