ethumb: make exists client API async.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 27 Apr 2011 18:06:42 +0000 (18:06 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 27 Apr 2011 18:06:42 +0000 (18:06 +0000)
Ethumb_Client now use Ecore_Thread with this patch.

TODO:
* cache exists requests (client side).
* cache generate requests (server side).

git-svn-id: https://svn.enlightenment.org/svn/e/trunk/ethumb@58977 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/ethumbd_client.c
src/lib/Ethumb.c
src/lib/Ethumb.h
src/lib/client/Ethumb_Client.c
src/lib/client/Ethumb_Client.h

index 351eff4..57950e3 100644 (file)
@@ -157,12 +157,38 @@ _finished_thumb(void *data __UNUSED__, Ethumb_Client *client __UNUSED__, int id
 }
 
 static void
-_connected(void *data, Ethumb_Client *c, Eina_Bool success)
+_exists(Ethumb_Client *c, __UNUSED__ Ethumb_Exists *thread, Eina_Bool exists, void *data)
 {
    struct options *opts = data;
    const char *thumb_path, *thumb_key;
    long id;
 
+   if (exists)
+     {
+        ethumb_client_thumb_path_get(c, &thumb_path, &thumb_key);
+        _thumb_report
+          ("EXISTS", opts->src_path, opts->src_key, thumb_path, thumb_key);
+        ecore_main_loop_quit();
+        return;
+     }
+
+   id = ethumb_client_generate(c, _finished_thumb, NULL, NULL);
+   if (id < 0)
+     {
+       fputs("ERROR: could not request thumbnail to be generated.\n", stderr);
+       ecore_main_loop_quit();
+       return;
+     }
+   printf("request id=%ld, file='%s', key='%s'\n",
+         id, opts->src_path, opts->src_key ? opts->src_key : "");
+
+}
+
+static void
+_connected(void *data, Ethumb_Client *c, Eina_Bool success)
+{
+   struct options *opts = data;
+
    if (!success)
      {
        fputs("ERROR: could not connect to DBus server.\n", stderr);
@@ -196,24 +222,7 @@ _connected(void *data, Ethumb_Client *c, Eina_Bool success)
      }
 
    ethumb_client_thumb_path_set(c, opts->thumb_path, opts->thumb_key);
-   ethumb_client_thumb_path_get(c, &thumb_path, &thumb_key);
-   if (ethumb_client_thumb_exists(c))
-     {
-       _thumb_report
-         ("EXISTS", opts->src_path, opts->src_key, thumb_path, thumb_key);
-       ecore_main_loop_quit();
-       return;
-     }
-
-   id = ethumb_client_generate(c, _finished_thumb, NULL, NULL);
-   if (id < 0)
-     {
-       fputs("ERROR: could not request thumbnail to be generated.\n", stderr);
-       ecore_main_loop_quit();
-       return;
-     }
-   printf("request id=%ld, file='%s', key='%s'\n",
-         id, opts->src_path, opts->src_key ? opts->src_key : "");
+   ethumb_client_thumb_exists(c, _exists, opts);
 }
 
 int
index 067a409..7035ea2 100644 (file)
@@ -244,6 +244,7 @@ ethumb_new(void)
    if (!e)
      {
        ERR("could not create ecore evas buffer");
+        free(ethumb);
        return NULL;
      }
 
@@ -259,8 +260,8 @@ ethumb_new(void)
        return NULL;
      }
 
-   sub_ee = evas_object_data_get(o, "Ecore_Evas");
-   sub_e = ecore_evas_get(sub_ee);
+   sub_ee = ecore_evas_object_ecore_evas_get(o);
+   sub_e = ecore_evas_object_evas_get(o);
 
    evas_image_cache_set(sub_e, 0);
    evas_font_cache_set(sub_e, 0);
@@ -678,12 +679,12 @@ ethumb_video_start_get(const Ethumb *e)
 }
 
 EAPI void
