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