Merged in default (pull request #416)

Fri, 02 Nov 2018 01:37:22 +0000

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 02 Nov 2018 01:37:22 +0000
changeset 39263
ad2bcb22e4a9
parent 39261
183db900957f (diff)
parent 39262
53c6b966ac05 (current diff)
child 39269
3e6eb178b03b
child 39273
820a44d3d618
child 39286
9fd8469a1432
child 39291
9d253537d927

Merged in default (pull request #416)

screencap: Fix converting GdkPixbuf to PurpleImage

Approved-by: Elliott Sales de Andrade
Approved-by: Gary Kramlich
Approved-by: Eion Robb

--- a/ChangeLog	Thu Nov 01 17:28:46 2018 -0500
+++ b/ChangeLog	Fri Nov 02 01:37:22 2018 +0000
@@ -36,6 +36,11 @@
 	  joining a room. (Kha) (#15458)
 	* Fix gevolution plugin to compile with e-d-s >= 3.6, older versions are
 	  not supported anymore. (Ed Catmur) (#15353)
+	* Removed command line argument --multiple in *nix in favor of using
+	  GApplication's uniqueness checking directly. The new way to allow
+	  multiple Pidgin instances is to pass --gapplication-app-id with an
+	  alternate, valid app id. Be careful not to use the same configuration
+	  directory as the primary instance.
 
 	Finch:
 	* Support the conversation-extended signal for extending the
--- a/libpurple/media.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/media.c	Fri Nov 02 01:37:22 2018 +0000
@@ -82,8 +82,6 @@
 };
 
 #ifdef USE_VV
-#define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
-
 static void purple_media_class_init (PurpleMediaClass *klass);
 static void purple_media_init (PurpleMedia *media);
 static void purple_media_dispose (GObject *object);
@@ -105,9 +103,6 @@
 static void purple_media_codecs_changed_cb(PurpleMediaBackend *backend,
 		const gchar *sess_id, PurpleMedia *media);
 
-static GObjectClass *parent_class = NULL;
-
-
 
 enum {
 	S_ERROR,
@@ -131,42 +126,21 @@
 	PROP_INITIATOR,
 	PROP_PROTOCOL_DATA,
 };
-#endif
 
-
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleMedia, purple_media, G_TYPE_OBJECT);
+#else
 GType
 purple_media_get_type()
 {
-#ifdef USE_VV
-	static GType type = 0;
-
-	if (type == 0) {
-		static const GTypeInfo info = {
-			sizeof(PurpleMediaClass),
-			NULL,
-			NULL,
-			(GClassInitFunc) purple_media_class_init,
-			NULL,
-			NULL,
-			sizeof(PurpleMedia),
-			0,
-			(GInstanceInitFunc) purple_media_init,
-			NULL
-		};
-		type = g_type_register_static(G_TYPE_OBJECT, "PurpleMedia", &info, 0);
-	}
-	return type;
-#else
 	return G_TYPE_NONE;
-#endif
 }
+#endif /* USE_VV */
 
 #ifdef USE_VV
 static void
 purple_media_class_init (PurpleMediaClass *klass)
 {
 	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
 
 	gobject_class->dispose = purple_media_dispose;
 	gobject_class->finalize = purple_media_finalize;
@@ -252,14 +226,13 @@
 					 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
 					 G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_POINTER,
 					 PURPLE_TYPE_MEDIA_CANDIDATE, PURPLE_TYPE_MEDIA_CANDIDATE);
-	g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
 }
 
 
 static void
 purple_media_init (PurpleMedia *media)
 {
-	media->priv = PURPLE_MEDIA_GET_PRIVATE(media);
+	media->priv = purple_media_get_instance_private(media);
 	memset(media->priv, 0, sizeof(*media->priv));
 }
 
@@ -299,7 +272,8 @@
 static void
 purple_media_dispose(GObject *media)
 {
-	PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
+	PurpleMediaPrivate *priv =
+			purple_media_get_instance_private(PURPLE_MEDIA(media));
 
 	purple_debug_info("media","purple_media_dispose\n");
 
@@ -315,13 +289,14 @@
 		priv->manager = NULL;
 	}
 
-	G_OBJECT_CLASS(parent_class)->dispose(media);
+	G_OBJECT_CLASS(purple_media_parent_class)->dispose(media);
 }
 
 static void
 purple_media_finalize(GObject *media)
 {
-	PurpleMediaPrivate *priv = PURPLE_MEDIA_GET_PRIVATE(media);
+	PurpleMediaPrivate *priv =
+			purple_media_get_instance_private(PURPLE_MEDIA(media));
 	purple_debug_info("media","purple_media_finalize\n");
 
 	for (; priv->streams; priv->streams = g_list_delete_link(priv->streams, priv->streams))
@@ -339,7 +314,7 @@
 		g_hash_table_destroy(priv->sessions);
 	}
 
-	G_OBJECT_CLASS(parent_class)->finalize(media);
+	G_OBJECT_CLASS(purple_media_parent_class)->finalize(media);
 }
 
 static void
