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