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
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
)
38 static guint signals
[LAST_SIGNAL
] = {0};
46 /* private structure */
47 typedef struct _EmpathyGstAudioSrcPrivate EmpathyGstAudioSrcPrivate
;
49 struct _EmpathyGstAudioSrcPrivate
51 gboolean dispose_has_run
;
55 FsElementAddedNotifier
*notifier
;
64 #define EMPATHY_GST_AUDIO_SRC_GET_PRIVATE(o) \
65 (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \
66 EmpathyGstAudioSrcPrivate))
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"))
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
);
86 empathy_audio_src_set_volume (self
, volume
);
91 empathy_audio_src_init (EmpathyGstAudioSrc
*obj
)
93 EmpathyGstAudioSrcPrivate
*priv
= EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (obj
);
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
);
134 empathy_audio_src_set_property (GObject
*object
,
135 guint property_id
, const GValue
*value
, GParamSpec
*pspec
)
140 empathy_audio_src_set_volume (EMPATHY_GST_AUDIO_SRC (object
),
141 g_value_get_double (value
));
144 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
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
);
158 g_value_set_double (value
,
159 empathy_audio_src_get_volume (self
));
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
);
167 g_mutex_lock (priv
->lock
);
168 g_value_set_double (value
, priv
->rms_level
);
169 g_mutex_unlock (priv
->lock
);
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
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",
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
),
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
),
225 g_cclosure_marshal_VOID__DOUBLE
,
226 G_TYPE_NONE
, 1, G_TYPE_DOUBLE
);
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
)
238 priv
->dispose_has_run
= TRUE
;
240 if (priv
->idle_id
!= 0)
241 g_source_remove (priv
->idle_id
);
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
);
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
);
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
);
275 g_mutex_unlock (priv
->lock
);
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
;
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)
302 list
= gst_structure_get_value (s
, "peak");
303 len
= gst_value_list_get_size (list
);
305 for (i
=0 ; i
< len
; i
++)
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
++)
323 value
= gst_value_list_get_value (list
, i
);
324 db
= g_value_get_double (value
);
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
);
339 GST_BIN_CLASS (empathy_audio_src_parent_class
)->handle_message (bin
,
344 empathy_audio_src_new (void)
346 static gboolean registered
= FALSE
;
349 if (!gst_element_register (NULL
, "empathyaudiosrc",
350 GST_RANK_NONE
, EMPATHY_TYPE_GST_AUDIO_SRC
))
354 return gst_element_factory_make ("empathyaudiosrc", NULL
);
358 empathy_audio_src_set_volume (EmpathyGstAudioSrc
*src
, gdouble volume
)
360 EmpathyGstAudioSrcPrivate
*priv
= EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src
);
362 GParamSpecDouble
*pspec_double
;
364 pspec
= g_object_class_find_property (G_OBJECT_GET_CLASS (priv
->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
);
377 empathy_audio_src_get_volume (EmpathyGstAudioSrc
*src
)
379 EmpathyGstAudioSrcPrivate
*priv
= EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src
);
382 g_object_get (G_OBJECT (priv
->volume
), "volume", &volume
, NULL
);