changeset 26406:2d332d327a0e

Hide and GObjectify PurpleMediaCandidate.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Fri, 03 Apr 2009 00:21:10 +0000
parents 70ab418e9d4f
children 440e999c27ca
files libpurple/media.c libpurple/media.h libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jingle/rtp.c
diffstat 4 files changed, 606 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/media.c	Thu Apr 02 04:23:14 2009 +0000
+++ b/libpurple/media.c	Fri Apr 03 00:21:10 2009 +0000
@@ -45,6 +45,10 @@
 typedef struct _PurpleMediaSession PurpleMediaSession;
 /** @copydoc _PurpleMediaStream */
 typedef struct _PurpleMediaStream PurpleMediaStream;
+/** @copydoc _PurpleMediaCandidateClass */
+typedef struct _PurpleMediaCandidateClass PurpleMediaCandidateClass;
+/** @copydoc _PurpleMediaCandidatePrivate */
+typedef struct _PurpleMediaCandidatePrivate PurpleMediaCandidatePrivate;
 /** @copydoc _PurpleMediaCodecClass */
 typedef struct _PurpleMediaCodecClass PurpleMediaCodecClass;
 /** @copydoc _PurpleMediaCodecPrivate */
@@ -119,6 +123,7 @@
 
 #ifdef USE_VV
 #define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
+#define PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_CANDIDATE, PurpleMediaCandidatePrivate))
 #define PURPLE_MEDIA_CODEC_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA_CODEC, PurpleMediaCodecPrivate))
 
 static void purple_media_class_init (PurpleMediaClass *klass);
@@ -575,79 +580,413 @@
 }
 #endif
 
