Imported Upstream version 1.7.1
[platform/upstream/emotion.git] / src / lib / emotion_smart.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <Evas.h>
6 #include <Ecore.h>
7
8 #ifdef HAVE_EIO
9 # include <math.h>
10 # include <Eio.h>
11 #endif
12
13 #include "Emotion.h"
14 #include "emotion_private.h"
15
16 #ifdef _WIN32
17 # define FMT_UCHAR "%c"
18 #else
19 # define FMT_UCHAR "%hhu"
20 #endif
21
22 #define E_SMART_OBJ_GET(smart, o, type) \
23      { \
24         char *_e_smart_str; \
25         \
26         if (!o) return; \
27         smart = evas_object_smart_data_get(o); \
28         if (!smart) return; \
29         _e_smart_str = (char *)evas_object_type_get(o); \
30         if (!_e_smart_str) return; \
31         if (strcmp(_e_smart_str, type)) return; \
32      }
33
34 #define E_SMART_OBJ_GET_RETURN(smart, o, type, ret) \
35    { \
36       char *_e_smart_str; \
37       \
38       if (!o) return ret; \
39       smart = evas_object_smart_data_get(o); \
40       if (!smart) return ret; \
41       _e_smart_str = (char *)evas_object_type_get(o); \
42       if (!_e_smart_str) return ret; \
43       if (strcmp(_e_smart_str, type)) return ret; \
44    }
45
46 #define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
47 #define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
48 #define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__)
49 #define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
50 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_log_domain, __VA_ARGS__)
51
52 #define E_OBJ_NAME "emotion_object"
53
54 typedef struct _Smart_Data Smart_Data;
55
56 struct _Smart_Data
57 {
58    EINA_REFCOUNT;
59    Emotion_Video_Module  *module;
60    void                  *video_data;
61
62    char                  *module_name;
63
64    const char    *file;
65    Evas_Object   *obj;
66    Evas_Object   *bg;
67
68    Ecore_Job     *job;
69
70    char *title;
71
72 #ifdef HAVE_EIO
73    Eio_File *load_xattr;
74    Eio_File *save_xattr;
75 #endif
76
77    struct {
78       char   *info;
79       double  stat;
80    } progress;
81    struct {
82       char *file;
83       int   num;
84    } ref;
85    struct {
86       int button_num;
87       int button;
88    } spu;
89    struct {
90       int l; /* left */
91       int r; /* right */
92       int t; /* top */
93       int b; /* bottom */
94       Evas_Object *clipper;
95    } crop;
96
97    struct {
98       int         w, h;
99    } video;
100    struct {
101       double      w, h;
102    } fill;
103
104    double         ratio;
105    double         pos;
106    double         remember_jump;
107    double         seek_pos;
108    double         len;
109
110    Emotion_Module_Options module_options;
111
112    Emotion_Suspend state;
113    Emotion_Aspect aspect;
114
115    Ecore_Animator *anim;
116
117    Eina_Bool open : 1;
118    Eina_Bool play : 1;
119    Eina_Bool remember_play : 1;
120    Eina_Bool seek : 1;
121    Eina_Bool seeking : 1;
122 };
123
124 static void _mouse_move(void *data, Evas *ev, Evas_Object *obj, void *event_info);
125 static void _mouse_down(void *data, Evas *ev, Evas_Object *obj, void *event_info);
126 static void _pos_set_job(void *data);
127 static void _pixels_get(void *data, Evas_Object *obj);
128
129 static void _smart_init(void);
130 static void _smart_add(Evas_Object * obj);
131 static void _smart_del(Evas_Object * obj);
132 static void _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y);
133 static void _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h);
134 static void _smart_show(Evas_Object * obj);
135 static void _smart_hide(Evas_Object * obj);
136 static void _smart_color_set(Evas_Object * obj, int r, int g, int b, int a);
137 static void _smart_clip_set(Evas_Object * obj, Evas_Object * clip);
138 static void _smart_clip_unset(Evas_Object * obj);
139
140 /**********************************/
141 /* Globals for the E Video Object */
142 /**********************************/
143 static Evas_Smart  *smart = NULL;
144 static Eina_Hash *_backends = NULL;
145 static Eina_Array *_modules = NULL;
146 static int _log_domain = -1;
147
148 static const char *_backend_priority[] = {
149   "gstreamer",
150   "xine",
151   "generic"
152 };
153
154 static const char SIG_FRAME_DECODE[] = "frame_decode";
155 static const char SIG_POSITION_UPDATE[] = "position_update";
156 static const char SIG_LENGTH_CHANGE[] = "length_change";
157 static const char SIG_FRAME_RESIZE[] = "frame_resize";
158 static const char SIG_DECODE_STOP[] = "decode_stop";
159 static const char SIG_PLAYBACK_STARTED[] = "playback_started";
160 static const char SIG_PLAYBACK_FINISHED[] = "playback_finished";
161 static const char SIG_AUDIO_LEVEL_CHANGE[] = "audio_level_change";
162 static const char SIG_CHANNELS_CHANGE[] = "channels_change";
163 static const char SIG_TITLE_CHANGE[] = "title_change";
164 static const char SIG_PROGRESS_CHANGE[] = "progress_change";
165 static const char SIG_REF_CHANGE[] = "ref_change";
166 static const char SIG_BUTTON_NUM_CHANGE[] = "button_num_change";
167 static const char SIG_BUTTON_CHANGE[] = "button_change";
168 static const char SIG_OPEN_DONE[] = "open_done";
169 static const char SIG_POSITION_SAVE_SUCCEED[] = "position_save,succeed";
170 static const char SIG_POSITION_SAVE_FAILED[] = "position_save,failed";
171 static const char SIG_POSITION_LOAD_SUCCEED[] = "position_load,succeed";
172 static const char SIG_POSITION_LOAD_FAILED[] = "position_load,failed";
173
174 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
175   {SIG_FRAME_DECODE, ""},
176   {SIG_POSITION_UPDATE, ""},
177   {SIG_LENGTH_CHANGE, ""},
178   {SIG_FRAME_RESIZE, ""},
179   {SIG_DECODE_STOP, ""},
180   {SIG_PLAYBACK_STARTED, ""},
181   {SIG_PLAYBACK_FINISHED, ""},
182   {SIG_AUDIO_LEVEL_CHANGE, ""},
183   {SIG_CHANNELS_CHANGE, ""},
184   {SIG_TITLE_CHANGE, ""},
185   {SIG_PROGRESS_CHANGE, ""},
186   {SIG_REF_CHANGE, ""},
187   {SIG_BUTTON_NUM_CHANGE, ""},
188   {SIG_BUTTON_CHANGE, ""},
189   {SIG_OPEN_DONE, ""},
190   {NULL, NULL}
191 };
192
193 static void
194 _emotion_image_data_zero(Evas_Object *img)
195 {
196    void *data;
197
198    data = evas_object_image_data_get(img, 1);
199    if (data)
200      {
201         int w, h, sz = 0;
202         Evas_Colorspace cs;
203
204         evas_object_image_size_get(img, &w, &h);
205         cs = evas_object_image_colorspace_get(img);
206         if (cs == EVAS_COLORSPACE_ARGB8888)
207            sz = w * h * 4;
208         if ((cs == EVAS_COLORSPACE_YCBCR422P601_PL) ||
209             (cs == EVAS_COLORSPACE_YCBCR422P709_PL))
210            sz = h * 2 * sizeof(unsigned char *);
211         if (sz != 0) memset(data, 0, sz);
212      }
213    evas_object_image_data_set(img, data);
214 }
215
216 static void
217 _emotion_module_close(Emotion_Video_Module *mod, void *video)
218 {
219    if (!mod) return;
220    if (mod->plugin->close && video)
221      mod->plugin->close(mod, video);
222    /* FIXME: we can't go dlclosing here as a thread still may be running from
223     * the module - this in theory will leak- but it shouldn't be too bad and
224     * mean that once a module is dlopened() it can't be closed - its refcount
225     * will just keep going up
226     */
227 }
228
229 static void
230 _smart_data_free(Smart_Data *sd)
231 {
232    if (sd->video_data) sd->module->file_close(sd->video_data);
233    _emotion_module_close(sd->module, sd->video_data);
234    evas_object_del(sd->obj);
235    evas_object_del(sd->crop.clipper);
236    evas_object_del(sd->bg);
237    eina_stringshare_del(sd->file);
238    free(sd->module_name);
239    if (sd->job) ecore_job_del(sd->job);
240    if (sd->anim) ecore_animator_del(sd->anim);
241    free(sd->progress.info);
242    free(sd->ref.file);
243    free(sd);
244
245    ecore_shutdown();
246 }
247
248 EAPI Eina_Bool
249 _emotion_module_register(const char *name, Emotion_Module_Open mod_open, Emotion_Module_Close mod_close)
250 {
251    Eina_Emotion_Plugins *plugin;
252
253    plugin = malloc(sizeof (Eina_Emotion_Plugins));
254    if (!plugin) return EINA_FALSE;
255
256    plugin->open = mod_open;
257    plugin->close = mod_close;
258
259    return eina_hash_add(_backends, name, plugin);
260 }
261
262 EAPI Eina_Bool
263 _emotion_module_unregister(const char *name)
264 {
265    return eina_hash_del(_backends, name, NULL);
266 }
267
268 static const char *
269 _emotion_module_open(const char *name, Evas_Object *obj, Emotion_Video_Module **mod, void **video)
270 {
271    Eina_Emotion_Plugins *plugin;
272    Smart_Data *sd;
273    unsigned int i = 0;
274
275    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
276    if (!_backends)
277      {
278         ERR("No backend loaded");
279         return NULL;
280      }
281
282    if (!name && getenv("EMOTION_ENGINE"))
283      name = getenv("EMOTION_ENGINE");
284
285    /* FIXME: Always look for a working backend. */
286  retry:
287    if (!name || i > 0)
288      name = _backend_priority[i++];
289
290    plugin = eina_hash_find(_backends, name);
291    if (!plugin)
292      {
293         if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
294           goto retry;
295
296         ERR("No backend loaded");
297         return EINA_FALSE;
298      }
299
300    if (plugin->open(obj, (const Emotion_Video_Module **) mod, video, &(sd->module_options)))
301      {
302         if (*mod)
303           {
304              (*mod)->plugin = plugin;
305              return name;
306           }
307      }
308
309    if (i != 0 && i < (sizeof (_backend_priority) / sizeof (char*)))
310      goto retry;
311
312    ERR("Unable to load module: %s", name);
313
314    return NULL;
315 }
316
317 static void
318 _clipper_position_size_update(Evas_Object *obj, int x, int y, int w, int h, int vid_w, int vid_h)
319 {
320    Smart_Data *sd;
321    double scale_w, scale_h;
322
323    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
324
325    if (vid_w == 0 || vid_h == 0)
326      {
327        evas_object_image_fill_set(sd->obj, 0, 0, 0, 0);
328        evas_object_move(sd->obj, x, y);
329        evas_object_resize(sd->obj, 0, 0);
330        evas_object_move(sd->crop.clipper, x, y);
331        evas_object_resize(sd->crop.clipper, 0, 0);
332      }
333    else
334      {
335        evas_object_move(sd->crop.clipper, x, y);
336        scale_w = (double)w / (double)(vid_w - sd->crop.l - sd->crop.r);
337        scale_h = (double)h / (double)(vid_h - sd->crop.t - sd->crop.b);
338
339        if (sd->fill.w < 0 && sd->fill.h < 0)
340          evas_object_image_fill_set(sd->obj, 0, 0, vid_w * scale_w, vid_h * scale_h);
341        else
342          evas_object_image_fill_set(sd->obj, 0, 0, sd->fill.w * w, sd->fill.h * h);
343        evas_object_resize(sd->obj, vid_w * scale_w, vid_h * scale_h);
344        evas_object_move(sd->obj, x - sd->crop.l * scale_w, y - sd->crop.t * scale_h);
345        evas_object_resize(sd->crop.clipper, w, h);
346      }
347 }
348
349 /*******************************/
350 /* Externally accessible calls */
351 /*******************************/
352
353
354
355 EAPI Evas_Object *
356 emotion_object_add(Evas *evas)
357 {
358    _smart_init();
359    return evas_object_smart_add(evas, smart);
360 }
361
362 EAPI Evas_Object *
363 emotion_object_image_get(const Evas_Object *obj)
364 {
365    Smart_Data *sd;
366
367    sd = evas_object_smart_data_get(obj);
368    if (!sd) return NULL;
369    return sd->obj;
370 }
371
372 EAPI void
373 emotion_object_module_option_set(Evas_Object *obj, const char *opt, const char *val)
374 {
375    Smart_Data *sd;
376
377    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
378    if ((!opt) || (!val)) return;
379
380    if (!strcmp(opt, "player"))
381      eina_stringshare_replace(&sd->module_options.player, val);
382 }
383
384 EAPI Eina_Bool
385 emotion_object_init(Evas_Object *obj, const char *module_filename)
386 {
387    Smart_Data *sd;
388    const char *file;
389
390    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
391
392    if ((sd->module_name) && module_filename && (!strcmp(sd->module_name, module_filename)))
393      return EINA_TRUE;
394    free(sd->module_name);
395    sd->module_name = NULL;
396
397    file = sd->file;
398    sd->file = NULL;
399
400    free(sd->title);
401    sd->title = NULL;
402    free(sd->progress.info);
403    sd->progress.info = NULL;
404    sd->progress.stat = 0.0;
405    free(sd->ref.file);
406    sd->ref.file = NULL;
407    sd->ref.num = 0;
408    sd->spu.button_num = 0;
409    sd->spu.button = -1;
410    sd->ratio = 1.0;
411    sd->pos = 0;
412    sd->remember_jump = 0;
413    sd->seek_pos = 0;
414    sd->len = 0;
415    sd->remember_play = 0;
416
417    if (sd->anim) ecore_animator_del(sd->anim);
418    sd->anim = NULL;
419
420    _emotion_module_close(sd->module, sd->video_data);
421    sd->module = NULL;
422    sd->video_data = NULL;
423
424    module_filename = _emotion_module_open(module_filename, obj, &sd->module, &sd->video_data);
425    if (!module_filename)
426      return EINA_FALSE;
427
428    sd->module_name = strdup(module_filename);
429
430    if (file)
431      {
432         emotion_object_file_set(obj, file);
433         eina_stringshare_del(file);
434      }
435
436    return EINA_TRUE;
437 }
438
439 EAPI Eina_Bool
440 emotion_object_file_set(Evas_Object *obj, const char *file)
441 {
442    Smart_Data *sd;
443
444    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
445
446    DBG("file=%s", file);
447    if (!sd->module) return EINA_FALSE;
448
449    sd->video.w = 0;
450    sd->video.h = 0;
451    if ((file) && (sd->file) &&
452        ((file == sd->file) || (!strcmp(file, sd->file)))) return EINA_FALSE;
453    if ((file) && (file[0] != 0))
454      {
455         eina_stringshare_replace(&sd->file, file);
456         sd->module->file_close(sd->video_data);
457         evas_object_image_data_set(sd->obj, NULL);
458         evas_object_image_size_set(sd->obj, 1, 1);
459         _emotion_image_data_zero(sd->obj);
460         sd->open = 0;
461         if (!sd->module->file_open(sd->file, obj, sd->video_data))
462           return EINA_FALSE;
463         sd->pos = 0.0;
464         if (sd->play) sd->module->play(sd->video_data, 0.0);
465      }
466    else
467      {
468         if (sd->video_data && sd->module)
469           {
470              sd->module->file_close(sd->video_data);
471              evas_object_image_data_set(sd->obj, NULL);
472              evas_object_image_size_set(sd->obj, 1, 1);
473              _emotion_image_data_zero(sd->obj);
474           }
475         eina_stringshare_replace(&sd->file, NULL);
476      }
477
478    if (sd->anim) ecore_animator_del(sd->anim);
479    sd->anim = NULL;
480
481 #ifdef HAVE_EIO
482    /* Only cancel the load_xattr or we will loose ref to time_seek stringshare */
483    if (sd->load_xattr) eio_file_cancel(sd->load_xattr);
484    sd->load_xattr = NULL;
485    if (sd->save_xattr) eio_file_cancel(sd->save_xattr);
486    sd->save_xattr = NULL;
487 #endif
488
489    return EINA_TRUE;
490 }
491
492 EAPI const char *
493 emotion_object_file_get(const Evas_Object *obj)
494 {
495    Smart_Data *sd;
496
497    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
498    return sd->file;
499 }
500
501 static void
502 _emotion_aspect_borders_apply(Evas_Object *obj, Smart_Data *sd, int w, int h, int iw, int ih)
503 {
504    int x, y;
505
506    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
507
508    /* applying calculated borders */
509    if (sd->crop.l == 0 && sd->crop.r == 0 &&
510        sd->crop.t == 0 && sd->crop.b == 0)
511      {
512         Evas_Object *old_clipper;
513         if (sd->crop.clipper)
514           {
515              old_clipper = evas_object_clip_get(sd->crop.clipper);
516              evas_object_clip_unset(sd->obj);
517              evas_object_clip_set(sd->obj, old_clipper);
518              evas_object_del(sd->crop.clipper);
519              sd->crop.clipper = NULL;
520           }
521      }
522    else
523      {
524         if (!sd->crop.clipper)
525           {
526              Evas_Object *old_clipper;
527              sd->crop.clipper = evas_object_rectangle_add(
528                 evas_object_evas_get(obj));
529              evas_object_color_set(sd->crop.clipper, 255, 255, 255, 255);
530              evas_object_smart_member_add(sd->crop.clipper, obj);
531              old_clipper = evas_object_clip_get(sd->obj);
532              evas_object_clip_set(sd->obj, sd->crop.clipper);
533              evas_object_clip_set(sd->crop.clipper, old_clipper);
534              if (evas_object_visible_get(sd->obj))
535                evas_object_show(sd->crop.clipper);
536           }
537      }
538    _clipper_position_size_update(obj, x, y, w, h, iw, ih);
539 }
540
541 static void
542 _emotion_object_aspect_border_apply(Evas_Object *obj, Smart_Data *sd, int w, int h)
543 {
544    int iw, ih;
545    double ir;
546    double r;
547
548    int aspect_opt = 0;
549
550    iw = sd->video.w;
551    ih = sd->video.h;
552
553    ir = (double)iw / ih;
554    r = (double)w / h;
555
556    /* First check if we should fit the width or height of the video inside the
557     * width/height of the object.  This check takes into account the original
558     * aspect ratio and the object aspect ratio, if we are keeping both sizes or
559     * cropping the exceding area.
560     */
561    if (sd->aspect == EMOTION_ASPECT_KEEP_NONE)
562      {
563         sd->crop.l = 0;
564         sd->crop.r = 0;
565         sd->crop.t = 0;
566         sd->crop.b = 0;
567         aspect_opt = 0; // just ignore keep_aspect
568      }
569    else if (sd->aspect == EMOTION_ASPECT_KEEP_WIDTH)
570      {
571         aspect_opt = 1;
572      }
573    else if (sd->aspect == EMOTION_ASPECT_KEEP_HEIGHT)
574      {
575         aspect_opt = 2;
576      }
577    else if (sd->aspect == EMOTION_ASPECT_KEEP_BOTH)
578      {
579         if (ir > r)
580           aspect_opt = 1;
581         else
582           aspect_opt = 2;
583      }
584    else if (sd->aspect == EMOTION_ASPECT_CROP)
585      {
586         if (ir > r)
587           aspect_opt = 2;
588         else
589           aspect_opt = 1;
590      }
591    else if (sd->aspect == EMOTION_ASPECT_CUSTOM)
592      {
593         // nothing to do, just respect the border settings
594         aspect_opt = 0;
595      }
596
597    /* updating borders based on keep_aspect settings */
598    if (aspect_opt == 1) // keep width
599      {
600         int th, dh;
601         double scale;
602
603         sd->crop.l = 0;
604         sd->crop.r = 0;
605         scale = (double)iw / w;
606         th = h * scale;
607         dh = ih - th;
608         sd->crop.t = sd->crop.b = dh / 2;
609      }
610    else if (aspect_opt == 2) // keep height
611      {
612         int tw, dw;
613         double scale;
614
615         sd->crop.t = 0;
616         sd->crop.b = 0;
617         scale = (double)ih / h;
618         tw = w * scale;
619         dw = iw - tw;
620         sd->crop.l = sd->crop.r = dw / 2;
621      }
622
623    _emotion_aspect_borders_apply(obj, sd, w, h, iw, ih);
624 }
625
626 EAPI void
627 emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b)
628 {
629    Smart_Data *sd;
630    int w, h;
631
632    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
633
634    sd->aspect = EMOTION_ASPECT_CUSTOM;
635    sd->crop.l = -l;
636    sd->crop.r = -r;
637    sd->crop.t = -t;
638    sd->crop.b = -b;
639    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
640    _emotion_object_aspect_border_apply(obj, sd, w, h);
641 }
642
643 EAPI void
644 emotion_object_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
645 {
646    Smart_Data *sd;
647
648    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
649    *l = -sd->crop.l;
650    *r = -sd->crop.r;
651    *t = -sd->crop.t;
652    *b = -sd->crop.b;
653 }
654
655 EAPI void
656 emotion_object_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
657 {
658    Smart_Data *sd;
659
660    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
661
662    evas_object_color_set(sd->bg, r, g, b, a);
663
664    if (!evas_object_visible_get(obj))
665      return;
666
667    if (a > 0)
668      evas_object_show(sd->bg);
669    else
670      evas_object_hide(sd->bg);
671 }
672
673 EAPI void
674 emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
675 {
676    Smart_Data *sd;
677
678    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
679    evas_object_color_get(sd->bg, r, g, b, a);
680 }
681
682 EAPI void
683 emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a)
684 {
685    Smart_Data *sd;
686    int w, h;
687
688    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
689
690    if (a == sd->aspect)
691      return;
692
693    sd->aspect = a;
694    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
695    _emotion_object_aspect_border_apply(obj, sd, w, h);
696 }
697
698 EAPI Emotion_Aspect
699 emotion_object_keep_aspect_get(const Evas_Object *obj)
700 {
701    Smart_Data *sd;
702
703    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_ASPECT_KEEP_NONE);
704
705    return sd->aspect;
706 }
707
708 EAPI void
709 emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
710 {
711    Smart_Data *sd;
712
713    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
714    DBG("play=" FMT_UCHAR ", was=" FMT_UCHAR, play, sd->play);
715    if (play == sd->play) return;
716    if (!sd->module) return;
717    if (!sd->video_data) return;
718    if (!sd->open)
719      {
720         sd->remember_play = play;
721         return;
722      }
723    sd->play = play;
724    sd->remember_play = play;
725    if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
726    if (sd->play) sd->module->play(sd->video_data, sd->pos);
727    else sd->module->stop(sd->video_data);
728 }
729
730 EAPI Eina_Bool
731 emotion_object_play_get(const Evas_Object *obj)
732 {
733    Smart_Data *sd;
734
735    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
736    if (!sd->video_data) return EINA_FALSE;
737
738    return sd->play;
739 }
740
741 EAPI void
742 emotion_object_position_set(Evas_Object *obj, double sec)
743 {
744    Smart_Data *sd;
745
746    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
747    DBG("sec=%f", sec);
748    if (!sd->module) return;
749    if (!sd->video_data) return;
750    if (!sd->open)
751      {
752         sd->remember_jump = sec;
753         return ;
754      }
755    sd->remember_jump = 0;
756    sd->seek_pos = sec;
757    sd->seek = 1;
758    sd->pos = sd->seek_pos;
759    if (sd->job) ecore_job_del(sd->job);
760    sd->job = ecore_job_add(_pos_set_job, obj);
761 }
762
763 EAPI double
764 emotion_object_position_get(const Evas_Object *obj)
765 {
766    Smart_Data *sd;
767
768    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0);
769    if (!sd->module) return 0.0;
770    if (!sd->video_data) return 0.0;
771    if (!sd->module->pos_get) return 0.0;
772    sd->pos = sd->module->pos_get(sd->video_data);
773    return sd->pos;
774 }
775
776 EAPI double
777 emotion_object_buffer_size_get(const Evas_Object *obj)
778 {
779    Smart_Data *sd;
780
781    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0);
782    if (!sd->module) return 1.0;
783    if (!sd->video_data) return 1.0;
784    if (!sd->module->buffer_size_get) return 1.0;
785    return sd->module->buffer_size_get(sd->video_data);
786 }
787
788 EAPI Eina_Bool
789 emotion_object_seekable_get(const Evas_Object *obj)
790 {
791    Smart_Data *sd;
792
793    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
794    if (!sd->module) return EINA_FALSE;
795    if (!sd->video_data) return EINA_FALSE;
796    return sd->module->seekable(sd->video_data);
797 }
798
799 EAPI Eina_Bool
800 emotion_object_video_handled_get(const Evas_Object *obj)
801 {
802    Smart_Data *sd;
803
804    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
805    if (!sd->module) return EINA_FALSE;
806    if (!sd->video_data) return EINA_FALSE;
807    return sd->module->video_handled(sd->video_data);
808 }
809
810 EAPI Eina_Bool
811 emotion_object_audio_handled_get(const Evas_Object *obj)
812 {
813    Smart_Data *sd;
814
815    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
816    if (!sd->module) return EINA_FALSE;
817    if (!sd->video_data) return EINA_FALSE;
818    return sd->module->audio_handled(sd->video_data);
819 }
820
821 EAPI double
822 emotion_object_play_length_get(const Evas_Object *obj)
823 {
824    Smart_Data *sd;
825
826    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0);
827    if (!sd->module) return 0.0;
828    if (!sd->video_data) return 0.0;
829    sd->len = sd->module->len_get(sd->video_data);
830    return sd->len;
831 }
832
833 EAPI void
834 emotion_object_size_get(const Evas_Object *obj, int *iw, int *ih)
835 {
836    Smart_Data *sd;
837
838    if (iw) *iw = 0;
839    if (ih) *ih = 0;
840    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
841    if (iw) *iw = sd->video.w;
842    if (ih) *ih = sd->video.h;
843 }
844
845 EAPI void
846 emotion_object_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
847 {
848    Smart_Data *sd;
849
850    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
851    evas_object_image_smooth_scale_set(sd->obj, smooth);
852 }
853
854 EAPI Eina_Bool
855 emotion_object_smooth_scale_get(const Evas_Object *obj)
856 {
857    Smart_Data *sd;
858
859    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
860    return evas_object_image_smooth_scale_get(sd->obj);
861 }
862
863 EAPI double
864 emotion_object_ratio_get(const Evas_Object *obj)
865 {
866    Smart_Data *sd;
867
868    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0);
869    if (!sd->module) return 0.0;
870    if (!sd->video_data) return 0.0;
871    return sd->ratio;
872 }
873
874 /*
875  * Send a control event to the DVD.
876  */
877 EAPI void
878 emotion_object_event_simple_send(Evas_Object *obj, Emotion_Event ev)
879 {
880    Smart_Data *sd;
881
882    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
883    if (!sd->module) return;
884    if (!sd->video_data) return;
885    sd->module->event_feed(sd->video_data, ev);
886 }
887
888 EAPI void
889 emotion_object_audio_volume_set(Evas_Object *obj, double vol)
890 {
891    Smart_Data *sd;
892
893    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
894    DBG("vol=%f", vol);
895    if (!sd->module) return;
896    if (!sd->video_data) return;
897    sd->module->audio_channel_volume_set(sd->video_data, vol);
898 }
899
900 EAPI double
901 emotion_object_audio_volume_get(const Evas_Object *obj)
902 {
903    Smart_Data *sd;
904
905    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0);
906    if (!sd->module) return 0.0;
907    if (!sd->video_data) return 0.0;
908    return sd->module->audio_channel_volume_get(sd->video_data);
909 }
910
911 EAPI void
912 emotion_object_audio_mute_set(Evas_Object *obj, Eina_Bool mute)
913 {
914    Smart_Data *sd;
915
916    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
917    DBG("mute=" FMT_UCHAR, mute);
918    if (!sd->module) return;
919    if (!sd->video_data) return;
920    sd->module->audio_channel_mute_set(sd->video_data, mute);
921 }
922
923 EAPI Eina_Bool
924 emotion_object_audio_mute_get(const Evas_Object *obj)
925 {
926    Smart_Data *sd;
927
928    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
929    if (!sd->module) return EINA_FALSE;
930    if (!sd->video_data) return EINA_FALSE;
931    return sd->module->audio_channel_mute_get(sd->video_data);
932 }
933
934 EAPI int
935 emotion_object_audio_channel_count(const Evas_Object *obj)
936 {
937    Smart_Data *sd;
938
939    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
940    if (!sd->module) return 0;
941    if (!sd->video_data) return 0;
942    return sd->module->audio_channel_count(sd->video_data);
943 }
944
945 EAPI const char *
946 emotion_object_audio_channel_name_get(const Evas_Object *obj, int channel)
947 {
948    Smart_Data *sd;
949
950    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
951    if (!sd->module) return NULL;
952    if (!sd->video_data) return NULL;
953    return sd->module->audio_channel_name_get(sd->video_data, channel);
954 }
955
956 EAPI void
957 emotion_object_audio_channel_set(Evas_Object *obj, int channel)
958 {
959    Smart_Data *sd;
960
961    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
962    DBG("channel=%d", channel);
963    if (!sd->module) return;
964    if (!sd->video_data) return;
965    sd->module->audio_channel_set(sd->video_data, channel);
966 }
967
968 EAPI int
969 emotion_object_audio_channel_get(const Evas_Object *obj)
970 {
971    Smart_Data *sd;
972
973    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
974    if (!sd->module) return 0;
975    if (!sd->video_data) return 0;
976    return sd->module->audio_channel_get(sd->video_data);
977 }
978
979 EAPI void
980 emotion_object_video_mute_set(Evas_Object *obj, Eina_Bool mute)
981 {
982    Smart_Data *sd;
983
984    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
985    DBG("mute=" FMT_UCHAR, mute);
986    if (!sd->module) return;
987    if (!sd->video_data) return;
988    sd->module->video_channel_mute_set(sd->video_data, mute);
989 }
990
991 EAPI Eina_Bool
992 emotion_object_video_mute_get(const Evas_Object *obj)
993 {
994    Smart_Data *sd;
995
996    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
997    if (!sd->module) return EINA_FALSE;
998    if (!sd->video_data) return EINA_FALSE;
999    return sd->module->video_channel_mute_get(sd->video_data);
1000 }
1001
1002 EAPI int
1003 emotion_object_video_channel_count(const Evas_Object *obj)
1004 {
1005    Smart_Data *sd;
1006
1007    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1008    if (!sd->module) return EINA_FALSE;
1009    if (!sd->video_data) return EINA_FALSE;
1010    return sd->module->video_channel_count(sd->video_data);
1011 }
1012
1013 EAPI const char *
1014 emotion_object_video_channel_name_get(const Evas_Object *obj, int channel)
1015 {
1016    Smart_Data *sd;
1017
1018    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1019    if (!sd->module) return NULL;
1020    if (!sd->video_data) return NULL;
1021    return sd->module->video_channel_name_get(sd->video_data, channel);
1022 }
1023
1024 EAPI void
1025 emotion_object_video_channel_set(Evas_Object *obj, int channel)
1026 {
1027    Smart_Data *sd;
1028
1029    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1030    DBG("channel=%d", channel);
1031    if (!sd->module) return;
1032    if (!sd->video_data) return;
1033    sd->module->video_channel_set(sd->video_data, channel);
1034 }
1035
1036 EAPI int
1037 emotion_object_video_channel_get(const Evas_Object *obj)
1038 {
1039    Smart_Data *sd;
1040
1041    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1042    if (!sd->module) return 0;
1043    if (!sd->video_data) return 0;
1044    return sd->module->video_channel_get(sd->video_data);
1045 }
1046
1047 EAPI void
1048 emotion_object_spu_mute_set(Evas_Object *obj, Eina_Bool mute)
1049 {
1050    Smart_Data *sd;
1051
1052    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1053    DBG("mute=" FMT_UCHAR, mute);
1054    if (!sd->module) return;
1055    if (!sd->video_data) return;
1056    sd->module->spu_channel_mute_set(sd->video_data, mute);
1057 }
1058
1059 EAPI Eina_Bool
1060 emotion_object_spu_mute_get(const Evas_Object *obj)
1061 {
1062    Smart_Data *sd;
1063
1064    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1065    if (!sd->module) return EINA_FALSE;
1066    if (!sd->video_data) return EINA_FALSE;
1067    return sd->module->spu_channel_mute_get(sd->video_data);
1068 }
1069
1070 EAPI int
1071 emotion_object_spu_channel_count(const Evas_Object *obj)
1072 {
1073    Smart_Data *sd;
1074
1075    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1076    if (!sd->module) return 0;
1077    if (!sd->video_data) return 0;
1078    return sd->module->spu_channel_count(sd->video_data);
1079 }
1080
1081 EAPI const char *
1082 emotion_object_spu_channel_name_get(const Evas_Object *obj, int channel)
1083 {
1084    Smart_Data *sd;
1085
1086    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1087    if (!sd->module) return NULL;
1088    if (!sd->video_data) return NULL;
1089    return sd->module->spu_channel_name_get(sd->video_data, channel);
1090 }
1091
1092 EAPI void
1093 emotion_object_spu_channel_set(Evas_Object *obj, int channel)
1094 {
1095    Smart_Data *sd;
1096
1097    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1098    DBG("channel=%d", channel);
1099    if (!sd->module) return;
1100    if (!sd->video_data) return;
1101    sd->module->spu_channel_set(sd->video_data, channel);
1102 }
1103
1104 EAPI int
1105 emotion_object_spu_channel_get(const Evas_Object *obj)
1106 {
1107    Smart_Data *sd;
1108
1109    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1110    if (!sd->module) return 0;
1111    if (!sd->video_data) return 0;
1112    return sd->module->spu_channel_get(sd->video_data);
1113 }
1114
1115 EAPI int
1116 emotion_object_chapter_count(const Evas_Object *obj)
1117 {
1118    Smart_Data *sd;
1119
1120    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1121    if (!sd->module) return 0;
1122    if (!sd->video_data) return 0;
1123    return sd->module->chapter_count(sd->video_data);
1124 }
1125
1126 EAPI void
1127 emotion_object_chapter_set(Evas_Object *obj, int chapter)
1128 {
1129    Smart_Data *sd;
1130
1131    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1132    DBG("chapter=%d", chapter);
1133    if (!sd->module) return;
1134    if (!sd->video_data) return;
1135    sd->module->chapter_set(sd->video_data, chapter);
1136 }
1137
1138 EAPI int
1139 emotion_object_chapter_get(const Evas_Object *obj)
1140 {
1141    Smart_Data *sd;
1142
1143    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1144    if (!sd->module) return 0;
1145    if (!sd->video_data) return 0;
1146    return sd->module->chapter_get(sd->video_data);
1147 }
1148
1149 EAPI const char *
1150 emotion_object_chapter_name_get(const Evas_Object *obj, int chapter)
1151 {
1152    Smart_Data *sd;
1153
1154    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1155    if (!sd->module) return NULL;
1156    if (!sd->video_data) return NULL;
1157    return sd->module->chapter_name_get(sd->video_data, chapter);
1158 }
1159
1160 EAPI void
1161 emotion_object_play_speed_set(Evas_Object *obj, double speed)
1162 {
1163    Smart_Data *sd;
1164
1165    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1166    DBG("speed=%f", speed);
1167    if (!sd->module) return;
1168    if (!sd->video_data) return;
1169    sd->module->speed_set(sd->video_data, speed);
1170 }
1171
1172 EAPI double
1173 emotion_object_play_speed_get(const Evas_Object *obj)
1174 {
1175    Smart_Data *sd;
1176
1177    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0);
1178    if (!sd->module) return 0.0;
1179    if (!sd->video_data) return 0.0;
1180    return sd->module->speed_get(sd->video_data);
1181 }
1182
1183 EAPI void
1184 emotion_object_eject(Evas_Object *obj)
1185 {
1186    Smart_Data *sd;
1187
1188    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1189    if (!sd->module) return;
1190    if (!sd->video_data) return;
1191    sd->module->eject(sd->video_data);
1192 }
1193
1194 EAPI const char *
1195 emotion_object_title_get(const Evas_Object *obj)
1196 {
1197    Smart_Data *sd;
1198
1199    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1200    return sd->title;
1201 }
1202
1203 EAPI const char *
1204 emotion_object_progress_info_get(const Evas_Object *obj)
1205 {
1206    Smart_Data *sd;
1207
1208    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1209    return sd->progress.info;
1210 }
1211
1212 EAPI double
1213 emotion_object_progress_status_get(const Evas_Object *obj)
1214 {
1215    Smart_Data *sd;
1216
1217    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0);
1218    return sd->progress.stat;
1219 }
1220
1221 EAPI const char *
1222 emotion_object_ref_file_get(const Evas_Object *obj)
1223 {
1224    Smart_Data *sd;
1225
1226    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1227    return sd->ref.file;
1228 }
1229
1230 EAPI int
1231 emotion_object_ref_num_get(const Evas_Object *obj)
1232 {
1233    Smart_Data *sd;
1234
1235    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1236    return sd->ref.num;
1237 }
1238
1239 EAPI int
1240 emotion_object_spu_button_count_get(const Evas_Object *obj)
1241 {
1242    Smart_Data *sd;
1243
1244    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1245    return sd->spu.button_num;
1246 }
1247
1248 EAPI int
1249 emotion_object_spu_button_get(const Evas_Object *obj)
1250 {
1251    Smart_Data *sd;
1252
1253    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1254    return sd->spu.button;
1255 }
1256
1257 EAPI const char *
1258 emotion_object_meta_info_get(const Evas_Object *obj, Emotion_Meta_Info meta)
1259 {
1260    Smart_Data *sd;
1261
1262    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1263    if (!sd->module) return NULL;
1264    if (!sd->video_data) return NULL;
1265    switch (meta)
1266      {
1267       case EMOTION_META_INFO_TRACK_TITLE:
1268         return sd->module->meta_get(sd->video_data, META_TRACK_TITLE);
1269       case EMOTION_META_INFO_TRACK_ARTIST:
1270         return sd->module->meta_get(sd->video_data, META_TRACK_ARTIST);
1271       case EMOTION_META_INFO_TRACK_ALBUM:
1272         return sd->module->meta_get(sd->video_data, META_TRACK_ALBUM);
1273       case EMOTION_META_INFO_TRACK_YEAR:
1274         return sd->module->meta_get(sd->video_data, META_TRACK_YEAR);
1275       case EMOTION_META_INFO_TRACK_GENRE:
1276         return sd->module->meta_get(sd->video_data, META_TRACK_GENRE);
1277       case EMOTION_META_INFO_TRACK_COMMENT:
1278         return sd->module->meta_get(sd->video_data, META_TRACK_COMMENT);
1279       case EMOTION_META_INFO_TRACK_DISC_ID:
1280         return sd->module->meta_get(sd->video_data, META_TRACK_DISCID);
1281       default:
1282         break;
1283      }
1284    return NULL;
1285 }
1286
1287 EAPI void
1288 emotion_object_vis_set(Evas_Object *obj, Emotion_Vis visualization)
1289 {
1290    Smart_Data *sd;
1291
1292    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1293    DBG("visualization=%d", visualization);
1294    if (!sd->module) return;
1295    if (!sd->video_data) return;
1296    if (!sd->module->vis_set) return;
1297    sd->module->vis_set(sd->video_data, visualization);
1298 }
1299
1300 EAPI Emotion_Vis
1301 emotion_object_vis_get(const Evas_Object *obj)
1302 {
1303    Smart_Data *sd;
1304
1305    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_VIS_NONE);
1306    if (!sd->module) return EMOTION_VIS_NONE;
1307    if (!sd->video_data) return EMOTION_VIS_NONE;
1308    if (!sd->module->vis_get) return EMOTION_VIS_NONE;
1309    return sd->module->vis_get(sd->video_data);
1310 }
1311
1312 EAPI Eina_Bool
1313 emotion_object_vis_supported(const Evas_Object *obj, Emotion_Vis visualization)
1314 {
1315    Smart_Data *sd;
1316
1317    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1318    if (!sd->module) return EINA_FALSE;
1319    if (!sd->video_data) return EINA_FALSE;
1320    if (!sd->module->vis_supported) return EINA_FALSE;
1321    return sd->module->vis_supported(sd->video_data, visualization);
1322 }
1323
1324 EAPI void
1325 emotion_object_priority_set(Evas_Object *obj, Eina_Bool priority)
1326 {
1327    Smart_Data *sd;
1328
1329    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1330    if (!sd->module) return ;
1331    if (!sd->video_data) return ;
1332    if (!sd->module->priority_set) return ;
1333    sd->module->priority_set(sd->video_data, priority);
1334 }
1335
1336 EAPI Eina_Bool
1337 emotion_object_priority_get(const Evas_Object *obj)
1338 {
1339    Smart_Data *sd;
1340
1341    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1342    if (!sd->module) return EINA_FALSE;
1343    if (!sd->video_data) return EINA_FALSE;
1344    if (!sd->module->priority_get) return EINA_FALSE;
1345    return sd->module->priority_get(sd->video_data);
1346 }
1347
1348 #ifdef HAVE_EIO
1349 static void
1350 _eio_load_xattr_cleanup(Smart_Data *sd, Eio_File *handler)
1351 {
1352    if (handler == sd->load_xattr) sd->load_xattr = NULL;
1353
1354    EINA_REFCOUNT_UNREF(sd)
1355      _smart_data_free(sd);
1356 }
1357
1358 static void
1359 _eio_load_xattr_done(void *data, Eio_File *handler, double xattr_double)
1360 {
1361    Smart_Data *sd = data;
1362
1363    emotion_object_position_set(evas_object_smart_parent_get(sd->obj), xattr_double);
1364    evas_object_smart_callback_call(evas_object_smart_parent_get(sd->obj), SIG_POSITION_LOAD_SUCCEED, NULL);
1365    _eio_load_xattr_cleanup(sd, handler);
1366 }
1367
1368 static void
1369 _eio_load_xattr_error(void *data, Eio_File *handler, int err __UNUSED__)
1370 {
1371    Smart_Data *sd = data;
1372
1373    evas_object_smart_callback_call(evas_object_smart_parent_get(sd->obj), SIG_POSITION_LOAD_FAILED, NULL);
1374    _eio_load_xattr_cleanup(sd, handler);
1375 }
1376 #endif
1377
1378 EAPI void
1379 emotion_object_last_position_load(Evas_Object *obj)
1380 {
1381    Smart_Data *sd;
1382    const char *tmp;
1383 #ifndef HAVE_EIO
1384    double xattr;
1385 #endif
1386
1387    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1388    if (!sd->file) return ;
1389
1390    if (!strncmp(sd->file, "file://", 7))
1391      tmp = sd->file + 7;
1392    else if (!strstr(sd->file, "://"))
1393      tmp = sd->file;
1394    else
1395      return ;
1396
1397 #ifdef HAVE_EIO
1398    if (sd->load_xattr) return ;
1399
1400    EINA_REFCOUNT_REF(sd);
1401
1402    sd->load_xattr = eio_file_xattr_double_get(tmp,
1403                                               "user.e.time_seek",
1404                                               _eio_load_xattr_done,
1405                                               _eio_load_xattr_error,
1406                                               sd);
1407 #else
1408    if (eina_xattr_double_get(tmp, "user.e.time_seek", &xattr))
1409      {
1410         emotion_object_position_set(obj, xattr);
1411         evas_object_smart_callback_call(obj, SIG_POSITION_LOAD_SUCCEED, NULL);
1412      }
1413    else
1414      {
1415         evas_object_smart_callback_call(obj, SIG_POSITION_LOAD_FAILED, NULL);
1416      }
1417 #endif
1418 }
1419
1420 #ifdef HAVE_EIO
1421 static void
1422 _eio_save_xattr_cleanup(Smart_Data *sd, Eio_File *handler)
1423 {
1424    if (handler == sd->save_xattr) sd->save_xattr = NULL;
1425
1426    EINA_REFCOUNT_UNREF(sd)
1427      _smart_data_free(sd);
1428 }
1429
1430 static void
1431 _eio_save_xattr_done(void *data, Eio_File *handler)
1432 {
1433    Smart_Data *sd = data;
1434
1435    evas_object_smart_callback_call(sd->obj, SIG_POSITION_SAVE_SUCCEED, NULL);
1436    _eio_save_xattr_cleanup(sd, handler);
1437 }
1438
1439 static void
1440 _eio_save_xattr_error(void *data, Eio_File *handler, int err __UNUSED__)
1441 {
1442    Smart_Data *sd = data;
1443
1444    evas_object_smart_callback_call(sd->obj, SIG_POSITION_SAVE_FAILED, NULL);
1445    _eio_save_xattr_cleanup(sd, handler);
1446 }
1447 #endif
1448
1449 EAPI void
1450 emotion_object_last_position_save(Evas_Object *obj)
1451 {
1452    Smart_Data *sd;
1453    const char *tmp;
1454
1455    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1456    if (!sd->file) return ;
1457
1458    if (!strncmp(sd->file, "file://", 7))
1459      tmp = sd->file + 7;
1460    else if (!strstr(sd->file, "://"))
1461      tmp = sd->file;
1462    else
1463      return ;
1464
1465 #ifdef HAVE_EIO
1466    if (sd->save_xattr) return ;
1467
1468    EINA_REFCOUNT_REF(sd);
1469
1470    sd->save_xattr = eio_file_xattr_double_set(tmp,
1471                                               "user.e.time_seek",
1472                                               emotion_object_position_get(obj),
1473                                               0,
1474                                               _eio_save_xattr_done,
1475                                               _eio_save_xattr_error,
1476                                               sd);
1477 #else
1478    if (eina_xattr_double_set(tmp, "user.e.time_seek", emotion_object_position_get(obj), 0))
1479      evas_object_smart_callback_call(obj, SIG_POSITION_SAVE_SUCCEED, NULL);
1480    else
1481      evas_object_smart_callback_call(obj, SIG_POSITION_SAVE_FAILED, NULL);
1482 #endif
1483 }
1484
1485 EAPI void
1486 emotion_object_suspend_set(Evas_Object *obj, Emotion_Suspend state)
1487 {
1488    Smart_Data *sd;
1489
1490    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1491    switch (state)
1492      {
1493       case EMOTION_WAKEUP:
1494          /* Restore the rendering pipeline, offset and everything back to play again (this will be called automatically by play_set) */
1495       case EMOTION_SLEEP:
1496          /* This destroy some part of the rendering pipeline */
1497       case EMOTION_DEEP_SLEEP:
1498          /* This destroy all the rendering pipeline and just keep the last rendered image (fullscreen) */
1499       case EMOTION_HIBERNATE:
1500          /* This destroy all the rendering pipeline and keep 1/4 of the last rendered image */
1501       default:
1502          break;
1503      }
1504
1505    sd->state = state;
1506 }
1507
1508 EAPI Emotion_Suspend
1509 motion_object_suspend_get(Evas_Object *obj)
1510 {
1511    Smart_Data *sd;
1512
1513    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_WAKEUP);
1514    return sd->state;
1515 }
1516
1517 /*****************************/
1518 /* Utility calls for modules */
1519 /*****************************/
1520
1521 EAPI void *
1522 _emotion_video_get(const Evas_Object *obj)
1523 {
1524    Smart_Data *sd;
1525
1526    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1527    return sd->video_data;
1528 }
1529
1530 static Eina_Bool
1531 _emotion_frame_anim(void *data)
1532 {
1533    Evas_Object *obj = data;
1534    Smart_Data *sd;
1535
1536    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
1537
1538    evas_object_image_pixels_dirty_set(sd->obj, 1);
1539    evas_object_smart_callback_call(obj, SIG_FRAME_DECODE, NULL);
1540    sd->anim = NULL;
1541
1542    return EINA_FALSE;
1543 }
1544
1545 EAPI void
1546 _emotion_frame_new(Evas_Object *obj)
1547 {
1548    Smart_Data *sd;
1549
1550    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1551
1552    if (!sd->anim) sd->anim = ecore_animator_add(_emotion_frame_anim, obj);
1553 }
1554
1555 EAPI void
1556 _emotion_video_pos_update(Evas_Object *obj, double pos, double len)
1557 {
1558    Smart_Data *sd;
1559    int npos = 0, nlen = 0;
1560
1561    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1562    if (pos != sd->pos) npos = 1;
1563    if (len != sd->len) nlen = 1;
1564    sd->pos = pos;
1565    sd->len = len;
1566    if (npos) evas_object_smart_callback_call(obj, SIG_POSITION_UPDATE, NULL);
1567    if (nlen) evas_object_smart_callback_call(obj, SIG_LENGTH_CHANGE, NULL);
1568 }
1569
1570 EAPI void
1571 _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio)
1572 {
1573    Smart_Data *sd;
1574    double tmp;
1575    int changed = 0;
1576
1577    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1578    if ((w != sd->video.w) || (h != sd->video.h))
1579      {
1580         sd->video.w = w;
1581         sd->video.h = h;
1582         _emotion_image_data_zero(sd->obj);
1583         changed = 1;
1584      }
1585    if (h > 0) tmp  = (double)w / (double)h;
1586    else tmp = 1.0;
1587    if (ratio != tmp) tmp = ratio;
1588    if (tmp != sd->ratio)
1589      {
1590         sd->ratio = tmp;
1591         changed = 1;
1592      }
1593    if (changed)
1594      {
1595         evas_object_size_hint_request_set(obj, w, h);
1596         evas_object_smart_callback_call(obj, SIG_FRAME_RESIZE, NULL);
1597         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1598         _emotion_object_aspect_border_apply(obj, sd, w, h);
1599      }
1600 }
1601
1602 EAPI void
1603 _emotion_image_reset(Evas_Object *obj)
1604 {
1605    Smart_Data *sd;
1606
1607    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1608    _emotion_image_data_zero(sd->obj);
1609 }
1610
1611 EAPI void
1612 _emotion_decode_stop(Evas_Object *obj)
1613 {
1614    Smart_Data *sd;
1615
1616    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1617    if (sd->play)
1618      {
1619         sd->play = 0;
1620         evas_object_smart_callback_call(obj, SIG_DECODE_STOP, NULL);
1621      }
1622 }
1623
1624 EAPI void
1625 _emotion_open_done(Evas_Object *obj)
1626 {
1627    Smart_Data *sd;
1628
1629    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1630    sd->open = 1;
1631
1632    if (sd->remember_jump)
1633      emotion_object_position_set(obj, sd->remember_jump);
1634    if (sd->remember_play != sd->play)
1635      emotion_object_play_set(obj, sd->remember_play);
1636    evas_object_smart_callback_call(obj, SIG_OPEN_DONE, NULL);
1637 }
1638
1639 EAPI void
1640 _emotion_playback_started(Evas_Object *obj)
1641 {
1642    evas_object_smart_callback_call(obj, SIG_PLAYBACK_STARTED, NULL);
1643 }
1644
1645 EAPI void
1646 _emotion_playback_finished(Evas_Object *obj)
1647 {
1648    evas_object_smart_callback_call(obj, SIG_PLAYBACK_FINISHED, NULL);
1649 }
1650
1651 EAPI void
1652 _emotion_audio_level_change(Evas_Object *obj)
1653 {
1654    evas_object_smart_callback_call(obj, SIG_AUDIO_LEVEL_CHANGE, NULL);
1655 }
1656
1657 EAPI void
1658 _emotion_channels_change(Evas_Object *obj)
1659 {
1660    Smart_Data *sd;
1661
1662    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1663    evas_object_smart_callback_call(obj, SIG_CHANNELS_CHANGE, NULL);
1664 }
1665
1666 EAPI void
1667 _emotion_title_set(Evas_Object *obj, char *title)
1668 {
1669    Smart_Data *sd;
1670
1671    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1672    free(sd->title);
1673    sd->title = strdup(title);
1674    evas_object_smart_callback_call(obj, SIG_TITLE_CHANGE, NULL);
1675 }
1676
1677 EAPI void
1678 _emotion_progress_set(Evas_Object *obj, char *info, double st)
1679 {
1680    Smart_Data *sd;
1681
1682    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1683    free(sd->progress.info);
1684    sd->progress.info = strdup(info);
1685    sd->progress.stat = st;
1686    evas_object_smart_callback_call(obj, SIG_PROGRESS_CHANGE, NULL);
1687 }
1688
1689 EAPI void
1690 _emotion_file_ref_set(Evas_Object *obj, const char *file, int num)
1691 {
1692    Smart_Data *sd;
1693
1694    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1695    free(sd->ref.file);
1696    sd->ref.file = strdup(file);
1697    sd->ref.num = num;
1698    evas_object_smart_callback_call(obj, SIG_REF_CHANGE, NULL);
1699 }
1700
1701 EAPI void
1702 _emotion_spu_button_num_set(Evas_Object *obj, int num)
1703 {
1704    Smart_Data *sd;
1705
1706    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1707    sd->spu.button_num = num;
1708    evas_object_smart_callback_call(obj, SIG_BUTTON_NUM_CHANGE, NULL);
1709 }
1710
1711 EAPI void
1712 _emotion_spu_button_set(Evas_Object *obj, int button)
1713 {
1714    Smart_Data *sd;
1715
1716    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1717    sd->spu.button = button;
1718    evas_object_smart_callback_call(obj, SIG_BUTTON_CHANGE, NULL);
1719 }
1720
1721 EAPI void
1722 _emotion_seek_done(Evas_Object *obj)
1723 {
1724    Smart_Data *sd;
1725
1726    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1727    if (sd->seeking)
1728      {
1729         sd->seeking = 0;
1730         if (sd->seek) emotion_object_position_set(obj, sd->seek_pos);
1731      }
1732 }
1733
1734 EAPI void
1735 _emotion_frame_refill(Evas_Object *obj, double w, double h)
1736 {
1737    Smart_Data *sd;
1738
1739    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1740    if (sd->fill.w != w || sd->fill.h != h)
1741      {
1742         Evas_Coord ow, oh;
1743
1744         evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1745         if (w <= 0 || h <= 0)
1746           {
1747              double scale_w, scale_h;
1748
1749              sd->fill.w = -1;
1750              sd->fill.h = -1;
1751
1752              scale_w = (double) ow / (double)(sd->video.w - sd->crop.l - sd->crop.r);
1753              scale_h = (double) oh / (double)(sd->video.h - sd->crop.t - sd->crop.b);
1754
1755              evas_object_image_fill_set(sd->obj, 0, 0, scale_w * sd->video.w, scale_h * sd->video.h);
1756           }
1757         else
1758           {
1759              sd->fill.w = w;
1760              sd->fill.h = h;
1761
1762              evas_object_image_fill_set(sd->obj, 0, 0, w * ow, h * oh);
1763           }
1764      }
1765 }
1766
1767 /****************************/
1768 /* Internal object routines */
1769 /****************************/
1770
1771 static void
1772 _mouse_move(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
1773 {
1774    Evas_Event_Mouse_Move *e;
1775    Smart_Data *sd;
1776    int x, y, iw, ih;
1777    Evas_Coord ox, oy, ow, oh;
1778
1779    e = event_info;
1780    sd = data;
1781    if (!sd->module) return;
1782    if (!sd->video_data) return;
1783    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1784    evas_object_image_size_get(obj, &iw, &ih);
1785    if ((iw < 1) || (ih < 1)) return;
1786    x = (((int)e->cur.canvas.x - ox) * iw) / ow;
1787    y = (((int)e->cur.canvas.y - oy) * ih) / oh;
1788    sd->module->event_mouse_move_feed(sd->video_data, x, y);
1789 }
1790
1791 static void
1792 _mouse_down(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
1793 {
1794    Evas_Event_Mouse_Down *e;
1795    Smart_Data *sd;
1796    int x, y, iw, ih;
1797    Evas_Coord ox, oy, ow, oh;
1798
1799    e = event_info;
1800    sd = data;
1801    if (!sd->module) return;
1802    if (!sd->video_data) return;
1803    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1804    evas_object_image_size_get(obj, &iw, &ih);
1805    if ((iw < 1) || (ih < 1)) return;
1806    x = (((int)e->canvas.x - ox) * iw) / ow;
1807    y = (((int)e->canvas.y - oy) * ih) / oh;
1808    sd->module->event_mouse_button_feed(sd->video_data, 1, x, y);
1809 }
1810
1811 static void
1812 _pos_set_job(void *data)
1813 {
1814    Evas_Object *obj;
1815    Smart_Data *sd;
1816
1817    obj = data;
1818    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1819    sd->job = NULL;
1820    if (sd->seeking) return;
1821    if (sd->seek)
1822      {
1823         sd->seeking = 1;
1824         sd->module->pos_set(sd->video_data, sd->seek_pos);
1825         sd->seek = 0;
1826      }
1827 }
1828
1829 /* called by evas when it needs pixels for the image object */
1830 static void
1831 _pixels_get(void *data, Evas_Object *obj)
1832 {
1833    int iw, ih, w, h;
1834    Smart_Data *sd;
1835    Emotion_Format format;
1836    unsigned char *bgra_data;
1837
1838    sd = data;
1839    sd->module->video_data_size_get(sd->video_data, &w, &h);
1840    w = (w >> 1) << 1;
1841    h = (h >> 1) << 1;
1842
1843    evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1844    evas_object_image_alpha_set(obj, 0);
1845    evas_object_image_size_set(obj, w, h);
1846    iw = w;
1847    ih = h;
1848
1849    if ((iw <= 1) || (ih <= 1))
1850      {
1851         _emotion_image_data_zero(sd->obj);
1852         evas_object_image_pixels_dirty_set(obj, 0);
1853      }
1854    else
1855      {
1856         format = sd->module->format_get(sd->video_data);
1857         if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
1858           {
1859              unsigned char **rows;
1860
1861              evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1862              rows = evas_object_image_data_get(obj, 1);
1863              if (rows)
1864                {
1865                   if (sd->module->yuv_rows_get(sd->video_data, iw, ih,
1866                                                rows,
1867                                                &rows[ih],
1868                                                &rows[ih + (ih / 2)]))
1869                     evas_object_image_data_update_add(obj, 0, 0, iw, ih);
1870                }
1871              evas_object_image_data_set(obj, rows);
1872              evas_object_image_pixels_dirty_set(obj, 0);
1873           }
1874         else if (format == EMOTION_FORMAT_BGRA)
1875           {
1876              evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_ARGB8888);
1877              if (sd->module->bgra_data_get(sd->video_data, &bgra_data))
1878                {
1879                   evas_object_image_data_set(obj, bgra_data);
1880                   evas_object_image_pixels_dirty_set(obj, 0);
1881                }
1882           }
1883      }
1884 }
1885
1886 /*******************************************/
1887 /* Internal smart object required routines */
1888 /*******************************************/
1889 #ifdef EMOTION_STATIC_BUILD_XINE
1890 Eina_Bool xine_module_init(void);
1891 #endif
1892 #ifdef EMOTION_STATIC_BUILD_GSTREAMER
1893 Eina_Bool gstreamer_module_init(void);
1894 #endif
1895 #ifdef EMOTION_STATIC_BUILD_GENERIC
1896 Eina_Bool generic_module_init(void);
1897 #endif
1898
1899 static void
1900 _smart_init(void)
1901 {
1902    char *path;
1903
1904    if (smart) return;
1905      {
1906         eina_init();
1907
1908         _log_domain = eina_log_domain_register("emotion", EINA_COLOR_LIGHTCYAN);
1909         if (_log_domain < 0)
1910           {
1911              EINA_LOG_CRIT("Could not register log domain 'emotion'");
1912              eina_shutdown();
1913              return;
1914           }
1915
1916         _backends = eina_hash_string_small_new(free);
1917
1918         _modules = eina_module_list_get(NULL, PACKAGE_LIB_DIR "/emotion/", 0, NULL, NULL);
1919
1920         path = eina_module_environment_path_get("HOME", "/.emotion/");
1921         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1922         if (path) free(path);
1923
1924         path = eina_module_environment_path_get("EMOTION_MODULES_DIR", "/emotion/");
1925         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1926         if (path) free(path);
1927
1928         path = eina_module_symbol_path_get(emotion_object_add, "/emotion/");
1929         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1930         if (path) free(path);
1931
1932         if (!_modules)
1933           {
1934              ERR("No module found!");
1935              return;
1936           }
1937
1938         eina_module_list_load(_modules);
1939
1940         /* Init static module */
1941 #ifdef EMOTION_STATIC_BUILD_XINE
1942         xine_module_init();
1943 #endif
1944 #ifdef EMOTION_STATIC_BUILD_GSTREAMER
1945         gstreamer_module_init();
1946 #endif
1947 #ifdef EMOTION_STATIC_BUILD_GENERIC
1948         generic_module_init();
1949 #endif
1950
1951         static Evas_Smart_Class sc =
1952           EVAS_SMART_CLASS_INIT_NAME_VERSION(E_OBJ_NAME);
1953         if (!sc.add)
1954           {
1955              sc.add = _smart_add;
1956              sc.del = _smart_del;
1957              sc.move = _smart_move;
1958              sc.resize = _smart_resize;
1959              sc.show = _smart_show;
1960              sc.hide = _smart_hide;
1961              sc.color_set = _smart_color_set;
1962              sc.clip_set = _smart_clip_set;
1963              sc.clip_unset = _smart_clip_unset;
1964              sc.callbacks = _smart_callbacks;
1965           }
1966         smart = evas_smart_class_new(&sc);
1967      }
1968 }
1969
1970 static void
1971 _smart_add(Evas_Object * obj)
1972 {
1973    Smart_Data *sd;
1974    unsigned int *pixel;
1975
1976    sd = calloc(1, sizeof(Smart_Data));
1977    if (!sd) return;
1978    EINA_REFCOUNT_INIT(sd);
1979    sd->state = EMOTION_WAKEUP;
1980    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
1981    sd->bg = evas_object_rectangle_add(evas_object_evas_get(obj));
1982    evas_object_color_set(sd->bg, 0, 0, 0, 0);
1983    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, sd);
1984    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, sd);
1985    evas_object_image_pixels_get_callback_set(sd->obj, _pixels_get, sd);
1986    evas_object_smart_member_add(sd->obj, obj);
1987    evas_object_smart_member_add(sd->bg, obj);
1988    evas_object_lower(sd->bg);
1989    sd->ratio = 1.0;
1990    sd->spu.button = -1;
1991    sd->fill.w = -1;
1992    sd->fill.h = -1;
1993    evas_object_image_alpha_set(sd->obj, 0);
1994    pixel = evas_object_image_data_get(sd->obj, 1);
1995    if (pixel)
1996      {
1997         *pixel = 0xff000000;
1998         evas_object_image_data_set(obj, pixel);
1999      }
2000    evas_object_smart_data_set(obj, sd);
2001
2002    ecore_init();
2003 }
2004
2005 static void
2006 _smart_del(Evas_Object * obj)
2007 {
2008    Smart_Data *sd;
2009
2010    sd = evas_object_smart_data_get(obj);
2011    if (!sd) return;
2012    EINA_REFCOUNT_UNREF(sd)
2013      _smart_data_free(sd);
2014 }
2015
2016 static void
2017 _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y)
2018 {
2019    Smart_Data *sd;
2020    int w, h;
2021
2022    sd = evas_object_smart_data_get(obj);
2023    if (!sd) return;
2024
2025    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2026    _clipper_position_size_update(obj, x, y, w, h, sd->video.w, sd->video.h);
2027    evas_object_move(sd->bg, x, y);
2028 }
2029
2030 static void
2031 _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h)
2032 {
2033    Smart_Data *sd;
2034
2035    sd = evas_object_smart_data_get(obj);
2036    if (!sd) return;
2037
2038    _emotion_object_aspect_border_apply(obj, sd, w, h);
2039    evas_object_resize(sd->bg, w, h);
2040 }
2041
2042 static void
2043 _smart_show(Evas_Object * obj)
2044 {
2045    Smart_Data *sd;
2046    int a;
2047
2048    sd = evas_object_smart_data_get(obj);
2049    if (!sd) return;
2050    evas_object_show(sd->obj);
2051    if (sd->crop.clipper)
2052      evas_object_show(sd->crop.clipper);
2053
2054    evas_object_color_get(sd->bg, NULL, NULL, NULL, &a);
2055    if (a > 0)
2056      evas_object_show(sd->bg);
2057 }
2058
2059 static void
2060 _smart_hide(Evas_Object * obj)
2061 {
2062    Smart_Data *sd;
2063
2064    sd = evas_object_smart_data_get(obj);
2065    if (!sd) return;
2066    evas_object_hide(sd->obj);
2067    if (sd->crop.clipper)
2068      evas_object_hide(sd->crop.clipper);
2069    evas_object_hide(sd->bg);
2070 }
2071
2072 static void
2073 _smart_color_set(Evas_Object * obj, int r, int g, int b, int a)
2074 {
2075    Smart_Data *sd;
2076
2077    sd = evas_object_smart_data_get(obj);
2078    if (!sd) return;
2079    evas_object_color_set(sd->obj, r, g, b, a);
2080    evas_object_color_set(sd->crop.clipper, r, g, b, a);
2081 }
2082
2083 static void
2084 _smart_clip_set(Evas_Object * obj, Evas_Object * clip)
2085 {
2086    Smart_Data *sd;
2087
2088    sd = evas_object_smart_data_get(obj);
2089    if (!sd) return;
2090    if (sd->crop.clipper)
2091      evas_object_clip_set(sd->crop.clipper, clip);
2092    else
2093      evas_object_clip_set(sd->obj, clip);
2094    evas_object_clip_set(sd->bg, clip);
2095 }
2096
2097 static void
2098 _smart_clip_unset(Evas_Object * obj)
2099 {
2100    Smart_Data *sd;
2101
2102    sd = evas_object_smart_data_get(obj);
2103    if (!sd) return;
2104    if (sd->crop.clipper)
2105      evas_object_clip_unset(sd->crop.clipper);
2106    else
2107      evas_object_clip_unset(sd->obj);
2108    evas_object_clip_unset(sd->bg);
2109 }
2110