Generate closures for src/
[empathy-mirror.git] / libempathy-gtk / empathy-audio-src.c
bloba3416f2eacbc79aafc6defeacbc5bc6f0e5a6d77
1 /*
2 * empathy-gst-audio-src.c - Source for EmpathyGstAudioSrc
3 * Copyright (C) 2008 Collabora Ltd.
4 * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <stdio.h>
23 #include <stdlib.h>
25 #include <gst/farsight/fs-element-added-notifier.h>
26 #include "empathy-audio-src.h"
28 G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN)
30 /* signal enum */
31 enum
33 PEAK_LEVEL_CHANGED,
34 RMS_LEVEL_CHANGED,
35 LAST_SIGNAL
38 static guint signals[LAST_SIGNAL] = {0};
40 enum {
41 PROP_VOLUME = 1,
42 PROP_RMS_LEVEL,
43 PROP_PEAK_LEVEL,
46 /* private structure */
47 typedef struct _EmpathyGstAudioSrcPrivate EmpathyGstAudioSrcPrivate;
49 struct _EmpathyGstAudioSrcPrivate
51 gboolean dispose_has_run;
52 GstElement *src;
53 GstElement *volume;
54 GstElement *level;
55 FsElementAddedNotifier *notifier;
57 gdouble peak_level;
58 gdouble rms_level;
60 GMutex *lock;
61 guint idle_id;
64 #define EMPATHY_GST_AUDIO_SRC_GET_PRIVATE(o) \
65 (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \
66 EmpathyGstAudioSrcPrivate))
68 static void
69 empathy_audio_src_element_added_cb (FsElementAddedNotifier *notifier,
70 GstBin *bin, GstElement *element, EmpathyGstAudioSrc *self)
72 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
74 if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume"))
76 gdouble volume;
78 volume = empathy_audio_src_get_volume (self);
79 empathy_audio_src_set_volume (self, 1.0);
81 if (priv->volume != NULL)
82 g_object_unref (priv->volume);
83 priv->volume = g_object_ref (element);
85 if (volume != 1.0)
86 empathy_audio_src_set_volume (self, volume);
90 static void
91 empathy_audio_src_init (EmpathyGstAudioSrc *obj)
93 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (obj);
94 GstPad *ghost, *src;
96 priv->peak_level = -G_MAXDOUBLE;
97 priv->lock = g_mutex_new ();
99 priv->notifier = fs_element_added_notifier_new ();
100 g_signal_connect (priv->notifier, "element-added",
101 G_CALLBACK (empathy_audio_src_element_added_cb), obj);
103 priv->src = gst_element_factory_make ("gconfaudiosrc", NULL);
104 gst_bin_add (GST_BIN (obj), priv->src);
106 fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src));
108 priv->volume = gst_element_factory_make ("volume", NULL);
109 g_object_ref (priv->volume);
111 gst_bin_add (GST_BIN (obj), priv->volume);
112 gst_element_link (priv->src, priv->volume);
114 priv->level = gst_element_factory_make ("level", NULL);
115 gst_bin_add (GST_BIN (obj), priv->level);
116 gst_element_link (priv->volume, priv->level);
118 src = gst_element_get_static_pad (priv->level, "src");
120 ghost = gst_ghost_pad_new ("src", src);
121 gst_element_add_pad (GST_ELEMENT (obj), ghost);
123 gst_object_unref (G_OBJECT (src));
126 static void empathy_audio_src_dispose (GObject *object);
127 static void empathy_audio_src_finalize (GObject *object);
128 static void empathy_audio_src_handle_message (GstBin *bin,
129 GstMessage *message);
131 static gboolean empathy_audio_src_levels_updated (gpointer user_data);
133 static void
134 empathy_audio_src_set_property (GObject *object,
135 guint property_id, const GValue *value, GParamSpec *pspec)
137 switch (property_id)
139 case PROP_VOLUME:
140 empathy_audio_src_set_volume (EMPATHY_GST_AUDIO_SRC (object),
141 g_value_get_double (value));
142 break;
143 default:
144 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
148 static void
149 empathy_audio_src_get_property (GObject *object,
150 guint property_id, GValue *value, GParamSpec *pspec)
152 EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object);
153 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
155 switch (property_id)
157 case PROP_VOLUME:
158 g_value_set_double (value,
159 empathy_audio_src_get_volume (self));
160 break;
161 case PROP_PEAK_LEVEL:
162 g_mutex_lock (priv->lock);
163 g_value_set_double (value, priv->peak_level);
164 g_mutex_unlock (priv->lock);
165 break;
166 case PROP_RMS_LEVEL:
167 g_mutex_lock (priv->lock);
168 g_value_set_double (value, priv->rms_level);
169 g_mutex_unlock (priv->lock);
170 break;
171 default:
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
176 static void
177 empathy_audio_src_class_init (EmpathyGstAudioSrcClass
178 *empathy_audio_src_class)
180 GObjectClass *object_class = G_OBJECT_CLASS (empathy_audio_src_class);
181 GstBinClass *gstbin_class = GST_BIN_CLASS (empathy_audio_src_class);
182 GParamSpec *param_spec;
184 g_type_class_add_private (empathy_audio_src_class,
185 sizeof (EmpathyGstAudioSrcPrivate));
187 object_class->dispose = empathy_audio_src_dispose;
188 object_class->finalize = empathy_audio_src_finalize;
190 object_class->set_property = empathy_audio_src_set_property;
191 object_class->get_property = empathy_audio_src_get_property;
193 gstbin_class->handle_message =
194 GST_DEBUG_FUNCPTR (empathy_audio_src_handle_message);
196 param_spec = g_param_spec_double ("volume", "Volume", "volume contol",
197 0.0, 5.0, 1.0,
198 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
199 g_object_class_install_property (object_class, PROP_VOLUME, param_spec);
201 param_spec = g_param_spec_double ("peak-level", "peak level", "peak level",
202 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
203 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
204 g_object_class_install_property (object_class, PROP_VOLUME, param_spec);
206 signals[PEAK_LEVEL_CHANGED] = g_signal_new ("peak-level-changed",
207 G_TYPE_FROM_CLASS (empathy_audio_src_class),
208 G_SIGNAL_RUN_LAST,
210 NULL, NULL,
211 g_cclosure_marshal_VOID__DOUBLE,
212 G_TYPE_NONE, 1, G_TYPE_DOUBLE);
214 param_spec = g_param_spec_double ("rms-level", "RMS level", "RMS level",
215 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
216 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
217 g_object_class_install_property (object_class, PROP_VOLUME, param_spec);
220 signals[RMS_LEVEL_CHANGED] = g_signal_new ("rms-level-changed",
221 G_TYPE_FROM_CLASS (empathy_audio_src_class),
222 G_SIGNAL_RUN_LAST,
224 NULL, NULL,
225 g_cclosure_marshal_VOID__DOUBLE,
226 G_TYPE_NONE, 1, G_TYPE_DOUBLE);
229 void
230 empathy_audio_src_dispose (GObject *object)
232 EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object);
233 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
235 if (priv->dispose_has_run)
236 return;
238 priv->dispose_has_run = TRUE;
240 if (priv->idle_id != 0)
241 g_source_remove (priv->idle_id);
243 priv->idle_id = 0;
245 /* release any references held by the object here */
247 if (G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose)
248 G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose (object);
251 void
252 empathy_audio_src_finalize (GObject *object)
254 EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object);
255 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
257 /* free any data held directly by the object here */
258 g_mutex_free (priv->lock);
260 G_OBJECT_CLASS (empathy_audio_src_parent_class)->finalize (object);
263 static gboolean
264 empathy_audio_src_levels_updated (gpointer user_data)
266 EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (user_data);
267 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
269 g_mutex_lock (priv->lock);
271 g_signal_emit (self, signals[PEAK_LEVEL_CHANGED], 0, priv->peak_level);
272 g_signal_emit (self, signals[RMS_LEVEL_CHANGED], 0, priv->rms_level);
273 priv->idle_id = 0;
275 g_mutex_unlock (priv->lock);
277 return FALSE;
280 static void
281 empathy_audio_src_handle_message (GstBin *bin, GstMessage *message)
283 EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (bin);
284 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self);
286 if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT &&
287 GST_MESSAGE_SRC (message) == GST_OBJECT (priv->level))
289 const GstStructure *s;
290 const gchar *name;
291 const GValue *list;
292 guint i, len;
293 gdouble peak = -G_MAXDOUBLE;
294 gdouble rms = -G_MAXDOUBLE;
296 s = gst_message_get_structure (message);
297 name = gst_structure_get_name (s);
299 if (g_strcmp0 ("level", name) != 0)
300 goto out;
302 list = gst_structure_get_value (s, "peak");
303 len = gst_value_list_get_size (list);
305 for (i =0 ; i < len; i++)
307 const GValue *value;
308 gdouble db;
310 value = gst_value_list_get_value (list, i);
311 db = g_value_get_double (value);
312 peak = MAX (db, peak);
315 list = gst_structure_get_value (s, "rms");
316 len = gst_value_list_get_size (list);
318 for (i =0 ; i < len; i++)
320 const GValue *value;
321 gdouble db;
323 value = gst_value_list_get_value (list, i);
324 db = g_value_get_double (value);
325 rms = MAX (db, rms);
328 g_mutex_lock (priv->lock);
330 priv->peak_level = peak;
331 priv->rms_level = rms;
332 if (priv->idle_id == 0)
333 priv->idle_id = g_idle_add (empathy_audio_src_levels_updated, self);
335 g_mutex_unlock (priv->lock);
338 out:
339 GST_BIN_CLASS (empathy_audio_src_parent_class)->handle_message (bin,
340 message);
343 GstElement *
344 empathy_audio_src_new (void)
346 static gboolean registered = FALSE;
348 if (!registered) {
349 if (!gst_element_register (NULL, "empathyaudiosrc",
350 GST_RANK_NONE, EMPATHY_TYPE_GST_AUDIO_SRC))
351 return NULL;
352 registered = TRUE;
354 return gst_element_factory_make ("empathyaudiosrc", NULL);
357 void
358 empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume)
360 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src);
361 GParamSpec *pspec;
362 GParamSpecDouble *pspec_double;
364 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (priv->volume),
365 "volume");
367 g_assert (pspec != NULL);
369 pspec_double = G_PARAM_SPEC_DOUBLE (pspec);
371 volume = CLAMP (volume, pspec_double->minimum, pspec_double->maximum);
373 g_object_set (G_OBJECT (priv->volume), "volume", volume, NULL);
376 gdouble
377 empathy_audio_src_get_volume (EmpathyGstAudioSrc *src)
379 EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src);
380 gdouble volume;
382 g_object_get (G_OBJECT (priv->volume), "volume", &volume, NULL);
384 return volume;