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