-ethumb_video_time_set(Ethumb *e, float time)
+ethumb_video_time_set(Ethumb *e, float t)
 {
    EINA_SAFETY_ON_NULL_RETURN(e);
 
-   DBG("ethumb=%p, video_start=%f", e, time);
-   e->video.time = time;
+   DBG("ethumb=%p, video_start=%f", e, t);
+   e->video.time = t;
 }
 
 EAPI float
@@ -1550,3 +1551,109 @@ ethumb_ecore_evas_get(const Ethumb *e)
 
    return e->sub_ee;
 }
+
+Ethumb *
+ethumb_dup(const Ethumb *e)
+{
+   Ecore_Evas *ee;
+   Ecore_Evas *sub_ee;
+   Evas *ev;
+   Evas *sub_ev;
+   Evas_Object *o;
+   Evas_Object *img;
+   Ethumb *r;
+
+   r = malloc(sizeof (Ethumb));
+   if (!r) return NULL;
+
+   memcpy(r, e, sizeof (Ethumb));
+
+   r->thumb_dir = eina_stringshare_ref(e->thumb_dir);
+   r->category = eina_stringshare_ref(e->category);
+   r->src_path = eina_stringshare_ref(e->src_path);
+   r->src_key = eina_stringshare_ref(e->src_key);
+   r->thumb_path = eina_stringshare_ref(e->thumb_path);
+   r->thumb_key = eina_stringshare_ref(e->thumb_key);
+
+   ee = ecore_evas_buffer_new(1, 1);
+   ev = ecore_evas_get(ee);
+   if (!ev)
+     {
+        ERR("could not create ecore evas buffer");
+        free(r);
+        return NULL;
+     }
+
+   evas_image_cache_set(ev, 0);
+   evas_font_cache_set(ev, 0);
+
+   o = ecore_evas_object_image_new(ee);
+   if (!o)
+     {
+        ERR("could not create sub ecore evas buffer");
+        ecore_evas_free(ee);
+        free(r);
+        return NULL;
+     }
+
+   sub_ee = ecore_evas_object_ecore_evas_get(o);
+   sub_ev = ecore_evas_object_evas_get(o);
+
+   evas_image_cache_set(sub_ev, 0);
+   evas_font_cache_set(sub_ev, 0);
+
+   img = evas_object_image_add(sub_ev);
+   if (!img)
+     {
+        ERR("could not create source objects.");
+        ecore_evas_free(ee);
+        free(r);
+        return NULL;
+     }
+
+   r->ee = ee;
+   r->sub_ee = sub_ee;
+   r->e = ev;
+   r->sub_e = sub_ev;
+   r->o = o;
+   r->img = img;
+
+   r->frame = NULL;
+   r->finished_idler = NULL;
+   r->finished_cb = NULL;
+   r->cb_data = NULL;
+   r->cb_data_free = NULL;
+   r->cb_result = 0;
+
+   return r;
+}
+
+#define CHECK_DELTA(Param)                      \
+  if (e1->Param != e2->Param)                   \
+    return EINA_TRUE;
+
+Eina_Bool
+ethumb_cmp(const Ethumb *e1, const Ethumb *e2)
+{
+   CHECK_DELTA(thumb_dir);
+   CHECK_DELTA(category);
+   CHECK_DELTA(tw);
+   CHECK_DELTA(th);
+   CHECK_DELTA(format);
+   CHECK_DELTA(aspect);
+   CHECK_DELTA(orientation);
+   CHECK_DELTA(crop_x);
+   CHECK_DELTA(crop_y);
+   CHECK_DELTA(quality);
+   CHECK_DELTA(compress);
+   CHECK_DELTA(rw);
+   CHECK_DELTA(rh);
+   CHECK_DELTA(video.start);
+   CHECK_DELTA(video.time);
+   CHECK_DELTA(video.interval);
+   CHECK_DELTA(video.ntimes);
+   CHECK_DELTA(video.fps);
+   CHECK_DELTA(document.page);
+
+   return EINA_FALSE;
+}
index b9c0c86..afa0220 100644 (file)
@@ -183,7 +183,11 @@ EAPI void      ethumb_file_free(Ethumb *e) EINA_ARG_NONNULL(1);
 
 EAPI Eina_Bool ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, const void *data, Eina_Free_Cb free_data) EINA_ARG_NONNULL(1, 2);
 EAPI Eina_Bool ethumb_exists(Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-/**
+
+EAPI Ethumb *ethumb_dup(const Ethumb *e) EINA_ARG_NONNULL(1);
+EAPI Eina_Bool ethumb_cmp(const Ethumb *e1, const Ethumb *e2) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
+
+  /**
  * @}
  */
 
index e67fbf2..3e05fac 100644 (file)
@@ -78,6 +78,7 @@
 #include <eina_safety_checks.h>
 #include <E_DBus.h>
 #include <Ethumb.h>
+#include <Ecore.h>
 
 #include "Ethumb_Client.h"
 
@@ -123,9 +124,12 @@ struct _Ethumb_Client
    } die;
    const char *object_path;
 
