#include #include #include #include #include #include "mmyth_ui.h" #include "mmyth_videoplayer.h" #include "mmyth_sdpreader.h" #include "esg_database.h" #include "ipd_demux.h" #include "ipd_network.h" #ifdef INDT_IP_DECAPSULATOR #include #include #endif /* Global flag/semaphore to control IP decapsulator threads */ gboolean state_keep_running = 0; typedef struct _GstPlayerWindowStateChange { GstElement *play; GstState old_state, new_state; MMythUi *mmyth_ui; } GstPlayerWindowStateChange; typedef struct _GstPlayerWindowTagFound { GstElement *play; GstTagList *taglist; MMythUi *mmyth_ui; } GstPlayerWindowTagFound; GstElement *gst_pipeline, *gst_decoder, *gst_videosink; static gboolean idle_state (gpointer data); static gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data) { MMythUi *mmyth_ui = (MMythUi *) data; GMainLoop *loop = mmyth_ui->loop; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: if (mmyth_ui->idle_id != 0) { g_source_remove (mmyth_ui->idle_id); mmyth_ui->idle_id = 0; } //g_idle_add ((GSourceFunc) idle_eos, data); gst_element_set_state (GST_ELEMENT (GST_MESSAGE_SRC (msg)), GST_STATE_READY); break; case GST_MESSAGE_ERROR:{ gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_free (debug); printf ("Error: %s\n", err->message); g_error_free (err); g_main_loop_quit (loop); } break; case GST_MESSAGE_STATE_CHANGED:{ GstState oldstate; GstState newstate; GstState pending; GstPlayerWindowStateChange *st = g_new (GstPlayerWindowStateChange, 1); gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending); st->play = mmyth_ui->play; gst_object_ref (GST_OBJECT (mmyth_ui->play)); st->old_state = oldstate; st->new_state = newstate; st->mmyth_ui = mmyth_ui; /* State debug messages */ printf ("oldstate = %s, newstate = %s, pendingstate = %s\n", gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate), gst_element_state_get_name (pending)); g_idle_add ((GSourceFunc) idle_state, st); } break; default: printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg))); printf ("\n"); break; } return TRUE; } static gboolean cb_iterate (gpointer data) { MMythUi *mmyth_ui = (MMythUi *) data; //gboolean res; g_main_loop_run (mmyth_ui->loop); /* if (!GST_FLAG_IS_SET (mmyth_ui->play, GST_BIN_SELF_SCHEDULABLE)) { res = gst_bin_iterate (GST_BIN (mmyth_ui->play)); } else { g_usleep (100); res = (gst_element_get_state (mmyth_ui->play) == GST_STATE_PLAYING); } if (!res) mmyth_ui->idle_id = 0; return res; */ return FALSE; } static gboolean idle_state (gpointer data) { GstPlayerWindowStateChange *st = data; if (st->old_state == GST_STATE_PLAYING) { if (st->mmyth_ui->idle_id != 0) { g_source_remove (st->mmyth_ui->idle_id); st->mmyth_ui->idle_id = 0; } } else if (st->new_state == GST_STATE_PLAYING) { if (st->mmyth_ui->idle_id != 0) g_source_remove (st->mmyth_ui->idle_id); st->mmyth_ui->idle_id = g_idle_add (cb_iterate, st->mmyth_ui); } /* new movie loaded? */ if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) { /* gboolean have_video = FALSE; */ gtk_widget_show (st->mmyth_ui->videow); gtk_window_resize (GTK_WINDOW (st->mmyth_ui->main_window), 1, 1); } /* discarded movie? */ if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) { if (st->mmyth_ui->tagcache) { gst_tag_list_free (st->mmyth_ui->tagcache); st->mmyth_ui->tagcache = NULL; } } gst_object_unref (GST_OBJECT (st->play)); //g_object_unref (G_OBJECT (st->win)); g_free (st); /* once */ return FALSE; } static gboolean expose (GtkWidget * widget, GdkEventExpose * event, gpointer user_data) { MMythUi *mmyth_ui = (MMythUi *) user_data; gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mmyth_ui->videosink), GDK_WINDOW_XWINDOW (mmyth_ui->videow-> window)); return TRUE; } void mmyth_player_init (MMythUi * mmyth_ui) { GstElement *play; GstElement *source, *parser, *decoder, *videosink; play = gst_pipeline_new ("video-player"); source = gst_element_factory_make ("udpsrc", "file-source"); parser = gst_element_factory_make ("rtph263pdepay", "rtp-demux"); decoder = gst_element_factory_make ("ffdec_h263", "mpeg-decoder"); videosink = gst_element_factory_make ("xvimagesink", "image-output"); gst_pipeline = play; gst_decoder = decoder; gst_videosink = videosink; if (!(gst_pipeline && source && parser && decoder && videosink)) { /* FIXME: hanlde the error correctly */ /* video_alignment is not being created (below) and is causing problems to the ui */ g_print ("GstElement creation error!\n"); return; } g_object_set (G_OBJECT (videosink), "sync", FALSE, NULL); gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline)), bus_call, mmyth_ui); gst_bin_add_many (GST_BIN (gst_pipeline), source, parser, decoder, videosink, NULL); { GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL); gst_element_link_filtered(source, parser, rtpcaps); } gst_element_link_many (/*source,*/ parser, decoder, videosink, NULL); /* actual window */ mmyth_ui->play = play; mmyth_ui->videosink = videosink; mmyth_ui->udpsource = source; g_object_ref (mmyth_ui->play); g_object_ref (mmyth_ui->videosink); /* video widget */ //mmyth_ui->videow = gst_player_video_new (videosink, play); mmyth_ui->videow = gtk_drawing_area_new (); gtk_widget_set_size_request (mmyth_ui->videow, 300, 240); mmyth_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL); mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 0, 0); gtk_widget_hide (mmyth_ui->video_alignment); gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment), mmyth_ui->videow); g_signal_connect (mmyth_ui->videow, "expose-event", G_CALLBACK (expose), mmyth_ui); //g_signal_connect(mmyth_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), mmyth_ui); g_object_ref (mmyth_ui->videow); g_object_ref (mmyth_ui->video_alignment); //gnome_app_set_contents (app, videow); //gtk_widget_show (mmyth_ui->videow); //fail: // gst_object_unref (GST_OBJECT (play)); // return NULL; } void mmyth_player_stop (MMythUi * mmyth_ui) { gst_element_set_state (mmyth_ui->play, GST_STATE_NULL); if(mmyth_ui->videow != NULL) gtk_widget_hide (mmyth_ui->videow); /* Disable IP Decapsulator playing threads */ state_keep_running = FALSE; } static gboolean idle_play (gpointer data) { MMythUi *mmyth_ui = (MMythUi *) data; sleep (2); gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING); return FALSE; } /* Run IP decapsulator play function in a new thread. The thread is finished setting the * semaphore "state_keep_running" to FALSE*/ gpointer run_ipd(gpointer data) { GString *ip_addr = (GString*) data; state_keep_running = TRUE; printf("Inside thread\n"); ipd_mpe_play_section (ip_addr->str, &state_keep_running); return 0; } void mmyth_play_channel (MMythUi * mmyth_ui, gint service_number) { ESGDatabase *esg_db; DVBHService *service; SDPData sdp_data; GString *service_ip_addr; /* First verifies if there is a tuned network */ if ( !ipd_network_is_tuned() ) { /* FIXME: show alert and handle this error */ g_warning ("Play not possible, network not tuned"); return; } esg_db = esg_database_get_instance(); /* Gets the service structure */ service = (DVBHService *) esg_database_get_service_from_number (esg_db, service_number); /* Verifies if sdp fragment exists to this service */ if ( service->sdp_file == NULL ) { /* FIXME: Implement error handling */ g_warning ("SDP fragment not available to access service"); return; } /* Parses the sdp to get ipv6 address and port */ mmyth_sdp_parse_file (service->sdp_file->str, &sdp_data); /* Sets the gstreamer properties acording to the service access address */ /* FIXME: Develop sdp_bin in gstreamer to give sdp file as pipeline config */ g_object_set (G_OBJECT (mmyth_ui->udpsource), "multicast_group", sdp_data.ip_addr->str, NULL); g_object_set (G_OBJECT (mmyth_ui->udpsource), "port", sdp_data.video_port, NULL); /* Shows the video widget on screen */ mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon); gtk_widget_show (mmyth_ui->videow); gtk_widget_queue_draw (mmyth_ui->videow); #ifdef INDT_IP_DECAPSULATOR /* Will be dealocated in run_ipd */ service_ip_addr = g_string_new (sdp_data.ip_addr->str); /* Requests the IP decapsulator to play the channel stream*/ g_thread_create (run_ipd, (gpointer) service_ip_addr, FALSE, NULL); #endif //gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING); g_idle_add (idle_play, mmyth_ui); }