summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@gmail.com>2009-07-15 04:19:44 +0000
committerGustavo Sverzut Barbieri <barbieri@gmail.com>2009-07-15 04:19:44 +0000
commit8db7791cde8adf8d2d96251323dfaf8f0bd97fdd (patch)
treeb42a2ddba6ba76fd1514b391cb20e9bc7bfec1c7
parentf6eeda654637394b08975c1d449b1fd94f81218e (diff)
Ethumb python improvements.
* docs (should copy to C later) * on_server_die callback * explicit disconnect() * better finalization and error handling * simple example. SVN revision: 41346
-rwxr-xr-xbuild.sh20
-rw-r--r--ethumb/ethumb.client.pyx384
-rwxr-xr-xexamples/01-simple.py49
-rw-r--r--include/ethumb/client.pxd3
4 files changed, 421 insertions, 35 deletions
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..e3cfd7d
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,20 @@
1#!/bin/sh
2
3PREFIX="$HOME/usr"
4PYX_FILES="ethumb/ethumb.c_ethumb.pyx ethumb/ethumb.client.pyx"
5
6for arg in $@; do
7 case $arg in
8 --force)
9 touch $PYX_FILES
10 ;;
11 *)
12 PREFIX="$arg"
13 ;;
14 esac
15done
16
17PYINCDIR=`python -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc()" | cut -d/ -f3-`
18INCDIR="$PREFIX/$PYINCDIR"
19
20python setup.py build_ext --include-dirs="$INCDIR" develop --prefix="$PREFIX" install_headers --install-dir="$INCDIR"
diff --git a/ethumb/ethumb.client.pyx b/ethumb/ethumb.client.pyx
index d1a336f..3c0a6c0 100644
--- a/ethumb/ethumb.client.pyx
+++ b/ethumb/ethumb.client.pyx
@@ -29,20 +29,34 @@ def init():
29 return ethumb_client_init() 29 return ethumb_client_init()
30 30
31cdef void _connect_cb(Ethumb_Client *client, Eina_Bool success, void *data) with gil: 31cdef void _connect_cb(Ethumb_Client *client, Eina_Bool success, void *data) with gil:
32 obj = <object>data 32 cdef Client self = <Client>data
33 (self, func, args, kargs) = obj 33 s = bool(<unsigned int>success)
34 if success:
35 s = True
36 else:
37 s = False
38 try: 34 try:
35 func, args, kargs = self._on_connect_callback
39 func(self, s, *args, **kargs) 36 func(self, s, *args, **kargs)
40 except Exception, e: 37 except Exception, e:
41 traceback.print_exc() 38 traceback.print_exc()
42 39
43cdef void _free_connect_cb_data(void *data) with gil: 40 if not s and self.obj != NULL:
44 obj = <object>data 41 ethumb_client_disconnect(self.obj)
45 python.Py_DECREF(obj) 42 self.obj = NULL
43 self._on_connect_callback = None
44
45
46cdef void _on_server_die_cb(Ethumb_Client *client, void *data) with gil:
47 cdef Client self = <Client>data
48 if self._on_server_die_callback is not None:
49 try:
50 func, args, kargs = self._on_server_die_callback
51 func(self, *args, **kargs)
52 except Exception, e:
53 traceback.print_exc()
54
55 if self.obj != NULL:
56 ethumb_client_disconnect(self.obj)
57 self.obj = NULL
58 self._on_server_die_callback = None
59
46 60
47cdef void _generated_cb(int id, char *file, char *key, char *thumb_path, char *thumb_key, Eina_Bool success, void *data) with gil: 61cdef void _generated_cb(int id, char *file, char *key, char *thumb_path, char *thumb_key, Eina_Bool success, void *data) with gil:
48 obj = <object>data 62 obj = <object>data
@@ -78,26 +92,140 @@ cdef object str_from_c(char *mystr):
78 return mystr 92 return mystr
79 93
80cdef class Client: 94cdef class Client:
81 """Client for Ethumbd server.""" 95 """Client for Ethumbd server.
96
97 This client is the recommended way to generate thumbnails with
98 Ethumb. All you have to do is create a client instance, wait it to
99 be connected to server, configure thumbnail parameters and then
100 start feed it with file_set(), exists() generate(). Basic steps are:
101
102 - instantiate Client, wait for func to be called with success.
103 - set various parameters, like format and size.
104 - loop on original files:
105 - C{c.file_set(file)}
106 - C{if not c.exists(): c.generate(generated_cb)}
107
108 When the last reference to client is released, server is
109 automatically disconnected. Since callback may contain references
110 to server itself, it is recommended explicit call to
111 L{disconnect()} function.
112 """
113
82 def __init__(self, func, *args, **kargs): 114 def __init__(self, func, *args, **kargs):
83 """Ethumb Client constructor.""" 115 """Ethumb Client constructor.
116
117 Server is ready to receive requests just after B{func} is
118 called back with C{status == True}.
119
120 @parm: B{func} function to call when connection with server is
121 established. Function signature is:
122 C{func(client, status, *args, **kargs)}
123 with status being True for successful connection or False
124 on error.
125
126 @raise TypeError: if B{func} is not callable.
127 @raise SystemError: if it was not possible to connect to
128 server, allocate memory or use DBus.
129 """
84 if not callable(func): 130 if not callable(func):
85 raise TypeError("Parameter 'func' must be callable") 131 raise TypeError("Parameter 'func' must be callable")
86 if self.obj == NULL: 132 if self.obj == NULL:
87 targs = (self, func, args, kargs) 133 self._on_connect_callback = (func, args, kargs)
88 python.Py_INCREF(targs) 134 self._on_server_die_callback = None
89 self.obj = ethumb_client_connect( 135 self.obj = ethumb_client_connect(_connect_cb, <void*>self, NULL)
90 _connect_cb, <void*>targs, _free_connect_cb_data) 136 if self.obj == NULL:
137 raise SystemError("Error connecting to server.")
138 else:
139 ethumb_client_on_server_die_callback_set(
140 self.obj, _on_server_die_cb, <void*>self)
141
142 def __dealloc__(self):
143 if self.obj != NULL:
144 ethumb_client_disconnect(self.obj)
145
146 def disconnect(self):
147 """Explicitly request server disconnection.
148
149 After this call object becomes shallow, that is operations
150 will be void.
151 """
152 if self.obj != NULL:
153 ethumb_client_disconnect(self.obj)
154 self.obj = NULL
155 self._on_connect_callback = None
156 self._on_server_die_callback = None
157
158 def __str__(self):
159 f, k = self.file
160 tf, tk = self.thumb_path
161 w, h = self.size
162
163 format = ("FDO", "JPEG", "EET")[self.format]
164 aspect = ("KEEP", "IGNORE", "CROP")[self.aspect]
165 if self.aspect == 2:
166 aspect = "CROP[%f, %f]" % self.crop
167 return ("%s(file=(%r, %r), thumb=(%r, %r), exists=%s, size=%dx%d, "
168 "format=%s, aspect=%s, quality=%d, compress=%d, "
169 "directory=%r, category=%r)") % \
170 (self.__class__.__name__, f, k, tf, tk, self.exists(),
171 w, h, format, aspect, self.quality, self.compress,
172 self.directory, self.category)
173
174 def __repr__(self):
175 f, k = self.file
176 tf, tk = self.thumb_path
177 return "%s(obj=%#x, file=(%r, %r), thumb=(%r, %r), exists=%s)" % \
178 (self.__class__.__name__, f, k, tf, tk, self.exists())
179
180 def on_server_die_callback_set(self, func, *args, **kargs):
181 """Function to call when server dies.
182
183 When server is dead there is nothing to do with this client
184 anymore, just create a new one and start over, hope that
185 server could be started and you could generate more
186 thumbnails.
187
188 @parm: B{func} function to call when server dies. Signature:
189 C{func(client, *args, **kargs)
190
191 @raise TypeError: if B{func} is not callable or None.
192 """
193 if func is None:
194 self._on_server_die_callback = None
195 elif callable(func):
196 self._on_server_die_callback = (func, args, kargs)
197 else:
198 raise TypeError("Parameter 'func' must be callable or None")
91 199
92 # FDO
93 def fdo_set(self, int s): 200 def fdo_set(self, int s):
201 """Configure future requests to use FreeDesktop.Org preset.
202
203 This is a preset to provide freedesktop.org (fdo) standard
204 compliant thumbnails. That is, files are stored as JPEG under
205 ~/.thumbnails/SIZE, with size being either normal (128x128) or
206 large (256x256).
207
208 @parm: B{s} size identifier, either ETHUMB_THUMB_NORMAL (0) or
209 ETHUMB_THUMB_LARGE.
210
211 @see: L{size_set()}, L{format_set()}, L{aspect_set()}, L{crop_set()},
212 L{category_set()}, L{directory_set()}.
213 """
94 ethumb_client_fdo_set(self.obj, s) 214 ethumb_client_fdo_set(self.obj, s)
95 215
96 # Size
97 def size_set(self, int w, int h): 216 def size_set(self, int w, int h):
217 """Configure future request to use custom size.
218
219 @parm: B{w} width, default is 128.
220 @parm: B{h} height, default is 128.
221 """
98 ethumb_client_size_set(self.obj, w, h) 222 ethumb_client_size_set(self.obj, w, h)
99 223
100 def size_get(self): 224 def size_get(self):
225 """Get current size being used by requests.
226
227 @rtype: tuple of int.
228 """
101 cdef int w, h 229 cdef int w, h
102 ethumb_client_size_get(self.obj, &w, &h) 230 ethumb_client_size_get(self.obj, &w, &h)
103 return (w, h) 231 return (w, h)
@@ -111,11 +239,19 @@ cdef class Client:
111 def __get__(self): 239 def __get__(self):
112 return self.size_get() 240 return self.size_get()
113 241
114 # Format
115 def format_set(self, int f): 242 def format_set(self, int f):
243 """Configure format to use for future requests.
244
245 @parm: B{f} format identifier to use, either ETHUMB_THUMB_FDO (0),
246 ETHUMB_THUMB_JPEG (1) or ETHUMB_THUMB_EET (2). Default is FDO.
247 """
116 ethumb_client_format_set(self.obj, f) 248 ethumb_client_format_set(self.obj, f)
117 249
118 def format_get(self): 250 def format_get(self):
251 """Get current format in use for requests.
252
253 @rtype: int
254 """
119 return ethumb_client_format_get(self.obj) 255 return ethumb_client_format_get(self.obj)
120 256
121 property format: 257 property format:
@@ -125,11 +261,42 @@ cdef class Client:
125 def __get__(self): 261 def __get__(self):
126 return self.format_get() 262 return self.format_get()
127 263
128 # Aspect
129 def aspect_set(self, int a): 264 def aspect_set(self, int a):
265 """Configure aspect mode to use.
266
267 If aspect is kept (ETHUMB_THUMB_KEEP_ASPECT), then image will
268 be rescaled so the largest dimension is not bigger than it's
269 specified size (see L{size_get()}) and the other dimension is
270 resized in the same proportion. Example: size is 256x256,
271 image is 1000x500, resulting thumbnail is 256x128.
272
273 If aspect is ignored (ETHUMB_THUMB_IGNORE_ASPECT), then image
274 will be distorted to match required thumbnail size. Example:
275 size is 256x256, image is 1000x500, resulting thumbnail is
276 256x256.
277
278 If crop is required (ETHUMB_THUMB_CROP), then image will be
279 cropped so the smallest dimension is not bigger than its
280 specified size (see L{size_get()}) and the other dimension
281 will overflow, not being visible in the final image. How it
282 will overflow is speficied by L{crop_set()}
283 alignment. Example: size is 256x256, image is 1000x500, crop
284 alignment is 0.5, 0.5, resulting thumbnail is 256x256 with 250
285 pixels from left and 250 pixels from right being lost, that is
286 just the 500x500 central pixels of image will be considered
287 for scaling.
288
289 @parm: B{a} aspect mode identifier, either ETHUMB_THUMB_KEEP_ASPECT (0),
290 ETHUMB_THUMB_IGNORE_ASPECT (1) or ETHUMB_THUMB_CROP (2).
291
292 """
130 ethumb_client_aspect_set(self.obj, a) 293 ethumb_client_aspect_set(self.obj, a)
131 294
132 def aspect_get(self): 295 def aspect_get(self):
296 """Get current aspect in use for requests.
297
298 @rtype: int
299 """
133 return ethumb_client_aspect_get(self.obj) 300 return ethumb_client_aspect_get(self.obj)
134 301
135 property aspect: 302 property aspect:
@@ -139,11 +306,24 @@ cdef class Client:
139 def __get__(self): 306 def __get__(self):
140 return self.aspect_get() 307 return self.aspect_get()
141 308
142 # Crop
143 def crop_set(self, float x, float y): 309 def crop_set(self, float x, float y):
310 """Configure crop alignment in use for future requests.
311
312 @parm: B{x} horizontal alignment. 0.0 means left side will be
313 visible or right side is being lost. 1.0 means right
314 side will be visible or left side is being lost. 0.5
315 means just center is visible, both sides will be lost.
316 Default is 0.5.
317 @parm: B{y} vertical alignment. 0.0 is top visible, 1.0 is
318 bottom visible, 0.5 is center visible. Default is 0.5
319 """
144 ethumb_client_crop_align_set(self.obj, x, y) 320 ethumb_client_crop_align_set(self.obj, x, y)
145 321
146 def crop_get(self): 322 def crop_get(self):
323 """Get current crop alignment in use for requests.
324
325 @rtype: tuple of float
326 """
147 cdef float x, y 327 cdef float x, y
148 ethumb_client_crop_align_get(self.obj, &x, &y) 328 ethumb_client_crop_align_get(self.obj, &x, &y)
149 return (x, y) 329 return (x, y)
@@ -157,11 +337,20 @@ cdef class Client:
157 def __get__(self): 337 def __get__(self):
158 return self.crop_get() 338 return self.crop_get()
159 339
160 # Quality
161 def quality_set(self, int quality): 340 def quality_set(self, int quality):
341 """Configure quality to be used in thumbnails.
342
343 @parm: B{quality} value from 0 to 100, default is 80. The
344 effect depends on the format being used, PNG will not
345 use it.
346 """
162 ethumb_client_quality_set(self.obj, quality) 347 ethumb_client_quality_set(self.obj, quality)
163 348
164 def quality_get(self): 349 def quality_get(self):
350 """Get current quality in use for requests.
351
352 @rtype: int
353 """
165 return ethumb_client_quality_get(self.obj) 354 return ethumb_client_quality_get(self.obj)
166 355
167 property quality: 356 property quality:
@@ -171,11 +360,19 @@ cdef class Client:
171 def __get__(self): 360 def __get__(self):
172 return self.quality_get() 361 return self.quality_get()
173 362
174 # Compress
175 def compress_set(self, int compress): 363 def compress_set(self, int compress):
364 """Configure compression level used in requests.
365
366 @parm: B{compress} value from 0 to 9, default is 9. The effect
367 depends on the format being used, JPEG will not use it.
368 """
176 ethumb_client_compress_set(self.obj, compress) 369 ethumb_client_compress_set(self.obj, compress)
177 370
178 def compress_get(self): 371 def compress_get(self):
372 """Get current compression level in use for requests.
373
374 @rtype: int
375 """
179 return ethumb_client_compress_get(self.obj) 376 return ethumb_client_compress_get(self.obj)
180 377
181 property compress: 378 property compress:
@@ -185,11 +382,22 @@ cdef class Client:
185 def __get__(self): 382 def __get__(self):
186 return self.compress_get() 383 return self.compress_get()
187 384
188 # Directory
189 def directory_set(self, path): 385 def directory_set(self, path):
386 """Configure where to store thumbnails in future requests.
387
388 Note that this is the base, a category is added to this path
389 as a sub directory.
390
391 @parm: B{path} base directory where to store
392 thumbnails. Default is ~/.thumbnails
393 """
190 ethumb_client_dir_path_set(self.obj, str_to_c(path)) 394 ethumb_client_dir_path_set(self.obj, str_to_c(path))
191 395
192 def directory_get(self): 396 def directory_get(self):
397 """Get current base directory to store thumbnails.
398
399 @rtype: str or None
400 """
193 return str_from_c(ethumb_client_dir_path_get(self.obj)) 401 return str_from_c(ethumb_client_dir_path_get(self.obj))
194 402
195 property directory: 403 property directory:
@@ -199,11 +407,22 @@ cdef class Client:
199 def __get__(self): 407 def __get__(self):
200 return self.directory_get() 408 return self.directory_get()
201 409
202 # Category
203 def category_set(self, category): 410 def category_set(self, category):
411 """Category directory to store thumbnails.
412
413 @parm: B{category} category sub directory to store
414 thumbnail. Default is either "normal" or "large" for FDO
415 compliant thumbnails or
416 WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT. It can be a string or
417 None to use auto generated names.
418 """
204 ethumb_client_category_set(self.obj, str_to_c(category)) 419 ethumb_client_category_set(self.obj, str_to_c(category))
205 420
206 def category_get(self): 421 def category_get(self):
422 """Get current category sub directory to store thumbnails.
423
424 @rtype: str or None
425 """
207 return str_from_c(ethumb_client_category_get(self.obj)) 426 return str_from_c(ethumb_client_category_get(self.obj))
208 427
209 property category: 428 property category:
@@ -213,22 +432,46 @@ cdef class Client:
213 def __get__(self): 432 def __get__(self):
214 return self.category_get() 433 return self.category_get()
215 434
216 # frame
217 def frame_set(self, file, group, swallow): 435 def frame_set(self, file, group, swallow):
436 """Set frame to apply to future thumbnails.
437
438 This will create an edje object that will have image swallowed
439 in. This can be used to simulate Polaroid or wood frames in
440 the generated image. Remeber it is bad to modify the original
441 contents of thumbnails, but sometimes it's useful to have it
442 composited and avoid runtime overhead.
443
444 @parm: B{file} file path to edje.
445 @parm: B{group} group inside edje to use.
446 @parm: B{swallow} name of swallow part.
447 """
218 cdef char *f, *g, *s 448 cdef char *f, *g, *s
219 f = str_to_c(file) 449 f = str_to_c(file)
220 g = str_to_c(group) 450 g = str_to_c(group)
221 s = str_to_c(swallow) 451 s = str_to_c(swallow)
222 return ethumb_client_frame_set(self.obj, f, g, s) 452 return ethumb_client_frame_set(self.obj, f, g, s)
223 453
224 # file
225 def file_set(self, path, key=None): 454 def file_set(self, path, key=None):
455 """Set file to thumbnail.
456
457 Calling this function will zero L{thumb_set()}
458 specifications. This is done to avoid one using the last thumb
459 path for new images.
460
461 @parm: B{path} path to thumbnail subject.
462 @parm: B{key} path to key inside B{path}, this is used to
463 generate thumbnail of edje groups or images inside EET.
464 """
226 cdef char *p, *k 465 cdef char *p, *k
227 p = str_to_c(path) 466 p = str_to_c(path)
228 k = str_to_c(key) 467 k = str_to_c(key)
229 ethumb_client_file_set(self.obj, p, k) 468 ethumb_client_file_set(self.obj, p, k)
230 469
231 def file_get(self): 470 def file_get(self):
471 """Get current file to thumbnail.
472
473 @rtype: tuple of str
474 """
232 cdef char *p, *k 475 cdef char *p, *k
233 ethumb_client_file_get(self.obj, &p, &k) 476 ethumb_client_file_get(self.obj, &p, &k)
234 return (str_from_c(p), str_from_c(k)) 477 return (str_from_c(p), str_from_c(k))
@@ -242,16 +485,39 @@ cdef class Client:
242 return self.file_get() 485 return self.file_get()
243 486
244 def file_free(self): 487 def file_free(self):
488 """Zero/Reset file parameters.
489
490 This call will reset file and thumb specifications.
491
492 @see: L{file_set()} and L{thumb_set()}
493 """
245 ethumb_client_file_free(self.obj) 494 ethumb_client_file_free(self.obj)
246 495
247 # thumbnail
248 def thumb_set(self, path, key=None): 496 def thumb_set(self, path, key=None):
497 """Set thumbnail path and key.
498
499 Note that these parameters are forgotten (reset) after
500 L{file_set()}.
501
502 @parm: B{path} path to generated thumbnail to use, this is an
503 absolute path to file, overriding directory and category.
504 @parm: B{key} path to key inside B{path}, this is used to
505 generate thumbnail inside EET files.
506 """
249 cdef char *p, *k 507 cdef char *p, *k
250 p = str_to_c(path) 508 p = str_to_c(path)
251 k = str_to_c(key) 509 k = str_to_c(key)
252 ethumb_client_thumb_path_set(self.obj, p, k) 510 ethumb_client_thumb_path_set(self.obj, p, k)
253 511
254 def thumb_get(self): 512 def thumb_get(self):
513 """Get current path and key of thumbnail.
514
515 Note that if no explicit L{thumb_set()} was called, it will
516 auto generate path based on existing parameters such as
517 directory, category and others.
518
519 @rtype: tuple of str
520 """
255 cdef char *p, *k 521 cdef char *p, *k
256 ethumb_client_thumb_path_get(self.obj, &p, &k) 522 ethumb_client_thumb_path_get(self.obj, &p, &k)
257 return (str_from_c(p), str_from_c(k)) 523 return (str_from_c(p), str_from_c(k))
@@ -263,7 +529,6 @@ cdef class Client:
263 def __get__(self): 529 def __get__(self):
264 return self.thumb_get() 530 return self.thumb_get()
265 531
266 # video_time
267 def video_time_set(self, float time): 532 def video_time_set(self, float time):
268 ethumb_client_video_time_set(self.obj, time) 533 ethumb_client_video_time_set(self.obj, time)
269 534
@@ -283,24 +548,73 @@ cdef class Client:
283 def document_page_set(self, int page): 548 def document_page_set(self, int page):
284 ethumb_client_document_page_set(self.obj, page) 549 ethumb_client_document_page_set(self.obj, page)
285 550
286 # thumbnail generation
287 def exists(self): 551 def exists(self):
288 return ethumb_client_thumb_exists(self.obj) 552 """Checks if thumbnail already exists.
553
554 If you want to avoid regenerating thumbnails, check if they
555 already exist with this function.
556 """
557 return bool(ethumb_client_thumb_exists(self.obj))
289 558
290 def generate(self, func, *args, **kargs): 559 def generate(self, func, *args, **kargs):
560 """Ask EThumb server to generate the specified thumbnail.
561
562 Thumbnail generation is asynchronous and depend on ecore main
563 loop running. Given function will be called back with
564 generation status if True is returned by this call. If False
565 is returned, given function will not be called.
566
567 Existing thumbnails will be overwritten with this call. Check
568 if they already exist with L{exists()} before calling.
569
570 @parm: B{func} function to call on generation completion, even
571 if failed or succeeded. Signature is:
572 C{func(id, file, key, thumb_path, thumb_key, status, *args, **kargs)}
573 with status being True for successful generation or
574 False on failure.
575
576 @return: request identifier. Request can be canceled calling
577 L{cancel()} with given id. If an identifier is returned (>=
578 0), then func is guaranteed to be called unless it is
579 explicitly canceled.
580
581 @raise TypeError: if B{func} is not callable.
582 @raise SystemError: if could not generate thumbnail, probably
583 no L{file_set()}.
584
585 @see: L{cancel()}, L{clear()}, L{exists()}
586 """
587 if not callable(func):
588 raise TypeError("func must be callable")
589
291 targs = (self, func, args, kargs) 590 targs = (self, func, args, kargs)
292 python.Py_INCREF(targs)
293 r = ethumb_client_generate(self.obj, _generated_cb, <void*>targs, 591 r = ethumb_client_generate(self.obj, _generated_cb, <void*>targs,
294 _generated_cb_free_data) 592 _generated_cb_free_data)
295 return r 593 if r >= 0:
594 python.Py_INCREF(targs)
595 return r
596 else:
597 raise SystemError("could not generate thumbnail. "
598 "Did you set the file?")
296 599
297 def cancel(self, int id): 600 def cancel(self, int id):
601 """Cancel thumbnail request.
602
603 Calling this function aborts thumbnail generation and B{func}
604 given to L{generate()} will not be called!
605
606 @parm: B{id} identifier returned by L{generate()}
607 """
298 ethumb_client_queue_remove(self.obj, id, NULL, NULL) 608 ethumb_client_queue_remove(self.obj, id, NULL, NULL)
299 609
300 def clear(self): 610 def clear(self):
301 ethumb_client_queue_clear(self.obj) 611 """Clear request queue.
302 612
303 def __dealloc__(self): 613 This will abort all existing requests, no B{func} given to
304 ethumb_client_disconnect(self.obj) 614 L{generate()} will be called.
615
616 Same as calling L{cancel()} in all exising requests.
617 """
618 ethumb_client_queue_clear(self.obj)
305 619
306init() 620init()
diff --git a/examples/01-simple.py b/examples/01-simple.py
new file mode 100755
index 0000000..f039789
--- /dev/null
+++ b/examples/01-simple.py
@@ -0,0 +1,49 @@
1#!/usr/bin/env python
2
3import sys
4import os
5import ethumb.client
6import ecore
7
8if len(sys.argv) < 2:
9 raise SystemExit("missing file names.")
10
11def pop_existent(client, files):
12 while files:
13 f = files.pop()
14 client.file_set(f)
15 print client
16 if not client.exists():
17 return f
18 tf, tk = client.thumb_path
19 print "%s already thumbnailed %s, %s" % (f, tf, tk)
20 return None
21
22def request_next(client, files):
23 if pop_existent(client, files):
24 id = client.generate(generated_cb, files, client)
25 print "generating id=%d" % id
26 else:
27 print "nothing left to generate."
28 ecore.main_loop_quit()
29
30def generated_cb(id, file, key, tpath, tkey, success, files, client):
31 if success:
32 print "id=%d (%s, %s) successfully generated %s, %s" % \
33 (id, file, key, tpath, tkey)
34 else:
35 print "id=%d (%s, %s) failed to generate" % (id, file, key)
36
37 request_next(client, files)
38
39
40def connected_cb(client, success, files):
41 if not success:
42 print "could not connect to server."
43 ecore.main_loop_quit()
44 return
45 request_next(client, files)
46
47c = ethumb.client.Client(connected_cb, sys.argv[1:])
48ecore.main_loop_begin()
49del c
diff --git a/include/ethumb/client.pxd b/include/ethumb/client.pxd
index d102f20..a358087 100644
--- a/include/ethumb/client.pxd
+++ b/include/ethumb/client.pxd
@@ -28,6 +28,7 @@ cdef extern from "Ethumb_Client.h":
28 28
29 Ethumb_Client *ethumb_client_connect(connect_callback_t cb, void *data, void (*free_data)(void *)) 29 Ethumb_Client *ethumb_client_connect(connect_callback_t cb, void *data, void (*free_data)(void *))
30 void ethumb_client_disconnect(Ethumb_Client *client) 30 void ethumb_client_disconnect(Ethumb_Client *client)
31 void ethumb_client_on_server_die_callback_set(Ethumb_Client *client, void (*on_server_die_cb)(Ethumb_Client *client, void *data), void *data)
31 32
32 void ethumb_client_fdo_set(Ethumb_Client *client, int s) 33 void ethumb_client_fdo_set(Ethumb_Client *client, int s)
33 34
@@ -68,3 +69,5 @@ cdef extern from "Ethumb_Client.h":
68 69
69cdef class Client: 70cdef class Client:
70 cdef Ethumb_Client *obj 71 cdef Ethumb_Client *obj
72 cdef object _on_connect_callback
73 cdef object _on_server_die_callback