--- a/libpurple/media/backend-fs2.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/media/backend-fs2.c	Fri Nov 02 01:37:22 2018 +0000
@@ -48,10 +48,6 @@
 /** @copydoc _PurpleMediaBackendFs2Stream */
 typedef struct _PurpleMediaBackendFs2Stream PurpleMediaBackendFs2Stream;
 
-#define PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj) \
-		(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
-		PURPLE_TYPE_MEDIA_BACKEND_FS2, PurpleMediaBackendFs2Private))
-
 static void purple_media_backend_iface_init(PurpleMediaBackendIface *iface);
 
 static gboolean
@@ -118,10 +114,6 @@
 	GObject parent;
 };
 
-G_DEFINE_TYPE_WITH_CODE(PurpleMediaBackendFs2, purple_media_backend_fs2,
-		G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(
-		PURPLE_TYPE_MEDIA_BACKEND, purple_media_backend_iface_init));
-
 struct _PurpleMediaBackendFs2Stream
 {
 	PurpleMediaBackendFs2Session *session;
@@ -181,6 +173,12 @@
 	PROP_MEDIA,
 };
 
+G_DEFINE_TYPE_WITH_CODE(PurpleMediaBackendFs2, purple_media_backend_fs2,
+		G_TYPE_OBJECT,
+		G_ADD_PRIVATE(PurpleMediaBackendFs2)
+		G_IMPLEMENT_INTERFACE(PURPLE_TYPE_MEDIA_BACKEND,
+				purple_media_backend_iface_init));
+
 static void
 purple_media_backend_fs2_init(PurpleMediaBackendFs2 *self)
 {
@@ -300,7 +298,8 @@
 purple_media_backend_fs2_dispose(GObject *obj)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj);
+			purple_media_backend_fs2_get_instance_private(
+					PURPLE_MEDIA_BACKEND_FS2(obj));
 	GList *iter = NULL;
 
 	purple_debug_info("backend-fs2", "purple_media_backend_fs2_dispose\n");
@@ -397,7 +396,8 @@
 purple_media_backend_fs2_finalize(GObject *obj)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj);
+			purple_media_backend_fs2_get_instance_private(
+					PURPLE_MEDIA_BACKEND_FS2(obj));
 
 	purple_debug_info("backend-fs2", "purple_media_backend_fs2_finalize\n");
 
@@ -432,7 +432,8 @@
 	PurpleMediaBackendFs2Private *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(object));
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(object);
+	priv = purple_media_backend_fs2_get_instance_private(
+			PURPLE_MEDIA_BACKEND_FS2(object));
 
 	switch (prop_id) {
 		case PROP_CONFERENCE_TYPE:
@@ -469,7 +470,8 @@
 	PurpleMediaBackendFs2Private *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(object));
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(object);
+	priv = purple_media_backend_fs2_get_instance_private(
+			PURPLE_MEDIA_BACKEND_FS2(object));
 
 	switch (prop_id) {
 		case PROP_CONFERENCE_TYPE:
@@ -501,8 +503,6 @@
 			"conference-type");
 	g_object_class_override_property(gobject_class, PROP_MEDIA, "media");
 
-	g_type_class_add_private(klass, sizeof(PurpleMediaBackendFs2Private));
-
 	/* VA-API elements aren't well supported in Farstream. Ignore them. */
 	features = gst_registry_get_feature_list_by_plugin(gst_registry_get(),
 			"vaapi");
@@ -798,7 +798,7 @@
 
 	g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), NULL);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(self);
 
 	if (priv->sessions != NULL)
 		session = g_hash_table_lookup(priv->sessions, sess_id);
@@ -814,7 +814,7 @@
 
 	g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), NULL);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(self);
 
 	if (priv->participants != NULL)
 		participant = g_hash_table_lookup(priv->participants, name);
@@ -831,7 +831,7 @@
 
 	g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), NULL);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(self);
 	streams = priv->streams;
 
 	for (; streams; streams = g_list_next(streams)) {
@@ -853,7 +853,7 @@
 
 	g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), NULL);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(self);
 	streams = priv->streams;
 
 	for (; streams; streams = g_list_next(streams)) {
@@ -875,7 +875,7 @@
 get_session_from_fs_stream(PurpleMediaBackendFs2 *self, FsStream *stream)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	FsSession *fssession;
 	GList *values;
 
@@ -933,7 +933,7 @@
 		PurpleMediaBackendFs2 *self)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg));
 	static guint level_id = 0;
 	const GstStructure *structure = gst_message_get_structure(msg);
@@ -1232,7 +1232,7 @@
 		PurpleMediaBackendFs2 *self)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(msg));
 	GstElement *lastElement = NULL;
 	GList *sessions;