+/*
+ * PurpleMediaCandidateType
+ */
+
+GType
+purple_media_candidate_type_get_type()
+{
+	static GType type = 0;
+	if (type == 0) {
+		static const GEnumValue values[] = {
+			{ PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
+					"PURPLE_MEDIA_CANDIDATE_TYPE_HOST",
+					"host" },
+			{ PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX,
+					"PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX",
+					"srflx" },
+			{ PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX,
+					"PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX",
+					"prflx" },
+			{ PURPLE_MEDIA_CANDIDATE_TYPE_RELAY,
+					"PPURPLE_MEDIA_CANDIDATE_TYPE_RELAY",
+					"relay" },
+			{ PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST,
+					"PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST",
+					"multicast" },
+			{ 0, NULL, NULL }
+		};
+		type = g_enum_register_static("PurpleMediaCandidateType",
+				values);
+	}
+	return type;
+}
+
+/*
+ * PurpleMediaNetworkProtocol
+ */
+
+GType
+purple_media_network_protocol_get_type()
+{
+	static GType type = 0;
+	if (type == 0) {
+		static const GEnumValue values[] = {
+			{ PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
+					"PURPLE_MEDIA_NETWORK_PROTOCOL_UDP",
+					"udp" },
+			{ PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
+					"PURPLE_MEDIA_NETWORK_PROTOCOL_TCP",
+					"tcp" },
+			{ 0, NULL, NULL }
+		};
+		type = g_enum_register_static("PurpleMediaNetworkProtocol",
+				values);
+	}
+	return type;
+}
+
+/*
+ * PurpleMediaCandidate
+ */
+
+struct _PurpleMediaCandidateClass
+{
+	GObjectClass parent_class;
+};
+
+struct _PurpleMediaCandidate
+{
+	GObject parent;
+};
+
+struct _PurpleMediaCandidatePrivate
+{
+	gchar *foundation;
+	guint component_id;
+	gchar *ip;
+	guint16 port;
+	gchar *base_ip;
+	guint16 base_port;
+	PurpleMediaNetworkProtocol proto;
+	guint32 priority;
+	PurpleMediaCandidateType type;
+	gchar *username;
+	gchar *password;
+	guint ttl;
+};
+
+enum {
+	PROP_CANDIDATE_0,
+	PROP_FOUNDATION,
+	PROP_COMPONENT_ID,
+	PROP_IP,
+	PROP_PORT,
+	PROP_BASE_IP,
+	PROP_BASE_PORT,
+	PROP_PROTOCOL,
+	PROP_PRIORITY,
+	PROP_TYPE,
+	PROP_USERNAME,
+	PROP_PASSWORD,
+	PROP_TTL,
+};
+
+static void
+purple_media_candidate_init(PurpleMediaCandidate *info)
+{
+	PurpleMediaCandidatePrivate *priv =
+			PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(info);
+	priv->foundation = NULL;
+	priv->component_id = 0;
+	priv->ip = NULL;
+	priv->port = 0;
+	priv->base_ip = NULL;
+	priv->proto = PURPLE_MEDIA_NETWORK_PROTOCOL_UDP;
+	priv->priority = 0;
+	priv->type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
+	priv->username = NULL;
+	priv->password = NULL;
+	priv->ttl = 0;
+}
+
+static void
+purple_media_candidate_finalize(GObject *info)
+{
+	PurpleMediaCandidatePrivate *priv =
+			PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(info);
+
+	g_free(priv->foundation);
+	g_free(priv->ip);
+	g_free(priv->base_ip);
+	g_free(priv->username);
+	g_free(priv->password);
+}
+
+static void
+purple_media_candidate_set_property (GObject *object, guint prop_id,
+		const GValue *value, GParamSpec *pspec)
+{
+	PurpleMediaCandidatePrivate *priv;
+	g_return_if_fail(PURPLE_IS_MEDIA_CANDIDATE(object));
+
+	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(object);
+
+	switch (prop_id) {
+		case PROP_FOUNDATION:
+			g_free(priv->foundation);
+			priv->foundation = g_value_dup_string(value);
+			break;
+		case PROP_COMPONENT_ID:
+			priv->component_id = g_value_get_uint(value);
+			break;
+		case PROP_IP:
+			g_free(priv->ip);
+			priv->ip = g_value_dup_string(value);
+			break;
+		case PROP_PORT:
+			priv->port = g_value_get_uint(value);
+			break;
+		case PROP_BASE_IP:
+			g_free(priv->base_ip);
+			priv->base_ip = g_value_dup_string(value);
+			break;
+		case PROP_BASE_PORT:
+			priv->base_port = g_value_get_uint(value);
+			break;
+		case PROP_PROTOCOL:
+			priv->proto = g_value_get_enum(value);
+			break;
+		case PROP_PRIORITY:
+			priv->priority = g_value_get_uint(value);
+			break;
+		case PROP_TYPE:
+			priv->type = g_value_get_enum(value);
+			break;
+		case PROP_USERNAME:
+			g_free(priv->username);
+			priv->username = g_value_dup_string(value);
+			break;
+		case PROP_PASSWORD:
+			g_free(priv->password);
+			priv->password = g_value_dup_string(value);
+			break;
+		case PROP_TTL:
+			priv->ttl = g_value_get_uint(value);
+			break;
+		default:	
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(
+					object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_media_candidate_get_property (GObject *object, guint prop_id,
+		GValue *value, GParamSpec *pspec)
+{
+	PurpleMediaCandidatePrivate *priv;
+	g_return_if_fail(PURPLE_IS_MEDIA_CANDIDATE(object));
+	
+	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(object);
+
+	switch (prop_id) {
+		case PROP_FOUNDATION:
+			g_value_set_string(value, priv->foundation);
+			break;
+		case PROP_COMPONENT_ID:
+			g_value_set_uint(value, priv->component_id);
+			break;
+		case PROP_IP:
+			g_value_set_string(value, priv->ip);
+			break;
+		case PROP_PORT:
+			g_value_set_uint(value, priv->port);
+			break;
+		case PROP_BASE_IP:
+			g_value_set_string(value, priv->base_ip);
+			break;
+		case PROP_BASE_PORT:
+			g_value_set_uint(value, priv->base_port);
+			break;
+		case PROP_PROTOCOL:
+			g_value_set_enum(value, priv->proto);
+			break;
+		case PROP_PRIORITY:
+			g_value_set_uint(value, priv->priority);
+			break;
+		case PROP_TYPE:
+			g_value_set_enum(value, priv->type);
+			break;
+		case PROP_USERNAME:
+			g_value_set_string(value, priv->username);
+			break;
+		case PROP_PASSWORD:
+			g_value_set_string(value, priv->password);
+			break;
+		case PROP_TTL:
+			g_value_set_uint(value, priv->ttl);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(
+					object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_media_candidate_class_init(PurpleMediaCandidateClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	
+	gobject_class->finalize = purple_media_candidate_finalize;
+	gobject_class->set_property = purple_media_candidate_set_property;
+	gobject_class->get_property = purple_media_candidate_get_property;
+
+	g_object_class_install_property(gobject_class, PROP_FOUNDATION,
+			g_param_spec_string("foundation",
+			"Foundation",
+			"The foundation of the candidate.",
+			NULL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_COMPONENT_ID,
+			g_param_spec_uint("component-id",
+			"Component ID",
+			"The component id of the candidate.",
+			0, G_MAXUINT, 0,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_IP,
+			g_param_spec_string("ip",
+			"IP Address",
+			"The IP address of the candidate.",
+			NULL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_PORT,
+			g_param_spec_uint("port",
+			"Port",
+			"The port of the candidate.",
+			0, G_MAXUINT16, 0,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_BASE_IP,
+			g_param_spec_string("base-ip",
+			"Base IP",
+			"The internal IP address of the candidate.",
+			NULL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_BASE_PORT,
+			g_param_spec_uint("base-port",
+			"Base Port",
+			"The internal port of the candidate.",
+			0, G_MAXUINT16, 0,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_PROTOCOL,
+			g_param_spec_enum("protocol",
+			"Protocol",
+			"The protocol of the candidate.",
+			PURPLE_TYPE_MEDIA_NETWORK_PROTOCOL,
+			PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_PRIORITY,
+			g_param_spec_uint("priority",
+			"Priority",
+			"The priority of the candidate.",
+			0, G_MAXUINT32, 0,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_TYPE,
+			g_param_spec_enum("type",
+			"Type",
+			"The type of the candidate.",
+			PURPLE_TYPE_MEDIA_CANDIDATE_TYPE,
+			PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_USERNAME,
+			g_param_spec_string("username",
+			"Username",
+			"The username used to connect to the candidate.",
+			NULL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_PASSWORD,
+			g_param_spec_string("password",
+			"Password",
+			"The password use to connect to the candidate.",
+			NULL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_TTL,
+			g_param_spec_uint("ttl",
+			"TTL",
+			"The TTL of the candidate.",
+			0, G_MAXUINT, 0,
+			G_PARAM_READWRITE));
+
+	g_type_class_add_private(klass, sizeof(PurpleMediaCandidatePrivate));
+}
+
+G_DEFINE_TYPE(PurpleMediaCandidate,
+		purple_media_candidate, G_TYPE_OBJECT);
+
 PurpleMediaCandidate *
 purple_media_candidate_new(const gchar *foundation, guint component_id,
 		PurpleMediaCandidateType type,
 		PurpleMediaNetworkProtocol proto,
 		const gchar *ip, guint port)
 {
-	PurpleMediaCandidate *candidate = g_new0(PurpleMediaCandidate, 1);
-	candidate->foundation = g_strdup(foundation);
-	candidate->component_id = component_id;
-	candidate->type = type;
-	candidate->proto = proto;
-	candidate->ip = g_strdup(ip);
-	candidate->port = port;
-	return candidate;
+	return g_object_new(PURPLE_TYPE_MEDIA_CANDIDATE,
+			"foundation", foundation,
+			"component-id", component_id,
+			"type", type,
+			"protocol", proto,
+			"ip", ip,
+			"port", port, NULL);
 }
 
 static PurpleMediaCandidate *
 purple_media_candidate_copy(PurpleMediaCandidate *candidate)
 {
+	PurpleMediaCandidatePrivate *priv;
 	PurpleMediaCandidate *new_candidate;
 
 	if (candidate == NULL)
 		return NULL;
 
-	new_candidate = g_new0(PurpleMediaCandidate, 1);
-	new_candidate->foundation = g_strdup(candidate->foundation);
-	new_candidate->component_id = candidate->component_id;
-	new_candidate->ip = g_strdup(candidate->ip);
-	new_candidate->port = candidate->port;
-	new_candidate->base_ip = g_strdup(candidate->base_ip);
-	new_candidate->base_port = candidate->base_port;
-	new_candidate->proto = candidate->proto;
-	new_candidate->priority = candidate->priority;
-	new_candidate->type = candidate->type;
-	new_candidate->username = g_strdup(candidate->username);
-	new_candidate->password = g_strdup(candidate->password);
-	new_candidate->ttl = candidate->ttl;
+	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(candidate);
+
+	new_candidate = purple_media_candidate_new(priv->foundation,
+			priv->component_id, priv->type, priv->proto,
+			priv->ip, priv->port);
+	g_object_set(new_candidate,
+			"base-ip", priv->base_ip,
+			"base-port", priv->base_port,
+			"priority", priv->priority,
+			"username", priv->username,
+			"password", priv->password,
+			"ttl", priv->ttl, NULL);
 	return new_candidate;
 }
 
-static void
-purple_media_candidate_free(PurpleMediaCandidate *candidate)
-{
-	if (candidate == NULL)
-		return;
-
-	g_free((gchar*)candidate->foundation);
-	g_free((gchar*)candidate->ip);
-	g_free((gchar*)candidate->base_ip);
-	g_free((gchar*)candidate->username);
-	g_free((gchar*)candidate->password);
-	g_free(candidate);
-}
-
 #ifdef USE_VV
 static FsCandidate *
 purple_media_candidate_to_fs(PurpleMediaCandidate *candidate)
 {
+	PurpleMediaCandidatePrivate *priv;
 	FsCandidate *fscandidate;
 
 	if (candidate == NULL)
 		return NULL;
 
-	fscandidate = fs_candidate_new(candidate->foundation,
-		candidate->component_id, candidate->type,
-		candidate->proto, candidate->ip, candidate->port);
-
-	fscandidate->base_ip = g_strdup(candidate->base_ip);
-	fscandidate->base_port = candidate->base_port;
-	fscandidate->priority = candidate->priority;
-	fscandidate->username = g_strdup(candidate->username);
-	fscandidate->password = g_strdup(candidate->password);
-	fscandidate->ttl = candidate->ttl;
+	priv = PURPLE_MEDIA_CANDIDATE_GET_PRIVATE(candidate);
+
+	fscandidate = fs_candidate_new(priv->foundation,
+			priv->component_id, priv->type,
+			priv->proto, priv->ip, priv->port);
+
+	fscandidate->base_ip = g_strdup(priv->base_ip);
+	fscandidate->base_port = priv->base_port;
+	fscandidate->priority = priv->priority;
+	fscandidate->username = g_strdup(priv->username);
+	fscandidate->password = g_strdup(priv->password);
+	fscandidate->ttl = priv->ttl;
 	return fscandidate;
 }
 
@@ -662,12 +1001,13 @@
 	candidate = purple_media_candidate_new(fscandidate->foundation,
 		fscandidate->component_id, fscandidate->type,
 		fscandidate->proto, fscandidate->ip, fscandidate->port);
-	candidate->base_ip = g_strdup(fscandidate->base_ip);
-	candidate->base_port = fscandidate->base_port;
-	candidate->priority = fscandidate->priority;
-	candidate->username = g_strdup(fscandidate->username);
-	candidate->password = g_strdup(fscandidate->password);
-	candidate->ttl = fscandidate->ttl;
+	g_object_set(candidate,
+			"base-ip", fscandidate->base_ip,
+			"base-port", fscandidate->base_port,
+			"priority", fscandidate->priority,
+			"username", fscandidate->username,
+			"password", fscandidate->password,
+			"ttl", fscandidate->ttl, NULL);
 	return candidate;
 }
 
@@ -708,9 +1048,8 @@
 	GList *new_list = NULL;
 
 	for (; candidates; candidates = g_list_next(candidates)) {
-		new_list = g_list_prepend(new_list, g_boxed_copy(
-				PURPLE_TYPE_MEDIA_CANDIDATE,
-				candidates->data));
+		new_list = g_list_prepend(new_list,
+				purple_media_candidate_copy(candidates->data));
 	}
 
 	new_list = g_list_reverse(new_list);
@@ -722,24 +1061,120 @@
 {
 	for (; candidates; candidates =
 			g_list_delete_link(candidates, candidates)) {
-		g_boxed_free(PURPLE_TYPE_MEDIA_CANDIDATE,
-				candidates->data);
+		g_object_unref(candidates->data);
 	}
 }
 
-GType
-purple_media_candidate_get_type()
+gchar *
+purple_media_candidate_get_foundation(PurpleMediaCandidate *candidate)
+{
+	gchar *foundation;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), NULL);
+	g_object_get(candidate, "foundation", &foundation, NULL);
+	return foundation;
+}
+
+guint
+purple_media_candidate_get_component_id(PurpleMediaCandidate *candidate)
+{
+	guint component_id;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), 0);
+	g_object_get(candidate, "component-id", &component_id, NULL);
+	return component_id;
+}
+
+gchar *
+purple_media_candidate_get_ip(PurpleMediaCandidate *candidate)
+{
+	gchar *ip;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), NULL);
+	g_object_get(candidate, "ip", &ip, NULL);
+	return ip;
+}
+
+guint16
+purple_media_candidate_get_port(PurpleMediaCandidate *candidate)
+{
+	guint port;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), 0);
+	g_object_get(candidate, "port", &port, NULL);
+	return port;
+}
+
+gchar *
+purple_media_candidate_get_base_ip(PurpleMediaCandidate *candidate)
+{
+	gchar *base_ip;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), NULL);
+	g_object_get(candidate, "base-ip", &base_ip, NULL);
+	return base_ip;
+}
+
+guint16
+purple_media_candidate_get_base_port(PurpleMediaCandidate *candidate)
 {
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleMediaCandidate",
-				(GBoxedCopyFunc)purple_media_candidate_copy,
-				(GBoxedFreeFunc)purple_media_candidate_free);
-	}
+	guint base_port;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), 0);
+	g_object_get(candidate, "base_port", &base_port, NULL);
+	return base_port;
+}
+
+PurpleMediaNetworkProtocol
+purple_media_candidate_get_protocol(PurpleMediaCandidate *candidate)
+{
+	PurpleMediaNetworkProtocol protocol;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate),
+			PURPLE_MEDIA_NETWORK_PROTOCOL_UDP);
+	g_object_get(candidate, "protocol", &protocol, NULL);
+	return protocol;
+}
+
+guint32
+purple_media_candidate_get_priority(PurpleMediaCandidate *candidate)
+{
+	guint priority;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), 0);
+	g_object_get(candidate, "priority", &priority, NULL);
+	return priority;
+}
+
+PurpleMediaCandidateType
+purple_media_candidate_get_candidate_type(PurpleMediaCandidate *candidate)
+{
+	PurpleMediaCandidateType type;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate),
+			PURPLE_MEDIA_CANDIDATE_TYPE_HOST);
+	g_object_get(candidate, "type", &type, NULL);
 	return type;
 }
 
