[svn r91] Added changes proposed by melunko (buffer on plug-in).
5 #include <gst/interfaces/xoverlay.h>
9 #include "mmyth_videoplayer.h"
10 #include "mmyth_sdpreader.h"
12 #include "esg_database.h"
14 #include "ipd_demux.h"
15 #include "ipd_network.h"
17 #ifdef INDT_IP_DECAPSULATOR
18 #include <sys/types.h>
22 /* Global flag/semaphore to control IP decapsulator threads */
23 gboolean state_keep_running = 0;
26 typedef struct _GstPlayerWindowStateChange
29 GstState old_state, new_state;
31 } GstPlayerWindowStateChange;
33 typedef struct _GstPlayerWindowTagFound
38 } GstPlayerWindowTagFound;
41 GstElement *gst_pipeline, *gst_decoder, *gst_videosink;
43 static gboolean idle_state (gpointer data);
46 bus_call (GstBus * bus, GstMessage * msg, gpointer data)
48 MMythUi *mmyth_ui = (MMythUi *) data;
49 GMainLoop *loop = mmyth_ui->loop;
51 switch (GST_MESSAGE_TYPE (msg)) {
54 if (mmyth_ui->idle_id != 0) {
55 g_source_remove (mmyth_ui->idle_id);
56 mmyth_ui->idle_id = 0;
59 //g_idle_add ((GSourceFunc) idle_eos, data);
60 gst_element_set_state (GST_ELEMENT (GST_MESSAGE_SRC (msg)),
63 case GST_MESSAGE_ERROR:{
67 gst_message_parse_error (msg, &err, &debug);
70 printf ("Error: %s\n", err->message);
73 g_main_loop_quit (loop);
76 case GST_MESSAGE_STATE_CHANGED:{
80 GstPlayerWindowStateChange *st =
81 g_new (GstPlayerWindowStateChange, 1);
83 gst_message_parse_state_changed (msg,
87 st->play = mmyth_ui->play;
88 gst_object_ref (GST_OBJECT (mmyth_ui->play));
89 st->old_state = oldstate;
90 st->new_state = newstate;
92 st->mmyth_ui = mmyth_ui;
94 /* State debug messages */
95 printf ("oldstate = %s, newstate = %s, pendingstate = %s\n",
96 gst_element_state_get_name (oldstate),
97 gst_element_state_get_name (newstate),
98 gst_element_state_get_name (pending));
100 g_idle_add ((GSourceFunc) idle_state, st);
105 printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
115 cb_iterate (gpointer data)
117 MMythUi *mmyth_ui = (MMythUi *) data;
120 g_main_loop_run (mmyth_ui->loop);
122 if (!GST_FLAG_IS_SET (mmyth_ui->play, GST_BIN_SELF_SCHEDULABLE)) {
123 res = gst_bin_iterate (GST_BIN (mmyth_ui->play));
126 res = (gst_element_get_state (mmyth_ui->play) == GST_STATE_PLAYING);
130 mmyth_ui->idle_id = 0;
139 idle_state (gpointer data)
141 GstPlayerWindowStateChange *st = data;
143 if (st->old_state == GST_STATE_PLAYING) {
144 if (st->mmyth_ui->idle_id != 0) {
145 g_source_remove (st->mmyth_ui->idle_id);
146 st->mmyth_ui->idle_id = 0;
149 else if (st->new_state == GST_STATE_PLAYING) {
150 if (st->mmyth_ui->idle_id != 0)
151 g_source_remove (st->mmyth_ui->idle_id);
153 st->mmyth_ui->idle_id = g_idle_add (cb_iterate, st->mmyth_ui);
156 /* new movie loaded? */
157 if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) {
159 /* gboolean have_video = FALSE; */
161 gtk_widget_show (st->mmyth_ui->videow);
163 gtk_window_resize (GTK_WINDOW (st->mmyth_ui->main_window), 1, 1);
167 /* discarded movie? */
168 if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) {
170 if (st->mmyth_ui->tagcache) {
171 gst_tag_list_free (st->mmyth_ui->tagcache);
172 st->mmyth_ui->tagcache = NULL;
176 gst_object_unref (GST_OBJECT (st->play));
177 //g_object_unref (G_OBJECT (st->win));
187 expose (GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
189 MMythUi *mmyth_ui = (MMythUi *) user_data;
191 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mmyth_ui->videosink),
192 GDK_WINDOW_XWINDOW (mmyth_ui->videow->
199 mmyth_player_init (MMythUi * mmyth_ui)
202 GstElement *source, *parser, *decoder, *videosink;
204 play = gst_pipeline_new ("video-player");
205 source = gst_element_factory_make ("udpsrc", "file-source");
206 parser = gst_element_factory_make ("rtph263pdepay", "rtp-demux");
207 decoder = gst_element_factory_make ("ffdec_h263", "mpeg-decoder");
208 videosink = gst_element_factory_make ("xvimagesink", "image-output");
210 gst_decoder = decoder;
211 gst_videosink = videosink;
213 if (!(gst_pipeline && source && parser && decoder && videosink)) {
214 /* FIXME: hanlde the error correctly */
215 /* video_alignment is not being created (below)
216 and is causing problems to the ui */
217 g_print ("GstElement creation error!\n");
221 g_object_set (G_OBJECT (videosink), "sync", FALSE, NULL);
223 gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline)),
226 gst_bin_add_many (GST_BIN (gst_pipeline), source, parser, decoder,
230 GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL);
231 gst_element_link_filtered(source, parser, rtpcaps);
234 gst_element_link_many (/*source,*/ parser, decoder, videosink, NULL);
237 mmyth_ui->play = play;
238 mmyth_ui->videosink = videosink;
239 mmyth_ui->udpsource = source;
241 g_object_ref (mmyth_ui->play);
242 g_object_ref (mmyth_ui->videosink);
245 //mmyth_ui->videow = gst_player_video_new (videosink, play);
246 mmyth_ui->videow = gtk_drawing_area_new ();
247 gtk_widget_set_size_request (mmyth_ui->videow, 300, 240);
249 mmyth_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL);
252 mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
253 gtk_widget_hide (mmyth_ui->video_alignment);
255 gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment),
258 g_signal_connect (mmyth_ui->videow, "expose-event", G_CALLBACK (expose),
260 //g_signal_connect(mmyth_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), mmyth_ui);
263 g_object_ref (mmyth_ui->videow);
264 g_object_ref (mmyth_ui->video_alignment);
266 //gnome_app_set_contents (app, videow);
267 //gtk_widget_show (mmyth_ui->videow);
270 // gst_object_unref (GST_OBJECT (play));
276 mmyth_player_stop (MMythUi * mmyth_ui)
278 gst_element_set_state (mmyth_ui->play, GST_STATE_NULL);
280 if(mmyth_ui->videow != NULL)
281 gtk_widget_hide (mmyth_ui->videow);
283 /* Disable IP Decapsulator playing threads */
284 state_keep_running = FALSE;
289 idle_play (gpointer data)
291 MMythUi *mmyth_ui = (MMythUi *) data;
295 gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING);
301 /* Run IP decapsulator play function in a new thread. The thread is finished setting the
302 * semaphore "state_keep_running" to FALSE*/
304 run_ipd(gpointer data)
306 GString *ip_addr = (GString*) data;
308 state_keep_running = TRUE;
310 printf("Inside thread\n");
312 ipd_mpe_play_section (ip_addr->str, &state_keep_running);
318 mmyth_play_channel (MMythUi * mmyth_ui, gint service_number)
321 DVBHService *service;
323 GString *service_ip_addr;
325 /* First verifies if there is a tuned network */
326 if ( !ipd_network_is_tuned() ) {
327 /* FIXME: show alert and handle this error */
328 g_warning ("Play not possible, network not tuned");
332 esg_db = esg_database_get_instance();
333 /* Gets the service structure */
334 service = (DVBHService *) esg_database_get_service_from_number
335 (esg_db, service_number);
337 /* Verifies if sdp fragment exists to this service */
338 if ( service->sdp_file == NULL ) {
339 /* FIXME: Implement error handling */
340 g_warning ("SDP fragment not available to access service");
344 /* Parses the sdp to get ipv6 address and port */
345 mmyth_sdp_parse_file (service->sdp_file->str, &sdp_data);
347 /* Sets the gstreamer properties acording to the service access address */
348 /* FIXME: Develop sdp_bin in gstreamer to give sdp file as pipeline config */
349 g_object_set (G_OBJECT (mmyth_ui->udpsource), "multicast_group",
350 sdp_data.ip_addr->str, NULL);
351 g_object_set (G_OBJECT (mmyth_ui->udpsource), "port", sdp_data.video_port, NULL);
353 /* Shows the video widget on screen */
354 mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon);
356 gtk_widget_show (mmyth_ui->videow);
357 gtk_widget_queue_draw (mmyth_ui->videow);
359 #ifdef INDT_IP_DECAPSULATOR
360 /* Will be dealocated in run_ipd */
361 service_ip_addr = g_string_new (sdp_data.ip_addr->str);
363 /* Requests the IP decapsulator to play the channel stream*/
364 g_thread_create (run_ipd, (gpointer) service_ip_addr, FALSE, NULL);
367 //gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING);
368 g_idle_add (idle_play, mmyth_ui);