6 #include "emotion_private.h"
7 #include "emotion_gstreamer.h"
10 int _emotion_gstreamer_log_domain = -1;
12 /* Callbacks to get the eos */
13 static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);
14 static void _free_metadata (Emotion_Gstreamer_Metadata *m);
18 static unsigned char em_init (Evas_Object *obj,
20 Emotion_Module_Options *opt);
22 static int em_shutdown (void *video);
24 static unsigned char em_file_open (const char *file,
28 static void em_file_close (void *video);
30 static void em_play (void *video,
33 static void em_stop (void *video);
35 static void em_size_get (void *video,
39 static void em_pos_set (void *video,
43 static double em_len_get (void *video);
45 static int em_fps_num_get (void *video);
47 static int em_fps_den_get (void *video);
49 static double em_fps_get (void *video);
51 static double em_pos_get (void *video);
53 static void em_vis_set (void *video,
56 static Emotion_Vis em_vis_get (void *video);
58 static Eina_Bool em_vis_supported (void *video,
61 static double em_ratio_get (void *video);
63 static int em_video_handled (void *video);
65 static int em_audio_handled (void *video);
67 static int em_seekable (void *video);
69 static void em_frame_done (void *video);
71 static Emotion_Format em_format_get (void *video);
73 static void em_video_data_size_get (void *video,
77 static int em_yuv_rows_get (void *video,
80 unsigned char **yrows,
81 unsigned char **urows,
82 unsigned char **vrows);
84 static int em_bgra_data_get (void *video,
85 unsigned char **bgra_data);
87 static void em_event_feed (void *video,
90 static void em_event_mouse_button_feed (void *video,
95 static void em_event_mouse_move_feed (void *video,
99 static int em_video_channel_count (void *video);
101 static void em_video_channel_set (void *video,
104 static int em_video_channel_get (void *video);
106 static const char *em_video_channel_name_get (void *video,
109 static void em_video_channel_mute_set (void *video,
112 static int em_video_channel_mute_get (void *video);
114 static int em_audio_channel_count (void *video);
116 static void em_audio_channel_set (void *video,
119 static int em_audio_channel_get (void *video);
121 static const char *em_audio_channel_name_get (void *video,
124 static void em_audio_channel_mute_set (void *video,
127 static int em_audio_channel_mute_get (void *video);
129 static void em_audio_channel_volume_set (void *video,
132 static double em_audio_channel_volume_get (void *video);
134 static int em_spu_channel_count (void *video);
136 static void em_spu_channel_set (void *video,
139 static int em_spu_channel_get (void *video);
141 static const char *em_spu_channel_name_get (void *video,
144 static void em_spu_channel_mute_set (void *video,
147 static int em_spu_channel_mute_get (void *video);
149 static int em_chapter_count (void *video);
151 static void em_chapter_set (void *video,
154 static int em_chapter_get (void *video);
156 static const char *em_chapter_name_get (void *video,
159 static void em_speed_set (void *video,
162 static double em_speed_get (void *video);
164 static int em_eject (void *video);
166 static const char *em_meta_get (void *video,
169 static GstBusSyncReply _eos_sync_fct(GstBus *bus,
173 /* Module interface */
175 static Emotion_Video_Module em_module =
178 em_shutdown, /* shutdown */
179 em_file_open, /* file_open */
180 em_file_close, /* file_close */
183 em_size_get, /* size_get */
184 em_pos_set, /* pos_set */
185 em_len_get, /* len_get */
186 em_fps_num_get, /* fps_num_get */
187 em_fps_den_get, /* fps_den_get */
188 em_fps_get, /* fps_get */
189 em_pos_get, /* pos_get */
190 em_vis_set, /* vis_set */
191 em_vis_get, /* vis_get */
192 em_vis_supported, /* vis_supported */
193 em_ratio_get, /* ratio_get */
194 em_video_handled, /* video_handled */
195 em_audio_handled, /* audio_handled */
196 em_seekable, /* seekable */
197 em_frame_done, /* frame_done */
198 em_format_get, /* format_get */
199 em_video_data_size_get, /* video_data_size_get */
200 em_yuv_rows_get, /* yuv_rows_get */
201 em_bgra_data_get, /* bgra_data_get */
202 em_event_feed, /* event_feed */
203 em_event_mouse_button_feed, /* event_mouse_button_feed */
204 em_event_mouse_move_feed, /* event_mouse_move_feed */
205 em_video_channel_count, /* video_channel_count */
206 em_video_channel_set, /* video_channel_set */
207 em_video_channel_get, /* video_channel_get */
208 em_video_channel_name_get, /* video_channel_name_get */
209 em_video_channel_mute_set, /* video_channel_mute_set */
210 em_video_channel_mute_get, /* video_channel_mute_get */
211 em_audio_channel_count, /* audio_channel_count */
212 em_audio_channel_set, /* audio_channel_set */
213 em_audio_channel_get, /* audio_channel_get */
214 em_audio_channel_name_get, /* audio_channel_name_get */
215 em_audio_channel_mute_set, /* audio_channel_mute_set */
216 em_audio_channel_mute_get, /* audio_channel_mute_get */
217 em_audio_channel_volume_set, /* audio_channel_volume_set */
218 em_audio_channel_volume_get, /* audio_channel_volume_get */
219 em_spu_channel_count, /* spu_channel_count */
220 em_spu_channel_set, /* spu_channel_set */
221 em_spu_channel_get, /* spu_channel_get */
222 em_spu_channel_name_get, /* spu_channel_name_get */
223 em_spu_channel_mute_set, /* spu_channel_mute_set */
224 em_spu_channel_mute_get, /* spu_channel_mute_get */
225 em_chapter_count, /* chapter_count */
226 em_chapter_set, /* chapter_set */
227 em_chapter_get, /* chapter_get */
228 em_chapter_name_get, /* chapter_name_get */
229 em_speed_set, /* speed_set */
230 em_speed_get, /* speed_get */
231 em_eject, /* eject */
232 em_meta_get, /* meta_get */
236 static Emotion_Video_Stream *
237 emotion_video_stream_new(Emotion_Gstreamer_Video *ev)
239 Emotion_Video_Stream *vstream;
241 if (!ev) return NULL;
243 vstream = (Emotion_Video_Stream *)calloc(1, sizeof(Emotion_Video_Stream));
244 if (!vstream) return NULL;
246 ev->video_streams = eina_list_append(ev->video_streams, vstream);
247 if (eina_error_get())
256 emotion_video_stream_free(Emotion_Gstreamer_Video *ev, Emotion_Video_Stream *vstream)
258 if (!ev || !vstream) return;
260 ev->video_streams = eina_list_remove(ev->video_streams, vstream);
265 emotion_visualization_element_name_get(Emotion_Vis visualisation)
267 switch (visualisation)
269 case EMOTION_VIS_NONE:
271 case EMOTION_VIS_GOOM:
273 case EMOTION_VIS_LIBVISUAL_BUMPSCOPE:
274 return "libvisual_bumpscope";
275 case EMOTION_VIS_LIBVISUAL_CORONA:
276 return "libvisual_corona";
277 case EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES:
278 return "libvisual_dancingparticles";
279 case EMOTION_VIS_LIBVISUAL_GDKPIXBUF:
280 return "libvisual_gdkpixbuf";
281 case EMOTION_VIS_LIBVISUAL_G_FORCE:
282 return "libvisual_G-Force";
283 case EMOTION_VIS_LIBVISUAL_GOOM:
284 return "libvisual_goom";
285 case EMOTION_VIS_LIBVISUAL_INFINITE:
286 return "libvisual_infinite";
287 case EMOTION_VIS_LIBVISUAL_JAKDAW:
288 return "libvisual_jakdaw";
289 case EMOTION_VIS_LIBVISUAL_JESS:
290 return "libvisual_jess";
291 case EMOTION_VIS_LIBVISUAL_LV_ANALYSER:
292 return "libvisual_lv_analyzer";
293 case EMOTION_VIS_LIBVISUAL_LV_FLOWER:
294 return "libvisual_lv_flower";
295 case EMOTION_VIS_LIBVISUAL_LV_GLTEST:
296 return "libvisual_lv_gltest";
297 case EMOTION_VIS_LIBVISUAL_LV_SCOPE:
298 return "libvisual_lv_scope";
299 case EMOTION_VIS_LIBVISUAL_MADSPIN:
300 return "libvisual_madspin";
301 case EMOTION_VIS_LIBVISUAL_NEBULUS:
302 return "libvisual_nebulus";
303 case EMOTION_VIS_LIBVISUAL_OINKSIE:
304 return "libvisual_oinksie";
305 case EMOTION_VIS_LIBVISUAL_PLASMA:
306 return "libvisual_plazma";
313 em_init(Evas_Object *obj,
314 void **emotion_video,
315 Emotion_Module_Options *opt __UNUSED__)
317 Emotion_Gstreamer_Video *ev;
323 ev = calloc(1, sizeof(Emotion_Gstreamer_Video));
328 /* Initialization of gstreamer */
329 if (!gst_init_check(NULL, NULL, &error))
334 ev->vis = EMOTION_VIS_NONE;
348 em_shutdown(void *video)
350 Emotion_Gstreamer_Video *ev;
351 Emotion_Audio_Stream *astream;
352 Emotion_Video_Stream *vstream;
354 ev = (Emotion_Gstreamer_Video *)video;
360 ecore_thread_cancel(ev->thread);
366 gst_element_set_state(ev->pipeline, GST_STATE_NULL);
367 gst_object_unref(ev->pipeline);
371 EINA_LIST_FREE(ev->audio_streams, astream)
373 EINA_LIST_FREE(ev->video_streams, vstream)
383 em_file_open(const char *file,
387 Emotion_Gstreamer_Video *ev;
388 Eina_Strbuf *sbuf = NULL;
391 ev = (Emotion_Gstreamer_Video *)video;
393 if (!file) return EINA_FALSE;
394 if (strstr(file, "://") == NULL)
396 sbuf = eina_strbuf_new();
397 eina_strbuf_append(sbuf, "file://");
398 if (strncmp(file, "./", 2) == 0)
400 if (strstr(file, ":/") != NULL)
401 { /* We absolutely need file:///C:/ under Windows, so adding it here */
402 eina_strbuf_append(sbuf, "/");
404 else if (*file != '/')
408 if (getcwd(tmp, PATH_MAX))
410 eina_strbuf_append(sbuf, tmp);
411 eina_strbuf_append(sbuf, "/");
414 eina_strbuf_append(sbuf, file);
417 uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
418 DBG("setting file to '%s'", uri);
419 ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
420 if (sbuf) eina_strbuf_free(sbuf);
425 ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
428 ERR("could not get the bus");
432 gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev);
443 em_file_close(void *video)
445 Emotion_Gstreamer_Video *ev;
446 Emotion_Audio_Stream *astream;
447 Emotion_Video_Stream *vstream;
449 ev = (Emotion_Gstreamer_Video *)video;
455 gst_object_unref(GST_OBJECT(ev->eos_bus));
461 ecore_thread_cancel(ev->thread);
467 gst_element_set_state(ev->pipeline, GST_STATE_NULL);
468 gst_object_unref(ev->pipeline);
472 /* we clear the stream lists */
473 EINA_LIST_FREE(ev->audio_streams, astream)
475 EINA_LIST_FREE(ev->video_streams, vstream)
477 ev->pipeline_parsed = EINA_FALSE;
482 _free_metadata(ev->metadata);
489 double pos __UNUSED__)
491 Emotion_Gstreamer_Video *ev;
493 ev = (Emotion_Gstreamer_Video *)video;
494 if (!ev->pipeline) return ;
496 gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
498 ev->play_started = 1;
504 Emotion_Gstreamer_Video *ev;
506 ev = (Emotion_Gstreamer_Video *)video;
508 if (!ev->pipeline) return ;
510 gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
515 em_size_get(void *video,
519 Emotion_Gstreamer_Video *ev;
520 Emotion_Video_Stream *vstream;
522 ev = (Emotion_Gstreamer_Video *)video;
524 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
527 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
530 if (width) *width = vstream->width;
531 if (height) *height = vstream->height;
537 if (width) *width = 0;
538 if (height) *height = 0;
542 em_pos_set(void *video,
545 Emotion_Gstreamer_Video *ev;
548 ev = (Emotion_Gstreamer_Video *)video;
550 if (!ev->pipeline) return ;
553 res = gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
555 res = gst_element_seek(ev->pipeline, 1.0,
557 GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
559 (gint64)(pos * (double)GST_SECOND),
560 GST_SEEK_TYPE_NONE, -1);
563 res = gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
567 em_len_get(void *video)
569 Emotion_Gstreamer_Video *ev;
570 Emotion_Video_Stream *vstream;
571 Emotion_Audio_Stream *astream;
578 fmt = GST_FORMAT_TIME;
580 if (!ev->pipeline) return 0.0;
582 ret = gst_element_query_duration(ev->pipeline, &fmt, &val);
586 if (fmt != GST_FORMAT_TIME)
588 DBG("requrested duration in time, but got %s instead.",
589 gst_format_get_name(fmt));
596 return val / 1000000000.0;
599 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
602 EINA_LIST_FOREACH(ev->audio_streams, l, astream)
603 if (astream->length_time >= 0)
604 return astream->length_time;
606 EINA_LIST_FOREACH(ev->video_streams, l, vstream)
607 if (vstream->length_time >= 0)
608 return vstream->length_time;
614 em_fps_num_get(void *video)
616 Emotion_Gstreamer_Video *ev;
617 Emotion_Video_Stream *vstream;
619 ev = (Emotion_Gstreamer_Video *)video;
621 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
624 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
626 return vstream->fps_num;
632 em_fps_den_get(void *video)
634 Emotion_Gstreamer_Video *ev;
635 Emotion_Video_Stream *vstream;
637 ev = (Emotion_Gstreamer_Video *)video;
639 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
642 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
644 return vstream->fps_den;
650 em_fps_get(void *video)
652 Emotion_Gstreamer_Video *ev;
653 Emotion_Video_Stream *vstream;
655 ev = (Emotion_Gstreamer_Video *)video;
657 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
660 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
662 return (double)vstream->fps_num / (double)vstream->fps_den;
668 em_pos_get(void *video)
670 Emotion_Gstreamer_Video *ev;
676 fmt = GST_FORMAT_TIME;
678 if (!ev->pipeline) return 0.0;
680 ret = gst_element_query_position(ev->pipeline, &fmt, &val);
684 if (fmt != GST_FORMAT_TIME)
686 ERR("requrested position in time, but got %s instead.",
687 gst_format_get_name(fmt));
691 ev->position = val / 1000000000.0;
696 em_vis_set(void *video,
699 Emotion_Gstreamer_Video *ev;
701 ev = (Emotion_Gstreamer_Video *)video;
707 em_vis_get(void *video)
709 Emotion_Gstreamer_Video *ev;
711 ev = (Emotion_Gstreamer_Video *)video;
717 em_vis_supported(void *ef __UNUSED__, Emotion_Vis vis)
720 GstElementFactory *factory;
722 if (vis == EMOTION_VIS_NONE)
725 name = emotion_visualization_element_name_get(vis);
729 factory = gst_element_factory_find(name);
733 gst_object_unref(factory);
738 em_ratio_get(void *video)
740 Emotion_Gstreamer_Video *ev;
742 ev = (Emotion_Gstreamer_Video *)video;
748 em_video_handled(void *video)
750 Emotion_Gstreamer_Video *ev;
752 ev = (Emotion_Gstreamer_Video *)video;
754 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
756 if (!eina_list_count(ev->video_streams))
763 em_audio_handled(void *video)
765 Emotion_Gstreamer_Video *ev;
767 ev = (Emotion_Gstreamer_Video *)video;
769 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
771 if (!eina_list_count(ev->audio_streams))
778 em_seekable(void *video __UNUSED__)
784 em_frame_done(void *video __UNUSED__)
788 static Emotion_Format
789 em_format_get(void *video)
791 Emotion_Gstreamer_Video *ev;
792 Emotion_Video_Stream *vstream;
794 ev = (Emotion_Gstreamer_Video *)video;
796 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
797 return EMOTION_FORMAT_NONE;
799 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
802 switch (vstream->fourcc)
804 case GST_MAKE_FOURCC('I', '4', '2', '0'):
805 return EMOTION_FORMAT_I420;
806 case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
807 return EMOTION_FORMAT_YV12;
808 case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
809 return EMOTION_FORMAT_YUY2;
810 case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
811 return EMOTION_FORMAT_BGRA;
813 return EMOTION_FORMAT_NONE;
816 return EMOTION_FORMAT_NONE;
820 em_video_data_size_get(void *video, int *w, int *h)
822 Emotion_Gstreamer_Video *ev;
823 Emotion_Video_Stream *vstream;
825 ev = (Emotion_Gstreamer_Video *)video;
827 if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
830 vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
834 *h = vstream->height;
845 em_yuv_rows_get(void *video __UNUSED__,
848 unsigned char **yrows __UNUSED__,
849 unsigned char **urows __UNUSED__,
850 unsigned char **vrows __UNUSED__)
856 em_bgra_data_get(void *video __UNUSED__, unsigned char **bgra_data __UNUSED__)
862 em_event_feed(void *video __UNUSED__, int event __UNUSED__)
867 em_event_mouse_button_feed(void *video __UNUSED__, int button __UNUSED__, int x __UNUSED__, int y __UNUSED__)
872 em_event_mouse_move_feed(void *video __UNUSED__, int x __UNUSED__, int y __UNUSED__)
878 em_video_channel_count(void *video)
880 Emotion_Gstreamer_Video *ev;
882 ev = (Emotion_Gstreamer_Video *)video;
884 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
886 return eina_list_count(ev->video_streams);
890 em_video_channel_set(void *video __UNUSED__,
891 int channel __UNUSED__)
894 Emotion_Gstreamer_Video *ev;
896 ev = (Emotion_Gstreamer_Video *)video;
898 if (channel < 0) channel = 0;
900 /* FIXME: a faire... */
904 em_video_channel_get(void *video)
906 Emotion_Gstreamer_Video *ev;
908 ev = (Emotion_Gstreamer_Video *)video;
910 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
912 return ev->video_stream_nbr;
916 em_video_channel_name_get(void *video __UNUSED__,
917 int channel __UNUSED__)
923 em_video_channel_mute_set(void *video,
926 Emotion_Gstreamer_Video *ev;
928 ev = (Emotion_Gstreamer_Video *)video;
930 ev->video_mute = mute;
934 em_video_channel_mute_get(void *video)
936 Emotion_Gstreamer_Video *ev;
938 ev = (Emotion_Gstreamer_Video *)video;
940 return ev->video_mute;
946 em_audio_channel_count(void *video)
948 Emotion_Gstreamer_Video *ev;
950 ev = (Emotion_Gstreamer_Video *)video;
952 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
954 return eina_list_count(ev->audio_streams);
958 em_audio_channel_set(void *video __UNUSED__,
959 int channel __UNUSED__)
962 Emotion_Gstreamer_Video *ev;
964 ev = (Emotion_Gstreamer_Video *)video;
966 if (channel < -1) channel = -1;
968 /* FIXME: a faire... */
972 em_audio_channel_get(void *video)
974 Emotion_Gstreamer_Video *ev;
976 ev = (Emotion_Gstreamer_Video *)video;
978 _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
980 return ev->audio_stream_nbr;
984 em_audio_channel_name_get(void *video __UNUSED__,
985 int channel __UNUSED__)
990 #define GST_PLAY_FLAG_AUDIO (1 << 1)
993 em_audio_channel_mute_set(void *video,
996 Emotion_Gstreamer_Video *ev;
999 ev = (Emotion_Gstreamer_Video *)video;
1001 if (!ev->pipeline) return ;
1003 ev->audio_mute = mute;
1005 g_object_set(G_OBJECT(ev->pipeline), "mute", !!mute, NULL);
1006 /* This code should stop the decoding of only the audio stream, but everything stop :"( */
1007 /* g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL); */
1009 /* flags &= ~GST_PLAY_FLAG_AUDIO; */
1011 /* flags |= GST_PLAY_FLAG_AUDIO; */
1012 /* g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL); */
1013 /* g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL); */
1014 /* fprintf(stderr, "flags-n: %x\n", flags); */
1018 em_audio_channel_mute_get(void *video)
1020 Emotion_Gstreamer_Video *ev;
1022 ev = (Emotion_Gstreamer_Video *)video;
1024 return ev->audio_mute;
1028 em_audio_channel_volume_set(void *video,
1031 Emotion_Gstreamer_Video *ev;
1033 ev = (Emotion_Gstreamer_Video *)video;
1035 if (!ev->pipeline) return ;
1042 g_object_set(G_OBJECT(ev->pipeline), "volume", vol, NULL);
1046 em_audio_channel_volume_get(void *video)
1048 Emotion_Gstreamer_Video *ev;
1050 ev = (Emotion_Gstreamer_Video *)video;
1058 em_spu_channel_count(void *video __UNUSED__)
1064 em_spu_channel_set(void *video __UNUSED__, int channel __UNUSED__)
1069 em_spu_channel_get(void *video __UNUSED__)
1075 em_spu_channel_name_get(void *video __UNUSED__, int channel __UNUSED__)
1081 em_spu_channel_mute_set(void *video __UNUSED__, int mute __UNUSED__)
1086 em_spu_channel_mute_get(void *video __UNUSED__)
1092 em_chapter_count(void *video __UNUSED__)
1098 em_chapter_set(void *video __UNUSED__, int chapter __UNUSED__)
1103 em_chapter_get(void *video __UNUSED__)
1109 em_chapter_name_get(void *video __UNUSED__, int chapter __UNUSED__)
1115 em_speed_set(void *video __UNUSED__, double speed __UNUSED__)
1120 em_speed_get(void *video __UNUSED__)
1126 em_eject(void *video __UNUSED__)
1132 em_meta_get(void *video, int meta)
1134 Emotion_Gstreamer_Video *ev;
1135 const char *str = NULL;
1137 ev = (Emotion_Gstreamer_Video *)video;
1139 if (!ev || !ev->metadata) return NULL;
1142 case META_TRACK_TITLE:
1143 str = ev->metadata->title;
1145 case META_TRACK_ARTIST:
1146 str = ev->metadata->artist;
1148 case META_TRACK_ALBUM:
1149 str = ev->metadata->album;
1151 case META_TRACK_YEAR:
1152 str = ev->metadata->year;
1154 case META_TRACK_GENRE:
1155 str = ev->metadata->genre;
1157 case META_TRACK_COMMENT:
1158 str = ev->metadata->comment;
1160 case META_TRACK_DISCID:
1161 str = ev->metadata->disc_id;
1171 module_open(Evas_Object *obj,
1172 const Emotion_Video_Module **module,
1174 Emotion_Module_Options *opt)
1179 if (_emotion_gstreamer_log_domain < 0)
1181 eina_threads_init();
1182 eina_log_threads_enable();
1183 _emotion_gstreamer_log_domain = eina_log_domain_register
1184 ("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);
1185 if (_emotion_gstreamer_log_domain < 0)
1187 EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");
1192 if (!em_module.init(obj, video, opt))
1195 eina_threads_init();
1197 *module = &em_module;
1202 module_close(Emotion_Video_Module *module __UNUSED__,
1205 em_module.shutdown(video);
1207 eina_threads_shutdown();
1211 gstreamer_module_init(void)
1215 if (!gst_init_check(0, NULL, &error))
1217 EINA_LOG_CRIT("Could not init GStreamer");
1221 if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
1223 "video sink plugin for Emotion",
1224 gstreamer_plugin_init,
1229 "http://www.enlightenment.org/") == FALSE)
1231 EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");
1235 return _emotion_module_register("gstreamer", module_open, module_close);
1239 gstreamer_module_shutdown(void)
1241 _emotion_module_unregister("gstreamer");
1246 #ifndef EMOTION_STATIC_BUILD_GSTREAMER
1248 EINA_MODULE_INIT(gstreamer_module_init);
1249 EINA_MODULE_SHUTDOWN(gstreamer_module_shutdown);
1254 _for_each_tag(GstTagList const* list,
1258 Emotion_Gstreamer_Video *ev;
1263 ev = (Emotion_Gstreamer_Video*)data;
1265 if (!ev || !ev->metadata) return;
1267 count = gst_tag_list_get_tag_size(list, tag);
1269 for (i = 0; i < count; i++)
1271 if (!strcmp(tag, GST_TAG_TITLE))
1274 if (ev->metadata->title) g_free(ev->metadata->title);
1275 if (gst_tag_list_get_string(list, GST_TAG_TITLE, &str))
1276 ev->metadata->title = str;
1278 ev->metadata->title = NULL;
1281 if (!strcmp(tag, GST_TAG_ALBUM))
1284 if (ev->metadata->album) g_free(ev->metadata->album);
1285 if (gst_tag_list_get_string(list, GST_TAG_ALBUM, &str))
1286 ev->metadata->album = str;
1288 ev->metadata->album = NULL;
1291 if (!strcmp(tag, GST_TAG_ARTIST))
1294 if (ev->metadata->artist) g_free( ev->metadata->artist);
1295 if (gst_tag_list_get_string(list, GST_TAG_ARTIST, &str))
1296 ev->metadata->artist = str;
1298 ev->metadata->artist = NULL;
1301 if (!strcmp(tag, GST_TAG_GENRE))
1304 if (ev->metadata->genre) g_free( ev->metadata->genre);
1305 if (gst_tag_list_get_string(list, GST_TAG_GENRE, &str))
1306 ev->metadata->genre = str;
1308 ev->metadata->genre = NULL;
1311 if (!strcmp(tag, GST_TAG_COMMENT))
1314 if (ev->metadata->comment) g_free(ev->metadata->comment);
1315 if (gst_tag_list_get_string(list, GST_TAG_COMMENT, &str))
1316 ev->metadata->comment = str;
1318 ev->metadata->comment = NULL;
1321 if (!strcmp(tag, GST_TAG_DATE))
1325 if (ev->metadata->year) g_free(ev->metadata->year);
1326 date = gst_tag_list_get_value_index(list, GST_TAG_DATE, 0);
1328 str = g_strdup_value_contents(date);
1331 ev->metadata->year = str;
1335 if (!strcmp(tag, GST_TAG_TRACK_NUMBER))
1338 const GValue *track;
1339 if (ev->metadata->count) g_free( ev->metadata->count);
1340 track = gst_tag_list_get_value_index(list, GST_TAG_TRACK_NUMBER, 0);
1342 str = g_strdup_value_contents(track);
1345 ev->metadata->count = str;
1349 #ifdef GST_TAG_CDDA_CDDB_DISCID
1350 if (!strcmp(tag, GST_TAG_CDDA_CDDB_DISCID))
1353 const GValue *discid;
1354 if (ev->metadata->disc_id) g_free(ev->metadata->disc_id);
1355 discid = gst_tag_list_get_value_index(list, GST_TAG_CDDA_CDDB_DISCID, 0);
1357 str = g_strdup_value_contents(discid);
1360 ev->metadata->disc_id = str;
1369 _free_metadata(Emotion_Gstreamer_Metadata *m)
1373 if (m->title) g_free(m->title);
1374 if (m->album) g_free(m->album);
1375 if (m->artist) g_free(m->artist);
1376 if (m->genre) g_free(m->genre);
1377 if (m->comment) g_free(m->comment);
1378 if (m->year) g_free(m->year);
1379 if (m->count) g_free(m->count);
1380 if (m->disc_id) g_free(m->disc_id);
1386 _eos_main_fct(void *data)
1388 Emotion_Gstreamer_Message *send;
1389 Emotion_Gstreamer_Video *ev;
1396 if (ev->play_started)
1398 _emotion_playback_started(ev->obj);
1399 ev->play_started = 0;
1402 switch (GST_MESSAGE_TYPE(msg))
1404 case GST_MESSAGE_ERROR:
1409 gst_message_parse_error(msg, &err, &debug);
1412 ERR("Error: %s", err->message);
1417 case GST_MESSAGE_EOS:
1419 _emotion_decode_stop(ev->obj);
1420 _emotion_playback_finished(ev->obj);
1422 case GST_MESSAGE_TAG:
1424 GstTagList *new_tags;
1425 gst_message_parse_tag(msg, &new_tags);
1428 gst_tag_list_foreach(new_tags,
1429 (GstTagForeachFunc)_for_each_tag,
1431 gst_tag_list_free(new_tags);
1435 case GST_MESSAGE_ASYNC_DONE:
1436 _emotion_seek_done(ev->obj);
1439 ERR("bus say: %s [%i]",
1440 GST_MESSAGE_SRC_NAME(msg),
1441 GST_MESSAGE_TYPE(msg));
1445 emotion_gstreamer_message_free(send);
1448 static GstBusSyncReply
1449 _eos_sync_fct(GstBus *bus, GstMessage *msg, gpointer data)
1451 Emotion_Gstreamer_Video *ev = data;
1452 Emotion_Gstreamer_Message *send;
1454 switch (GST_MESSAGE_TYPE(msg))
1456 case GST_MESSAGE_ERROR:
1457 case GST_MESSAGE_EOS:
1458 case GST_MESSAGE_TAG:
1459 case GST_MESSAGE_ASYNC_DONE:
1460 send = emotion_gstreamer_message_alloc(ev, msg);
1462 if (send) ecore_main_loop_thread_safe_call(_eos_main_fct, send);
1467 WRN("bus say: %s [%i]",
1468 GST_MESSAGE_SRC_NAME(msg),
1469 GST_MESSAGE_TYPE(msg));
1473 return GST_BUS_DROP;
1477 _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
1483 if (ev->pipeline_parsed)
1486 if (force && ev->thread)
1488 ecore_thread_cancel(ev->thread);
1495 res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1496 if (res == GST_STATE_CHANGE_NO_PREROLL)
1497 gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
1499 res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1500 if (!(res == GST_STATE_CHANGE_SUCCESS
1501 || res == GST_STATE_CHANGE_NO_PREROLL))
1503 /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
1504 /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */
1505 if (getenv("EMOTION_GSTREAMER_DOT"))
1506 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline),
1507 GST_DEBUG_GRAPH_SHOW_ALL,
1508 getenv("EMOTION_GSTREAMER_DOT"));
1510 ERR("Unable to get GST_CLOCK_TIME_NONE.");
1514 g_object_get(G_OBJECT(ev->pipeline),
1515 "n-audio", &ev->audio_stream_nbr,
1516 "n-video", &ev->video_stream_nbr,
1519 if ((ev->video_stream_nbr == 0) && (ev->audio_stream_nbr == 0))
1521 ERR("No audio nor video stream found");
1526 for (i = 0; i < ev->video_stream_nbr; i++)
1528 Emotion_Video_Stream *vstream;
1531 GstStructure *structure;
1536 gdouble length_time = 0.0;
1543 g_signal_emit_by_name(ev->pipeline, "get-video-pad", i, &pad);
1547 caps = gst_pad_get_negotiated_caps(pad);
1550 structure = gst_caps_get_structure(caps, 0);
1551 str = gst_caps_to_string(caps);
1553 if (!gst_structure_get_int(structure, "width", &width))
1555 if (!gst_structure_get_int(structure, "height", &height))
1557 if (!gst_structure_get_fraction(structure, "framerate", &fps_num, &fps_den))
1560 if (g_str_has_prefix(str, "video/x-raw-yuv"))
1562 val = gst_structure_get_value(structure, "format");
1563 fourcc = gst_value_get_fourcc(val);
1565 else if (g_str_has_prefix(str, "video/x-raw-rgb"))
1566 fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
1570 query = gst_query_new_duration(GST_FORMAT_TIME);
1571 if (gst_pad_peer_query(pad, query))
1575 gst_query_parse_duration(query, NULL, &t);
1576 length_time = (double)t / (double)GST_SECOND;
1581 vstream = emotion_video_stream_new(ev);
1582 if (!vstream) goto unref_query_v;
1584 vstream->length_time = length_time;
1585 vstream->width = width;
1586 vstream->height = height;
1587 vstream->fps_num = fps_num;
1588 vstream->fps_den = fps_den;
1589 vstream->fourcc = fourcc;
1593 gst_query_unref(query);
1595 gst_caps_unref(caps);
1597 gst_object_unref(pad);
1601 for (i = 0; i < ev->audio_stream_nbr; i++)
1603 Emotion_Audio_Stream *astream;
1606 GstStructure *structure;
1609 gdouble length_time = 0.0;
1613 g_signal_emit_by_name(ev->pipeline, "get-audio-pad", i, &pad);
1617 caps = gst_pad_get_negotiated_caps(pad);
1620 structure = gst_caps_get_structure(caps, 0);
1622 if (!gst_structure_get_int(structure, "channels", &channels))
1624 if (!gst_structure_get_int(structure, "rate", &samplerate))
1627 query = gst_query_new_duration(GST_FORMAT_TIME);
1628 if (gst_pad_peer_query(pad, query))
1632 gst_query_parse_duration(query, NULL, &t);
1633 length_time = (double)t / (double)GST_SECOND;
1638 astream = calloc(1, sizeof(Emotion_Audio_Stream));
1639 if (!astream) continue;
1640 ev->audio_streams = eina_list_append(ev->audio_streams, astream);
1641 if (eina_error_get())
1647 astream->length_time = length_time;
1648 astream->channels = channels;
1649 astream->samplerate = samplerate;
1652 gst_query_unref(query);
1654 gst_caps_unref(caps);
1656 gst_object_unref(pad);
1659 /* Visualization sink */
1660 if (ev->video_stream_nbr == 0)
1662 GstElement *vis = NULL;
1663 Emotion_Video_Stream *vstream;
1664 Emotion_Audio_Stream *astream;
1666 const char *vis_name;
1668 if (!(vis_name = emotion_visualization_element_name_get(ev->vis)))
1670 WRN("pb vis name %d", ev->vis);
1674 astream = eina_list_data_get(ev->audio_streams);
1676 vis = gst_element_factory_make(vis_name, "vissink");
1677 vstream = emotion_video_stream_new(ev);
1681 DBG("could not create visualization stream");
1683 vstream->length_time = astream->length_time;
1684 vstream->width = 320;
1685 vstream->height = 200;
1686 vstream->fps_num = 25;
1687 vstream->fps_den = 1;
1688 vstream->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
1690 g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL);
1691 g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL);
1692 flags |= 0x00000008;
1693 g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL);
1698 ev->video_stream_nbr = eina_list_count(ev->video_streams);
1699 ev->audio_stream_nbr = eina_list_count(ev->audio_streams);
1701 if (ev->video_stream_nbr == 1)
1703 Emotion_Video_Stream *vstream;
1705 vstream = eina_list_data_get(ev->video_streams);
1706 ev->ratio = (double)vstream->width / (double)vstream->height;
1707 _emotion_frame_resize(ev->obj, vstream->width, vstream->height, ev->ratio);
1711 /* on recapitule : */
1712 Emotion_Video_Stream *vstream;
1713 Emotion_Audio_Stream *astream;
1715 vstream = eina_list_data_get(ev->video_streams);
1718 DBG("video size=%dx%d, fps=%d/%d, "
1719 "fourcc=%"GST_FOURCC_FORMAT", length=%"GST_TIME_FORMAT,
1720 vstream->width, vstream->height, vstream->fps_num, vstream->fps_den,
1721 GST_FOURCC_ARGS(vstream->fourcc),
1722 GST_TIME_ARGS((guint64)(vstream->length_time * GST_SECOND)));
1725 astream = eina_list_data_get(ev->audio_streams);
1728 DBG("audio channels=%d, rate=%d, length=%"GST_TIME_FORMAT,
1729 astream->channels, astream->samplerate,
1730 GST_TIME_ARGS((guint64)(astream->length_time * GST_SECOND)));
1735 _free_metadata(ev->metadata);
1736 ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));
1738 em_audio_channel_volume_set(ev, ev->volume);
1739 em_audio_channel_mute_set(ev, ev->audio_mute);
1741 if (ev->play_started)
1743 _emotion_playback_started(ev->obj);
1744 ev->play_started = 0;
1747 _emotion_open_done(ev->obj);
1748 ev->pipeline_parsed = EINA_TRUE;