Use g_list_free_full instead of manual iterations
[pidgin-git.git] / libpurple / media / codec.c
blobaa924fb99dcda6a4afe3234bfe18f11f197e73a3
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 #include "internal.h"
23 #include "glibcompat.h"
24 #include "codec.h"
26 struct _PurpleMediaCodec
28 GObject parent;
31 typedef struct
33 gint id;
34 char *encoding_name;
35 PurpleMediaSessionType media_type;
36 guint clock_rate;
37 guint channels;
38 GList *optional_params;
39 } PurpleMediaCodecPrivate;
41 enum {
42 PROP_CODEC_0,
43 PROP_ID,
44 PROP_ENCODING_NAME,
45 PROP_MEDIA_TYPE,
46 PROP_CLOCK_RATE,
47 PROP_CHANNELS,
48 PROP_OPTIONAL_PARAMS,
49 PROP_LAST
52 static GParamSpec *properties[PROP_LAST];
54 G_DEFINE_TYPE_WITH_PRIVATE(PurpleMediaCodec, purple_media_codec, G_TYPE_OBJECT);
56 static void
57 purple_media_codec_init(PurpleMediaCodec *info)
59 PurpleMediaCodecPrivate *priv =
60 purple_media_codec_get_instance_private(info);
61 priv->encoding_name = NULL;
62 priv->optional_params = NULL;
65 static void
66 purple_media_codec_finalize(GObject *info)
68 PurpleMediaCodecPrivate *priv =
69 purple_media_codec_get_instance_private(
70 PURPLE_MEDIA_CODEC(info));
71 g_free(priv->encoding_name);
72 for (; priv->optional_params; priv->optional_params =
73 g_list_delete_link(priv->optional_params, priv->optional_params)) {
74 PurpleKeyValuePair *param = priv->optional_params->data;
75 g_free(param->key);
76 g_free(param->value);
77 g_free(param);
80 G_OBJECT_CLASS(purple_media_codec_parent_class)->finalize(info);
83 static void
84 purple_media_codec_set_property (GObject *object, guint prop_id,
85 const GValue *value, GParamSpec *pspec)
87 PurpleMediaCodecPrivate *priv;
88 g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
90 priv = purple_media_codec_get_instance_private(
91 PURPLE_MEDIA_CODEC(object));
93 switch (prop_id) {
94 case PROP_ID:
95 priv->id = g_value_get_uint(value);
96 break;
97 case PROP_ENCODING_NAME:
98 g_free(priv->encoding_name);
99 priv->encoding_name = g_value_dup_string(value);
100 break;
101 case PROP_MEDIA_TYPE:
102 priv->media_type = g_value_get_flags(value);
103 break;
104 case PROP_CLOCK_RATE:
105 priv->clock_rate = g_value_get_uint(value);
106 break;
107 case PROP_CHANNELS:
108 priv->channels = g_value_get_uint(value);
109 break;
110 case PROP_OPTIONAL_PARAMS:
111 priv->optional_params = g_value_get_pointer(value);
112 break;
113 default:
114 G_OBJECT_WARN_INVALID_PROPERTY_ID(
115 object, prop_id, pspec);
116 break;
120 static void
121 purple_media_codec_get_property (GObject *object, guint prop_id,
122 GValue *value, GParamSpec *pspec)
124 PurpleMediaCodecPrivate *priv;
125 g_return_if_fail(PURPLE_IS_MEDIA_CODEC(object));
127 priv = purple_media_codec_get_instance_private(
128 PURPLE_MEDIA_CODEC(object));
130 switch (prop_id) {
131 case PROP_ID:
132 g_value_set_uint(value, priv->id);
133 break;
134 case PROP_ENCODING_NAME:
135 g_value_set_string(value, priv->encoding_name);
136 break;
137 case PROP_MEDIA_TYPE:
138 g_value_set_flags(value, priv->media_type);
139 break;
140 case PROP_CLOCK_RATE:
141 g_value_set_uint(value, priv->clock_rate);
142 break;
143 case PROP_CHANNELS:
144 g_value_set_uint(value, priv->channels);
145 break;
146 case PROP_OPTIONAL_PARAMS:
147 g_value_set_pointer(value, priv->optional_params);
148 break;
149 default:
150 G_OBJECT_WARN_INVALID_PROPERTY_ID(
151 object, prop_id, pspec);
152 break;
156 static void
157 purple_media_codec_class_init(PurpleMediaCodecClass *klass)
159 GObjectClass *gobject_class = (GObjectClass*)klass;
161 gobject_class->finalize = purple_media_codec_finalize;
162 gobject_class->set_property = purple_media_codec_set_property;
163 gobject_class->get_property = purple_media_codec_get_property;
165 properties[PROP_ID] = g_param_spec_uint("id",
166 "ID",
167 "The numeric identifier of the codec.",
168 0, G_MAXUINT, 0,
169 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
170 G_PARAM_STATIC_STRINGS);
172 properties[PROP_ENCODING_NAME] = g_param_spec_string("encoding-name",
173 "Encoding Name",
174 "The name of the codec.",
175 NULL,
176 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
177 G_PARAM_STATIC_STRINGS);
179 properties[PROP_MEDIA_TYPE] = g_param_spec_flags("media-type",
180 "Media Type",
181 "Whether this is an audio, video or application codec.",
182 PURPLE_TYPE_MEDIA_SESSION_TYPE,
183 PURPLE_MEDIA_NONE,
184 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
185 G_PARAM_STATIC_STRINGS);
187 properties[PROP_CLOCK_RATE] = g_param_spec_uint("clock-rate",
188 "Create Callback",
189 "The function called to create this element.",
190 0, G_MAXUINT, 0,
191 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
193 properties[PROP_CHANNELS] = g_param_spec_uint("channels",
194 "Channels",
195 "The number of channels in this codec.",
196 0, G_MAXUINT, 0,
197 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
199 properties[PROP_OPTIONAL_PARAMS] = g_param_spec_pointer("optional-params",
200 "Optional Params",
201 "A list of optional parameters for the codec.",
202 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
204 g_object_class_install_properties(gobject_class, PROP_LAST, properties);
207 PurpleMediaCodec *
208 purple_media_codec_new(int id, const char *encoding_name,
209 PurpleMediaSessionType media_type, guint clock_rate)
211 PurpleMediaCodec *codec =
212 g_object_new(PURPLE_TYPE_MEDIA_CODEC,
213 "id", id,
214 "encoding_name", encoding_name,
215 "media_type", media_type,
216 "clock-rate", clock_rate, NULL);
217 return codec;
220 guint
221 purple_media_codec_get_id(PurpleMediaCodec *codec)
223 guint id;
224 g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
225 g_object_get(codec, "id", &id, NULL);
226 return id;
229 gchar *
230 purple_media_codec_get_encoding_name(PurpleMediaCodec *codec)
232 gchar *name;
233 g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), NULL);
234 g_object_get(codec, "encoding-name", &name, NULL);
235 return name;
238 guint
239 purple_media_codec_get_clock_rate(PurpleMediaCodec *codec)
241 guint clock_rate;
242 g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
243 g_object_get(codec, "clock-rate", &clock_rate, NULL);
244 return clock_rate;
247 guint
248 purple_media_codec_get_channels(PurpleMediaCodec *codec)
250 guint channels;
251 g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), 0);
252 g_object_get(codec, "channels", &channels, NULL);
253 return channels;
256 GList *
257 purple_media_codec_get_optional_parameters(PurpleMediaCodec *codec)
259 GList *optional_params;
260 g_return_val_if_fail(PURPLE_IS_MEDIA_CODEC(codec), NULL);
261 g_object_get(codec, "optional-params", &optional_params, NULL);
262 return optional_params;
265 void
266 purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec,
267 const gchar *name, const gchar *value)
269 PurpleMediaCodecPrivate *priv;
270 PurpleKeyValuePair *new_param;
272 g_return_if_fail(codec != NULL);
273 g_return_if_fail(name != NULL && value != NULL);
275 priv = purple_media_codec_get_instance_private(codec);
277 new_param = g_new0(PurpleKeyValuePair, 1);
278 new_param->key = g_strdup(name);
279 new_param->value = g_strdup(value);
280 priv->optional_params = g_list_append(
281 priv->optional_params, new_param);
283 g_object_notify_by_pspec(G_OBJECT(codec), properties[PROP_OPTIONAL_PARAMS]);
286 void
287 purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec,
288 PurpleKeyValuePair *param)
290 PurpleMediaCodecPrivate *priv;
292 g_return_if_fail(codec != NULL && param != NULL);
294 priv = purple_media_codec_get_instance_private(codec);
296 g_free(param->key);
297 g_free(param->value);
299 priv->optional_params =
300 g_list_remove(priv->optional_params, param);
301 g_free(param);
303 g_object_notify_by_pspec(G_OBJECT(codec), properties[PROP_OPTIONAL_PARAMS]);
306 PurpleKeyValuePair *
307 purple_media_codec_get_optional_parameter(PurpleMediaCodec *codec,
308 const gchar *name, const gchar *value)
310 PurpleMediaCodecPrivate *priv;
311 GList *iter;
313 g_return_val_if_fail(codec != NULL, NULL);
314 g_return_val_if_fail(name != NULL, NULL);
316 priv = purple_media_codec_get_instance_private(codec);
318 for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
319 PurpleKeyValuePair *param = iter->data;
320 if (!g_ascii_strcasecmp(param->key, name) &&
321 (value == NULL ||
322 !g_ascii_strcasecmp(param->value, value)))
323 return param;
326 return NULL;
329 PurpleMediaCodec *
330 purple_media_codec_copy(PurpleMediaCodec *codec)
332 PurpleMediaCodecPrivate *priv;
333 PurpleMediaCodec *new_codec;
334 GList *iter;
336 if (codec == NULL)
337 return NULL;
339 priv = purple_media_codec_get_instance_private(codec);
341 new_codec = purple_media_codec_new(priv->id, priv->encoding_name,
342 priv->media_type, priv->clock_rate);
343 g_object_set(codec, "channels", priv->channels, NULL);
345 for (iter = priv->optional_params; iter; iter = g_list_next(iter)) {
346 PurpleKeyValuePair *param =
347 (PurpleKeyValuePair*)iter->data;
348 purple_media_codec_add_optional_parameter(new_codec,
349 param->key, param->value);
352 return new_codec;
355 GList *
356 purple_media_codec_list_copy(GList *codecs)
358 GList *new_list = NULL;
360 for (; codecs; codecs = g_list_next(codecs)) {
361 new_list = g_list_prepend(new_list,
362 purple_media_codec_copy(codecs->data));
365 new_list = g_list_reverse(new_list);
366 return new_list;
369 void
370 purple_media_codec_list_free(GList *codecs)
372 g_list_free_full(codecs, g_object_unref);
375 gchar *
376 purple_media_codec_to_string(PurpleMediaCodec *codec)
378 PurpleMediaCodecPrivate *priv;
379 GString *string = NULL;
380 GList *item;
381 gchar *charstring;
382 const gchar *media_type_str = NULL;
384 if (codec == NULL)
385 return g_strdup("(NULL)");
387 priv = purple_media_codec_get_instance_private(codec);
389 string = g_string_new("");
391 if (priv->media_type & PURPLE_MEDIA_AUDIO)
392 media_type_str = "audio";
393 else if (priv->media_type & PURPLE_MEDIA_VIDEO)
394 media_type_str = "video";
395 else if (priv->media_type & PURPLE_MEDIA_APPLICATION)
396 media_type_str = "application";
398 g_string_printf(string, "%d: %s %s clock:%d channels:%d", priv->id,
399 media_type_str, priv->encoding_name,
400 priv->clock_rate, priv->channels);
402 for (item = priv->optional_params; item; item = g_list_next (item)) {
403 PurpleKeyValuePair *param = item->data;
404 g_string_append_printf (string, " %s=%s",
405 param->key, (gchar *)param->value);
408 charstring = string->str;
409 g_string_free (string, FALSE);
411 return charstring;