fb32dfb85e67ff66ed90c97616334f065f1c68f8
[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 Eina_Bool
1160 emotion_object_extension_can_play_fast_get(const Evas_Object *obj, const char *file)
1161 {
1162    const Smart_Data *sd;
1163
1164    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1165    if (!sd->module) return EINA_FALSE;
1166    if (!sd->video) return EINA_FALSE;
1167    if (!sd->module->can_play_get) return EINA_FALSE;
1168    return sd->module->can_play_get(sd->video, file);
1169 }
1170
1171 EAPI Eina_Bool
1172 emotion_object_extension_can_play_get(const Evas_Object *obj, const char *file)
1173 {
1174    const char *tmp;
1175    Eina_Bool result;
1176
1177    tmp = eina_stringshare_add(file);
1178    result = emotion_object_extension_can_play_fast_get(obj, tmp);
1179    eina_stringshare_del(tmp);
1180
1181    return result;
1182 }
1183
1184 EAPI Eina_Bool
1185 emotion_object_extension_may_play_fast_get(const char *file)
1186 {
1187    if (!file) return EINA_FALSE;
1188    return _emotion_object_extension_can_play_generic_get(NULL, file);
1189 }
1190
1191 EAPI Eina_Bool
1192 emotion_object_extension_may_play_get(const char *file)
1193 {
1194    const char *tmp;
1195    Eina_Bool result;
1196
1197    if (!file) return EINA_FALSE;
1198    tmp = eina_stringshare_add(file);
1199    result = emotion_object_extension_may_play_fast_get(tmp);
1200    eina_stringshare_del(tmp);
1201
1202    return result;
1203 }
1204
1205 EAPI void
1206 emotion_object_suspend_set(Evas_Object *obj, Emotion_Suspend state)
1207 {
1208    Smart_Data *sd;
1209
1210    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1211    switch (state)
1212      {
1213       case EMOTION_WAKEUP:
1214          /* Restore the rendering pipeline, offset and everything back to play again (this will be called automatically by play_set) */
1215       case EMOTION_SLEEP:
1216          /* This destroy some part of the rendering pipeline */
1217       case EMOTION_DEEP_SLEEP:
1218          /* This destroy all the rendering pipeline and just keep the last rendered image (fullscreen) */
1219       case EMOTION_HIBERNATE:
1220          /* This destroy all the rendering pipeline and keep 1/4 of the last rendered image */
1221       default:
1222          break;
1223      }
1224
1225    sd->state = state;
1226 }
1227
1228 EAPI Emotion_Suspend
1229 motion_object_suspend_get(Evas_Object *obj)
1230 {
1231    Smart_Data *sd;
1232
1233    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_WAKEUP);
1234    return sd->state;
1235 }
1236
1237 /*****************************/
1238 /* Utility calls for modules */
1239 /*****************************/
1240
1241 struct ext_match_s
1242 {
1243    unsigned int length;
1244    const char *extension;
1245 };
1246
1247 #define MATCHING(Ext)                           \
1248   { sizeof (Ext), Ext }
1249
1250 static const struct ext_match_s matchs[] =
1251 { /* map extensions to know if it's a emotion playable content for good first-guess tries */
1252    MATCHING(".264"),
1253    MATCHING(".3g2"),
1254    MATCHING(".3gp"),
1255    MATCHING(".3gp2"),
1256    MATCHING(".3gpp"),
1257    MATCHING(".3gpp2"),
1258    MATCHING(".3p2"),
1259    MATCHING(".asf"),
1260    MATCHING(".avi"),
1261    MATCHING(".bdm"),
1262    MATCHING(".bdmv"),
1263    MATCHING(".clpi"),
1264    MATCHING(".clp"),
1265    MATCHING(".fla"),
1266    MATCHING(".flv"),
1267    MATCHING(".m1v"),
1268    MATCHING(".m2v"),
1269    MATCHING(".m2t"),
1270    MATCHING(".m4v"),
1271    MATCHING(".mkv"),
1272    MATCHING(".mov"),
1273    MATCHING(".mp2"),
1274    MATCHING(".mp2ts"),
1275    MATCHING(".mp4"),
1276    MATCHING(".mpe"),
1277    MATCHING(".mpeg"),
1278    MATCHING(".mpg"),
1279    MATCHING(".mpl"),
1280    MATCHING(".mpls"),
1281    MATCHING(".mts"),
1282    MATCHING(".mxf"),
1283    MATCHING(".nut"),
1284    MATCHING(".nuv"),
1285    MATCHING(".ogg"),
1286    MATCHING(".ogm"),
1287    MATCHING(".ogv"),
1288    MATCHING(".rm"),
1289    MATCHING(".rmj"),
1290    MATCHING(".rmm"),
1291    MATCHING(".rms"),
1292    MATCHING(".rmx"),
1293    MATCHING(".rmvb"),
1294    MATCHING(".swf"),
1295    MATCHING(".ts"),
1296    MATCHING(".weba"),
1297    MATCHING(".webm"),
1298    MATCHING(".wmv")
1299 };
1300
1301 EAPI Eina_Bool
1302 _emotion_object_extension_can_play_generic_get(const void *data __UNUSED__, const char *file)
1303 {
1304    unsigned int length;
1305    unsigned int i;
1306
1307    length = eina_stringshare_strlen(file) + 1;
1308    if (length < 5) return EINA_FALSE;
1309
1310    for (i = 0; i < sizeof (matchs) / sizeof (struct ext_match_s); ++i)
1311      {
1312         if (matchs[i].length > length) continue;
1313
1314         if (!strcasecmp(matchs[i].extension,
1315                         file + length - matchs[i].length))
1316           return EINA_TRUE;
1317      }
1318
1319    return EINA_FALSE;
1320 }
1321
1322 EAPI void *
1323 _emotion_video_get(const Evas_Object *obj)
1324 {
1325    Smart_Data *sd;
1326
1327    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1328    return sd->video;
1329 }
1330
1331 EAPI void
1332 _emotion_frame_new(Evas_Object *obj)
1333 {
1334    Smart_Data *sd;
1335
1336    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1337 //   printf("pix get set 1 %p\n", sd->obj);
1338    evas_object_image_pixels_dirty_set(sd->obj, 1);
1339    evas_object_smart_callback_call(obj, SIG_FRAME_DECODE, NULL);
1340 }
1341
1342 EAPI void
1343 _emotion_video_pos_update(Evas_Object *obj, double pos, double len)
1344 {
1345    Smart_Data *sd;
1346    int npos = 0, nlen = 0;
1347
1348    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1349    if (pos != sd->pos) npos = 1;
1350    if (len != sd->len) nlen = 1;
1351    sd->pos = pos;
1352    sd->len = len;
1353    if (npos) evas_object_smart_callback_call(obj, SIG_POSITION_UPDATE, NULL);
1354    if (nlen) evas_object_smart_callback_call(obj, SIG_LENGTH_CHANGE, NULL);
1355 }
1356
1357 EAPI void
1358 _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio)
1359 {
1360    Smart_Data *sd;
1361    int iw, ih;
1362    double tmp;
1363    int changed = 0;
1364
1365    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1366    evas_object_image_size_get(sd->obj, &iw, &ih);
1367    if ((w != iw) || (h != ih))
1368      {
1369         evas_object_image_size_set(sd->obj, w, h);
1370         _emotion_image_data_zero(sd->obj);
1371         changed = 1;
1372      }
1373    if (h > 0) tmp  = (double)w / (double)h;
1374    else tmp = 1.0;
1375    if (ratio != tmp) tmp = ratio;
1376    if (tmp != sd->ratio)
1377      {
1378         sd->ratio = tmp;
1379         changed = 1;
1380      }
1381    if (changed)
1382      {
1383         evas_object_size_hint_request_set(obj, w, h);
1384         evas_object_smart_callback_call(obj, SIG_FRAME_RESIZE, NULL);
1385      }
1386 }
1387
1388 EAPI void
1389 _emotion_decode_stop(Evas_Object *obj)
1390 {
1391    Smart_Data *sd;
1392
1393    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1394    if (sd->play)
1395      {
1396         sd->play = 0;
1397         evas_object_smart_callback_call(obj, SIG_DECODE_STOP, NULL);
1398      }
1399 }
1400
1401 EAPI void
1402 _emotion_open_done(Evas_Object *obj)
1403 {
1404    evas_object_smart_callback_call(obj, SIG_OPEN_DONE, NULL);
1405 }
1406
1407 EAPI void
1408 _emotion_playback_started(Evas_Object *obj)
1409 {
1410    evas_object_smart_callback_call(obj, SIG_PLAYBACK_STARTED, NULL);
1411 }
1412
1413 EAPI void
1414 _emotion_playback_finished(Evas_Object *obj)
1415 {
1416    evas_object_smart_callback_call(obj, SIG_PLAYBACK_FINISHED, NULL);
1417 }
1418
1419 EAPI void
1420 _emotion_audio_level_change(Evas_Object *obj)
1421 {
1422    evas_object_smart_callback_call(obj, SIG_AUDIO_LEVEL_CHANGE, NULL);
1423 }
1424
1425 EAPI void
1426 _emotion_channels_change(Evas_Object *obj)
1427 {
1428    Smart_Data *sd;
1429
1430    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1431    evas_object_smart_callback_call(obj, SIG_CHANNELS_CHANGE, NULL);
1432 }
1433
1434 EAPI void
1435 _emotion_title_set(Evas_Object *obj, char *title)
1436 {
1437    Smart_Data *sd;
1438
1439    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1440    free(sd->title);
1441    sd->title = strdup(title);
1442    evas_object_smart_callback_call(obj, SIG_TITLE_CHANGE, NULL);
1443 }
1444
1445 EAPI void
1446 _emotion_progress_set(Evas_Object *obj, char *info, double st)
1447 {
1448    Smart_Data *sd;
1449
1450    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1451    free(sd->progress.info);
1452    sd->progress.info = strdup(info);
1453    sd->progress.stat = st;
1454    evas_object_smart_callback_call(obj, SIG_PROGRESS_CHANGE, NULL);
1455 }
1456
1457 EAPI void
1458 _emotion_file_ref_set(Evas_Object *obj, const char *file, int num)
1459 {
1460    Smart_Data *sd;
1461
1462    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1463    free(sd->ref.file);
1464    sd->ref.file = strdup(file);
1465    sd->ref.num = num;
1466    evas_object_smart_callback_call(obj, SIG_REF_CHANGE, NULL);
1467 }
1468
1469 EAPI void
1470 _emotion_spu_button_num_set(Evas_Object *obj, int num)
1471 {
1472    Smart_Data *sd;
1473
1474    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1475    sd->spu.button_num = num;
1476    evas_object_smart_callback_call(obj, SIG_BUTTON_NUM_CHANGE, NULL);
1477 }
1478
1479 EAPI void
1480 _emotion_spu_button_set(Evas_Object *obj, int button)
1481 {
1482    Smart_Data *sd;
1483
1484    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1485    sd->spu.button = button;
1486    evas_object_smart_callback_call(obj, SIG_BUTTON_CHANGE, NULL);
1487 }
1488
1489 EAPI void
1490 _emotion_seek_done(Evas_Object *obj)
1491 {
1492    Smart_Data *sd;
1493
1494    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1495    if (sd->seeking)
1496      {
1497         sd->seeking = 0;
1498         if (sd->seek) emotion_object_position_set(obj, sd->seek_pos);
1499      }
1500 }
1501
1502
1503
1504 /****************************/
1505 /* Internal object routines */
1506 /****************************/
1507
1508 static void
1509 _mouse_move(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
1510 {
1511    Evas_Event_Mouse_Move *e;
1512    Smart_Data *sd;
1513    int x, y, iw, ih;
1514    Evas_Coord ox, oy, ow, oh;
1515
1516    e = event_info;
1517    sd = data;
1518    if (!sd->module) return;
1519    if (!sd->video) return;
1520    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1521    evas_object_image_size_get(obj, &iw, &ih);
1522    if ((iw < 1) || (ih < 1)) return;
1523    x = (((int)e->cur.canvas.x - ox) * iw) / ow;
1524    y = (((int)e->cur.canvas.y - oy) * ih) / oh;
1525    sd->module->event_mouse_move_feed(sd->video, x, y);
1526 }
1527
1528 static void
1529 _mouse_down(void *data, Evas *ev __UNUSED__, Evas_Object *obj, void *event_info)
1530 {
1531    Evas_Event_Mouse_Down *e;
1532    Smart_Data *sd;
1533    int x, y, iw, ih;
1534    Evas_Coord ox, oy, ow, oh;
1535
1536    e = event_info;
1537    sd = data;
1538    if (!sd->module) return;
1539    if (!sd->video) return;
1540    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1541    evas_object_image_size_get(obj, &iw, &ih);
1542    if ((iw < 1) || (ih < 1)) return;
1543    x = (((int)e->canvas.x - ox) * iw) / ow;
1544    y = (((int)e->canvas.y - oy) * ih) / oh;
1545    sd->module->event_mouse_button_feed(sd->video, 1, x, y);
1546 }
1547
1548 static void
1549 _pos_set_job(void *data)
1550 {
1551    Evas_Object *obj;
1552    Smart_Data *sd;
1553
1554    obj = data;
1555    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1556    sd->job = NULL;
1557    if (sd->seeking) return;
1558    if (sd->seek)
1559      {
1560         sd->seeking = 1;
1561         sd->module->pos_set(sd->video, sd->seek_pos);
1562         sd->seek = 0;
1563      }
1564 }
1565
1566 /* called by evas when it needs pixels for the image object */
1567 static void
1568 _pixels_get(void *data, Evas_Object *obj)
1569 {
1570    int iw, ih, w, h;
1571    Smart_Data *sd;
1572    Emotion_Format format;
1573    unsigned char *bgra_data;
1574
1575    sd = data;
1576    evas_object_image_size_get(obj, &iw, &ih);
1577    sd->module->video_data_size_get(sd->video, &w, &h);
1578    w = (w >> 1) << 1;
1579    h = (h >> 1) << 1;
1580    if ((w != iw) || (h != ih))
1581      {
1582         evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1583         evas_object_image_alpha_set(obj, 0);
1584         evas_object_image_size_set(obj, w, h);
1585         _emotion_image_data_zero(sd->obj);
1586         iw = w;
1587         ih = h;
1588      }
1589    if ((iw < 1) || (ih < 1))
1590      {
1591 //      printf("pix get set 0 (1)\n");
1592         evas_object_image_pixels_dirty_set(obj, 0);
1593      }
1594    else
1595      {
1596         format = sd->module->format_get(sd->video);
1597         if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
1598           {
1599              unsigned char **rows;
1600
1601              evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1602              rows = evas_object_image_data_get(obj, 1);
1603              if (rows)
1604                {
1605                   if (sd->module->yuv_rows_get(sd->video, iw, ih,
1606                                                rows,
1607                                                &rows[ih],
1608                                                &rows[ih + (ih / 2)]))
1609                     evas_object_image_data_update_add(obj, 0, 0, iw, ih);
1610                }
1611              evas_object_image_data_set(obj, rows);
1612 //           printf("pix get set 0 (2)\n");
1613              evas_object_image_pixels_dirty_set(obj, 0);
1614           }
1615         else if (format == EMOTION_FORMAT_BGRA)
1616           {
1617              if (sd->module->bgra_data_get(sd->video, &bgra_data))
1618                {
1619                   evas_object_image_data_set(obj, bgra_data);
1620 //                printf("pix get set 0 (3)\n");
1621                   evas_object_image_pixels_dirty_set(obj, 0);
1622                }
1623           }
1624      }
1625 // no need for this because on any new frame decode info from the decoder
1626 // module, the previous "current frame" is released (done) for us anyway
1627 //   sd->module->frame_done(sd->video);
1628
1629 /*
1630    evas_object_image_size_get(obj, &iw, &ih);
1631    sd->module->video_data_size_get(sd->video, &w, &h);
1632    if ((w != iw) || (h != ih))
1633      {
1634         evas_object_image_size_set(obj, w, h);
1635         _emotion_image_data_zero(sd->obj);
1636         iw = w;
1637         ih = h;
1638      }
1639    format = sd->module->format_get(sd->video);
1640    if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
1641      {
1642         unsigned char **rows;
1643         Evas_Pixel_Import_Source ps;
1644
1645         ps.format = EVAS_PIXEL_FORMAT_YUV420P_601;
1646         ps.w = iw;
1647         ps.h = ih;
1648
1649         ps.rows = malloc(ps.h * 2 * sizeof(void *));
1650         if (!ps.rows)
1651           {
1652              sd->module->frame_done(sd->video);
1653              return;
1654           }
1655
1656         rows = (unsigned char **)ps.rows;
1657
1658         if (sd->module->yuv_rows_get(sd->video, iw, ih,
1659                                      rows,
1660                                      &rows[ps.h],
1661                                      &rows[ps.h + (ps.h / 2)]))
1662           evas_object_image_pixels_import(obj, &ps);
1663         evas_object_image_pixels_dirty_set(obj, 0);
1664         free(ps.rows);
1665      }
1666    else if (format == EMOTION_FORMAT_BGRA)
1667      {
1668         if (sd->module->bgra_data_get(sd->video, &bgra_data));
1669           {
1670              evas_object_image_data_set(obj, bgra_data);
1671              evas_object_image_pixels_dirty_set(obj, 0);
1672           }
1673      }
1674    sd->module->frame_done(sd->video);
1675  */
1676 }
1677
1678 /*******************************************/
1679 /* Internal smart object required routines */
1680 /*******************************************/
1681 #ifdef EMOTION_STATIC_BUILD_XINE
1682 Eina_Bool xine_module_init(void);
1683 #endif
1684 #ifdef EMOTION_STATIC_BUILD_VLC
1685 Eina_Bool vlc_module_init(void);
1686 #endif
1687 #ifdef EMOTION_STATIC_BUILD_GSTREAMER
1688 Eina_Bool gstreamer_module_init(void);
1689 #endif
1690
1691 static void
1692 _smart_init(void)
1693 {
1694    char *path;
1695
1696    if (smart) return;
1697      {
1698         eina_init();
1699
1700         _log_domain = eina_log_domain_register("emotion", EINA_COLOR_LIGHTCYAN);
1701         if (_log_domain < 0)
1702           {
1703              EINA_LOG_CRIT("Could not register log domain 'emotion'");
1704              eina_shutdown();
1705              return;
1706           }
1707
1708         _backends = eina_hash_string_small_new(free);
1709
1710         _modules = eina_module_list_get(NULL, PACKAGE_LIB_DIR "/emotion/", 0, NULL, NULL);
1711
1712         path = eina_module_environment_path_get("HOME", "/.emotion/");
1713         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1714         if (path) free(path);
1715
1716         path = eina_module_environment_path_get("EMOTION_MODULES_DIR", "/emotion/");
1717         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1718         if (path) free(path);
1719
1720         path = eina_module_symbol_path_get(emotion_object_add, "/emotion/");
1721         _modules = eina_module_list_get(_modules, path, 0, NULL, NULL);
1722         if (path) free(path);
1723
1724         if (!_modules)
1725           {
1726              ERR("No module found!");
1727              return;
1728           }
1729
1730         eina_module_list_load(_modules);
1731
1732         /* Init static module */
1733 #ifdef EMOTION_STATIC_BUILD_XINE
1734         xine_module_init();
1735 #endif
1736 #ifdef EMOTION_STATIC_BUILD_VLC
1737         vlc_module_init();
1738 #endif
1739 #ifdef EMOTION_STATIC_BUILD_GSTREAMER
1740         gstreamer_module_init();
1741 #endif
1742
1743         static Evas_Smart_Class sc =
1744           EVAS_SMART_CLASS_INIT_NAME_VERSION(E_OBJ_NAME);
1745         if (!sc.add)
1746           {
1747              sc.add = _smart_add;
1748              sc.del = _smart_del;
1749              sc.move = _smart_move;
1750              sc.resize = _smart_resize;
1751              sc.show = _smart_show;
1752              sc.hide = _smart_hide;
1753              sc.color_set = _smart_color_set;
1754              sc.clip_set = _smart_clip_set;
1755              sc.clip_unset = _smart_clip_unset;
1756              sc.callbacks = _smart_callbacks;
1757           }
1758         smart = evas_smart_class_new(&sc);
1759      }
1760 }
1761
1762 static void
1763 _smart_add(Evas_Object * obj)
1764 {
1765    Smart_Data *sd;
1766    unsigned int *pixel;
1767
1768    sd = calloc(1, sizeof(Smart_Data));
1769    if (!sd) return;
1770    EINA_REFCOUNT_INIT(sd);
1771    sd->state = EMOTION_WAKEUP;
1772    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
1773    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, sd);
1774    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, sd);
1775    evas_object_image_pixels_get_callback_set(sd->obj, _pixels_get, sd);
1776    evas_object_smart_member_add(sd->obj, obj);
1777    sd->ratio = 1.0;
1778    sd->spu.button = -1;
1779    evas_object_image_alpha_set(sd->obj, 0);
1780    pixel = evas_object_image_data_get(sd->obj, 1);
1781    if (pixel)
1782      {
1783         *pixel = 0xff000000;
1784         evas_object_image_data_set(obj, pixel);
1785      }
1786    evas_object_smart_data_set(obj, sd);
1787
1788    ecore_init();
1789 }
1790
1791 static void
1792 _smart_del(Evas_Object * obj)
1793 {
1794    Smart_Data *sd;
1795
1796    sd = evas_object_smart_data_get(obj);
1797    if (!sd) return;
1798    EINA_REFCOUNT_UNREF(sd)
1799      _smart_data_free(sd);
1800 }
1801
1802 static void
1803 _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y)
1804 {
1805    Smart_Data *sd;
1806
1807    sd = evas_object_smart_data_get(obj);
1808    if (!sd) return;
1809    evas_object_move(sd->obj, x, y);
1810 }
1811
1812 static void
1813 _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h)
1814 {
1815    Smart_Data *sd;
1816
1817    sd = evas_object_smart_data_get(obj);
1818    if (!sd) return;
1819    evas_object_image_fill_set(sd->obj, 0, 0, w, h);
1820    evas_object_resize(sd->obj, w, h);
1821 }
1822
1823 static void
1824 _smart_show(Evas_Object * obj)
1825 {
1826    Smart_Data *sd;
1827
1828    sd = evas_object_smart_data_get(obj);
1829    if (!sd) return;
1830    evas_object_show(sd->obj);
1831
1832 }
1833
1834 static void
1835 _smart_hide(Evas_Object * obj)
1836 {
1837    Smart_Data *sd;
1838
1839    sd = evas_object_smart_data_get(obj);
1840    if (!sd) return;
1841    evas_object_hide(sd->obj);
1842 }
1843
1844 static void
1845 _smart_color_set(Evas_Object * obj, int r, int g, int b, int a)
1846 {
1847    Smart_Data *sd;
1848
1849    sd = evas_object_smart_data_get(obj);
1850    if (!sd) return;
1851    evas_object_color_set(sd->obj, r, g, b, a);
1852 }
1853
1854 static void
1855 _smart_clip_set(Evas_Object * obj, Evas_Object * clip)
1856 {
1857    Smart_Data *sd;
1858
1859    sd = evas_object_smart_data_get(obj);
1860    if (!sd) return;
1861    evas_object_clip_set(sd->obj, clip);
1862 }
1863
1864 static void
1865 _smart_clip_unset(Evas_Object * obj)
1866 {
1867    Smart_Data *sd;
1868
1869    sd = evas_object_smart_data_get(obj);
1870    if (!sd) return;
1871    evas_object_clip_unset(sd->obj);
1872 }
1873
1874 EAPI Evas_Object *
1875 _emotion_image_get(const Evas_Object *obj)
1876 {
1877    Smart_Data *sd;
1878
1879    sd = evas_object_smart_data_get(obj);
1880    if (!sd) return NULL;
1881    return sd->obj;
1882 }