1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6
7 #include <Elementary.h>
8
9 #include "elm_priv.h"
10 #include "elm_thumb_eo.h"
11 #include "elm_widget_thumb.h"
12
13 #define MY_CLASS_NAME "Elm_Thumb"
14 #define MY_CLASS_NAME_LEGACY "elm_thumb"
15
16 #define MY_CLASS ELM_THUMB_CLASS
17
18 static const char SIG_CLICKED[] = "clicked";
19 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
20 static const char SIG_GENERATE_ERROR[] = "generate,error";
21 static const char SIG_GENERATE_START[] = "generate,start";
22 static const char SIG_GENERATE_STOP[] = "generate,stop";
23 static const char SIG_LOAD_ERROR[] = "load,error";
24 static const char SIG_PRESS[] = "press";
25 static const Evas_Smart_Cb_Description _smart_callbacks[] =
26 {
27 {SIG_CLICKED, ""},
28 {SIG_CLICKED_DOUBLE, ""},
29 {SIG_GENERATE_ERROR, ""},
30 {SIG_GENERATE_START, ""},
31 {SIG_GENERATE_STOP, ""},
32 {SIG_LOAD_ERROR, ""},
33 {SIG_PRESS, ""},
34 {NULL, NULL}
35 };
36
37 #define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start"
38 #define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop"
39 #define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error"
40 #define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error"
41 #define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start"
42 #define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop"
43
44 static struct _Ethumb_Client *_elm_ethumb_client = NULL;
45 static Eina_Bool _elm_ethumb_connected = EINA_FALSE;
46
47 static Eina_List *retry = NULL;
48 static int pending_request = 0;
49
50 EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
51
52 static void
_mouse_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)53 _mouse_down_cb(void *data,
54 Evas *e EINA_UNUSED,
55 Evas_Object *obj,
56 void *event_info)
57 {
58 ELM_THUMB_DATA_GET(data, sd);
59 Evas_Event_Mouse_Down *ev = event_info;
60
61 if (ev->button != 1) return;
62 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
63 else sd->on_hold = EINA_FALSE;
64
65 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
66 evas_object_smart_callback_call(obj, "clicked", NULL);
67 else
68 efl_event_callback_legacy_call(obj, ELM_THUMB_EVENT_PRESS, NULL);
69 }
70
71 static void
_mouse_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)72 _mouse_up_cb(void *data,
73 Evas *e EINA_UNUSED,
74 Evas_Object *obj,
75 void *event_info)
76 {
77 ELM_THUMB_DATA_GET(data, sd);
78 Evas_Event_Mouse_Up *ev = event_info;
79
80 if (ev->button != 1) return;
81 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
82 else sd->on_hold = EINA_FALSE;
83
84 if (!sd->on_hold)
85 evas_object_smart_callback_call(obj, "clicked", NULL);
86
87 sd->on_hold = EINA_FALSE;
88 }
89
90 static void
_thumb_ready_inform(Elm_Thumb_Data * sd,const char * thumb_path,const char * thumb_key)91 _thumb_ready_inform(Elm_Thumb_Data *sd,
92 const char *thumb_path,
93 const char *thumb_key)
94 {
95 Evas_Coord mw, mh;
96 Evas_Coord aw, ah;
97 ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
98
99 if ((sd->is_video) && (sd->thumb.format == ETHUMB_THUMB_EET))
100 {
101 edje_object_size_min_get(sd->view, &mw, &mh);
102 edje_object_size_min_restricted_calc(sd->view, &mw, &mh, mw, mh);
103 evas_object_size_hint_min_set(sd->view, mw, mh);
104 }
105 else
106 {
107 evas_object_image_size_get(sd->view, &aw, &ah);
108 evas_object_size_hint_aspect_set(sd->view, EVAS_ASPECT_CONTROL_BOTH,
109 aw, ah);
110 }
111
112 edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->view);
113 eina_stringshare_replace(&(sd->thumb.file), thumb_path);
114 eina_stringshare_replace(&(sd->thumb.key), thumb_key);
115 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_PULSE_STOP, "elm");
116 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_GENERATE_STOP, "elm");
117 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_GENERATE_STOP, NULL);
118 }
119
120 static void
_on_thumb_preloaded(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)121 _on_thumb_preloaded(void *data,
122 Evas *e EINA_UNUSED,
123 Evas_Object *obj EINA_UNUSED,
124 void *event_info EINA_UNUSED)
125 {
126 ELM_THUMB_DATA_GET(data, sd);
127 const char *thumb_path;
128 const char *thumb_key;
129
130 evas_object_image_file_get(sd->view, &thumb_path, &thumb_key);
131
132 _thumb_ready_inform(sd, thumb_path, thumb_key);
133 }
134
135 /* As we do use stat to check if a thumbnail is available, it's
136 * possible that we end up accessing it before the file is completely
137 * written on disk. By retrying each time a thumbnail is finished we
138 * should be fine or not.
139 */
140 static Eina_Bool
_thumb_retry(Elm_Thumb_Data * sd)141 _thumb_retry(Elm_Thumb_Data *sd)
142 {
143 int r;
144
145 if ((sd->is_video) && (sd->thumb.format == ETHUMB_THUMB_EET))
146 {
147 edje_object_file_set(sd->view, NULL, NULL);
148 if (!edje_object_file_set
149 (sd->view, sd->thumb.thumb_path, "movie/thumb"))
150 {
151 if (pending_request == 0)
152 ERR("could not set file=%s key=%s for %s",
153 sd->thumb.thumb_path,
154 sd->thumb.thumb_key,
155 sd->file);
156 goto view_err;
157 }
158 /* FIXME: Do we want to reload a thumbnail when the file
159 changes? I think not at the moment, as this may increase
160 the presure on the system a lot when using it in a file
161 browser */
162 }
163 else
164 {
165 evas_object_image_file_set(sd->view, NULL, NULL);
166 evas_object_image_file_set
167 (sd->view, sd->thumb.thumb_path, sd->thumb.thumb_key);
168 r = evas_object_image_load_error_get(sd->view);
169 if (r != EVAS_LOAD_ERROR_NONE)
170 {
171 if (pending_request == 0)
172 ERR("%s: %s", sd->thumb.thumb_path, evas_load_error_str(r));
173 goto view_err;
174 }
175
176 evas_object_event_callback_add
177 (sd->view, EVAS_CALLBACK_IMAGE_PRELOADED, _on_thumb_preloaded, sd->obj);
178 evas_object_image_preload(sd->view, EINA_TRUE);
179
180 return EINA_TRUE;
181 }
182
183 _thumb_ready_inform(sd, sd->thumb.thumb_path, sd->thumb.thumb_key);
184
185 ELM_SAFE_FREE(sd->thumb.thumb_path, eina_stringshare_del);
186 ELM_SAFE_FREE(sd->thumb.thumb_key, eina_stringshare_del);
187
188 return EINA_TRUE;
189
190 view_err:
191 return EINA_FALSE;
192 }
193
194 static void
_thumb_finish(Elm_Thumb_Data * sd,const char * thumb_path,const char * thumb_key)195 _thumb_finish(Elm_Thumb_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 ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
203
204 evas = evas_object_evas_get(sd->obj);
205 if ((sd->view) && (sd->is_video ^ sd->was_video))
206 {
207 ELM_SAFE_FREE(sd->view, evas_object_del);
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 efl_data_ref(sd->obj, MY_CLASS);
233 return;
234 }
235 }
236 else
237 {
238 if (!sd->view)
239 {
240 sd->view = evas_object_image_filled_add(evas);
241 if (!sd->view)
242 {
243 ERR("could not create image object");
244 goto err;
245 }
246 evas_object_event_callback_add(sd->view, EVAS_CALLBACK_IMAGE_PRELOADED,
247 _on_thumb_preloaded, sd->obj);
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 efl_data_ref(sd->obj, MY_CLASS);
263 return;
264 }
265
266 evas_object_image_preload(sd->view, EINA_FALSE);
267 return;
268 }
269
270 _thumb_ready_inform(sd, thumb_path, thumb_key);
271
272 EINA_LIST_FOREACH_SAFE(retry, l, ll, sd)
273 {
274 if (_thumb_retry(sd))
275 {
276 retry = eina_list_remove_list(retry, l);
277 efl_data_unref(sd->obj, sd);
278 }
279
280 }
281
282 if (pending_request == 0)
283 EINA_LIST_FREE(retry, sd)
284 {
285 efl_data_unref(sd->obj, sd);
286 ELM_SAFE_FREE(sd->thumb.thumb_path, eina_stringshare_del);
287 ELM_SAFE_FREE(sd->thumb.thumb_key, eina_stringshare_del);
288 ELM_SAFE_FREE(sd->view, evas_object_del);
289
290 wd = efl_data_scope_get(sd->obj, EFL_UI_WIDGET_CLASS);
291 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_LOAD_ERROR, "elm");
292 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_LOAD_ERROR, NULL);
293 }
294
295 return;
296
297 err:
298 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_LOAD_ERROR, "elm");
299 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_LOAD_ERROR, NULL);
300 }
301
302 static void
_on_ethumb_thumb_done(Ethumb_Client * client EINA_UNUSED,const char * thumb_path,const char * thumb_key,void * data)303 _on_ethumb_thumb_done(Ethumb_Client *client EINA_UNUSED,
304 const char *thumb_path,
305 const char *thumb_key,
306 void *data)
307 {
308 ELM_THUMB_DATA_GET(data, sd);
309
310 if (EINA_UNLIKELY(!sd->thumb.request))
311 {
312 ERR("Something odd happened with a thumbnail request");
313 return;
314 }
315
316 pending_request--;
317 sd->thumb.request = NULL;
318
319 _thumb_finish(sd, thumb_path, thumb_key);
320 }
321
322 static void
_on_ethumb_thumb_error(Ethumb_Client * client EINA_UNUSED,void * data)323 _on_ethumb_thumb_error(Ethumb_Client *client EINA_UNUSED,
324 void *data)
325 {
326 ELM_THUMB_DATA_GET(data, sd);
327
328 if (EINA_UNLIKELY(!sd->thumb.request))
329 {
330 ERR("Something odd happened with a thumbnail request");
331 return;
332 }
333 evas_object_event_callback_del_full(sd->view, EVAS_CALLBACK_IMAGE_PRELOADED,
334 _on_thumb_preloaded, sd);
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_WIDGET_DATA_GET_OR_RETURN(data, wd);
343 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_GENERATE_ERROR, "elm");
344 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_PULSE_STOP, "elm");
345 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_GENERATE_ERROR, NULL);
346 }
347
348 static void
_thumb_start(Elm_Thumb_Data * sd)349 _thumb_start(Elm_Thumb_Data *sd)
350 {
351 if (sd->thumb.aspect)
352 ethumb_client_aspect_set(_elm_ethumb_client, sd->thumb.aspect);
353 if (sd->thumb.size)
354 ethumb_client_fdo_set(_elm_ethumb_client, sd->thumb.size);
355 if (sd->thumb.format)
356 ethumb_client_format_set(_elm_ethumb_client, sd->thumb.format);
357 if (sd->thumb.orient)
358 ethumb_client_orientation_set(_elm_ethumb_client, sd->thumb.orient);
359 if (sd->thumb.tw && sd->thumb.th)
360 ethumb_client_size_set(_elm_ethumb_client, sd->thumb.tw, sd->thumb.th);
361 if (!EINA_DBL_EQ(sd->thumb.cropx, 0) && !EINA_DBL_EQ(sd->thumb.cropy, 0))
362 ethumb_client_crop_align_set(_elm_ethumb_client, sd->thumb.cropx, sd->thumb.cropy);
363 if (sd->thumb.quality)
364 ethumb_client_quality_set(_elm_ethumb_client, sd->thumb.quality);
365 if (sd->thumb.compress)
366 ethumb_client_compress_set(_elm_ethumb_client, sd->thumb.compress);
367 if (sd->thumb.request)
368 {
369 ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
370 sd->thumb.request = NULL;
371 }
372 if (sd->thumb.retry)
373 {
374 retry = eina_list_remove(retry, sd);
375 efl_data_unref(sd->obj, sd);
376 sd->thumb.retry = EINA_FALSE;
377 }
378
379 if (!sd->file) return;
380
381 ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
382 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_PULSE_START, "elm");
383 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_GENERATE_START, "elm");
384 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_GENERATE_START, NULL);
385
386 pending_request++;
387 ethumb_client_file_set(_elm_ethumb_client, sd->file, sd->key);
388 sd->thumb.request = ethumb_client_thumb_async_get(_elm_ethumb_client,
389 _on_ethumb_thumb_done,
390 _on_ethumb_thumb_error,
391 sd->obj);
392 }
393
394 static Eina_Bool
_thumbnailing_available_cb(void * data,int type EINA_UNUSED,void * ev EINA_UNUSED)395 _thumbnailing_available_cb(void *data,
396 int type EINA_UNUSED,
397 void *ev EINA_UNUSED)
398 {
399 ELM_THUMB_DATA_GET(data, sd);
400 _thumb_start(sd);
401
402 return ECORE_CALLBACK_RENEW;
403 }
404
405 static Eina_Bool _elm_need_ethumb = EINA_FALSE;
406 static void _on_die_cb(void *, Ethumb_Client *);
407
408 static void
_connect_cb(void * data EINA_UNUSED,Ethumb_Client * c,Eina_Bool success)409 _connect_cb(void *data EINA_UNUSED,
410 Ethumb_Client *c,
411 Eina_Bool success)
412 {
413 if (success)
414 {
415 ethumb_client_on_server_die_callback_set(c, _on_die_cb, NULL, NULL);
416 _elm_ethumb_connected = EINA_TRUE;
417 ecore_event_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, NULL, NULL, NULL);
418 }
419 else
420 _elm_ethumb_client = NULL;
421 }
422
423 static void
_on_die_cb(void * data EINA_UNUSED,Ethumb_Client * c EINA_UNUSED)424 _on_die_cb(void *data EINA_UNUSED,
425 Ethumb_Client *c EINA_UNUSED)
426 {
427 if (_elm_ethumb_client)
428 {
429 ethumb_client_disconnect(_elm_ethumb_client);
430 _elm_ethumb_client = NULL;
431 }
432 _elm_ethumb_connected = EINA_FALSE;
433 if (pending_request > 0)
434 _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
435 }
436
437 static void
_thumb_show(Elm_Thumb_Data * sd)438 _thumb_show(Elm_Thumb_Data *sd)
439 {
440 ELM_WIDGET_DATA_GET_OR_RETURN(sd->obj, wd);
441 evas_object_show(wd->resize_obj);
442
443 if (!_elm_ethumb_client)
444 _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
445 else if (elm_thumb_ethumb_client_connected_get())
446 {
447 _thumb_start(sd);
448 return;
449 }
450
451 if (!sd->eeh)
452 sd->eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT,
453 _thumbnailing_available_cb, sd->obj);
454 }
455
456 EOLIAN static void
_elm_thumb_efl_gfx_entity_visible_set(Eo * obj,Elm_Thumb_Data * sd,Eina_Bool vis)457 _elm_thumb_efl_gfx_entity_visible_set(Eo *obj, Elm_Thumb_Data *sd, Eina_Bool vis)
458 {
459 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
460 return;
461
462 efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
463
464 if (vis)
465 {
466 _thumb_show(sd);
467 return;
468 }
469
470 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
471
472 if (sd->thumb.request)
473 {
474 ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
475 sd->thumb.request = NULL;
476
477 edje_object_signal_emit(wd->resize_obj, EDJE_SIGNAL_GENERATE_STOP, "elm");
478 efl_event_callback_legacy_call(sd->obj, ELM_THUMB_EVENT_GENERATE_STOP, NULL);
479 }
480
481 if (sd->thumb.retry)
482 {
483 retry = eina_list_remove(retry, sd);
484 efl_data_unref(sd->obj, sd);
485 sd->thumb.retry = EINA_FALSE;
486 }
487
488 ELM_SAFE_FREE(sd->eeh, ecore_event_handler_del);
489 }
490
491 void
_elm_unneed_ethumb(void)492 _elm_unneed_ethumb(void)
493 {
494 if (!_elm_need_ethumb) return;
495 _elm_need_ethumb = EINA_FALSE;
496
497 if (_elm_ethumb_client)
498 {
499 ethumb_client_disconnect(_elm_ethumb_client);
500 _elm_ethumb_client = NULL;
501 }
502 ethumb_client_shutdown();
503
504 ecore_event_type_flush(ELM_ECORE_EVENT_ETHUMB_CONNECT);
505 }
506
507 static Eina_Bool
_elm_thumb_dnd_cb(void * data EINA_UNUSED,Evas_Object * o,Elm_Selection_Data * drop)508 _elm_thumb_dnd_cb(void *data EINA_UNUSED,
509 Evas_Object *o,
510 Elm_Selection_Data *drop)
511 {
512 if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE;
513 elm_thumb_file_set(o, drop->data, NULL);
514 return EINA_TRUE;
515 }
516
517 EAPI Eina_Bool
elm_need_ethumb(void)518 elm_need_ethumb(void)
519 {
520 if (_elm_need_ethumb) return EINA_TRUE;
521 _elm_need_ethumb = EINA_TRUE;
522
523 ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new();
524 ethumb_client_init();
525
526 return EINA_TRUE;
527 }
528
529 EOLIAN static void
_elm_thumb_efl_canvas_group_group_add(Eo * obj,Elm_Thumb_Data * _pd EINA_UNUSED)530 _elm_thumb_efl_canvas_group_group_add(Eo *obj, Elm_Thumb_Data *_pd EINA_UNUSED)
531 {
532 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
533
534 efl_canvas_group_add(efl_super(obj, MY_CLASS));
535
536 if (!elm_layout_theme_set(obj, "thumb", "base", elm_widget_style_get(obj)))
537 CRI("Failed to set layout!");
538
539 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
540 _mouse_down_cb, obj);
541 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
542 _mouse_up_cb, obj);
543
544 elm_widget_can_focus_set(obj, EINA_FALSE);
545 }
546
547 EOLIAN static void
_elm_thumb_efl_canvas_group_group_del(Eo * obj,Elm_Thumb_Data * sd)548 _elm_thumb_efl_canvas_group_group_del(Eo *obj, Elm_Thumb_Data *sd)
549 {
550 if (sd->thumb.request)
551 {
552 ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
553 sd->thumb.request = NULL;
554 }
555 if (sd->thumb.retry)
556 {
557 retry = eina_list_remove(retry, sd);
558 efl_data_unref(sd->obj, sd);
559 sd->thumb.retry = EINA_FALSE;
560 }
561 evas_object_event_callback_del_full(sd->view, EVAS_CALLBACK_IMAGE_PRELOADED,
562 _on_thumb_preloaded, sd);
563
564 ELM_SAFE_FREE(sd->view, evas_object_del);
565 eina_stringshare_del(sd->thumb.thumb_path);
566 eina_stringshare_del(sd->thumb.thumb_key);
567
568 eina_stringshare_del(sd->file);
569 eina_stringshare_del(sd->key);
570
571 ecore_event_handler_del(sd->eeh);
572
573 efl_canvas_group_del(efl_super(obj, MY_CLASS));
574 }
575
576 EAPI Evas_Object *
elm_thumb_add(Evas_Object * parent)577 elm_thumb_add(Evas_Object *parent)
578 {
579 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
580 return elm_legacy_add(MY_CLASS, parent);
581 }
582
583 EOLIAN static Eo *
_elm_thumb_efl_object_finalize(Eo * obj,Elm_Thumb_Data * sd)584 _elm_thumb_efl_object_finalize(Eo *obj, Elm_Thumb_Data *sd)
585 {
586 obj = efl_finalize(efl_super(obj, MY_CLASS));
587 if (sd->file) efl_file_load(obj);
588 return obj;
589 }
590
591 EOLIAN static Eo *
_elm_thumb_efl_object_constructor(Eo * obj,Elm_Thumb_Data * sd)592 _elm_thumb_efl_object_constructor(Eo *obj, Elm_Thumb_Data *sd)
593 {
594 obj = efl_constructor(efl_super(obj, MY_CLASS));
595 efl_canvas_object_type_set(obj, "Elm_Thumb");
596 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
597 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_IMAGE);
598
599 sd->obj = obj;
600
601 return obj;
602 }
603
604 EOLIAN static Eina_Error
_elm_thumb_efl_file_file_set(Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd,const char * file)605 _elm_thumb_efl_file_file_set(Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd, const char *file)
606 {
607 if (eina_stringshare_replace(&(sd->file), file))
608 sd->loaded = EINA_FALSE;
609 return 0;
610 }
611
612 EOLIAN static void
_elm_thumb_efl_file_key_set(Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd,const char * key)613 _elm_thumb_efl_file_key_set(Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd, const char *key)
614 {
615 if (eina_stringshare_replace(&(sd->key), key))
616 sd->loaded = EINA_FALSE;
617 }
618
619 EOLIAN static const char *
_elm_thumb_efl_file_file_get(const Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd)620 _elm_thumb_efl_file_file_get(const Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd)
621 {
622 return sd->file;
623 }
624
625 EOLIAN static const char *
_elm_thumb_efl_file_key_get(const Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd)626 _elm_thumb_efl_file_key_get(const Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd)
627 {
628 return sd->key;
629 }
630
631 EOLIAN static Eina_Bool
_elm_thumb_efl_file_loaded_get(const Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd)632 _elm_thumb_efl_file_loaded_get(const Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd)
633 {
634 return sd->loaded;
635 }
636
637 EOLIAN static void
_elm_thumb_efl_file_unload(Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd)638 _elm_thumb_efl_file_unload(Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd)
639 {
640 sd->is_video = EINA_FALSE;
641 eina_stringshare_replace(&(sd->thumb.file), NULL);
642 eina_stringshare_replace(&(sd->thumb.key), NULL);
643 sd->loaded = EINA_FALSE;
644
645 if (sd->thumb.request)
646 {
647 ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request);
648 sd->thumb.request = NULL;
649 }
650 if (sd->thumb.retry)
651 {
652 retry = eina_list_remove(retry, sd);
653 efl_data_unref(sd->obj, sd);
654 sd->thumb.retry = EINA_FALSE;
655 }
656 evas_object_event_callback_del_full(sd->view, EVAS_CALLBACK_IMAGE_PRELOADED,
657 _on_thumb_preloaded, sd);
658
659 ELM_SAFE_FREE(sd->view, evas_object_del);
660 eina_stringshare_replace(&sd->thumb.thumb_path, NULL);
661 eina_stringshare_replace(&sd->thumb.thumb_key, NULL);
662
663 ELM_SAFE_FREE(sd->eeh, ecore_event_handler_del);
664
665 }
666
667 EOLIAN static Eina_Error
_elm_thumb_efl_file_load(Eo * obj,Elm_Thumb_Data * sd)668 _elm_thumb_efl_file_load(Eo *obj, Elm_Thumb_Data *sd)
669 {
670 int prefix_size;
671 const char **ext, *ptr;
672 static const char *extensions[] =
673 {
674 ".asf", ".avi", ".bdm", ".bdmv", ".clpi", ".cpi", ".dv", ".fla",
675 ".flv", ".m1v", ".m2t", ".m2v", ".m4v", ".mkv", ".mov", ".mp2",
676 ".mp2ts", ".mp4", ".mpe", ".mpeg", ".mpg", ".mpl", ".mpls", ".mts",
677 ".mxf", ".nut", ".nuv", ".ogg", ".ogm", ".ogv", ".qt", ".rm", ".rmj",
678 ".rmm", ".rms", ".rmvb", ".rmx", ".rv", ".swf", ".ts", ".weba",
679 ".webm", ".wmv", ".3g2", ".3gp", ".3gp2", ".3gpp", ".3gpp2", ".3p2",
680 ".264",
681 NULL
682 };
683
684 if (efl_file_loaded_get(obj)) return 0;
685 prefix_size = eina_stringshare_strlen(sd->file) - 4;
686 if (prefix_size >= 0)
687 {
688 ptr = sd->file + prefix_size;
689 sd->is_video = EINA_FALSE;
690 for (ext = extensions; *ext; ext++)
691 if (!strcasecmp(ptr, *ext))
692 {
693 sd->is_video = EINA_TRUE;
694 break;
695 }
696 }
697
698 eina_stringshare_replace(&(sd->thumb.file), NULL);
699 eina_stringshare_replace(&(sd->thumb.key), NULL);
700 sd->loaded = EINA_TRUE;
701
702 if (evas_object_visible_get(obj))
703 _thumb_show(sd);
704
705 return 0;
706 }
707
708 EAPI void *
elm_thumb_ethumb_client_get(void)709 elm_thumb_ethumb_client_get(void)
710 {
711 return _elm_ethumb_client;
712 }
713
714 EAPI Eina_Bool
elm_thumb_ethumb_client_connected_get(void)715 elm_thumb_ethumb_client_connected_get(void)
716 {
717 return _elm_ethumb_connected;
718 }
719
720 EOLIAN static void
_elm_thumb_efl_ui_draggable_drag_target_set(Eo * obj,Elm_Thumb_Data * sd,Eina_Bool edit)721 _elm_thumb_efl_ui_draggable_drag_target_set(Eo *obj, Elm_Thumb_Data *sd, Eina_Bool edit)
722 {
723 edit = !!edit;
724 if (sd->edit == edit) return;
725
726 sd->edit = edit;
727 if (sd->edit)
728 elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE,
729 NULL, NULL,
730 NULL, NULL,
731 NULL, NULL,
732 _elm_thumb_dnd_cb, obj);
733 else
734 elm_drop_target_del(obj, ELM_SEL_FORMAT_IMAGE,
735 NULL, NULL,
736 NULL, NULL,
737 NULL, NULL,
738 _elm_thumb_dnd_cb, obj);
739
740 return;
741 }
742
743 EOLIAN static Eina_Bool
_elm_thumb_efl_ui_draggable_drag_target_get(const Eo * obj EINA_UNUSED,Elm_Thumb_Data * sd)744 _elm_thumb_efl_ui_draggable_drag_target_get(const Eo *obj EINA_UNUSED, Elm_Thumb_Data *sd)
745 {
746 return sd->edit;
747 }
748
749 EOLIAN static void
_elm_thumb_class_constructor(Efl_Class * klass)750 _elm_thumb_class_constructor(Efl_Class *klass)
751 {
752 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
753 }
754
755 EAPI void
elm_thumb_file_set(Eo * obj,const char * file,const char * key)756 elm_thumb_file_set(Eo *obj, const char *file, const char *key)
757 {
758 efl_file_simple_load((Eo *) obj, file, key);
759 }
760
761 EAPI void
elm_thumb_file_get(const Eo * obj,const char ** file,const char ** key)762 elm_thumb_file_get(const Eo *obj, const char **file, const char **key)
763 {
764 efl_file_simple_get((Eo *) obj, file, key);
765 }
766
767 /* Legacy deprecated functions */
768 EAPI Eina_Bool
elm_thumb_editable_set(Evas_Object * obj,Eina_Bool edit)769 elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit)
770 {
771 efl_ui_draggable_drag_target_set(obj, edit);
772 return EINA_TRUE;
773 }
774
775 EAPI Eina_Bool
elm_thumb_editable_get(const Evas_Object * obj)776 elm_thumb_editable_get(const Evas_Object *obj)
777 {
778 return efl_ui_draggable_drag_target_get(obj);
779 }
780
781 EAPI void
elm_thumb_aspect_set(Evas_Object * obj,Ethumb_Thumb_Aspect aspect)782 elm_thumb_aspect_set(Evas_Object *obj, Ethumb_Thumb_Aspect aspect)
783 {
784 ELM_THUMB_CHECK(obj);
785 ELM_THUMB_DATA_GET(obj, sd);
786 sd->thumb.aspect = aspect;
787 }
788
789 EAPI Ethumb_Thumb_Aspect
elm_thumb_aspect_get(const Evas_Object * obj)790 elm_thumb_aspect_get(const Evas_Object *obj)
791 {
792 ELM_THUMB_CHECK(obj) ETHUMB_THUMB_KEEP_ASPECT;
793 ELM_THUMB_DATA_GET(obj, sd);
794 return sd->thumb.aspect;
795 }
796
797 EAPI void
elm_thumb_fdo_size_set(Evas_Object * obj,Ethumb_Thumb_FDO_Size size)798 elm_thumb_fdo_size_set(Evas_Object *obj, Ethumb_Thumb_FDO_Size size)
799 {
800 ELM_THUMB_CHECK(obj);
801 ELM_THUMB_DATA_GET(obj, sd);
802 sd->thumb.size = size;
803 }
804
805 EAPI Ethumb_Thumb_FDO_Size
elm_thumb_fdo_size_get(const Evas_Object * obj)806 elm_thumb_fdo_size_get(const Evas_Object *obj)
807 {
808 ELM_THUMB_CHECK(obj) ETHUMB_THUMB_NORMAL;
809 ELM_THUMB_DATA_GET(obj, sd);
810 return sd->thumb.size;
811 }
812
813 EAPI void
elm_thumb_format_set(Evas_Object * obj,Ethumb_Thumb_Format format)814 elm_thumb_format_set(Evas_Object *obj, Ethumb_Thumb_Format format)
815 {
816 ELM_THUMB_CHECK(obj);
817 ELM_THUMB_DATA_GET(obj, sd);
818 sd->thumb.format = format;
819 }
820
821 EAPI Ethumb_Thumb_Format
elm_thumb_format_get(const Evas_Object * obj)822 elm_thumb_format_get(const Evas_Object *obj)
823 {
824 ELM_THUMB_CHECK(obj) ETHUMB_THUMB_FDO;
825 ELM_THUMB_DATA_GET(obj, sd);
826 return sd->thumb.format;
827 }
828
829 EAPI void
elm_thumb_orientation_set(Evas_Object * obj,Ethumb_Thumb_Orientation orient)830 elm_thumb_orientation_set(Evas_Object *obj, Ethumb_Thumb_Orientation orient)
831 {
832 ELM_THUMB_CHECK(obj);
833 ELM_THUMB_DATA_GET(obj, sd);
834 sd->thumb.orient = orient;
835 }
836
837 EAPI Ethumb_Thumb_Orientation
elm_thumb_orientation_get(const Evas_Object * obj)838 elm_thumb_orientation_get(const Evas_Object *obj)
839 {
840 ELM_THUMB_CHECK(obj) ETHUMB_THUMB_ORIENT_NONE;
841 ELM_THUMB_DATA_GET(obj, sd);
842 return sd->thumb.orient;
843 }
844
845 EAPI void
elm_thumb_size_set(Evas_Object * obj,int tw,int th)846 elm_thumb_size_set(Evas_Object *obj, int tw, int th)
847 {
848 ELM_THUMB_CHECK(obj);
849 ELM_THUMB_DATA_GET(obj, sd);
850 sd->thumb.tw = tw;
851 sd->thumb.th = th;
852 }
853
854 EAPI void
elm_thumb_size_get(const Evas_Object * obj,int * tw,int * th)855 elm_thumb_size_get(const Evas_Object *obj, int *tw, int *th)
856 {
857 ELM_THUMB_CHECK(obj);
858 ELM_THUMB_DATA_GET(obj, sd);
859 if (tw)
860 *tw = sd->thumb.tw;
861 if (th)
862 *th = sd->thumb.th;
863 }
864
865 EAPI void
elm_thumb_crop_align_set(Evas_Object * obj,double cropx,double cropy)866 elm_thumb_crop_align_set(Evas_Object *obj, double cropx, double cropy)
867 {
868 ELM_THUMB_CHECK(obj);
869 ELM_THUMB_DATA_GET(obj, sd);
870 sd->thumb.cropx = cropx;
871 sd->thumb.cropy = cropy;
872 }
873
874 EAPI void
elm_thumb_crop_align_get(const Evas_Object * obj,double * cropx,double * cropy)875 elm_thumb_crop_align_get(const Evas_Object *obj, double *cropx, double *cropy)
876 {
877 ELM_THUMB_CHECK(obj);
878 ELM_THUMB_DATA_GET(obj, sd);
879 if (cropx)
880 *cropx = sd->thumb.cropx;
881 if (cropy)
882 *cropy = sd->thumb.cropy;
883 }
884
885 EAPI void
elm_thumb_compress_set(Evas_Object * obj,int compress)886 elm_thumb_compress_set(Evas_Object *obj, int compress)
887 {
888 ELM_THUMB_CHECK(obj);
889 ELM_THUMB_DATA_GET(obj, sd);
890 sd->thumb.compress = compress;
891 }
892
893 EAPI void
elm_thumb_compress_get(const Evas_Object * obj,int * compress)894 elm_thumb_compress_get(const Evas_Object *obj, int *compress)
895 {
896 ELM_THUMB_CHECK(obj);
897 ELM_THUMB_DATA_GET(obj, sd);
898 if (compress)
899 *compress = sd->thumb.compress;
900 }
901
902 EAPI void
elm_thumb_quality_set(Evas_Object * obj,int quality)903 elm_thumb_quality_set(Evas_Object *obj, int quality)
904 {
905 ELM_THUMB_CHECK(obj);
906 ELM_THUMB_DATA_GET(obj, sd);
907 sd->thumb.quality = quality;
908 }
909
910 EAPI void
elm_thumb_quality_get(const Evas_Object * obj,int * quality)911 elm_thumb_quality_get(const Evas_Object *obj, int *quality)
912 {
913 ELM_THUMB_CHECK(obj);
914 ELM_THUMB_DATA_GET(obj, sd);
915 if (quality)
916 *quality = sd->thumb.quality;
917 }
918
919 EAPI void
elm_thumb_animate_set(Evas_Object * obj,Elm_Thumb_Animation_Setting setting)920 elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting setting)
921 {
922 ELM_THUMB_CHECK(obj);
923 ELM_THUMB_DATA_GET(obj, sd);
924 EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST);
925
926 sd->anim_setting = setting;
927
928 if ((sd->is_video) && (sd->thumb.format == ETHUMB_THUMB_EET))
929 {
930 if (setting == ELM_THUMB_ANIMATION_LOOP)
931 edje_object_signal_emit(sd->view, "elm,action,animate_loop", "elm");
932 else if (setting == ELM_THUMB_ANIMATION_START)
933 edje_object_signal_emit(sd->view, "elm,action,animate", "elm");
934 else if (setting == ELM_THUMB_ANIMATION_STOP)
935 edje_object_signal_emit(sd->view, "elm,action,animate_stop", "elm");
936 }
937 }
938
939 EAPI Elm_Thumb_Animation_Setting
elm_thumb_animate_get(const Evas_Object * obj)940 elm_thumb_animate_get(const Evas_Object *obj)
941 {
942 ELM_THUMB_CHECK(obj) 0;
943 ELM_THUMB_DATA_GET(obj, sd);
944 return sd->anim_setting;
945 }
946
947 EAPI void
elm_thumb_path_get(const Evas_Object * obj,const char ** file,const char ** key)948 elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key)
949 {
950 ELM_THUMB_CHECK(obj);
951 ELM_THUMB_DATA_GET(obj, sd);
952 if (file)
953 *file = sd->thumb.file;
954 if (key)
955 *key = sd->thumb.key;
956 }
957
958 EAPI void
elm_thumb_reload(Evas_Object * obj)959 elm_thumb_reload(Evas_Object *obj)
960 {
961 ELM_THUMB_CHECK(obj);
962 ELM_THUMB_DATA_GET(obj, sd);
963 eina_stringshare_replace(&(sd->thumb.file), NULL);
964 eina_stringshare_replace(&(sd->thumb.key), NULL);
965
966 if (evas_object_visible_get(obj))
967 _thumb_show(sd);
968 }
969
970 /* Internal EO APIs and hidden overrides */
971
972 #define ELM_THUMB_EXTRA_OPS \
973 EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_thumb)
974
975 #include "elm_thumb_eo.c"
976