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