2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000,2005 Wim Taymans <wim@fluendo.com>
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.
26 #include <sys/ioctl.h>
31 #include <sys/soundcard.h>
33 #include "gstosssrc.h"
35 GST_DEBUG_CATEGORY_EXTERN (oss_debug);
36 #define GST_CAT_DEFAULT oss_debug
38 static GstElementDetails gst_oss_src_details =
39 GST_ELEMENT_DETAILS ("Audio Source (OSS)",
41 "Capture from a sound card via OSS",
42 "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
44 #define DEFAULT_DEVICE "/dev/dsp"
45 #define DEFAULT_DEVICE_NAME ""
54 GST_BOILERPLATE_WITH_INTERFACE (GstOssSrc, gst_oss_src, GstAudioSrc,
55 GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_oss_src_mixer);
57 GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssSrc, gst_oss_src_mixer);
59 static void gst_oss_src_get_property (GObject * object, guint prop_id,
60 GValue * value, GParamSpec * pspec);
61 static void gst_oss_src_set_property (GObject * object, guint prop_id,
62 const GValue * value, GParamSpec * pspec);
64 static void gst_oss_src_dispose (GObject * object);
66 static GstCaps *gst_oss_src_getcaps (GstBaseSrc * bsrc);
68 static gboolean gst_oss_src_open (GstAudioSrc * asrc);
69 static gboolean gst_oss_src_close (GstAudioSrc * asrc);
70 static gboolean gst_oss_src_prepare (GstAudioSrc * asrc,
71 GstRingBufferSpec * spec);
72 static gboolean gst_oss_src_unprepare (GstAudioSrc * asrc);
73 static guint gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length);
74 static guint gst_oss_src_delay (GstAudioSrc * asrc);
75 static void gst_oss_src_reset (GstAudioSrc * asrc);
79 static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
82 GST_STATIC_CAPS ("audio/x-raw-int, "
83 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
84 "signed = (boolean) { TRUE, FALSE }, "
87 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
89 "signed = (boolean) { TRUE, FALSE }, "
92 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
97 gst_oss_src_dispose (GObject * object)
99 G_OBJECT_CLASS (parent_class)->dispose (object);
103 gst_oss_src_base_init (gpointer g_class)
105 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
107 gst_element_class_set_details (element_class, &gst_oss_src_details);
109 gst_element_class_add_pad_template (element_class,
110 gst_static_pad_template_get (&osssrc_src_factory));
113 gst_oss_src_class_init (GstOssSrcClass * klass)
115 GObjectClass *gobject_class;
116 GstElementClass *gstelement_class;
117 GstBaseSrcClass *gstbasesrc_class;
118 GstBaseAudioSrcClass *gstbaseaudiosrc_class;
119 GstAudioSrcClass *gstaudiosrc_class;
121 gobject_class = (GObjectClass *) klass;
122 gstelement_class = (GstElementClass *) klass;
123 gstbasesrc_class = (GstBaseSrcClass *) klass;
124 gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
125 gstaudiosrc_class = (GstAudioSrcClass *) klass;
127 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss_src_dispose);
128 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss_src_get_property);
129 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss_src_set_property);
131 gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_src_getcaps);
133 gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss_src_open);
134 gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_src_prepare);
135 gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_src_unprepare);
136 gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss_src_close);
137 gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss_src_read);
138 gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss_src_delay);
139 gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss_src_reset);
141 g_object_class_install_property (gobject_class, PROP_DEVICE,
142 g_param_spec_string ("device", "Device",
143 "OSS device (usually /dev/dspN)", DEFAULT_DEVICE, G_PARAM_READWRITE));
145 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
146 g_param_spec_string ("device-name", "Device name",
147 "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
152 gst_oss_src_set_property (GObject * object, guint prop_id,
153 const GValue * value, GParamSpec * pspec)
157 src = GST_OSS_SRC (object);
162 g_free (src->device);
163 src->device = g_value_dup_string (value);
166 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172 gst_oss_src_get_property (GObject * object, guint prop_id,
173 GValue * value, GParamSpec * pspec)
177 src = GST_OSS_SRC (object);
181 g_value_set_string (value, src->device);
183 case PROP_DEVICE_NAME:
184 g_value_set_string (value, src->device_name);
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193 gst_oss_src_init (GstOssSrc * osssrc, GstOssSrcClass * g_class)
195 GST_DEBUG ("initializing osssrc");
198 osssrc->device = g_strdup (DEFAULT_DEVICE);
199 osssrc->device_name = g_strdup (DEFAULT_DEVICE_NAME);
203 gst_oss_src_getcaps (GstBaseSrc * bsrc)
208 osssrc = GST_OSS_SRC (bsrc);
210 if (osssrc->fd == -1) {
211 caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
214 caps = gst_oss_helper_probe_caps (osssrc->fd);
223 /* well... hacker's delight explains... */
229 x = x - ((x >> 1) & 0x55555555);
230 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
231 x = (x + (x >> 4)) & 0x0f0f0f0f;
234 return (x & 0x0000003f) - 1;
237 #define SET_PARAM(_oss, _name, _val) \
240 if (ioctl(_oss->fd, _name, &_tmp) == -1) { \
241 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ, \
242 ("Unable to set param "G_STRINGIFY (_name)": %s", \
243 g_strerror (errno)), \
247 GST_DEBUG_OBJECT (_oss, G_STRINGIFY (_name)" %d", _tmp); \
250 #define GET_PARAM(_oss, _name, _val) \
252 if (ioctl(oss->fd, _name, _val) == -1) { \
253 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ, \
254 ("Unable to get param "G_STRINGIFY (_name)": %s", \
255 g_strerror (errno)), \
259 GST_DEBUG_OBJECT (_oss, G_STRINGIFY (_name)" %d", _val); \
263 gst_oss_src_get_format (GstBufferFormat fmt)
269 result = AFMT_MU_LAW;
275 result = AFMT_IMA_ADPCM;
281 result = AFMT_S16_LE;
284 result = AFMT_S16_BE;
290 result = AFMT_U16_LE;
293 result = AFMT_U16_BE;
306 gst_oss_src_open (GstAudioSrc * asrc)
311 oss = GST_OSS_SRC (asrc);
316 oss->fd = open (oss->device, mode, 0);
321 oss->mixer = gst_ossmixer_new ("/dev/mixer", GST_OSS_MIXER_CAPTURE);
324 g_free (oss->device_name);
325 oss->device_name = g_strdup (oss->mixer->cardname);
332 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
333 ("Unable to open device %s for recording: %s",
334 oss->device, g_strerror (errno)), (NULL));
340 gst_oss_src_close (GstAudioSrc * asrc)
344 oss = GST_OSS_SRC (asrc);
349 gst_ossmixer_free (oss->mixer);
357 gst_oss_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
360 struct audio_buf_info info;
364 oss = GST_OSS_SRC (asrc);
366 mode = fcntl (oss->fd, F_GETFL);
368 if (fcntl (oss->fd, F_SETFL, mode) == -1)
371 tmp = gst_oss_src_get_format (spec->format);
375 tmp = ilog2 (spec->segsize);
376 tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
377 GST_DEBUG ("set segsize: %d, segtotal: %d, value: %08x", spec->segsize,
378 spec->segtotal, tmp);
380 SET_PARAM (oss, SNDCTL_DSP_SETFRAGMENT, tmp);
382 SET_PARAM (oss, SNDCTL_DSP_RESET, 0);
384 SET_PARAM (oss, SNDCTL_DSP_SETFMT, tmp);
385 if (spec->channels == 2)
386 SET_PARAM (oss, SNDCTL_DSP_STEREO, 1);
387 SET_PARAM (oss, SNDCTL_DSP_CHANNELS, spec->channels);
388 SET_PARAM (oss, SNDCTL_DSP_SPEED, spec->rate);
390 GET_PARAM (oss, SNDCTL_DSP_GETISPACE, &info);
392 spec->segsize = info.fragsize;
393 spec->segtotal = info.fragstotal;
395 if (spec->width != 16 && spec->width != 8)
398 spec->bytes_per_sample = (spec->width / 8) * spec->channels;
399 oss->bytes_per_sample = (spec->width / 8) * spec->channels;
400 memset (spec->silence_sample, 0, spec->bytes_per_sample);
402 GST_DEBUG ("got segsize: %d, segtotal: %d, value: %08x", spec->segsize,
403 spec->segtotal, tmp);
409 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
410 ("Unable to set device %s in non blocking mode: %s",
411 oss->device, g_strerror (errno)), (NULL));
416 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
417 ("Unable to get format %d", spec->format), (NULL));
422 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
423 ("Unexpected width %d", spec->width), (NULL));
429 gst_oss_src_unprepare (GstAudioSrc * asrc)
431 /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
433 if (!gst_oss_src_close (asrc))
436 if (!gst_oss_src_open (asrc))
443 GST_DEBUG ("Could not close the audio device");
448 GST_DEBUG ("Could not reopen the audio device");
454 gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length)
456 return read (GST_OSS_SRC (asrc)->fd, data, length);
460 gst_oss_src_delay (GstAudioSrc * asrc)
466 oss = GST_OSS_SRC (asrc);
468 #ifdef SNDCTL_DSP_GETODELAY
469 ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
476 ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
478 delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
480 return delay / oss->bytes_per_sample;
484 gst_oss_src_reset (GstAudioSrc * asrc)
490 oss = GST_OSS_SRC (asrc);
492 /* deadlocks on my machine... */
493 //ret = ioctl (oss->fd, SNDCTL_DSP_RESET, 0);