+gchar *
+purple_media_candidate_get_username(PurpleMediaCandidate *candidate)
+{
+	gchar *username;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), NULL);
+	g_object_get(candidate, "username", &username, NULL);
+	return username;
+}
+
+gchar *
+purple_media_candidate_get_password(PurpleMediaCandidate *candidate)
+{
+	gchar *password;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), NULL);
+	g_object_get(candidate, "password", &password, NULL);
+	return password;
+}
+
+guint
+purple_media_candidate_get_ttl(PurpleMediaCandidate *candidate)
+{
+	guint ttl;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CANDIDATE(candidate), 0);
+	g_object_get(candidate, "ttl", &ttl, NULL);
+	return ttl;
+}
+
 #ifdef USE_VV
 static FsMediaType
 purple_media_to_fs_media_type(PurpleMediaSessionType type)
@@ -1746,7 +2181,7 @@
 	candidate = purple_media_candidate_from_fs(local_candidate);
 	g_signal_emit(session->media, purple_media_signals[NEW_CANDIDATE],
 		      0, session->id, name, candidate);
-	purple_media_candidate_free(candidate);
+	g_object_unref(candidate);
 
 	g_free(name);
 }
--- a/libpurple/media.h	Thu Apr 02 04:23:14 2009 +0000
+++ b/libpurple/media.h	Fri Apr 03 00:21:10 2009 +0000
@@ -35,6 +35,13 @@
 
 G_BEGIN_DECLS
 
