[access] call a callback function with information
[framework/uifw/elementary.git] / src / lib / elm_thumb.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_thumb.h"
4
5 EAPI const char ELM_THUMB_SMART_NAME[] = "elm_thumb";
6
7 static const char SIG_CLICKED[] = "clicked";
8 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
9 static const char SIG_GENERATE_ERROR[] = "generate,error";
10 static const char SIG_GENERATE_START[] = "generate,start";
11 static const char SIG_GENERATE_STOP[] = "generate,stop";
12 static const char SIG_LOAD_ERROR[] = "load,error";
13 static const char SIG_PRESS[] = "press";
14 static const Evas_Smart_Cb_Description _smart_callbacks[] =
15 {
16    {SIG_CLICKED, ""},
17    {SIG_CLICKED_DOUBLE, ""},
18    {SIG_GENERATE_ERROR, ""},
19    {SIG_GENERATE_START, ""},
20    {SIG_GENERATE_STOP, ""},
21    {SIG_LOAD_ERROR, ""},
22    {SIG_PRESS, ""},
23    {NULL, NULL}
24 };
25
26 #define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start"
27 #define EDJE_SIGNAL_GENERATE_STOP  "elm,thumb,generate,stop"
28 #define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error"
29 #define EDJE_SIGNAL_LOAD_ERROR     "elm,thumb,load,error"
30 #define EDJE_SIGNAL_PULSE_START    "elm,state,pulse,start"
31 #define EDJE_SIGNAL_PULSE_STOP     "elm,state,pulse,stop"
32
33 static struct _Ethumb_Client *_elm_ethumb_client = NULL;
34 static Eina_Bool _elm_ethumb_connected = EINA_FALSE;
35
36 #ifdef HAVE_ELEMENTARY_ETHUMB
37 static Eina_List *retry = NULL;
38 static int pending_request = 0;
39 #endif
40
41 EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
42
43 EVAS_SMART_SUBCLASS_NEW
44   (ELM_THUMB_SMART_NAME, _elm_thumb, Elm_Thumb_Smart_Class,
45   Elm_Widget_Smart_Class, elm_widget_smart_class_get, _smart_callbacks);
46
47 #ifdef HAVE_ELEMENTARY_ETHUMB
48 static void
49 _mouse_down_cb(void *data,
50                Evas *e __UNUSED__,
51                Evas_Object *obj,
52                void *event_info)
53 {
54    Elm_Thumb_Smart_Data *sd = data;
55    Evas_Event_Mouse_Down *ev = event_info;
56
57    if (ev->button != 1)
58      return;
59    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
60      sd->on_hold = EINA_TRUE;
61    else
62      sd->on_hold = EINA_FALSE;
63    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
64      evas_object_smart_callback_call(obj, SIG_CLICKED_DOUBLE, NULL);
65    else
66      evas_object_smart_callback_call(obj, SIG_PRESS, NULL);
67 }
68
69 static void
70 _mouse_up_cb(void *data,
71              Evas *e __UNUSED__,
72              Evas_Object *obj,
73              void *event_info)
74 {
75    Elm_Thumb_Smart_Data *sd = data;
76    Evas_Event_Mouse_Up *ev = event_info;
77
78    if (ev->button != 1)
79      return;
80    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
81      sd->on_hold = EINA_TRUE;
82    else
83      sd->on_hold = EINA_FALSE;
84    if (!sd->on_hold)
85      evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
86
87    sd->on_hold = EINA_FALSE;
88 }
89
90 static void
91 _thumb_ready_inform(Elm_Thumb_Smart_Data *sd,
92                     const char *thumb_path,
93                     const char *thumb_key)
94 {
95    Evas_Coord mw, mh;
96    Evas_Coord aw, ah;
97
98    evas_object_image_size_get(sd->view, &aw, &ah);
99    evas_object_size_hint_aspect_set
100      (sd->view, EVAS_ASPECT_CONTROL_BOTH, aw, ah);
101    elm_layout_content_set
102      (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->view);
103    edje_object_size_min_get(ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh);
104    edje_object_size_min_restricted_calc
105      (ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh, mw, mh);
106    evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->obj, mw, mh);
107    eina_stringshare_replace(&(sd->thumb.file), thumb_path);
108    eina_stringshare_replace(&(sd->thumb.key), thumb_key);
109    elm_layout_signal_emit
110      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_PULSE_STOP, "elm");
111    elm_layout_signal_emit
112      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_GENERATE_STOP, "elm");
113    evas_object_smart_callback_call
114      (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_STOP, NULL);
115 }
116
117 static void
118 _on_thumb_preloaded(void *data,
119                     Evas *e __UNUSED__,
120                     Evas_Object *obj __UNUSED__,
121                     void *event_info __UNUSED__)
122 {
123    Elm_Thumb_Smart_Data *sd = data;
124    const char *thumb_path;
125    const char *thumb_key;
126
127    evas_object_image_file_get(sd->view, &thumb_path, &thumb_key);
128
129    _thumb_ready_inform(sd, thumb_path, thumb_key);
130 }
131
132 /* As we do use stat to check if a thumbnail is available, it's
133  * possible that we end up accessing it before the file is completly
134  * written on disk. By retrying each time a thumbnail is finished we
135  * should be fine or not.
136  */
137 static Eina_Bool
138 _thumb_retry(Elm_Thumb_Smart_Data *sd)
139 {
140    int r;
141
142    if ((sd->is_video) && (sd->thumb.format == ETHUMB_THUMB_EET))
143      {
144         edje_object_file_set(sd->view, NULL, NULL);
145         if (!edje_object_file_set
146               (sd->view, sd->thumb.thumb_path, "movie/thumb"))
147           {
148              if (pending_request == 0)
149                ERR("could not set file=%s key=%s for %s",
150                    sd->thumb.thumb_path,
151                    sd->thumb.thumb_key,
152                    sd->file);
153              goto view_err;
154           }
155         /* FIXME: Do we want to reload a thumbnail when the file
156            changes? I think not at the moment, as this may increase
157            the presure on the system a lot when using it in a file
158            browser */
159      }
160    else
161      {
162         evas_object_image_file_set(sd->view, NULL, NULL);
163         evas_object_image_file_set
164           (sd->view, sd->thumb.thumb_path, sd->thumb.thumb_key);
165         r = evas_object_image_load_error_get(sd->view);
166         if (r != EVAS_LOAD_ERROR_NONE)
167           {
168              if (pending_request == 0)
169                ERR("%s: %s", sd->thumb.thumb_path, evas_load_error_str(r));
170              goto view_err;
171           }
172
173         evas_object_event_callback_add
174           (sd->view, EVAS_CALLBACK_IMAGE_PRELOADED, _on_thumb_preloaded, sd);
175         evas_object_image_preload(sd->view, EINA_TRUE);
176
177         return EINA_TRUE;
178      }
179
180    _thumb_ready_inform(sd, sd->thumb.thumb_path, sd->thumb.thumb_key);
181
182    eina_stringshare_del(sd->thumb.thumb_path);
183    sd->thumb.thumb_path = NULL;
184
185    eina_stringshare_del(sd->thumb.thumb_key);
186    sd->thumb.thumb_key = NULL;
187
188    return EINA_TRUE;
189
190 view_err:
191    return EINA_FALSE;
192 }
193
194 static void
195 _thumb_finish(Elm_Thumb_Smart_Data *sd,
196               const char *thumb_path,
197               const char *thumb_key)
198 {
199    Eina_List *l, *ll;
200    Evas *evas;
201    int r;
202
203    evas = evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj);
204    if ((sd->view) && (sd->is_video ^ sd->was_video))
205      {
206         evas_object_del(sd->view);
207         sd->view = NULL;
208      }
209    sd->was_video = sd->is_video;
210
211    if ((sd->is_video) &&
212        (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
213      {
214         if (!sd->view)
215           {
216              sd->view = edje_object_add(evas);
217              if (!sd->view)
218                {
219                   ERR("could not create edje object");
220                   goto err;
221                }
222           }
223
224         if (!edje_object_file_set(sd->view, thumb_path, thumb_key))
225           {
226              sd->thumb.thumb_path = eina_stringshare_ref(thumb_path);
227              sd->thumb.thumb_key = eina_stringshare_ref(thumb_key);
228              sd->thumb.format = ethumb_client_format_get(_elm_ethumb_client);
229              sd->thumb.retry = EINA_TRUE;
230
231              retry = eina_list_append(retry, sd);
232              return;
233           }
234      }
235    else
236      {
237         if (!sd->view)
238           {
239              sd->view = evas_object_image_filled_add(evas);
240              if (!sd->view)
241                {
242                   ERR("could not create image object");
243                   goto err;
244                }
245              evas_object_event_callback_add
246                (sd->view, EVAS_CALLBACK_IMAGE_PRELOADED, _on_thumb_preloaded,
247                sd);
248              evas_object_hide(sd->view);
249           }
250
251         evas_object_image_file_set(sd->view, thumb_path, thumb_key);
252         r = evas_object_image_load_error_get(sd->view);
253         if (r != EVAS_LOAD_ERROR_NONE)
254           {
255              WRN("%s: %s", thumb_path, evas_load_error_str(r));
256              sd->thumb.thumb_path = eina_stringshare_ref(thumb_path);
257              sd->thumb.thumb_key = eina_stringshare_ref(thumb_key);
258              sd->thumb.format = ethumb_client_format_get(_elm_ethumb_client);
259              sd->thumb.retry = EINA_TRUE;
260
261              retry = eina_list_append(retry, sd);
262              return;
263           }
264
265         evas_object_image_preload(sd->view, EINA_FALSE);
266         return;
267      }
268
269    _thumb_ready_inform(sd, thumb_path, thumb_key);
270
271    EINA_LIST_FOREACH_SAFE(retry, l, ll, sd)
272      {
273         if (_thumb_retry(sd))
274           retry = eina_list_remove_list(retry, l);
275      }
276
277    if (pending_request == 0)
278      EINA_LIST_FREE (retry, sd)
279        {
280           eina_stringshare_del(sd->thumb.thumb_path);
281           sd->thumb.thumb_path = NULL;
282
283           eina_stringshare_del(sd->thumb.thumb_key);
284           sd->thumb.thumb_key = NULL;
285
286           evas_object_del(sd->view);
287           sd->view = NULL;
288
289           elm_layout_signal_emit
290             (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_LOAD_ERROR, "elm");
291           evas_object_smart_callback_call
292             (ELM_WIDGET_DATA(sd)->obj, SIG_LOAD_ERROR, NULL);
293        }
294
295    return;
296
297 err:
298    elm_layout_signal_emit
299      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_LOAD_ERROR, "elm");
300    evas_object_smart_callback_call
301      (ELM_WIDGET_DATA(sd)->obj, SIG_LOAD_ERROR, NULL);
302 }
303
304 static void
305 _on_ethumb_thumb_done(Ethumb_Client *client __UNUSED__,
306                       const char *thumb_path,
307                       const char *thumb_key,
308                       void *data)
309 {
310    Elm_Thumb_Smart_Data *sd = data;
311
312    if (EINA_UNLIKELY(!sd->thumb.request))
313      {
314         ERR("Something odd happened with a thumbnail request");
315         return;
316      }
317
318    pending_request--;
319    sd->thumb.request = NULL;
320
321    _thumb_finish(sd, thumb_path, thumb_key);
322 }
323
324 static void
325 _on_ethumb_thumb_error(Ethumb_Client *client __UNUSED__,
326                        void *data)
327 {
328    Elm_Thumb_Smart_Data *sd = data;
329
330    if (EINA_UNLIKELY(!sd->thumb.request))
331      {
332         ERR("Something odd happened with a thumbnail request");
333         return;
334      }
335
336    pending_request--;
337    sd->thumb.request = NULL;
338
339    ERR("could not generate thumbnail for %s (key: %s)",
340        sd->thumb.file, sd->thumb.key ? sd->thumb.key : "");
341
342    elm_layout_signal_emit
343      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_GENERATE_ERROR, "elm");
344    evas_object_smart_callback_call
345      (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_ERROR, NULL);
346 }
347
348 static void
349 _thumb_start(Elm_Thumb_Smart_Data *sd)
350 {
351    if (sd->thumb.request)
352      {
353         ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
354         sd->thumb.request = NULL;
355      }
356    if (sd->thumb.retry)
357      {
358         retry = eina_list_remove(retry, sd);
359         sd->thumb.retry = EINA_FALSE;
360      }
361
362    if (!sd->file) return;
363
364    elm_layout_signal_emit
365      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_PULSE_START, "elm");
366    elm_layout_signal_emit
367      (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_GENERATE_START, "elm");
368    evas_object_smart_callback_call
369      (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_START, NULL);
370
371    pending_request++;
372    ethumb_client_file_set(_elm_ethumb_client, sd->file, sd->key);
373    sd->thumb.request = ethumb_client_thumb_async_get
374        (_elm_ethumb_client, _on_ethumb_thumb_done, _on_ethumb_thumb_error, sd);
375 }
376
377 static Eina_Bool
378 _thumbnailing_available_cb(void *data,
379                            int type __UNUSED__,
380                            void *ev __UNUSED__)
381 {
382    _thumb_start(data);
383
384    return ECORE_CALLBACK_RENEW;
385 }
386
387 static void
388 _thumb_show(Elm_Thumb_Smart_Data *sd)
389 {
390    evas_object_show(ELM_WIDGET_DATA(sd)->resize_obj);
391
392    if (elm_thumb_ethumb_client_connected_get())
393      {
394         _thumb_start(sd);
395         return;
396      }
397
398    if (!sd->eeh)
399      sd->eeh = ecore_event_handler_add
400          (ELM_ECORE_EVENT_ETHUMB_CONNECT, _thumbnailing_available_cb, sd);
401 }
402
403 #endif
404
405 static void
406 _elm_thumb_smart_show(Evas_Object *obj)
407 {
408    ELM_THUMB_DATA_GET(obj, sd);
409
410    ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.show(obj);
411
412 #ifdef ELM_ETHUMB
413    _thumb_show(sd);
414 #else
415    (void)sd;
416 #endif
417 }
418
419 static void
420 _elm_thumb_smart_hide(Evas_Object *obj)
421 {
422    ELM_THUMB_DATA_GET(obj, sd);
423
424    ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.hide(obj);
425
426    evas_object_hide(ELM_WIDGET_DATA(sd)->resize_obj);
427
428 #ifdef ELM_ETHUMB
429    if (sd->thumb.request)
430      {
431         ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
432         sd->thumb.request = NULL;
433
434         elm_layout_signal_emit
435           (ELM_WIDGET_DATA(sd)->resize_obj, EDJE_SIGNAL_GENERATE_STOP, "elm");
436         evas_object_smart_callback_call
437           (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_STOP, NULL);
438      }
439
440    if (sd->thumb.retry)
441      {
442         retry = eina_list_remove(retry, sd);
443         sd->thumb.retry = EINA_FALSE;
444      }
445
446    if (sd->eeh)
447      {
448         ecore_event_handler_del(sd->eeh);
449         sd->eeh = NULL;
450      }
451 #endif
452 }
453
454 #ifdef ELM_ETHUMB
455 static int _elm_need_ethumb = 0;
456 static void _on_die_cb(void *, Ethumb_Client *);
457
458 static void
459 _connect_cb(void *data __UNUSED__,
460             Ethumb_Client *c,
461             Eina_Bool success)
462 {
463    if (success)
464      {
465         ethumb_client_on_server_die_callback_set(c, _on_die_cb, NULL, NULL);
466         _elm_ethumb_connected = EINA_TRUE;
467         ecore_event_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, NULL, NULL, NULL);
468      }
469    else
470      _elm_ethumb_client = NULL;
471 }
472
473 static void
474 _on_die_cb(void *data __UNUSED__,
475            Ethumb_Client *c __UNUSED__)
476 {
477    ethumb_client_disconnect(_elm_ethumb_client);
478
479    _elm_ethumb_client = NULL;
480    _elm_ethumb_connected = EINA_FALSE;
481    _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
482 }
483
484 #endif
485
486 void
487 _elm_unneed_ethumb(void)
488 {
489 #ifdef ELM_ETHUMB
490    if (--_elm_need_ethumb) return;
491
492    ethumb_client_disconnect(_elm_ethumb_client);
493    _elm_ethumb_client = NULL;
494    ethumb_client_shutdown();
495    ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
496 #endif
497 }
498
499 static Eina_Bool
500 _elm_thumb_dnd_cb(void *data __UNUSED__,
501                   Evas_Object *o,
502                   Elm_Selection_Data *drop)
503 {
504    if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE;
505    elm_thumb_file_set(o, drop->data, NULL);
506    return EINA_TRUE;
507 }
508
509 EAPI Eina_Bool
510 elm_need_ethumb(void)
511 {
512 #ifdef ELM_ETHUMB
513    if (_elm_need_ethumb++) return EINA_TRUE;
514
515    ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new();
516    ethumb_client_init();
517    _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
518
519    return EINA_TRUE;
520 #else
521    return EINA_FALSE;
522 #endif
523 }
524
525 static void
526 _elm_thumb_smart_add(Evas_Object *obj)
527 {
528    EVAS_SMART_DATA_ALLOC(obj, Elm_Thumb_Smart_Data);
529
530    ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.add(obj);
531
532    elm_widget_resize_object_set(obj, elm_layout_add(obj));
533
534    elm_layout_theme_set
535      (ELM_WIDGET_DATA(priv)->resize_obj, "thumb", "base",
536      elm_widget_style_get(obj));
537
538    priv->view = NULL;
539    priv->file = NULL;
540    priv->key = NULL;
541    priv->eeh = NULL;
542    priv->on_hold = EINA_FALSE;
543    priv->is_video = EINA_FALSE;
544    priv->was_video = EINA_FALSE;
545
546 #ifdef HAVE_ELEMENTARY_ETHUMB
547    priv->thumb.thumb_path = NULL;
548    priv->thumb.thumb_key = NULL;
549    priv->thumb.request = NULL;
550    evas_object_event_callback_add
551      (obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, priv);
552    evas_object_event_callback_add
553      (obj, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, priv);
554 #endif
555
556    elm_widget_can_focus_set(obj, EINA_FALSE);
557 }
558
559 static void
560 _elm_thumb_smart_del(Evas_Object *obj)
561 {
562    ELM_THUMB_DATA_GET(obj, sd);
563
564 #ifdef HAVE_ELEMENTARY_ETHUMB
565    if (sd->thumb.request)
566      {
567         ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
568         sd->thumb.request = NULL;
569      }
570    if (sd->thumb.retry)
571      {
572         retry = eina_list_remove(retry, sd);
573         sd->thumb.retry = EINA_FALSE;
574      }
575
576    eina_stringshare_del(sd->thumb.thumb_path);
577    eina_stringshare_del(sd->thumb.thumb_key);
578 #endif
579
580    eina_stringshare_del(sd->file);
581    eina_stringshare_del(sd->key);
582
583    if (sd->eeh) ecore_event_handler_del(sd->eeh);
584
585    ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.del(obj);
586 }
587
588 static void
589 _elm_thumb_smart_set_user(Elm_Thumb_Smart_Class *sc)
590 {
591    ELM_WIDGET_CLASS(sc)->base.add = _elm_thumb_smart_add;
592    ELM_WIDGET_CLASS(sc)->base.del = _elm_thumb_smart_del;
593
594    ELM_WIDGET_CLASS(sc)->base.show = _elm_thumb_smart_show;
595    ELM_WIDGET_CLASS(sc)->base.hide = _elm_thumb_smart_hide;
596 }
597
598 EAPI const Elm_Thumb_Smart_Class *
599 elm_thumb_smart_class_get(void)
600 {
601    static Elm_Thumb_Smart_Class _sc =
602      ELM_THUMB_SMART_CLASS_INIT_NAME_VERSION(ELM_THUMB_SMART_NAME);
603    static const Elm_Thumb_Smart_Class *class = NULL;
604    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
605
606    if (class) return class;
607
608    _elm_thumb_smart_set(&_sc);
609    esc->callbacks = _smart_callbacks;
610    class = &_sc;
611
612    return class;
613 }
614
615 EAPI Evas_Object *
616 elm_thumb_add(Evas_Object *parent)
617 {
618    Evas_Object *obj;
619
620    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
621
622    obj = elm_widget_add(_elm_thumb_smart_class_new(), parent);
623    if (!obj) return NULL;
624
625    if (!elm_widget_sub_object_add(parent, obj))
626      ERR("could not add %p as sub object of %p", obj, parent);
627
628    return obj;
629 }
630
631 EAPI void
632 elm_thumb_reload(Evas_Object *obj)
633 {
634    ELM_THUMB_CHECK(obj);
635    ELM_THUMB_DATA_GET(obj, sd);
636
637    eina_stringshare_replace(&(sd->thumb.file), NULL);
638    eina_stringshare_replace(&(sd->thumb.key), NULL);
639
640 #ifdef HAVE_ELEMENTARY_ETHUMB
641    if (evas_object_visible_get(obj))
642      _thumb_show(sd);
643 #endif
644 }
645
646 EAPI void
647 elm_thumb_file_set(Evas_Object *obj,
648                    const char *file,
649                    const char *key)
650 {
651    Eina_Bool file_replaced, key_replaced;
652
653    ELM_THUMB_CHECK(obj);
654    ELM_THUMB_DATA_GET(obj, sd);
655
656    file_replaced = eina_stringshare_replace(&(sd->file), file);
657    key_replaced = eina_stringshare_replace(&(sd->key), key);
658
659    if (file_replaced)
660      {
661         int prefix_size;
662         const char **ext, *ptr;
663         static const char *extensions[] =
664         {
665            ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
666         };
667
668         prefix_size = eina_stringshare_strlen(sd->file) - 4;
669         if (prefix_size >= 0)
670           {
671              ptr = sd->file + prefix_size;
672              sd->is_video = EINA_FALSE;
673              for (ext = extensions; *ext; ext++)
674                if (!strcasecmp(ptr, *ext))
675                  {
676                     sd->is_video = EINA_TRUE;
677                     break;
678                  }
679           }
680      }
681
682    eina_stringshare_replace(&(sd->thumb.file), NULL);
683    eina_stringshare_replace(&(sd->thumb.key), NULL);
684
685 #ifdef HAVE_ELEMENTARY_ETHUMB
686    if (((file_replaced) || (key_replaced)) && (evas_object_visible_get(obj)))
687      _thumb_show(sd);
688 #else
689    (void)key_replaced;
690 #endif
691 }
692
693 EAPI void
694 elm_thumb_file_get(const Evas_Object *obj,
695                    const char **file,
696                    const char **key)
697 {
698    ELM_THUMB_CHECK(obj);
699    ELM_THUMB_DATA_GET(obj, sd);
700
701    if (file)
702      *file = sd->file;
703    if (key)
704      *key = sd->key;
705 }
706
707 EAPI void
708 elm_thumb_path_get(const Evas_Object *obj,
709                    const char **file,
710                    const char **key)
711 {
712    ELM_THUMB_CHECK(obj);
713    ELM_THUMB_DATA_GET(obj, sd);
714
715    if (file)
716      *file = sd->thumb.file;
717    if (key)
718      *key = sd->thumb.key;
719 }
720
721 EAPI void
722 elm_thumb_animate_set(Evas_Object *obj,
723                       Elm_Thumb_Animation_Setting setting)
724 {
725    ELM_THUMB_CHECK(obj);
726    ELM_THUMB_DATA_GET(obj, sd);
727
728    EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST);
729
730    sd->anim_setting = setting;
731    if (setting == ELM_THUMB_ANIMATION_LOOP)
732      edje_object_signal_emit(sd->view, "animate_loop", "");
733    else if (setting == ELM_THUMB_ANIMATION_START)
734      edje_object_signal_emit(sd->view, "animate", "");
735    else if (setting == ELM_THUMB_ANIMATION_STOP)
736      edje_object_signal_emit(sd->view, "animate_stop", "");
737 }
738
739 EAPI Elm_Thumb_Animation_Setting
740 elm_thumb_animate_get(const Evas_Object *obj)
741 {
742    ELM_THUMB_CHECK(obj) ELM_THUMB_ANIMATION_LAST;
743    ELM_THUMB_DATA_GET(obj, sd);
744
745    return sd->anim_setting;
746 }
747
748 EAPI void *
749 elm_thumb_ethumb_client_get(void)
750 {
751    return _elm_ethumb_client;
752 }
753
754 EAPI Eina_Bool
755 elm_thumb_ethumb_client_connected_get(void)
756 {
757    return _elm_ethumb_connected;
758 }
759
760 EAPI Eina_Bool
761 elm_thumb_editable_set(Evas_Object *obj,
762                        Eina_Bool edit)
763 {
764    ELM_THUMB_CHECK(obj) EINA_FALSE;
765    ELM_THUMB_DATA_GET(obj, sd);
766
767    edit = !!edit;
768    if (sd->edit == edit) return EINA_TRUE;
769
770    sd->edit = edit;
771    if (sd->edit)
772      elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE, _elm_thumb_dnd_cb, obj);
773    else
774      elm_drop_target_del(obj);
775
776    return EINA_TRUE;
777 }
778
779 EAPI Eina_Bool
780 elm_thumb_editable_get(const Evas_Object *obj)
781 {
782    ELM_THUMB_CHECK(obj) EINA_FALSE;
783    ELM_THUMB_DATA_GET(obj, sd);
784
785    return sd->edit;
786 }