2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library 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 GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <sys/types.h>
26 #include <sys/soundcard.h>
27 #include <sys/ioctl.h>
30 #include <gstosssrc.h>
32 static GstElementDetails gst_osssrc_details = {
35 "Read from the sound card",
37 "Erik Walthinsen <omega@cse.ogi.edu>",
42 /* OssSrc signals and args */
58 GST_PADTEMPLATE_FACTORY (osssrc_src_factory,
65 "format", GST_PROPS_STRING ("int"),
66 "law", GST_PROPS_INT (0),
67 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
68 "signed", GST_PROPS_LIST (
69 GST_PROPS_BOOLEAN (TRUE),
70 GST_PROPS_BOOLEAN (FALSE)
72 "width", GST_PROPS_LIST (
76 "depth", GST_PROPS_LIST (
80 "rate", GST_PROPS_INT_RANGE (1000, 48000),
81 "channels", GST_PROPS_INT_RANGE (1, 2)
85 static void gst_osssrc_class_init (GstOssSrcClass *klass);
86 static void gst_osssrc_init (GstOssSrc *osssrc);
88 static void gst_osssrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
89 static void gst_osssrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
90 static GstElementStateReturn gst_osssrc_change_state (GstElement *element);
92 static void gst_osssrc_close_audio (GstOssSrc *src);
93 static gboolean gst_osssrc_open_audio (GstOssSrc *src);
94 static void gst_osssrc_sync_parms (GstOssSrc *osssrc);
96 static GstBuffer * gst_osssrc_get (GstPad *pad);
98 static GstElementClass *parent_class = NULL;
99 /*static guint gst_osssrc_signals[LAST_SIGNAL] = { 0 }; */
102 gst_osssrc_get_type (void)
104 static GType osssrc_type = 0;
107 static const GTypeInfo osssrc_info = {
108 sizeof(GstOssSrcClass),
111 (GClassInitFunc)gst_osssrc_class_init,
116 (GInstanceInitFunc)gst_osssrc_init,
118 osssrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOssSrc", &osssrc_info, 0);
124 gst_osssrc_class_init (GstOssSrcClass *klass)
126 GObjectClass *gobject_class;
127 GstElementClass *gstelement_class;
129 gobject_class = (GObjectClass*)klass;
130 gstelement_class = (GstElementClass*)klass;
132 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
134 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BYTESPERREAD,
135 g_param_spec_ulong("bytes_per_read","bytes_per_read","bytes_per_read",
136 0,G_MAXULONG,0,G_PARAM_READWRITE)); /* CHECKME */
137 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CUROFFSET,
138 g_param_spec_ulong("curoffset","curoffset","curoffset",
139 0,G_MAXULONG,0,G_PARAM_READABLE)); /* CHECKME */
140 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORMAT,
141 g_param_spec_int("format","format","format",
142 G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
143 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNELS,
144 g_param_spec_int("channels","channels","channels",
145 G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
146 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQUENCY,
147 g_param_spec_int("frequency","frequency","frequency",
148 G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
149 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
150 g_param_spec_string("device","device","oss device (/dev/dspN usually)",
151 "default",G_PARAM_READWRITE));
153 gobject_class->set_property = gst_osssrc_set_property;
154 gobject_class->get_property = gst_osssrc_get_property;
156 gstelement_class->change_state = gst_osssrc_change_state;
160 gst_osssrc_init (GstOssSrc *osssrc)
162 osssrc->srcpad = gst_pad_new_from_template (
163 GST_PADTEMPLATE_GET (osssrc_src_factory), "src");
164 gst_pad_set_get_function(osssrc->srcpad,gst_osssrc_get);
165 gst_element_add_pad (GST_ELEMENT (osssrc), osssrc->srcpad);
167 osssrc->device = g_strdup ("/dev/dsp");
170 /* adding some default values */
171 osssrc->format = AFMT_S16_LE;
172 osssrc->channels = 2;
173 osssrc->frequency = 44100;
175 osssrc->bytes_per_read = 4096;
176 osssrc->curoffset = 0;
177 osssrc->basetime = 0;
178 osssrc->samples_since_basetime = 0;
182 gst_osssrc_get (GstPad *pad)
189 g_return_val_if_fail (pad != NULL, NULL);
190 src = GST_OSSSRC(gst_pad_get_parent (pad));
192 GST_DEBUG (GST_CAT_PLUGIN_INFO, "attempting to read something from soundcard\n");
194 buf = gst_buffer_new ();
195 g_return_val_if_fail (buf, NULL);
197 GST_BUFFER_DATA (buf) = (gpointer)g_malloc (src->bytes_per_read);
199 readbytes = read (src->fd,GST_BUFFER_DATA (buf),
200 src->bytes_per_read);
202 if (readbytes == 0) {
203 gst_element_set_eos (GST_ELEMENT (src));
206 if (!GST_PAD_CAPS (pad)) {
207 /* set caps on src pad */
208 if (!gst_pad_try_set_caps (src->srcpad,
212 "format", GST_PROPS_STRING ("int"),
213 "law", GST_PROPS_INT (0), /*FIXME */
214 "endianness", GST_PROPS_INT (G_BYTE_ORDER), /*FIXME */
215 "signed", GST_PROPS_BOOLEAN (TRUE), /*FIXME */
216 "width", GST_PROPS_INT (src->format),
217 "depth", GST_PROPS_INT (src->format),
218 "rate", GST_PROPS_INT (src->frequency),
219 "channels", GST_PROPS_INT (src->channels)
222 gst_element_error (GST_ELEMENT (src), "could not set caps");
227 GST_BUFFER_SIZE (buf) = readbytes;
228 GST_BUFFER_OFFSET (buf) = src->curoffset;
229 GST_BUFFER_TIMESTAMP (buf) = src->basetime +
230 src->samples_since_basetime * 1000000LL / src->frequency;
232 src->curoffset += readbytes;
233 readsamples = readbytes / src->channels;
234 if (src->format == 16) readsamples /= 2;
235 src->samples_since_basetime += readsamples;
237 GST_DEBUG (GST_CAT_PLUGIN_INFO, "pushed buffer from soundcard of %ld bytes, timestamp %lld\n", readbytes, GST_BUFFER_TIMESTAMP (buf));
242 gst_osssrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
246 /* it's not null if we got it, but it might not be ours */
247 g_return_if_fail (GST_IS_OSSSRC (object));
249 src = GST_OSSSRC (object);
252 case ARG_BYTESPERREAD:
253 src->bytes_per_read = g_value_get_ulong (value);
256 src->format = g_value_get_int (value);
259 src->channels = g_value_get_int (value);
262 /* Preserve the timestamps */
263 src->basetime = src->samples_since_basetime * 1000000LL / src->frequency;
264 src->samples_since_basetime = 0;
266 src->frequency = g_value_get_int (value);
269 src->curoffset = g_value_get_int (value);
273 src->device = g_strdup (g_value_get_string (value));
281 gst_osssrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
285 /* it's not null if we got it, but it might not be ours */
286 g_return_if_fail (GST_IS_OSSSRC (object));
288 src = GST_OSSSRC (object);
291 case ARG_BYTESPERREAD:
292 g_value_set_ulong (value, src->bytes_per_read);
295 g_value_set_int (value, src->format);
298 g_value_set_int (value, src->channels);
301 g_value_set_int (value, src->frequency);
304 g_value_set_ulong (value, src->curoffset);
307 g_value_set_string (value, src->device);
310 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
315 static GstElementStateReturn
316 gst_osssrc_change_state (GstElement *element)
318 /* GstOssSrc *src = GST_OSSSRC (element); */
320 g_return_val_if_fail (GST_IS_OSSSRC (element), FALSE);
321 GST_DEBUG (GST_CAT_PLUGIN_INFO, "osssrc: state change\n");
322 /* if going down into NULL state, close the file if it's open */
323 if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
324 if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN))
325 gst_osssrc_close_audio (GST_OSSSRC (element));
326 /* otherwise (READY or higher) we need to open the sound card */
328 GST_DEBUG (GST_CAT_PLUGIN_INFO, "DEBUG: osssrc: ready or higher\n");
330 if (!GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) {
331 if (!gst_osssrc_open_audio (GST_OSSSRC (element)))
332 return GST_STATE_FAILURE;
335 GST_DEBUG (GST_CAT_PLUGIN_INFO, "osssrc: device opened successfully\n");
336 /* thomas: we can't set caps here because the element is
337 * not actually ready yet */
342 if (GST_ELEMENT_CLASS (parent_class)->change_state)
343 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
345 return GST_STATE_SUCCESS;
349 gst_osssrc_open_audio (GstOssSrc *src)
351 g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_OSSSRC_OPEN), FALSE);
353 /* first try to open the sound card */
354 src->fd = open(src->device, O_RDONLY);
356 /* if we have it, set the default parameters and go have fun */
360 gst_osssrc_sync_parms (src);
361 GST_DEBUG (GST_CAT_PLUGIN_INFO,"opened audio: %s\n",src->device);
363 GST_FLAG_SET (src, GST_OSSSRC_OPEN);
371 gst_osssrc_close_audio (GstOssSrc *src)
373 g_return_if_fail (GST_FLAG_IS_SET (src, GST_OSSSRC_OPEN));
378 GST_FLAG_UNSET (src, GST_OSSSRC_OPEN);
382 gst_osssrc_sync_parms (GstOssSrc *osssrc)
384 audio_buf_info ispace;
386 /* remember : ioctl on samplerate returns the sample rate the card
387 * is actually set to ! Setting it to 44101 KHz could cause it to
388 * be set to 44101, for example
393 g_return_if_fail (osssrc != NULL);
394 g_return_if_fail (GST_IS_OSSSRC (osssrc));
395 g_return_if_fail (osssrc->fd > 0);
397 frequency = osssrc->frequency;
401 ioctl(osssrc->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
402 ioctl(osssrc->fd, SNDCTL_DSP_RESET, 0);
404 ioctl(osssrc->fd, SNDCTL_DSP_SETFMT, &osssrc->format);
405 ioctl(osssrc->fd, SNDCTL_DSP_CHANNELS, &osssrc->channels);
406 ioctl(osssrc->fd, SNDCTL_DSP_SPEED, &osssrc->frequency);
407 osssrc->frequency = frequency;
408 ioctl(osssrc->fd, SNDCTL_DSP_SPEED, &frequency);
409 ioctl(osssrc->fd, SNDCTL_DSP_GETISPACE, &ispace);
410 ioctl(osssrc->fd, SNDCTL_DSP_GETBLKSIZE, &frag);
412 g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
413 osssrc->frequency, osssrc->format,
414 (osssrc->channels == 2) ? "stereo" : "mono", ispace.bytes, frag);
419 gst_osssrc_factory_init (GstPlugin *plugin)
421 GstElementFactory *factory;
423 factory = gst_elementfactory_new ("osssrc", GST_TYPE_OSSSRC, &gst_osssrc_details);
424 g_return_val_if_fail (factory != NULL, FALSE);
426 gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (osssrc_src_factory));
428 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));