faaaa7fd5edc76f6fd6ea5578010013d5fcf8270
[profile/ivi/emotion.git] / src / modules / gstreamer / emotion_gstreamer.c
1 #include <unistd.h>
2 #include <fcntl.h>
3
4 #include <Eina.h>
5
6 #include "emotion_private.h"
7 #include "emotion_gstreamer.h"
8 #include "Emotion.h"
9
10 int _emotion_gstreamer_log_domain = -1;
11
12 /* Callbacks to get the eos */
13 static Eina_Bool  _eos_timer_fct   (void *data);
14 static void _for_each_tag    (GstTagList const* list, gchar const* tag, void *data);
15 static void _free_metadata   (Emotion_Gstreamer_Metadata *m);
16
17 /* Interface */
18
19 static unsigned char  em_init                     (Evas_Object     *obj,
20                                                    void           **emotion_video,
21                                                    Emotion_Module_Options *opt);
22
23 static int            em_shutdown                 (void           *video);
24
25 static unsigned char  em_file_open                (const char     *file,
26                                                    Evas_Object     *obj,
27                                                    void            *video);
28
29 static void           em_file_close               (void            *video);
30
31 static void           em_play                     (void            *video,
32                                                    double           pos);
33
34 static void           em_stop                     (void            *video);
35
36 static void           em_size_get                 (void            *video,
37                                                    int             *width,
38                                                    int             *height);
39
40 static void           em_pos_set                  (void            *video,
41                                                    double           pos);
42
43
44 static double         em_len_get                  (void            *video);
45
46 static int            em_fps_num_get              (void            *video);
47
48 static int            em_fps_den_get              (void            *video);
49
50 static double         em_fps_get                  (void            *video);
51
52 static double         em_pos_get                  (void            *video);
53
54 static void           em_vis_set                  (void            *video,
55                                                    Emotion_Vis      vis);
56
57 static Emotion_Vis    em_vis_get                  (void            *video);
58
59 static Eina_Bool      em_vis_supported            (void            *video,
60                                                    Emotion_Vis      vis);
61
62 static double         em_ratio_get                (void            *video);
63
64 static int            em_video_handled            (void            *video);
65
66 static int            em_audio_handled            (void            *video);
67
68 static int            em_seekable                 (void            *video);
69
70 static void           em_frame_done               (void            *video);
71
72 static Emotion_Format em_format_get               (void            *video);
73
74 static void           em_video_data_size_get      (void            *video,
75                                                    int             *w,
76                                                    int             *h);
77
78 static int            em_yuv_rows_get             (void            *video,
79                                                    int              w,
80                                                    int              h,
81                                                    unsigned char  **yrows,
82                                                    unsigned char  **urows,
83                                                    unsigned char  **vrows);
84
85 static int            em_bgra_data_get            (void            *video,
86                                                    unsigned char  **bgra_data);
87
88 static void           em_event_feed               (void            *video,
89                                                    int              event);
90
91 static void           em_event_mouse_button_feed  (void            *video,
92                                                    int              button,
93                                                    int              x,
94                                                    int              y);
95
96 static void           em_event_mouse_move_feed    (void            *video,
97                                                    int              x,
98                                                    int              y);
99
100 static int            em_video_channel_count      (void             *video);
101
102 static void           em_video_channel_set        (void             *video,
103                                                    int               channel);
104
105 static int            em_video_channel_get        (void             *video);
106
107 static const char    *em_video_channel_name_get   (void             *video,
108                                                    int               channel);
109
110 static void           em_video_channel_mute_set   (void             *video,
111                                                    int               mute);
112
113 static int            em_video_channel_mute_get   (void             *video);
114
115 static int            em_audio_channel_count      (void             *video);
116
117 static void           em_audio_channel_set        (void             *video,
118                                                    int               channel);
119
120 static int            em_audio_channel_get        (void             *video);
121
122 static const char    *em_audio_channel_name_get   (void             *video,
123                                                    int               channel);
124
125 static void           em_audio_channel_mute_set   (void             *video,
126                                                    int               mute);
127
128 static int            em_audio_channel_mute_get   (void             *video);
129
130 static void           em_audio_channel_volume_set (void             *video,
131                                                    double             vol);
132
133 static double         em_audio_channel_volume_get (void             *video);
134
135 static int            em_spu_channel_count        (void             *video);
136
137 static void           em_spu_channel_set          (void             *video,
138                                                    int               channel);
139
140 static int            em_spu_channel_get          (void             *video);
141
142 static const char    *em_spu_channel_name_get     (void             *video,
143                                                    int               channel);
144
145 static void           em_spu_channel_mute_set     (void             *video,
146                                                    int               mute);
147
148 static int            em_spu_channel_mute_get     (void             *video);
149
150 static int            em_chapter_count            (void             *video);
151
152 static void           em_chapter_set              (void             *video,
153                                                    int               chapter);
154
155 static int            em_chapter_get              (void             *video);
156
157 static const char    *em_chapter_name_get         (void             *video,
158                                                    int               chapter);
159
160 static void           em_speed_set                (void             *video,
161                                                    double            speed);
162
163 static double         em_speed_get                (void             *video);
164
165 static int            em_eject                    (void             *video);
166
167 static const char    *em_meta_get                 (void             *video,
168                                                    int               meta);
169
170 /* Module interface */
171
172 static Emotion_Video_Module em_module =
173 {
174    em_init, /* init */
175    em_shutdown, /* shutdown */
176    em_file_open, /* file_open */
177    em_file_close, /* file_close */
178    em_play, /* play */
179    em_stop, /* stop */
180    em_size_get, /* size_get */
181    em_pos_set, /* pos_set */
182    em_len_get, /* len_get */
183    em_fps_num_get, /* fps_num_get */
184    em_fps_den_get, /* fps_den_get */
185    em_fps_get, /* fps_get */
186    em_pos_get, /* pos_get */
187    em_vis_set, /* vis_set */
188    em_vis_get, /* vis_get */
189    em_vis_supported, /* vis_supported */
190    em_ratio_get, /* ratio_get */
191    em_video_handled, /* video_handled */
192    em_audio_handled, /* audio_handled */
193    em_seekable, /* seekable */
194    em_frame_done, /* frame_done */
195    em_format_get, /* format_get */
196    em_video_data_size_get, /* video_data_size_get */
197    em_yuv_rows_get, /* yuv_rows_get */
198    em_bgra_data_get, /* bgra_data_get */
199    em_event_feed, /* event_feed */
200    em_event_mouse_button_feed, /* event_mouse_button_feed */
201    em_event_mouse_move_feed, /* event_mouse_move_feed */
202    em_video_channel_count, /* video_channel_count */
203    em_video_channel_set, /* video_channel_set */
204    em_video_channel_get, /* video_channel_get */
205    em_video_channel_name_get, /* video_channel_name_get */
206    em_video_channel_mute_set, /* video_channel_mute_set */
207    em_video_channel_mute_get, /* video_channel_mute_get */
208    em_audio_channel_count, /* audio_channel_count */
209    em_audio_channel_set, /* audio_channel_set */
210    em_audio_channel_get, /* audio_channel_get */
211    em_audio_channel_name_get, /* audio_channel_name_get */
212    em_audio_channel_mute_set, /* audio_channel_mute_set */
213    em_audio_channel_mute_get, /* audio_channel_mute_get */
214    em_audio_channel_volume_set, /* audio_channel_volume_set */
215    em_audio_channel_volume_get, /* audio_channel_volume_get */
216    em_spu_channel_count, /* spu_channel_count */
217    em_spu_channel_set, /* spu_channel_set */
218    em_spu_channel_get, /* spu_channel_get */
219    em_spu_channel_name_get, /* spu_channel_name_get */
220    em_spu_channel_mute_set, /* spu_channel_mute_set */
221    em_spu_channel_mute_get, /* spu_channel_mute_get */
222    em_chapter_count, /* chapter_count */
223    em_chapter_set, /* chapter_set */
224    em_chapter_get, /* chapter_get */
225    em_chapter_name_get, /* chapter_name_get */
226    em_speed_set, /* speed_set */
227    em_speed_get, /* speed_get */
228    em_eject, /* eject */
229    em_meta_get, /* meta_get */
230    _emotion_object_extension_can_play_generic_get, /* play_get */
231    NULL /* handle */
232 };
233
234 static Emotion_Video_Stream *
235 emotion_video_stream_new(Emotion_Gstreamer_Video *ev)
236 {
237    Emotion_Video_Stream *vstream;
238
239    if (!ev) return NULL;
240
241    vstream = (Emotion_Video_Stream *)calloc(1, sizeof(Emotion_Video_Stream));
242    if (!vstream) return NULL;
243
244    ev->video_streams = eina_list_append(ev->video_streams, vstream);
245    if (eina_error_get())
246      {
247         free(vstream);
248         return NULL;
249      }
250    return vstream;
251 }
252
253 static void
254 emotion_video_stream_free(Emotion_Gstreamer_Video *ev, Emotion_Video_Stream *vstream)
255 {
256    if (!ev || !vstream) return;
257
258    ev->video_streams = eina_list_remove(ev->video_streams, vstream);
259         free(vstream);
260 }
261
262 static const char *
263 emotion_visualization_element_name_get(Emotion_Vis visualisation)
264 {
265    switch (visualisation)
266      {
267       case EMOTION_VIS_NONE:
268          return NULL;
269       case EMOTION_VIS_GOOM:
270          return "goom";
271       case EMOTION_VIS_LIBVISUAL_BUMPSCOPE:
272          return "libvisual_bumpscope";
273       case EMOTION_VIS_LIBVISUAL_CORONA:
274          return "libvisual_corona";
275       case EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES:
276          return "libvisual_dancingparticles";
277       case EMOTION_VIS_LIBVISUAL_GDKPIXBUF:
278          return "libvisual_gdkpixbuf";
279       case EMOTION_VIS_LIBVISUAL_G_FORCE:
280          return "libvisual_G-Force";
281       case EMOTION_VIS_LIBVISUAL_GOOM:
282          return "libvisual_goom";
283       case EMOTION_VIS_LIBVISUAL_INFINITE:
284          return "libvisual_infinite";
285       case EMOTION_VIS_LIBVISUAL_JAKDAW:
286          return "libvisual_jakdaw";
287       case EMOTION_VIS_LIBVISUAL_JESS:
288          return "libvisual_jess";
289       case EMOTION_VIS_LIBVISUAL_LV_ANALYSER:
290          return "libvisual_lv_analyzer";
291       case EMOTION_VIS_LIBVISUAL_LV_FLOWER:
292          return "libvisual_lv_flower";
293       case EMOTION_VIS_LIBVISUAL_LV_GLTEST:
294          return "libvisual_lv_gltest";
295       case EMOTION_VIS_LIBVISUAL_LV_SCOPE:
296          return "libvisual_lv_scope";
297       case EMOTION_VIS_LIBVISUAL_MADSPIN:
298          return "libvisual_madspin";
299       case EMOTION_VIS_LIBVISUAL_NEBULUS:
300          return "libvisual_nebulus";
301       case EMOTION_VIS_LIBVISUAL_OINKSIE:
302          return "libvisual_oinksie";
303       case EMOTION_VIS_LIBVISUAL_PLASMA:
304          return "libvisual_plazma";
305       default:
306          return "goom";
307      }
308 }
309
310 static unsigned char
311 em_init(Evas_Object            *obj,
312         void                  **emotion_video,
313         Emotion_Module_Options *opt __UNUSED__)
314 {
315    Emotion_Gstreamer_Video *ev;
316    GError                  *error;
317
318    if (!emotion_video)
319      return 0;
320
321    ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
322    if (!ev) return 0;
323
324    ev->obj = obj;
325
326    /* Initialization of gstreamer */
327    if (!gst_init_check(NULL, NULL, &error))
328      goto failure;
329
330    /* Default values */
331    ev->ratio = 1.0;
332    ev->vis = EMOTION_VIS_NONE;
333    ev->volume = 0.8;
334
335    *emotion_video = ev;
336
337    return 1;
338
339 failure:
340    free(ev);
341
342    return 0;
343 }
344
345 static int
346 em_shutdown(void *video)
347 {
348    Emotion_Gstreamer_Video *ev;
349    Emotion_Audio_Stream *astream;
350    Emotion_Video_Stream *vstream;
351
352    ev = (Emotion_Gstreamer_Video *)video;
353    if (!ev)
354      return 0;
355
356    if (ev->pipeline)
357      {
358        gst_element_set_state(ev->pipeline, GST_STATE_NULL);
359        gst_object_unref(ev->pipeline);
360        ev->pipeline = NULL;
361      }
362
363    EINA_LIST_FREE(ev->audio_streams, astream)
364      free(astream);
365    EINA_LIST_FREE(ev->video_streams, vstream)
366      free(vstream);
367
368    free(ev);
369
370    return 1;
371 }
372
373
374 static unsigned char
375 em_file_open(const char   *file,
376              Evas_Object  *obj,
377              void         *video)
378 {
379    Emotion_Gstreamer_Video *ev;
380    Eina_Strbuf *sbuf = NULL;
381    const char *uri;
382    int i;
383
384    ev = (Emotion_Gstreamer_Video *)video;
385
386    if (!file) return EINA_FALSE;
387    if (strstr(file, "://") == NULL)
388      {
389         sbuf = eina_strbuf_new();
390         eina_strbuf_append(sbuf, "file://");
391         if (strncmp(file, "./", 2) == 0)
392           file += 2;
393         if (strstr(file, ":/") != NULL)
394           { /* We absolutely need file:///C:/ under Windows, so adding it here */
395              eina_strbuf_append(sbuf, "/");
396           }
397         else if (*file != '/')
398           {
399              char tmp[PATH_MAX];
400
401              if (getcwd(tmp, PATH_MAX))
402                {
403                   eina_strbuf_append(sbuf, tmp);
404                   eina_strbuf_append(sbuf, "/");
405                }
406           }
407         eina_strbuf_append(sbuf, file);
408      }
409
410    uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
411    DBG("setting file to '%s'", uri);
412    ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
413    if (sbuf) eina_strbuf_free(sbuf);
414
415    if (!ev->pipeline)
416      return EINA_FALSE;
417
418    ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
419    if (!ev->eos_bus)
420      {
421         ERR("could not get the bus");
422         return EINA_FALSE;
423      }
424
425    /* Evas Object */
426    ev->obj = obj;
427
428    ev->position = 0.0;
429
430    g_object_get(G_OBJECT(ev->pipeline),
431                 "n-audio", &ev->audio_stream_nbr,
432                 "n-video", &ev->video_stream_nbr,
433                 NULL);
434
435    if ((ev->video_stream_nbr == 0) && (ev->audio_stream_nbr == 0))
436      {
437         ERR("No audio nor video stream found");
438         gst_object_unref(ev->pipeline);
439         ev->pipeline = NULL;
440         return EINA_FALSE;
441      }
442
443    /* video stream */
444
445    for (i = 0; i < ev->video_stream_nbr; i++)
446      {
447         Emotion_Video_Stream *vstream;
448         GstPad       *pad;
449         GstCaps      *caps;
450         GstStructure *structure;
451         GstQuery     *query;
452         const GValue *val;
453         gchar        *str;
454
455         gdouble length_time = 0.0;
456         gint width;
457         gint height;
458         gint fps_num;
459         gint fps_den;
460         guint32 fourcc = 0;
461
462         g_signal_emit_by_name(ev->pipeline, "get-video-pad", i, &pad);
463         if (!pad)
464           continue;
465
466         caps = gst_pad_get_negotiated_caps(pad);
467         if (!caps)
468           goto unref_pad_v;
469         structure = gst_caps_get_structure(caps, 0);
470         str = gst_caps_to_string(caps);
471
472         if (!gst_structure_get_int(structure, "width", &width))
473           goto unref_caps_v;
474         if (!gst_structure_get_int(structure, "height", &height))
475           goto unref_caps_v;
476         if (!gst_structure_get_fraction(structure, "framerate", &fps_num, &fps_den))
477           goto unref_caps_v;
478
479         if (g_str_has_prefix(str, "video/x-raw-yuv"))
480           {
481              val = gst_structure_get_value(structure, "format");
482              fourcc = gst_value_get_fourcc(val);
483           }
484         else if (g_str_has_prefix(str, "video/x-raw-rgb"))
485           fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
486         else
487           goto unref_caps_v;
488
489         query = gst_query_new_duration(GST_FORMAT_TIME);
490         if (gst_pad_peer_query(pad, query))
491           {
492              gint64 t;
493
494              gst_query_parse_duration(query, NULL, &t);
495              length_time = (double)t / (double)GST_SECOND;
496           }
497         else
498           goto unref_query_v;
499
500         vstream = emotion_video_stream_new(ev);
501         if (!vstream) goto unref_query_v;
502
503         vstream->length_time = length_time;
504         vstream->width = width;
505         vstream->height = height;
506         vstream->fps_num = fps_num;
507         vstream->fps_den = fps_den;
508         vstream->fourcc = fourcc;
509         vstream->index = i;
510
511      unref_query_v:
512         gst_query_unref(query);
513      unref_caps_v:
514         gst_caps_unref(caps);
515      unref_pad_v:
516         gst_object_unref(pad);
517      }
518
519    /* Audio streams */
520
521    for (i = 0; i < ev->audio_stream_nbr; i++)
522      {
523         Emotion_Audio_Stream *astream;
524         GstPad       *pad;
525         GstCaps      *caps;
526         GstStructure *structure;
527         GstQuery     *query;
528
529         gdouble length_time = 0.0;
530         gint channels;
531         gint samplerate;
532
533         g_signal_emit_by_name(ev->pipeline, "get-audio-pad", i, &pad);
534         if (!pad)
535           continue;
536
537         caps = gst_pad_get_negotiated_caps(pad);
538         if (!caps)
539           goto unref_pad_a;
540         structure = gst_caps_get_structure(caps, 0);
541
542         if (!gst_structure_get_int(structure, "channels", &channels))
543           goto unref_caps_a;
544         if (!gst_structure_get_int(structure, "rate", &samplerate))
545           goto unref_caps_a;
546
547         query = gst_query_new_duration(GST_FORMAT_TIME);
548         if (gst_pad_peer_query(pad, query))
549           {
550              gint64 t;
551
552              gst_query_parse_duration(query, NULL, &t);
553              length_time = (double)t / (double)GST_SECOND;
554           }
555         else
556           goto unref_query_a;
557
558         astream = calloc(1, sizeof(Emotion_Audio_Stream));
559         if (!astream) continue;
560         ev->audio_streams = eina_list_append(ev->audio_streams, astream);
561         if (eina_error_get())
562           {
563              free(astream);
564              continue;
565           }
566
567         astream->length_time = length_time;
568         astream->channels = channels;
569         astream->samplerate = samplerate;
570
571      unref_query_a:
572         gst_query_unref(query);
573      unref_caps_a:
574         gst_caps_unref(caps);
575      unref_pad_a:
576         gst_object_unref(pad);
577      }
578
579    /* Visualization sink */
580
581    if (ev->video_stream_nbr == 0)
582      {
583         GstElement *vis = NULL;
584         Emotion_Video_Stream *vstream;
585         Emotion_Audio_Stream *astream;
586         gint flags;
587         const char *vis_name;
588
589         if (!(vis_name = emotion_visualization_element_name_get(ev->vis)))
590           {
591              ERR("pb vis name %d\n", ev->vis);
592              goto finalize;
593           }
594
595         astream = eina_list_data_get(ev->audio_streams);
596
597         vis = gst_element_factory_make(vis_name, "vissink");
598         vstream = emotion_video_stream_new(ev);
599         if (!vstream)
600           goto finalize;
601         else
602           DBG("could not create visualization stream");
603
604         vstream->length_time = astream->length_time;
605         vstream->width = 320;
606         vstream->height = 200;
607         vstream->fps_num = 25;
608         vstream->fps_den = 1;
609         vstream->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
610
611         g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL);
612         g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL);
613         flags |= 0x00000008;
614         g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL);
615      }
616
617  finalize:
618
619    ev->video_stream_nbr = eina_list_count(ev->video_streams);
620    ev->audio_stream_nbr = eina_list_count(ev->audio_streams);
621
622    if (ev->video_stream_nbr == 1)
623      {
624        Emotion_Video_Stream *vstream;
625
626        vstream = eina_list_data_get(ev->video_streams);
627        ev->ratio = (double)vstream->width / (double)vstream->height;
628        _emotion_frame_resize(ev->obj, vstream->width, vstream->height, ev->ratio);
629      }
630
631    {
632      /* on recapitule : */
633      Emotion_Video_Stream *vstream;
634      Emotion_Audio_Stream *astream;
635
636      vstream = eina_list_data_get(ev->video_streams);
637      if (vstream)
638        {
639          DBG("video size=%dx%d, fps=%d/%d, "
640              "fourcc=%"GST_FOURCC_FORMAT", length=%"GST_TIME_FORMAT,
641              vstream->width, vstream->height, vstream->fps_num, vstream->fps_den,
642              GST_FOURCC_ARGS(vstream->fourcc),
643              GST_TIME_ARGS((guint64)(vstream->length_time * GST_SECOND)));
644        }
645
646      astream = eina_list_data_get(ev->audio_streams);
647      if (astream)
648        {
649          DBG("audio channels=%d, rate=%d, length=%"GST_TIME_FORMAT,
650              astream->channels, astream->samplerate,
651              GST_TIME_ARGS((guint64)(astream->length_time * GST_SECOND)));
652        }
653    }
654
655    if (ev->metadata)
656      _free_metadata(ev->metadata);
657    ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));
658
659    em_audio_channel_volume_set(ev, ev->volume);
660
661    _eos_timer_fct(ev);
662    _emotion_open_done(ev->obj);
663
664    return 1;
665 }
666
667 static void
668 em_file_close(void *video)
669 {
670    Emotion_Gstreamer_Video *ev;
671    Emotion_Audio_Stream *astream;
672    Emotion_Video_Stream *vstream;
673
674    ev = (Emotion_Gstreamer_Video *)video;
675    if (!ev)
676      return;
677
678    if (ev->eos_bus)
679      {
680         gst_object_unref(GST_OBJECT(ev->eos_bus));
681         ev->eos_bus = NULL;
682      }
683
684    /* we clear the stream lists */
685    EINA_LIST_FREE(ev->audio_streams, astream)
686      free(astream);
687    EINA_LIST_FREE(ev->video_streams, vstream)
688      free(vstream);
689
690    /* shutdown eos */
691    if (ev->eos_timer)
692      {
693         ecore_timer_del(ev->eos_timer);
694         ev->eos_timer = NULL;
695      }
696
697    if (ev->metadata)
698      {
699         _free_metadata(ev->metadata);
700         ev->metadata = NULL;
701      }
702 }
703
704 static void
705 em_play(void   *video,
706         double  pos __UNUSED__)
707 {
708    Emotion_Gstreamer_Video *ev;
709
710    ev = (Emotion_Gstreamer_Video *)video;
711    gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
712    ev->play = 1;
713    ev->play_started = 1;
714
715    /* eos */
716    ev->eos_timer = ecore_timer_add(0.1, _eos_timer_fct, ev);
717 }
718
719 static void
720 em_stop(void *video)
721 {
722    Emotion_Gstreamer_Video *ev;
723
724    ev = (Emotion_Gstreamer_Video *)video;
725
726    /* shutdown eos */
727    if (ev->eos_timer)
728      {
729         ecore_timer_del(ev->eos_timer);
730         ev->eos_timer = NULL;
731      }
732
733    gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
734    ev->play = 0;
735 }
736
737 static void
738 em_size_get(void  *video,
739             int   *width,
740             int   *height)
741 {
742    Emotion_Gstreamer_Video *ev;
743    Emotion_Video_Stream      *vstream;
744
745    ev = (Emotion_Gstreamer_Video *)video;
746
747    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
748    if (vstream)
749      {
750         if (width) *width = vstream->width;
751         if (height) *height = vstream->height;
752      }
753    else
754      {
755         if (width) *width = 0;
756         if (height) *height = 0;
757      }
758 }
759
760 static void
761 em_pos_set(void   *video,
762            double  pos)
763 {
764    Emotion_Gstreamer_Video *ev;
765    gboolean res;
766
767    ev = (Emotion_Gstreamer_Video *)video;
768
769    res = gst_element_seek(ev->pipeline, 1.0,
770                           GST_FORMAT_TIME,
771                           GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
772                           GST_SEEK_TYPE_SET,
773                           (gint64)(pos * (double)GST_SECOND),
774                           GST_SEEK_TYPE_NONE, -1);
775 }
776
777 static double
778 em_len_get(void *video)
779 {
780    Emotion_Gstreamer_Video *ev;
781    Emotion_Video_Stream *vstream;
782    Emotion_Audio_Stream *astream;
783    Eina_List *l;
784    GstFormat fmt;
785    gint64 val;
786    gboolean ret;
787
788    ev = video;
789    fmt = GST_FORMAT_TIME;
790    ret = gst_element_query_duration(ev->pipeline, &fmt, &val);
791    if (!ret)
792      goto fallback;
793
794    if (fmt != GST_FORMAT_TIME)
795      {
796         DBG("requrested duration in time, but got %s instead.",
797                 gst_format_get_name(fmt));
798         goto fallback;
799      }
800
801    if (val <= 0.0)
802      goto fallback;
803
804    return val / 1000000000.0;
805
806  fallback:
807    EINA_LIST_FOREACH(ev->audio_streams, l, astream)
808      if (astream->length_time >= 0)
809        return astream->length_time;
810
811    EINA_LIST_FOREACH(ev->video_streams, l, vstream)
812      if (vstream->length_time >= 0)
813        return vstream->length_time;
814
815    return 0.0;
816 }
817
818 static int
819 em_fps_num_get(void *video)
820 {
821    Emotion_Gstreamer_Video *ev;
822    Emotion_Video_Stream      *vstream;
823
824    ev = (Emotion_Gstreamer_Video *)video;
825
826    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
827    if (vstream)
828      return vstream->fps_num;
829
830    return 0;
831 }
832
833 static int
834 em_fps_den_get(void *video)
835 {
836    Emotion_Gstreamer_Video *ev;
837    Emotion_Video_Stream      *vstream;
838
839    ev = (Emotion_Gstreamer_Video *)video;
840
841    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
842    if (vstream)
843      return vstream->fps_den;
844
845    return 1;
846 }
847
848 static double
849 em_fps_get(void *video)
850 {
851    Emotion_Gstreamer_Video *ev;
852    Emotion_Video_Stream      *vstream;
853
854    ev = (Emotion_Gstreamer_Video *)video;
855
856    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
857    if (vstream)
858      return (double)vstream->fps_num / (double)vstream->fps_den;
859
860    return 0.0;
861 }
862
863 static double
864 em_pos_get(void *video)
865 {
866    Emotion_Gstreamer_Video *ev;
867    GstFormat fmt;
868    gint64 val;
869    gboolean ret;
870
871    ev = video;
872    fmt = GST_FORMAT_TIME;
873    ret = gst_element_query_position(ev->pipeline, &fmt, &val);
874    if (!ret)
875      return ev->position;
876
877    if (fmt != GST_FORMAT_TIME)
878      {
879         ERR("requrested position in time, but got %s instead.",
880             gst_format_get_name(fmt));
881         return ev->position;
882      }
883
884    ev->position = val / 1000000000.0;
885    return ev->position;
886 }
887
888 static void
889 em_vis_set(void *video,
890            Emotion_Vis vis)
891 {
892    Emotion_Gstreamer_Video *ev;
893
894    ev = (Emotion_Gstreamer_Video *)video;
895
896    if (ev->vis == vis) return;
897    ev->vis = vis;
898 }
899
900 static Emotion_Vis
901 em_vis_get(void *video)
902 {
903    Emotion_Gstreamer_Video *ev;
904
905    ev = (Emotion_Gstreamer_Video *)video;
906
907    return ev->vis;
908 }
909
910 static Eina_Bool
911 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis)
912 {
913    const char *name;
914    GstElementFactory *factory;
915
916    if (vis == EMOTION_VIS_NONE)
917      return EINA_TRUE;
918
919    name = emotion_visualization_element_name_get(vis);
920    if (!name)
921      return EINA_FALSE;
922
923    factory = gst_element_factory_find(name);
924    if (!factory)
925      return EINA_FALSE;
926
927    gst_object_unref(factory);
928    return EINA_TRUE;
929 }
930
931 static double
932 em_ratio_get(void *video)
933 {
934    Emotion_Gstreamer_Video *ev;
935
936    ev = (Emotion_Gstreamer_Video *)video;
937
938    return ev->ratio;
939 }
940
941 static int
942 em_video_handled(void *video)
943 {
944    Emotion_Gstreamer_Video *ev;
945
946    ev = (Emotion_Gstreamer_Video *)video;
947
948    if (!eina_list_count(ev->video_streams))
949      return 0;
950
951    return 1;
952 }
953
954 static int
955 em_audio_handled(void *video)
956 {
957    Emotion_Gstreamer_Video *ev;
958
959    ev = (Emotion_Gstreamer_Video *)video;
960
961    if (!eina_list_count(ev->audio_streams))
962      return 0;
963
964    return 1;
965 }
966
967 static int
968 em_seekable(void *video __UNUSED__)
969 {
970    return 1;
971 }
972
973 static void
974 em_frame_done(void *video __UNUSED__)
975 {
976 }
977
978 static Emotion_Format
979 em_format_get(void *video)
980 {
981    Emotion_Gstreamer_Video *ev;
982    Emotion_Video_Stream      *vstream;
983
984    ev = (Emotion_Gstreamer_Video *)video;
985
986    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
987    if (vstream)
988      {
989         switch (vstream->fourcc)
990           {
991            case GST_MAKE_FOURCC('I', '4', '2', '0'):
992               return EMOTION_FORMAT_I420;
993            case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
994               return EMOTION_FORMAT_YV12;
995            case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
996               return EMOTION_FORMAT_YUY2;
997            case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
998               return EMOTION_FORMAT_BGRA;
999            default:
1000               return EMOTION_FORMAT_NONE;
1001           }
1002      }
1003    return EMOTION_FORMAT_NONE;
1004 }
1005
1006 static void
1007 em_video_data_size_get(void *video, int *w, int *h)
1008 {
1009    Emotion_Gstreamer_Video *ev;
1010    Emotion_Video_Stream      *vstream;
1011
1012    ev = (Emotion_Gstreamer_Video *)video;
1013
1014    vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
1015    if (vstream)
1016      {
1017         *w = vstream->width;
1018         *h = vstream->height;
1019      }
1020    else
1021      {
1022         *w = 0;
1023         *h = 0;
1024      }
1025 }
1026
1027 static int
1028 em_yuv_rows_get(void           *video __UNUSED__,
1029                 int             w __UNUSED__,
1030                 int             h __UNUSED__,
1031                 unsigned char **yrows __UNUSED__,
1032                 unsigned char **urows __UNUSED__,
1033                 unsigned char **vrows __UNUSED__)
1034 {
1035    return 0;
1036 }
1037
1038 static int
1039 em_bgra_data_get(void *video __UNUSED__, unsigned char **bgra_data __UNUSED__)
1040 {
1041    return 0;
1042 }
1043
1044 static void
1045 em_event_feed(void *video __UNUSED__, int event __UNUSED__)
1046 {
1047 }
1048
1049 static void
1050 em_event_mouse_button_feed(void *video __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1051 {
1052 }
1053
1054 static void
1055 em_event_mouse_move_feed(void *video __UNUSED__, int x __UNUSED__, int y __UNUSED__)
1056 {
1057 }
1058
1059 /* Video channels */
1060 static int
1061 em_video_channel_count(void *video)
1062 {
1063    Emotion_Gstreamer_Video *ev;
1064
1065    ev = (Emotion_Gstreamer_Video *)video;
1066
1067    return eina_list_count(ev->video_streams);
1068 }
1069
1070 static void
1071 em_video_channel_set(void *video __UNUSED__,
1072                      int   channel __UNUSED__)
1073 {
1074 #if 0
1075    Emotion_Gstreamer_Video *ev;
1076
1077    ev = (Emotion_Gstreamer_Video *)video;
1078
1079    if (channel < 0) channel = 0;
1080 #endif
1081    /* FIXME: a faire... */
1082 }
1083
1084 static int
1085 em_video_channel_get(void *video)
1086 {
1087    Emotion_Gstreamer_Video *ev;
1088
1089    ev = (Emotion_Gstreamer_Video *)video;
1090
1091    return ev->video_stream_nbr;
1092 }
1093
1094 static const char *
1095 em_video_channel_name_get(void *video __UNUSED__,
1096                           int   channel __UNUSED__)
1097 {
1098    return NULL;
1099 }
1100
1101 static void
1102 em_video_channel_mute_set(void *video,
1103                           int   mute)
1104 {
1105    Emotion_Gstreamer_Video *ev;
1106
1107    ev = (Emotion_Gstreamer_Video *)video;
1108
1109    ev->video_mute = mute;
1110 }
1111
1112 static int
1113 em_video_channel_mute_get(void *video)
1114 {
1115    Emotion_Gstreamer_Video *ev;
1116
1117    ev = (Emotion_Gstreamer_Video *)video;
1118
1119    return ev->video_mute;
1120 }
1121
1122 /* Audio channels */
1123
1124 static int
1125 em_audio_channel_count(void *video)
1126 {
1127    Emotion_Gstreamer_Video *ev;
1128
1129    ev = (Emotion_Gstreamer_Video *)video;
1130
1131    return eina_list_count(ev->audio_streams);
1132 }
1133
1134 static void
1135 em_audio_channel_set(void *video __UNUSED__,
1136                      int   channel __UNUSED__)
1137 {
1138 #if 0
1139    Emotion_Gstreamer_Video *ev;
1140
1141    ev = (Emotion_Gstreamer_Video *)video;
1142
1143    if (channel < -1) channel = -1;
1144 #endif
1145    /* FIXME: a faire... */
1146 }
1147
1148 static int
1149 em_audio_channel_get(void *video)
1150 {
1151    Emotion_Gstreamer_Video *ev;
1152
1153    ev = (Emotion_Gstreamer_Video *)video;
1154
1155    return ev->audio_stream_nbr;
1156 }
1157
1158 static const char *
1159 em_audio_channel_name_get(void *video __UNUSED__,
1160                           int   channel __UNUSED__)
1161 {
1162    return NULL;
1163 }
1164
1165 #define GST_PLAY_FLAG_AUDIO (1 << 1)
1166
1167 static void
1168 em_audio_channel_mute_set(void *video,
1169                           int   mute)
1170 {
1171    Emotion_Gstreamer_Video *ev;
1172    int flags;
1173
1174    ev = (Emotion_Gstreamer_Video *)video;
1175
1176    if (ev->audio_mute == mute)
1177      return;
1178
1179    ev->audio_mute = mute;
1180
1181    g_object_set(G_OBJECT(ev->pipeline), "mute", !!mute, NULL);
1182    /* This code should stop the decoding of only the audio stream, but everything stop :"( */
1183    /* g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL); */
1184    /* if (mute) */
1185    /*   flags &= ~GST_PLAY_FLAG_AUDIO; */
1186    /* else */
1187    /*   flags |= GST_PLAY_FLAG_AUDIO; */
1188    /* g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL); */
1189    /* g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL); */
1190    /* fprintf(stderr, "flags-n: %x\n", flags); */
1191 }
1192
1193 static int
1194 em_audio_channel_mute_get(void *video)
1195 {
1196    Emotion_Gstreamer_Video *ev;
1197
1198    ev = (Emotion_Gstreamer_Video *)video;
1199
1200    return ev->audio_mute;
1201 }
1202
1203 static void
1204 em_audio_channel_volume_set(void  *video,
1205                             double vol)
1206 {
1207    Emotion_Gstreamer_Video *ev;
1208
1209    ev = (Emotion_Gstreamer_Video *)video;
1210
1211    if (vol < 0.0)
1212      vol = 0.0;
1213    if (vol > 1.0)
1214      vol = 1.0;
1215    ev->volume = vol;
1216    g_object_set(G_OBJECT(ev->pipeline), "volume", vol, NULL);
1217 }
1218
1219 static double
1220 em_audio_channel_volume_get(void *video)
1221 {
1222    Emotion_Gstreamer_Video *ev;
1223
1224    ev = (Emotion_Gstreamer_Video *)video;
1225
1226    return ev->volume;
1227 }
1228
1229 /* spu stuff */
1230
1231 static int
1232 em_spu_channel_count(void *video __UNUSED__)
1233 {
1234    return 0;
1235 }
1236
1237 static void
1238 em_spu_channel_set(void *video __UNUSED__, int channel __UNUSED__)
1239 {
1240 }
1241
1242 static int
1243 em_spu_channel_get(void *video __UNUSED__)
1244 {
1245    return 1;
1246 }
1247
1248 static const char *
1249 em_spu_channel_name_get(void *video __UNUSED__, int channel __UNUSED__)
1250 {
1251    return NULL;
1252 }
1253
1254 static void
1255 em_spu_channel_mute_set(void *video __UNUSED__, int mute __UNUSED__)
1256 {
1257 }
1258
1259 static int
1260 em_spu_channel_mute_get(void *video __UNUSED__)
1261 {
1262    return 0;
1263 }
1264
1265 static int
1266 em_chapter_count(void *video __UNUSED__)
1267 {
1268    return 0;
1269 }
1270
1271 static void
1272 em_chapter_set(void *video __UNUSED__, int chapter __UNUSED__)
1273 {
1274 }
1275
1276 static int
1277 em_chapter_get(void *video __UNUSED__)
1278 {
1279    return 0;
1280 }
1281
1282 static const char *
1283 em_chapter_name_get(void *video __UNUSED__, int chapter __UNUSED__)
1284 {
1285    return NULL;
1286 }
1287
1288 static void
1289 em_speed_set(void *video __UNUSED__, double speed __UNUSED__)
1290 {
1291 }
1292
1293 static double
1294 em_speed_get(void *video __UNUSED__)
1295 {
1296    return 1.0;
1297 }
1298
1299 static int
1300 em_eject(void *video __UNUSED__)
1301 {
1302    return 1;
1303 }
1304
1305 static const char *
1306 em_meta_get(void *video, int meta)
1307 {
1308    Emotion_Gstreamer_Video *ev;
1309    const char *str = NULL;
1310
1311    ev = (Emotion_Gstreamer_Video *)video;
1312
1313    if (!ev || !ev->metadata) return NULL;
1314    switch (meta)
1315      {
1316       case META_TRACK_TITLE:
1317          str = ev->metadata->title;
1318          break;
1319       case META_TRACK_ARTIST:
1320          str = ev->metadata->artist;
1321          break;
1322       case  META_TRACK_ALBUM:
1323          str = ev->metadata->album;
1324          break;
1325       case META_TRACK_YEAR:
1326          str = ev->metadata->year;
1327          break;
1328       case META_TRACK_GENRE:
1329          str = ev->metadata->genre;
1330          break;
1331       case META_TRACK_COMMENT:
1332          str = ev->metadata->comment;
1333          break;
1334       case META_TRACK_DISCID:
1335          str = ev->metadata->disc_id;
1336          break;
1337       default:
1338          break;
1339      }
1340
1341    return str;
1342 }
1343
1344 static Eina_Bool
1345 module_open(Evas_Object           *obj,
1346             const Emotion_Video_Module **module,
1347             void                 **video,
1348             Emotion_Module_Options *opt)
1349 {
1350    if (!module)
1351      return EINA_FALSE;
1352
1353    if (_emotion_gstreamer_log_domain < 0)
1354      {
1355         eina_threads_init();
1356         eina_log_threads_enable();
1357         _emotion_gstreamer_log_domain = eina_log_domain_register
1358           ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);
1359         if (_emotion_gstreamer_log_domain < 0)
1360           {
1361              EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");
1362              return EINA_FALSE;
1363           }
1364      }
1365
1366    if (!em_module.init(obj, video, opt))
1367      return EINA_FALSE;
1368
1369    eina_threads_init();
1370
1371    *module = &em_module;
1372    return EINA_TRUE;
1373 }
1374
1375 static void
1376 module_close(Emotion_Video_Module *module __UNUSED__,
1377              void                 *video)
1378 {
1379    em_module.shutdown(video);
1380
1381    eina_threads_shutdown();
1382 }
1383
1384 Eina_Bool
1385 gstreamer_module_init(void)
1386 {
1387    GError *error;
1388
1389    if (!gst_init_check(0, NULL, &error))
1390      {
1391         EINA_LOG_CRIT("Could not init GStreamer");
1392         return EINA_FALSE;
1393      }
1394
1395    if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
1396                                   "emotion-sink",
1397                                   "video sink plugin for Emotion",
1398                                   gstreamer_plugin_init,
1399                                   VERSION,
1400                                   "LGPL",
1401                                   "Enlightenment",
1402                                   PACKAGE,
1403                                   "http://www.enlightenment.org/") == FALSE)
1404      {
1405         EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");
1406         return EINA_FALSE;
1407      }
1408
1409    return _emotion_module_register("gstreamer", module_open, module_close);
1410 }
1411
1412 void
1413 gstreamer_module_shutdown(void)
1414 {
1415    _emotion_module_unregister("gstreamer");
1416
1417    gst_deinit();
1418 }
1419
1420 #ifndef EMOTION_STATIC_BUILD_GSTREAMER
1421
1422 EINA_MODULE_INIT(gstreamer_module_init);
1423 EINA_MODULE_SHUTDOWN(gstreamer_module_shutdown);
1424
1425 #endif
1426
1427 static void
1428 _for_each_tag(GstTagList const* list,
1429                     gchar const* tag,
1430                     void *data)
1431 {
1432    Emotion_Gstreamer_Video *ev;
1433    int i;
1434    int count;
1435
1436
1437    ev = (Emotion_Gstreamer_Video*)data;
1438
1439    if (!ev || !ev->metadata) return;
1440
1441    count = gst_tag_list_get_tag_size(list, tag);
1442
1443    for (i = 0; i < count; i++)
1444      {
1445         if (!strcmp(tag, GST_TAG_TITLE))
1446           {
1447              char *str;
1448              if (ev->metadata->title) g_free(ev->metadata->title);
1449              if (gst_tag_list_get_string(list, GST_TAG_TITLE, &str))
1450                ev->metadata->title = str;
1451              else
1452                ev->metadata->title = NULL;
1453              break;
1454           }
1455         if (!strcmp(tag, GST_TAG_ALBUM))
1456           {
1457              gchar *str;
1458              if (ev->metadata->album) g_free(ev->metadata->album);
1459              if (gst_tag_list_get_string(list, GST_TAG_ALBUM, &str))
1460                ev->metadata->album = str;
1461              else
1462                ev->metadata->album = NULL;
1463              break;
1464           }
1465         if (!strcmp(tag, GST_TAG_ARTIST))
1466           {
1467              gchar *str;
1468              if (ev->metadata->artist) g_free( ev->metadata->artist);
1469              if (gst_tag_list_get_string(list, GST_TAG_ARTIST, &str))
1470                ev->metadata->artist = str;
1471              else
1472                ev->metadata->artist = NULL;
1473              break;
1474           }
1475         if (!strcmp(tag, GST_TAG_GENRE))
1476           {
1477              gchar *str;
1478              if (ev->metadata->genre) g_free( ev->metadata->genre);
1479              if (gst_tag_list_get_string(list, GST_TAG_GENRE, &str))
1480                ev->metadata->genre = str;
1481              else
1482                ev->metadata->genre = NULL;
1483              break;
1484           }
1485         if (!strcmp(tag, GST_TAG_COMMENT))
1486           {
1487              gchar *str;
1488              if (ev->metadata->comment) g_free(ev->metadata->comment);
1489              if (gst_tag_list_get_string(list, GST_TAG_COMMENT, &str))
1490                ev->metadata->comment = str;
1491              else
1492                ev->metadata->comment = NULL;
1493              break;
1494           }
1495         if (!strcmp(tag, GST_TAG_DATE))
1496           {
1497              gchar *str;
1498              const GValue *date;
1499              if (ev->metadata->year) g_free(ev->metadata->year);
1500              date = gst_tag_list_get_value_index(list, GST_TAG_DATE, 0);
1501              if (date)
1502                str = g_strdup_value_contents(date);
1503              else
1504                str = NULL;
1505              ev->metadata->year = str;
1506              break;
1507           }
1508
1509         if (!strcmp(tag, GST_TAG_TRACK_NUMBER))
1510           {
1511              gchar *str;
1512              const GValue *track;
1513              if (ev->metadata->count) g_free( ev->metadata->count);
1514              track = gst_tag_list_get_value_index(list, GST_TAG_TRACK_NUMBER, 0);
1515              if (track)
1516                str = g_strdup_value_contents(track);
1517              else
1518                str = NULL;
1519              ev->metadata->count = str;
1520              break;
1521           }
1522
1523 #ifdef GST_TAG_CDDA_CDDB_DISCID
1524         if (!strcmp(tag, GST_TAG_CDDA_CDDB_DISCID))
1525           {
1526              gchar *str;
1527              const GValue *discid;
1528              if (ev->metadata->disc_id) g_free(ev->metadata->disc_id);
1529              discid = gst_tag_list_get_value_index(list, GST_TAG_CDDA_CDDB_DISCID, 0);
1530              if (discid)
1531                str = g_strdup_value_contents(discid);
1532              else
1533                str = NULL;
1534              ev->metadata->disc_id = str;
1535              break;
1536           }
1537 #endif
1538      }
1539
1540 }
1541
1542 static void
1543 _free_metadata(Emotion_Gstreamer_Metadata *m)
1544 {
1545   if (!m) return;
1546
1547   if (m->title)   g_free(m->title);
1548   if (m->album)   g_free(m->album);
1549   if (m->artist)  g_free(m->artist);
1550   if (m->genre)   g_free(m->genre);
1551   if (m->comment) g_free(m->comment);
1552   if (m->year)    g_free(m->year);
1553   if (m->count)   g_free(m->count);
1554   if (m->disc_id) g_free(m->disc_id);
1555
1556   free(m);
1557 }
1558
1559 static Eina_Bool
1560 _eos_timer_fct(void *data)
1561 {
1562    Emotion_Gstreamer_Video *ev;
1563    GstMessage              *msg;
1564
1565    ev = (Emotion_Gstreamer_Video *)data;
1566    if (ev->play_started)
1567      {
1568         _emotion_playback_started(ev->obj);
1569         ev->play_started = 0;
1570      }
1571    while ((msg = gst_bus_poll(ev->eos_bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_TAG | GST_MESSAGE_ASYNC_DONE, 0)))
1572      {
1573         switch (GST_MESSAGE_TYPE(msg))
1574           {
1575            case GST_MESSAGE_ERROR:
1576                 {
1577                    gchar *debug;
1578                    GError *err;
1579
1580                    gst_message_parse_error(msg, &err, &debug);
1581                    g_free(debug);
1582
1583                    ERR("Error: %s", err->message);
1584                    g_error_free(err);
1585
1586                    break;
1587                 }
1588            case GST_MESSAGE_EOS:
1589               if (ev->eos_timer)
1590                 {
1591                    ecore_timer_del(ev->eos_timer);
1592                    ev->eos_timer = NULL;
1593                 }
1594               ev->play = 0;
1595               _emotion_decode_stop(ev->obj);
1596               _emotion_playback_finished(ev->obj);
1597               break;
1598            case GST_MESSAGE_TAG:
1599                 {
1600                    GstTagList *new_tags;
1601                    gst_message_parse_tag(msg, &new_tags);
1602                    if (new_tags)
1603                      {
1604                         gst_tag_list_foreach(new_tags, (GstTagForeachFunc)_for_each_tag, ev);
1605                         gst_tag_list_free(new_tags);
1606                      }
1607                    break;
1608                 }
1609            case GST_MESSAGE_ASYNC_DONE:
1610               _emotion_seek_done(ev->obj);
1611               break;
1612            default:
1613               ERR("bus say: %s [%i]\n",
1614                   GST_MESSAGE_SRC_NAME(msg),
1615                   GST_MESSAGE_TYPE(msg));
1616               break;
1617           }
1618         gst_message_unref(msg);
1619      }
1620    return EINA_TRUE;
1621 }