upload tizen1.0 source
[framework/uifw/e17.git] / src / bin / e_thumb.c
1 #include "e.h"
2
3 typedef struct _E_Thumb E_Thumb;
4
5 struct _E_Thumb
6 {
7    int objid;
8    int w, h;
9    const char *file;
10    const char *key;
11    char *sort_id;
12    unsigned char queued : 1;
13    unsigned char busy : 1;
14    unsigned char done : 1;
15 };
16
17 /* local subsystem functions */
18 static void _e_thumb_gen_begin(int objid, const char *file, const char *key, int w, int h);
19 static void _e_thumb_gen_end(int objid);
20 static void _e_thumb_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
21 static void _e_thumb_hash_add(int objid, Evas_Object *obj);
22 static void _e_thumb_hash_del(int objid);
23 static Evas_Object *_e_thumb_hash_find(int objid);
24 static void _e_thumb_thumbnailers_kill(void);
25 static void _e_thumb_thumbnailers_kill_cancel(void);
26 static Eina_Bool _e_thumb_cb_kill(void *data);
27 static Eina_Bool _e_thumb_cb_exe_event_del(void *data, int type, void *event);
28
29 /* local subsystem globals */
30 static Eina_List *_thumbnailers = NULL;
31 static Eina_List *_thumbnailers_exe = NULL;
32 static Eina_List *_thumb_queue = NULL;
33 static int _objid = 0;
34 static Eina_Hash *_thumbs = NULL;
35 static int _pending = 0;
36 static int _num_thumbnailers = 1;
37 static Ecore_Event_Handler *_exe_del_handler = NULL;
38 static Ecore_Timer *_kill_timer = NULL;
39
40 /* externally accessible functions */
41 EINTERN int
42 e_thumb_init(void)
43 {
44    _exe_del_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
45                                               _e_thumb_cb_exe_event_del,
46                                               NULL);
47    _thumbs = eina_hash_string_superfast_new(NULL);
48    return 1;
49 }
50
51 EINTERN int
52 e_thumb_shutdown(void)
53 {
54    _e_thumb_thumbnailers_kill_cancel();
55    _e_thumb_cb_kill(NULL);
56    if (_exe_del_handler) ecore_event_handler_del(_exe_del_handler);
57    _exe_del_handler = NULL;
58    _thumbnailers = eina_list_free(_thumbnailers);
59    E_FREE_LIST(_thumbnailers_exe, ecore_exe_free);
60    _thumb_queue = eina_list_free(_thumb_queue);
61    _objid = 0;
62    eina_hash_free(_thumbs);
63    _thumbs = NULL;
64    _pending = 0;
65    return 1;
66 }
67
68 static void
69 _thumb_preloaded(void *data, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
70 {
71    evas_object_smart_callback_call(data, "e_thumb_gen", NULL);
72 }
73
74 EAPI Evas_Object *
75 e_thumb_icon_add(Evas *evas)
76 {
77    Evas_Object *obj;
78    E_Thumb *eth;
79
80    obj = e_icon_add(evas);
81    evas_object_smart_callback_add(obj, "preloaded", _thumb_preloaded, obj);
82    _objid++;
83    eth = E_NEW(E_Thumb, 1);
84    eth->objid = _objid;
85    eth->w = 64;
86    eth->h = 64;
87    evas_object_data_set(obj, "e_thumbdata", eth);
88    evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
89                                   _e_thumb_del_hook, NULL);
90    _e_thumb_hash_add(eth->objid, obj);
91    return obj;
92 }
93
94 EAPI void
95 e_thumb_icon_file_set(Evas_Object *obj, const char *file, const char *key)
96 {
97    E_Thumb *eth;
98
99    eth = evas_object_data_get(obj, "e_thumbdata");
100    if (!eth) return;
101    if (eth->file) eina_stringshare_del(eth->file);
102    eth->file = NULL;
103    if (eth->key) eina_stringshare_del(eth->key);
104    eth->key = NULL;
105    if (eth->sort_id) free(eth->sort_id);
106    eth->sort_id = NULL;
107    if (file) eth->file = eina_stringshare_add(file);
108    if (key) eth->key = eina_stringshare_add(key);
109 }
110
111 EAPI void
112 e_thumb_icon_size_set(Evas_Object *obj, int w, int h)
113 {
114    E_Thumb *eth;
115
116    eth = evas_object_data_get(obj, "e_thumbdata");
117    if (!eth) return;
118    if ((w < 1) || (h <1)) return;
119    eth->w = w;
120    eth->h = h;
121 }
122
123 EAPI void
124 e_thumb_icon_begin(Evas_Object *obj)
125 {
126    E_Thumb *eth, *eth2;
127    char buf[4096];
128
129    eth = evas_object_data_get(obj, "e_thumbdata");
130    if (!eth) return;
131    if (eth->queued) return;
132    if (eth->busy) return;
133    if (eth->done) return;
134    if (!eth->file) return;
135    if (!_thumbnailers)
136      {
137         while ((int) eina_list_count(_thumbnailers_exe) < _num_thumbnailers)
138           {
139              Ecore_Exe *exe;
140
141              snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_thumb --nice=%d", e_prefix_lib_get(),
142                       e_config->thumb_nice);
143              exe = ecore_exe_run(buf, NULL);
144              _thumbnailers_exe = eina_list_append(_thumbnailers_exe, exe);
145           }
146         _thumb_queue = eina_list_append(_thumb_queue, eth);
147         eth->queued = 1;
148         return;
149      }
150    EINA_LIST_FREE(_thumb_queue, eth2)
151      {
152         eth2->queued = 0;
153         eth2->busy = 1;
154         _pending++;
155         if (_pending == 1) _e_thumb_thumbnailers_kill_cancel();
156         _e_thumb_gen_begin(eth2->objid, eth2->file, eth2->key, eth2->w, eth2->h);
157      }
158    eth->busy = 1;
159    _pending++;
160    if (_pending == 1) _e_thumb_thumbnailers_kill_cancel();
161    _e_thumb_gen_begin(eth->objid, eth->file, eth->key, eth->w, eth->h);
162 }
163
164 EAPI void
165 e_thumb_icon_end(Evas_Object *obj)
166 {
167    E_Thumb *eth;
168
169    eth = evas_object_data_get(obj, "e_thumbdata");
170    if (!eth) return;
171    if (eth->queued)
172      {
173         _thumb_queue = eina_list_remove(_thumb_queue, eth);
174         eth->queued = 0;
175      }
176    if (eth->busy)
177      {
178         _e_thumb_gen_end(eth->objid);
179         eth->busy = 0;
180         _pending--;
181         if (_pending == 0) _e_thumb_thumbnailers_kill();
182      }
183 }
184
185 EAPI void
186 e_thumb_icon_rethumb(Evas_Object *obj)
187 {
188    E_Thumb *eth;
189    eth = evas_object_data_get(obj, "e_thumbdata");
190    if (!eth) return;
191
192    if (eth->done) eth->done = 0;
193    else e_thumb_icon_end(obj);
194
195    e_thumb_icon_begin(obj);
196 }
197
198 #define A(v) (((v) >> 24) & 0xff)
199 #define R(v) (((v) >> 16) & 0xff)
200 #define G(v) (((v) >> 8 ) & 0xff)
201 #define B(v) (((v)      ) & 0xff)
202 #define PIX(p, x, y) p[((y) << 2) + (x)]
203 #define PIX2(p, x, y) p[((y) << 1) + (x)]
204
205 static void
206 _e_thumb_key_load(E_Thumb *eth, const char *icon)
207 {
208    Eet_File *ef;
209    int size = 0;
210    
211    ef = eet_open(icon, EET_FILE_MODE_READ);
212    if (!ef) return;
213    eth->sort_id = eet_read(ef, "/thumbnail/sort_id", &size);
214    if (eth->sort_id)
215      {
216         if (size > 0) eth->sort_id[size - 1] = 0;
217         else
218           {
219              free(eth->sort_id);
220              eth->sort_id = NULL;
221           }
222      }
223    eet_close(ef);
224 }
225
226 EAPI const char *
227 e_thumb_sort_id_get(Evas_Object *obj)
228 {
229    E_Thumb *eth;
230    eth = evas_object_data_get(obj, "e_thumbdata");
231    if (!eth) return "";
232    if (!eth->sort_id) return "";
233    return eth->sort_id;
234 }
235
236 EAPI void
237 e_thumb_client_data(Ecore_Ipc_Event_Client_Data *e)
238 {
239    int objid;
240    char *icon;
241    E_Thumb *eth;
242    Evas_Object *obj;
243
244    if (!eina_list_data_find(_thumbnailers, e->client))
245      _thumbnailers = eina_list_prepend(_thumbnailers, e->client);
246    if (e->minor == 2)
247      {
248         objid = e->ref;
249         icon = e->data;
250         if ((icon) && (e->size > 1) && (icon[e->size - 1] == 0))
251           {
252              obj = _e_thumb_hash_find(objid);
253              if (obj)
254                {
255                   eth = evas_object_data_get(obj, "e_thumbdata");
256                   if (eth)
257                     {
258                        eth->busy = 0;
259                        _pending--;
260                        eth->done = 1;
261                        if (_pending == 0) _e_thumb_thumbnailers_kill();
262                        if (ecore_file_exists(icon))
263                          {
264                             e_icon_preload_set(obj, 1);
265                             e_icon_file_key_set(obj, icon, "/thumbnail/data");
266                             _e_thumb_key_load(eth, icon);
267                          }
268
269                        evas_object_smart_callback_call(obj, "e_thumb_gen", NULL);
270                     }
271                }
272           }
273      }
274    if (e->minor == 1)
275      {
276         /* hello message */
277         EINA_LIST_FREE(_thumb_queue, eth)
278           {
279              eth->queued = 0;
280              eth->busy = 1;
281              _pending++;
282              if (_pending == 1) _e_thumb_thumbnailers_kill_cancel();
283              _e_thumb_gen_begin(eth->objid, eth->file, eth->key, eth->w, eth->h);
284           }
285      }
286 }
287
288 EAPI void
289 e_thumb_client_del(Ecore_Ipc_Event_Client_Del *e)
290 {
291    if (!eina_list_data_find(_thumbnailers, e->client)) return;
292    _thumbnailers = eina_list_remove(_thumbnailers, e->client);
293    if ((!_thumbs) && (!_thumbnailers)) _objid = 0;
294 }
295
296 /* local subsystem functions */
297 static void
298 _e_thumb_gen_begin(int objid, const char *file, const char *key, int w, int h)
299 {
300    char *buf;
301    int l1, l2;
302    Ecore_Ipc_Client *cli;
303
304    /* send thumb req */
305    l1 = strlen(file);
306    l2 = 0;
307    if (key) l2 = strlen(key);
308    buf = alloca(l1 + 1 + l2 + 1);
309    strcpy(buf, file);
310    if (key) strcpy(buf + l1 + 1, key);
311    else buf[l1 + 1] = 0;
312    cli = eina_list_data_get(_thumbnailers);
313    if (!cli) return;
314    _thumbnailers = eina_list_remove_list(_thumbnailers, _thumbnailers);
315    _thumbnailers = eina_list_append(_thumbnailers, cli);
316    ecore_ipc_client_send(cli, E_IPC_DOMAIN_THUMB, 1, objid, w, h, buf, l1 + 1 + l2 + 1);
317 }
318
319 static void
320 _e_thumb_gen_end(int objid)
321 {
322    Eina_List *l;
323    Ecore_Ipc_Client *cli;
324
325    /* send thumb cancel */
326    EINA_LIST_FOREACH(_thumbnailers, l, cli)
327      {
328         ecore_ipc_client_send(cli, E_IPC_DOMAIN_THUMB, 2, objid, 0, 0, NULL, 0);
329      }
330 }
331
332 static void
333 _e_thumb_del_hook(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
334 {
335    E_Thumb *eth;
336
337    eth = evas_object_data_get(obj, "e_thumbdata");
338    if (!eth) return;
339    evas_object_data_del(obj, "e_thumbdata");
340    _e_thumb_hash_del(eth->objid);
341    if (eth->busy)
342      {
343         _e_thumb_gen_end(eth->objid);
344         eth->busy = 0;
345         _pending--;
346         if (_pending == 0) _e_thumb_thumbnailers_kill();
347      }
348    if (eth->queued)
349      _thumb_queue = eina_list_remove(_thumb_queue, eth);
350    if (eth->file) eina_stringshare_del(eth->file);
351    if (eth->key) eina_stringshare_del(eth->key);
352    if (eth->sort_id) free(eth->sort_id);
353    free(eth);
354 }
355
356 static void
357 _e_thumb_hash_add(int objid, Evas_Object *obj)
358 {
359    char buf[32];
360
361    snprintf(buf, sizeof(buf), "%i", objid);
362    eina_hash_add(_thumbs, buf, obj);
363 }
364
365 static void
366 _e_thumb_hash_del(int objid)
367 {
368    char buf[32];
369
370    snprintf(buf, sizeof(buf), "%i", objid);
371    eina_hash_del(_thumbs, buf, NULL);
372    if ((!_thumbs) && (!_thumbnailers)) _objid = 0;
373 }
374
375 static Evas_Object *
376 _e_thumb_hash_find(int objid)
377 {
378    char buf[32];
379
380    snprintf(buf, sizeof(buf), "%i", objid);
381    return eina_hash_find(_thumbs, buf);
382 }
383
384 static void
385 _e_thumb_thumbnailers_kill(void)
386 {
387    if (_kill_timer) ecore_timer_del(_kill_timer);
388    _kill_timer = ecore_timer_add(1.0, _e_thumb_cb_kill, NULL);
389 }
390
391 static void
392 _e_thumb_thumbnailers_kill_cancel(void)
393 {
394    if (_kill_timer) ecore_timer_del(_kill_timer);
395    _kill_timer = NULL;
396 }
397
398 static Eina_Bool
399 _e_thumb_cb_kill(void *data __UNUSED__)
400 {
401    Eina_List *l;
402    Ecore_Exe *exe;
403
404    EINA_LIST_FOREACH(_thumbnailers_exe, l, exe)
405      ecore_exe_terminate(exe);
406    _kill_timer = NULL;
407    return ECORE_CALLBACK_DONE;
408 }
409
410 static Eina_Bool
411 _e_thumb_cb_exe_event_del(void *data __UNUSED__, int type __UNUSED__, void *event)
412 {
413    Ecore_Exe_Event_Del *ev;
414    Ecore_Exe *exe;
415    Eina_List *l;
416
417    ev = event;
418    EINA_LIST_FOREACH(_thumbnailers_exe, l, exe)
419      {
420         if (exe == ev->exe)
421           {
422              _thumbnailers_exe = eina_list_remove_list(_thumbnailers_exe, l);
423              break;
424           }
425      }
426    if ((!_thumbnailers_exe) && (_thumb_queue))
427      {
428         while ((int) eina_list_count(_thumbnailers_exe) < _num_thumbnailers)
429           {
430              Ecore_Exe *exe;
431              char buf[4096];
432
433              snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_thumb --nice=%d", e_prefix_lib_get(),
434                       e_config->thumb_nice);
435              exe = ecore_exe_run(buf, NULL);
436              _thumbnailers_exe = eina_list_append(_thumbnailers_exe, exe);
437           }
438      }
439    return ECORE_CALLBACK_PASS_ON;
440 }