Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / ext / hal / gsthalaudiosrc.c
1 /* GStreamer
2  * (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
3  * (c) 2005 Tim-Philipp Müller <tim centricular net>
4  * (c) 2006 Jürg Billeter <j@bitron.ch>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
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  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:element-halaudiosrc
24  *
25  * HalAudioSrc allows access to input of sound devices by specifying the
26  * corresponding persistent Unique Device Id (UDI) from the Hardware Abstraction
27  * Layer (HAL) in the #GstHalAudioSrc:udi property.
28  * It currently always embeds alsasrc or osssrc as HAL doesn't support other
29  * sound systems yet. You can also specify the UDI of a device that has ALSA or
30  * OSS subdevices. If both are present ALSA is preferred.
31  *
32  * <refsect2>
33  * <title>Examples</title>
34  * |[
35  * hal-find-by-property --key alsa.type --string capture
36  * ]| list the UDIs of all your ALSA input devices
37  * |[
38  * gst-launch -v halaudiosrc udi=/org/freedesktop/Hal/devices/pci_8086_27d8_alsa_capture_0 ! autoaudiosink
39  * ]| You should now hear yourself with a small delay if you have a microphone
40  * connected to the specified sound device.
41  * </refsect2>
42  */
43
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include "gsthalelements.h"
49 #include "gsthalaudiosrc.h"
50
51 static void gst_hal_audio_src_dispose (GObject * object);
52 static GstStateChangeReturn
53 gst_hal_audio_src_change_state (GstElement * element,
54     GstStateChange transition);
55
56 enum
57 {
58   PROP_0,
59   PROP_UDI
60 };
61
62 GST_BOILERPLATE (GstHalAudioSrc, gst_hal_audio_src, GstBin, GST_TYPE_BIN);
63
64 static void gst_hal_audio_src_set_property (GObject * object, guint prop_id,
65     const GValue * value, GParamSpec * pspec);
66 static void gst_hal_audio_src_get_property (GObject * object, guint prop_id,
67     GValue * value, GParamSpec * pspec);
68
69 static void
70 gst_hal_audio_src_base_init (gpointer klass)
71 {
72   GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
73
74   static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
75       GST_PAD_SRC,
76       GST_PAD_ALWAYS,
77       GST_STATIC_CAPS_ANY);
78
79   gst_element_class_add_static_pad_template (eklass, &src_template);
80   gst_element_class_set_details_simple (eklass, "HAL audio source",
81       "Source/Audio",
82       "Audio source for sound device access via HAL",
83       "Jürg Billeter <j@bitron.ch>");
84 }
85
86 static void
87 gst_hal_audio_src_class_init (GstHalAudioSrcClass * klass)
88 {
89   GObjectClass *oklass = G_OBJECT_CLASS (klass);
90   GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
91
92   oklass->set_property = gst_hal_audio_src_set_property;
93   oklass->get_property = gst_hal_audio_src_get_property;
94   oklass->dispose = gst_hal_audio_src_dispose;
95   eklass->change_state = gst_hal_audio_src_change_state;
96
97   g_object_class_install_property (oklass, PROP_UDI,
98       g_param_spec_string ("udi",
99           "UDI", "Unique Device Id", NULL,
100           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
101 }
102
103 /*
104  * Hack to make negotiation work.
105  */
106
107 static void
108 gst_hal_audio_src_reset (GstHalAudioSrc * src)
109 {
110   GstPad *targetpad;
111
112   /* fakesrc */
113   if (src->kid) {
114     gst_element_set_state (src->kid, GST_STATE_NULL);
115     gst_bin_remove (GST_BIN (src), src->kid);
116   }
117   src->kid = gst_element_factory_make ("fakesrc", "testsrc");
118   gst_bin_add (GST_BIN (src), src->kid);
119
120   targetpad = gst_element_get_static_pad (src->kid, "src");
121   gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
122   gst_object_unref (targetpad);
123 }
124
125 static void
126 gst_hal_audio_src_init (GstHalAudioSrc * src, GstHalAudioSrcClass * g_class)
127 {
128   src->pad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
129   gst_element_add_pad (GST_ELEMENT (src), src->pad);
130
131   gst_hal_audio_src_reset (src);
132 }
133
134 static void
135 gst_hal_audio_src_dispose (GObject * object)
136 {
137   GstHalAudioSrc *src = GST_HAL_AUDIO_SRC (object);
138
139   if (src->udi) {
140     g_free (src->udi);
141     src->udi = NULL;
142   }
143
144   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
145 }
146
147 static gboolean
148 do_toggle_element (GstHalAudioSrc * src)
149 {
150   GstPad *targetpad;
151
152   /* kill old element */
153   if (src->kid) {
154     GST_DEBUG_OBJECT (src, "Removing old kid");
155     gst_element_set_state (src->kid, GST_STATE_NULL);
156     gst_bin_remove (GST_BIN (src), src->kid);
157     src->kid = NULL;
158   }
159
160   GST_DEBUG_OBJECT (src, "Creating new kid");
161   if (!src->udi)
162     GST_INFO_OBJECT (src, "No UDI set for device, using default one");
163
164   if (!(src->kid = gst_hal_get_audio_src (src->udi))) {
165     GST_ELEMENT_ERROR (src, LIBRARY, SETTINGS, (NULL),
166         ("Failed to render audio source from Hal"));
167     return FALSE;
168   }
169   gst_element_set_state (src->kid, GST_STATE (src));
170   gst_bin_add (GST_BIN (src), src->kid);
171
172   /* re-attach ghostpad */
173   GST_DEBUG_OBJECT (src, "Creating new ghostpad");
174   targetpad = gst_element_get_static_pad (src->kid, "src");
175   gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
176   gst_object_unref (targetpad);
177   GST_DEBUG_OBJECT (src, "done changing hal audio source");
178
179   return TRUE;
180 }
181
182 static void
183 gst_hal_audio_src_set_property (GObject * object, guint prop_id,
184     const GValue * value, GParamSpec * pspec)
185 {
186   GstHalAudioSrc *this = GST_HAL_AUDIO_SRC (object);
187
188   GST_OBJECT_LOCK (this);
189
190   switch (prop_id) {
191     case PROP_UDI:
192       if (this->udi)
193         g_free (this->udi);
194       this->udi = g_value_dup_string (value);
195       break;
196     default:
197       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
198       break;
199   }
200
201   GST_OBJECT_UNLOCK (this);
202 }
203
204 static void
205 gst_hal_audio_src_get_property (GObject * object, guint prop_id,
206     GValue * value, GParamSpec * pspec)
207 {
208   GstHalAudioSrc *this = GST_HAL_AUDIO_SRC (object);
209
210   GST_OBJECT_LOCK (this);
211
212   switch (prop_id) {
213     case PROP_UDI:
214       g_value_set_string (value, this->udi);
215       break;
216     default:
217       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
218       break;
219   }
220
221   GST_OBJECT_UNLOCK (this);
222 }
223
224 static GstStateChangeReturn
225 gst_hal_audio_src_change_state (GstElement * element, GstStateChange transition)
226 {
227   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
228   GstHalAudioSrc *src = GST_HAL_AUDIO_SRC (element);
229
230   switch (transition) {
231     case GST_STATE_CHANGE_NULL_TO_READY:
232       if (!do_toggle_element (src))
233         return GST_STATE_CHANGE_FAILURE;
234       break;
235     default:
236       break;
237   }
238
239   ret = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
240       (element, transition), GST_STATE_CHANGE_SUCCESS);
241
242   switch (transition) {
243     case GST_STATE_CHANGE_READY_TO_NULL:
244       gst_hal_audio_src_reset (src);
245       break;
246     default:
247       break;
248   }
249
250   return ret;
251 }