kuuko pushed a commit to branch master.

http://git.enlightenment.org/bindings/python/python-efl.git/commit/?id=6ebdf2b607491594c44deb6599861a35ff633667

commit 6ebdf2b607491594c44deb6599861a35ff633667
Author: Kai Huuhko <kai.huu...@gmail.com>
Date:   Fri Apr 11 18:12:49 2014 +0300

    Bring back Python bindings for Ethumb.
---
 TODO                             |   5 +-
 doc/ethumb/class-ethumb.rst      |  13 +
 doc/ethumb/ethumb.rst            |  30 ++
 doc/index.rst                    |   6 +
 efl/ethumb/__init__.py           |  30 ++
 efl/ethumb/efl.ethumb.pyx        |  30 ++
 efl/ethumb/efl.ethumb_client.pyx | 655 +++++++++++++++++++++++++++++++++++++++
 include/efl.ethumb.enums.pxd     |  26 ++
 include/efl.ethumb.pxd           | 106 +++++++
 include/efl.ethumb_client.pxd    |  96 ++++++
 setup.py                         |  18 ++
 11 files changed, 1012 insertions(+), 3 deletions(-)

diff --git a/TODO b/TODO
index 668f3da..87df368 100644
--- a/TODO
+++ b/TODO
@@ -25,9 +25,7 @@ TODO
 * Review the internal functions and name them consistently
 * Evas: SmartObject needs testing, work. Make it inheritable by extension
   classes?
-* Elm unit tests, things like top_widget and getting child objects
-  can be done easily.
-* include python-ethumb
+* Improve ethumb
 * edje: complete the unit tests
 * Initial Evas GL support (for Elm)
 * Add more documentation for callbacks, events, etc.
@@ -40,6 +38,7 @@ Elm
 * Add more examples
 * Prefs
 * GLView
+* Unit tests
 * Images missing in the documentation:
    - datetime
    - video
diff --git a/doc/ethumb/class-ethumb.rst b/doc/ethumb/class-ethumb.rst
new file mode 100644
index 0000000..593d585
--- /dev/null
+++ b/doc/ethumb/class-ethumb.rst
@@ -0,0 +1,13 @@
+.. currentmodule:: efl.ethumb
+
+:class:`efl.ethumb.PyEthumb` Class
+==================================
+
+.. autoclass:: efl.ethumb.PyEthumb
+
+.. currentmodule:: efl.ethumb
+
+:class:`efl.ethumb_client.Client` Class
+========================================
+
+.. autoclass:: efl.ethumb_client.Client
diff --git a/doc/ethumb/ethumb.rst b/doc/ethumb/ethumb.rst
new file mode 100644
index 0000000..d9f923a
--- /dev/null
+++ b/doc/ethumb/ethumb.rst
@@ -0,0 +1,30 @@
+:mod:`efl.ethumb` Module
+============================
+
+.. module:: efl.ethumb
+
+What is Ethumb?
+----------------
+
+
+How to use the Ethumb object
+-----------------------------
+
+
+Reference
+---------
+
+.. toctree::
+   :maxdepth: 4
+
+   class-ethumb
+
+
+Inheritance diagram
+-------------------
+
+.. inheritance-diagram::
+    efl.ethumb
+    efl.ethumb_client
+    :parts: 2
+
diff --git a/doc/index.rst b/doc/index.rst
index 2e56615..ac42901 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -54,6 +54,12 @@ Evas
 .. toctree:: evas/evas
 
 
+Ethumb
+------
+
+.. toctree:: ethumb/ethumb
+
+
 Edje
 ----
 
