--- a/libpurple/media.c Thu Oct 08 03:25:28 2020 -0500
+++ b/libpurple/media.c Thu Oct 08 23:31:08 2020 -0500
@@ -1371,13 +1371,13 @@
purple_media_set_output_window(PurpleMedia *media, const gchar *session_id,
- const gchar *participant, gulong window_id)
+ const gchar *participant) g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE);
return purple_media_manager_set_output_window(media->priv->manager,
- media, session_id, participant, window_id);
+ media, session_id, participant); --- a/libpurple/media.h Thu Oct 08 03:25:28 2020 -0500
+++ b/libpurple/media.h Thu Oct 08 23:31:08 2020 -0500
@@ -509,15 +509,13 @@
* @media: The media instance to set the output window on.
* @session_id: The session to set the output window on.
* @participant: Optionally, the participant to set the output window on.
- * @window_id: The window id use for embedding the video in.
* Sets a video output window for the given session/stream.
* Returns: An id to reference the output window.
gulong purple_media_set_output_window(PurpleMedia *media,
- const gchar *session_id, const gchar *participant,
+ const gchar *session_id, const gchar *participant); * purple_media_remove_output_windows:
--- a/libpurple/mediamanager.c Thu Oct 08 03:25:28 2020 -0500
+++ b/libpurple/mediamanager.c Thu Oct 08 23:31:08 2020 -0500
@@ -50,7 +50,6 @@
@@ -71,9 +70,7 @@
PurpleMediaElementInfo *audio_src;
PurpleMediaElementInfo *audio_sink;
-#if GST_CHECK_VERSION(1, 4, 0)
GstDeviceMonitor *device_monitor;
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
#ifdef HAVE_MEDIA_APPLICATION
/* Application data streams */
@@ -238,12 +235,10 @@
(GDestroyNotify) free_appdata_info_locked);
g_mutex_clear (&priv->appdata_mutex);
-#if GST_CHECK_VERSION(1, 4, 0)
if (priv->device_monitor) {
gst_device_monitor_stop(priv->device_monitor);
g_object_unref(priv->device_monitor);
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
G_OBJECT_CLASS(purple_media_manager_parent_class)->finalize(media);
@@ -1390,30 +1385,6 @@
-window_id_cb(GstBus *bus, GstMessage *msg, PurpleMediaOutputWindow *ow)
- if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT
- || !gst_is_video_overlay_prepare_window_handle_message(msg))
- sink = GST_ELEMENT(GST_MESSAGE_SRC(msg));
- while (sink != ow->sink) {
- sink = GST_ELEMENT_PARENT(sink);
- g_signal_handlers_disconnect_matched(bus, G_SIGNAL_MATCH_FUNC
- | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)),
@@ -1433,7 +1404,6 @@
if (ow->sink == NULL && ow->media == media &&
purple_strequal(participant, ow->participant) &&
purple_strequal(session_id, ow->session_id)) {
GstElement *queue, *convert, *scale;
GstElement *tee = purple_media_get_tee(media,
session_id, participant);
@@ -1466,12 +1436,6 @@
gst_bin_add_many(GST_BIN(GST_ELEMENT_PARENT(tee)),
queue, convert, scale, ow->sink, NULL);
- bus = gst_pipeline_get_bus(GST_PIPELINE(
- manager->priv->pipeline));
- g_signal_connect(bus, "sync-message::element",
- G_CALLBACK(window_id_cb), ow);
gst_element_set_state(ow->sink, GST_STATE_PLAYING);
gst_element_set_state(scale, GST_STATE_PLAYING);
gst_element_set_state(convert, GST_STATE_PLAYING);
@@ -1491,7 +1455,7 @@
purple_media_manager_set_output_window(PurpleMediaManager *manager,
PurpleMedia *media, const gchar *session_id,
- const gchar *participant, gulong window_id)
+ const gchar *participant) PurpleMediaOutputWindow *output_window;
@@ -1504,7 +1468,6 @@
output_window->media = media;
output_window->session_id = g_strdup(session_id);
output_window->participant = g_strdup(participant);
- output_window->window_id = window_id;
manager->priv->output_windows = g_list_prepend(
manager->priv->output_windows, output_window);
@@ -1863,8 +1826,6 @@
-#if GST_CHECK_VERSION(1, 4, 0)
static PurpleMediaElementType
gst_class_to_purple_element_type(const gchar *device_class)
@@ -1924,7 +1885,6 @@
-#if GST_CHECK_VERSION(1, 6, 0)
g_return_val_if_fail(device, TRUE);
@@ -1948,7 +1908,6 @@
-#endif /* GST_CHECK_VERSION(1, 6, 0) */
@@ -2063,12 +2022,9 @@
return G_SOURCE_CONTINUE;
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
purple_media_manager_init_device_monitor(PurpleMediaManager *manager)
-#if GST_CHECK_VERSION(1, 4, 0)
@@ -2090,7 +2046,6 @@
purple_media_manager_register_gst_device(manager, device);
gst_object_unref(device);
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
@@ -2177,11 +2132,9 @@
purple_media_manager_register_static_elements(PurpleMediaManager *manager)
static const gchar *VIDEO_SINK_PLUGINS[] = {
+ "gtkglsink", "GTK OpenGL", /* "aasink", "AALib", Didn't work for me */
- "directdrawsink", "DirectDraw",
- "glimagesink", "OpenGL",
- "ximagesink", "X Window System",
- "xvimagesink", "X Window System (Xv)",
const gchar **sinks = VIDEO_SINK_PLUGINS;
--- a/libpurple/mediamanager.h Thu Oct 08 03:25:28 2020 -0500
+++ b/libpurple/mediamanager.h Thu Oct 08 23:31:08 2020 -0500
@@ -231,7 +231,6 @@
* @media: The media instance to find the stream in.
* @session_id: The session the stream is associated with.
* @participant: The participant the stream is associated with.
- * @window_id: The window ID to embed the video in.
* Registers a video output window to be created for a given stream.
@@ -239,7 +238,7 @@
gulong purple_media_manager_set_output_window(PurpleMediaManager *manager,
PurpleMedia *media, const gchar *session_id,
- const gchar *participant, gulong window_id);
+ const gchar *participant); * purple_media_manager_remove_output_window:
--- a/pidgin/gtkmedia.c Thu Oct 08 03:25:28 2020 -0500
+++ b/pidgin/gtkmedia.c Thu Oct 08 23:31:08 2020 -0500
@@ -520,68 +520,6 @@
-} PidginMediaRealizeData;
-realize_cb_cb(PidginMediaRealizeData *data)
- PidginMediaPrivate *priv = data->gtkmedia->priv;
- GdkWindow *window = NULL;
- if (data->participant == NULL)
- window = gtk_widget_get_window(priv->local_video);
- GtkWidget *widget = pidgin_media_get_widget(data->gtkmedia,
- data->session_id, data->participant);
- window = gtk_widget_get_window(widget);
-#ifdef GDK_WINDOWING_WIN32
- if (GDK_IS_WIN32_WINDOW(window))
- window_id = GPOINTER_TO_UINT(GDK_WINDOW_HWND(window));
-#ifdef GDK_WINDOWING_X11
- if (GDK_IS_X11_WINDOW(window))
- window_id = gdk_x11_window_get_xid(window);
-#ifdef GDK_WINDOWING_QUARTZ
- if (GDK_IS_QUARTZ_WINDOW(window))
- window_id = (gulong)gdk_quartz_window_get_nsview(window);
- g_warning("Unsupported GDK backend");
-#if !(defined(GDK_WINDOWING_WIN32) \
- || defined(GDK_WINDOWING_X11) \
- || defined(GDK_WINDOWING_QUARTZ))
-# error "Unsupported GDK windowing system"
- purple_media_set_output_window(priv->media, data->session_id,
- data->participant, window_id);
- g_free(data->session_id);
- g_free(data->participant);
-realize_cb(GtkWidget *widget, PidginMediaRealizeData *data)
- g_timeout_add(0, (GSourceFunc)realize_cb_cb, data);
pidgin_media_error_cb(PidginMedia *media, const char *error, PidginMedia *gtkmedia)
@@ -927,58 +865,43 @@
if (type & PURPLE_MEDIA_RECV_VIDEO) {
- PidginMediaRealizeData *data;
- GtkWidget *remote_video;
- aspect = gtk_aspect_frame_new(NULL, 0, 0, 4.0/3.0, FALSE);
- gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
- gtk_box_pack_start(GTK_BOX(recv_widget), aspect, TRUE, TRUE, 0);
- data = g_new0(PidginMediaRealizeData, 1);
- data->gtkmedia = gtkmedia;
- data->session_id = g_strdup(sid);
- data->participant = g_strdup(gtkmedia->priv->screenname);
+ PidginMediaPrivate *priv = gtkmedia->priv; + PurpleMediaManager *manager = NULL; + GstElement *pipeline = NULL; + GstElement *sink = NULL; + GtkWidget *remote_video = NULL; - remote_video = pidgin_create_video_widget();
- g_signal_connect(G_OBJECT(remote_video), "realize",
- G_CALLBACK(realize_cb), data);
- gtk_container_add(GTK_CONTAINER(aspect), remote_video);
- gtk_widget_set_size_request (GTK_WIDGET(remote_video), 320, 240);
- g_signal_connect(G_OBJECT(remote_video), "destroy",
- G_CALLBACK(destroy_parent_widget_cb), aspect);
+ purple_media_set_output_window(priv->media, sid, priv->screenname); + manager = purple_media_get_manager(priv->media); + pipeline = purple_media_manager_get_pipeline(manager); + sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtkglsink"); + sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtksink"); + g_object_get(G_OBJECT(sink), "widget", &remote_video, NULL); + gtk_widget_show(remote_video); + gtk_box_pack_start(GTK_BOX(recv_widget), remote_video, TRUE, TRUE, 0); - gtk_widget_show(remote_video);
- gtk_widget_show(aspect);
- pidgin_media_insert_widget(gtkmedia, remote_video,
- data->session_id, data->participant);
+ pidgin_media_insert_widget(gtkmedia, remote_video, sid, priv->screenname); if (type & PURPLE_MEDIA_SEND_VIDEO && !gtkmedia->priv->local_video) {
- PidginMediaRealizeData *data;
- GtkWidget *local_video;
- aspect = gtk_aspect_frame_new(NULL, 0, 0, 4.0/3.0, TRUE);
- gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
- gtk_box_pack_start(GTK_BOX(send_widget), aspect, FALSE, TRUE, 0);
+ PidginMediaPrivate *priv = gtkmedia->priv; + PurpleMediaManager *manager = NULL; + GstElement *pipeline = NULL; + GstElement *sink = NULL; + GtkWidget *local_video = NULL; - data = g_new0(PidginMediaRealizeData, 1);
- data->gtkmedia = gtkmedia;
- data->session_id = g_strdup(sid);
- data->participant = NULL;
- local_video = pidgin_create_video_widget();
- g_signal_connect(G_OBJECT(local_video), "realize",
- G_CALLBACK(realize_cb), data);
- gtk_container_add(GTK_CONTAINER(aspect), local_video);
- gtk_widget_set_size_request (GTK_WIDGET(local_video), 80, 60);
- g_signal_connect(G_OBJECT(local_video), "destroy",
- G_CALLBACK(destroy_parent_widget_cb), aspect);
+ purple_media_set_output_window(priv->media, sid, NULL); + manager = purple_media_get_manager(priv->media); + pipeline = purple_media_manager_get_pipeline(manager); + sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtkglsink"); + sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtksink"); + g_object_get(G_OBJECT(sink), "widget", &local_video, NULL); gtk_widget_show(local_video);
- gtk_widget_show(aspect);
+ gtk_box_pack_start(GTK_BOX(send_widget), local_video, TRUE, TRUE, 0); gtk_toggle_button_new_with_mnemonic(_("_Pause"));
--- a/pidgin/gtkprefs.c Thu Oct 08 03:25:28 2020 -0500
+++ b/pidgin/gtkprefs.c Thu Oct 08 23:31:08 2020 -0500
@@ -225,7 +225,8 @@
- GtkWidget *drawing_area;
+ GtkWidget *sink_widget; @@ -2525,57 +2526,20 @@
-window_id_cb(GstBus *bus, GstMessage *msg, gulong window_id)
- if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT ||
- !gst_is_video_overlay_prepare_window_handle_message(msg)) {
- g_signal_handlers_disconnect_matched(bus,
- G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, window_id_cb,
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)),
enable_video_test(PidginPrefsWindow *win)
- GdkWindow *window = gtk_widget_get_window(win->vv.video.drawing_area);
-#ifdef GDK_WINDOWING_WIN32
- if (GDK_IS_WIN32_WINDOW(window))
- window_id = GPOINTER_TO_UINT(GDK_WINDOW_HWND(window));
-#ifdef GDK_WINDOWING_X11
- if (GDK_IS_X11_WINDOW(window))
- window_id = gdk_x11_window_get_xid(window);
-#ifdef GDK_WINDOWING_QUARTZ
- if (GDK_IS_QUARTZ_WINDOW(window))
- window_id = (gulong)gdk_quartz_window_get_nsview(window);
- g_warning("Unsupported GDK backend");
-#if !(defined(GDK_WINDOWING_WIN32) \
- || defined(GDK_WINDOWING_X11) \
- || defined(GDK_WINDOWING_QUARTZ))
-# error "Unsupported GDK windowing system"
+ GtkWidget *video = NULL; + GstElement *sink = NULL; win->vv.video.pipeline = create_video_pipeline();
- bus = gst_pipeline_get_bus(GST_PIPELINE(win->vv.video.pipeline));
- gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, NULL, NULL);
- g_signal_connect(bus, "sync-message::element",
- G_CALLBACK(window_id_cb), (gpointer)window_id);
+ sink = g_object_get_data(G_OBJECT(win->vv.video.pipeline), "sink"); + g_object_get(sink, "widget", &video, NULL); + gtk_widget_show(video); + g_clear_pointer(&win->vv.video.sink_widget, gtk_widget_destroy); + gtk_container_add(GTK_CONTAINER(win->vv.video.frame), video); + win->vv.video.sink_widget = video; gst_element_set_state(GST_ELEMENT(win->vv.video.pipeline),
@@ -2601,27 +2565,10 @@
bind_video_test(PidginPrefsWindow *win, GtkBuilder *builder)
- GdkRGBA color = {0.0, 0.0, 0.0, 1.0};
- win->vv.video.drawing_area = video = GTK_WIDGET(
- gtk_builder_get_object(builder, "vv.video.test_area"));
- gtk_widget_override_background_color(video, GTK_STATE_FLAG_NORMAL,
- /* In order to enable client shadow decorations, GtkDialog from GTK+ 3.0
- * uses ARGB visual which by default gets inherited by its child
- * widgets. XVideo adaptors on the other hand often support just depth
- * 24 and rendering video through xvimagesink onto a widget inside a
- * GtkDialog then results in no visible output.
- * This ensures the default system visual of the drawing area doesn't
- * get overridden by the widget's parent.
- gtk_widget_set_visual(video, gdk_screen_get_system_visual(
- gtk_widget_get_screen(video)));
+ win->vv.video.frame = GTK_WIDGET( + gtk_builder_get_object(builder, "vv.video.frame")); test = gtk_builder_get_object(builder, "vv.video.test");
g_signal_connect(test, "toggled",
G_CALLBACK(toggle_video_test_cb), win);
@@ -3142,6 +3089,8 @@
pidgin_prefs_update_old(void)
+ const gchar *video_sink = NULL; /* Rename some old prefs */
purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_ims", "/purple/logging/log_ims");
purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_chats", "/purple/logging/log_chats");
@@ -3270,6 +3219,18 @@
purple_prefs_get_string("/plugins/gtk/vvconfig/video/sink/device"));
+ video_sink = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/vvconfig/video/sink/device"); + if (purple_strequal(video_sink, "glimagesink") || purple_strequal(video_sink, "directdrawsink")) { + /* Accelerated sinks move to GTK GL. */ + video_sink = "gtkglsink"; + /* FIXME: I haven't been able to get gtkglsink to work yet: */ + video_sink = "gtksink"; + /* Everything else, including default will be moved to GTK sink. */ + video_sink = "gtksink"; + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/vvconfig/video/sink/device", video_sink); purple_prefs_remove("/plugins/core/vvconfig");
purple_prefs_remove("/plugins/gtk/vvconfig");
--- a/pidgin/gtkutils.c Thu Oct 08 03:25:28 2020 -0500
+++ b/pidgin/gtkutils.c Thu Oct 08 23:31:08 2020 -0500
@@ -128,30 +128,6 @@
*****************************************************************************/
-pidgin_create_video_widget(void)
- GtkWidget *video = NULL;
- GdkRGBA color = {0.0, 0.0, 0.0, 1.0};
- video = gtk_drawing_area_new();
- gtk_widget_override_background_color(video, GTK_STATE_FLAG_NORMAL, &color);
- /* In order to enable client shadow decorations, GtkDialog from GTK+ 3.0
- * uses ARGB visual which by default gets inherited by its child widgets.
- * XVideo adaptors on the other hand often support just depth 24 and
- * rendering video through xvimagesink onto a widget inside a GtkDialog
- * then results in no visible output.
- * This ensures the default system visual of the drawing area doesn't get
- * overridden by the widget's parent.
- gtk_widget_set_visual(video,
- gdk_screen_get_system_visual(gtk_widget_get_screen(video)));
pidgin_dialog_get_vbox_with_properties(GtkDialog *dialog, gboolean homogeneous, gint spacing)
GtkBox *vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
--- a/pidgin/resources/Prefs/vv.ui Thu Oct 08 03:25:28 2020 -0500
+++ b/pidgin/resources/Prefs/vv.ui Thu Oct 08 23:31:08 2020 -0500
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1
+<!-- Generated with glade 3.36.0 Pidgin - Internet Messenger
Copyright (C) Pidgin Developers <devel@pidgin.im>
@@ -521,19 +521,14 @@
- <object class="GtkAspectFrame">
+ <object class="GtkAspectFrame" id="vv.video.frame"> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="ratio">1.3300000429153442</property>
- <object class="GtkDrawingArea" id="vv.video.test_area">
- <property name="width_request">240</property>
- <property name="height_request">180</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>