+#define PURPLE_TYPE_MEDIA_CANDIDATE           (purple_media_candidate_get_type())
+#define PURPLE_MEDIA_CANDIDATE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_CANDIDATE, PurpleMediaCandidate))
+#define PURPLE_MEDIA_CANDIDATE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA_CANDIDATE, PurpleMediaCandidate))
+#define PURPLE_IS_MEDIA_CANDIDATE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MEDIA_CANDIDATE))
+#define PURPLE_IS_MEDIA_CANDIDATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_CANDIDATE))
+#define PURPLE_MEDIA_CANDIDATE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_CANDIDATE, PurpleMediaCandidate))
+
 #define PURPLE_TYPE_MEDIA_CODEC           (purple_media_codec_get_type())
 #define PURPLE_MEDIA_CODEC(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_CODEC, PurpleMediaCodec))
 #define PURPLE_MEDIA_CODEC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA_CODEC, PurpleMediaCodec))
@@ -44,13 +51,14 @@
 
 #define PURPLE_TYPE_MEDIA_SESSION_TYPE (purple_media_session_type_get_type())
 #define PURPLE_TYPE_MEDIA            (purple_media_get_type())
-#define PURPLE_TYPE_MEDIA_CANDIDATE  (purple_media_candidate_get_type())
 #define PURPLE_MEDIA(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA, PurpleMedia))
 #define PURPLE_MEDIA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA, PurpleMediaClass))
 #define PURPLE_IS_MEDIA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MEDIA))
 #define PURPLE_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA))
 #define PURPLE_MEDIA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA, PurpleMediaClass))
 
