changeset 26486:217574ec2a34

Hide and gobjectify PurpleMediaCodec.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Thu, 02 Apr 2009 04:06:07 +0000
parents f0de2405c2f1
children 70ab418e9d4f
files libpurple/media.c libpurple/media.h libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jingle/rtp.c
diffstat 4 files changed, 351 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/media.c	Thu Apr 02 01:12:23 2009 +0000
+++ b/libpurple/media.c	Thu Apr 02 04:06:07 2009 +0000
@@ -45,6 +45,10 @@
 typedef struct _PurpleMediaSession PurpleMediaSession;
 /** @copydoc _PurpleMediaStream */
 typedef struct _PurpleMediaStream PurpleMediaStream;
+/** @copydoc _PurpleMediaCodecClass */
+typedef struct _PurpleMediaCodecClass PurpleMediaCodecClass;
+/** @copydoc _PurpleMediaCodecPrivate */
+typedef struct _PurpleMediaCodecPrivate PurpleMediaCodecPrivate;
 
 /** The media class */
 struct _PurpleMediaClass
@@ -115,6 +119,7 @@
 
 #ifdef USE_VV
 #define PURPLE_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MEDIA, PurpleMediaPrivate))
+#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);
 static void purple_media_init (PurpleMedia *media);
@@ -159,6 +164,39 @@
 };
 #endif
 
+
+/*
+ * PurpleMediaElementType
+ */
+
+GType
+purple_media_session_type_get_type()
+{
+	static GType type = 0;
+	if (type == 0) {
+		static const GFlagsValue values[] = {
+			{ PURPLE_MEDIA_NONE,
+				"PURPLE_MEDIA_NONE", "none" },
+			{ PURPLE_MEDIA_RECV_AUDIO,
+				"PURPLE_MEDIA_RECV_AUDIO", "recv-audio" },
+			{ PURPLE_MEDIA_SEND_AUDIO,
+				"PURPLE_MEDIA_SEND_AUDIO", "send-audio" },
+			{ PURPLE_MEDIA_RECV_VIDEO,
+				"PURPLE_MEDIA_RECV_VIDEO", "recv-video" },
+			{ PURPLE_MEDIA_SEND_VIDEO,
+				"PURPLE_MEDIA_SEND_VIDEO", "send-audio" },
+			{ PURPLE_MEDIA_AUDIO,
+				"PURPLE_MEDIA_AUDIO", "audio" },
+			{ PURPLE_MEDIA_VIDEO,
+				"PURPLE_MEDIA_VIDEO", "video" },
+			{ 0, NULL, NULL }
+		};
+		type = g_flags_register_static(
+				"PurpleMediaSessionType", values);
+	}
+	return type;
+}
+
 GType
 purple_media_get_type()
 {
@@ -749,46 +787,284 @@
 }
 #endif
 