@@ -1316,7 +1316,8 @@
 {
 	if (state == PURPLE_MEDIA_STATE_END) {
 		PurpleMediaBackendFs2Private *priv =
-				PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+				purple_media_backend_fs2_get_instance_private(
+						self);
 
 		if (sid && name) {
 			PurpleMediaBackendFs2Stream *stream = get_stream(self, sid, name);
@@ -1394,7 +1395,8 @@
 	} else if (local == TRUE && (type == PURPLE_MEDIA_INFO_MUTE ||
 			type == PURPLE_MEDIA_INFO_UNMUTE)) {
 		PurpleMediaBackendFs2Private *priv =
-				PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+				purple_media_backend_fs2_get_instance_private(
+						self);
 		gboolean active = (type == PURPLE_MEDIA_INFO_MUTE);
 		GList *sessions;
 
@@ -1458,7 +1460,7 @@
 init_conference(PurpleMediaBackendFs2 *self)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	GstElement *pipeline;
 	GstBus *bus;
 	gchar *name;
@@ -1546,7 +1548,7 @@
 		PurpleMediaSessionType type)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	PurpleMediaBackendFs2Session *session;
 	PurpleMediaSessionType session_type;
 	FsMediaType media_type = session_type_to_fs_media_type(type);
@@ -1656,7 +1658,7 @@
 		const gchar *transmitter)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	PurpleMediaBackendFs2Session *session;
 	GError *err = NULL;
 	GList *codec_conf = NULL;
@@ -1756,7 +1758,7 @@
 create_participant(PurpleMediaBackendFs2 *self, const gchar *name)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	FsParticipant *participant;
 	GError *err = NULL;
 
@@ -1798,7 +1800,8 @@
 
 	g_return_val_if_fail(stream != NULL, FALSE);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(stream->session->backend);
+	priv = purple_media_backend_fs2_get_instance_private(
+			stream->session->backend);
 	stream->connected_cb_id = 0;
 
 	purple_media_manager_create_output_window(
@@ -1821,7 +1824,8 @@
 	g_return_if_fail(FS_IS_STREAM(fsstream));
 	g_return_if_fail(stream != NULL);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(stream->session->backend);
+	priv = purple_media_backend_fs2_get_instance_private(
+			stream->session->backend);
 
 	if (stream->src == NULL) {
 		GstElement *sink = NULL;
@@ -1927,7 +1931,7 @@
 		guint num_params, GParameter *params)
 {
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+			purple_media_backend_fs2_get_instance_private(self);
 	GError *err = NULL;
 	FsStream *fsstream = NULL;
 	const gchar *stun_ip = purple_network_get_stun_ip();
@@ -2152,7 +2156,7 @@
 {
 	PurpleMediaBackendFs2 *backend = PURPLE_MEDIA_BACKEND_FS2(self);
 	PurpleMediaBackendFs2Private *priv =
-			PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(backend);
+			purple_media_backend_fs2_get_instance_private(backend);
 	PurpleMediaBackendFs2Stream *stream;
 
 	if (priv->conference == NULL && !init_conference(backend)) {
@@ -2209,7 +2213,8 @@
 
 	g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self));
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(
+			PURPLE_MEDIA_BACKEND_FS2(self));
 	stream = get_stream(PURPLE_MEDIA_BACKEND_FS2(self),
 			sess_id, participant);
 
@@ -2253,7 +2258,8 @@
 
 	g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), FALSE);
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(
+			PURPLE_MEDIA_BACKEND_FS2(self));
 
 	if (sess_id != NULL) {
 		PurpleMediaBackendFs2Session *session = get_session(
@@ -2540,7 +2546,8 @@
 
 	g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self));
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(
+			PURPLE_MEDIA_BACKEND_FS2(self));
 
 	if (priv->conference == NULL &&
 		!init_conference(PURPLE_MEDIA_BACKEND_FS2(self))) {
@@ -2672,7 +2679,7 @@
 
 	g_return_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self));
 
-	priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+	priv = purple_media_backend_fs2_get_instance_private(self);
 
 	purple_prefs_set_int("/purple/media/audio/volume/input", level);
 
--- a/libpurple/media/candidate.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/media/candidate.c	Fri Nov 02 01:37:22 2018 +0000
@@ -26,12 +26,6 @@
 /** @copydoc _PurpleMediaCandidatePrivate */
 typedef struct _PurpleMediaCandidatePrivate PurpleMediaCandidatePrivate;
 
-#define PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(obj) \
-		(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
-		PURPLE_TYPE_MEDIA_CANDIDATE, \
-		PurpleMediaCandidatePrivate))
-
-
 struct _PurpleMediaCandidateClass
 {
 	GObjectClass parent_class;
@@ -42,8 +36,6 @@
 	GObject parent;
 };
 
-G_DEFINE_TYPE(PurpleMediaCandidate, purple_media_candidate, G_TYPE_OBJECT);
-
 struct _PurpleMediaCandidatePrivate
 {
 	gchar *foundation;
@@ -76,11 +68,14 @@
 	PROP_TTL,
 };
 
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleMediaCandidate, purple_media_candidate,
+		G_TYPE_OBJECT);
+
 static void
 purple_media_candidate_init(PurpleMediaCandidate *info)
 {
 	PurpleMediaCandidatePrivate *priv =
-			PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(info);
+			purple_media_candidate_get_instance_private(info);
 	priv->foundation = NULL;
 	priv->component_id = 0;
 	priv->ip = NULL;
@@ -98,13 +93,16 @@
 purple_media_candidate_finalize(GObject *info)
 {
 	PurpleMediaCandidatePrivate *priv =
-			PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(info);
+			purple_media_candidate_get_instance_private(
+					PURPLE_MEDIA_CANDIDATE(info));
 
 	g_free(priv->foundation);
 	g_free(priv->ip);
 	g_free(priv->base_ip);
 	g_free(priv->username);
 	g_free(priv->password);
+
+	G_OBJECT_CLASS(purple_media_candidate_parent_class)->finalize(info);
 }
 
 static void
@@ -114,7 +112,8 @@
 	PurpleMediaCandidatePrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_CANDIDATE(object));
 