+#define PURPLE_TYPE_MEDIA_CANDIDATE_TYPE (purple_media_candidate_type_get_type())
+#define PURPLE_TYPE_MEDIA_NETWORK_PROTOCOL (purple_media_network_protocol_get_type())
 #define PURPLE_MEDIA_TYPE_STATE      (purple_media_state_changed_get_type())
 #define PURPLE_MEDIA_TYPE_INFO_TYPE	(purple_media_info_type_get_type())
 
@@ -125,22 +133,6 @@
 	PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
 } PurpleMediaNetworkProtocol;
 
-struct _PurpleMediaCandidate
-{
-	const gchar *foundation;
-	guint component_id;
-	const gchar *ip;
-	guint16 port;
-	const gchar *base_ip;
-	guint16 base_port;
-	PurpleMediaNetworkProtocol proto;
-	guint32 priority;
-	PurpleMediaCandidateType type;
-	const gchar *username;
-	const gchar *password;
-	guint ttl;
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -153,6 +145,20 @@
 GType purple_media_session_type_get_type(void);
 
 /**
+ * Gets the media candidate type's GType
+ *
+ * @return The media candidate type's GType.
+ */
+GType purple_media_candidate_type_get_type(void);
+
+/**
+ * Gets the media network protocol's GType
+ *
+ * @return The media network protocol's GType.
+ */
+GType purple_media_network_protocol_get_type(void);
+
+/**
  * Gets the media class's GType
  *
  * @return The media class's GType.
@@ -214,6 +220,21 @@
  */
 void purple_media_candidate_list_free(GList *candidates);
 
+gchar *purple_media_candidate_get_foundation(PurpleMediaCandidate *candidate);
+guint purple_media_candidate_get_component_id(PurpleMediaCandidate *candidate);
+gchar *purple_media_candidate_get_ip(PurpleMediaCandidate *candidate);
+guint16 purple_media_candidate_get_port(PurpleMediaCandidate *candidate);
+gchar *purple_media_candidate_get_base_ip(PurpleMediaCandidate *candidate);
+guint16 purple_media_candidate_get_base_port(PurpleMediaCandidate *candidate);
+PurpleMediaNetworkProtocol purple_media_candidate_get_protocol(
+		PurpleMediaCandidate *candidate);
+guint32 purple_media_candidate_get_priority(PurpleMediaCandidate *candidate);
+PurpleMediaCandidateType purple_media_candidate_get_candidate_type(
+		PurpleMediaCandidate *candidate);
+gchar *purple_media_candidate_get_username(PurpleMediaCandidate *candidate);
+gchar *purple_media_candidate_get_password(PurpleMediaCandidate *candidate);
+guint purple_media_candidate_get_ttl(PurpleMediaCandidate *candidate);
+
 /**
  * Gets the type of the media codec structure.
  *
--- a/libpurple/protocols/jabber/google.c	Thu Apr 02 04:23:14 2009 +0000
+++ b/libpurple/protocols/jabber/google.c	Fri Apr 03 00:21:10 2009 +0000
@@ -110,13 +110,14 @@
 
 	for (;candidates;candidates = candidates->next) {
 		JabberIq *iq;
-		char port[8];
-		char pref[8];
+		gchar *ip, *port, *pref, *username, *password;
+		PurpleMediaCandidateType type;
 		xmlnode *sess;
 		xmlnode *candidate;
 		transport = (PurpleMediaCandidate*)(candidates->data);
 
-		if (transport->component_id != PURPLE_MEDIA_COMPONENT_RTP)
+		if (purple_media_candidate_get_component_id(transport)
+				!= PURPLE_MEDIA_COMPONENT_RTP)
 			continue;
 
 		iq = jabber_iq_new(session->js, JABBER_IQ_SET);
@@ -126,35 +127,49 @@
 
 		candidate = xmlnode_new("candidate");
 
-		g_snprintf(port, sizeof(port), "%d", transport->port);
-		g_snprintf(pref, sizeof(pref), "%f",
-				transport->priority/1000.0);
+		ip = purple_media_candidate_get_ip(transport);
+		port = g_strdup_printf("%d",
+				purple_media_candidate_get_port(transport));
+		pref = g_strdup_printf("%f",
+				purple_media_candidate_get_priority(transport)
+				/1000.0);
+		username = purple_media_candidate_get_username(transport);
+		password = purple_media_candidate_get_password(transport);
+		type = purple_media_candidate_get_candidate_type(transport);
 
-		xmlnode_set_attrib(candidate, "address", transport->ip);
+		xmlnode_set_attrib(candidate, "address", ip);
 		xmlnode_set_attrib(candidate, "port", port);
 		xmlnode_set_attrib(candidate, "name", "rtp");
-		xmlnode_set_attrib(candidate, "username", transport->username);
+		xmlnode_set_attrib(candidate, "username", username);
 		/*
 		 * As of this writing, Farsight 2 in Google compatibility
 		 * mode doesn't provide a password. The Gmail client
 		 * requires this to be set.
 		 */
 		xmlnode_set_attrib(candidate, "password",
-				transport->password != NULL ?
-				transport->password : "");
+				password != NULL ? password : "");
 		xmlnode_set_attrib(candidate, "preference", pref);