+   int refcount;
+
    Eina_Bool ethumb_dirty : 1;
    Eina_Bool connected : 1;
    Eina_Bool server_started : 1;
+   Eina_Bool delete_me : 1;
 };
 
 struct _ethumb_pending_add
@@ -164,6 +168,22 @@ struct _ethumb_pending_gen
    Eina_Free_Cb free_data;
 };
 
+typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists;
+
+struct _Ethumb_Async_Exists
+{
+   Ethumb *dup;
+   Ethumb_Client *source;
+
+   Ethumb_Client_Thumb_Exists_Cb exists_cb;
+   const void *data;
+
+   Ecore_Thread *thread;
+   int refcount;
+
+   Eina_Bool exists : 1;
+};
+
 static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb";
 static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb";
 static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects";
@@ -463,6 +483,54 @@ error:
    _ethumb_client_report_connect(client, 0);
 }
 
+static void
+_ethumb_client_exists_heavy(void *data, Ecore_Thread *thread)
+{
+   Ethumb_Async_Exists *async = data;
+
+   async->exists = ethumb_exists(async->dup);
+}
+
+static void
+_ethumb_client_exists_end(void *data, Ecore_Thread *thread)
+{
+   Ethumb_Async_Exists *async = data;
+   Ethumb *tmp = async->source->ethumb;
+
+   async->source->ethumb = async->dup;
+   async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup);
+   async->exists_cb(async->source, (Ethumb_Exists*) async, async->exists, (void*) async->data);
+   async->source->ethumb = tmp;
+
+   ethumb_free(async->dup);
+   async->source->refcount--;
+
+   if (async->source->delete_me == EINA_TRUE)
+     ethumb_client_disconnect(async->source);
+
+   free(async);
+}
+
+static void
+_ethumb_client_exists_cancel(void *data, Ecore_Thread *thread)
+{
+   Ethumb_Async_Exists *async = data;
+   Ethumb *tmp = async->source->ethumb;
+
+   async->source->ethumb = async->dup;
+   async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup);
+   async->exists_cb(async->source, (Ethumb_Exists*) async, EINA_FALSE, (void*) async->data);
+   async->source->ethumb = tmp;
+
+   ethumb_free(async->dup);
+   async->source->refcount--;
+
+   if (async->source->delete_me == EINA_TRUE)
+     ethumb_client_disconnect(async->source);
+
+   free(async);
+}
+
 /**
  * @endcond
  */
@@ -652,6 +720,10 @@ ethumb_client_disconnect(Ethumb_Client *client)
 
    EINA_SAFETY_ON_NULL_RETURN(client);
 
+   client->delete_me = EINA_TRUE;
+   if (client->refcount > 0)
+     return ;
+
    if (!client->connected)
      goto end_connection;
 