-	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(object);
+	priv = purple_media_candidate_get_instance_private(
+			PURPLE_MEDIA_CANDIDATE(object));
 
 	switch (prop_id) {
 		case PROP_FOUNDATION:
@@ -172,7 +171,8 @@
 	PurpleMediaCandidatePrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_CANDIDATE(object));
 
-	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(object);
+	priv = purple_media_candidate_get_instance_private(
+			PURPLE_MEDIA_CANDIDATE(object));
 
 	switch (prop_id) {
 		case PROP_FOUNDATION:
@@ -312,8 +312,6 @@
 			"The TTL of the candidate.",
 			0, G_MAXUINT, 0,
 			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-	g_type_class_add_private(klass, sizeof(PurpleMediaCandidatePrivate));
 }
 
 PurpleMediaCandidate *
@@ -340,7 +338,7 @@
 	if (candidate == NULL)
 		return NULL;
 
-	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(candidate);
+	priv = purple_media_candidate_get_instance_private(candidate);
 
 	new_candidate = purple_media_candidate_new(priv->foundation,
 			priv->component_id, priv->type, priv->proto,
--- a/libpurple/media/codec.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/media/codec.c	Fri Nov 02 01:37:22 2018 +0000
@@ -28,10 +28,6 @@
 /** @copydoc _PurpleMediaCodecPrivate */
 typedef struct _PurpleMediaCodecPrivate PurpleMediaCodecPrivate;
 
-#define PURPLE_MEDIA_CODEC_GET_PRIVATE(obj) \
-		(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
-		PURPLE_TYPE_MEDIA_CODEC, PurpleMediaCodecPrivate))
-
 struct _PurpleMediaCodecClass
 {
 	GObjectClass parent_class;
@@ -42,8 +38,6 @@
 	GObject parent;
 };
 
-G_DEFINE_TYPE(PurpleMediaCodec, purple_media_codec, G_TYPE_OBJECT);
-
 struct _PurpleMediaCodecPrivate
 {
 	gint id;
@@ -67,11 +61,13 @@
 
 static GParamSpec *properties[PROP_LAST];
 
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleMediaCodec, purple_media_codec, G_TYPE_OBJECT);
+
 static void
 purple_media_codec_init(PurpleMediaCodec *info)
 {
 	PurpleMediaCodecPrivate *priv =
-			PURPLE_MEDIA_CODEC_GET_PRIVATE(info);
+			purple_media_codec_get_instance_private(info);
 	priv->encoding_name = NULL;
 	priv->optional_params = NULL;
 }
@@ -80,7 +76,8 @@
 purple_media_codec_finalize(GObject *info)
 {
 	PurpleMediaCodecPrivate *priv =
-			PURPLE_MEDIA_CODEC_GET_PRIVATE(info);
+			purple_media_codec_get_instance_private(
+					PURPLE_MEDIA_CODEC(info));
 	g_free(priv->encoding_name);
 	for (; priv->optional_params; priv->optional_params =
 			g_list_delete_link(priv->optional_params, priv->optional_params)) {
@@ -89,6 +86,8 @@
 		g_free(param->value);
 		g_free(param);
 	}
+
+	G_OBJECT_CLASS(purple_media_codec_parent_class)->finalize(info);
 }
 
 static void
@@ -98,7 +97,8 @@
 	PurpleMediaCodecPrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(object);