+/*
+ * PurpleMediaCodec
+ */
+
+struct _PurpleMediaCodecClass
+{
+	GObjectClass parent_class;
+};
+
+struct _PurpleMediaCodec
+{
+	GObject parent;
+};
+
+struct _PurpleMediaCodecPrivate
+{
+	gint id;
+	char *encoding_name;
+	PurpleMediaSessionType media_type;
+	guint clock_rate;
+	guint channels;
+	GList *optional_params;
+};
+
+enum {
+	PROP_CODEC_0,
+	PROP_ID,
+	PROP_ENCODING_NAME,
+	PROP_MEDIA_TYPE,
+	PROP_CLOCK_RATE,
+	PROP_CHANNELS,
+	PROP_OPTIONAL_PARAMS,
+};
+
+static void
+purple_media_codec_init(PurpleMediaCodec *info)
+{
+	PurpleMediaCodecPrivate *priv =
+			PURPLE_MEDIA_CODEC_GET_PRIVATE(info);
+	priv->encoding_name = NULL;
+	priv->optional_params = NULL;
+}
+
+static void
+purple_media_codec_finalize(GObject *info)
+{
+	PurpleMediaCodecPrivate *priv =
+			PURPLE_MEDIA_CODEC_GET_PRIVATE(info);
+	g_free(priv->encoding_name);
+	for (; priv->optional_params; priv->optional_params =
+			g_list_delete_link(priv->optional_params,
+			priv->optional_params)) {
+		g_free(priv->optional_params->data);
+	}
+}
+
+static void
+purple_media_codec_set_property (GObject *object, guint prop_id,
+		const GValue *value, GParamSpec *pspec)
+{
+	PurpleMediaCodecPrivate *priv;
+	g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
+
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(object);
+
+	switch (prop_id) {
+		case PROP_ID:
+			priv->id = g_value_get_uint(value);
+			break;
+		case PROP_ENCODING_NAME:
+			g_free(priv->encoding_name);
+			priv->encoding_name = g_value_dup_string(value);
+			break;
+		case PROP_MEDIA_TYPE:
+			priv->media_type = g_value_get_flags(value);
+			break;
+		case PROP_CLOCK_RATE:
+			priv->clock_rate = g_value_get_uint(value);
+			break;
+		case PROP_CHANNELS:
+			priv->channels = g_value_get_uint(value);
+			break;
+		case PROP_OPTIONAL_PARAMS:
+			priv->optional_params = g_value_get_pointer(value);
+			break;
+		default:	
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(
+					object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_media_codec_get_property (GObject *object, guint prop_id,
+		GValue *value, GParamSpec *pspec)
+{
+	PurpleMediaCodecPrivate *priv;
+	g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
+	
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(object);
+
+	switch (prop_id) {
+		case PROP_ID:
+			g_value_set_uint(value, priv->id);
+			break;
+		case PROP_ENCODING_NAME:
+			g_value_set_string(value, priv->encoding_name);
+			break;
+		case PROP_MEDIA_TYPE:
+			g_value_set_flags(value, priv->media_type);
+			break;
+		case PROP_CLOCK_RATE:
+			g_value_set_uint(value, priv->clock_rate);
+			break;
+		case PROP_CHANNELS:
+			g_value_set_uint(value, priv->channels);
+			break;
+		case PROP_OPTIONAL_PARAMS:
+			g_value_set_pointer(value, priv->optional_params);
+			break;
+		default:	
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(
+					object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_media_codec_class_init(PurpleMediaCodecClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	
+	gobject_class->finalize = purple_media_codec_finalize;
+	gobject_class->set_property = purple_media_codec_set_property;
+	gobject_class->get_property = purple_media_codec_get_property;
+
+	g_object_class_install_property(gobject_class, PROP_ID,
+			g_param_spec_uint("id",
+			"ID",
+			"The numeric identifier of the codec.",
+			0, G_MAXUINT, 0,
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_ENCODING_NAME,
+			g_param_spec_string("encoding-name",
+			"Encoding Name",
+			"The name of the codec.",
+			NULL,
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+	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.",
+			PURPLE_TYPE_MEDIA_SESSION_TYPE,
+			PURPLE_MEDIA_NONE,
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_CLOCK_RATE,
+			g_param_spec_uint("clock-rate",
+			"Create Callback",
+			"The function called to create this element.",
+			0, G_MAXUINT, 0,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property(gobject_class, PROP_CHANNELS,
+			g_param_spec_uint("channels",
+			"Channels",
+			"The number of channels in this codec.",
+			0, G_MAXUINT, 0,
+			G_PARAM_READWRITE));
+	g_object_class_install_property(gobject_class, PROP_OPTIONAL_PARAMS,
+			g_param_spec_pointer("optional-params",
+			"Optional Params",
+			"A list of optional parameters for the codec.",
+			G_PARAM_READWRITE));
+
+	g_type_class_add_private(klass, sizeof(PurpleMediaCodecPrivate));
+}
+
+G_DEFINE_TYPE(PurpleMediaCodec,
+		purple_media_codec, G_TYPE_OBJECT);
+
+guint
+purple_media_codec_get_id(PurpleMediaCodec *codec)
+{
+	guint id;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
+	g_object_get(codec, "id", &id, NULL);
+	return id;
+}
+
+gchar *
+purple_media_codec_get_encoding_name(PurpleMediaCodec *codec)
+{
+	gchar *name;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), NULL);
+	g_object_get(codec, "encoding-name", &name, NULL);
+	return name;
+}
+
+guint
+purple_media_codec_get_clock_rate(PurpleMediaCodec *codec)
+{
+	guint clock_rate;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
+	g_object_get(codec, "clock-rate", &clock_rate, NULL);
+	return clock_rate;
+}
+
+guint
+purple_media_codec_get_channels(PurpleMediaCodec *codec)
+{
+	guint channels;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
+	g_object_get(codec, "channels", &channels, NULL);
+	return channels;
+}
+
+GList *
+purple_media_codec_get_optional_parameters(PurpleMediaCodec *codec)
+{
+	GList *optional_params;
+	g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), NULL);
+	g_object_get(codec, "optional-params", &optional_params, NULL);
+	return optional_params;
+}
+
 void
 purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec,
 		const gchar *name, const gchar *value)
 {
+	PurpleMediaCodecPrivate *priv;
 	PurpleKeyValuePair *new_param;
 
 	g_return_if_fail(codec != NULL);
 	g_return_if_fail(name != NULL && value != NULL);
 
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+
 	new_param = g_new0(PurpleKeyValuePair, 1);
 	new_param->key = g_strdup(name);
 	new_param->value = g_strdup(value);
-	codec->optional_params = g_list_append(
-			codec->optional_params, new_param);
+	priv->optional_params = g_list_append(
+			priv->optional_params, new_param);
 }
 
 void
 purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec,
 		PurpleKeyValuePair *param)
 {
+	PurpleMediaCodecPrivate *priv;
+
 	g_return_if_fail(codec != NULL && param != NULL);
 
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+
 	g_free(param->key);
 	g_free(param->value);
 	g_free(param);
 
-	codec->optional_params =
-			g_list_remove(codec->optional_params, param);
+	priv->optional_params =
+			g_list_remove(priv->optional_params, param);
 }
 
 PurpleKeyValuePair *
 purple_media_codec_get_optional_parameter(PurpleMediaCodec *codec,
 		const gchar *name, const gchar *value)
 {
+	PurpleMediaCodecPrivate *priv;
 	GList *iter;
 
 	g_return_val_if_fail(codec != NULL, NULL);
 	g_return_val_if_fail(name != NULL, NULL);
 
-	for (iter = codec->optional_params; iter; iter = g_list_next(iter)) {
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
+
+	for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
 		PurpleKeyValuePair *param = iter->data;
 		if (!g_ascii_strcasecmp(param->key, name) &&
 				(value == NULL ||
@@ -803,29 +1079,32 @@
 purple_media_codec_new(int id, const char *encoding_name,
 		PurpleMediaSessionType media_type, guint clock_rate)
 {
-	PurpleMediaCodec *codec = g_new0(PurpleMediaCodec, 1);
-
-	codec->id = id;
-	codec->encoding_name = g_strdup(encoding_name);
-	codec->media_type = media_type;
-	codec->clock_rate = clock_rate;
+	PurpleMediaCodec *codec =
+			g_object_new(PURPLE_TYPE_MEDIA_CODEC,
+			"id", id,
+			"encoding_name", encoding_name,
+			"media_type", media_type,
+			"clock-rate", clock_rate, NULL);
 	return codec;
 }
 
 static PurpleMediaCodec *
 purple_media_codec_copy(PurpleMediaCodec *codec)
 {
+	PurpleMediaCodecPrivate *priv;
 	PurpleMediaCodec *new_codec;
 	GList *iter;
 
 	if (codec == NULL)
 		return NULL;
 
-	new_codec = purple_media_codec_new(codec->id, codec->encoding_name,
-			codec->media_type, codec->clock_rate);
-	new_codec->channels = codec->channels;
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
 
-	for (iter = codec->optional_params; iter; iter = g_list_next(iter)) {
+	new_codec = purple_media_codec_new(priv->id, priv->encoding_name,
+			priv->media_type, priv->clock_rate);
+	g_object_set(codec, "channels", priv->channels, NULL);
+
+	for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
 		PurpleKeyValuePair *param =
 				(PurpleKeyValuePair*)iter->data;
 		purple_media_codec_add_optional_parameter(new_codec,
@@ -835,40 +1114,25 @@
 	return new_codec;
 }
 
-static void
-purple_media_codec_free(PurpleMediaCodec *codec)
-{
-	if (codec == NULL)
-		return;
-
-	g_free(codec->encoding_name);
-
-	for (; codec->optional_params; codec->optional_params =
-			g_list_delete_link(codec->optional_params,
-			codec->optional_params)) {
-		purple_media_codec_remove_optional_parameter(codec,
-				codec->optional_params->data);
-	}
-
-	g_free(codec);
-}
-
 #ifdef USE_VV
 static FsCodec *
 purple_media_codec_to_fs(const PurpleMediaCodec *codec)
 {
+	PurpleMediaCodecPrivate *priv;
 	FsCodec *new_codec;
 	GList *iter;
 
 	if (codec == NULL)
 		return NULL;
 
-	new_codec = fs_codec_new(codec->id, codec->encoding_name,
-			purple_media_to_fs_media_type(codec->media_type),
-			codec->clock_rate);
-	new_codec->channels = codec->channels;
+	priv = PURPLE_MEDIA_CODEC_GET_PRIVATE(codec);
 
-	for (iter = codec->optional_params; iter; iter = g_list_next(iter)) {
+	new_codec = fs_codec_new(priv->id, priv->encoding_name,
+			purple_media_to_fs_media_type(priv->media_type),
+			priv->clock_rate);
+	new_codec->channels = priv->channels;
+
+	for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
 		PurpleKeyValuePair *param = (PurpleKeyValuePair*)iter->data;
 		fs_codec_add_optional_parameter(new_codec,
 				param->key, param->value);
@@ -889,7 +1153,7 @@
 	new_codec = purple_media_codec_new(codec->id, codec->encoding_name,
 			purple_media_from_fs(codec->media_type,
 			FS_DIRECTION_BOTH), codec->clock_rate);
-	new_codec->channels = codec->channels;
+	g_object_set(new_codec, "channels", codec->channels, NULL);
 
 	for (iter = codec->optional_params; iter; iter = g_list_next(iter)) {
 		FsCodecParameter *param = (FsCodecParameter*)iter->data;
@@ -952,9 +1216,8 @@
 	GList *new_list = NULL;
 
 	for (; codecs; codecs = g_list_next(codecs)) {
-		new_list = g_list_prepend(new_list, g_boxed_copy(
-				PURPLE_TYPE_MEDIA_CODEC,
-				codecs->data));
+		new_list = g_list_prepend(new_list,
+				purple_media_codec_copy(codecs->data));
 	}
 
 	new_list = g_list_reverse(new_list);
@@ -966,24 +1229,10 @@
 {
 	for (; codecs; codecs =
 			g_list_delete_link(codecs, codecs)) {
-		g_boxed_free(PURPLE_TYPE_MEDIA_CODEC,
-				codecs->data);
+		g_object_unref(codecs->data);
 	}
 }
 
-GType
-purple_media_codec_get_type()
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		type = g_boxed_type_register_static("PurpleMediaCodec",
-				(GBoxedCopyFunc)purple_media_codec_copy,
-				(GBoxedFreeFunc)purple_media_codec_free);
-	}
-	return type;
-}
-
 #ifdef USE_VV
 static PurpleMediaSession*
 purple_media_get_session(PurpleMedia *media, const gchar *sess_id)
--- a/libpurple/media.h	Thu Apr 02 01:12:23 2009 +0000
+++ b/libpurple/media.h	Thu Apr 02 04:06:07 2009 +0000
@@ -35,9 +35,16 @@
 
 G_BEGIN_DECLS
 
+#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))
+#define PURPLE_IS_MEDIA_CODEC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MEDIA_CODEC))
+#define PURPLE_IS_MEDIA_CODEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_CODEC))
+#define PURPLE_MEDIA_CODEC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_CODEC, PurpleMediaCodec))
+
+#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_TYPE_MEDIA_CODEC      (purple_media_codec_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))
@@ -134,21 +141,18 @@
 	guint ttl;
 };
 
-struct _PurpleMediaCodec
-{
-	gint id;
-	char *encoding_name;
-	PurpleMediaSessionType media_type;
-	guint clock_rate;
-	guint channels;
-	GList *optional_params;
-};
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
+ * Gets the media session type's GType
+ *
+ * @return The media session type's GType.
+ */
+GType purple_media_session_type_get_type(void);
+
+/**
  * Gets the media class's GType
  *
  * @return The media class's GType.
@@ -230,6 +234,12 @@
 PurpleMediaCodec *purple_media_codec_new(int id, const char *encoding_name,
 		PurpleMediaSessionType media_type, guint clock_rate);
 
+guint purple_media_codec_get_id(PurpleMediaCodec *codec);
+gchar *purple_media_codec_get_encoding_name(PurpleMediaCodec *codec);
+guint purple_media_codec_get_clock_rate(PurpleMediaCodec *codec);
+guint purple_media_codec_get_channels(PurpleMediaCodec *codec);
+GList *purple_media_codec_get_optional_parameters(PurpleMediaCodec *codec);
+
 /**
  * Creates a string representation of the codec.
  *
--- a/libpurple/protocols/jabber/google.c	Thu Apr 02 01:12:23 2009 +0000
+++ b/libpurple/protocols/jabber/google.c	Thu Apr 02 04:06:07 2009 +0000
@@ -202,13 +202,18 @@
 
 		for (iter = codecs; iter; iter = g_list_next(iter)) {
 			PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
-			gchar *id = g_strdup_printf("%d", codec->id);
-			gchar *clock_rate = g_strdup_printf("%d", codec->clock_rate);
+			gchar *id = g_strdup_printf("%d",
+					purple_media_codec_get_id(codec));
+			gchar *encoding_name =
+					purple_media_codec_get_encoding_name(codec);
+			gchar *clock_rate = g_strdup_printf("%d",
+					purple_media_codec_get_clock_rate(codec));
 			payload = xmlnode_new_child(desc, "payload-type");
 			xmlnode_set_attrib(payload, "id", id);
-			xmlnode_set_attrib(payload, "name", codec->encoding_name);
+			xmlnode_set_attrib(payload, "name", encoding_name);
 			xmlnode_set_attrib(payload, "clockrate", clock_rate);
 			g_free(clock_rate);
+			g_free(encoding_name);
 			g_free(id);
 		}
 		purple_media_codec_list_free(codecs);
--- a/libpurple/protocols/jabber/jingle/rtp.c	Thu Apr 02 01:12:23 2009 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Thu Apr 02 04:06:07 2009 +0000
@@ -666,20 +666,29 @@
 {
 	for (; codecs ; codecs = codecs->next) {
 		PurpleMediaCodec *codec = (PurpleMediaCodec*)codecs->data;
-		GList *iter = codec->optional_params;
-		char id[8], clockrate[10], channels[10];
+		GList *iter = purple_media_codec_get_optional_parameters(codec);
+		gchar *id, *name, *clockrate, *channels;
 		gchar *codec_str;
 		xmlnode *payload = xmlnode_new_child(description, "payload-type");
 		
-		g_snprintf(id, sizeof(id), "%d", codec->id);
-		g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate);
-		g_snprintf(channels, sizeof(channels), "%d", codec->channels);
-		
-		xmlnode_set_attrib(payload, "name", codec->encoding_name);
+		id = g_strdup_printf("%d",
+				purple_media_codec_get_id(codec));
+		name = purple_media_codec_get_encoding_name(codec);
+		clockrate = g_strdup_printf("%d",
+				purple_media_codec_get_clock_rate(codec));
+		channels = g_strdup_printf("%d",
+				purple_media_codec_get_channels(codec));
+
+		xmlnode_set_attrib(payload, "name", name);
 		xmlnode_set_attrib(payload, "id", id);
 		xmlnode_set_attrib(payload, "clockrate", clockrate);
 		xmlnode_set_attrib(payload, "channels", channels);
 
+		g_free(channels);
+		g_free(clockrate);
+		g_free(name);
+		g_free(id);
+
 		for (; iter; iter = g_list_next(iter)) {
 			PurpleKeyValuePair *mparam = iter->data;
 			xmlnode *param = xmlnode_new_child(payload, "parameter");