@@ -1218,22 +1290,22 @@ ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Gener
    l = client->pending_add;
    while (l)
      {
-       struct _ethumb_pending_add *pending = l->data;
-       if (pending->id != id32)
+       struct _ethumb_pending_add *pending_add = l->data;
+       if (pending_add->id != id32)
          {
             l = l->next;
             continue;
          }
        client->pending_add = eina_list_remove_list(client->pending_add, l);
-       eina_stringshare_del(pending->file);
-       eina_stringshare_del(pending->key);
-       eina_stringshare_del(pending->thumb);
-       eina_stringshare_del(pending->thumb_key);
-       dbus_pending_call_cancel(pending->pending_call);
-       dbus_pending_call_unref(pending->pending_call);
-       if (pending->free_data)
-         pending->free_data(pending->data);
-       free(pending);
+       eina_stringshare_del(pending_add->file);
+       eina_stringshare_del(pending_add->key);
+       eina_stringshare_del(pending_add->thumb);
+       eina_stringshare_del(pending_add->thumb_key);
+       dbus_pending_call_cancel(pending_add->pending_call);
+       dbus_pending_call_unref(pending_add->pending_call);
+       if (pending_add->free_data)
+         pending_add->free_data(pending_add->data);
+       free(pending_add);
        found = 1;
        break;
      }
@@ -1244,20 +1316,20 @@ ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Gener
    l = client->pending_gen;
    while (l)
      {
-       struct _ethumb_pending_gen *pending = l->data;
-       if (pending->id != id32)
+       struct _ethumb_pending_gen *pending_gen = l->data;
+       if (pending_gen->id != id32)
          {
             l = l->next;
             continue;
          }
        client->pending_gen = eina_list_remove_list(client->pending_gen, l);
-       eina_stringshare_del(pending->file);
-       eina_stringshare_del(pending->key);
-       eina_stringshare_del(pending->thumb);
-       eina_stringshare_del(pending->thumb_key);
-       if (pending->free_data)
-         pending->free_data(pending->data);
-       free(pending);
+       eina_stringshare_del(pending_gen->file);
+       eina_stringshare_del(pending_gen->key);
+       eina_stringshare_del(pending_gen->thumb);
+       eina_stringshare_del(pending_gen->thumb_key);
+       if (pending_gen->free_data)
+         pending_gen->free_data(pending_gen->data);
+       free(pending_gen);
        break;
      }
 
@@ -1781,15 +1853,15 @@ ethumb_client_category_get(const Ethumb_Client *client)
  * @param client the client instance to use. Must @b not be @c
  *        NULL. May be pending connected (can be called before @c
  *        connected_cb)
- * @param time duration (in seconds). Defaults to 3 seconds.
+ * @param t duration (in seconds). Defaults to 3 seconds.
  */
 EAPI void
-ethumb_client_video_time_set(Ethumb_Client *client, float time)
+ethumb_client_video_time_set(Ethumb_Client *client, float t)
 {
    EINA_SAFETY_ON_NULL_RETURN(client);
 
    client->ethumb_dirty = 1;
-   ethumb_video_time_set(client->ethumb, time);
+   ethumb_video_time_set(client->ethumb, t);
 }
 
 /**
@@ -2047,12 +2119,67 @@ ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const cha
  *
  * @return @c EINA_TRUE if it exists, @c EINA_FALSE otherwise.
  */