+	priv = purple_media_codec_get_instance_private(
+			PURPLE_MEDIA_CODEC(object));
 
 	switch (prop_id) {
 		case PROP_ID:
@@ -134,7 +134,8 @@
 	PurpleMediaCodecPrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(object);
+	priv = purple_media_codec_get_instance_private(
+			PURPLE_MEDIA_CODEC(object));
 
 	switch (prop_id) {
 		case PROP_ID:
@@ -171,8 +172,6 @@
 	gobject_class->set_property = purple_media_codec_set_property;
 	gobject_class->get_property = purple_media_codec_get_property;
 
-	g_type_class_add_private(klass, sizeof(PurpleMediaCodecPrivate));
-
 	properties[PROP_ID] = g_param_spec_uint("id",
 			"ID",
 			"The numeric identifier of the codec.",
@@ -283,7 +282,7 @@
 	g_return_if_fail(codec != NULL);
 	g_return_if_fail(name != NULL && value != NULL);
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+	priv = purple_media_codec_get_instance_private(codec);
 
 	new_param = g_new0(PurpleKeyValuePair, 1);
 	new_param->key = g_strdup(name);
@@ -302,7 +301,7 @@
 
 	g_return_if_fail(codec != NULL && param != NULL);
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+	priv = purple_media_codec_get_instance_private(codec);
 
 	g_free(param->key);
 	g_free(param->value);
@@ -324,7 +323,7 @@
 	g_return_val_if_fail(codec != NULL, NULL);
 	g_return_val_if_fail(name != NULL, NULL);
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+	priv = purple_media_codec_get_instance_private(codec);
 
 	for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
 		PurpleKeyValuePair *param = iter->data;
@@ -347,7 +346,7 @@
 	if (codec == NULL)
 		return NULL;
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+	priv = purple_media_codec_get_instance_private(codec);
 
 	new_codec = purple_media_codec_new(priv->id, priv->encoding_name,
 			priv->media_type, priv->clock_rate);
@@ -387,7 +386,7 @@
 }
 
 gchar *
-purple_media_codec_to_string(const PurpleMediaCodec *codec)
+purple_media_codec_to_string(PurpleMediaCodec *codec)
 {
 	PurpleMediaCodecPrivate *priv;
 	GString *string = NULL;
@@ -398,7 +397,7 @@
 	if (codec == NULL)
 		return g_strdup("(NULL)");
 
-	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+	priv = purple_media_codec_get_instance_private(codec);
 
 	string = g_string_new("");
 
--- a/libpurple/media/codec.h	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/media/codec.h	Fri Nov 02 01:37:22 2018 +0000
@@ -198,7 +198,7 @@
  *
  * Returns: The new string representation.
  */
-gchar *purple_media_codec_to_string(const PurpleMediaCodec *codec);
+gchar *purple_media_codec_to_string(PurpleMediaCodec *codec);
 
 G_END_DECLS
 
--- a/libpurple/mediamanager.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/libpurple/mediamanager.c	Fri Nov 02 01:37:22 2018 +0000
@@ -113,12 +113,7 @@
 } 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))
-
 #ifdef USE_VV
-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);
@@ -126,9 +121,6 @@
 static void purple_media_manager_init_device_monitor(PurpleMediaManager *manager);
 static void purple_media_manager_register_static_elements(PurpleMediaManager *manager);
 
-static GObjectClass *parent_class = NULL;
-
-
 
 enum {
 	INIT_MEDIA,
@@ -138,41 +130,22 @@
 	LAST_SIGNAL
 };
 static guint purple_media_manager_signals[LAST_SIGNAL] = {0};
-#endif
-
+
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleMediaManager, purple_media_manager,
+		G_TYPE_OBJECT);
+#else
 GType
 purple_media_manager_get_type()
 {
-#ifdef USE_VV
-	static GType type = 0;
-
-	if (type == 0) {
-		static const GTypeInfo info = {
-			sizeof(PurpleMediaManagerClass),
-			NULL,
-			NULL,
-			(GClassInitFunc) purple_media_manager_class_init,
-			NULL,
-			NULL,
-			sizeof(PurpleMediaManager),
-			0,
-			(GInstanceInitFunc) purple_media_manager_init,
-			NULL
-		};
-		type = g_type_register_static(G_TYPE_OBJECT, "PurpleMediaManager", &info, 0);
-	}
-	return type;
-#else
 	return G_TYPE_NONE;
-#endif
 }
+#endif /* USE_VV */
 
 #ifdef USE_VV
 static void
 purple_media_manager_class_init (PurpleMediaManagerClass *klass)
 {
 	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
 
 	gobject_class->finalize = purple_media_manager_finalize;
 
@@ -204,8 +177,6 @@
 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
 			0, NULL, NULL, NULL,
 			G_TYPE_NONE, 0);
-
-	g_type_class_add_private(klass, sizeof(PurpleMediaManagerPrivate));
 }
 
 static void
@@ -213,7 +184,7 @@
 {
 	GError *error;
 
-	media->priv = PURPLE_MEDIA_MANAGER_GET_PRIVATE(media);
+	media->priv = purple_media_manager_get_instance_private(media);
 	media->priv->medias = NULL;
 	media->priv->private_medias = NULL;
 	media->priv->next_output_window_id = 1;
@@ -245,7 +216,10 @@
 static void
 purple_media_manager_finalize (GObject *media)
 {
-	PurpleMediaManagerPrivate *priv = PURPLE_MEDIA_MANAGER_GET_PRIVATE(media);
+	PurpleMediaManagerPrivate *priv =
+			purple_media_manager_get_instance_private(
+					PURPLE_MEDIA_MANAGER(media));
+
 	for (; priv->medias; priv->medias =
 			g_list_delete_link(priv->medias, priv->medias)) {
 		g_object_unref(priv->medias->data);
@@ -273,7 +247,7 @@
 	}
 #endif /* GST_CHECK_VERSION(1, 4, 0) */
 
-	parent_class->finalize(media);
+	G_OBJECT_CLASS(purple_media_manager_parent_class)->finalize(media);
 }
 #endif
 
@@ -2409,11 +2383,14 @@
 	PROP_CREATE_CB,
 };
 
