diff -r 000000000000 -r 686549eb5657 maemo-ui/src/mmyth_videoplayer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/maemo-ui/src/mmyth_videoplayer.c Mon Oct 23 16:02:15 2006 +0100 @@ -0,0 +1,369 @@ + +#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); +}