summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ruprecht <maiku@pidgin.im>2009-04-02 04:06:07 +0000
committerMichael Ruprecht <maiku@pidgin.im>2009-04-02 04:06:07 +0000
commit8f656be6a17b7dfd015c404791f541037abfbdcd (patch)
tree300f9ff04d7176eb283e6eaf7a924c7f6810008a
parent9dd779cd877576bebe1ca782ec5f0187801798d6 (diff)
downloadpidgin-8f656be6a17b7dfd015c404791f541037abfbdcd.tar.gz
Hide and gobjectify PurpleMediaCodec.
-rw-r--r--libpurple/media.c363
-rw-r--r--libpurple/media.h32
-rw-r--r--libpurple/protocols/jabber/google.c11
-rw-r--r--libpurple/protocols/jabber/jingle/rtp.c23
4 files changed, 351 insertions, 78 deletions
diff --git a/libpurple/media.c b/libpurple/media.c
index aefccf2369..cbcaac26d4 100644
--- a/libpurple/media.c
+++ b/libpurple/media.c
@@ -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 @@ struct _PurpleMediaPrivate
#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 @@ enum {
};
#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 @@ purple_media_from_fs(FsMediaType type, FsStreamDirection direction)
}
#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 @@ PurpleMediaCodec *
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 @@ purple_media_codec_copy(PurpleMediaCodec *codec)
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 @@ purple_media_codec_from_fs(const FsCodec *codec)
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 @@ purple_media_codec_list_copy(GList *codecs)
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 @@ purple_media_codec_list_free(GList *codecs)
{
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)
diff --git a/libpurple/media.h b/libpurple/media.h
index 862fbcd6e2..78bd4e913a 100644
--- a/libpurple/media.h
+++ b/libpurple/media.h
@@ -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 @@ struct _PurpleMediaCandidate
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 @@ GType purple_media_codec_get_type(void);
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.
*
diff --git a/libpurple/protocols/jabber/google.c b/libpurple/protocols/jabber/google.c
index f76c7f09a8..72d59c1c45 100644
--- a/libpurple/protocols/jabber/google.c
+++ b/libpurple/protocols/jabber/google.c
@@ -202,13 +202,18 @@ google_session_ready(GoogleSession *session)
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);
diff --git a/libpurple/protocols/jabber/jingle/rtp.c b/libpurple/protocols/jabber/jingle/rtp.c
index 935f9faaa0..f9eb3cdc9d 100644
--- a/libpurple/protocols/jabber/jingle/rtp.c
+++ b/libpurple/protocols/jabber/jingle/rtp.c
@@ -666,20 +666,29 @@ jingle_rtp_add_payloads(xmlnode *description, GList *codecs)
{
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");