+G_DEFINE_TYPE_WITH_PRIVATE(PurpleMediaElementInfo,
+		purple_media_element_info, G_TYPE_OBJECT);
+
 static void
 purple_media_element_info_init(PurpleMediaElementInfo *info)
 {
 	PurpleMediaElementInfoPrivate *priv =
-			PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(info);
+			purple_media_element_info_get_instance_private(info);
 	priv->id = NULL;
 	priv->name = NULL;
 	priv->type = PURPLE_MEDIA_ELEMENT_NONE;
@@ -2424,9 +2401,12 @@
 purple_media_element_info_finalize(GObject *info)
 {
 	PurpleMediaElementInfoPrivate *priv =
-			PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(info);
+			purple_media_element_info_get_instance_private(
+					PURPLE_MEDIA_ELEMENT_INFO(info));
 	g_free(priv->id);
 	g_free(priv->name);
+
+	G_OBJECT_CLASS(purple_media_element_info_parent_class)->finalize(info);
 }
 
 static void
@@ -2436,7 +2416,8 @@
 	PurpleMediaElementInfoPrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_ELEMENT_INFO(object));
 
-	priv = PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(object);
+	priv = purple_media_element_info_get_instance_private(
+			PURPLE_MEDIA_ELEMENT_INFO(object));
 
 	switch (prop_id) {
 		case PROP_ID:
@@ -2468,7 +2449,8 @@
 	PurpleMediaElementInfoPrivate *priv;
 	g_return_if_fail(PURPLE_IS_MEDIA_ELEMENT_INFO(object));
 
-	priv = PURPLE_MEDIA_ELEMENT_INFO_GET_PRIVATE(object);
+	priv = purple_media_element_info_get_instance_private(
+			PURPLE_MEDIA_ELEMENT_INFO(object));
 
 	switch (prop_id) {
 		case PROP_ID:
@@ -2530,13 +2512,8 @@
 			"The function called to create this element.",
 			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
 			G_PARAM_STATIC_STRINGS));
-
-	g_type_class_add_private(klass, sizeof(PurpleMediaElementInfoPrivate));
 }
 
-G_DEFINE_TYPE(PurpleMediaElementInfo,
-		purple_media_element_info, G_TYPE_OBJECT);
-
 gchar *
 purple_media_element_info_get_id(PurpleMediaElementInfo *info)
 {
--- a/pidgin/libpidgin.c	Thu Nov 01 17:28:46 2018 -0500
+++ b/pidgin/libpidgin.c	Fri Nov 02 01:37:22 2018 +0000
@@ -27,7 +27,6 @@
 #include "account.h"
 #include "conversation.h"
 #include "core.h"
-#include "dbus-maybe.h"
 #include "debug.h"
 #include "glibcompat.h"
 #include "log.h"
@@ -124,6 +123,8 @@
 #ifndef _WIN32
 static char *segfault_message;
 
+static guint signal_channel_watcher;
+
 static int signal_sockets[2];
 
 static void sighandler(int sig);
@@ -336,12 +337,40 @@
 	return &core_ops;
 }
 
+static gint
+pidgin_handle_local_options_cb(GApplication *app, GVariantDict *options,
+		gpointer user_data)
+{
+#if !GLIB_CHECK_VERSION(2, 48, 0)
+	gchar *app_id = NULL;
+#endif
+
+	if (g_variant_dict_contains(options, "version")) {
+		printf("%s %s (libpurple %s)\n", PIDGIN_NAME, DISPLAY_VERSION,
+		                                 purple_core_get_version());
+		return 0;
+	}
+
+#if !GLIB_CHECK_VERSION(2, 48, 0)
+	if (g_variant_dict_lookup(options, "gapplication-app-id",
+			"s", &app_id)) {
+		g_variant_dict_remove(options, "gapplication-app-id");
+		g_application_set_application_id(app, app_id);
+		g_free(app_id);
+	}
+#endif
+
+	return -1;
+}
+
 static void
 pidgin_activate_cb(GApplication *application, gpointer user_data)
 {
 	purple_blist_set_visible(TRUE);
 }
 
+static gchar *opt_config_dir_arg = NULL;
+static gboolean opt_nologin = FALSE;
 static gboolean opt_login = FALSE;
 static gchar *opt_login_arg = NULL;
 
@@ -357,77 +386,47 @@
 	return TRUE;
 }
 