-		xmlnode_set_attrib(candidate, "protocol", transport->proto ==
-				PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ? "udp" : "tcp");
-		xmlnode_set_attrib(candidate, "type", transport->type ==
+		xmlnode_set_attrib(candidate, "protocol",
+				purple_media_candidate_get_protocol(transport)
+				== PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
+				"udp" : "tcp");
+		xmlnode_set_attrib(candidate, "type", type ==
 				PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
-						      transport->type ==
+						      type ==
 				PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
-					       	      transport->type ==
-				PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" : NULL);
+					       	      type ==
+				PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
+				NULL);
 		xmlnode_set_attrib(candidate, "generation", "0");
 		xmlnode_set_attrib(candidate, "network", "0");
 		xmlnode_insert_child(sess, candidate);
 
+		g_free(ip);
+		g_free(port);
+		g_free(pref);
+		g_free(username);
+		g_free(password);
+
 		jabber_iq_send(iq);
 	}
 }
@@ -455,9 +470,8 @@
 							PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
 					xmlnode_get_attrib(cand, "address"),
 					atoi(xmlnode_get_attrib(cand, "port")));
-
-		info->username = g_strdup(xmlnode_get_attrib(cand, "username"));
-		info->password = g_strdup(xmlnode_get_attrib(cand, "password"));
+		g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
+				"password", xmlnode_get_attrib(cand, "password"), NULL);
 
 		list = g_list_append(list, info);
 	}
