diff --git a/pidgin-2.10.11-add-dtmf-support.patch b/pidgin-2.10.11-add-dtmf-support.patch deleted file mode 100644 index b7d7506..0000000 --- a/pidgin-2.10.11-add-dtmf-support.patch +++ /dev/null @@ -1,350 +0,0 @@ - -# HG changeset patch -# User David Woodhouse -# Date 1425675783 0 -# Node ID 6b4576edf2a694ab55d0d06d3643c44601a75b15 -# Parent 714ba418d0aa5ba0cc4cc3b9db37296cd2bbf041 -Add out-of-band DTMF support and dialpad to use it - -This is a backport of e4c122196b08 from the trunk. It adds the UI and -farstream backend support for sending DTMF. - -Fixes #15575 - -diff --git a/libpurple/media.c b/libpurple/media.c ---- a/libpurple/media.c -+++ b/libpurple/media.c -@@ -1439,3 +1439,46 @@ - } - #endif /* USE_GSTREAMER */ - -+gboolean -+purple_media_send_dtmf(PurpleMedia *media, const gchar *session_id, -+ gchar dtmf, guint8 volume, guint16 duration) -+{ -+#ifdef USE_VV -+ PurpleAccount *account = NULL; -+ PurpleConnection *gc = NULL; -+ PurplePlugin *prpl = NULL; -+ PurplePluginProtocolInfo *prpl_info = NULL; -+ PurpleMediaBackendIface *backend_iface = NULL; -+ -+ if (media) -+ { -+ account = purple_media_get_account(media); -+ backend_iface = PURPLE_MEDIA_BACKEND_GET_INTERFACE(media->priv->backend); -+ } -+ if (account) -+ gc = purple_account_get_connection(account); -+ if (gc) -+ prpl = purple_connection_get_prpl(gc); -+ if (prpl) -+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); -+ -+ if (dtmf == 'a') -+ dtmf = 'A'; -+ else if (dtmf == 'b') -+ dtmf = 'B'; -+ else if (dtmf == 'c') -+ dtmf = 'C'; -+ else if (dtmf == 'd') -+ dtmf = 'D'; -+ -+ g_return_val_if_fail(strchr("0123456789ABCD#*", dtmf), FALSE); -+ -+ if (backend_iface && backend_iface->send_dtmf -+ && backend_iface->send_dtmf(media->priv->backend, -+ session_id, dtmf, volume, duration)) -+ { -+ return TRUE; -+ } -+#endif -+ return FALSE; -+} -diff --git a/libpurple/media.h b/libpurple/media.h ---- a/libpurple/media.h -+++ b/libpurple/media.h -@@ -437,6 +437,21 @@ - */ - void purple_media_remove_output_windows(PurpleMedia *media); - -+/** -+ * Sends a DTMF signal out-of-band. -+ * -+ * @param media The media instance to send a DTMF signal to. -+ * @param sess_id The session id of the session to send the DTMF signal on. -+ * @param dtmf The character representing the DTMF in the range [0-9#*A-D]. -+ * @param volume The power level expressed in dBm0 after dropping the sign -+ * in the range of 0 to 63. A larger value represents a lower volume. -+ * @param duration The duration of the tone in milliseconds. -+ * -+ * @since 2.11 -+ */ -+gboolean purple_media_send_dtmf(PurpleMedia *media, const gchar *session_id, -+ gchar dtmf, guint8 volume, guint16 duration); -+ - #ifdef __cplusplus - } - #endif -diff --git a/libpurple/media/backend-fs2.c b/libpurple/media/backend-fs2.c ---- a/libpurple/media/backend-fs2.c -+++ b/libpurple/media/backend-fs2.c -@@ -94,6 +94,9 @@ - static void purple_media_backend_fs2_set_params(PurpleMediaBackend *self, - guint num_params, GParameter *params); - static const gchar **purple_media_backend_fs2_get_available_params(void); -+static gboolean purple_media_backend_fs2_send_dtmf( -+ PurpleMediaBackend *self, const gchar *sess_id, -+ gchar dtmf, guint8 volume, guint16 duration); - - static void free_stream(PurpleMediaBackendFs2Stream *stream); - static void free_session(PurpleMediaBackendFs2Session *session); -@@ -499,6 +502,7 @@ - iface->set_send_codec = purple_media_backend_fs2_set_send_codec; - iface->set_params = purple_media_backend_fs2_set_params; - iface->get_available_params = purple_media_backend_fs2_get_available_params; -+ iface->send_dtmf = purple_media_backend_fs2_send_dtmf; - } - - static FsMediaType -@@ -2436,6 +2440,65 @@ - - return supported_params; - } -+static gboolean -+send_dtmf_callback(gpointer userdata) -+{ -+ FsSession *session = userdata; -+ -+ fs_session_stop_telephony_event(session); -+ -+ return FALSE; -+} -+static gboolean -+purple_media_backend_fs2_send_dtmf(PurpleMediaBackend *self, -+ const gchar *sess_id, gchar dtmf, guint8 volume, -+ guint16 duration) -+{ -+ PurpleMediaBackendFs2Session *session; -+ FsDTMFEvent event; -+ -+ g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), FALSE); -+ -+ session = get_session(PURPLE_MEDIA_BACKEND_FS2(self), sess_id); -+ if (session == NULL) -+ return FALSE; -+ -+ /* Convert DTMF char into FsDTMFEvent enum */ -+ switch(dtmf) { -+ case '0': event = FS_DTMF_EVENT_0; break; -+ case '1': event = FS_DTMF_EVENT_1; break; -+ case '2': event = FS_DTMF_EVENT_2; break; -+ case '3': event = FS_DTMF_EVENT_3; break; -+ case '4': event = FS_DTMF_EVENT_4; break; -+ case '5': event = FS_DTMF_EVENT_5; break; -+ case '6': event = FS_DTMF_EVENT_6; break; -+ case '7': event = FS_DTMF_EVENT_7; break; -+ case '8': event = FS_DTMF_EVENT_8; break; -+ case '9': event = FS_DTMF_EVENT_9; break; -+ case '*': event = FS_DTMF_EVENT_STAR; break; -+ case '#': event = FS_DTMF_EVENT_POUND; break; -+ case 'A': event = FS_DTMF_EVENT_A; break; -+ case 'B': event = FS_DTMF_EVENT_B; break; -+ case 'C': event = FS_DTMF_EVENT_C; break; -+ case 'D': event = FS_DTMF_EVENT_D; break; -+ default: -+ return FALSE; -+ } -+ -+ if (!fs_session_start_telephony_event(session->session, -+ event, volume)) { -+ return FALSE; -+ } -+ -+ if (duration <= 50) { -+ fs_session_stop_telephony_event(session->session); -+ } else { -+ purple_timeout_add(duration, send_dtmf_callback, -+ session->session); -+ } -+ -+ return TRUE; -+} - #else - GType - purple_media_backend_fs2_get_type(void) -diff --git a/libpurple/media/backend-iface.h b/libpurple/media/backend-iface.h ---- a/libpurple/media/backend-iface.h -+++ b/libpurple/media/backend-iface.h -@@ -71,6 +71,9 @@ - void (*set_params) (PurpleMediaBackend *self, - guint num_params, GParameter *params); - const gchar **(*get_available_params) (void); -+ gboolean (*send_dtmf) (PurpleMediaBackend *self, -+ const gchar *sess_id, gchar dtmf, guint8 volume, -+ guint16 duration); - }; - - /** -diff --git a/pidgin/gtkmedia.c b/pidgin/gtkmedia.c ---- a/pidgin/gtkmedia.c -+++ b/pidgin/gtkmedia.c -@@ -41,6 +41,7 @@ - #ifdef _WIN32 - #include - #endif -+#include - - #include - -@@ -759,6 +760,136 @@ - } - - static void -+phone_dtmf_pressed_cb(GtkButton *button, gpointer user_data) -+{ -+ PidginMedia *gtkmedia = user_data; -+ gint num; -+ gchar *sid; -+ -+ num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "dtmf-digit")); -+ sid = g_object_get_data(G_OBJECT(button), "session-id"); -+ -+ purple_media_send_dtmf(gtkmedia->priv->media, sid, num, 25, 50); -+} -+ -+static inline GtkWidget * -+phone_create_button(const gchar *text_hi, const gchar *text_lo) -+{ -+ GtkWidget *button; -+ GtkWidget *label_hi; -+ GtkWidget *label_lo; -+ GtkWidget *grid; -+ const gchar *text_hi_local; -+ -+ if (text_hi) -+ text_hi_local = _(text_hi); -+ else -+ text_hi_local = ""; -+ -+ grid = gtk_vbox_new(TRUE, 0); -+ -+ button = gtk_button_new(); -+ label_hi = gtk_label_new(text_hi_local); -+ gtk_misc_set_alignment(GTK_MISC(label_hi), 0.5, 0.5); -+ gtk_box_pack_end(GTK_BOX(grid), label_hi, FALSE, TRUE, 0); -+ label_lo = gtk_label_new(text_lo); -+ gtk_misc_set_alignment(GTK_MISC(label_lo), 0.5, 0.5); -+ gtk_label_set_use_markup(GTK_LABEL(label_lo), TRUE); -+ gtk_box_pack_end(GTK_BOX(grid), label_lo, FALSE, TRUE, 0); -+ gtk_container_add(GTK_CONTAINER(button), grid); -+ -+ return button; -+} -+ -+static struct phone_label { -+ gchar *subtext; -+ gchar *text; -+ gchar chr; -+} phone_labels[] = { -+ {"1", NULL, '1'}, -+ /* Translators note: These are the letters on the keys of a numeric -+ keypad; translate according to ยง7.2.4 of -+ http://www.etsi.org/deliver/etsi_es/202100_202199/202130/01.01.01_60/es_20213 */ -+ /* Letters on the '2' key of a numeric keypad */ -+ {"2", N_("ABC"), '2'}, -+ /* Letters on the '3' key of a numeric keypad */ -+ {"3", N_("DEF"), '3'}, -+ /* Letters on the '4' key of a numeric keypad */ -+ {"4", N_("GHI"), '4'}, -+ /* Letters on the '5' key of a numeric keypad */ -+ {"5", N_("JKL"), '5'}, -+ /* Letters on the '6' key of a numeric keypad */ -+ {"6", N_("MNO"), '6'}, -+ /* Letters on the '7' key of a numeric keypad */ -+ {"7", N_("PQRS"), '7'}, -+ /* Letters on the '8' key of a numeric keypad */ -+ {"8", N_("TUV"), '8'}, -+ /* Letters on the '9' key of a numeric keypad */ -+ {"9", N_("WXYZ"), '9'}, -+ {"*", NULL, '*'}, -+ {"0", NULL, '0'}, -+ {"#", NULL, '#'}, -+ {NULL, NULL, 0} -+}; -+ -+static gboolean -+pidgin_media_dtmf_key_press_event_cb(GtkWidget *widget, -+ GdkEvent *event, gpointer user_data) -+{ -+ PidginMedia *gtkmedia = user_data; -+ GdkEventKey *key = (GdkEventKey *) event; -+ -+ if (event->type != GDK_KEY_PRESS) { -+ return FALSE; -+ } -+ -+ if ((key->keyval >= GDK_KEY_0 && key->keyval <= GDK_KEY_9) || -+ key->keyval == GDK_KEY_asterisk || -+ key->keyval == GDK_KEY_numbersign) { -+ gchar *sid = g_object_get_data(G_OBJECT(widget), "session-id"); -+ -+ purple_media_send_dtmf(gtkmedia->priv->media, sid, key->keyval, 25, 50); -+ } -+ -+ return FALSE; -+} -+ -+static GtkWidget * -+pidgin_media_add_dtmf_widget(PidginMedia *gtkmedia, -+ PurpleMediaSessionType type, const gchar *_sid) -+{ -+ GtkWidget *grid = gtk_table_new(4, 3, TRUE); -+ GtkWidget *button; -+ gint index = 0; -+ GtkWindow *win = >kmedia->parent; -+ -+ /* Add buttons */ -+ for (index = 0; phone_labels[index].subtext != NULL; index++) { -+ button = phone_create_button(phone_labels[index].text, -+ phone_labels[index].subtext); -+ g_signal_connect(button, "pressed", -+ G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia); -+ g_object_set_data(G_OBJECT(button), "dtmf-digit", -+ GINT_TO_POINTER(phone_labels[index].chr)); -+ g_object_set_data_full(G_OBJECT(button), "session-id", -+ g_strdup(_sid), g_free); -+ gtk_table_attach(GTK_TABLE(grid), button, index % 3, -+ index % 3 + 1, index / 3, index / 3 + 1, -+ GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, -+ 2, 2); -+ } -+ -+ g_signal_connect(G_OBJECT(win), "key-press-event", -+ G_CALLBACK(pidgin_media_dtmf_key_press_event_cb), gtkmedia); -+ g_object_set_data_full(G_OBJECT(win), "session-id", -+ g_strdup(_sid), g_free); -+ -+ gtk_widget_show_all(grid); -+ -+ return grid; -+} -+ -+static void - pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia, const gchar *sid) - { - GtkWidget *send_widget = NULL, *recv_widget = NULL, *button_widget = NULL; -@@ -888,7 +1019,11 @@ - - gtk_box_pack_end(GTK_BOX(recv_widget), - pidgin_media_add_audio_widget(gtkmedia, -- PURPLE_MEDIA_SEND_AUDIO, NULL), FALSE, FALSE, 0); -+ PURPLE_MEDIA_SEND_AUDIO, sid), FALSE, FALSE, 0); -+ -+ gtk_box_pack_end(GTK_BOX(recv_widget), -+ pidgin_media_add_dtmf_widget(gtkmedia, -+ PURPLE_MEDIA_SEND_AUDIO, sid), FALSE, FALSE, 0); - } - - if (type & PURPLE_MEDIA_AUDIO && - diff --git a/pidgin-2.10.11-application-media.patch b/pidgin-2.10.11-application-media.patch deleted file mode 100644 index 3cc66ca..0000000 --- a/pidgin-2.10.11-application-media.patch +++ /dev/null @@ -1,1137 +0,0 @@ - -# HG changeset patch -# User Youness Alaoui -# Date 1405979621 14400 -# Node ID 4fe1034f3dce1c5cd3c929ab8c58db8e27655beb -# Parent d729a9b2126594df3e38647e926ac7c0a7db807b -Add application media type and APIs - -Fixes #16315 - -Index: pidgin-2.10.11/configure.ac -=================================================================== ---- pidgin-2.10.11.orig/configure.ac -+++ pidgin-2.10.11/configure.ac -@@ -916,6 +916,20 @@ fi - AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno") - - dnl ####################################################################### -+dnl # Check for Raw data streams support in Farstream -+dnl ####################################################################### -+if test "x$enable_vv" != "xno" -a "x$with_gstreamer" == "x1.0"; then -+ AC_MSG_CHECKING(for raw data support in Farstream) -+ PKG_CHECK_MODULES(GSTAPP, [gstreamer-app-1.0], [ -+ AC_DEFINE(USE_GSTAPP, 1, [Use GStreamer Video Overlay support]) -+ AC_SUBST(GSTAPP_CFLAGS) -+ AC_SUBST(GSTAPP_LIBS) -+ AC_DEFINE(HAVE_MEDIA_APPLICATION, 1, [Define if we have support for application media type.]) -+ AC_MSG_RESULT(yes) -+ ], [AC_MSG_RESULT(no)]) -+fi -+ -+dnl ####################################################################### - dnl # Check for Internationalized Domain Name support - dnl ####################################################################### - -Index: pidgin-2.10.11/libpurple/Makefile.am -=================================================================== ---- pidgin-2.10.11.orig/libpurple/Makefile.am -+++ pidgin-2.10.11/libpurple/Makefile.am -@@ -314,6 +314,7 @@ libpurple_la_LIBADD = \ - $(FARSTREAM_LIBS) \ - $(GSTREAMER_LIBS) \ - $(GSTVIDEO_LIBS) \ -+ $(GSTAPP_LIBS) \ - $(GSTINTERFACES_LIBS) \ - $(IDN_LIBS) \ - ciphers/libpurple-ciphers.la \ -@@ -331,6 +332,7 @@ AM_CPPFLAGS = \ - $(FARSTREAM_CFLAGS) \ - $(GSTREAMER_CFLAGS) \ - $(GSTVIDEO_CFLAGS) \ -+ $(GSTAPP_CFLAGS) \ - $(GSTINTERFACES_CFLAGS) \ - $(IDN_CFLAGS) \ - $(NETWORKMANAGER_CFLAGS) \ -Index: pidgin-2.10.11/libpurple/media-gst.h -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media-gst.h -+++ pidgin-2.10.11/libpurple/media-gst.h -@@ -71,6 +71,7 @@ typedef enum { - - PURPLE_MEDIA_ELEMENT_SRC = 1 << 9, /** can be set as an active src */ - PURPLE_MEDIA_ELEMENT_SINK = 1 << 10, /** can be set as an active sink */ -+ PURPLE_MEDIA_ELEMENT_APPLICATION = 1 << 11, /** supports application data */ - } PurpleMediaElementType; - - #ifdef __cplusplus -Index: pidgin-2.10.11/libpurple/media/backend-fs2.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media/backend-fs2.c -+++ pidgin-2.10.11/libpurple/media/backend-fs2.c -@@ -543,6 +543,10 @@ session_type_to_fs_media_type(PurpleMedi - return FS_MEDIA_TYPE_AUDIO; - else if (type & PURPLE_MEDIA_VIDEO) - return FS_MEDIA_TYPE_VIDEO; -+#ifdef HAVE_MEDIA_APPLICATION -+ else if (type & PURPLE_MEDIA_APPLICATION) -+ return FS_MEDIA_TYPE_APPLICATION; -+#endif - else - return 0; - } -@@ -551,7 +555,7 @@ static FsStreamDirection - session_type_to_fs_stream_direction(PurpleMediaSessionType type) - { - if ((type & PURPLE_MEDIA_AUDIO) == PURPLE_MEDIA_AUDIO || -- (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) -+ (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) - return FS_DIRECTION_BOTH; - else if ((type & PURPLE_MEDIA_SEND_AUDIO) || - (type & PURPLE_MEDIA_SEND_VIDEO)) -@@ -559,6 +563,14 @@ session_type_to_fs_stream_direction(Purp - else if ((type & PURPLE_MEDIA_RECV_AUDIO) || - (type & PURPLE_MEDIA_RECV_VIDEO)) - return FS_DIRECTION_RECV; -+#ifdef HAVE_MEDIA_APPLICATION -+ else if ((type & PURPLE_MEDIA_APPLICATION) == PURPLE_MEDIA_APPLICATION) -+ return FS_DIRECTION_BOTH; -+ else if (type & PURPLE_MEDIA_SEND_APPLICATION) -+ return FS_DIRECTION_SEND; -+ else if (type & PURPLE_MEDIA_RECV_APPLICATION) -+ return FS_DIRECTION_RECV; -+#endif - else - return FS_DIRECTION_NONE; - } -@@ -577,6 +589,13 @@ session_type_from_fs(FsMediaType type, F - result |= PURPLE_MEDIA_SEND_VIDEO; - if (direction & FS_DIRECTION_RECV) - result |= PURPLE_MEDIA_RECV_VIDEO; -+#ifdef HAVE_MEDIA_APPLICATION -+ } else if (type == FS_MEDIA_TYPE_APPLICATION) { -+ if (direction & FS_DIRECTION_SEND) -+ result |= PURPLE_MEDIA_SEND_APPLICATION; -+ if (direction & FS_DIRECTION_RECV) -+ result |= PURPLE_MEDIA_RECV_APPLICATION; -+#endif - } - return result; - } -@@ -1333,7 +1352,8 @@ gst_handle_message_error(GstBus *bus, Gs - & PURPLE_MEDIA_AUDIO) - purple_media_error(priv->media, - _("Error with your microphone")); -- else -+ else if (purple_media_get_session_type(priv->media, -+ sessions->data) & PURPLE_MEDIA_VIDEO) - purple_media_error(priv->media, - _("Error with your webcam")); - -@@ -1756,6 +1776,21 @@ create_session(PurpleMediaBackendFs2 *se - session->session = fs_conference_new_session(priv->conference, - session_type_to_fs_media_type(type), &err); - -+#ifdef HAVE_MEDIA_APPLICATION -+ if (type == PURPLE_MEDIA_APPLICATION) { -+ GstCaps *caps; -+ GObject *rtpsession = NULL; -+ -+ caps = gst_caps_new_empty_simple ("application/octet-stream"); -+ fs_session_set_allowed_caps (session->session, caps, caps, NULL); -+ gst_caps_unref (caps); -+ g_object_get (session->session, "internal-session", &rtpsession, NULL); -+ if (rtpsession) { -+ g_object_set (rtpsession, "probation", 0, NULL); -+ g_object_unref (rtpsession); -+ } -+ } -+#endif - if (err != NULL) { - purple_media_error(priv->media, - _("Error creating session: %s"), -@@ -1970,6 +2005,21 @@ src_pad_added_cb(FsStream *fsstream, Gst - gst_bin_add(GST_BIN(priv->confbin), sink); - gst_element_set_state(sink, GST_STATE_PLAYING); - stream->fakesink = sink; -+#ifdef HAVE_MEDIA_APPLICATION -+ } else if (codec->media_type == FS_MEDIA_TYPE_APPLICATION) { -+#if GST_CHECK_VERSION(1,0,0) -+ stream->src = gst_element_factory_make("funnel", NULL); -+#else -+ stream->src = gst_element_factory_make("fsfunnel", NULL); -+#endif -+ sink = purple_media_manager_get_element( -+ purple_media_get_manager(priv->media), -+ PURPLE_MEDIA_RECV_APPLICATION, priv->media, -+ stream->session->id, -+ stream->participant); -+ gst_bin_add(GST_BIN(priv->confbin), sink); -+ gst_element_set_state(sink, GST_STATE_PLAYING); -+#endif - } - stream->tee = gst_element_factory_make("tee", NULL); - gst_bin_add_many(GST_BIN(priv->confbin), -@@ -2332,6 +2382,9 @@ purple_media_backend_fs2_codecs_ready(Pu - return FALSE; - - if (session->type & (PURPLE_MEDIA_SEND_AUDIO | -+#ifdef HAVE_MEDIA_APPLICATION -+ PURPLE_MEDIA_SEND_APPLICATION | -+#endif - PURPLE_MEDIA_SEND_VIDEO)) { - #ifdef HAVE_FARSIGHT - g_object_get(session->session, -@@ -2355,6 +2408,9 @@ purple_media_backend_fs2_codecs_ready(Pu - PurpleMediaBackendFs2Session *session = values->data; - - if (session->type & (PURPLE_MEDIA_SEND_AUDIO | -+#ifdef HAVE_MEDIA_APPLICATION -+ PURPLE_MEDIA_SEND_APPLICATION | -+#endif - PURPLE_MEDIA_SEND_VIDEO)) { - #ifdef HAVE_FARSIGHT - g_object_get(session->session, -Index: pidgin-2.10.11/libpurple/media/codec.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media/codec.c -+++ pidgin-2.10.11/libpurple/media/codec.c -@@ -188,7 +188,7 @@ purple_media_codec_class_init(PurpleMedi - g_object_class_install_property(gobject_class, PROP_MEDIA_TYPE, - g_param_spec_flags("media-type", - "Media Type", -- "Whether this is an audio of video codec.", -+ "Whether this is an audio, video or application codec.", - PURPLE_TYPE_MEDIA_SESSION_TYPE, - PURPLE_MEDIA_NONE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); -@@ -402,6 +402,8 @@ purple_media_codec_to_string(const Purpl - media_type_str = "audio"; - else if (priv->media_type & PURPLE_MEDIA_VIDEO) - media_type_str = "video"; -+ else if (priv->media_type & PURPLE_MEDIA_APPLICATION) -+ media_type_str = "application"; - - g_string_printf(string, "%d: %s %s clock:%d channels:%d", priv->id, - media_type_str, priv->encoding_name, -Index: pidgin-2.10.11/libpurple/media/enum-types.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media/enum-types.c -+++ pidgin-2.10.11/libpurple/media/enum-types.c -@@ -176,10 +176,16 @@ purple_media_session_type_get_type() - "PURPLE_MEDIA_RECV_VIDEO", "recv-video" }, - { PURPLE_MEDIA_SEND_VIDEO, - "PURPLE_MEDIA_SEND_VIDEO", "send-video" }, -+ { PURPLE_MEDIA_RECV_APPLICATION, -+ "PURPLE_MEDIA_RECV_APPLICATION", "recv-application" }, -+ { PURPLE_MEDIA_SEND_APPLICATION, -+ "PURPLE_MEDIA_SEND_APPLICATION", "send-application" }, - { PURPLE_MEDIA_AUDIO, - "PURPLE_MEDIA_AUDIO", "audio" }, - { PURPLE_MEDIA_VIDEO, - "PURPLE_MEDIA_VIDEO", "video" }, -+ { PURPLE_MEDIA_APPLICATION, -+ "PURPLE_MEDIA_APPLICATION", "application" }, - { 0, NULL, NULL } - }; - type = g_flags_register_static( -Index: pidgin-2.10.11/libpurple/media/enum-types.h -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media/enum-types.h -+++ pidgin-2.10.11/libpurple/media/enum-types.h -@@ -92,8 +92,12 @@ typedef enum { - PURPLE_MEDIA_SEND_AUDIO = 1 << 1, - PURPLE_MEDIA_RECV_VIDEO = 1 << 2, - PURPLE_MEDIA_SEND_VIDEO = 1 << 3, -+ PURPLE_MEDIA_RECV_APPLICATION = 1 << 4, -+ PURPLE_MEDIA_SEND_APPLICATION = 1 << 5, - PURPLE_MEDIA_AUDIO = PURPLE_MEDIA_RECV_AUDIO | PURPLE_MEDIA_SEND_AUDIO, -- PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO -+ PURPLE_MEDIA_VIDEO = PURPLE_MEDIA_RECV_VIDEO | PURPLE_MEDIA_SEND_VIDEO, -+ PURPLE_MEDIA_APPLICATION = PURPLE_MEDIA_RECV_APPLICATION | -+ PURPLE_MEDIA_SEND_APPLICATION - } PurpleMediaSessionType; - - /** Media state-changed types */ -Index: pidgin-2.10.11/libpurple/mediamanager.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/mediamanager.c -+++ pidgin-2.10.11/libpurple/mediamanager.c -@@ -44,6 +44,9 @@ - #else - #include - #endif -+#ifdef HAVE_MEDIA_APPLICATION -+#include -+#endif - - #if GST_CHECK_VERSION(1,0,0) - #include -@@ -97,14 +100,45 @@ struct _PurpleMediaManagerPrivate - PurpleMediaElementInfo *video_sink; - PurpleMediaElementInfo *audio_src; - PurpleMediaElementInfo *audio_sink; -+ -+#ifdef HAVE_MEDIA_APPLICATION -+ /* Application data streams */ -+ GList *appdata_info; /* holds PurpleMediaAppDataInfo */ -+ GMutex appdata_mutex; -+#endif - }; - -+#ifdef HAVE_MEDIA_APPLICATION -+typedef struct { -+ PurpleMedia *media; -+ GWeakRef media_ref; -+ gchar *session_id; -+ gchar *participant; -+ PurpleMediaAppDataCallbacks callbacks; -+ gpointer user_data; -+ GDestroyNotify notify; -+ GstAppSrc *appsrc; -+ GstAppSink *appsink; -+ gint num_samples; -+ GstSample *current_sample; -+ guint sample_offset; -+ gboolean writable; -+ gboolean connected; -+ guint writable_timer_id; -+ guint readable_timer_id; -+ GCond readable_cond; -+} PurpleMediaAppDataInfo; -+#endif -+ - #define PURPLE_MEDIA_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerPrivate)) - #define PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_ELEMENT_INFO, PurpleMediaElementInfoPrivate)) - - static void purple_media_manager_class_init (PurpleMediaManagerClass *klass); - static void purple_media_manager_init (PurpleMediaManager *media); - static void purple_media_manager_finalize (GObject *object); -+#ifdef HAVE_MEDIA_APPLICATION -+static void free_appdata_info_locked (PurpleMediaAppDataInfo *info); -+#endif - - static GObjectClass *parent_class = NULL; - -@@ -190,8 +224,10 @@ purple_media_manager_init (PurpleMediaMa - media->priv->medias = NULL; - media->priv->private_medias = NULL; - media->priv->next_output_window_id = 1; --#ifdef USE_VV - media->priv->backend_type = PURPLE_TYPE_MEDIA_BACKEND_FS2; -+#ifdef HAVE_MEDIA_APPLICATION -+ media->priv->appdata_info = NULL; -+ g_mutex_init (&media->priv->appdata_mutex); - #endif - - purple_prefs_add_none("/purple/media"); -@@ -220,6 +256,13 @@ purple_media_manager_finalize (GObject * - } - if (priv->video_caps) - gst_caps_unref(priv->video_caps); -+#ifdef HAVE_MEDIA_APPLICATION -+ if (priv->appdata_info) -+ g_list_free_full (priv->appdata_info, -+ (GDestroyNotify) free_appdata_info_locked); -+ g_mutex_clear (&priv->appdata_mutex); -+#endif -+ - parent_class->finalize(media); - } - #endif -@@ -440,8 +483,23 @@ purple_media_manager_remove_media(Purple - medias = &manager->priv->private_medias; - } - -- if (list) -+ if (list) { - *medias = g_list_delete_link(*medias, list); -+ -+#ifdef HAVE_MEDIA_APPLICATION -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ for (list = manager->priv->appdata_info; list; list = list->next) { -+ PurpleMediaAppDataInfo *info = list->data; -+ -+ if (info->media == media) { -+ manager->priv->appdata_info = g_list_delete_link ( -+ manager->priv->appdata_info, list); -+ free_appdata_info_locked (info); -+ } -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+#endif -+ } - #endif - } - -@@ -493,6 +551,92 @@ purple_media_manager_get_private_media_b - return get_media_by_account (manager, account, TRUE); - } - -+#ifdef HAVE_MEDIA_APPLICATION -+static void -+free_appdata_info_locked (PurpleMediaAppDataInfo *info) -+{ -+ if (info->notify) -+ info->notify (info->user_data); -+ -+ /* Make sure no other thread is using the structure */ -+ g_free (info->session_id); -+ g_free (info->participant); -+ -+ if (info->readable_timer_id) { -+ purple_timeout_remove (info->readable_timer_id); -+ info->readable_timer_id = 0; -+ } -+ -+ if (info->writable_timer_id) { -+ purple_timeout_remove (info->writable_timer_id); -+ info->writable_timer_id = 0; -+ } -+ -+ if (info->current_sample) -+ gst_sample_unref (info->current_sample); -+ info->current_sample = NULL; -+ -+ /* Unblock any reading thread before destroying the GCond */ -+ g_cond_broadcast (&info->readable_cond); -+ -+ g_cond_clear (&info->readable_cond); -+ -+ g_slice_free (PurpleMediaAppDataInfo, info); -+} -+ -+/* -+ * Get an app data info struct associated with a session and lock the mutex -+ * We don't want to return an info struct and unlock then it gets destroyed -+ * so we need to return it with the lock still taken -+ */ -+static PurpleMediaAppDataInfo * -+get_app_data_info_and_lock (PurpleMediaManager *manager, -+ PurpleMedia *media, const gchar *session_id, const gchar *participant) -+{ -+ GList *i; -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ for (i = manager->priv->appdata_info; i; i = i->next) { -+ PurpleMediaAppDataInfo *info = i->data; -+ -+ if (info->media == media && -+ g_strcmp0 (info->session_id, session_id) == 0 && -+ (participant == NULL || -+ g_strcmp0 (info->participant, participant) == 0)) { -+ return info; -+ } -+ } -+ -+ return NULL; -+} -+ -+/* -+ * Get an app data info struct associated with a session and lock the mutex -+ * if it doesn't exist, we create it. -+ */ -+static PurpleMediaAppDataInfo * -+ensure_app_data_info_and_lock (PurpleMediaManager *manager, PurpleMedia *media, -+ const gchar *session_id, const gchar *participant) -+{ -+ PurpleMediaAppDataInfo * info = get_app_data_info_and_lock (manager, media, -+ session_id, participant); -+ -+ if (info == NULL) { -+ info = g_slice_new0 (PurpleMediaAppDataInfo); -+ info->media = media; -+ g_weak_ref_init (&info->media_ref, media); -+ info->session_id = g_strdup (session_id); -+ info->participant = g_strdup (participant); -+ g_cond_init (&info->readable_cond); -+ manager->priv->appdata_info = g_list_prepend ( -+ manager->priv->appdata_info, info); -+ } -+ -+ return info; -+} -+#endif -+ -+ - #ifdef USE_VV - static void - request_pad_unlinked_cb(GstPad *pad, GstPad *peer, gpointer user_data) -@@ -577,6 +721,351 @@ purple_media_manager_get_video_caps(Purp - #endif - } - -+#ifdef HAVE_MEDIA_APPLICATION -+/* -+ * Calls the appdata writable callback from the main thread. -+ * This needs to grab the appdata lock and make sure it didn't get destroyed -+ * before calling the callback. -+ */ -+static gboolean -+appsrc_writable (gpointer user_data) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ PurpleMediaAppDataInfo *info = user_data; -+ void (*writable_cb) (PurpleMediaManager *manager, PurpleMedia *media, -+ const gchar *session_id, const gchar *participant, gboolean writable, -+ gpointer user_data); -+ PurpleMedia *media; -+ gchar *session_id; -+ gchar *participant; -+ gboolean writable; -+ gpointer cb_data; -+ guint *timer_id_ptr = &info->writable_timer_id; -+ guint timer_id = *timer_id_ptr; -+ -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ if (timer_id == 0 || timer_id != *timer_id_ptr) { -+ /* In case info was freed while we were waiting for the mutex to unlock -+ * we still have a pointer to the timer_id which should still be -+ * accessible since it's in the Glib slice allocator. It gets set to 0 -+ * just after the timeout is canceled which happens also before the -+ * AppDataInfo is freed, so even if that memory slice gets reused, the -+ * timer_id would be different from its previous value (unless -+ * extremely unlucky). So checking if the value for the timer_id changed -+ * should be enough to prevent any kind of race condition in which the -+ * media/AppDataInfo gets destroyed in one thread while the timeout was -+ * triggered and is waiting on the mutex to get unlocked in this thread -+ */ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return FALSE; -+ } -+ writable_cb = info->callbacks.writable; -+ media = g_weak_ref_get (&info->media_ref); -+ session_id = g_strdup (info->session_id); -+ participant = g_strdup (info->participant); -+ writable = info->writable && info->connected; -+ cb_data = info->user_data; -+ -+ info->writable_timer_id = 0; -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ -+ -+ if (writable_cb && media) -+ writable_cb (manager, media, session_id, participant, writable, -+ cb_data); -+ -+ g_object_unref (media); -+ g_free (session_id); -+ g_free (participant); -+ -+ return FALSE; -+} -+ -+/* -+ * Schedule a writable callback to be called from the main thread. -+ * We need to do this because need-data/enough-data signals from appsrc -+ * will come from the streaming thread and we need to create -+ * a source that we attach to the main context but we can't use -+ * g_main_context_invoke since we need to be able to cancel the source if the -+ * media gets destroyed. -+ * We use a timeout source instead of idle source, so the callback gets a higher -+ * priority -+ */ -+static void -+call_appsrc_writable_locked (PurpleMediaAppDataInfo *info) -+{ -+ /* We already have a writable callback scheduled, don't create another one */ -+ if (info->writable_timer_id || info->callbacks.writable == NULL) -+ return; -+ -+ info->writable_timer_id = purple_timeout_add (0, appsrc_writable, info); -+} -+ -+static void -+appsrc_need_data (GstAppSrc *appsrc, guint length, gpointer user_data) -+{ -+ PurpleMediaAppDataInfo *info = user_data; -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ if (!info->writable) { -+ info->writable = TRUE; -+ /* Only signal writable if we also established a connection */ -+ if (info->connected) -+ call_appsrc_writable_locked (info); -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+} -+ -+static void -+appsrc_enough_data (GstAppSrc *appsrc, gpointer user_data) -+{ -+ PurpleMediaAppDataInfo *info = user_data; -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ if (info->writable) { -+ info->writable = FALSE; -+ call_appsrc_writable_locked (info); -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+} -+ -+static gboolean -+appsrc_seek_data (GstAppSrc *appsrc, guint64 offset, gpointer user_data) -+{ -+ return FALSE; -+} -+ -+static void -+appsrc_destroyed (PurpleMediaAppDataInfo *info) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ info->appsrc = NULL; -+ if (info->writable) { -+ info->writable = FALSE; -+ call_appsrc_writable_locked (info); -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+} -+ -+static void -+media_established_cb (PurpleMedia *media,const gchar *session_id, -+ const gchar *participant, PurpleMediaCandidate *local_candidate, -+ PurpleMediaCandidate *remote_candidate, PurpleMediaAppDataInfo *info) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ info->connected = TRUE; -+ /* We established the connection, if we were writable, then we need to -+ * signal it now */ -+ if (info->writable) -+ call_appsrc_writable_locked (info); -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+} -+ -+static GstElement * -+create_send_appsrc(PurpleMedia *media, -+ const gchar *session_id, const gchar *participant) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ PurpleMediaAppDataInfo * info = ensure_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ GstElement *appsrc = (GstElement *)info->appsrc; -+ -+ if (appsrc == NULL) { -+ GstAppSrcCallbacks callbacks = {appsrc_need_data, appsrc_enough_data, -+ appsrc_seek_data, {NULL}}; -+ GstCaps *caps = gst_caps_new_empty_simple ("application/octet-stream"); -+ -+ appsrc = gst_element_factory_make("appsrc", NULL); -+ -+ info->appsrc = (GstAppSrc *)appsrc; -+ -+ gst_app_src_set_caps (info->appsrc, caps); -+ gst_app_src_set_callbacks (info->appsrc, -+ &callbacks, info, (GDestroyNotify) appsrc_destroyed); -+ g_signal_connect (media, "candidate-pair-established", -+ (GCallback) media_established_cb, info); -+ gst_caps_unref (caps); -+ } -+ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return appsrc; -+} -+ -+static void -+appsink_eos (GstAppSink *appsink, gpointer user_data) -+{ -+} -+ -+static GstFlowReturn -+appsink_new_preroll (GstAppSink *appsink, gpointer user_data) -+{ -+ return GST_FLOW_OK; -+} -+ -+static gboolean -+appsink_readable (gpointer user_data) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ PurpleMediaAppDataInfo *info = user_data; -+ void (*readable_cb) (PurpleMediaManager *manager, PurpleMedia *media, -+ const gchar *session_id, const gchar *participant, gpointer user_data); -+ PurpleMedia *media; -+ gchar *session_id; -+ gchar *participant; -+ gpointer cb_data; -+ guint *timer_id_ptr = &info->readable_timer_id; -+ guint timer_id = *timer_id_ptr; -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ if (timer_id == 0 || timer_id != *timer_id_ptr) { -+ /* Avoided a race condition (see writable callback) */ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return FALSE; -+ } -+ /* We need to signal readable until there are no more samples */ -+ while (info->callbacks.readable && -+ (info->num_samples > 0 || info->current_sample != NULL)) { -+ readable_cb = info->callbacks.readable; -+ media = g_weak_ref_get (&info->media_ref); -+ session_id = g_strdup (info->session_id); -+ participant = g_strdup (info->participant); -+ cb_data = info->user_data; -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ -+ if (readable_cb) -+ readable_cb (manager, media, session_id, participant, cb_data); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ g_object_unref (media); -+ g_free (session_id); -+ g_free (participant); -+ if (timer_id == 0 || timer_id != *timer_id_ptr) { -+ /* We got cancelled */ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return FALSE; -+ } -+ } -+ info->readable_timer_id = 0; -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return FALSE; -+} -+ -+static void -+call_appsink_readable_locked (PurpleMediaAppDataInfo *info) -+{ -+ /* We must signal that a new sample has arrived to release blocking reads */ -+ g_cond_broadcast (&info->readable_cond); -+ -+ /* We already have a writable callback scheduled, don't create another one */ -+ if (info->readable_timer_id || info->callbacks.readable == NULL) -+ return; -+ -+ info->readable_timer_id = purple_timeout_add (0, appsink_readable, info); -+} -+ -+static GstFlowReturn -+appsink_new_sample (GstAppSink *appsink, gpointer user_data) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ PurpleMediaAppDataInfo *info = user_data; -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ info->num_samples++; -+ call_appsink_readable_locked (info); -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ -+ return GST_FLOW_OK; -+} -+ -+static void -+appsink_destroyed (PurpleMediaAppDataInfo *info) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ -+ g_mutex_lock (&manager->priv->appdata_mutex); -+ info->appsink = NULL; -+ info->num_samples = 0; -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+} -+ -+static GstElement * -+create_recv_appsink(PurpleMedia *media, -+ const gchar *session_id, const gchar *participant) -+{ -+ PurpleMediaManager *manager = purple_media_manager_get (); -+ PurpleMediaAppDataInfo * info = ensure_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ GstElement *appsink = (GstElement *)info->appsink; -+ -+ if (appsink == NULL) { -+ GstAppSinkCallbacks callbacks = {appsink_eos, appsink_new_preroll, -+ appsink_new_sample, {NULL}}; -+ GstCaps *caps = gst_caps_new_empty_simple ("application/octet-stream"); -+ -+ appsink = gst_element_factory_make("appsink", NULL); -+ -+ info->appsink = (GstAppSink *)appsink; -+ -+ gst_app_sink_set_caps (info->appsink, caps); -+ gst_app_sink_set_callbacks (info->appsink, -+ &callbacks, info, (GDestroyNotify) appsink_destroyed); -+ gst_caps_unref (caps); -+ -+ } -+ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return appsink; -+} -+#endif -+ -+static PurpleMediaElementInfo * -+get_send_application_element_info () -+{ -+ static PurpleMediaElementInfo *info = NULL; -+ -+#ifdef HAVE_MEDIA_APPLICATION -+ if (info == NULL) { -+ info = g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO, -+ "id", "pidginappsrc", -+ "name", "Pidgin Application Source", -+ "type", PURPLE_MEDIA_ELEMENT_APPLICATION -+ | PURPLE_MEDIA_ELEMENT_SRC -+ | PURPLE_MEDIA_ELEMENT_ONE_SRC, -+ "create-cb", create_send_appsrc, NULL); -+ } -+#endif -+ -+ return info; -+} -+ -+ -+static PurpleMediaElementInfo * -+get_recv_application_element_info () -+{ -+ static PurpleMediaElementInfo *info = NULL; -+ -+#ifdef HAVE_MEDIA_APPLICATION -+ if (info == NULL) { -+ info = g_object_new(PURPLE_TYPE_MEDIA_ELEMENT_INFO, -+ "id", "pidginappsink", -+ "name", "Pidgin Application Sink", -+ "type", PURPLE_MEDIA_ELEMENT_APPLICATION -+ | PURPLE_MEDIA_ELEMENT_SINK -+ | PURPLE_MEDIA_ELEMENT_ONE_SINK, -+ "create-cb", create_recv_appsink, NULL); -+ } -+#endif -+ -+ return info; -+} -+ - GstElement * - purple_media_manager_get_element(PurpleMediaManager *manager, - PurpleMediaSessionType type, PurpleMedia *media, -@@ -595,6 +1084,10 @@ purple_media_manager_get_element(PurpleM - info = manager->priv->video_src; - else if (type & PURPLE_MEDIA_RECV_VIDEO) - info = manager->priv->video_sink; -+ else if (type & PURPLE_MEDIA_SEND_APPLICATION) -+ info = get_send_application_element_info (); -+ else if (type & PURPLE_MEDIA_RECV_APPLICATION) -+ info = get_recv_application_element_info (); - - if (info == NULL) - return NULL; -@@ -834,11 +1327,16 @@ purple_media_manager_get_active_element( - return manager->priv->audio_src; - else if (type & PURPLE_MEDIA_ELEMENT_VIDEO) - return manager->priv->video_src; -+ else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION) -+ return get_send_application_element_info (); - } else if (type & PURPLE_MEDIA_ELEMENT_SINK) { - if (type & PURPLE_MEDIA_ELEMENT_AUDIO) - return manager->priv->audio_sink; - else if (type & PURPLE_MEDIA_ELEMENT_VIDEO) - return manager->priv->video_sink; -+ else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION) -+ return get_recv_application_element_info (); -+ - } - #endif - -@@ -1138,6 +1636,174 @@ purple_media_manager_get_backend_type(Pu - #endif - } - -+void -+purple_media_manager_set_application_data_callbacks(PurpleMediaManager *manager, -+ PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, PurpleMediaAppDataCallbacks *callbacks, -+ gpointer user_data, GDestroyNotify notify) -+{ -+#ifdef HAVE_MEDIA_APPLICATION -+ PurpleMediaAppDataInfo * info = ensure_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ -+ if (info->notify) -+ info->notify (info->user_data); -+ -+ if (info->readable_timer_id) { -+ purple_timeout_remove (info->readable_timer_id); -+ info->readable_timer_id = 0; -+ } -+ -+ if (info->writable_timer_id) { -+ purple_timeout_remove (info->writable_timer_id); -+ info->writable_timer_id = 0; -+ } -+ -+ if (callbacks) { -+ info->callbacks = *callbacks; -+ } else { -+ info->callbacks.writable = NULL; -+ info->callbacks.readable = NULL; -+ } -+ info->user_data = user_data; -+ info->notify = notify; -+ -+ call_appsrc_writable_locked (info); -+ if (info->num_samples > 0 || info->current_sample != NULL) -+ call_appsink_readable_locked (info); -+ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+#endif -+} -+ -+gint -+purple_media_manager_send_application_data ( -+ PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, gpointer buffer, guint size, gboolean blocking) -+{ -+#ifdef HAVE_MEDIA_APPLICATION -+ PurpleMediaAppDataInfo * info = get_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ -+ if (info && info->appsrc && info->connected) { -+ GstBuffer *gstbuffer = gst_buffer_new_wrapped (g_memdup (buffer, size), -+ size); -+ GstAppSrc *appsrc = gst_object_ref (info->appsrc); -+ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ if (gst_app_src_push_buffer (appsrc, gstbuffer) == GST_FLOW_OK) { -+ if (blocking) { -+ GstPad *srcpad; -+ -+ srcpad = gst_element_get_static_pad (GST_ELEMENT (appsrc), -+ "src"); -+ if (srcpad) { -+ gst_pad_peer_query (srcpad, gst_query_new_drain ()); -+ gst_object_unref (srcpad); -+ } -+ } -+ gst_object_unref (appsrc); -+ return size; -+ } else { -+ gst_object_unref (appsrc); -+ return -1; -+ } -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return -1; -+#else -+ return -1; -+#endif -+} -+ -+gint -+purple_media_manager_receive_application_data ( -+ PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, gpointer buffer, guint max_size, -+ gboolean blocking) -+{ -+#ifdef HAVE_MEDIA_APPLICATION -+ PurpleMediaAppDataInfo * info = get_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ guint bytes_read = 0; -+ -+ if (info) { -+ /* If we are in a blocking read, we need to loop until max_size data -+ * is read into the buffer, if we're not, then we need to read as much -+ * data as possible -+ */ -+ do { -+ if (!info->current_sample && info->appsink && info->num_samples > 0) { -+ info->current_sample = gst_app_sink_pull_sample (info->appsink); -+ info->sample_offset = 0; -+ if (info->current_sample) -+ info->num_samples--; -+ } -+ -+ if (info->current_sample) { -+ GstBuffer *gstbuffer = gst_sample_get_buffer ( -+ info->current_sample); -+ -+ if (gstbuffer) { -+ GstMapInfo mapinfo; -+ guint bytes_to_copy; -+ -+ gst_buffer_map (gstbuffer, &mapinfo, GST_MAP_READ); -+ /* We must copy only the data remaining in the buffer without -+ * overflowing the buffer */ -+ bytes_to_copy = max_size - bytes_read; -+ if (bytes_to_copy > mapinfo.size - info->sample_offset) -+ bytes_to_copy = mapinfo.size - info->sample_offset; -+ memcpy ((guint8 *)buffer + bytes_read, -+ mapinfo.data + info->sample_offset, bytes_to_copy); -+ -+ gst_buffer_unmap (gstbuffer, &mapinfo); -+ info->sample_offset += bytes_to_copy; -+ bytes_read += bytes_to_copy; -+ if (info->sample_offset == mapinfo.size) { -+ gst_sample_unref (info->current_sample); -+ info->current_sample = NULL; -+ info->sample_offset = 0; -+ } -+ } else { -+ /* In case there's no buffer in the sample (should never -+ * happen), we need to at least unref it */ -+ gst_sample_unref (info->current_sample); -+ info->current_sample = NULL; -+ info->sample_offset = 0; -+ } -+ } -+ -+ /* If blocking, wait until there's an available sample */ -+ while (bytes_read < max_size && blocking && -+ info->current_sample == NULL && info->num_samples == 0) { -+ g_cond_wait (&info->readable_cond, &manager->priv->appdata_mutex); -+ -+ /* We've been signaled, we need to unlock and regrab the info -+ * struct to make sure nothing changed */ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ info = get_app_data_info_and_lock (manager, -+ media, session_id, participant); -+ if (info == NULL || info->appsink == NULL) { -+ /* The session was destroyed while we were waiting, we -+ * should return here */ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return bytes_read; -+ } -+ } -+ } while (bytes_read < max_size && -+ (blocking || info->num_samples > 0)); -+ -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return bytes_read; -+ } -+ g_mutex_unlock (&manager->priv->appdata_mutex); -+ return -1; -+#else -+ return -1; -+#endif -+} -+ - #ifdef USE_GSTREAMER - - /* -@@ -1185,6 +1851,8 @@ purple_media_element_type_get_type() - "PURPLE_MEDIA_ELEMENT_SRC", "src" }, - { PURPLE_MEDIA_ELEMENT_SINK, - "PURPLE_MEDIA_ELEMENT_SINK", "sink" }, -+ { PURPLE_MEDIA_ELEMENT_APPLICATION, -+ "PURPLE_MEDIA_ELEMENT_APPLICATION", "application" }, - { 0, NULL, NULL } - }; - type = g_flags_register_static( -@@ -1410,5 +2078,6 @@ purple_media_element_info_call_create(Pu - return NULL; - } - -+ - #endif /* USE_GSTREAMER */ - -Index: pidgin-2.10.11/libpurple/mediamanager.h -=================================================================== ---- pidgin-2.10.11.orig/libpurple/mediamanager.h -+++ pidgin-2.10.11/libpurple/mediamanager.h -@@ -38,6 +38,30 @@ typedef struct _PurpleMediaManagerClass - #include "account.h" - #include "media.h" - -+/** -+ * PurpleMediaAppDataCallbacks: -+ * @readable: Called when the stream has received data and is readable. -+ * @writable: Called when the stream has become writable or has stopped being -+ * writable. -+ * -+ * A set of callbacks that can be installed on an Application data session with -+ * purple_media_manager_set_application_data_callbacks() -+ * -+ * Once installed the @readable callback will get called as long as data is -+ * available to read, so the data must be read completely. -+ * The @writable callback will only be called when the writable state of the -+ * stream changes. The @writable argument defines whether the stream has -+ * become writable or stopped being writable. -+ * -+ */ -+typedef struct { -+ void (*readable) (PurpleMediaManager *manager, PurpleMedia *media, -+ const gchar *session_id, const gchar *participant, gpointer user_data); -+ void (*writable) (PurpleMediaManager *manager, PurpleMedia *media, -+ const gchar *session_id, const gchar *participant, gboolean writable, -+ gpointer user_data); -+} PurpleMediaAppDataCallbacks; -+ - G_BEGIN_DECLS - - #define PURPLE_TYPE_MEDIA_MANAGER (purple_media_manager_get_type()) -@@ -285,6 +309,71 @@ void purple_media_manager_set_backend_ty - */ - GType purple_media_manager_get_backend_type(PurpleMediaManager *manager); - -+/** -+ * purple_media_manager_set_application_data_callbacks: -+ * @manager: The manager to register the callbacks with. -+ * @media: The media instance to register the callbacks with. -+ * @session_id: The session to register the callbacks with. -+ * @participant: The participant to register the callbacks with. -+ * @callbacks: The callbacks to be set on the session. -+ * @user_data: a user_data argument for the callbacks. -+ * @notify: a destroy notify function. -+ * -+ * Set callbacks on a session to be called when the stream becomes writable -+ * or readable for media sessions of type #PURPLE_MEDIA_APPLICATION -+ */ -+void purple_media_manager_set_application_data_callbacks( -+ PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, PurpleMediaAppDataCallbacks *callbacks, -+ gpointer user_data, GDestroyNotify notify); -+ -+/** -+ * purple_media_manager_send_application_data: -+ * @manager: The manager to send data with. -+ * @media: The media instance to which the session belongs. -+ * @session_id: The session to send data to. -+ * @participant: The participant to send data to. -+ * @buffer: The buffer of data to send. -+ * @size: The size of @buffer -+ * @blocking: Whether to block until the data was send or not. -+ * -+ * Sends a buffer of data to a #PURPLE_MEDIA_APPLICATION session. -+ * If @blocking is set, unless an error occured, the function will not return -+ * until the data has been flushed into the network. -+ * If the stream is not writable, the data will be queued. It is the -+ * responsability of the user to stop sending data when the stream isn't -+ * writable anymore. It is also the responsability of the user to only start -+ * sending data after the stream has been configured correctly (encryption -+ * parameters for example). -+ * -+ * Returns: Number of bytes sent or -1 in case of error. -+ */ -+gint purple_media_manager_send_application_data ( -+ PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, gpointer buffer, guint size, gboolean blocking); -+ -+/** -+ * purple_media_manager_receive_application_data: -+ * @manager: The manager to receive data with. -+ * @media: The media instance to which the session belongs. -+ * @session_id: The session to receive data from. -+ * @participant: The participant to receive data from. -+ * @buffer: The buffer to receive data into. -+ * @max_size: The max_size of @buffer -+ * @blocking: Whether to block until the buffer is entirely filled or return -+ * with currently available data. -+ * -+ * Receive a buffer of data from a #PURPLE_MEDIA_APPLICATION session. -+ * If @blocking is set, unless an error occured, the function will not return -+ * until @max_size bytes are read. -+ * -+ * Returns: Number of bytes received or -1 in case of error. -+ */ -+gint purple_media_manager_receive_application_data ( -+ PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, -+ const gchar *participant, gpointer buffer, guint max_size, -+ gboolean blocking); -+ - /*}@*/ - - #ifdef __cplusplus diff --git a/pidgin-2.10.11-fix-sound-play-fd-leak.patch b/pidgin-2.10.11-fix-sound-play-fd-leak.patch deleted file mode 100644 index 3f19c1a..0000000 --- a/pidgin-2.10.11-fix-sound-play-fd-leak.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/finch/gntsound.c -+++ b/finch/gntsound.c -@@ -449,6 +449,7 @@ bus_call (GstBus *bus, GstMessage *msg, - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); -+ return FALSE; - break; - case GST_MESSAGE_WARNING: - gst_message_parse_warning(msg, &err, NULL); ---- a/libpurple/mediamanager.c -+++ b/libpurple/mediamanager.c -@@ -288,6 +288,7 @@ pipeline_bus_call(GstBus *bus, GstMessag - switch(GST_MESSAGE_TYPE(msg)) { - case GST_MESSAGE_EOS: - purple_debug_info("mediamanager", "End of Stream\n"); -+ return FALSE; - break; - case GST_MESSAGE_ERROR: { - gchar *debug = NULL; -@@ -305,6 +306,7 @@ - "Debug details: %s\n", debug); - g_free (debug); - } -+ return FALSE; - break; - } - default: ---- a/pidgin/gtksound.c -+++ b/pidgin/gtksound.c -@@ -394,6 +394,7 @@ bus_call (GstBus *bus, - case GST_MESSAGE_EOS: - gst_element_set_state(play, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(play)); -+ return FALSE; - break; - case GST_MESSAGE_WARNING: - gst_message_parse_warning(msg, &err, NULL); diff --git a/pidgin-2.10.11-gst-references.patch b/pidgin-2.10.11-gst-references.patch deleted file mode 100644 index 94df8cd..0000000 --- a/pidgin-2.10.11-gst-references.patch +++ /dev/null @@ -1,44 +0,0 @@ - -# HG changeset patch -# User Youness Alaoui -# Date 1404874798 14400 -# Node ID b52be4fef1ded825e262095480915f2c675a5694 -# Parent 2b41ba1fde8a80a4f2d715874a0b02449d4b66ad -Fix gstreamer elements references -In backend-fs2, the create_src will unref the src after it's done with -it, if we simply return the created source, it will segfault. -The issue never happened before because every source so far also has -the UNIQUE flag, which causes it to go in a different branch of the -code which does ref the element and add it to the bin. - -Refs #16315 - -diff --git a/libpurple/mediamanager.c b/libpurple/mediamanager.c ---- a/libpurple/mediamanager.c -+++ b/libpurple/mediamanager.c -@@ -443,7 +443,11 @@ - - if (src) { - GstElement *capsfilter = gst_bin_get_by_name(GST_BIN(src), "prpl_video_caps"); -- g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL); -+ if (capsfilter) { -+ g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL); -+ gst_object_unref (capsfilter); -+ } -+ gst_object_unref (src); - } - - g_free(id); -@@ -550,6 +554,11 @@ - } else { - ret = purple_media_element_info_call_create(info, - media, session_id, participant); -+ if (element_type & PURPLE_MEDIA_ELEMENT_SRC) { -+ gst_object_ref(ret); -+ gst_bin_add(GST_BIN(purple_media_manager_get_pipeline(manager)), -+ ret); -+ } - } - - if (ret == NULL) - diff --git a/pidgin-2.10.11-init-media-optional.patch b/pidgin-2.10.11-init-media-optional.patch deleted file mode 100644 index 9f62ad8..0000000 --- a/pidgin-2.10.11-init-media-optional.patch +++ /dev/null @@ -1,52 +0,0 @@ - -# HG changeset patch -# User Jakub Adam -# Date 1407847148 -7200 -# Node ID 7767aaeade6404396204794f9bc75d9a2cb723f0 -# Parent 8e4fa54f166211ffd6cd869cca611e8d64ea1fdf -media: make "init-media" signal handler optional - -Change the logic so that the PurpleMedia instance isn't disposed when -"init-media" has no connected handlers. - -We want the media object freed only when some signal callback function -explicitly returns FALSE, indicating an error during the initialization. - -This is mostly useful for the imminent addition of private media streams. - -diff --git a/libpurple/mediamanager.c b/libpurple/mediamanager.c ---- a/libpurple/mediamanager.c -+++ b/libpurple/mediamanager.c -@@ -334,7 +334,7 @@ - { - #ifdef USE_VV - PurpleMedia *media; -- gboolean signal_ret; -+ guint signal_id; - - media = PURPLE_MEDIA(g_object_new(purple_media_get_type(), - "manager", manager, -@@ -343,12 +343,17 @@ - "initiator", initiator, - NULL)); - -- g_signal_emit(manager, purple_media_manager_signals[INIT_MEDIA], 0, -- media, account, remote_user, &signal_ret); -+ signal_id = purple_media_manager_signals[INIT_MEDIA]; - -- if (signal_ret == FALSE) { -- g_object_unref(media); -- return NULL; -+ if (g_signal_has_handler_pending(manager, signal_id, 0, FALSE)) { -+ gboolean signal_ret; -+ -+ g_signal_emit(manager, signal_id, 0, media, account, remote_user, -+ &signal_ret); -+ if (signal_ret == FALSE) { -+ g_object_unref(media); -+ return NULL; -+ } - } - - manager->priv->medias = g_list_append(manager->priv->medias, media); - diff --git a/pidgin-2.10.11-private-media.patch b/pidgin-2.10.11-private-media.patch deleted file mode 100644 index 8b9e961..0000000 --- a/pidgin-2.10.11-private-media.patch +++ /dev/null @@ -1,290 +0,0 @@ - -# HG changeset patch -# User Youness Alaoui -# Date 1404764862 14400 -# Node ID d729a9b2126594df3e38647e926ac7c0a7db807b -# Parent 7767aaeade6404396204794f9bc75d9a2cb723f0 -Add Private media API - -Creating a private media can be useful for plugins that want to create a -PurpleMedia for internal use without the front-end being notified of its -creation. - -diff --git a/libpurple/mediamanager.c b/libpurple/mediamanager.c ---- a/libpurple/mediamanager.c -+++ b/libpurple/mediamanager.c -@@ -86,6 +86,7 @@ - GstElement *pipeline; - PurpleMediaCaps ui_caps; - GList *medias; -+ GList *private_medias; - GList *elements; - GList *output_windows; - gulong next_output_window_id; -@@ -111,6 +112,7 @@ - - enum { - INIT_MEDIA, -+ INIT_PRIVATE_MEDIA, - UI_CAPS_CHANGED, - LAST_SIGNAL - }; -@@ -161,6 +163,15 @@ - G_TYPE_BOOLEAN, 3, PURPLE_TYPE_MEDIA, - G_TYPE_POINTER, G_TYPE_STRING); - -+ purple_media_manager_signals[INIT_PRIVATE_MEDIA] = -+ g_signal_new ("init-private-media", -+ G_TYPE_FROM_CLASS (klass), -+ G_SIGNAL_RUN_LAST, -+ 0, NULL, NULL, -+ purple_smarshal_BOOLEAN__OBJECT_POINTER_STRING, -+ G_TYPE_BOOLEAN, 3, PURPLE_TYPE_MEDIA, -+ G_TYPE_POINTER, G_TYPE_STRING); -+ - purple_media_manager_signals[UI_CAPS_CHANGED] = g_signal_new ("ui-caps-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, -@@ -177,6 +188,7 @@ - { - media->priv = PURPLE_MEDIA_MANAGER_GET_PRIVATE(media); - media->priv->medias = NULL; -+ media->priv->private_medias = NULL; - media->priv->next_output_window_id = 1; - #ifdef USE_VV - media->priv->backend_type = PURPLE_TYPE_MEDIA_BACKEND_FS2; -@@ -198,6 +210,10 @@ - g_list_delete_link(priv->medias, priv->medias)) { - g_object_unref(priv->medias->data); - } -+ for (; priv->private_medias; priv->private_medias = -+ g_list_delete_link(priv->private_medias, priv->private_medias)) { -+ g_object_unref(priv->private_medias->data); -+ } - for (; priv->elements; priv->elements = - g_list_delete_link(priv->elements, priv->elements)) { - g_object_unref(priv->elements->data); -@@ -325,12 +341,13 @@ - } - #endif /* USE_GSTREAMER */ - --PurpleMedia * --purple_media_manager_create_media(PurpleMediaManager *manager, -- PurpleAccount *account, -- const char *conference_type, -- const char *remote_user, -- gboolean initiator) -+static PurpleMedia * -+create_media(PurpleMediaManager *manager, -+ PurpleAccount *account, -+ const char *conference_type, -+ const char *remote_user, -+ gboolean initiator, -+ gboolean private) - { - #ifdef USE_VV - PurpleMedia *media; -@@ -343,7 +360,9 @@ - "initiator", initiator, - NULL)); - -- signal_id = purple_media_manager_signals[INIT_MEDIA]; -+ signal_id = private ? -+ purple_media_manager_signals[INIT_PRIVATE_MEDIA] : -+ purple_media_manager_signals[INIT_MEDIA]; - - if (g_signal_has_handler_pending(manager, signal_id, 0, FALSE)) { - gboolean signal_ret; -@@ -356,26 +375,33 @@ - } - } - -- manager->priv->medias = g_list_append(manager->priv->medias, media); -+ if (private) -+ manager->priv->private_medias = g_list_append( -+ manager->priv->private_medias, media); -+ else -+ manager->priv->medias = g_list_append(manager->priv->medias, media); - return media; - #else - return NULL; - #endif - } - --GList * --purple_media_manager_get_media(PurpleMediaManager *manager) -+static GList * -+get_media(PurpleMediaManager *manager, gboolean private) - { - #ifdef USE_VV -- return manager->priv->medias; -+ if (private) -+ return manager->priv->private_medias; -+ else -+ return manager->priv->medias; - #else - return NULL; - #endif - } - --GList * --purple_media_manager_get_media_by_account(PurpleMediaManager *manager, -- PurpleAccount *account) -+static GList * -+get_media_by_account(PurpleMediaManager *manager, -+ PurpleAccount *account, gboolean private) - { - #ifdef USE_VV - GList *media = NULL; -@@ -383,7 +409,10 @@ - - g_return_val_if_fail(PURPLE_IS_MEDIA_MANAGER(manager), NULL); - -- iter = manager->priv->medias; -+ if (private) -+ iter = manager->priv->private_medias; -+ else -+ iter = manager->priv->medias; - for (; iter; iter = g_list_next(iter)) { - if (purple_media_get_account(iter->data) == account) { - media = g_list_prepend(media, iter->data); -@@ -397,21 +426,73 @@ - } - - void --purple_media_manager_remove_media(PurpleMediaManager *manager, -- PurpleMedia *media) -+purple_media_manager_remove_media(PurpleMediaManager *manager, PurpleMedia *media) - { - #ifdef USE_VV - GList *list; -+ GList **medias; - - g_return_if_fail(manager != NULL); - -- list = g_list_find(manager->priv->medias, media); -+ if ((list = g_list_find(manager->priv->medias, media))) { -+ medias = &manager->priv->medias; -+ } else if ((list = g_list_find(manager->priv->private_medias, media))) { -+ medias = &manager->priv->private_medias; -+ } -+ - if (list) -- manager->priv->medias = -- g_list_delete_link(manager->priv->medias, list); -+ *medias = g_list_delete_link(*medias, list); - #endif - } - -+PurpleMedia * -+purple_media_manager_create_media(PurpleMediaManager *manager, -+ PurpleAccount *account, -+ const char *conference_type, -+ const char *remote_user, -+ gboolean initiator) -+{ -+ return create_media (manager, account, conference_type, -+ remote_user, initiator, FALSE); -+} -+ -+GList * -+purple_media_manager_get_media(PurpleMediaManager *manager) -+{ -+ return get_media (manager, FALSE); -+} -+ -+GList * -+purple_media_manager_get_media_by_account(PurpleMediaManager *manager, -+ PurpleAccount *account) -+{ -+ return get_media_by_account (manager, account, FALSE); -+} -+ -+PurpleMedia * -+purple_media_manager_create_private_media(PurpleMediaManager *manager, -+ PurpleAccount *account, -+ const char *conference_type, -+ const char *remote_user, -+ gboolean initiator) -+{ -+ return create_media (manager, account, conference_type, -+ remote_user, initiator, TRUE); -+} -+ -+GList * -+purple_media_manager_get_private_media(PurpleMediaManager *manager) -+{ -+ return get_media (manager, TRUE); -+} -+ -+GList * -+purple_media_manager_get_private_media_by_account(PurpleMediaManager *manager, -+ PurpleAccount *account) -+{ -+ return get_media_by_account (manager, account, TRUE); -+} -+ - #ifdef USE_VV - static void - request_pad_unlinked_cb(GstPad *pad, GstPad *peer, gpointer user_data) -diff --git a/libpurple/mediamanager.h b/libpurple/mediamanager.h ---- a/libpurple/mediamanager.h -+++ b/libpurple/mediamanager.h -@@ -130,6 +130,56 @@ - PurpleMedia *media); - - /** -+ * Creates a private media session. A private media session is a -+ * media session which is private to the caller. It is meant to be -+ * used by plugins to create a media session that the front-end does -+ * not get notified about. It is useful especially for sessions with a -+ * type of PURPLE_MEDIA_APPLICATION which the front-end wouldn't know -+ * how to handle. -+ * -+ * @param manager The media manager to create the session under. -+ * @param account The account to create the session on. -+ * @param conference_type The conference type to feed into Farsight2. -+ * @param remote_user The remote user to initiate the session with. -+ * @param initiator TRUE if the local user is the initiator of this media -+ * call, FALSE otherwise. -+ * -+ * @return A newly created media session. -+ * -+ * @since 2.11.0 -+ */ -+PurpleMedia *purple_media_manager_create_private_media( -+ PurpleMediaManager *manager, -+ PurpleAccount *account, -+ const char *conference_type, -+ const char *remote_user, -+ gboolean initiator); -+ -+/** -+ * Gets all of the private media sessions. -+ * -+ * @param manager The media manager to get all of the sessions from. -+ * -+ * @return A list of all the private media sessions. -+ * -+ * @since 2.11.0 -+ */ -+GList *purple_media_manager_get_private_media(PurpleMediaManager *manager); -+ -+/** -+ * Gets all of the private media sessions for a given account. -+ * -+ * @param manager The media manager to get the sessions from. -+ * @param account The account the sessions are on. -+ * -+ * @return A list of the private media sessions on the given account. -+ * -+ * @since 2.11.0 -+ */ -+GList *purple_media_manager_get_private_media_by_account( -+ PurpleMediaManager *manager, PurpleAccount *account); -+ -+/** - * Signals that output windows should be created for the chosen stream. - * - * This shouldn't be called outside of mediamanager.c and media.c - diff --git a/pidgin-2.10.11-send-video-enum.patch b/pidgin-2.10.11-send-video-enum.patch deleted file mode 100644 index 41803ec..0000000 --- a/pidgin-2.10.11-send-video-enum.patch +++ /dev/null @@ -1,23 +0,0 @@ - -# HG changeset patch -# User Youness Alaoui -# Date 1404159462 14400 -# Node ID 2b41ba1fde8a80a4f2d715874a0b02449d4b66ad -# Parent f02f7d1fb4d545c6d7353745094e1afcf0428ca9 -Fix send-video enum typo - -Refs #16315 - -diff --git a/libpurple/media/enum-types.c b/libpurple/media/enum-types.c ---- a/libpurple/media/enum-types.c -+++ b/libpurple/media/enum-types.c -@@ -175,7 +175,7 @@ - { PURPLE_MEDIA_RECV_VIDEO, - "PURPLE_MEDIA_RECV_VIDEO", "recv-video" }, - { PURPLE_MEDIA_SEND_VIDEO, -- "PURPLE_MEDIA_SEND_VIDEO", "send-audio" }, -+ "PURPLE_MEDIA_SEND_VIDEO", "send-video" }, - { PURPLE_MEDIA_AUDIO, - "PURPLE_MEDIA_AUDIO", "audio" }, - { PURPLE_MEDIA_VIDEO, - diff --git a/pidgin-2.10.11.tar.gz b/pidgin-2.10.11.tar.gz deleted file mode 100644 index bfd9e98..0000000 --- a/pidgin-2.10.11.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:69dcfeead545d1ff2262c33285ad8d231429763d10aee50c38601999b762e828 -size 13568253 diff --git a/pidgin-2.10.12.tar.bz2 b/pidgin-2.10.12.tar.bz2 new file mode 100644 index 0000000..663e65d --- /dev/null +++ b/pidgin-2.10.12.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c7523f0fefe89749c03b2b738ab9f7bd186da435be4762f1487eee31e77ffdd +size 9837598 diff --git a/pidgin-2.10.12.tar.bz2.asc b/pidgin-2.10.12.tar.bz2.asc new file mode 100644 index 0000000..20d280d --- /dev/null +++ b/pidgin-2.10.12.tar.bz2.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1 + +iEYEABECAAYFAlaFud4ACgkQdf4lmqisgDLznQCfWyI2lo7UotafQcwb+7HGbWdV +3UAAnRgqfjZ2NRtjMPDaVgJiC31Dyvwx +=raka +-----END PGP SIGNATURE----- diff --git a/pidgin-gnome-keyring.patch b/pidgin-gnome-keyring.patch index 835e318..7dbf60b 100644 --- a/pidgin-gnome-keyring.patch +++ b/pidgin-gnome-keyring.patch @@ -1,7 +1,7 @@ -diff -Naur pidgin-2.10.10.orig/configure.ac pidgin-2.10.10/configure.ac ---- pidgin-2.10.10.orig/configure.ac -+++ pidgin-2.10.10/configure.ac -@@ -2124,6 +2124,20 @@ +diff -Naur pidgin-2.10.12.orig/configure.ac pidgin-2.10.12/configure.ac +--- pidgin-2.10.12.orig/configure.ac ++++ pidgin-2.10.12/configure.ac +@@ -2222,6 +2222,20 @@ fi dnl ####################################################################### @@ -22,9 +22,9 @@ diff -Naur pidgin-2.10.10.orig/configure.ac pidgin-2.10.10/configure.ac dnl # Check for Tcl dnl ####################################################################### AC_ARG_ENABLE(tcl, [AC_HELP_STRING([--disable-tcl], -diff -Naur pidgin-2.10.10.orig/libpurple/account.c pidgin-2.10.10/libpurple/account.c ---- pidgin-2.10.10.orig/libpurple/account.c -+++ pidgin-2.10.10/libpurple/account.c +diff -Naur pidgin-2.10.12.orig/libpurple/account.c pidgin-2.10.12/libpurple/account.c +--- pidgin-2.10.12.orig/libpurple/account.c ++++ pidgin-2.10.12/libpurple/account.c @@ -54,6 +54,13 @@ #define PURPLE_ACCOUNT_GET_PRIVATE(account) \ ((PurpleAccountPrivate *) (account->priv)) @@ -132,7 +132,7 @@ diff -Naur pidgin-2.10.10.orig/libpurple/account.c pidgin-2.10.10/libpurple/acco /* Read the alias */ child = xmlnode_get_child(node, "alias"); -@@ -3305,6 +3331,63 @@ +@@ -3306,6 +3332,63 @@ purple_signals_unregister_by_instance(handle); } @@ -196,10 +196,10 @@ diff -Naur pidgin-2.10.10.orig/libpurple/account.c pidgin-2.10.10/libpurple/acco /* libpurple 3.0.0 compatibility */ static void -diff -Naur pidgin-2.10.10.orig/libpurple/Makefile.am pidgin-2.10.10/libpurple/Makefile.am ---- pidgin-2.10.10.orig/libpurple/Makefile.am -+++ pidgin-2.10.10/libpurple/Makefile.am -@@ -305,6 +305,7 @@ +diff -Naur pidgin-2.10.12.orig/libpurple/Makefile.am pidgin-2.10.12/libpurple/Makefile.am +--- pidgin-2.10.12.orig/libpurple/Makefile.am ++++ pidgin-2.10.12/libpurple/Makefile.am +@@ -309,6 +309,7 @@ $(GLIB_LIBS) \ $(LIBXML_LIBS) \ $(NETWORKMANAGER_LIBS) \ @@ -207,8 +207,8 @@ diff -Naur pidgin-2.10.10.orig/libpurple/Makefile.am pidgin-2.10.10/libpurple/Ma $(INTLLIBS) \ $(FARSTREAM_LIBS) \ $(GSTREAMER_LIBS) \ -@@ -326,7 +327,8 @@ - $(GSTREAMER_CFLAGS) \ +@@ -334,7 +335,8 @@ + $(GSTAPP_CFLAGS) \ $(GSTINTERFACES_CFLAGS) \ $(IDN_CFLAGS) \ - $(NETWORKMANAGER_CFLAGS) diff --git a/pidgin-port-to-gst-1.0.patch b/pidgin-port-to-gst-1.0.patch deleted file mode 100644 index 75beec3..0000000 --- a/pidgin-port-to-gst-1.0.patch +++ /dev/null @@ -1,1128 +0,0 @@ - -# HG changeset patch -# User David Woodhouse -# Date 1426073959 0 -# Node ID 2415067473ba10a2090d6130b93204a3b537b05c -# Parent 6b4576edf2a694ab55d0d06d3643c44601a75b15 -Support GStreamer 1.x and resync with trunk - -Index: pidgin-2.10.11/configure.ac -=================================================================== ---- pidgin-2.10.11.orig/configure.ac -+++ pidgin-2.10.11/configure.ac -@@ -741,42 +741,115 @@ AM_GCONF_SOURCE_2 - dnl ####################################################################### - dnl # Check for GStreamer - dnl ####################################################################### --dnl --dnl TODO: Depend on gstreamer >= 0.10.10, and remove the conditional use of --dnl gst_registry_fork_set_enabled. - AC_ARG_ENABLE(gstreamer, -- [AC_HELP_STRING([--disable-gstreamer], [compile without GStreamer audio support])], -+ [AS_HELP_STRING([--disable-gstreamer], [compile without GStreamer audio support])], - enable_gst="$enableval", enable_gst="yes") -+AC_ARG_WITH(gstreamer, [AS_HELP_STRING([--with-gstreamer=], -+ [compile with GStreamer 0.10 or 1.0 interface (default: auto)])], -+ with_gstreamer="$withval", with_gstreamer="auto") - if test "x$enable_gst" != "xno"; then -- PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], [ -- AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds]) -- AC_SUBST(GSTREAMER_CFLAGS) -- AC_SUBST(GSTREAMER_LIBS) -- AC_CHECK_LIB(gstreamer-0.10, gst_registry_fork_set_enabled, -- [ AC_DEFINE(GST_CAN_DISABLE_FORKING, [], -- [Define if gst_registry_fork_set_enabled exists])], -- [], [$GSTREAMER_LIBS]) -- ], [ -- AC_MSG_RESULT(no) -- enable_gst="no" -- if test "x$force_deps" = "xyes" ; then -- AC_MSG_ERROR([ -+ if test "x$with_gstreamer" == "xauto"; then -+ PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0], [ -+ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds]) -+ with_gstreamer="1.0" -+ AC_SUBST(GSTREAMER_CFLAGS) -+ AC_SUBST(GSTREAMER_LIBS) -+ dnl Check whether forking stuff is required for this version. -+ ], [ -+ PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], [ -+ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds]) -+ with_gstreamer="0.10" -+ AC_SUBST(GSTREAMER_CFLAGS) -+ AC_SUBST(GSTREAMER_LIBS) -+ ], [ -+ AC_MSG_RESULT(no) -+ enable_gst="no" -+ if test "x$force_deps" = "xyes" ; then -+ AC_MSG_ERROR([ - GStreamer development headers not found. - Use --disable-gstreamer if you do not need GStreamer (sound) support. - ]) -- fi]) -+ fi -+ ]) -+ ]) -+ elif test "x$with_gstreamer" == "x1.0"; then -+ PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0], [ -+ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer 1.0 for playing sounds]) -+ AC_SUBST(GSTREAMER_CFLAGS) -+ AC_SUBST(GSTREAMER_LIBS) -+ ], [ -+ AC_MSG_RESULT(no) -+ enable_gst="no" -+ if test "x$force_deps" = "xyes" ; then -+ AC_MSG_ERROR([ -+GStreamer development headers not found. -+Use --disable-gstreamer if you do not need GStreamer (sound) support. -+]) -+ fi -+ ]) -+ elif test "x$with_gstreamer" == "x0.10"; then -+ PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], [ -+ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer 0.10 for playing sounds]) -+ AC_SUBST(GSTREAMER_CFLAGS) -+ AC_SUBST(GSTREAMER_LIBS) -+ ], [ -+ AC_MSG_RESULT(no) -+ enable_gst="no" -+ if test "x$force_deps" = "xyes" ; then -+ AC_MSG_ERROR([ -+GStreamer development headers not found. -+Use --disable-gstreamer if you do not need GStreamer (sound) support. -+]) -+ fi -+ ]) -+ else -+ AC_MSG_ERROR([--with-gstreamer must specify one of 0.10, 1.0 or auto.]) -+ fi -+fi -+ -+if test "x$with_gtk" == "x3" -a "x$with_gstreamer" == "x0.10"; then -+ AC_MSG_ERROR([WebKitGTK+ 3.0 cannot be mixed with GStreamer 0.10. -+Please switch to WebKitGTK+ 2.0 or GStreamer 1.0.]) -+elif test "x$with_gtk" == "x2" -a "x$with_gstreamer" == "x1.0"; then -+ AC_MSG_ERROR([WebKitGTK+ 2.0 cannot be mixed with GStreamer 1.0. -+Please switch to WebKitGTK+ 3.0 or GStreamer 0.10.]) -+fi -+if test "x$with_gstreamer" == "x0.10" -o "x$with_gstreamer" == "x1.0"; then -+ AC_SUBST(GSTREAMER_VER, [$with_gstreamer]) -+else -+ AC_SUBST(GSTREAMER_VER, "") -+fi -+ -+dnl ####################################################################### -+dnl # Check for GStreamer Video -+dnl ####################################################################### -+if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x1.0"; then -+ AC_ARG_ENABLE(gstreamer-video, -+ [AS_HELP_STRING([--disable-gstreamer-video], [compile without GStreamer 1.0 Video Overlay support])], -+ enable_gstvideo="$enableval", enable_gstvideo="yes") -+ if test "x$enable_gstvideo" != "xno"; then -+ PKG_CHECK_MODULES(GSTVIDEO, [gstreamer-video-1.0], [ -+ AC_DEFINE(USE_GSTVIDEO, 1, [Use GStreamer Video Overlay support]) -+ AC_SUBST(GSTVIDEO_CFLAGS) -+ AC_SUBST(GSTVIDEO_LIBS) -+ ], [ -+ enable_gstvideo="no" -+ ]) -+ fi -+else -+ enable_gstvideo="no" - fi - - dnl ####################################################################### - dnl # Check for GStreamer Interfaces - dnl ####################################################################### --if test "x$enable_gst" != "xno"; then -+if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x0.10"; then - AC_ARG_ENABLE(gstreamer-interfaces, -- [AC_HELP_STRING([--disable-gstreamer-interfaces], [compile without GStreamer interface support])], -+ [AS_HELP_STRING([--disable-gstreamer-interfaces], [compile without GStreamer 0.10 interface support])], - enable_gstinterfaces="$enableval", enable_gstinterfaces="yes") - if test "x$enable_gstinterfaces" != "xno"; then - PKG_CHECK_MODULES(GSTINTERFACES, [gstreamer-interfaces-0.10], [ -- AC_DEFINE(USE_GSTINTERFACES, 1, [Use GStreamer interfaces for X overlay support]) -+ AC_DEFINE(USE_GSTINTERFACES, 1, [Use GStreamer 0.10 interfaces for X overlay support]) - AC_SUBST(GSTINTERFACES_CFLAGS) - AC_SUBST(GSTINTERFACES_LIBS) - ], [ -@@ -791,32 +864,43 @@ dnl #################################### - dnl # Check for Farstream - dnl ####################################################################### - AC_ARG_ENABLE(farstream, -- [AC_HELP_STRING([--disable-farstream], [compile without farstream support])], -+ [AS_HELP_STRING([--disable-farstream], [compile without farstream support])], - enable_farstream="$enableval", enable_farstream="yes") - if test "x$enable_farstream" != "xno"; then -- PKG_CHECK_MODULES(FARSTREAM, [farstream-0.1], [ -- AC_SUBST(FARSTREAM_CFLAGS) -- AC_SUBST(FARSTREAM_LIBS) -- ], [ -- # Try farsight. -- PKG_CHECK_MODULES(FARSTREAM, [farsight2-0.10 >= 0.0.9], [ -- AC_DEFINE(HAVE_FARSIGHT, 1, [Use Farsight instead of Farstream]) -+ if test "x$with_gstreamer" == "x1.0"; then -+ PKG_CHECK_MODULES(FARSTREAM, [farstream-0.2], [ - AC_SUBST(FARSTREAM_CFLAGS) - AC_SUBST(FARSTREAM_LIBS) - ], [ - enable_farstream="no" - ]) -- ]) -- fi -+ else -+ PKG_CHECK_MODULES(FARSTREAM, [farstream-0.1], [ -+ AC_SUBST(FARSTREAM_CFLAGS) -+ AC_SUBST(FARSTREAM_LIBS) -+ ], [ -+ # Try farsight. -+ PKG_CHECK_MODULES(FARSTREAM, [farsight2-0.10 >= 0.0.9], [ -+ AC_DEFINE(HAVE_FARSIGHT, 1, [Use Farsight instead of Farstream]) -+ AC_SUBST(FARSTREAM_CFLAGS) -+ AC_SUBST(FARSTREAM_LIBS) -+ ], [ -+ enable_farstream="no" -+ ]) -+ ]) -+ fi -+fi - - dnl ####################################################################### - dnl # Check for Voice and Video support - dnl ####################################################################### - AC_ARG_ENABLE(vv, -- [AC_HELP_STRING([--disable-vv], [compile without voice and video support])], -+ [AS_HELP_STRING([--disable-vv], [compile without voice and video support])], - enable_vv="$enableval", enable_vv="yes") - if test "x$enable_vv" != "xno"; then -- if test "x$enable_gstreamer" != "xno" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farstream" != "xno"; then -+ if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x1.0" -a "x$enable_gstvideo" != "xno" -a "x$enable_farstream" != "xno"; then -+ AC_DEFINE(USE_VV, 1, [Use voice and video]) -+ elif test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x0.10" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farstream" != "xno"; then - AC_DEFINE(USE_VV, 1, [Use voice and video]) - else - enable_vv="no" -@@ -829,7 +913,7 @@ Or use --disable-vv if you do not need v - fi - fi - fi --AM_CONDITIONAL(USE_VV, test "x$enable_gstreamer" != "xno" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farstream" != "xno") -+AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno") - - dnl ####################################################################### - dnl # Check for Internationalized Domain Name support -@@ -2619,6 +2703,7 @@ echo Protocols to build dynamically : $D - echo Protocols to link statically.. : $STATIC_PRPLS - echo - echo Build with GStreamer support.. : $enable_gst -+echo Build for GStreamer version... : $with_gstreamer - echo Build with D-Bus support...... : $enable_dbus - echo Build with voice and video.... : $enable_vv - if test "x$enable_dbus" = "xyes" ; then -Index: pidgin-2.10.11/finch/Makefile.am -=================================================================== ---- pidgin-2.10.11.orig/finch/Makefile.am -+++ pidgin-2.10.11/finch/Makefile.am -@@ -73,6 +73,7 @@ finch_LDADD = \ - $(LIBXML_LIBS) \ - $(GNT_LIBS) \ - $(GSTREAMER_LIBS) \ -+ $(GSTVIDEO_LIBS) \ - ./libgnt/libgnt.la \ - $(top_builddir)/libpurple/libpurple.la - -Index: pidgin-2.10.11/libpurple/Makefile.am -=================================================================== ---- pidgin-2.10.11.orig/libpurple/Makefile.am -+++ pidgin-2.10.11/libpurple/Makefile.am -@@ -313,6 +313,7 @@ libpurple_la_LIBADD = \ - $(INTLLIBS) \ - $(FARSTREAM_LIBS) \ - $(GSTREAMER_LIBS) \ -+ $(GSTVIDEO_LIBS) \ - $(GSTINTERFACES_LIBS) \ - $(IDN_LIBS) \ - ciphers/libpurple-ciphers.la \ -@@ -329,6 +330,7 @@ AM_CPPFLAGS = \ - $(LIBXML_CFLAGS) \ - $(FARSTREAM_CFLAGS) \ - $(GSTREAMER_CFLAGS) \ -+ $(GSTVIDEO_CFLAGS) \ - $(GSTINTERFACES_CFLAGS) \ - $(IDN_CFLAGS) \ - $(NETWORKMANAGER_CFLAGS) \ -Index: pidgin-2.10.11/libpurple/data/purple.pc.in -=================================================================== ---- pidgin-2.10.11.orig/libpurple/data/purple.pc.in -+++ pidgin-2.10.11/libpurple/data/purple.pc.in -@@ -5,6 +5,7 @@ includedir=@includedir@ - datarootdir=@datarootdir@ - datadir=@datadir@ - sysconfdir=@sysconfdir@ -+gstreamer=@GSTREAMER_VER@ - - plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ - -Index: pidgin-2.10.11/libpurple/example/Makefile.am -=================================================================== ---- pidgin-2.10.11.orig/libpurple/example/Makefile.am -+++ pidgin-2.10.11/libpurple/example/Makefile.am -@@ -8,6 +8,7 @@ nullclient_LDADD = \ - $(INTLLIBS) \ - $(GLIB_LIBS) \ - $(LIBXML_LIBS) \ -+ $(GSTVIDEO_LIBS) \ - $(top_builddir)/libpurple/libpurple.la - - AM_CPPFLAGS = \ -Index: pidgin-2.10.11/libpurple/media/backend-fs2.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/media/backend-fs2.c -+++ pidgin-2.10.11/libpurple/media/backend-fs2.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - #endif - - /** @copydoc _PurpleMediaBackendFs2Class */ -@@ -242,9 +243,17 @@ purple_media_network_protocol_from_fs(Fs - g_return_val_if_reached(PURPLE_MEDIA_NETWORK_PROTOCOL_TCP); - } - -+#if GST_CHECK_VERSION(1,0,0) -+static GstPadProbeReturn -+event_probe_cb(GstPad *srcpad, GstPadProbeInfo *info, gpointer unused) -+#else - static gboolean - event_probe_cb(GstPad *srcpad, GstEvent *event, gboolean release_pad) -+#endif - { -+#if GST_CHECK_VERSION(1,0,0) -+ GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); -+#endif - if (GST_EVENT_TYPE(event) == GST_EVENT_CUSTOM_DOWNSTREAM - && gst_event_has_name(event, "purple-unlink-tee")) { - -@@ -252,22 +261,40 @@ event_probe_cb(GstPad *srcpad, GstEvent - - gst_pad_unlink(srcpad, gst_pad_get_peer(srcpad)); - -+#if GST_CHECK_VERSION(1,0,0) -+ gst_pad_remove_probe(srcpad, -+ g_value_get_ulong(gst_structure_get_value(s, "handler-id"))); -+#else - gst_pad_remove_event_probe(srcpad, - g_value_get_uint(gst_structure_get_value(s, "handler-id"))); -+#endif - - if (g_value_get_boolean(gst_structure_get_value(s, "release-pad"))) - gst_element_release_request_pad(GST_ELEMENT_PARENT(srcpad), srcpad); - -+#if GST_CHECK_VERSION(1,0,0) -+ return GST_PAD_PROBE_DROP; -+#else - return FALSE; -+#endif - } - -+#if GST_CHECK_VERSION(1,0,0) -+ return GST_PAD_PROBE_OK; -+#else - return TRUE; -+#endif - } - - static void - unlink_teepad_dynamic(GstPad *srcpad, gboolean release_pad) - { -+#if GST_CHECK_VERSION(1,0,0) -+ gulong id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, -+ event_probe_cb, NULL, NULL); -+#else - guint id = gst_pad_add_event_probe(srcpad, G_CALLBACK(event_probe_cb), NULL); -+#endif - - if (GST_IS_GHOST_PAD(srcpad)) - srcpad = gst_ghost_pad_get_target(GST_GHOST_PAD(srcpad)); -@@ -276,7 +303,11 @@ unlink_teepad_dynamic(GstPad *srcpad, gb - gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, - gst_structure_new("purple-unlink-tee", - "release-pad", G_TYPE_BOOLEAN, release_pad, -+#if GST_CHECK_VERSION(1,0,0) -+ "handler-id", G_TYPE_ULONG, id, -+#else - "handler-id", G_TYPE_UINT, id, -+#endif - NULL))); - } - -@@ -859,15 +890,31 @@ gst_msg_db_to_percent(GstMessage *msg, g - gdouble value_db; - gdouble percent; - -- list = gst_structure_get_value( -- gst_message_get_structure(msg), value_name); -+ list = gst_structure_get_value(gst_message_get_structure(msg), value_name); -+#if GST_CHECK_VERSION(1,0,0) -+G_GNUC_BEGIN_IGNORE_DEPRECATIONS -+ value = g_value_array_get_nth(g_value_get_boxed(list), 0); -+G_GNUC_END_IGNORE_DEPRECATIONS -+#else - value = gst_value_list_get_value(list, 0); -+#endif - value_db = g_value_get_double(value); - percent = pow(10, value_db / 20); - return (percent > 1.0) ? 1.0 : percent; - } - - static void -+purple_media_error_fs(PurpleMedia *media, const gchar *error, -+ const GstStructure *fs_error) -+{ -+ const gchar *error_msg = gst_structure_get_string(fs_error, "error-msg"); -+ -+ purple_media_error(media, "%s%s%s", error, -+ error_msg ? _("\n\nMessage from Farsight: ") : "", -+ error_msg ? error_msg : ""); -+} -+ -+static void - gst_handle_message_element(GstBus *bus, GstMessage *msg, - PurpleMediaBackendFs2 *self) - { -@@ -875,11 +922,12 @@ gst_handle_message_element(GstBus *bus, - PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); - GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); - static guint level_id = 0; -+ const GstStructure *structure = gst_message_get_structure(msg); - - if (level_id == 0) - level_id = g_signal_lookup("level", PURPLE_TYPE_MEDIA); - -- if (gst_structure_has_name(msg->structure, "level")) { -+ if (gst_structure_has_name(structure, "level")) { - GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); - gchar *name; - gchar *participant = NULL; -@@ -934,31 +982,63 @@ gst_handle_message_element(GstBus *bus, - return; - - #ifdef HAVE_FARSIGHT -- if (gst_structure_has_name(msg->structure, "farsight-error")) { -+ if (gst_structure_has_name(structure, "farsight-error")) { - #else -- if (gst_structure_has_name(msg->structure, "farstream-error")) { -+ if (gst_structure_has_name(structure, "farstream-error")) { - #endif - FsError error_no; -- gst_structure_get_enum(msg->structure, "error-no", -+ gboolean error_emitted = FALSE; -+ gst_structure_get_enum(structure, "error-no", - FS_TYPE_ERROR, (gint*)&error_no); - switch (error_no) { -+ case FS_ERROR_CONSTRUCTION: -+ purple_media_error_fs(priv->media, -+ _("Error initializing the call. " -+ "This probably denotes problem in " -+#ifdef HAVE_FARSIGHT -+ "installation of GStreamer or Farsight."), -+#else -+ "installation of GStreamer or Farstream."), -+#endif -+ structure); -+ error_emitted = TRUE; -+ break; -+ case FS_ERROR_NETWORK: -+ purple_media_error_fs(priv->media, _("Network error."), -+ structure); -+ error_emitted = TRUE; -+ purple_media_end(priv->media, NULL, NULL); -+ break; -+ case FS_ERROR_NEGOTIATION_FAILED: -+ purple_media_error_fs(priv->media, -+ _("Codec negotiation failed. " -+ "This problem might be resolved by installing " -+ "more GStreamer codecs."), -+ structure); -+ error_emitted = TRUE; -+ purple_media_end(priv->media, NULL, NULL); -+ break; - case FS_ERROR_NO_CODECS: -- purple_media_error(priv->media, _("No codecs" -- " found. Install some" -- " GStreamer codecs found" -- " in GStreamer plugins" -- " packages.")); -+ purple_media_error(priv->media, -+ _("No codecs found. " -+ "Install some GStreamer codecs found " -+ "in GStreamer plugins packages.")); -+ error_emitted = TRUE; - purple_media_end(priv->media, NULL, NULL); - break; - #ifdef HAVE_FARSIGHT - case FS_ERROR_NO_CODECS_LEFT: -- purple_media_error(priv->media, _("No codecs" -- " left. Your codec" -- " preferences in" -- " fs-codecs.conf are too" -- " strict.")); -+ purple_media_error(priv->media, -+ _("No codecs left. Your codec preferences " -+ "in fs-codecs.conf are too strict.")); -+ error_emitted = TRUE; - purple_media_end(priv->media, NULL, NULL); - break; -+ case FS_ERROR_CONNECTION_FAILED: -+ purple_media_error(priv->media, -+ _("Could not connect to the remote party")); -+ error_emitted = TRUE; -+ break; - case FS_ERROR_UNKNOWN_CNAME: - /* - * Unknown CName is only a problem for the -@@ -975,22 +1055,22 @@ gst_handle_message_element(GstBus *bus, - "farstream-error: %i: %s\n", - #endif - error_no, -- gst_structure_get_string( -- msg->structure, "error-msg")); -+ gst_structure_get_string(structure, "error-msg")); - break; - } - - if (FS_ERROR_IS_FATAL(error_no)) { -+ if (!error_emitted) - #ifdef HAVE_FARSIGHT -- purple_media_error(priv->media, _("A non-recoverable " -- "Farsight2 error has occurred.")); -+ purple_media_error(priv->media, -+ _("A non-recoverable Farsight2 error has occurred.")); - #else -- purple_media_error(priv->media, _("A non-recoverable " -- "Farstream error has occurred.")); -+ purple_media_error(priv->media, -+ _("A non-recoverable Farstream error has occurred.")); - #endif - purple_media_end(priv->media, NULL, NULL); - } -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-new-local-candidate")) { - #else -@@ -1005,9 +1085,9 @@ gst_handle_message_element(GstBus *bus, - PurpleMediaBackendFs2Stream *media_stream; - gchar *name; - -- value = gst_structure_get_value(msg->structure, "stream"); -+ value = gst_structure_get_value(structure, "stream"); - stream = g_value_get_object(value); -- value = gst_structure_get_value(msg->structure, "candidate"); -+ value = gst_structure_get_value(structure, "candidate"); - local_candidate = g_value_get_boxed(value); - - session = get_session_from_fs_stream(self, stream); -@@ -1029,7 +1109,7 @@ gst_handle_message_element(GstBus *bus, - g_signal_emit_by_name(self, "new-candidate", - session->id, name, candidate); - g_object_unref(candidate); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-local-candidates-prepared")) { - #else -@@ -1041,7 +1121,7 @@ gst_handle_message_element(GstBus *bus, - PurpleMediaBackendFs2Session *session; - gchar *name; - -- value = gst_structure_get_value(msg->structure, "stream"); -+ value = gst_structure_get_value(structure, "stream"); - stream = g_value_get_object(value); - session = get_session_from_fs_stream(self, stream); - -@@ -1051,7 +1131,7 @@ gst_handle_message_element(GstBus *bus, - - g_signal_emit_by_name(self, "candidates-prepared", - session->id, name); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-new-active-candidate-pair")) { - #else -@@ -1066,13 +1146,11 @@ gst_handle_message_element(GstBus *bus, - PurpleMediaCandidate *lcandidate, *rcandidate; - gchar *name; - -- value = gst_structure_get_value(msg->structure, "stream"); -+ value = gst_structure_get_value(structure, "stream"); - stream = g_value_get_object(value); -- value = gst_structure_get_value(msg->structure, -- "local-candidate"); -+ value = gst_structure_get_value(structure, "local-candidate"); - local_candidate = g_value_get_boxed(value); -- value = gst_structure_get_value(msg->structure, -- "remote-candidate"); -+ value = gst_structure_get_value(structure, "remote-candidate"); - remote_candidate = g_value_get_boxed(value); - - g_object_get(stream, "participant", &participant, NULL); -@@ -1089,7 +1167,7 @@ gst_handle_message_element(GstBus *bus, - - g_object_unref(lcandidate); - g_object_unref(rcandidate); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-recv-codecs-changed")) { - #else -@@ -1099,7 +1177,7 @@ gst_handle_message_element(GstBus *bus, - GList *codecs; - FsCodec *codec; - -- value = gst_structure_get_value(msg->structure, "codecs"); -+ value = gst_structure_get_value(structure, "codecs"); - codecs = g_value_get_boxed(value); - codec = codecs->data; - -@@ -1110,7 +1188,7 @@ gst_handle_message_element(GstBus *bus, - "farstream-recv-codecs-changed: %s\n", - #endif - codec->encoding_name); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-component-state-changed")) { - #else -@@ -1121,9 +1199,9 @@ gst_handle_message_element(GstBus *bus, - guint component; - const gchar *state; - -- value = gst_structure_get_value(msg->structure, "state"); -+ value = gst_structure_get_value(structure, "state"); - fsstate = g_value_get_enum(value); -- value = gst_structure_get_value(msg->structure, "component"); -+ value = gst_structure_get_value(structure, "component"); - component = g_value_get_uint(value); - - switch (fsstate) { -@@ -1158,7 +1236,7 @@ gst_handle_message_element(GstBus *bus, - #endif - "component: %u state: %s\n", - component, state); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-send-codec-changed")) { - #else -@@ -1168,7 +1246,7 @@ gst_handle_message_element(GstBus *bus, - FsCodec *codec; - gchar *codec_str; - -- value = gst_structure_get_value(msg->structure, "codec"); -+ value = gst_structure_get_value(structure, "codec"); - codec = g_value_get_boxed(value); - codec_str = fs_codec_to_string(codec); - -@@ -1181,7 +1259,7 @@ gst_handle_message_element(GstBus *bus, - codec_str); - - g_free(codec_str); -- } else if (gst_structure_has_name(msg->structure, -+ } else if (gst_structure_has_name(structure, - #ifdef HAVE_FARSIGHT - "farsight-codecs-changed")) { - #else -@@ -1191,7 +1269,7 @@ gst_handle_message_element(GstBus *bus, - FsSession *fssession; - GList *sessions; - -- value = gst_structure_get_value(msg->structure, "session"); -+ value = gst_structure_get_value(structure, "session"); - fssession = g_value_get_object(value); - sessions = g_hash_table_get_values(priv->sessions); - -@@ -1635,7 +1713,11 @@ create_src(PurpleMediaBackendFs2 *self, - srcpad = gst_element_get_static_pad(session->srcvalve, "src"); - g_object_set(volume, "volume", input_volume, NULL); - } else { -+#if GST_CHECK_VERSION(1,0,0) -+ srcpad = gst_element_get_request_pad(session->tee, "src_%u"); -+#else - srcpad = gst_element_get_request_pad(session->tee, "src%d"); -+#endif - } - - purple_debug_info("backend-fs2", "connecting pad: %s\n", -@@ -1645,11 +1727,14 @@ create_src(PurpleMediaBackendFs2 *self, - gst_object_unref(session->src); - gst_object_unref(sinkpad); - -- gst_element_set_state(session->src, GST_STATE_PLAYING); -- - purple_media_manager_create_output_window(purple_media_get_manager( - priv->media), priv->media, sess_id, NULL); - -+ purple_debug_info("backend-fs2", "create_src: setting source " -+ "state to GST_STATE_PLAYING - it may hang here on win32\n"); -+ gst_element_set_state(session->src, GST_STATE_PLAYING); -+ purple_debug_info("backend-fs2", "create_src: state set\n"); -+ - return TRUE; - } - -@@ -1853,14 +1938,10 @@ src_pad_added_cb(FsStream *fsstream, Gst - * audioresample ! audioconvert ! realsink - */ - stream->queue = gst_element_factory_make("queue", NULL); -- stream->volume = gst_element_factory_make( -- "volume", NULL); -- g_object_set(stream->volume, "volume", -- output_volume, NULL); -- stream->level = gst_element_factory_make( -- "level", NULL); -- stream->src = gst_element_factory_make( -- "liveadder", NULL); -+ stream->volume = gst_element_factory_make("volume", NULL); -+ g_object_set(stream->volume, "volume", output_volume, NULL); -+ stream->level = gst_element_factory_make("level", NULL); -+ stream->src = gst_element_factory_make("liveadder", NULL); - sink = purple_media_manager_get_element( - purple_media_get_manager(priv->media), - PURPLE_MEDIA_RECV_AUDIO, priv->media, -@@ -1879,10 +1960,12 @@ src_pad_added_cb(FsStream *fsstream, Gst - gst_element_link(stream->queue, stream->volume); - sink = stream->queue; - } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { -- stream->src = gst_element_factory_make( -- "fsfunnel", NULL); -- sink = gst_element_factory_make( -- "fakesink", NULL); -+#if GST_CHECK_VERSION(1,0,0) -+ stream->src = gst_element_factory_make("funnel", NULL); -+#else -+ stream->src = gst_element_factory_make("fsfunnel", NULL); -+#endif -+ sink = gst_element_factory_make("fakesink", NULL); - g_object_set(G_OBJECT(sink), "async", FALSE, NULL); - gst_bin_add(GST_BIN(priv->confbin), sink); - gst_element_set_state(sink, GST_STATE_PLAYING); -@@ -1896,7 +1979,11 @@ src_pad_added_cb(FsStream *fsstream, Gst - gst_element_link_many(stream->src, stream->tee, sink, NULL); - } - -+#if GST_CHECK_VERSION(1,0,0) -+ sinkpad = gst_element_get_request_pad(stream->src, "sink_%u"); -+#else - sinkpad = gst_element_get_request_pad(stream->src, "sink%d"); -+#endif - gst_pad_link(srcpad, sinkpad); - gst_object_unref(sinkpad); - -@@ -2078,8 +2165,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS - if (!fs_stream_set_transmitter(fsstream, transmitter, - _params, _num_params, &err)) { - purple_debug_error("backend-fs2", -- "Could not set transmitter %s: %s.\n", -- transmitter, err->message); -+ "Could not set transmitter %s: %s.\n", -+ transmitter, err ? err->message : NULL); - g_clear_error(&err); - g_free(_params); - return FALSE; -@@ -2398,14 +2485,44 @@ purple_media_backend_fs2_set_send_codec( - return TRUE; - } - -+static const gchar ** -+purple_media_backend_fs2_get_available_params(void) -+{ -+ static const gchar *supported_params[] = { -+ "sdes-cname", "sdes-email", "sdes-location", "sdes-name", "sdes-note", -+ "sdes-phone", "sdes-tool", NULL -+ }; -+ -+ return supported_params; -+} -+ -+static const gchar* -+param_to_sdes_type(const gchar *param) -+{ -+ const gchar **supported = purple_media_backend_fs2_get_available_params(); -+ static const gchar *sdes_types[] = { -+ "cname", "email", "location", "name", "note", "phone", "tool", NULL -+ }; -+ guint i; -+ -+ for (i = 0; supported[i] != NULL; ++i) { -+ if (!strcmp(param, supported[i])) { -+ return sdes_types[i]; -+ } -+ } -+ -+ return NULL; -+} -+ - static void - purple_media_backend_fs2_set_params(PurpleMediaBackend *self, - guint num_params, GParameter *params) - { - PurpleMediaBackendFs2Private *priv; -- const gchar **supported = purple_media_backend_fs2_get_available_params(); -- const gchar **p; - guint i; -+#ifndef HAVE_FARSIGHT -+ GstStructure *sdes; -+#endif - - g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self)); - -@@ -2418,27 +2535,30 @@ purple_media_backend_fs2_set_params(Purp - return; - } - -+#ifdef HAVE_FARSIGHT - for (i = 0; i != num_params; ++i) { -- for (p = supported; *p != NULL; ++p) { -- if (!strcmp(params[i].name, *p)) { -- g_object_set(priv->conference, -- params[i].name, g_value_get_string(¶ms[i].value), -- NULL); -- break; -- } -+ if (param_to_sdes_type(params[i].name)) { -+ g_object_set(priv->conference, -+ params[i].name, g_value_get_string(¶ms[i].value), -+ NULL); - } - } --} -+#else -+ g_object_get(G_OBJECT(priv->conference), "sdes", &sdes, NULL); - --static const gchar ** --purple_media_backend_fs2_get_available_params(void) --{ -- static const gchar *supported_params[] = { -- "sdes-cname", "sdes-email", "sdes-location", "sdes-name", "sdes-note", -- "sdes-phone", "sdes-tool", NULL -- }; -+ for (i = 0; i != num_params; ++i) { -+ const gchar *sdes_type = param_to_sdes_type(params[i].name); -+ if (!sdes_type) -+ continue; - -- return supported_params; -+ gst_structure_set(sdes, sdes_type, -+ G_TYPE_STRING, g_value_get_string(¶ms[i].value), -+ NULL); -+ } -+ -+ g_object_set(G_OBJECT(priv->conference), "sdes", sdes, NULL); -+ gst_structure_free(sdes); -+#endif /* HAVE_FARSIGHT */ - } - static gboolean - send_dtmf_callback(gpointer userdata) -Index: pidgin-2.10.11/libpurple/mediamanager.c -=================================================================== ---- pidgin-2.10.11.orig/libpurple/mediamanager.c -+++ pidgin-2.10.11/libpurple/mediamanager.c -@@ -44,7 +44,12 @@ - #else - #include - #endif -+ -+#if GST_CHECK_VERSION(1,0,0) -+#include -+#else - #include -+#endif - - /** @copydoc _PurpleMediaManagerPrivate */ - typedef struct _PurpleMediaManagerPrivate PurpleMediaManagerPrivate; -@@ -270,8 +275,11 @@ purple_media_manager_get_pipeline(Purple - gst_bus_add_signal_watch(GST_BUS(bus)); - g_signal_connect(G_OBJECT(bus), "message", - G_CALLBACK(pipeline_bus_call), manager); -- gst_bus_set_sync_handler(bus, -- gst_bus_sync_signal_handler, NULL); -+#if GST_CHECK_VERSION(1,0,0) -+ gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, NULL, NULL); -+#else -+ gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, NULL); -+#endif - gst_object_unref(bus); - - filename = g_build_filename(purple_user_dir(), -@@ -405,20 +413,31 @@ request_pad_unlinked_cb(GstPad *pad, Gst - { - GstElement *parent = GST_ELEMENT_PARENT(pad); - GstIterator *iter; -+#if GST_CHECK_VERSION(1,0,0) -+ GValue tmp = G_VALUE_INIT; -+#endif - GstPad *remaining_pad; - GstIteratorResult result; - -- gst_element_release_request_pad(GST_ELEMENT_PARENT(pad), pad); -+ gst_element_release_request_pad(parent, pad); - - iter = gst_element_iterate_src_pads(parent); - -+#if GST_CHECK_VERSION(1,0,0) -+ result = gst_iterator_next(iter, &tmp); -+#else - result = gst_iterator_next(iter, (gpointer)&remaining_pad); -+#endif - - if (result == GST_ITERATOR_DONE) { - gst_element_set_locked_state(parent, TRUE); - gst_element_set_state(parent, GST_STATE_NULL); - gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(parent)), parent); - } else if (result == GST_ITERATOR_OK) { -+#if GST_CHECK_VERSION(1,0,0) -+ remaining_pad = g_value_get_object(&tmp); -+ g_value_reset(&tmp); -+#endif - gst_object_unref(remaining_pad); - } - -@@ -456,7 +475,11 @@ purple_media_manager_get_video_caps(Purp - { - #ifdef USE_VV - if (manager->priv->video_caps == NULL) -+#if GST_CHECK_VERSION(1,0,0) -+ manager->priv->video_caps = gst_caps_from_string("video/x-raw," -+#else - manager->priv->video_caps = gst_caps_from_string("video/x-raw-yuv," -+#endif - "width=[250,352], height=[200,288], framerate=[1/1,20/1]"); - return manager->priv->video_caps; - #else -@@ -539,7 +562,11 @@ purple_media_manager_get_element(PurpleM - g_free(id); - - tee = gst_bin_get_by_name(GST_BIN(ret), "tee"); -+#if GST_CHECK_VERSION(1,0,0) -+ pad = gst_element_get_request_pad(tee, "src_%u"); -+#else - pad = gst_element_get_request_pad(tee, "src%d"); -+#endif - gst_object_unref(tee); - ghost = gst_ghost_pad_new(NULL, pad); - gst_object_unref(pad); -@@ -730,9 +757,12 @@ window_id_cb(GstBus *bus, GstMessage *ms - { - GstElement *sink; - -- if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT || -- !gst_structure_has_name(msg->structure, -- "prepare-xwindow-id")) -+ if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT -+#if GST_CHECK_VERSION(1,0,0) -+ || !gst_is_video_overlay_prepare_window_handle_message(msg)) -+#else -+ || !gst_structure_has_name(msg->structure, "prepare-xwindow-id")) -+#endif - return; - - sink = GST_ELEMENT(GST_MESSAGE_SRC(msg)); -@@ -746,8 +776,16 @@ window_id_cb(GstBus *bus, GstMessage *ms - | G_SIGNAL_MATCH_DATA, 0, 0, NULL, - window_id_cb, ow); - -- gst_x_overlay_set_xwindow_id(GST_X_OVERLAY( -- GST_MESSAGE_SRC(msg)), ow->window_id); -+#if GST_CHECK_VERSION(1,0,0) -+ gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)), -+ ow->window_id); -+#elif GST_CHECK_VERSION(0,10,31) -+ gst_x_overlay_set_window_handle(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), -+ ow->window_id); -+#else -+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), -+ ow->window_id); -+#endif - } - #endif - -@@ -772,17 +810,19 @@ purple_media_manager_create_output_windo - (participant == ow->participant)) && - !strcmp(session_id, ow->session_id)) { - GstBus *bus; -- GstElement *queue, *colorspace; -+ GstElement *queue, *convert; - GstElement *tee = purple_media_get_tee(media, - session_id, participant); - - if (tee == NULL) - continue; - -- queue = gst_element_factory_make( -- "queue", NULL); -- colorspace = gst_element_factory_make( -- "ffmpegcolorspace", NULL); -+ queue = gst_element_factory_make("queue", NULL); -+#if GST_CHECK_VERSION(1,0,0) -+ convert = gst_element_factory_make("videoconvert", NULL); -+#else -+ convert = gst_element_factory_make("ffmpegcolorspace", NULL); -+#endif - ow->sink = purple_media_manager_get_element( - manager, PURPLE_MEDIA_RECV_VIDEO, - ow->media, ow->session_id, -@@ -795,7 +835,7 @@ purple_media_manager_create_output_windo - if (g_object_class_find_property(klass, - "sync")) - g_object_set(G_OBJECT(ow->sink), -- "sync", "FALSE", NULL); -+ "sync", FALSE, NULL); - if (g_object_class_find_property(klass, - "async")) - g_object_set(G_OBJECT(ow->sink), -@@ -803,7 +843,7 @@ purple_media_manager_create_output_windo - } - - gst_bin_add_many(GST_BIN(GST_ELEMENT_PARENT(tee)), -- queue, colorspace, ow->sink, NULL); -+ queue, convert, ow->sink, NULL); - - bus = gst_pipeline_get_bus(GST_PIPELINE( - manager->priv->pipeline)); -@@ -812,10 +852,10 @@ purple_media_manager_create_output_windo - gst_object_unref(bus); - - gst_element_set_state(ow->sink, GST_STATE_PLAYING); -- gst_element_set_state(colorspace, GST_STATE_PLAYING); -+ gst_element_set_state(convert, GST_STATE_PLAYING); - gst_element_set_state(queue, GST_STATE_PLAYING); -- gst_element_link(colorspace, ow->sink); -- gst_element_link(queue, colorspace); -+ gst_element_link(convert, ow->sink); -+ gst_element_link(queue, convert); - gst_element_link(tee, queue); - } - } -Index: pidgin-2.10.11/pidgin/Makefile.am -=================================================================== ---- pidgin-2.10.11.orig/pidgin/Makefile.am -+++ pidgin-2.10.11/pidgin/Makefile.am -@@ -151,6 +151,7 @@ pidgin_LDADD = \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) \ - $(GSTREAMER_LIBS) \ -+ $(GSTVIDEO_LIBS) \ - $(XSS_LIBS) \ - $(SM_LIBS) \ - $(INTLLIBS) \ -Index: pidgin-2.10.11/pidgin/gtkmedia.c -=================================================================== ---- pidgin-2.10.11.orig/pidgin/gtkmedia.c -+++ pidgin-2.10.11/pidgin/gtkmedia.c -@@ -43,7 +43,9 @@ - #endif - #include - -+#if !GST_CHECK_VERSION(1,0,0) - #include -+#endif - - #define PIDGIN_TYPE_MEDIA (pidgin_media_get_type()) - #define PIDGIN_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_MEDIA, PidginMedia)) -@@ -590,6 +592,9 @@ pidgin_media_error_cb(PidginMedia *media - if (conv != NULL) - purple_conversation_write(conv, NULL, error, - PURPLE_MESSAGE_ERROR, time(NULL)); -+ else -+ purple_notify_error(NULL, NULL, _("Media error"), error); -+ - gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar), - 0, error); - } -Index: pidgin-2.10.11/pidgin/plugins/vvconfig.c -=================================================================== ---- pidgin-2.10.11.orig/pidgin/plugins/vvconfig.c -+++ pidgin-2.10.11/pidgin/plugins/vvconfig.c -@@ -26,7 +26,11 @@ - #include "gtkutils.h" - #include "gtkprefs.h" - -+#if GST_CHECK_VERSION(1,0,0) -+#include -+#else - #include -+#endif - - /* container window for showing a stand-alone configurator */ - static GtkWidget *window = NULL; -@@ -81,8 +85,10 @@ get_element_devices(const gchar *element - GList *ret = NULL; - GstElement *element; - GObjectClass *klass; -+#if !GST_CHECK_VERSION(1,0,0) - GstPropertyProbe *probe; - const GParamSpec *pspec; -+#endif - - ret = g_list_prepend(ret, (gpointer)_("Default")); - ret = g_list_prepend(ret, ""); -@@ -103,6 +109,10 @@ get_element_devices(const gchar *element - return g_list_reverse(ret); - } - -+#if GST_CHECK_VERSION(1,0,0) -+ purple_debug_info("vvconfig", "'%s' - gstreamer-1.0 doesn't suport " -+ "property probing\n", element_name); -+#else - if (!g_object_class_find_property(klass, "device") || - !GST_IS_PROPERTY_PROBE(element) || - !(probe = GST_PROPERTY_PROBE(element)) || -@@ -155,6 +165,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS - gst_element_set_state(element, GST_STATE_NULL); - } - } -+#endif - gst_object_unref(element); - - return g_list_reverse(ret); -@@ -168,8 +179,13 @@ get_element_plugins(const gchar **plugin - ret = g_list_prepend(ret, "Default"); - ret = g_list_prepend(ret, ""); - for (; plugins[0] && plugins[1]; plugins += 2) { -+#if GST_CHECK_VERSION(1,0,0) -+ if (gst_registry_check_feature_version(gst_registry_get(), -+ plugins[0], 0, 0, 0)) { -+#else - if (gst_default_registry_check_feature_version( - plugins[0], 0, 0, 0)) { -+#endif - ret = g_list_prepend(ret, (gpointer)plugins[1]); - ret = g_list_prepend(ret, (gpointer)plugins[0]); - } -@@ -588,7 +604,13 @@ gst_msg_db_to_percent(GstMessage *msg, g - - list = gst_structure_get_value( - gst_message_get_structure(msg), value_name); -+#if GST_CHECK_VERSION(1,0,0) -+G_GNUC_BEGIN_IGNORE_DEPRECATIONS -+ value = g_value_array_get_nth(g_value_get_boxed(list), 0); -+G_GNUC_END_IGNORE_DEPRECATIONS -+#else - value = gst_value_list_get_value(list, 0); -+#endif - value_db = g_value_get_double(value); - percent = pow(10, value_db / 20); - return (percent > 1.0) ? 1.0 : percent; -@@ -604,7 +626,7 @@ static gboolean - gst_bus_cb(GstBus *bus, GstMessage *msg, BusCbCtx *ctx) - { - if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ELEMENT && -- gst_structure_has_name(msg->structure, "level")) { -+ gst_structure_has_name(gst_message_get_structure(msg), "level")) { - - GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); - gchar *name = gst_element_get_name(src); diff --git a/pidgin.changes b/pidgin.changes index 315e883..6d7624b 100644 --- a/pidgin.changes +++ b/pidgin.changes @@ -1,3 +1,24 @@ +------------------------------------------------------------------- +Sat Jan 2 09:45:54 UTC 2016 - sor.alexei@meowr.ru + +- Update to 2.10.12: + + General: + - purple-url-handler now works with Python 3.x. + - Fix an issue where transient startup statuses could be + deleted (pidgin.im#16762). + + Pidgin: The shout smile now matches the default theme. + + Gadu-Gadu: Update internal libgadu to version 1.12.1. +- Use tarball signing. +- Rebase pidgin-gnome-keyring.patch. +- Remove pidgin-2.10.11-add-dtmf-support.patch, + pidgin-2.10.11-gst-references.patch, + pidgin-2.10.11-send-video-enum.patch, + pidgin-2.10.11-application-media.patch, + pidgin-2.10.11-init-media-optional.patch, + pidgin-2.10.11-fix-sound-play-fd-leak.patch, + pidgin-2.10.11-private-media.patch and + pidgin-port-to-gst-1.0.patch: added upstream. + ------------------------------------------------------------------- Wed Sep 9 08:19:54 UTC 2015 - dimstar@opensuse.org diff --git a/pidgin.keyring b/pidgin.keyring new file mode 100644 index 0000000..37e160c --- /dev/null +++ b/pidgin.keyring @@ -0,0 +1,53 @@ +pub dsa1024/A8AC8032 2004-12-03 + Key fingerprint = 364E 2EB3 8EA6 A8D6 1FB9 63AD 75FE 259A A8AC 8032 +uid [ unknown] Gary Kramlich (grim) +sub elg2048/A471F9D3 2004-12-03 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +mQGiBEGv9+sRBACI6qhXQnirKxAgmNIIcsLgxyItefSmbNMtmpiG9zTeobDrNn8W +L/H/hiSepghXsTSCqoBhMCz3quG9zzo7Wokj/va5Y5icVQEfiSCAqN/OVDTN1JnN +P1/tsrHMkGZW2a3SHg11e9vtMkgvlNHvxkgFj+nVMdWSeR54URRG6nHnowCgoY1K +1UwrG8gNnAiksV3HEKsUYvMD/1tjVW8b+Um3AERNF9eokIYi5S7xJOF4uObvI5cy +m4VjUbbaFLA6LYHTm1sfVydDLYOh6xw6BuvlfVLu5AUl6NTINpgnV9IqHXcXNk09 +n9NjUC7QEFKR9hl+VmsWJQgelvnoKS7c90F21ibBgNYzfhU+ZRCa7ufsp9QDrXKh +MV/QA/0VgDnzLBvB5hF6usOyXuNXXB0xNpybGcOx3fe4dyCHxuiPanqxwLRNinIx +U22Z6qGzwOvvRrLH1/WbcYxZoayBc+SoFXie+PDLn7ezDr4KyL5vR1krk6GKE6GT +B/HQa4dBPIm4gyF6ESgjUDrqbjJZDRakkxu2W+6bGYCo9On/RrQrR2FyeSBLcmFt +bGljaCAoZ3JpbSkgPGdyaW1AcmVhcGVyd29ybGQuY29tPohGBBARAgAGBQJCOsel +AAoJEFHWtqRSzconkYEAnA821cifk0XaoI+Yn6jCxfpzKULuAKDACv5hBXbYYHcM +pZgzr+dHzlizU4hGBBARAgAGBQJDGjO9AAoJEKszLNffuoFddgUAoJUlZUywKjIG +oGfdtzDrf3dFEkUWAJ4vkOzy45/GQV3ky2398ShGClrBjYhGBBARAgAGBQJHB9at +AAoJEE6Nhw5MKS/MoFIAnibOJsmEa9RJ7LJwuzZTOHapMi09AKCQktO0w0NiBT21 +HQ/Q2JfxY7hEK4hGBBARAgAGBQJIwdugAAoJEJHfwaHio4NIPLgAn3LakmOb0/+u +mNAyQKXYsANf8BPoAJ9sG7syG+UGGhegmIgUjuBLYBju54hGBBARAgAGBQJJCIiE +AAoJEHDnXY+tMLq8WAMAn0TPs54oTtw41I6ktJWIlYyQx8LdAJ41UBUSi+wwdPKC +xUyGjXGrabh5b4hGBBMRAgAGBQJChqCyAAoJEHlNJodr1ROmZAkAoMuuw4aMPfG9 +sTjep9n73+b+ewciAJ9gqchpBeSvcsV01Tt8q8Lt7T4bs4hGBBMRAgAGBQJHB8/X +AAoJEG31OrleHxvO6PQAoJfD1gw66wbkEFKavQi0CCV8myi7AJsEyUGDNivHxzqj +MtXaTBJoTuuMnIheBBMRAgAeBQJBr/frAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheA +AAoJEHX+JZqorIAyGZkAoIK9QI/QA88UMLuL9a8+atz0nLkEAKCVZUpkbhoTiIOv +9nc5u+xbUHtdq4heBBMRAgAeBQJBr/frAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheA +AAoJEHX+JZqorIAyGZkAoImKgYxRu674UvSqx66Is5A7clE0AJ42bRnlUSpyp6oY ++paT7vSQqBgRlIkBHAQTAQgABgUCSuJXYwAKCRD/H4sWdx/HK7EKB/sHe2kUm/ok +MlXaF23VKjfDMqMmcIF6iG55tbFJA12BRn93zk0AiI6uM6UK9GCeAALk+G/tIbnK +aTuBOJkJ6hOCGEDYkgUTYRwpTJxhMNwf7RfXQLkrq+U5P8K23+gIg4YdJzqXp50y +Vm+MUqlUMICaPwijOVzj43Za5KROFOxH1T8NPRrJxJ/XQcxHmpCvCwlLPIN3GC4U +NIyoAyvgPacjdGctOM6/2/w4w7PxikAt48rO7xxz6pz6s6vh9vQ4Tu9RKI/In6u+ +SRgr8/WTnfhWPiO/OUg0de9PZuHhUUNvFiWW4dtSd3s7XsNgVKIiitY5vpGWFl3g +nbs/SPPobanPuQINBEGv+BoQCADIEWOtutfUCakMXhhTdb22NEO/qAqZwNsgkjb3 +VgiZ6DVxszh/wkeURCsmR+RnlfzBmjstF/ndQ8bWhwhp7Ooh/UH3Qrnu2fdqu9Dz +G/nWaSOGVjUMG0cMvSIVIJf/SaNSAY9XrC3JITi+lW/VzQcAYvqrnQR8SOl5c0Kx +f3WTgoP+/nnPV5bWQhiiy94nlEFLTGebpA1wvAY+EwZBzJYja7z4x/RTHa9K/fEJ +gLWU+8XfL15RnSoQULYfkbfImaKbPG1ipk1CmUXtzwLk3pwobpV+R20PwxfZZih0 +zo6+lByOuk2+5GnbHdAxgss6vUFnOwT1A86vNWml8Fs38XLjAAMGCAC6f839iYmn +FhYr0QAMSPwotuHFoE9P+6Jw3rkH0osDZufRkP1MjledxSPo6wmtl+5K3Xjcxshz +yJWrbsedqRNQbmt63571ekwSxDZ6xhA/B3nvj1XvHKNixsCVMtpENmkHH7IRnSZY +7SVq1RczC1kFMYIddIYMCKHESFraEstqntYdvw+U2UI03jFvv8EgzZdRHRDKhaRh +fWB9GWS3uhgPe+NEzGd7EhYTqwVBopy6WTmjzZDYRtRd+o2ZM6dV5g3HfN2e76Mp +0h4CGOp0x49OimAu3mIn5FYAlJnGM0EnY9/eel+WsiG494OJ/4cTLOwfWEbtHxaF +ks08zGRwRYk0iEkEGBECAAkFAkGv+BoCGwwACgkQdf4lmqisgDLrSACfewkvfajp +dM/0fYm3UbSqthpaXE8AnRjHE59o+d3ip8NM+l+o1/0ryN+O +=+0NZ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/pidgin.spec b/pidgin.spec index 514ec9f..b64d34a 100644 --- a/pidgin.spec +++ b/pidgin.spec @@ -1,7 +1,7 @@ # # spec file for package pidgin # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,14 +18,16 @@ %define _name Pidgin Name: pidgin -Version: 2.10.11 +Version: 2.10.12 Release: 0 Summary: Multiprotocol Instant Messaging Client License: GPL-2.0+ Group: Productivity/Networking/Instant Messenger -Url: http://pidgin.im/ -Source: http://downloads.sf.net/%{name}/%{name}-%{version}.tar.gz -Source1: pidgin-prefs.xml +Url: https://pidgin.im/ +Source: http://downloads.sf.net/%{name}/%{name}-%{version}.tar.bz2 +Source1: http://downloads.sf.net/%{name}/%{name}-%{version}.tar.bz2.asc +Source2: pidgin.keyring +Source3: pidgin-prefs.xml # PATCH-FIX-OPENSUSE pidgin-nonblock-common.patch Patch0: pidgin-nonblock-common.patch # PATCH-FIX-OPENSUSE pidgin-nonblock-gwim.patch @@ -34,27 +36,12 @@ Patch1: pidgin-nonblock-gwim.patch Patch2: pidgin-nonblock-common2.patch # PATCH-FEATURE-SLE pidgin-gnome-keyring.patch Patch3: pidgin-gnome-keyring.patch -# PATCH-FIX-OPENSUSE pidgin-fix-perl-build.patch vuntz@opensuse.org -- Revert http://developer.pidgin.im/viewmtn/revision/info/f32151852a00fb5abd3fdccdd8df2419031666de as it breaks the build +# PATCH-FIX-OPENSUSE pidgin-fix-perl-build.patch vuntz@opensuse.org -- Revert http://developer.pidgin.im/viewmtn/revision/info/f32151852a00fb5abd3fdccdd8df2419031666de as it breaks the build. Patch4: pidgin-fix-perl-build.patch # PATCH-FIX-UPSTREAM pidgin-crash-missing-gst-registry.patch boo#866455 pidgin.im#16224 cxiong@suse.com -- Fix crash when GST registry cache file is missing. -Patch6: pidgin-crash-missing-gst-registry.patch -Patch7: pidgin-2.10.11-send-video-enum.patch -# PATCH-FEATURE-UPSTREAM pidgin-2.10.11-gst-references.patch dimstar@opensuse.org -- http://hg.pidgin.im/pidgin/main/rev/b52be4fef1de -Patch8: pidgin-2.10.11-gst-references.patch -# PATCH-FEATURE-UPSTREAM pidgin-2.10.11-add-dtmf-support.patch dimstar@opensuse.org -- http://hg.pidgin.im/pidgin/main/rev/6b4576edf2a6 -Patch9: pidgin-2.10.11-add-dtmf-support.patch -# PATCH-FEATURE-UPSTREAM pidgin-port-to-gst-1.0.patch dimstar@opensuse.org -- Port to GStreamer 1.0 / farstream 0.2; taken from https://pidgin.im/pipermail/devel/2015-March/023645.html -Patch10: pidgin-port-to-gst-1.0.patch -# PATCH-FIX-UPSTREAM pidgin-2.10.11-init-media-optional.patch dimstar@opensuse.org -- make "init-media" signal handler optional -Patch11: pidgin-2.10.11-init-media-optional.patch -# PATCH-FIX-UPSTREAM pidgin-2.10.11-private-media.patch dimstar@opensuse.org -- Add Private media API. -Patch12: pidgin-2.10.11-private-media.patch -# PATCH-FIX-UPSTREAM pidgin-2.10.11-application-media.patch dimstar@opensuse.org -- Add application media type and APIs, pidgin.im#16315 -Patch13: pidgin-2.10.11-application-media.patch -# PATCH-FIX-UPSTREAM pidgin-2.10.11-fix-sound-play-fd-leak.patch boo#942818 sor.alexei@meowr.ru -- Fix a file desriptor leak while playing sound files. -Patch14: pidgin-2.10.11-fix-sound-play-fd-leak.patch +Patch5: pidgin-crash-missing-gst-registry.patch # PATCH-FIX-UPSTREAM pidgin-ncurses-6.0-accessors.patch pidgin.im#16764 dimstar@opensuse.org -- Fix build with NCurses 6.0 with WINDOW_OPAQUE set to 1 -Patch15: pidgin-ncurses-6.0-accessors.patch +Patch6: pidgin-ncurses-6.0-accessors.patch BuildRequires: NetworkManager-devel # Can use external libzephyr. BuildRequires: cyrus-sasl-devel @@ -277,16 +264,10 @@ translation-update-upstream %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 %patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 + +cp -f %{SOURCE3} %{name}-prefs.xml # Change Myanmar/Myanmar to Myanmar. mv -f po/my_MM.po po/my.po @@ -324,10 +305,10 @@ make %{?_smp_mflags} %install %make_install -mkdir -p %{buildroot}%{_sysconfdir}/purple/ %if 0%{?suse_version} > 1140 -cp -f %{SOURCE1} %{buildroot}%{_sysconfdir}/purple/prefs.xml +install -Dm 0644 %{name}-prefs.xml %{buildroot}%{_sysconfdir}/purple/prefs.xml %else +mkdir -p %{buildroot}%{_sysconfdir}/purple/ rm -f %{buildroot}%{_sysconfdir}/gconf/schemas/purple.schemas %endif %perl_process_packlist @@ -373,7 +354,7 @@ find %{buildroot}%{_libdir}/finch/ -maxdepth 1 -xtype f -print | \ %files %defattr(-,root,root) -%doc AUTHORS COPYING COPYRIGHT ChangeLog NEWS README doc/the_penguin.txt +%doc AUTHORS COPYING COPYRIGHT ChangeLog README doc/the_penguin.txt %{_bindir}/%{name} %{_libdir}/%{name}/ %dir %{_datadir}/appdata/ @@ -411,10 +392,16 @@ find %{buildroot}%{_libdir}/finch/ -maxdepth 1 -xtype f -print | \ %if 0%{?suse_version} < 1140 # These locales are not included in respective products. # See https://bugzilla.opensuse.org/show_bug.cgi?id=659001 +%dir %{_datadir}/locale/brx/ +%dir %{_datadir}/locale/brx/LC_MESSAGES/ %dir %{_datadir}/locale/ku_IQ/ %dir %{_datadir}/locale/ku_IQ/LC_MESSAGES/ %dir %{_datadir}/locale/mhr/ %dir %{_datadir}/locale/mhr/LC_MESSAGES/ +%dir %{_datadir}/locale/ms_MY/ +%dir %{_datadir}/locale/ms_MY/LC_MESSAGES/ +%dir %{_datadir}/locale/sd/ +%dir %{_datadir}/locale/sd/LC_MESSAGES/ %endif %if 0%{?suse_version} > 1140