diff --git a/efl/ethumb/__init__.py b/efl/ethumb/__init__.py
new file mode 100644
index 0000000..d8d3e48
--- /dev/null
+++ b/efl/ethumb/__init__.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2009 by ProFUSION embedded systems
+#
+# This file is part of Python-Ethumb.
+#
+# Python-Ethumb is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-Ethumb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-Ethumb.  If not, see <http://www.gnu.org/licenses/>.
+
+from c_ethumb import init, shutdown, PyEthumb
+
+ETHUMB_THUMB_NORMAL = 0
+ETHUMB_THUMB_LARGE = 1
+
+ETHUMB_THUMB_FDO = 0
+ETHUMB_THUMB_JPEG = 1
+ETHUMB_THUMB_EET = 2
+
+ETHUMB_THUMB_KEEP_ASPECT = 0
+ETHUMB_THUMB_IGNORE_ASPECT = 1
+ETHUMB_THUMB_CROP = 2
+
diff --git a/efl/ethumb/efl.ethumb.pyx b/efl/ethumb/efl.ethumb.pyx
new file mode 100644
index 0000000..80db58a
--- /dev/null
+++ b/efl/ethumb/efl.ethumb.pyx
@@ -0,0 +1,30 @@
+# Copyright (C) 2009 by ProFUSION embedded systems
+#
+# This file is part of Python-Ethumb.
+#
+# Python-Ethumb is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-Ethumb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-Ethumb.  If not, see <http://www.gnu.org/licenses/>.
+
+def init():
+    return ethumb_init()
+
+def shutdown():
+    ethumb_shutdown()
+
+cdef class PyEthumb:
+    """Ethumb thumbnail generator"""
+    def __init__(self):
+        """Ethumb constructor."""
+
+
+init()
diff --git a/efl/ethumb/efl.ethumb_client.pyx b/efl/ethumb/efl.ethumb_client.pyx
new file mode 100644
index 0000000..7666250
--- /dev/null
+++ b/efl/ethumb/efl.ethumb_client.pyx
@@ -0,0 +1,655 @@
+# Copyright (C) 2009 by ProFUSION embedded systems
+#
+# This file is part of Python-Ethumb.
+#
+# Python-Ethumb is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-Ethumb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-Ethumb.  If not, see <http://www.gnu.org/licenses/>.
+
+from cpython cimport Py_INCREF, Py_DECREF
+from libc.stdint cimport uintptr_t
+import traceback
+
+def shutdown():
+    ethumb_client_shutdown()
+
+def init():
+    return ethumb_client_init()
+
+cdef void _connect_cb(void *data, Ethumb_Client *client, Eina_Bool success) 
with gil:
+    cdef Client self = <Client>data
+    s = bool(success)
+    try:
+        func, args, kargs = self._on_connect_callback
+        func(self, s, *args, **kargs)
+    except Exception, e:
+        traceback.print_exc()
+
+    if not s and self.obj != NULL:
+        ethumb_client_disconnect(self.obj)
+        self.obj = NULL
+    self._on_connect_callback = None
+
+
+cdef void _on_server_die_cb(void *data, Ethumb_Client *client) with gil:
+    cdef Client self = <Client>data
+    if self._on_server_die_callback is not None:
+        try:
+            func, args, kargs = self._on_server_die_callback
+            func(self, *args, **kargs)
+        except Exception, e:
+            traceback.print_exc()
+
+    if self.obj != NULL:
+        ethumb_client_disconnect(self.obj)
+        self.obj = NULL
+    self._on_server_die_callback = None
+
+
+cdef void _generated_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) with gil:
+    obj = <object>data
+    (self, func, args, kargs) = obj
+    f = str_from_c(file)
+    k = str_from_c(key)
+    tp = str_from_c(thumb_path)
+    tk = str_from_c(thumb_key)
+    s = bool(success != 0)
+    try:
+        func(self, id, f, k, tp, tk, s, *args, **kargs)
+    except Exception, e:
+        traceback.print_exc()
+
+cdef void _generated_cb_free_data(void *data) with gil:
+    obj = <object>data
+    Py_DECREF(obj)
+
+cdef void _thumb_exists_cb(void *data, Ethumb_Client *client, Ethumb_Exists 
*thread, Eina_Bool exists) with gil:
+    #TODO
+    print("Not implemented")
+    #pass
+
+cdef char *str_to_c(object s):
+    cdef char *mystr
+    if s is None:
+        mystr = NULL
+    else:
+        mystr = s
+    return mystr
+
+cdef object str_from_c(const char *mystr):
+    if mystr != NULL:
+        return mystr
+
+cdef class Client:
+    """
+
+    Client for Ethumbd server.
+
+    This client is the recommended way to generate thumbnails with
+    Ethumb. All you have to do is create a client instance, wait it to
+    be connected to server, configure thumbnail parameters and then
+    start feed it with file_set(), exists() generate(). Basic steps are:
+
+    - instantiate Client, wait for func to be called with success.
+    - set various parameters, like format and size.
+    - loop on original files:
+
+      - ``c.file_set(file)``
+      - ``if not c.exists(): c.generate(generated_cb)``
+
+    When the last reference to client is released, server is
+    automatically disconnected. Since callback may contain references
+    to server itself, it is recommended explicit call to
+    :py:func:`disconnect` function.
+
+    """
+
+    def __init__(self, func, *args, **kargs):
+        """
+
+        Ethumb Client constructor.
+
+        Server is ready to receive requests just after **func** is
+        called back with ``status == True``.
+
+        :param func: function to call when connection with server is
+            established. Function signature is::
+
+                func(client, status, *args, **kargs)
+
+            with status being True for successful connection or False
+            on error.
+
+        :raise TypeError: if **func** is not callable.
+        :raise SystemError: if it was not possible to connect to
+            server, allocate memory or use DBus.
+
+        """
+        if not callable(func):
+            raise TypeError("Parameter 'func' must be callable")
+        if self.obj == NULL:
+            self._on_connect_callback = (func, args, kargs)
+            self._on_server_die_callback = None
+            self.obj = ethumb_client_connect(_connect_cb, <void*>self, NULL)
+            if self.obj == NULL:
+                raise SystemError("Error connecting to server.")
+            else:
+                ethumb_client_on_server_die_callback_set(
+                    self.obj, _on_server_die_cb, <void*>self, NULL)
+
+    def __dealloc__(self):
+        if self.obj != NULL:
+            ethumb_client_disconnect(self.obj)
+
+    def disconnect(self):
+        """Explicitly request server disconnection.
+
+        After this call object becomes shallow, that is operations
+        will be void.
+        """
+        if self.obj != NULL:
+            ethumb_client_disconnect(self.obj)
+            self.obj = NULL
+        self._on_connect_callback = None
+        self._on_server_die_callback = None
+
+    def __str__(self):
+        f, k = self.file
+        tf, tk = self.thumb_path
+        w, h = self.size
+
+        format = ("FDO", "JPEG", "EET")[self.format]
+        aspect = ("KEEP", "IGNORE", "CROP")[self.aspect]
+        if self.aspect == 2:
+            aspect = "CROP[%f, %f]" % self.crop
+        return ("%s(file=(%r, %r), thumb=(%r, %r), exists=%s, size=%dx%d, "
+                "format=%s, aspect=%s, quality=%d, compress=%d, "
+                "directory=%r, category=%r)") % \
+                (self.__class__.__name__, f, k, tf, tk, self.thumb_exists(),
+                 w, h, format, aspect, self.quality, self.compress,
+                 self.directory, self.category)
+
+    def __repr__(self):
+        f, k = self.file
+        tf, tk = self.thumb_path
+        return "%s(obj=%#x, file=(%r, %r), thumb=(%r, %r), exists=%s)" % \
+            (self.__class__.__name__, <uintptr_t><void *>self, f, k, tf, tk, 
self.thumb_exists())
+
+    def on_server_die_callback_set(self, func, *args, **kargs):
+        """Function to call when server dies.
+
+        When server is dead there is nothing to do with this client
+        anymore, just create a new one and start over, hope that
+        server could be started and you could generate more
+        thumbnails.
+
+        :param func: function to call when server dies.
+            Signature::
+
+                func(client, *args, **kargs)
+
+        :raise TypeError: if **func** is not callable or None.
+        """
+        if func is None:
+            self._on_server_die_callback = None
+        elif callable(func):
+            self._on_server_die_callback = (func, args, kargs)
+        else:
+            raise TypeError("Parameter 'func' must be callable or None")
+
+    def fdo_set(self, int s):
+        """Configure future requests to use FreeDesktop.Org preset.
+
+        This is a preset to provide freedesktop.org (fdo) standard
+        compliant thumbnails. That is, files are stored as JPEG under
+        ~/.thumbnails/SIZE, with size being either normal (128x128) or
+        large (256x256).
+
+        :param s: size identifier, either ETHUMB_THUMB_NORMAL (0) or
+           ETHUMB_THUMB_LARGE.
+
+        .. seealso:: :py:func:`size_set`, :py:func:`format_set`, 
:py:func:`aspect_set`, :py:func:`crop_set`,
+           :py:func:`category_set`, :py:func:`directory_set`.
+        """
+        ethumb_client_fdo_set(self.obj, s)
+
+    def size_set(self, int w, int h):
+        """Configure future request to use custom size.
+
+        :param w: width, default is 128.
+        :param h: height, default is 128.
+        """
+        ethumb_client_size_set(self.obj, w, h)
+
+    def size_get(self):
+        """Get current size being used by requests.
+
+        :rtype: tuple of int.
+        """
+        cdef int w, h
+        ethumb_client_size_get(self.obj, &w, &h)
+        return (w, h)
+
+    property size:
+        def __set__(self, value):
+            cdef int w, h
+            w, h = value
+            self.size_set(w, h)
+
+        def __get__(self):
+            return self.size_get()
+
+    def format_set(self, int f):
+        """Configure format to use for future requests.
+
+        :param f: format identifier to use, either ETHUMB_THUMB_FDO (0),
+           ETHUMB_THUMB_JPEG (1) or ETHUMB_THUMB_EET (2). Default is FDO.
+        """
+        ethumb_client_format_set(self.obj, f)
+
+    def format_get(self):
+        """Get current format in use for requests.
+
+        :rtype: int
+        """
+        return ethumb_client_format_get(self.obj)
+
+    property format:
+        def __set__(self, value):
+            self.format_set(value)
+
+        def __get__(self):
+            return self.format_get()
+
+    def aspect_set(self, int a):
+        """Configure aspect mode to use.
+
+        If aspect is kept (ETHUMB_THUMB_KEEP_ASPECT), then image will
+        be rescaled so the largest dimension is not bigger than it's
+        specified size (see :py:func:`size_get`) and the other dimension is
+        resized in the same proportion. Example: size is 256x256,
+        image is 1000x500, resulting thumbnail is 256x128.
+
+        If aspect is ignored (ETHUMB_THUMB_IGNORE_ASPECT), then image
+        will be distorted to match required thumbnail size. Example:
+        size is 256x256, image is 1000x500, resulting thumbnail is
+        256x256.
+
+        If crop is required (ETHUMB_THUMB_CROP), then image will be
+        cropped so the smallest dimension is not bigger than its
+        specified size (see :py:func:`size_get`) and the other dimension
+        will overflow, not being visible in the final image. How it
+        will overflow is speficied by :py:func:`crop_set`
+        alignment. Example: size is 256x256, image is 1000x500, crop
+        alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
+        pixels from left and 250 pixels from right being lost, that is
+        just the 500x500 central pixels of image will be considered
+        for scaling.
+
+        :param a: aspect mode identifier, either ETHUMB_THUMB_KEEP_ASPECT (0),
+           ETHUMB_THUMB_IGNORE_ASPECT (1) or ETHUMB_THUMB_CROP (2).
+
+        """
+        ethumb_client_aspect_set(self.obj, a)
+
+    def aspect_get(self):
+        """Get current aspect in use for requests.
+
+        :rtype: int
+        """
+        return ethumb_client_aspect_get(self.obj)
+
+    property aspect:
+        def __set__(self, value):
+            self.aspect_set(value)
+
+        def __get__(self):
+            return self.aspect_get()
+
+    def crop_set(self, float x, float y):
+        """Configure crop alignment in use for future requests.
+
+        :param x: horizontal alignment. 0.0 means left side will be
+           visible or right side is being lost. 1.0 means right
+           side will be visible or left side is being lost. 0.5
+           means just center is visible, both sides will be lost.
+           Default is 0.5.
+        :param y: vertical alignment. 0.0 is top visible, 1.0 is
+           bottom visible, 0.5 is center visible. Default is 0.5
+        """
+        ethumb_client_crop_align_set(self.obj, x, y)
+
+    def crop_get(self):
+        """Get current crop alignment in use for requests.
+
+        :rtype: tuple of float
+        """
+        cdef float x, y
+        ethumb_client_crop_align_get(self.obj, &x, &y)
+        return (x, y)
+
+    property crop:
+        def __set__(self, value):
+            cdef float x, y
+            x, y = value
+            self.crop_set(x, y)
+
+        def __get__(self):
+            return self.crop_get()
+
+    def quality_set(self, int quality):
+        """Configure quality to be used in thumbnails.
+
+        :param quality: value from 0 to 100, default is 80. The
+           effect depends on the format being used, PNG will not
+           use it.
+        """
+        ethumb_client_quality_set(self.obj, quality)
+
+    def quality_get(self):
+        """Get current quality in use for requests.
+
+        :rtype: int
+        """
+        return ethumb_client_quality_get(self.obj)
+
+    property quality:
+        def __set__(self, value):
+            self.quality_set(value)
+
+        def __get__(self):
+            return self.quality_get()
+
+    def compress_set(self, int compress):
+        """Configure compression level used in requests.
+
+        :param compress: value from 0 to 9, default is 9. The effect
+           depends on the format being used, JPEG will not use it.
+        """
+        ethumb_client_compress_set(self.obj, compress)
+
+    def compress_get(self):
+        """Get current compression level in use for requests.
+
+        :rtype: int
+        """
+        return ethumb_client_compress_get(self.obj)
+
+    property compress:
+        def __set__(self, value):
+            self.compress_set(value)
+
+        def __get__(self):
+            return self.compress_get()
+
+    def directory_set(self, path):
+        """Configure where to store thumbnails in future requests.
+
+        Note that this is the base, a category is added to this path
+        as a sub directory.
+
+        :param path: base directory where to store
+           thumbnails. Default is ~/.thumbnails
+        """
+        ethumb_client_dir_path_set(self.obj, str_to_c(path))
+
+    def directory_get(self):
+        """Get current base directory to store thumbnails.
+
+        :rtype: str or None
+        """
+        return str_from_c(ethumb_client_dir_path_get(self.obj))
+
+    property directory:
+        def __set__(self, value):
+            self.directory_set(value)
+
+        def __get__(self):
+            return self.directory_get()
+
+    def category_set(self, category):
+        """Category directory to store thumbnails.
+
+        :param category: category sub directory to store
+           thumbnail. Default is either "normal" or "large" for FDO
+           compliant thumbnails or
+           WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string or
+           None to use auto generated names.
+        """
+        ethumb_client_category_set(self.obj, str_to_c(category))
+
+    def category_get(self):
+        """Get current category sub directory to store thumbnails.
+
+        :rtype: str or None
+        """
+        return str_from_c(ethumb_client_category_get(self.obj))
+
+    property category:
+        def __set__(self, value):
+            self.category_set(value)
+
+        def __get__(self):
+            return self.category_get()
+
+    def frame_set(self, file, group, swallow):
+        """Set frame to apply to future thumbnails.
+
+        This will create an edje object that will have image swallowed
+        in. This can be used to simulate Polaroid or wood frames in
+        the generated image. Remeber it is bad to modify the original
+        contents of thumbnails, but sometimes it's useful to have it
+        composited and avoid runtime overhead.
+
+        :param file: file path to edje.
+        :param group: group inside edje to use.
+        :param swallow: name of swallow part.
+        """
+        cdef:
+            char *f
+            char *g
+            char *s
+        f = str_to_c(file)
+        g = str_to_c(group)
+        s = str_to_c(swallow)
+        return ethumb_client_frame_set(self.obj, f, g, s)
+
+    def file_set(self, path, key=None):
+        """Set file to thumbnail.
+
+        Calling this function will zero :py:func:`thumb_set`
+        specifications. This is done to avoid one using the last thumb
+        path for new images.
+
+        :param path: path to thumbnail subject.
+        :param key: path to key inside **path**, this is used to
+           generate thumbnail of edje groups or images inside EET.
+        """
+        cdef:
+            char *p
+            char *k
+        p = str_to_c(path)
+        k = str_to_c(key)
+        ethumb_client_file_set(self.obj, p, k)
+
+    def file_get(self):
+        """Get current file to thumbnail.
+
+        :rtype: tuple of str
+        """
+        cdef:
+            const char *p
+            const char *k
+        ethumb_client_file_get(self.obj, &p, &k)
+        return (str_from_c(p), str_from_c(k))
+
+    property file:
+        def __set__(self, value):
+            p, k = value
+            self.file_set(p, k)
+
+        def __get__(self):
+            return self.file_get()
+
+    def file_free(self):
+        """Zero/Reset file parameters.
+
+        This call will reset file and thumb specifications.
+
+        .. seealso:: :py:func:`file_set` and :py:func:`thumb_set`
+        """
+        ethumb_client_file_free(self.obj)
+
+    def thumb_set(self, path, key=None):
+        """Set thumbnail path and key.
+
+        Note that these parameters are forgotten (reset) after
+        :py:func:`file_set`.
+
+        :param path: path to generated thumbnail to use, this is an
+           absolute path to file, overriding directory and category.
+        :param key: path to key inside **path**, this is used to
+           generate thumbnail inside EET files.
+        """
+        cdef:
+            const char *p
+            const char *k
+        p = str_to_c(path)
+        k = str_to_c(key)
+        ethumb_client_thumb_path_set(self.obj, p, k)
+
+    def thumb_get(self):
+        """Get current path and key of thumbnail.
+
+        Note that if no explicit :py:func:`thumb_set` was called, it will
+        auto generate path based on existing parameters such as
+        directory, category and others.
+
+        :rtype: tuple of str
+        """
+        cdef:
+            const char *p
+            const char *k
+        ethumb_client_thumb_path_get(self.obj, &p, &k)
+        return (str_from_c(p), str_from_c(k))
+
+    property thumb_path:
+        def __set__(self, value):
+            p, k = value
+            self.thumb_set(p, k)
+        def __get__(self):
+            return self.thumb_get()
+
+    def video_time_set(self, float time):
+        ethumb_client_video_time_set(self.obj, time)
+
+    def video_start_set(self, float start):
+        ethumb_client_video_start_set(self.obj, start)
+
+    def video_interval_set(self, float interval):
+        ethumb_client_video_interval_set(self.obj, interval)
+
+    def video_ntimes_set(self, int ntimes):
+        ethumb_client_video_ntimes_set(self.obj, ntimes)
+
+    def video_fps_set(self, int fps):
+        ethumb_client_video_fps_set(self.obj, fps)
+
+    # document_page
+    def document_page_set(self, int page):
+        ethumb_client_document_page_set(self.obj, page)
+
+    def thumb_exists(self, callback = None, *args, **kwargs):
+        """Checks if thumbnail already exists.
+
+        If you want to avoid regenerating thumbnails, check if they
+        already exist with this function.
+
+        """
+        cdef Ethumb_Client_Thumb_Exists_Cb cb = NULL
+        cdef Ethumb_Exists *res
+
+        if callback:
+            if not callable(callback):
+                raise TypeError("callback is not callable")
+            cb = _thumb_exists_cb
+
+            data = (args, kwargs)
+            res = ethumb_client_thumb_exists(self.obj, cb, <void *>data)
+
+        return False
+        #TODO: handle return value
+
+    def generate(self, func, *args, **kargs):
+        """Ask EThumb server to generate the specified thumbnail.
+
+        Thumbnail generation is asynchronous and depend on ecore main
+        loop running. Given function will be called back with
+        generation status if True is returned by this call. If False
+        is returned, given function will not be called.
+
+        Existing thumbnails will be overwritten with this call. Check
+        if they already exist with :py:func:`exists` before calling.
+
+        :param func: function to call on generation completion, even
+            if failed or succeeded. Signature is::
+
+                func(self, id, file, key, thumb_path, thumb_key, status, 
*args, **kargs)
+
+            with status being True for successful generation or
+            False on failure.
+
+        :return: request identifier. Request can be canceled calling
+            :py:func:`cancel` with given id. If an identifier is returned (>=
+            0), then func is guaranteed to be called unless it is
+            explicitly canceled.
+
+        :raise TypeError: if **func** is not callable.
+        :raise SystemError: if could not generate thumbnail, probably
+           no :py:func:`file_set`.
+
+        .. seealso:: :py:func:`cancel`, :py:func:`clear`, :py:func:`exists`
+        """
+        if not callable(func):
+            raise TypeError("func must be callable")
+
+        targs = (self, func, args, kargs)
+        r = ethumb_client_generate(self.obj, _generated_cb, <void*>targs,
+                                   _generated_cb_free_data)
+        if r >= 0:
+            Py_INCREF(targs)
+            return r
+        else:
+            raise SystemError("could not generate thumbnail. "
+                              "Did you set the file?")
+
+    def generate_cancel(self, int id):
+        """Cancel thumbnail request given its id.
+
+        Calling this function aborts thumbnail generation and **func**
+        given to :py:func:`generate` will not be called!
+
+        :param id: identifier returned by :py:func:`generate`
+        """
+        ethumb_client_generate_cancel(self.obj, id, NULL, NULL, NULL)
+
+    def generate_cancel_all(self):
+        """Clear request queue, canceling all generation requests.
+
+        This will abort all existing requests, no **func** given to
+        :py:func:`generate` will be called.
+
+        Same as calling :py:func:`cancel` in all exising requests.
+        """
+        ethumb_client_generate_cancel_all(self.obj)
+
+init()
diff --git a/include/efl.ethumb.enums.pxd b/include/efl.ethumb.enums.pxd
new file mode 100644
index 0000000..2c6f6e4
--- /dev/null
+++ b/include/efl.ethumb.enums.pxd
@@ -0,0 +1,26 @@
+cdef extern from "Ethumb.h":
+    ctypedef enum Ethumb_Thumb_Orientation:
+        ETHUMB_THUMB_ORIENT_NONE     # keep orientation as pixel data is
+        ETHUMB_THUMB_ROTATE_90_CW    # rotate 90° clockwise
+        ETHUMB_THUMB_ROTATE_180      # rotate 180°
+        ETHUMB_THUMB_ROTATE_90_CCW   # rotate 90° counter-clockwise
+        ETHUMB_THUMB_FLIP_HORIZONTAL # flip horizontally
+        ETHUMB_THUMB_FLIP_VERTICAL   # flip vertically
+        ETHUMB_THUMB_FLIP_TRANSPOSE  # transpose
+        ETHUMB_THUMB_FLIP_TRANSVERSE # transverse
+        ETHUMB_THUMB_ORIENT_ORIGINAL  # use orientation from metadata 
(EXIF-only currently)
+
+    ctypedef enum Ethumb_Thumb_FDO_Size:
+        ETHUMB_THUMB_NORMAL # 128x128 as defined by FreeDesktop.Org standard
+        ETHUMB_THUMB_LARGE   # 256x256 as defined by FreeDesktop.Org standard
+
+    ctypedef enum Ethumb_Thumb_Format:
+        ETHUMB_THUMB_FDO   # PNG as defined by FreeDesktop.Org standard
+        ETHUMB_THUMB_JPEG  # JPEGs are often smaller and faster to read/write
+        ETHUMB_THUMB_EET    # EFL's own storage system, supports key parameter
+
+    ctypedef enum Ethumb_Thumb_Aspect:
+        ETHUMB_THUMB_KEEP_ASPECT # keep original proportion between width and 
height
+        ETHUMB_THUMB_IGNORE_ASPECT # ignore aspect and foce it to match 
thumbnail's width and height
+        ETHUMB_THUMB_CROP # keep aspect but crop (cut) the largest dimension
+
diff --git a/include/efl.ethumb.pxd b/include/efl.ethumb.pxd
new file mode 100644
index 0000000..16ffe60
--- /dev/null
+++ b/include/efl.ethumb.pxd
@@ -0,0 +1,106 @@
+# Copyright (C) 2009 by ProFUSION embedded systems
+#
+# This file is part of Python-Ethumb.
+#
+# Python-Ethumb is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-Ethumb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-Ethumb.  If not, see <http://www.gnu.org/licenses/>.
+
+from efl.eina cimport Eina_Bool, Eina_Free_Cb
+from efl.ethumb.enums cimport Ethumb_Thumb_FDO_Size, Ethumb_Thumb_Format, \
+    Ethumb_Thumb_Aspect, Ethumb_Thumb_Orientation
+
+cdef extern from "Ethumb.h":
+    cdef struct Ethumb:
+        int tw
+        int th
+        int format
+        int aspect
+
+    ctypedef void (*Ethumb_Generate_Cb)(void *data, Ethumb *e, Eina_Bool 
success)
+
+    # Ethumb
+    int                         ethumb_init()
+    void                        ethumb_shutdown()
+    Ethumb                      *ethumb_new()
+    void                        ethumb_free(Ethumb *e)
+
+    # Setup
+    Eina_Bool                   ethumb_frame_set(Ethumb *e, const char 
*theme_file, const char *group, const char *swallow)
+    void                        ethumb_frame_get(Ethumb *e, const char 
**theme_file, const char **group, const char **swallow)
+
+    void                        ethumb_thumb_dir_path_set(Ethumb *e, const 
char *path)
+    const char *             ethumb_thumb_dir_path_get(Ethumb *e)
+
+    void                        ethumb_thumb_category_set(Ethumb *e, const 
char *category)
+    const char *             ethumb_thumb_category_get(Ethumb *e)
+
+    void                        ethumb_thumb_path_set(Ethumb *e, const char 
*path, const char *key)
+    void                        ethumb_thumb_path_get(Ethumb *e, const char 
**path, const char **key)
+    void                        ethumb_thumb_hash(Ethumb *e)
+    void                        ethumb_thumb_hash_copy(Ethumb *dst, Ethumb 
*src)
+
+
+    void                        ethumb_thumb_fdo_set(Ethumb *e, 
Ethumb_Thumb_FDO_Size s)
+
+    void                        ethumb_thumb_size_set(Ethumb *e, int tw, int 
th)
+    void                        ethumb_thumb_size_get(Ethumb *e, int *tw, int 
*th)
+
+    void                        ethumb_thumb_format_set(Ethumb *e, 
Ethumb_Thumb_Format f)
+    Ethumb_Thumb_Format         ethumb_thumb_format_get(Ethumb *e)
+
+    void                        ethumb_thumb_aspect_set(Ethumb *e, 
Ethumb_Thumb_Aspect a)
+    Ethumb_Thumb_Aspect         ethumb_thumb_aspect_get(Ethumb *e)
+
+    void                        ethumb_thumb_orientation_set(Ethumb *e, 
Ethumb_Thumb_Orientation o)
+    Ethumb_Thumb_Orientation    ethumb_thumb_orientation_get(Ethumb *e)
+
+    void                        ethumb_thumb_crop_align_set(Ethumb *e, float 
x, float y)
+    void                        ethumb_thumb_crop_align_get(Ethumb *e, float 
*x, float *y)
+
+    void                        ethumb_thumb_quality_set(Ethumb *e, int 
quality)
+    int                         ethumb_thumb_quality_get(Ethumb *e)
+
+    void                        ethumb_thumb_compress_set(Ethumb *e, int 
compress)
+    int                         ethumb_thumb_compress_get(Ethumb *e)
+
+    void                        ethumb_video_start_set(Ethumb *e, float start)
+    float                       ethumb_video_start_get(Ethumb *e)
+    void                        ethumb_video_time_set(Ethumb *e, float time)
+    float                       ethumb_video_time_get(Ethumb *e)
+    void                        ethumb_video_interval_set(Ethumb *e, float 
interval)
+    float                       ethumb_video_interval_get(Ethumb *e)
+    void                        ethumb_video_ntimes_set(Ethumb *e, unsigned 
int ntimes)
+    unsigned int                ethumb_video_ntimes_get(Ethumb *e)
+    void                        ethumb_video_fps_set(Ethumb *e, unsigned int 
fps)
+    unsigned int                ethumb_video_fps_get(Ethumb *e)
+
+    # Basics
+    void                        ethumb_document_page_set(Ethumb *e, unsigned 
int page)
+    unsigned int                ethumb_document_page_get(Ethumb *e)
+
+    Eina_Bool                   ethumb_file_set(Ethumb *e, const char *path, 
const char *key)
+    void                        ethumb_file_get(Ethumb *e, const char **path, 
const char **key)
+    void                        ethumb_file_free(Ethumb *e)
+
+    Eina_Bool                   ethumb_generate(Ethumb *e, Ethumb_Generate_Cb 
finished_cb, void *data, Eina_Free_Cb free_data)
+    Eina_Bool                   ethumb_exists(Ethumb *e)
+
+    Ethumb                      *ethumb_dup(Ethumb *e)
+    Eina_Bool                   ethumb_cmp(Ethumb *e1, Ethumb *e2)
+    int                         ethumb_hash(void *key, int key_length)
+    int                         ethumb_key_cmp(void *key1, int key1_length, 
void *key2, int key2_length)
+    unsigned int                ethumb_length(void *key)
+
+
+cdef class PyEthumb:
+    cdef Ethumb *obj
diff --git a/include/efl.ethumb_client.pxd b/include/efl.ethumb_client.pxd
new file mode 100644
index 0000000..902f4dd
--- /dev/null
+++ b/include/efl.ethumb_client.pxd
@@ -0,0 +1,96 @@
+# Copyright (C) 2009 by ProFUSION embedded systems
+#
+# This file is part of Python-Ethumb.
+#
+# Python-Ethumb is free software you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# Python-Ethumb is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this Python-Ethumb.  If not, see <http://www.gnu.org/licenses/>.
+
+from efl.eina cimport Eina_Bool, Eina_Free_Cb
+from efl.ethumb.enums cimport Ethumb_Thumb_Orientation
+
+cdef extern from "Ethumb_Client.h":
+    ctypedef struct Ethumb_Client
+    ctypedef struct Ethumb_Exists
+    ctypedef void (*Ethumb_Client_Connect_Cb)(void *data, Ethumb_Client 
*client, Eina_Bool success)
+    ctypedef void (*Ethumb_Client_Die_Cb)(void *data, Ethumb_Client *client)
+    ctypedef 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)
+    ctypedef void (*Ethumb_Client_Thumb_Exists_Cb)(void *data, Ethumb_Client 
*client, Ethumb_Exists *thread, Eina_Bool exists)
+    ctypedef void (*Ethumb_Client_Generate_Cancel_Cb)(void *data, Eina_Bool 
success)
+
+    int             ethumb_client_init()
+    int             ethumb_client_shutdown()
+
+    Ethumb_Client   *ethumb_client_connect(Ethumb_Client_Connect_Cb cb, void 
*data, Eina_Free_Cb free_data)
+    void            ethumb_client_disconnect(Ethumb_Client *client)
+    void            ethumb_client_on_server_die_callback_set(Ethumb_Client 
*client, Ethumb_Client_Die_Cb server_die_cb, void *data, Eina_Free_Cb free_data)
+
+    void            ethumb_client_fdo_set(Ethumb_Client *client, int s)
+
+    void            ethumb_client_size_set(Ethumb_Client *client, int tw, int 
th)
+    void            ethumb_client_size_get(Ethumb_Client *client, int *tw, int 
*th)
+    void            ethumb_client_format_set(Ethumb_Client *client, int f)
+    int             ethumb_client_format_get(Ethumb_Client *client)
+    void            ethumb_client_aspect_set(Ethumb_Client *client, int a)
+    int             ethumb_client_aspect_get(Ethumb_Client *client)
+    void            ethumb_client_orientation_set(Ethumb_Client *client, 
Ethumb_Thumb_Orientation o)
+    Ethumb_Thumb_Orientation ethumb_client_orientation_get(Ethumb_Client 
*client)
+    void            ethumb_client_crop_align_set(Ethumb_Client *client, float 
x, float y)
+    void            ethumb_client_crop_align_get(Ethumb_Client *client, float 
*x, float *y)
+    void            ethumb_client_quality_set(Ethumb_Client *client, int 
quality)
+    int             ethumb_client_quality_get(Ethumb_Client *client)
+    void            ethumb_client_compress_set(Ethumb_Client *client, int 
compress)
+    int             ethumb_client_compress_get(Ethumb_Client *client)
+    Eina_Bool       ethumb_client_frame_set(Ethumb_Client *client, const char 
*file, const char *group, const char *swallow)
+    void            ethumb_client_dir_path_set(Ethumb_Client *client, const 
char *path)
+    const char * ethumb_client_dir_path_get(Ethumb_Client *client)
+    void            ethumb_client_category_set(Ethumb_Client *client, const 
char *category)
+    const char * ethumb_client_category_get(Ethumb_Client *client)
+    void            ethumb_client_video_time_set(Ethumb_Client *client, float 
time)
+    void            ethumb_client_video_start_set(Ethumb_Client *client, float 
start)
+    void            ethumb_client_video_interval_set(Ethumb_Client *client, 
float interval)
+    void            ethumb_client_video_ntimes_set(Ethumb_Client *client, int 
ntimes)
+    void            ethumb_client_video_fps_set(Ethumb_Client *client, int fps)
+    void            ethumb_client_document_page_set(Ethumb_Client *client, int 
page)
+
+    void            ethumb_client_ethumb_setup(Ethumb_Client *client)
+
+    void            ethumb_client_thumb_path_set(Ethumb_Client *client, const 
char *path, const char *key)
+    void            ethumb_client_thumb_path_get(Ethumb_Client *client, const 
char **path, const char **key)
+
+    Eina_Bool       ethumb_client_file_set(Ethumb_Client *client, const char 
*path, const char *key)
+    void            ethumb_client_file_get(Ethumb_Client *client, const char 
**path, const char **key)
+    void            ethumb_client_file_free(Ethumb_Client *client)
+
+    Ethumb_Exists   *ethumb_client_thumb_exists(Ethumb_Client *client, 
Ethumb_Client_Thumb_Exists_Cb exists_cb, void *data)
+    void            ethumb_client_thumb_exists_cancel(Ethumb_Exists *exists)
+    Eina_Bool       ethumb_client_thumb_exists_check(Ethumb_Exists *exists)
+    int             ethumb_client_generate(Ethumb_Client *client, 
Ethumb_Client_Generate_Cb generated_cb, void *data, Eina_Free_Cb free_data)
+    void            ethumb_client_generate_cancel(Ethumb_Client *client, int 
id, Ethumb_Client_Generate_Cancel_Cb cancel_cb, void *data, Eina_Free_Cb 
free_data)
+    void            ethumb_client_generate_cancel_all(Ethumb_Client *client)
+
+    ctypedef void (*Ethumb_Client_Async_Done_Cb)(Ethumb_Client *ethumbd, const 
char *thumb_path, const char *thumb_key, void *data)
+    ctypedef void (*Ethumb_Client_Async_Error_Cb)(Ethumb_Client *ethumbd, void 
*data)
+
+    ctypedef struct Ethumb_Client_Async
+
+    Ethumb_Client_Async *ethumb_client_thumb_async_get(Ethumb_Client *client,
+                            Ethumb_Client_Async_Done_Cb done,
+                            Ethumb_Client_Async_Error_Cb error,
+                            void *data)
+
+    void            ethumb_client_thumb_async_cancel(Ethumb_Client *client, 
Ethumb_Client_Async *request)
+
+cdef class Client:
+    cdef Ethumb_Client *obj
+    cdef object _on_connect_callback
+    cdef object _on_server_die_callback
diff --git a/setup.py b/setup.py
index bd37371..822be2c 100755
--- a/setup.py
+++ b/setup.py
@@ -186,6 +186,24 @@ if set(("build", "build_ext", "install", "bdist", 
"sdist")) & set(sys.argv):
     package_dirs["ecore"] = "compat/ecore"
 
 
+    # === Ethumb ===
+    ethumb_cflags, ethumb_libs = pkg_config('Ethumb', 'ethumb', 
EFL_MIN_VERSION)
+    ethumb_ext = Extension("ethumb", ["efl/ethumb/efl.ethumb"+module_suffix],
+                         include_dirs = ['include/'],
+                         extra_compile_args = ethumb_cflags,
+                         extra_link_args = ethumb_libs + eina_libs,
+                        )
+    modules.append(ethumb_ext)
+
+    ethumb_client_cflags, ethumb_client_libs = pkg_config('Ethumb_Client', 
'ethumb_client', EFL_MIN_VERSION)
+    ethumb_client_ext = Extension("ethumb_client", 
["efl/ethumb/efl.ethumb_client"+module_suffix],
+                         include_dirs = ['include/'],
+                         extra_compile_args = ethumb_client_cflags,
+                         extra_link_args = ethumb_client_libs + eina_libs,
+                        )
+    modules.append(ethumb_client_ext)
+
+
     # === Edje ===
     edje_cflags, edje_libs = pkg_config('Edje', 'edje', EFL_MIN_VERSION)
     edje_ext = Extension("edje", ["efl/edje/efl.edje"+module_suffix],

-- 


Reply via email to