--- a/libpurple/protocols/jabber/jingle/rtp.c	Thu Apr 02 04:23:14 2009 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Fri Apr 03 00:21:10 2009 +0000
@@ -226,10 +226,12 @@
 		PurpleMediaCandidate *candidate)
 {
 	gchar *id = jabber_get_next_id(jingle_session_get_js(session));
+	gchar *ip = purple_media_candidate_get_ip(candidate);
 	JingleRawUdpCandidate *rawudp_candidate =
-			jingle_rawudp_candidate_new(id,
-			generation, candidate->component_id,
-			candidate->ip, candidate->port);
+			jingle_rawudp_candidate_new(id, generation,
+			purple_media_candidate_get_component_id(candidate),
+			ip, purple_media_candidate_get_port(candidate));
+	g_free(ip);
 	g_free(id);
 	return rawudp_candidate;
 }
@@ -239,17 +241,30 @@
 		PurpleMediaCandidate *candidate)
 {
 	gchar *id = jabber_get_next_id(jingle_session_get_js(session));
+	gchar *ip = purple_media_candidate_get_ip(candidate);
+	gchar *username = purple_media_candidate_get_username(candidate);
+	gchar *password = purple_media_candidate_get_password(candidate);
+	PurpleMediaCandidateType type =
+			purple_media_candidate_get_candidate_type(candidate);
+	
 	JingleIceUdpCandidate *iceudp_candidate = jingle_iceudp_candidate_new(
-			candidate->component_id, candidate->foundation,
-			generation, id, candidate->ip, 0,
-			candidate->port, candidate->priority, "udp",
-			candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "host" :
-			candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "srflx" :
-			candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX ? "prflx" :
-			candidate->type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" : "",
-			candidate->username, candidate->password);
-	iceudp_candidate->reladdr = g_strdup(candidate->base_ip);
-	iceudp_candidate->relport = candidate->base_port;
+			purple_media_candidate_get_component_id(candidate),
+			purple_media_candidate_get_foundation(candidate),
+			generation, id, ip, 0,
+			purple_media_candidate_get_port(candidate),
+			purple_media_candidate_get_priority(candidate), "udp",
+			type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "host" :
+			type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "srflx" :
+			type == PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX ? "prflx" :
+			type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
+			"", username, password);
+	iceudp_candidate->reladdr =
+			purple_media_candidate_get_base_ip(candidate);
+	iceudp_candidate->relport =
+			purple_media_candidate_get_base_port(candidate);
+	g_free(password);
+	g_free(username);
+	g_free(ip);
 	g_free(id);
 	return iceudp_candidate;
 }
@@ -321,11 +336,12 @@
 					PURPLE_MEDIA_CANDIDATE_TYPE_RELAY : 0,
 					PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
 					candidate->ip, candidate->port);
-			new_candidate->base_ip = g_strdup(candidate->reladdr);
-			new_candidate->base_port = candidate->relport;
-			new_candidate->username = g_strdup(candidate->username);
-			new_candidate->password = g_strdup(candidate->password);
-			new_candidate->priority = candidate->priority;
+			g_object_set(new_candidate,
+					"base-ip", candidate->reladdr,
+					"base-port", candidate->relport,
+					"username", candidate->username,
+					"password", candidate->password,
+					"priority", candidate->priority, NULL);
 			ret = g_list_append(ret, new_candidate);
 		}