efl
1820 строк · 43.9 Кб
1#ifdef HAVE_CONFIG_H2# include "config.h"3#endif4#include "emotion_gstreamer.h"5
6int _emotion_gstreamer_log_domain = -1;7Eina_Bool debug_fps = EINA_FALSE;8
9static int _emotion_init_count = 0;10
11/* Callbacks to get the eos */
12static void _for_each_tag (GstTagList const* list, gchar const* tag, void *data);13static void _free_metadata (Emotion_Gstreamer_Metadata *m);14
15static GstElement * _create_pipeline (Emotion_Gstreamer *ev, Evas_Object *o, const char *uri, const char *suburi);16
17static GstBusSyncReply _bus_sync_handler(GstBus *bus,18GstMessage *message,19gpointer data);20
21static void em_audio_channel_volume_set(void *video, double vol);22static void em_audio_channel_mute_set(void *video, int mute);23
24/* Module interface */
25
26static const char *27emotion_visualization_element_name_get(Emotion_Vis visualisation)28{
29switch (visualisation)30{31case EMOTION_VIS_NONE:32return NULL;33case EMOTION_VIS_GOOM:34return "goom";35case EMOTION_VIS_LIBVISUAL_BUMPSCOPE:36return "libvisual_bumpscope";37case EMOTION_VIS_LIBVISUAL_CORONA:38return "libvisual_corona";39case EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES:40return "libvisual_dancingparticles";41case EMOTION_VIS_LIBVISUAL_GDKPIXBUF:42return "libvisual_gdkpixbuf";43case EMOTION_VIS_LIBVISUAL_G_FORCE:44return "libvisual_G-Force";45case EMOTION_VIS_LIBVISUAL_GOOM:46return "libvisual_goom";47case EMOTION_VIS_LIBVISUAL_INFINITE:48return "libvisual_infinite";49case EMOTION_VIS_LIBVISUAL_JAKDAW:50return "libvisual_jakdaw";51case EMOTION_VIS_LIBVISUAL_JESS:52return "libvisual_jess";53case EMOTION_VIS_LIBVISUAL_LV_ANALYSER:54return "libvisual_lv_analyzer";55case EMOTION_VIS_LIBVISUAL_LV_FLOWER:56return "libvisual_lv_flower";57case EMOTION_VIS_LIBVISUAL_LV_GLTEST:58return "libvisual_lv_gltest";59case EMOTION_VIS_LIBVISUAL_LV_SCOPE:60return "libvisual_lv_scope";61case EMOTION_VIS_LIBVISUAL_MADSPIN:62return "libvisual_madspin";63case EMOTION_VIS_LIBVISUAL_NEBULUS:64return "libvisual_nebulus";65case EMOTION_VIS_LIBVISUAL_OINKSIE:66return "libvisual_oinksie";67case EMOTION_VIS_LIBVISUAL_PLASMA:68return "libvisual_plazma";69default:70return "goom";71}72}
73
74Emotion_Gstreamer *75emotion_gstreamer_ref(Emotion_Gstreamer *ev)76{
77g_atomic_int_inc (&ev->ref_count);78return ev;79}
80
81void
82emotion_gstreamer_unref(Emotion_Gstreamer *ev)83{
84if (g_atomic_int_dec_and_test(&ev->ref_count))85{86if (ev->subtitle)87{88eina_stringshare_del(ev->subtitle);89ev->subtitle = NULL;90}91free(ev);92}93}
94
95static Eina_Bool96em_file_open(void *video,97const char *file)98{
99Emotion_Gstreamer *ev = video;100char *uri;101char *suburi = NULL;102gboolean mute = 0;103gdouble vol = 0.0;104
105if (!file) return EINA_FALSE;106
107if (gst_uri_is_valid(file)) uri = strdup(file);108else uri = gst_filename_to_uri(file, NULL);109if (!uri) return EINA_FALSE;110
111ev->shutdown = EINA_FALSE;112ev->ready = EINA_FALSE;113ev->live = EINA_FALSE;114ev->buffering = EINA_FALSE;115
116DBG("setting file to '%s'", uri);117
118if (ev->subtitle)119{120if (gst_uri_is_valid(ev->subtitle)) suburi = strdup(ev->subtitle);121else suburi = gst_filename_to_uri(ev->subtitle, NULL);122}123ev->pipeline = _create_pipeline(ev, ev->obj, uri, suburi);124g_free(uri);125
126if (!ev->pipeline)127return EINA_FALSE;128
129g_object_get(ev->pipeline, "volume", &vol, NULL);130g_object_get(ev->pipeline, "mute", &mute, NULL);131ev->volume = vol;132ev->audio_mute = mute;133
134ev->position = 0.0;135
136return EINA_TRUE;137}
138
139static void140em_file_close(void *video)141{
142Emotion_Gstreamer *ev = video;143Eina_List *l;144
145ev->shutdown = EINA_TRUE;146
147if (ev->threads)148{149Ecore_Thread *t;150
151EINA_LIST_FOREACH(ev->threads, l, t)152{153ecore_thread_cancel(t);154}155}156
157if (ev->pipeline)158{159if (ev->audio_buffer_probe)160{161gst_pad_remove_probe(ev->audio_buffer_probe_pad, ev->audio_buffer_probe);162gst_object_unref(ev->audio_buffer_probe_pad);163ev->audio_buffer_probe_pad = NULL;164ev->audio_buffer_probe = 0;165}166
167gst_element_set_state(ev->pipeline, GST_STATE_NULL);168g_object_set(G_OBJECT(ev->vsink), "emotion-object", NULL, NULL);169gst_object_unref(ev->pipeline);170
171ev->pipeline = NULL;172ev->vsink = NULL;173}174
175if (ev->metadata)176{177_free_metadata(ev->metadata);178ev->metadata = NULL;179}180
181ev->ready = EINA_FALSE;182}
183
184static void185em_del(void *video)186{
187Emotion_Gstreamer *ev = video;188
189em_file_close(ev);190
191emotion_gstreamer_unref(ev);192}
193
194static void195em_play(void *video,196double pos EINA_UNUSED)197{
198Emotion_Gstreamer *ev = video;199
200if (!ev->pipeline) return;201
202if (ev->ready && !ev->buffering)203gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);204ev->play = EINA_TRUE;205}
206
207static void208em_stop(void *video)209{
210Emotion_Gstreamer *ev = video;211
212if (!ev->pipeline) return;213
214if (ev->ready)215gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);216ev->play = EINA_FALSE;217}
218
219static void220em_size_get(void *video,221int *width,222int *height)223{
224Emotion_Gstreamer *ev = video;225gint cur;226GstPad *pad;227GstCaps *caps;228GstVideoInfo info;229
230if (width) *width = 0;231if (height) *height = 0;232
233if (!ev->ready)234return;235
236g_object_get(ev->pipeline, "current-video", &cur, NULL);237g_signal_emit_by_name (ev->pipeline, "get-video-pad", cur, &pad);238if (!pad)239return;240
241caps = gst_pad_get_current_caps(pad);242gst_object_unref(pad);243if (!caps)244return;245
246gst_video_info_from_caps (&info, caps);247if (width) *width = info.width;248if (height) *height = info.height;249gst_caps_unref(caps);250}
251
252static void253em_pos_set(void *video,254double pos)255{
256Emotion_Gstreamer *ev = video;257
258if (!ev->ready) return;259
260gst_element_seek(ev->pipeline, 1.0,261GST_FORMAT_TIME,262GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,263GST_SEEK_TYPE_SET,264(gint64)(pos * (double)GST_SECOND),265GST_SEEK_TYPE_NONE, -1);266}
267
268static double269em_len_get(void *video)270{
271Emotion_Gstreamer *ev = video;272gint64 val;273gboolean ret;274
275if (!ev->ready)276return 0.0;277
278ret = gst_element_query_duration(ev->pipeline, GST_FORMAT_TIME, &val);279if (!ret || val == -1)280return 0.0;281
282return val / 1000000000.0;283}
284
285static double286em_buffer_size_get(void *video)287{
288Emotion_Gstreamer *ev = video;289GstQuery *query;290gboolean busy;291gint percent;292
293if (!ev->ready) return 0.0;294
295query = gst_query_new_buffering(GST_FORMAT_DEFAULT);296if (gst_element_query(ev->pipeline, query))297gst_query_parse_buffering_percent(query, &busy, &percent);298else299percent = 100;300
301gst_query_unref(query);302return ((float)(percent)) / 100.0;303}
304
305static Eina_Bool306_em_fps_get(Emotion_Gstreamer *ev, int *n, int *d)307{
308gint cur;309GstPad *pad;310GstCaps *caps;311GstVideoInfo info;312Eina_Bool ret = EINA_FALSE;313
314if (n) *n = 0;315if (d) *d = 1;316
317if (!ev->ready)318goto on_error;319
320g_object_get(ev->pipeline, "current-video", &cur, NULL);321g_signal_emit_by_name (ev->pipeline, "get-video-pad", cur, &pad);322if (!pad)323goto on_error;324
325caps = gst_pad_get_current_caps(pad);326gst_object_unref(pad);327if (!caps)328goto on_error;329
330gst_video_info_from_caps (&info, caps);331if (n) *n = info.fps_n;332if (d) *d = info.fps_d;333gst_caps_unref(caps);334ret = EINA_TRUE;335
336on_error:337
338return ret;339}
340
341static int342em_fps_num_get(void *video)343{
344Emotion_Gstreamer *ev = video;345int num;346
347_em_fps_get(ev, &num, NULL);348
349return num;350}
351
352static int353em_fps_den_get(void *video)354{
355Emotion_Gstreamer *ev = video;356int den;357
358_em_fps_get(ev, NULL, &den);359
360return den;361}
362
363static double364em_fps_get(void *video)365{
366Emotion_Gstreamer *ev = video;367int num, den;368
369if (!ev->ready)370return 0.0;371
372_em_fps_get(ev, &num, &den);373
374return (double)num / (double)den;375}
376
377static double378em_pos_get(void *video)379{
380Emotion_Gstreamer *ev = video;381gint64 val;382gboolean ret;383
384if (!ev->ready) return 0.0;385
386ret = gst_element_query_position(ev->pipeline, GST_FORMAT_TIME, &val);387if (!ret || val == -1)388return ev->position;389
390ev->position = val / 1000000000.0;391return ev->position;392}
393
394static void395em_vis_set(void *video,396Emotion_Vis vis)397{
398Emotion_Gstreamer *ev = video;399
400ev->vis = vis;401}
402
403static Emotion_Vis404em_vis_get(void *video)405{
406Emotion_Gstreamer *ev = video;407
408return ev->vis;409}
410
411static Eina_Bool412em_vis_supported(void *ef EINA_UNUSED, Emotion_Vis vis)413{
414const char *name;415GstElementFactory *factory;416
417if (vis == EMOTION_VIS_NONE)418return EINA_TRUE;419
420name = emotion_visualization_element_name_get(vis);421if (!name)422return EINA_FALSE;423
424factory = gst_element_factory_find(name);425if (!factory)426return EINA_FALSE;427
428gst_object_unref(factory);429return EINA_TRUE;430}
431
432static double433em_ratio_get(void *video)434{
435Emotion_Gstreamer *ev = video;436gint cur;437GstPad *pad;438GstCaps *caps;439GstVideoInfo info;440
441info.par_n = info.par_d = 1;442
443if (!ev->ready)444goto on_error;445
446g_object_get(ev->pipeline, "current-video", &cur, NULL);447g_signal_emit_by_name (ev->pipeline, "get-video-pad", cur, &pad);448if (!pad)449goto on_error;450
451caps = gst_pad_get_current_caps(pad);452gst_object_unref(pad);453if (!caps)454goto on_error;455
456gst_video_info_from_caps (&info, caps);457gst_caps_unref(caps);458
459on_error:460
461return (double)info.par_n / (double)info.par_d;462}
463
464static int em_audio_channel_count(void *video);465static int em_video_channel_count(void *video);466
467static int468em_video_handled(void *video)469{
470Emotion_Gstreamer *ev = video;471
472return em_video_channel_count(ev) > 0 ? 1 : 0;473}
474
475static int476em_audio_handled(void *video)477{
478Emotion_Gstreamer *ev = video;479
480return em_audio_channel_count(ev) > 0 ? 1 : 0;481}
482
483static int484em_seekable(void *video)485{
486Emotion_Gstreamer *ev = video;487GstQuery *query;488int ret = 0;489gboolean seekable;490
491if (!ev->ready) return ret;492
493query = gst_query_new_seeking(GST_FORMAT_TIME);494if (!gst_element_query(ev->pipeline, query))495goto on_error;496
497gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);498if (!seekable)499goto on_error;500
501ret = 1;502
503on_error:504gst_query_unref(query);505
506return ret;507}
508
509static void510em_frame_done(void *video EINA_UNUSED)511{
512}
513
514static Emotion_Format515em_format_get(void *video)516{
517Emotion_Gstreamer *ev = video;518gint cur;519GstPad *pad;520GstCaps *caps;521GstVideoInfo info;522Emotion_Format format = EMOTION_FORMAT_NONE;523
524if (!ev->ready)525goto on_error;526
527g_object_get(ev->pipeline, "current-video", &cur, NULL);528g_signal_emit_by_name (ev->pipeline, "get-video-pad", cur, &pad);529if (!pad)530goto on_error;531
532caps = gst_pad_get_current_caps(pad);533gst_object_unref(pad);534if (!caps)535goto on_error;536
537gst_video_info_from_caps (&info, caps);538gst_caps_unref(caps);539
540switch (info.finfo->format)541{542case GST_VIDEO_FORMAT_I420:543return EMOTION_FORMAT_I420;544case GST_VIDEO_FORMAT_YV12:545return EMOTION_FORMAT_YV12;546case GST_VIDEO_FORMAT_YUY2:547return EMOTION_FORMAT_YUY2;548case GST_VIDEO_FORMAT_ARGB:549/* FIXME: This will be wrong for big endian archs */550return EMOTION_FORMAT_BGRA;551default:552return EMOTION_FORMAT_NONE;553}554
555on_error:556
557return format;558}
559
560static void561em_video_data_size_get(void *video, int *w, int *h)562{
563em_size_get(video, w, h);564}
565
566static int567em_yuv_rows_get(void *video EINA_UNUSED,568int w EINA_UNUSED,569int h EINA_UNUSED,570unsigned char **yrows EINA_UNUSED,571unsigned char **urows EINA_UNUSED,572unsigned char **vrows EINA_UNUSED)573{
574return 0;575}
576
577static int578em_bgra_data_get(void *video EINA_UNUSED, unsigned char **bgra_data EINA_UNUSED)579{
580return 0;581}
582
583static void584em_event_feed(void *video, int event)585{
586Emotion_Gstreamer *ev = video;587GstNavigationCommand command;588
589if (!ev->ready) return;590
591switch (event)592{593case EMOTION_EVENT_MENU1:594command = GST_NAVIGATION_COMMAND_MENU1;595break;596case EMOTION_EVENT_MENU2:597command = GST_NAVIGATION_COMMAND_MENU2;598break;599case EMOTION_EVENT_MENU3:600command = GST_NAVIGATION_COMMAND_MENU3;601break;602case EMOTION_EVENT_MENU4:603command = GST_NAVIGATION_COMMAND_MENU4;604break;605case EMOTION_EVENT_MENU5:606command = GST_NAVIGATION_COMMAND_MENU5;607break;608case EMOTION_EVENT_MENU6:609command = GST_NAVIGATION_COMMAND_MENU6;610break;611case EMOTION_EVENT_MENU7:612command = GST_NAVIGATION_COMMAND_MENU7;613break;614case EMOTION_EVENT_UP:615command = GST_NAVIGATION_COMMAND_UP;616break;617case EMOTION_EVENT_DOWN:618command = GST_NAVIGATION_COMMAND_DOWN;619break;620case EMOTION_EVENT_LEFT:621command = GST_NAVIGATION_COMMAND_LEFT;622break;623case EMOTION_EVENT_RIGHT:624command = GST_NAVIGATION_COMMAND_RIGHT;625break;626case EMOTION_EVENT_SELECT:627command = GST_NAVIGATION_COMMAND_ACTIVATE;628break;629case EMOTION_EVENT_NEXT:630/* FIXME */631command = GST_NAVIGATION_COMMAND_RIGHT;632break;633case EMOTION_EVENT_PREV:634/* FIXME */635command = GST_NAVIGATION_COMMAND_LEFT;636break;637case EMOTION_EVENT_ANGLE_NEXT:638command = GST_NAVIGATION_COMMAND_NEXT_ANGLE;639break;640case EMOTION_EVENT_ANGLE_PREV:641command = GST_NAVIGATION_COMMAND_PREV_ANGLE;642break;643case EMOTION_EVENT_FORCE:644/* FIXME */645command = GST_NAVIGATION_COMMAND_ACTIVATE;646break;647case EMOTION_EVENT_0:648case EMOTION_EVENT_1:649case EMOTION_EVENT_2:650case EMOTION_EVENT_3:651case EMOTION_EVENT_4:652case EMOTION_EVENT_5:653case EMOTION_EVENT_6:654case EMOTION_EVENT_7:655case EMOTION_EVENT_8:656case EMOTION_EVENT_9:657case EMOTION_EVENT_10:658default:659return;660break;661}662
663gst_navigation_send_command (GST_NAVIGATION (ev->pipeline), command);664}
665
666static void667em_event_mouse_button_feed(void *video, int button, int x, int y)668{
669Emotion_Gstreamer *ev = video;670
671if (!ev->ready) return;672
673/* FIXME */674gst_navigation_send_mouse_event (GST_NAVIGATION (ev->pipeline), "mouse-button-press", button, x, y);675gst_navigation_send_mouse_event (GST_NAVIGATION (ev->pipeline), "mouse-button-release", button, x, y);676}
677
678static void679em_event_mouse_move_feed(void *video, int x, int y)680{
681Emotion_Gstreamer *ev = video;682
683if (!ev->ready) return;684
685gst_navigation_send_mouse_event (GST_NAVIGATION (ev->pipeline), "mouse-move", 0, x, y);686}
687
688/* Video channels */
689static int690em_video_channel_count(void *video)691{
692Emotion_Gstreamer *ev = video;693gint n;694
695if (!ev->ready) return 0;696
697g_object_get(ev->pipeline, "n-video", &n, NULL);698
699return n;700}
701
702static void703em_video_channel_set(void *video,704int channel)705{
706Emotion_Gstreamer *ev = video;707
708if (!ev->ready) return;709
710if (channel < 0) channel = -1;711
712g_object_set (ev->pipeline, "current-video", channel, NULL);713}
714
715static int716em_video_channel_get(void *video)717{
718Emotion_Gstreamer *ev = video;719gint cur;720
721if (!ev->ready) return -1;722
723g_object_get(ev->pipeline, "current-video", &cur, NULL);724
725return cur;726}
727
728static void729em_video_subtitle_file_set(void *video,730const char *filepath)731{
732Emotion_Gstreamer *ev = video;733
734eina_stringshare_replace(&(ev->subtitle), filepath);735}
736
737static const char *738em_video_subtitle_file_get(void *video)739{
740Emotion_Gstreamer *ev = video;741
742return ev->subtitle;743}
744
745static const char *746em_video_channel_name_get(void *video EINA_UNUSED,747int channel EINA_UNUSED)748{
749return NULL;750}
751
752static void753em_video_channel_mute_set(void *video,754int mute)755{
756Emotion_Gstreamer *ev = video;757
758ev->video_mute = mute;759}
760
761static int762em_video_channel_mute_get(void *video)763{
764Emotion_Gstreamer *ev = video;765
766return ev->video_mute;767}
768
769/* Audio channels */
770
771static int772em_audio_channel_count(void *video)773{
774Emotion_Gstreamer *ev = video;775gint n;776
777if (!ev->ready) return 0;778
779g_object_get(ev->pipeline, "n-audio", &n, NULL);780
781return n;782}
783
784static void785em_audio_channel_set(void *video,786int channel)787{
788Emotion_Gstreamer *ev = video;789
790if (!ev->ready) return;791
792if (channel < 0) channel = -1;793
794g_object_set (ev->pipeline, "current-audio", channel, NULL);795}
796
797static int798em_audio_channel_get(void *video)799{
800Emotion_Gstreamer *ev = video;801gint cur;802
803if (!ev->ready) return -1;804
805g_object_get(ev->pipeline, "current-audio", &cur, NULL);806
807return cur;808}
809
810static const char *811em_audio_channel_name_get(void *video EINA_UNUSED,812int channel EINA_UNUSED)813{
814return NULL;815}
816
817static void818em_audio_channel_mute_set(void *video,819int mute)820{
821Emotion_Gstreamer *ev = video;822
823ev->audio_mute = !!mute;824
825if (!ev->pipeline) return;826
827g_object_set(G_OBJECT(ev->pipeline), "mute", !!mute, NULL);828}
829
830static int831em_audio_channel_mute_get(void *video)832{
833Emotion_Gstreamer *ev = video;834gboolean mute;835
836if (!ev->pipeline)837return ev->audio_mute;838
839g_object_get(ev->pipeline, "mute", &mute, NULL);840
841return !!mute;842}
843
844static void845em_audio_channel_volume_set(void *video,846double vol)847{
848Emotion_Gstreamer *ev = video;849
850if (vol < 0.0)851vol = 0.0;852ev->volume = vol;853
854if (!ev->pipeline) return;855
856g_object_set(G_OBJECT(ev->pipeline), "volume", vol, NULL);857}
858
859static double860em_audio_channel_volume_get(void *video)861{
862Emotion_Gstreamer *ev = video;863gdouble vol;864
865if (!ev->pipeline)866return ev->volume;867
868g_object_get(ev->pipeline, "volume", &vol, NULL);869
870return vol;871}
872
873/* spu stuff */
874
875static int876em_spu_channel_count(void *video)877{
878Emotion_Gstreamer *ev = video;879gint n;880
881if (!ev->ready) return 0;882
883g_object_get(ev->pipeline, "n-text", &n, NULL);884
885return n;886}
887
888static void889em_spu_channel_set(void *video, int channel)890{
891Emotion_Gstreamer *ev = video;892
893if (!ev->ready) return;894
895if (channel < 0) channel = -1;896
897g_object_set(ev->pipeline, "current-text", channel, NULL);898}
899
900static int901em_spu_channel_get(void *video)902{
903Emotion_Gstreamer *ev = video;904gint cur;905
906if (!ev->ready) return -1;907
908g_object_get(ev->pipeline, "current-text", &cur, NULL);909
910return cur;911}
912
913static const char *914em_spu_channel_name_get(void *video EINA_UNUSED, int channel EINA_UNUSED)915{
916return NULL;917}
918
919static void920em_spu_channel_mute_set(void *video, int mute)921{
922Emotion_Gstreamer *ev = video;923gint flags;924
925ev->spu_mute = !!mute;926
927if (!ev->pipeline) return;928
929g_object_get(ev->pipeline, "flags", &flags, NULL);930if (ev->spu_mute) flags &= ~GST_PLAY_FLAG_TEXT;931else flags |= GST_PLAY_FLAG_TEXT;932g_object_set(ev->pipeline, "flags", flags, NULL);933}
934
935static int936em_spu_channel_mute_get(void *video)937{
938Emotion_Gstreamer *ev = video;939gint flags;940
941if (!ev->pipeline) return 0;942
943g_object_get(ev->pipeline, "flags", &flags, NULL);944
945return (flags & GST_PLAY_FLAG_TEXT) ? 0 : 1;946}
947
948static int949em_chapter_count(void *video EINA_UNUSED)950{
951return 0;952}
953
954static void955em_chapter_set(void *video EINA_UNUSED, int chapter EINA_UNUSED)956{
957}
958
959static int960em_chapter_get(void *video EINA_UNUSED)961{
962return 0;963}
964
965static const char *966em_chapter_name_get(void *video EINA_UNUSED, int chapter EINA_UNUSED)967{
968return NULL;969}
970
971static void972em_speed_set(void *video EINA_UNUSED, double speed EINA_UNUSED)973{
974}
975
976static double977em_speed_get(void *video EINA_UNUSED)978{
979return 1.0;980}
981
982static int983em_eject(void *video EINA_UNUSED)984{
985return 1;986}
987
988static void989_img_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)990{
991GstBuffer *buffer = data;992
993gst_buffer_unref(buffer);994}
995
996void *997em_meta_artwork_get(void *video, Evas_Object *img, const char *path, Emotion_Artwork_Info type)998{
999Emotion_Gstreamer *ev = video;1000GError *err = NULL;1001
1002if (!ev) return NULL;1003
1004gst_init(NULL,NULL);1005
1006gchar *uri = gst_filename_to_uri(path, NULL);1007
1008GstDiscoverer *discoverer = gst_discoverer_new(10 * GST_SECOND, &err);1009if (!discoverer) return NULL;1010GstDiscovererInfo* info = gst_discoverer_discover_uri(discoverer,1011uri, &err);1012if (!info) return NULL;1013
1014int ret = gst_discoverer_info_get_result(info);1015if (ret != GST_DISCOVERER_OK) goto done;1016
1017const GstTagList *tags = gst_discoverer_info_get_tags(info);1018
1019GstSample *sample;1020GstBuffer *buffer;1021GstMapInfo map;1022
1023const gchar *tag = GST_TAG_PREVIEW_IMAGE;1024if (type == EMOTION_ARTWORK_IMAGE) tag = GST_TAG_IMAGE;1025
1026if (gst_tag_list_get_sample(tags, tag, &sample))1027{1028buffer = gst_sample_get_buffer(sample);1029if (!buffer)1030{1031evas_object_del(img);1032img = NULL;1033goto done;1034}1035
1036if (gst_buffer_map(gst_buffer_ref(buffer), &map, GST_MAP_READ))1037{1038evas_object_image_memfile_set(img, map.data, map.size, NULL, NULL);1039evas_object_event_callback_add(img, EVAS_CALLBACK_DEL, _img_del_cb, buffer);1040}1041gst_sample_unref(sample);1042}1043else1044{1045evas_object_del(img);1046img = NULL;1047}1048
1049done:1050if (err) g_error_free(err);1051
1052gst_discoverer_info_unref(info);1053g_free(uri);1054g_object_unref(discoverer);1055
1056return img;1057}
1058
1059static const char *1060em_meta_get(void *video, int meta)1061{
1062Emotion_Gstreamer *ev = video;1063const char *str = NULL;1064
1065if (!ev->metadata) return NULL;1066
1067switch (meta)1068{1069case META_TRACK_TITLE:1070str = ev->metadata->title;1071break;1072case META_TRACK_ARTIST:1073str = ev->metadata->artist;1074break;1075case META_TRACK_ALBUM:1076str = ev->metadata->album;1077break;1078case META_TRACK_YEAR:1079str = ev->metadata->year;1080break;1081case META_TRACK_GENRE:1082str = ev->metadata->genre;1083break;1084case META_TRACK_COMMENT:1085str = ev->metadata->comment;1086break;1087case META_TRACK_DISCID:1088str = ev->metadata->disc_id;1089break;1090default:1091break;1092}1093
1094return str;1095}
1096
1097static void *1098em_add(const Emotion_Engine *api,1099Evas_Object *obj,1100const Emotion_Module_Options *opt EINA_UNUSED)1101{
1102Emotion_Gstreamer *ev;1103
1104ev = calloc(1, sizeof(Emotion_Gstreamer));1105EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);1106
1107ev->api = api;1108ev->obj = obj;1109
1110ev->ref_count = 1;1111
1112/* Default values */1113ev->vis = EMOTION_VIS_NONE;1114ev->volume = 1.0;1115ev->ready = EINA_FALSE;1116ev->shutdown = EINA_FALSE;1117ev->threads = NULL;1118ev->spu_mute = EINA_TRUE;1119
1120return ev;1121}
1122
1123static const Emotion_Engine em_engine =1124{
1125EMOTION_ENGINE_API_VERSION,1126EMOTION_ENGINE_PRIORITY_DEFAULT,1127"gstreamer1",1128em_add, /* add */1129em_del, /* del */1130em_file_open, /* file_open */1131em_file_close, /* file_close */1132em_play, /* play */1133em_stop, /* stop */1134em_size_get, /* size_get */1135em_pos_set, /* pos_set */1136em_len_get, /* len_get */1137em_buffer_size_get, /* buffer_size_get */1138em_fps_num_get, /* fps_num_get */1139em_fps_den_get, /* fps_den_get */1140em_fps_get, /* fps_get */1141em_pos_get, /* pos_get */1142em_vis_set, /* vis_set */1143em_vis_get, /* vis_get */1144em_vis_supported, /* vis_supported */1145em_ratio_get, /* ratio_get */1146em_video_handled, /* video_handled */1147em_audio_handled, /* audio_handled */1148em_seekable, /* seekable */1149em_frame_done, /* frame_done */1150em_format_get, /* format_get */1151em_video_data_size_get, /* video_data_size_get */1152em_yuv_rows_get, /* yuv_rows_get */1153em_bgra_data_get, /* bgra_data_get */1154em_event_feed, /* event_feed */1155em_event_mouse_button_feed, /* event_mouse_button_feed */1156em_event_mouse_move_feed, /* event_mouse_move_feed */1157em_video_channel_count, /* video_channel_count */1158em_video_channel_set, /* video_channel_set */1159em_video_channel_get, /* video_channel_get */1160em_video_subtitle_file_set, /* video_subtitle_file_set */1161em_video_subtitle_file_get, /* video_subtitle_file_get */1162em_video_channel_name_get, /* video_channel_name_get */1163em_video_channel_mute_set, /* video_channel_mute_set */1164em_video_channel_mute_get, /* video_channel_mute_get */1165em_audio_channel_count, /* audio_channel_count */1166em_audio_channel_set, /* audio_channel_set */1167em_audio_channel_get, /* audio_channel_get */1168em_audio_channel_name_get, /* audio_channel_name_get */1169em_audio_channel_mute_set, /* audio_channel_mute_set */1170em_audio_channel_mute_get, /* audio_channel_mute_get */1171em_audio_channel_volume_set, /* audio_channel_volume_set */1172em_audio_channel_volume_get, /* audio_channel_volume_get */1173em_spu_channel_count, /* spu_channel_count */1174em_spu_channel_set, /* spu_channel_set */1175em_spu_channel_get, /* spu_channel_get */1176em_spu_channel_name_get, /* spu_channel_name_get */1177em_spu_channel_mute_set, /* spu_channel_mute_set */1178em_spu_channel_mute_get, /* spu_channel_mute_get */1179em_chapter_count, /* chapter_count */1180em_chapter_set, /* chapter_set */1181em_chapter_get, /* chapter_get */1182em_chapter_name_get, /* chapter_name_get */1183em_speed_set, /* speed_set */1184em_speed_get, /* speed_get */1185em_eject, /* eject */1186em_meta_get, /* meta_get */1187NULL, /* priority_set */1188NULL, /* priority_get */1189em_meta_artwork_get,1190};1191
1192Eina_Bool
1193gstreamer_module_init(void)1194{
1195GError *error;1196
1197if (_emotion_init_count > 0)1198{1199_emotion_pending_ecore_begin();1200return EINA_TRUE;1201}1202
1203if (getenv("EMOTION_FPS_DEBUG")) debug_fps = EINA_TRUE;1204
1205eina_threads_init();1206eina_log_threads_enable();1207_emotion_gstreamer_log_domain = eina_log_domain_register1208("emotion-gstreamer", EINA_COLOR_LIGHTCYAN);1209if (_emotion_gstreamer_log_domain < 0)1210{1211EINA_LOG_CRIT("Could not register log domain 'emotion-gstreamer'");1212return EINA_FALSE;1213}1214
1215if (!gst_init_check(0, NULL, &error))1216{1217EINA_LOG_CRIT("Could not init GStreamer");1218goto error_gst_init;1219}1220
1221if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,1222"emotion-sink",1223"video sink plugin for Emotion",1224gstreamer_plugin_init,1225VERSION,1226"LGPL",1227"Enlightenment",1228PACKAGE,1229"http://www.enlightenment.org/") == FALSE)1230{1231EINA_LOG_CRIT("Could not load static gstreamer video sink for Emotion.");1232goto error_gst_plugin;1233}1234
1235if (!_emotion_module_register(&em_engine))1236{1237ERR("Could not register module %p", &em_engine);1238goto error_register;1239}1240
1241_emotion_init_count = 1;1242return EINA_TRUE;1243
1244error_register:1245error_gst_plugin:1246
1247gst_deinit();1248
1249error_gst_init:1250eina_log_domain_unregister(_emotion_gstreamer_log_domain);1251_emotion_gstreamer_log_domain = -1;1252
1253return EINA_FALSE;1254}
1255
1256void
1257gstreamer_module_shutdown(void)1258{
1259if (_emotion_init_count > 1)1260{1261_emotion_init_count--;1262return;1263}1264else if (_emotion_init_count == 0)1265{1266EINA_LOG_ERR("too many gstreamer_module_shutdown()");1267return;1268}1269_emotion_init_count = 0;1270
1271_emotion_module_unregister(&em_engine);1272
1273eina_log_domain_unregister(_emotion_gstreamer_log_domain);1274_emotion_gstreamer_log_domain = -1;1275
1276gst_deinit();1277}
1278
1279#ifndef EMOTION_STATIC_BUILD_GSTREAMER1280
1281EINA_MODULE_INIT(gstreamer_module_init);1282EINA_MODULE_SHUTDOWN(gstreamer_module_shutdown);1283
1284#endif1285
1286static void1287_for_each_tag(GstTagList const* list,1288gchar const* tag,1289void *data)1290{
1291Emotion_Gstreamer *ev;1292int i;1293int count;1294
1295
1296ev = (Emotion_Gstreamer*)data;1297
1298if (!ev || !ev->metadata) return;1299
1300count = gst_tag_list_get_tag_size(list, tag);1301
1302for (i = 0; i < count; i++)1303{1304if (!strcmp(tag, GST_TAG_TITLE))1305{1306char *str;1307g_free(ev->metadata->title);1308if (gst_tag_list_get_string(list, GST_TAG_TITLE, &str))1309ev->metadata->title = str;1310else1311ev->metadata->title = NULL;1312break;1313}1314if (!strcmp(tag, GST_TAG_ALBUM))1315{1316gchar *str;1317g_free(ev->metadata->album);1318if (gst_tag_list_get_string(list, GST_TAG_ALBUM, &str))1319ev->metadata->album = str;1320else1321ev->metadata->album = NULL;1322break;1323}1324if (!strcmp(tag, GST_TAG_ARTIST))1325{1326gchar *str;1327g_free(ev->metadata->artist);1328if (gst_tag_list_get_string(list, GST_TAG_ARTIST, &str))1329ev->metadata->artist = str;1330else1331ev->metadata->artist = NULL;1332break;1333}1334if (!strcmp(tag, GST_TAG_GENRE))1335{1336gchar *str;1337g_free(ev->metadata->genre);1338if (gst_tag_list_get_string(list, GST_TAG_GENRE, &str))1339ev->metadata->genre = str;1340else1341ev->metadata->genre = NULL;1342break;1343}1344if (!strcmp(tag, GST_TAG_COMMENT))1345{1346gchar *str;1347g_free(ev->metadata->comment);1348if (gst_tag_list_get_string(list, GST_TAG_COMMENT, &str))1349ev->metadata->comment = str;1350else1351ev->metadata->comment = NULL;1352break;1353}1354if (!strcmp(tag, GST_TAG_DATE))1355{1356gchar *str;1357const GValue *date;1358g_free(ev->metadata->year);1359date = gst_tag_list_get_value_index(list, GST_TAG_DATE, 0);1360if (date)1361str = g_strdup_value_contents(date);1362else1363str = NULL;1364ev->metadata->year = str;1365break;1366}1367
1368if (!strcmp(tag, GST_TAG_DATE_TIME))1369{1370gchar *str;1371const GValue *date;1372g_free(ev->metadata->year);1373date = gst_tag_list_get_value_index(list, GST_TAG_DATE_TIME, 0);1374if (date)1375str = g_strdup_value_contents(date);1376else1377str = NULL;1378ev->metadata->year = str;1379break;1380}1381
1382if (!strcmp(tag, GST_TAG_TRACK_NUMBER))1383{1384gchar *str;1385const GValue *track;1386g_free(ev->metadata->count);1387track = gst_tag_list_get_value_index(list, GST_TAG_TRACK_NUMBER, 0);1388if (track)1389str = g_strdup_value_contents(track);1390else1391str = NULL;1392ev->metadata->count = str;1393break;1394}1395
1396if (!strcmp(tag, GST_TAG_CDDA_CDDB_DISCID))1397{1398gchar *str;1399const GValue *discid;1400g_free(ev->metadata->disc_id);1401discid = gst_tag_list_get_value_index(list, GST_TAG_CDDA_CDDB_DISCID, 0);1402if (discid)1403str = g_strdup_value_contents(discid);1404else1405str = NULL;1406ev->metadata->disc_id = str;1407break;1408}1409}1410
1411}
1412
1413static void1414_free_metadata(Emotion_Gstreamer_Metadata *m)1415{
1416if (!m) return;1417
1418g_free(m->title);1419g_free(m->album);1420g_free(m->artist);1421g_free(m->genre);1422g_free(m->comment);1423g_free(m->year);1424g_free(m->count);1425g_free(m->disc_id);1426
1427free(m);1428}
1429
1430static void1431audio_buffer_probe_main(void *data)1432{
1433Emotion_Gstreamer *ev = data;1434
1435if (!ev->shutdown)1436_emotion_frame_new(ev->obj);1437
1438g_atomic_int_set(&ev->audio_buffer_probe_pending, 0);1439
1440emotion_gstreamer_unref(ev);1441_emotion_pending_ecore_end();1442}
1443
1444static GstPadProbeReturn1445audio_buffer_probe(GstPad *pad EINA_UNUSED, GstPadProbeInfo *info EINA_UNUSED, gpointer user_data)1446{
1447Emotion_Gstreamer *ev = user_data;1448
1449/* Don't call too many of these */1450if (!g_atomic_int_compare_and_exchange(&ev->audio_buffer_probe_pending, 0, 1))1451return GST_PAD_PROBE_OK;1452
1453_emotion_pending_ecore_begin();1454ecore_main_loop_thread_safe_call_async(audio_buffer_probe_main, emotion_gstreamer_ref(ev));1455
1456return GST_PAD_PROBE_OK;1457}
1458
1459static void1460_bus_main_handler(void *data)1461{
1462Emotion_Gstreamer_Message *send;1463Emotion_Gstreamer *ev;1464GstMessage *msg;1465
1466send = data;1467ev = send->ev;1468msg = send->msg;1469
1470/* Just exit immediately if we're shutting down */1471if (ev->shutdown)1472{1473emotion_gstreamer_message_free(send);1474_emotion_pending_ecore_end();1475return;1476}1477
1478switch (GST_MESSAGE_TYPE(msg))1479{1480case GST_MESSAGE_EOS:1481ev->play = EINA_FALSE;1482_emotion_decode_stop(ev->obj);1483_emotion_playback_finished(ev->obj);1484break;1485case GST_MESSAGE_TAG:1486{1487GstTagList *new_tags;1488gst_message_parse_tag(msg, &new_tags);1489if (new_tags)1490{1491gst_tag_list_foreach(new_tags,1492(GstTagForeachFunc)_for_each_tag,1493ev);1494gst_tag_list_free(new_tags);1495}1496_emotion_title_set(ev->obj, ev->metadata->title);1497break;1498}1499case GST_MESSAGE_ASYNC_DONE:1500_emotion_seek_done(ev->obj);1501break;1502case GST_MESSAGE_STATE_CHANGED:1503{1504GstState old_state, new_state;1505
1506gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);1507INF("Element %s changed state from %s to %s.",1508GST_OBJECT_NAME(msg->src),1509gst_element_state_get_name(old_state),1510gst_element_state_get_name(new_state));1511
1512if (GST_MESSAGE_SRC(msg) == GST_OBJECT(ev->pipeline) && new_state >= GST_STATE_PAUSED && !ev->ready)1513{1514gint n_audio, n_video;1515
1516ev->ready = EINA_TRUE;1517
1518g_object_get(G_OBJECT(ev->pipeline),1519"n-audio", &n_audio,1520"n-video", &n_video,1521NULL);1522
1523if (n_audio == 0 && n_video == 0)1524ERR("No audio nor video stream found");1525
1526if (n_audio > 0 && n_video == 0)1527{1528GstElement *vis = NULL;1529gint flags;1530const char *vis_name;1531
1532if ((vis_name = emotion_visualization_element_name_get(ev->vis)))1533{1534vis = gst_element_factory_make(vis_name, "vis");1535g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL);1536g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL);1537flags |= GST_PLAY_FLAG_VIS;1538g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL);1539}1540else1541{1542GstElement *audio_sink;1543
1544g_object_get(ev->pipeline, "audio-sink", &audio_sink, NULL);1545ev->audio_buffer_probe_pad = gst_element_get_static_pad(audio_sink, "sink");1546ev->audio_buffer_probe = gst_pad_add_probe(ev->audio_buffer_probe_pad,1547GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,1548audio_buffer_probe,1549ev,1550NULL);1551gst_object_unref(audio_sink);1552}1553}1554
1555if (n_audio > 0 || n_video > 0)1556{1557/** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */1558/** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */1559
1560#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)1561if (getuid() == geteuid())1562#endif1563{1564if (getenv("EMOTION_GSTREAMER_DOT"))1565{1566GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline),1567GST_DEBUG_GRAPH_SHOW_ALL,1568getenv("EMOTION_GSTREAMER_DOT"));1569}1570}1571
1572_emotion_open_done(ev->obj);1573_emotion_playback_started(ev->obj);1574}1575}1576break;1577}1578case GST_MESSAGE_ERROR:1579{1580GError *err = NULL;1581gchar *name, *debug = NULL;1582
1583name = gst_object_get_path_string (msg->src);1584gst_message_parse_error (msg, &err, &debug);1585
1586ERR("ERROR: from element %s: %s\nAdditional debug info:\n%s", name, err->message, debug);1587
1588g_error_free (err);1589g_free (debug);1590g_free (name);1591
1592gst_element_set_state(ev->pipeline, GST_STATE_NULL);1593
1594ev->play = EINA_FALSE;1595_emotion_decode_stop(ev->obj);1596_emotion_playback_finished(ev->obj);1597
1598break;1599}1600case GST_MESSAGE_WARNING:1601{1602GError *err = NULL;1603gchar *name, *debug = NULL;1604
1605name = gst_object_get_path_string (msg->src);1606gst_message_parse_warning (msg, &err, &debug);1607
1608WRN("WARNING: from element %s: %s\nAdditional debug info:\n%s", name, err->message, debug);1609
1610g_error_free (err);1611g_free (debug);1612g_free (name);1613
1614break;1615}1616case GST_MESSAGE_BUFFERING:1617{1618gint percent = 0;1619
1620/* If the stream is live, we do not care about buffering. */1621if (ev->live)1622{1623ev->buffering = FALSE;1624break;1625}1626
1627gst_message_parse_buffering (msg, &percent);1628
1629/* Wait until buffering is complete before start/resume playing */1630if (percent < 100)1631gst_element_set_state (ev->pipeline, GST_STATE_PAUSED);1632else if (ev->play)1633gst_element_set_state (ev->pipeline, GST_STATE_PLAYING);1634
1635ev->buffering = (percent < 100);1636
1637break;1638}1639case GST_MESSAGE_CLOCK_LOST:1640{1641gst_element_set_state (ev->pipeline, GST_STATE_PAUSED);1642gst_element_set_state (ev->pipeline, GST_STATE_PLAYING);1643break;1644}1645default:1646break;1647}1648
1649emotion_gstreamer_message_free(send);1650_emotion_pending_ecore_end();1651}
1652
1653static GstBusSyncReply1654_bus_sync_handler(GstBus *bus EINA_UNUSED, GstMessage *msg, gpointer data)1655{
1656Emotion_Gstreamer *ev = data;1657Emotion_Gstreamer_Message *send;1658
1659INF("Message %s from %s",1660GST_MESSAGE_TYPE_NAME(msg),1661GST_MESSAGE_SRC_NAME(msg));1662
1663send = emotion_gstreamer_message_alloc(ev, msg);1664
1665if (send)1666{1667_emotion_pending_ecore_begin();1668ecore_main_loop_thread_safe_call_async(_bus_main_handler, send);1669}1670
1671gst_message_unref(msg);1672
1673return GST_BUS_DROP;1674}
1675
1676static void1677_emotion_gstreamer_pause(void *data, Ecore_Thread *thread)1678{
1679Emotion_Gstreamer *ev = data;1680gboolean res;1681
1682if (ecore_thread_check(thread) || !ev->pipeline) return;1683
1684gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);1685res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);1686if (res == GST_STATE_CHANGE_NO_PREROLL)1687{1688ev->live = EINA_TRUE;1689gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);1690gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);1691}1692}
1693
1694static void1695_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread)1696{
1697Emotion_Gstreamer *ev = data;1698
1699ev->threads = eina_list_remove(ev->threads, thread);1700
1701#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)1702if (getuid() == geteuid())1703#endif1704{1705if (getenv("EMOTION_GSTREAMER_DOT"))1706{1707GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline),1708GST_DEBUG_GRAPH_SHOW_ALL,1709getenv("EMOTION_GSTREAMER_DOT"));1710}1711}1712
1713emotion_gstreamer_unref(ev);1714}
1715
1716static void1717_emotion_gstreamer_end(void *data, Ecore_Thread *thread)1718{
1719Emotion_Gstreamer *ev = data;1720
1721ev->threads = eina_list_remove(ev->threads, thread);1722
1723if (ev->play && !ev->buffering)1724{1725gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);1726}1727
1728#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)1729if (getuid() == geteuid())1730#endif1731{1732if (getenv("EMOTION_GSTREAMER_DOT"))1733{1734GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline),1735GST_DEBUG_GRAPH_SHOW_ALL,1736getenv("EMOTION_GSTREAMER_DOT"));1737}1738}1739
1740emotion_gstreamer_unref(ev);1741}
1742
1743static GstElement *1744_create_pipeline(Emotion_Gstreamer *ev,1745Evas_Object *o,1746const char *uri,1747const char *suburi)1748{
1749GstElement *playbin;1750GstElement *vsink;1751GstBus *bus;1752int flags;1753
1754if (!uri)1755return NULL;1756
1757playbin = gst_element_factory_make("playbin", "playbin");1758if (!playbin)1759{1760ERR("Unable to create 'playbin' GstElement.");1761return NULL;1762}1763
1764vsink = gst_element_factory_make("emotion-sink", "sink");1765if (!vsink)1766{1767ERR("Unable to create 'emotion-sink' GstElement.");1768goto unref_pipeline;1769}1770
1771g_object_set(G_OBJECT(vsink), "emotion-object", o, NULL);1772
1773g_object_get(G_OBJECT(playbin), "flags", &flags, NULL);1774if (ev->spu_mute) flags &= ~GST_PLAY_FLAG_TEXT;1775else flags |= GST_PLAY_FLAG_TEXT;1776g_object_set(G_OBJECT(playbin), "flags", (flags | GST_PLAY_FLAG_DOWNLOAD), NULL);1777g_object_set(G_OBJECT(playbin), "video-sink", vsink, NULL);1778g_object_set(G_OBJECT(playbin), "uri", uri, NULL);1779if (suburi)1780{1781g_object_set(G_OBJECT(playbin), "suburi", suburi, NULL);1782g_object_set(G_OBJECT(playbin), "subtitle-font-desc", "Sans, 10", NULL);1783}1784
1785bus = gst_element_get_bus(playbin);1786gst_bus_set_sync_handler(bus, _bus_sync_handler, ev, NULL);1787gst_object_unref(bus);1788
1789ev->pipeline = playbin;1790ev->vsink = vsink;1791
1792ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));1793
1794ev->threads = eina_list_append(ev->threads,1795ecore_thread_run(_emotion_gstreamer_pause,1796_emotion_gstreamer_end,1797_emotion_gstreamer_cancel,1798emotion_gstreamer_ref(ev)));1799
1800/** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */1801/** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */1802#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)1803if (getuid() == geteuid())1804#endif1805{1806if (getenv("EMOTION_GSTREAMER_DOT"))1807{1808GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(playbin),1809GST_DEBUG_GRAPH_SHOW_ALL,1810getenv("EMOTION_GSTREAMER_DOT"));1811}1812}1813
1814return playbin;1815
1816unref_pipeline:1817gst_object_unref(vsink);1818gst_object_unref(playbin);1819return NULL;1820}
1821