+EAPI Ethumb_Exists *
+ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data)
+{
+   Ethumb_Async_Exists *async;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL);
+
+   async = malloc(sizeof (Ethumb_Async_Exists));
+   if (!async)
+     {
+        exists_cb(client, NULL, EINA_FALSE, (void*) data);
+        return NULL;
+     }
+
+   async->dup = ethumb_dup(client->ethumb);
+   async->source = client;
+   async->source->refcount++;
+   async->exists_cb = exists_cb;
+   async->data = data;
+   async->exists = EINA_FALSE;
+
+   async->refcount = 1;
+   async->thread = ecore_thread_run(_ethumb_client_exists_heavy,
+                                   _ethumb_client_exists_end,
+                                   _ethumb_client_exists_cancel,
+                                   async);
+
+   return (Ethumb_Exists*) async;
+}
+
+/**
+ * Cancel an ongoing exists request.
+ *
+ * @param exists the request to cancel.
+ */
+EAPI void
+ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
+{
+   Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
+
+   async->refcount--;
+
+   if (async->refcount > 0) return ;
+
+   ecore_thread_cancel(async->thread);
+}
+
+/**
+ * Check if an exists request was cancelled.
+ *
+ * @param exists the request to check.
+ * @result return EINA_TRUE if the request was cancelled.
+ */
 EAPI Eina_Bool
-ethumb_client_thumb_exists(Ethumb_Client *client)
+ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
 {
-   EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
+   Ethumb_Async_Exists *async = (Ethumb_Async_Exists*) exists;
+
+   if (!async) return EINA_TRUE;
 
-   return ethumb_exists(client->ethumb);
+   return ecore_thread_check(async->thread);
 }
 
 /**
index 355ecad..e105693 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ETHUMB_CLIENT_H__
 #define __ETHUMB_CLIENT_H__ 1
 
+#include <Ecore.h>
 #include <Ethumb.h>
 
 #ifdef EAPI
@@ -64,6 +65,15 @@ extern "C" {
 typedef struct _Ethumb_Client Ethumb_Client;
 
 /**
+ * @brief client exists request handle.
+ *
+ * The exists request handle is created by ethumb_client_thumb_exists(),
+ * automatically destroyed when it end and cancelled when requested by
+ * ethumb_client_thumb_exists_cancel().
+ */
+typedef struct _Ethumb_Exists Ethumb_Exists;
+
+/**
  * @brief reports results of ethumb_client_connect()
  *
  * @param data extra context given to ethumb_client_connect().
@@ -101,6 +111,19 @@ typedef void (*Ethumb_Client_Die_Cb)(void *data, Ethumb_Client *client);
 typedef void (*Ethumb_Client_Generate_Cb)(void *data, Ethumb_Client *client, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success);
 
 /**
+ * @brief report results of ethumb_client_thumb_exists().
+ *
+ * @param client handle of the current connection to server.
+ * @param exists EINA_TRUE if the thumbnail exists.
+ * @param data extra context given to ethumb_client_thumb_exists().
+ *
+ * During the execution of the callback the state of the @p client is
+ * temporarily realy restored to what it was when the call to
+ * ethumb_client_thumb_exists() was done.
+ */
+typedef void (*Ethumb_Client_Thumb_Exists_Cb)(Ethumb_Client *client, Ethumb_Exists *thread, Eina_Bool exists, void *data);
+
+/**
  * @brief reports results of ethumb_client_generate_cancel()
  *
  * @param data extra context given to ethumb_client_generate_cancel()
@@ -171,7 +194,9 @@ EAPI Eina_Bool ethumb_client_file_set(Ethumb_Client *client, const char *path, c
 EAPI void ethumb_client_file_get(Ethumb_Client *client, const char **path, const char **key);
 EAPI void ethumb_client_file_free(Ethumb_Client *client);
 
-EAPI Eina_Bool ethumb_client_thumb_exists(Ethumb_Client *client);
+EAPI Ethumb_Exists *ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data);
+EAPI void ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists);
+EAPI Eina_Bool ethumb_client_thumb_exists_check(Ethumb_Exists *exists);
 EAPI int  ethumb_client_generate(Ethumb_Client *client, Ethumb_Client_Generate_Cb generated_cb, const void *data, Eina_Free_Cb free_data);
 EAPI void ethumb_client_generate_cancel(Ethumb_Client *client, int id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, const void *data, Eina_Free_Cb free_data);
 EAPI void ethumb_client_generate_cancel_all(Ethumb_Client *client);