pidgin/pidgin

vv: Switch to GTK sinks by default.

2020-10-08, Elliott Sales de Andrade
86e0c5080a58
Parents aa0d59a5c23d
Children 42556c49e1e2
vv: Switch to GTK sinks by default.

Set minimum gstreamer to 1.14.

Stop trying to set window id on GStreamer sinks. This is all handled by gtksink.

Use gtksink's embedding widget in conversations. This replaces the previous window id method, and doesn't need fiddling with GStreamer events.

Testing Done:
Compiled; tested prefs window. Did not check conversations because I don't know how to test that.

Reviewed at https://reviews.imfreedom.org/r/154/
--- 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 @@
gulong
purple_media_set_output_window(PurpleMedia *media, const gchar *session_id,
- const gchar *participant, gulong window_id)
+ const gchar *participant)
{
#ifdef USE_VV
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);
#else
return 0;
#endif
--- 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,
- gulong window_id);
+ 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 @@
PurpleMedia *media;
gchar *session_id;
gchar *participant;
- gulong window_id;
GstElement *sink;
};
@@ -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);
#endif
-#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 @@
return NULL;
}
-
-static void
-window_id_cb(GstBus *bus, GstMessage *msg, PurpleMediaOutputWindow *ow)
-{
- GstElement *sink;
-
- if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT
- || !gst_is_video_overlay_prepare_window_handle_message(msg))
- return;
-
- sink = GST_ELEMENT(GST_MESSAGE_SRC(msg));
- while (sink != ow->sink) {
- if (sink == NULL)
- return;
- sink = GST_ELEMENT_PARENT(sink);
- }
-
- g_signal_handlers_disconnect_matched(bus, G_SIGNAL_MATCH_FUNC
- | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
- window_id_cb, ow);
-
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)),
- ow->window_id);
-}
#endif
gboolean
@@ -1433,7 +1404,6 @@
if (ow->sink == NULL && ow->media == media &&
purple_strequal(participant, ow->participant) &&
purple_strequal(session_id, ow->session_id)) {
- GstBus *bus;
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_object_unref(bus);
-
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 @@
gulong
purple_media_manager_set_output_window(PurpleMediaManager *manager,
PurpleMedia *media, const gchar *session_id,
- const gchar *participant, gulong window_id)
+ const gchar *participant)
{
#ifdef USE_VV
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 @@
{
gboolean result = FALSE;
-#if GST_CHECK_VERSION(1, 6, 0)
gchar *device_class;
g_return_val_if_fail(device, TRUE);
@@ -1948,7 +1908,6 @@
}
g_free(device_class);
-#endif /* GST_CHECK_VERSION(1, 6, 0) */
return result;
}
@@ -2063,12 +2022,9 @@
return G_SOURCE_CONTINUE;
}
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
-
static void
purple_media_manager_init_device_monitor(PurpleMediaManager *manager)
{
-#if GST_CHECK_VERSION(1, 4, 0)
GstBus *bus;
GList *i;
@@ -2090,7 +2046,6 @@
purple_media_manager_register_gst_device(manager, device);
gst_object_unref(device);
}
-#endif /* GST_CHECK_VERSION(1, 4, 0) */
}
GList *
@@ -2177,11 +2132,9 @@
purple_media_manager_register_static_elements(PurpleMediaManager *manager)
{
static const gchar *VIDEO_SINK_PLUGINS[] = {
+ "gtksink", "GTK",
+ "gtkglsink", "GTK OpenGL",
/* "aasink", "AALib", Didn't work for me */
- "directdrawsink", "DirectDraw",
- "glimagesink", "OpenGL",
- "ximagesink", "X Window System",
- "xvimagesink", "X Window System (Xv)",
NULL
};
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/meson.build Thu Oct 08 03:25:28 2020 -0500
+++ b/meson.build Thu Oct 08 23:31:08 2020 -0500
@@ -351,7 +351,7 @@
# Check for GStreamer
#######################################################################
-gstreamer = dependency('gstreamer-1.0')
+gstreamer = dependency('gstreamer-1.0', version : '>=1.14')
#######################################################################
# Check for GStreamer Video
--- 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 @@
g_object_unref(account);
}
-typedef struct
-{
- PidginMedia *gtkmedia;
- gchar *session_id;
- gchar *participant;
-} PidginMediaRealizeData;
-
-static gboolean
-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);
- else {
- GtkWidget *widget = pidgin_media_get_widget(data->gtkmedia,
- data->session_id, data->participant);
- if (widget)
- window = gtk_widget_get_window(widget);
- }
-
- if (window) {
- gulong window_id = 0;
-#ifdef GDK_WINDOWING_WIN32
- if (GDK_IS_WIN32_WINDOW(window))
- window_id = GPOINTER_TO_UINT(GDK_WINDOW_HWND(window));
- else
-#endif
-#ifdef GDK_WINDOWING_X11
- if (GDK_IS_X11_WINDOW(window))
- window_id = gdk_x11_window_get_xid(window);
- else
-#endif
-#ifdef GDK_WINDOWING_QUARTZ
- if (GDK_IS_QUARTZ_WINDOW(window))
- window_id = (gulong)gdk_quartz_window_get_nsview(window);
- else
-#endif
- g_warning("Unsupported GDK backend");
-#if !(defined(GDK_WINDOWING_WIN32) \
- || defined(GDK_WINDOWING_X11) \
- || defined(GDK_WINDOWING_QUARTZ))
-# error "Unsupported GDK windowing system"
-#endif
-
- purple_media_set_output_window(priv->media, data->session_id,
- data->participant, window_id);
- }
-
- g_free(data->session_id);
- g_free(data->participant);
- g_free(data);
- return FALSE;
-}
-
-static void
-realize_cb(GtkWidget *widget, PidginMediaRealizeData *data)
-{
- g_timeout_add(0, (GSourceFunc)realize_cb_cb, data);
-}
-
static void
pidgin_media_error_cb(PidginMedia *media, const char *error, PidginMedia *gtkmedia)
{
@@ -927,58 +865,43 @@
}
if (type & PURPLE_MEDIA_RECV_VIDEO) {
- PidginMediaRealizeData *data;
- GtkWidget *aspect;
- 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");
+ if (sink == NULL) {
+ 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 *aspect;
- 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");
+ if (sink == NULL) {
+ 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);
gtkmedia->priv->pause =
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 @@
struct {
PidginPrefCombo input;
PidginPrefCombo output;
- GtkWidget *drawing_area;
+ GtkWidget *frame;
+ GtkWidget *sink_widget;
GtkWidget *test;
GstElement *pipeline;
} video;
@@ -2525,57 +2526,20 @@
}
static void
-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)) {
- return;
- }
-
- g_signal_handlers_disconnect_matched(bus,
- G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, window_id_cb,
- (gpointer)window_id);
-
- gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)),
- window_id);
-}
-
-static void
enable_video_test(PidginPrefsWindow *win)
{
- GstBus *bus;
- GdkWindow *window = gtk_widget_get_window(win->vv.video.drawing_area);
- gulong window_id = 0;
-
-#ifdef GDK_WINDOWING_WIN32
- if (GDK_IS_WIN32_WINDOW(window))
- window_id = GPOINTER_TO_UINT(GDK_WINDOW_HWND(window));
- else
-#endif
-#ifdef GDK_WINDOWING_X11
- if (GDK_IS_X11_WINDOW(window))
- window_id = gdk_x11_window_get_xid(window);
- else
-#endif
-#ifdef GDK_WINDOWING_QUARTZ
- if (GDK_IS_QUARTZ_WINDOW(window))
- window_id = (gulong)gdk_quartz_window_get_nsview(window);
- else
-#endif
- g_warning("Unsupported GDK backend");
-#if !(defined(GDK_WINDOWING_WIN32) \
- || defined(GDK_WINDOWING_X11) \
- || defined(GDK_WINDOWING_QUARTZ))
-# error "Unsupported GDK windowing system"
-#endif
+ 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);
- gst_object_unref(bus);
+
+ 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),
GST_STATE_PLAYING);
@@ -2601,27 +2565,10 @@
static void
bind_video_test(PidginPrefsWindow *win, GtkBuilder *builder)
{
- GtkWidget *video;
GObject *test;
- 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,
- &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)));
-
+
+ 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 @@
void
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";
+ } else {
+ /* 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 @@
* Code
*****************************************************************************/
GtkWidget *
-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)));
-
- return video;
-}
-
-GtkWidget *
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/gtkutils.h Thu Oct 08 03:25:28 2020 -0500
+++ b/pidgin/gtkutils.h Thu Oct 08 23:31:08 2020 -0500
@@ -64,15 +64,6 @@
G_BEGIN_DECLS
/**
- * pidgin_create_video_widget:
- *
- * Creates a new drawing area suitable for displaying a video
- *
- * Returns: (transfer full): A new drawing area for displaying video.
- */
-GtkWidget *pidgin_create_video_widget(void);
-
-/**
* pidgin_dialog_get_vbox_with_properties:
* @dialog: The dialog window
* @homogeneous: TRUE if all children are to be given equal space allotments.
--- 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 @@
</packing>
</child>
<child>
- <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>
<child>
- <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>
- </object>
+ <placeholder/>
</child>
</object>
<packing>