-int pidgin_start(int argc, char *argv[])
+static GOptionEntry option_entries[] = {
+#if !GLIB_CHECK_VERSION(2, 48, 0)
+	/* Support G_APPLICATION_CAN_OVERRIDE_APP_ID functionality
+	 * even though we don't depend on version 2.48 yet
+	 */
+	{"gapplication-app-id", '\0', 0, G_OPTION_ARG_STRING, NULL,
+		N_("Override the application's ID") },
+#endif
+	{"config", 'c', 0,
+		G_OPTION_ARG_FILENAME, &opt_config_dir_arg,
+		N_("use DIR for config files"), N_("DIR")},
+	{"login", 'l', G_OPTION_FLAG_OPTIONAL_ARG,
+		G_OPTION_ARG_CALLBACK, &login_opt_arg_func,
+		N_("enable specified account(s) (optional argument NAME\n"
+		  "                            "
+		  "specifies account(s) to use, separated by commas.\n"
+		  "                            "
+		  "Without this only the first account will be enabled)"),
+		N_("[NAME]")},
+	{"nologin", 'n', 0,
+		G_OPTION_ARG_NONE, &opt_nologin,
+		N_("don't automatically login"), NULL},
+	{"version", 'v', 0,
+		G_OPTION_ARG_NONE, NULL,
+		N_("display the current version and exit"), NULL},
+	{NULL}
+};
+
+#ifndef _WIN32
+static void
+pidgin_setup_error_handler(void)
 {
-	GApplication *app;
-	gboolean opt_nologin = FALSE;
-	gboolean opt_version = FALSE;
-	gboolean opt_si = TRUE;     /* Check for single instance? */
-	char *opt_config_dir_arg = NULL;
-	char *search_path;
-	GtkCssProvider *provider;
-	GdkScreen *screen;
-	GList *accounts;
-#ifndef _WIN32
 	int sig_indx;	/* for setting up signal catching */
 	sigset_t sigset;
 	char errmsg[BUFSIZ];
 	GIOChannel *signal_channel;
 	GIOStatus signal_status;
-	guint signal_channel_watcher;
 #ifndef DEBUG
 	char *segfault_message_tmp;
-#endif /* DEBUG */
-#endif /* !_WIN32 */
-	GOptionContext *context;
-	gchar *summary;
-	gchar **args;
-	gboolean gui_check;
-	GList *active_accounts;
-	GStatBuf st;
 	GError *error = NULL;
-	int ret;
 
-	GOptionEntry option_entries[] = {
-		{"config", 'c', 0,
-			G_OPTION_ARG_FILENAME, &opt_config_dir_arg,
-			_("use DIR for config files"), _("DIR")},
-		{"login", 'l', G_OPTION_FLAG_OPTIONAL_ARG,
-			G_OPTION_ARG_CALLBACK, &login_opt_arg_func,
-			_("enable specified account(s) (optional argument NAME\n"
-			  "                            "
-			  "specifies account(s) to use, separated by commas.\n"
-			  "                            "
-			  "Without this only the first account will be enabled)"),
-			_("[NAME]")},
-		{"multiple", 'm', G_OPTION_FLAG_REVERSE,
-			G_OPTION_ARG_NONE,  &opt_si,
-			_("allow multiple instances"), NULL},
-		{"nologin", 'n', 0,
-			G_OPTION_ARG_NONE, &opt_nologin,
-			_("don't automatically login"), NULL},
-		{"version", 'v', 0,
-			G_OPTION_ARG_NONE, &opt_version,
-			_("display the current version and exit"), NULL},
-		{NULL}
-	};
-
-#ifdef DEBUG
-	purple_debug_set_enabled(TRUE);
-#endif
-
-#ifdef ENABLE_NLS
-	bindtextdomain(PACKAGE, PURPLE_LOCALEDIR);
-	bind_textdomain_codeset(PACKAGE, "UTF-8");
-	textdomain(PACKAGE);
-#endif
-
-	/* Locale initialization is not complete here.  See gtk_init_check() */
-	setlocale(LC_ALL, "");
-
-#ifndef _WIN32
-
-#ifndef DEBUG
 		/* We translate this here in case the crash breaks gettext. */
 		segfault_message_tmp = g_strdup_printf(_(
 			"%s %s has segfaulted and attempted to dump a core file.\n"
@@ -526,51 +525,20 @@
 		snprintf(errmsg, sizeof(errmsg), "Warning: couldn't unblock signals");
 		perror(errmsg);
 	}
+}
 #endif /* !_WIN32 */
 
-	context = g_option_context_new(NULL);
-
-	summary = g_strdup_printf("%s %s", PIDGIN_NAME, DISPLAY_VERSION);
-	g_option_context_set_summary(context, summary);
-	g_free(summary);
-
-	g_option_context_add_main_entries(context, option_entries, PACKAGE);
-	g_option_context_add_group(context, purple_get_option_group());
-#ifdef PURPLE_PLUGINS
-	g_option_context_add_group(context, gplugin_get_option_group());
-#endif
-	g_option_context_add_group(context, gtk_get_option_group(TRUE));
-
-#ifdef G_OS_WIN32
-	/* Handle Unicode filenames on Windows. See GOptionContext docs. */
-	args = g_win32_get_command_line();
-#else
-	args = g_strdupv(argv);
-#endif
-
-	if (!g_option_context_parse_strv(context, &args, &error)) {
-		g_strfreev(args);
-		g_printerr(_("%s %s: %s\nTry `%s -h' for more information.\n"),
-				PIDGIN_NAME, DISPLAY_VERSION, error->message,
-				argv[0]);
-		g_clear_error(&error);
-#ifndef _WIN32
-		g_free(segfault_message);
-#endif
-		return 1;
-	}
-
-	g_strfreev(args);
-
-	/* show version message */
-	if (opt_version) {
-		printf("%s %s (libpurple %s)\n", PIDGIN_NAME, DISPLAY_VERSION,
-		                                 purple_core_get_version());
-#ifndef _WIN32
-		g_free(segfault_message);
-#endif
-		return 0;
-	}
+static void
+pidgin_startup_cb(GApplication *app, gpointer user_data)
+{
+	char *search_path;
+	GtkCssProvider *provider;
+	GdkScreen *screen;
+	GList *accounts;
+	gboolean gui_check;
+	GList *active_accounts;
+	GStatBuf st;
+	GError *error = NULL;
 
 	/* set a user-specified config directory */
 	if (opt_config_dir_arg != NULL) {
@@ -586,31 +554,6 @@
 		}
 	}
 
-	/*
-	 * We're done piddling around with command line arguments.
-	 * Fire up this baby.
-	 */
-
-	app = G_APPLICATION(gtk_application_new("im.pidgin.Pidgin",
-				G_APPLICATION_NON_UNIQUE));
-
-	g_object_set(app, "register-session", TRUE, NULL);
-
-	g_signal_connect(app, "activate",
-			G_CALLBACK(pidgin_activate_cb), NULL);
-
-	if (!g_application_register(app, NULL, &error)) {
-		purple_debug_error("gtk",
-				"Unable to register GApplication: %s\n",
-				error->message);
-		g_clear_error(&error);
-		g_object_unref(app);
-#ifndef _WIN32
-		g_free(segfault_message);
-#endif
-		return 1;
-	}
-
 	search_path = g_build_filename(purple_user_dir(), "gtk-3.0.css", NULL);
 
 	provider = gtk_css_provider_new();
@@ -662,25 +605,6 @@
 
 	purple_plugins_refresh();
 
-	if (opt_si && !purple_core_ensure_single_instance()) {
-#ifdef HAVE_DBUS
-		DBusConnection *conn = purple_dbus_get_connection();
-		DBusMessage *message = dbus_message_new_method_call(PURPLE_DBUS_SERVICE, PURPLE_DBUS_PATH,
-				PURPLE_DBUS_INTERFACE, "PurpleBlistSetVisible");
-		gboolean tr = TRUE;
-		dbus_message_append_args(message, DBUS_TYPE_INT32, &tr, DBUS_TYPE_INVALID);
-		dbus_connection_send_with_reply_and_block(conn, message, -1, NULL);
-		dbus_message_unref(message);
-#endif
-		gdk_notify_startup_complete();
-		purple_core_quit();
-		g_printerr(_("Exiting because another libpurple client is already running.\n"));
-#ifndef _WIN32
-		g_free(segfault_message);
-#endif
-		return 0;
-	}
-
 	/* load plugins we had when we quit */
 	purple_plugins_load_saved(PIDGIN_PREFS_ROOT "/plugins/loaded");
 
@@ -752,8 +676,59 @@
 
 	/* TODO: Use GtkApplicationWindow or add a window instead */
 	g_application_hold(app);
+}
 
