upload tizen1.0 source
[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_pad_template (eklass,
80       gst_static_pad_template_get (&src_template));
81   gst_element_class_set_details_simple (eklass, "HAL audio source",
82       "Source/Audio",
83       "Audio source for sound device access via HAL",
84       "Jürg Billeter <j@bitron.ch>");
85 }
86
87 static void
88 gst_hal_audio_src_class_init (GstHalAudioSrcClass * klass)
89 {
90   GObjectClass *oklass = G_OBJECT_CLASS (klass);
91   GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
92
93   oklass->set_property = gst_hal_audio_src_set_property;
94   oklass->get_property = gst_hal_audio_src_get_property;
95   oklass->dispose = gst_hal_audio_src_dispose;
96   eklass->change_state = gst_hal_audio_src_change_state;
97
98   g_object_class_install_property (oklass, PROP_UDI,
99       g_param_spec_string ("udi",
100           "UDI", "Unique Device Id", NULL,
101           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
102 }
103
104 /*
105  * Hack to make negotiation work.
106  */
107
108 static void
109 gst_hal_audio_src_reset (GstHalAudioSrc * src)
110 {
111   GstPad *targetpad;
112
113   /* fakesrc */
114   if (src->kid) {
115     gst_element_set_state (src->kid, GST_STATE_NULL);
116     gst_bin_remove (GST_BIN (src), src->kid);
117   }
118   src->kid = gst_element_factory_make ("fakesrc", "testsrc");
119   gst_bin_add (GST_BIN (src), src->kid);
120
121   targetpad = gst_element_get_static_pad (src->kid, "src");
122   gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
123   gst_object_unref (targetpad);
124 }
125
126 static void
127 gst_hal_audio_src_init (GstHalAudioSrc * src, GstHalAudioSrcClass * g_class)
128 {
129   src->pad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
130   gst_element_add_pad (GST_ELEMENT (src), src->pad);
131
132   gst_hal_audio_src_reset (src);
133 }
134
135 static void
136 gst_hal_audio_src_dispose (GObject * object)
137 {
138   GstHalAudioSrc *src = GST_HAL_AUDIO_SRC (object);
139
140   if (src->udi) {
141     g_free (src->udi);
142     src->udi = NULL;
143   }
144
145   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
146 }
147
148 static gboolean
149 do_toggle_element (GstHalAudioSrc * src)
150 {
151   GstPad *targetpad;
152
153   /* kill old element */
154   if (src->kid) {
155     GST_DEBUG_OBJECT (src, "Removing old kid");
156     gst_element_set_state (src->kid, GST_STATE_NULL);
157     gst_bin_remove (GST_BIN (src), src->kid);
158     src->kid = NULL;
159   }
160
161   GST_DEBUG_OBJECT (src, "Creating new kid");
162   if (!src->udi)
163     GST_INFO_OBJECT (src, "No UDI set for device, using default one");
164
165   if (!(src->kid = gst_hal_get_audio_src (src->udi))) {
166     GST_ELEMENT_ERROR (src, LIBRARY, SETTINGS, (NULL),
167         ("Failed to render audio source from Hal"));
168     return FALSE;
169   }
170   gst_element_set_state (src->kid, GST_STATE (src));
171   gst_bin_add (GST_BIN (src), src->kid);
172
173   /* re-attach ghostpad */
174   GST_DEBUG_OBJECT (src, "Creating new ghostpad");
175   targetpad = gst_element_get_static_pad (src->kid, "src");
176   gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
177   gst_object_unref (targetpad);
178   GST_DEBUG_OBJECT (src, "done changing hal audio source");
179
180   return TRUE;
181 }
182
183 static void
184 gst_hal_audio_src_set_property (GObject * object, guint prop_id,
185     const GValue * value, GParamSpec * pspec)
186 {
187   GstHalAudioSrc *this = GST_HAL_AUDIO_SRC (object);
188
189   GST_OBJECT_LOCK (this);
190
191   switch (prop_id) {
192     case PROP_UDI:
193       if (this->udi)
194         g_free (this->udi);
195       this->udi = g_value_dup_string (value);
196       break;
197     default:
198       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
199       break;
200   }
201
202   GST_OBJECT_UNLOCK (this);
203 }
204
205 static void
206 gst_hal_audio_src_get_property (GObject * object, guint prop_id,
207     GValue * value, GParamSpec * pspec)
208 {
209   GstHalAudioSrc *this = GST_HAL_AUDIO_SRC (object);
210
211   GST_OBJECT_LOCK (this);
212
213   switch (prop_id) {
214     case PROP_UDI:
215       g_value_set_string (value, this->udi);
216       break;
217     default:
218       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
219       break;
220   }
221
222   GST_OBJECT_UNLOCK (this);
223 }
224
225 static GstStateChangeReturn
226 gst_hal_audio_src_change_state (GstElement * element, GstStateChange transition)
227 {
228   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
229   GstHalAudioSrc *src = GST_HAL_AUDIO_SRC (element);
230
231   switch (transition) {
232     case GST_STATE_CHANGE_NULL_TO_READY:
233       if (!do_toggle_element (src))
234         return GST_STATE_CHANGE_FAILURE;
235       break;
236     default:
237       break;
238   }
239
240   ret = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
241       (element, transition), GST_STATE_CHANGE_SUCCESS);
242
243   switch (transition) {
244     case GST_STATE_CHANGE_READY_TO_NULL:
245       gst_hal_audio_src_reset (src);
246       break;
247     default:
248       break;
249   }
250
251   return ret;
252 }