# HG changeset patch # User Mike Ruprecht # Date 1213075109 0 # Node ID 3bf9748fdef09dcd29f80ba295ae085ffc669deb # Parent c2231cf3be71ea8ae59e9ff39366924ef85ae52e Preliminary video embedded in the conversation window. It's still kind of buggy. diff -r c2231cf3be71 -r 3bf9748fdef0 libpurple/media.c --- a/libpurple/media.c Sun Jun 08 02:47:38 2008 +0000 +++ b/libpurple/media.c Tue Jun 10 05:18:29 2008 +0000 @@ -676,7 +676,7 @@ void purple_media_video_init_src(GstElement **sendbin) { - GstElement *src; + GstElement *src, *tee, *queue, *local_sink; GstPad *pad; GstPad *ghost; const gchar *video_plugin = purple_prefs_get_string("/purple/media/video/plugin"); @@ -685,17 +685,34 @@ purple_debug_info("media", "purple_media_video_init_src\n"); *sendbin = gst_bin_new("purplesendvideobin"); - src = gst_element_factory_make(video_plugin, "videosrc"); + src = gst_element_factory_make(video_plugin, "purplevideosource"); gst_bin_add(GST_BIN(*sendbin), src); + tee = gst_element_factory_make("tee", NULL); + gst_bin_add(GST_BIN(*sendbin), tee); + gst_element_link(src, tee); + + queue = gst_element_factory_make("queue", NULL); + gst_bin_add(GST_BIN(*sendbin), queue); + gst_element_link(tee, queue); + if (!strcmp(video_plugin, "videotestsrc")) { /* unless is-live is set to true it doesn't throttle videotestsrc */ g_object_set (G_OBJECT(src), "is-live", TRUE, NULL); } - pad = gst_element_get_pad(src, "src"); + + pad = gst_element_get_pad(queue, "src"); ghost = gst_ghost_pad_new("ghostsrc", pad); gst_element_add_pad(*sendbin, ghost); + queue = gst_element_factory_make("queue", NULL); + gst_bin_add(GST_BIN(*sendbin), queue); + gst_element_link(tee, queue); + + local_sink = gst_element_factory_make("autovideosink", "purplelocalvideosink"); + gst_bin_add(GST_BIN(*sendbin), local_sink); + gst_element_link(queue, local_sink); + /* set current video device on "src"... */ if (video_device) { GList *devices = purple_media_get_devices(src); diff -r c2231cf3be71 -r 3bf9748fdef0 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sun Jun 08 02:47:38 2008 +0000 +++ b/pidgin/gtkconv.c Tue Jun 10 05:18:29 2008 +0000 @@ -4743,7 +4743,7 @@ static GtkWidget * setup_common_pane(PidginConversation *gtkconv) { - GtkWidget *vbox, *frame, *imhtml_sw, *event_box; + GtkWidget *vbox, *hpaned, *frame, *imhtml_sw, *event_box; GtkCellRenderer *rend; GtkTreePath *path; PurpleConversation *conv = gtkconv->active_conv; @@ -4823,23 +4823,21 @@ /* Setup the gtkimhtml widget */ frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); + + /* Add the gtkimhtml frame */ + gtkconv->middle_hpaned = hpaned = gtk_hpaned_new(); + gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); + gtk_widget_show(hpaned); + gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); + if (chat) { - GtkWidget *hpaned; - /* Add the topic */ setup_chat_topic(gtkconv, vbox); - /* Add the gtkimhtml frame */ - hpaned = gtk_hpaned_new(); - gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); - gtk_widget_show(hpaned); - gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE); - /* Now add the userlist */ setup_chat_userlist(gtkconv, hpaned); - } else { - gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - } + } + gtk_widget_show(frame); gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); @@ -7727,6 +7725,9 @@ gtkconv->gtkmedia = gtkmedia; g_signal_connect(G_OBJECT(gtkmedia), "destroy", G_CALLBACK(gtk_widget_destroyed), &(gtkconv->gtkmedia)); + + gtk_paned_pack2(GTK_PANED(gtkconv->middle_hpaned), + pidgin_media_get_display_widget(gtkmedia), FALSE, TRUE); } #endif diff -r c2231cf3be71 -r 3bf9748fdef0 pidgin/gtkconv.h --- a/pidgin/gtkconv.h Sun Jun 08 02:47:38 2008 +0000 +++ b/pidgin/gtkconv.h Tue Jun 10 05:18:29 2008 +0000 @@ -150,6 +150,7 @@ gpointer depr1; #endif + GtkWidget *middle_hpaned; GtkWidget *lower_hbox; GtkWidget *toolbar; diff -r c2231cf3be71 -r 3bf9748fdef0 pidgin/gtkmedia.c --- a/pidgin/gtkmedia.c Sun Jun 08 02:47:38 2008 +0000 +++ b/pidgin/gtkmedia.c Tue Jun 10 05:18:29 2008 +0000 @@ -28,11 +28,14 @@ #include "internal.h" #include "connection.h" #include "media.h" +#include "pidgin.h" #include "gtkmedia.h" #ifdef USE_VV +#include + typedef enum { /* Waiting for response */ @@ -60,6 +63,10 @@ GtkWidget *recv_progress; PidginMediaState state; + + GtkWidget *display; + GtkWidget *local_video; + GtkWidget *remote_video; }; #define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate)) @@ -178,6 +185,8 @@ gtk_widget_show_all(media->priv->accept); gtk_widget_show_all(media->priv->reject); + + media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); } static gboolean @@ -246,6 +255,8 @@ gst_object_unref(gtkmedia->priv->send_level); if (gtkmedia->priv->recv_level) gst_object_unref(gtkmedia->priv->recv_level); + if (gtkmedia->priv->display) + gtk_widget_destroy(gtkmedia->priv->display); } static void @@ -254,6 +265,12 @@ g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg); } +GtkWidget * +pidgin_media_get_display_widget(GtkWidget *gtkmedia) +{ + return PIDGIN_MEDIA_GET_PRIVATE(gtkmedia)->display; +} + static gboolean media_bus_call(GstBus *bus, GstMessage *msg, gpointer gtkmedia) { @@ -284,30 +301,57 @@ return TRUE; } +static gboolean +create_window (GstBus *bus, GstMessage *message, PidginMedia *gtkmedia) +{ + char *name; + + if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT) + return TRUE; + + if (!gst_structure_has_name(message->structure, "prepare-xwindow-id")) + return TRUE; + + name = gst_object_get_name(GST_MESSAGE_SRC (message)); + purple_debug_info("gtkmedia", "prepare-xwindow-id object name: %s\n", name); + + /* The XOverlay's name is the sink's name with a suffix */ + if (!strncmp(name, "purplevideosink", strlen("purplevideosink"))) + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), + GDK_WINDOW_XWINDOW(gtkmedia->priv->remote_video->window)); + else if (!strncmp(name, "purplelocalvideosink", strlen("purplelocalvideosink"))) + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), + GDK_WINDOW_XWINDOW(gtkmedia->priv->local_video->window)); + g_free(name); + return TRUE; +} + static void pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia) { GstElement *element = purple_media_get_pipeline(media); - GstElement *audiosendbin, *audiosendlevel; - GstElement *audiorecvbin, *audiorecvlevel; - GstElement *videosendbin; - GstElement *videorecvbin; + GstElement *audiosendbin = NULL, *audiosendlevel = NULL; + GstElement *audiorecvbin = NULL, *audiorecvlevel = NULL; + GstElement *videosendbin = NULL; + GstElement *videorecvbin = NULL; GList *sessions = purple_media_get_session_names(media); GstBus *bus; - purple_media_audio_init_src(&audiosendbin, &audiosendlevel); - purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel); - - purple_media_video_init_src(&videosendbin); - purple_media_video_init_recv(&videorecvbin); - for (; sessions; sessions = sessions->next) { if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_AUDIO) { + if (!audiosendbin) + purple_media_audio_init_src(&audiosendbin, &audiosendlevel); + if (!audiorecvbin) + purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel); purple_media_set_src(media, sessions->data, audiosendbin); purple_media_set_sink(media, sessions->data, audiorecvbin); } else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) { + if (!videosendbin) + purple_media_video_init_src(&videosendbin); + if (!videorecvbin) + purple_media_video_init_recv(&videorecvbin); purple_media_set_src(media, sessions->data, videosendbin); purple_media_set_sink(media, sessions->data, videorecvbin); } @@ -320,9 +364,42 @@ NULL); } + if (videorecvbin || videosendbin) { + GtkWidget *aspect; + GtkWidget *remote_video; + GtkWidget *local_video; + + gtk_widget_show(gtkmedia->priv->display); + + aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE); + gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN); + gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0); + + remote_video = gtk_drawing_area_new(); + gtk_container_add(GTK_CONTAINER(aspect), remote_video); + gtk_widget_set_size_request (GTK_WIDGET(remote_video), 100, -1); + gtk_widget_show(remote_video); + gtk_widget_show(aspect); + + aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE); + gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN); + gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0); + + local_video = gtk_drawing_area_new(); + gtk_container_add(GTK_CONTAINER(aspect), local_video); + gtk_widget_show(local_video); + gtk_widget_show(aspect); + + gtkmedia->priv->local_video = local_video; + gtkmedia->priv->remote_video = remote_video; + } + bus = gst_pipeline_get_bus(GST_PIPELINE(element)); gst_bus_add_signal_watch(GST_BUS(bus)); - g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), "message", G_CALLBACK(level_message_cb), gtkmedia); + g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), + "message", G_CALLBACK(level_message_cb), gtkmedia); + if (videorecvbin || videosendbin) + gst_bus_set_sync_handler(bus, (GstBusSyncHandler)create_window, gtkmedia); gst_bus_add_watch(bus, media_bus_call, gtkmedia); gst_object_unref(bus); } diff -r c2231cf3be71 -r 3bf9748fdef0 pidgin/gtkmedia.h --- a/pidgin/gtkmedia.h Sun Jun 08 02:47:38 2008 +0000 +++ b/pidgin/gtkmedia.h Tue Jun 10 05:18:29 2008 +0000 @@ -60,6 +60,7 @@ GType pidgin_media_get_type(void); GtkWidget *pidgin_media_new(PurpleMedia *media); +GtkWidget *pidgin_media_get_display_widget(GtkWidget *gtkmedia); G_END_DECLS