-	ret = g_application_run(app, 0, NULL);
+int pidgin_start(int argc, char *argv[])
+{
+	GApplication *app;
+	gchar *summary;
+	int ret;
+
+#ifdef DEBUG
+	purple_debug_set_enabled(TRUE);
+#endif
+
+#ifdef ENABLE_NLS
+	bindtextdomain(PACKAGE, PURPLE_LOCALEDIR);
+	bind_textdomain_codeset(PACKAGE, "UTF-8");
+	textdomain(PACKAGE);
+#endif
+
+	/* Locale initialization is not complete here.  See gtk_init_check() */
+	setlocale(LC_ALL, "");
+
+#ifndef _WIN32
+	pidgin_setup_error_handler();
+#endif
+
+	app = G_APPLICATION(gtk_application_new("im.pidgin.Pidgin",
+#if GLIB_CHECK_VERSION(2, 48, 0)
+				G_APPLICATION_CAN_OVERRIDE_APP_ID
+#else
+				G_APPLICATION_FLAGS_NONE
+#endif
+				));
+
+	summary = g_strdup_printf("%s %s", PIDGIN_NAME, DISPLAY_VERSION);
+	g_application_set_option_context_summary(app, summary);
+	g_free(summary);
+
+	g_application_add_main_option_entries(app, option_entries);
+	g_application_add_option_group(app, purple_get_option_group());
+#ifdef PURPLE_PLUGINS
+	g_application_add_option_group(app, gplugin_get_option_group());
+#endif
+
+	g_object_set(app, "register-session", TRUE, NULL);
+
+	g_signal_connect(app, "handle-local-options",
+			G_CALLBACK(pidgin_handle_local_options_cb), NULL);
+	g_signal_connect(app, "startup",
+			G_CALLBACK(pidgin_startup_cb), NULL);
+	g_signal_connect(app, "activate",
+			G_CALLBACK(pidgin_activate_cb), NULL);
+
+	ret = g_application_run(app, argc, argv);
 
 	/* Make sure purple has quit in case something in GApplication
 	 * has caused g_application_run() to finish on its own. This can
@@ -763,6 +738,12 @@
 		purple_core_quit();
 	}
 
+	if (g_application_get_is_registered(app) &&
+			g_application_get_is_remote(app)) {
+		g_printerr(_("Exiting because another libpurple client is "
+				"already running.\n"));
+	}
+
 	/* Now that we're sure purple_core_quit() has been called,
 	 * this can be freed.
 	 */

mercurial