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"
36 static GstElementDetails gst_oss_src_details =
37 GST_ELEMENT_DETAILS ("Audio Source (OSS)",
39 "Capture from a sound card via OSS",
40 "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
50 GST_BOILERPLATE (GstOssSrc, gst_oss_src, GstAudioSrc, GST_TYPE_AUDIO_SRC);
53 GST_BOILERPLATE_WITH_INTERFACE (GstOssSrc, gst_oss_src, GstAudioSrc, GST_TYPE_AUDIO_SRC,
54 GstMixer, GST_TYPE_MIXER, gst_oss_src_mixer);
55 GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssSrc, gst_oss_src_mixer);
58 static void gst_oss_src_get_property (GObject * object, guint prop_id,
59 GValue * value, GParamSpec * pspec);
60 static void gst_oss_src_set_property (GObject * object, guint prop_id,
61 const GValue * value, GParamSpec * pspec);
63 static void gst_oss_src_dispose (GObject * object);
65 static GstCaps *gst_oss_src_getcaps (GstBaseSrc * bsrc);
67 static gboolean gst_oss_src_open (GstAudioSrc * asrc);
68 static gboolean gst_oss_src_close (GstAudioSrc * asrc);
69 static gboolean gst_oss_src_prepare (GstAudioSrc * asrc,
70 GstRingBufferSpec * spec);
71 static gboolean gst_oss_src_unprepare (GstAudioSrc * asrc);
72 static guint gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length);
73 static guint gst_oss_src_delay (GstAudioSrc * asrc);
74 static void gst_oss_src_reset (GstAudioSrc * asrc);
78 static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
81 GST_STATIC_CAPS ("audio/x-raw-int, "
82 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
83 "signed = (boolean) { TRUE, FALSE }, "
86 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
88 "signed = (boolean) { TRUE, FALSE }, "
91 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
96 gst_oss_src_dispose (GObject * object)
98 G_OBJECT_CLASS (parent_class)->dispose (object);
102 gst_oss_src_base_init (gpointer g_class)
104 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
106 gst_element_class_set_details (element_class, &gst_oss_src_details);
108 gst_element_class_add_pad_template (element_class,
109 gst_static_pad_template_get (&osssrc_src_factory));
112 gst_oss_src_class_init (GstOssSrcClass * klass)
114 GObjectClass *gobject_class;
115 GstElementClass *gstelement_class;
116 GstBaseSrcClass *gstbasesrc_class;
117 GstBaseAudioSrcClass *gstbaseaudiosrc_class;
118 GstAudioSrcClass *gstaudiosrc_class;
120 gobject_class = (GObjectClass *) klass;
121 gstelement_class = (GstElementClass *) klass;
122 gstbasesrc_class = (GstBaseSrcClass *) klass;
123 gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
124 gstaudiosrc_class = (GstAudioSrcClass *) klass;
126 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss_src_dispose);
127 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss_src_get_property);
128 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss_src_set_property);
130 gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_src_getcaps);
132 gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss_src_open);
133 gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_src_prepare);
134 gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_src_unprepare);
135 gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss_src_close);
136 gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss_src_read);
137 gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss_src_delay);
138 gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss_src_reset);
140 g_object_class_install_property (gobject_class, PROP_DEVICE,
141 g_param_spec_string ("device", "Device",
142 "OSS device (usually /dev/dspN)", "/dev/dsp", G_PARAM_READWRITE));
144 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
145 g_param_spec_string ("device-name", "Device name",
146 "Human-readable name of the sound device", "", G_PARAM_READABLE));
150 gst_oss_src_set_property (GObject * object, guint prop_id,
151 const GValue * value, GParamSpec * pspec)
155 src = GST_OSS_SRC (object);
160 g_free (src->device);
161 src->device = g_strdup (g_value_get_string (value));
164 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 gst_oss_src_get_property (GObject * object, guint prop_id,
171 GValue * value, GParamSpec * pspec)
175 src = GST_OSS_SRC (object);
179 g_value_set_string (value, src->device);
181 case PROP_DEVICE_NAME:
182 g_value_set_string (value, src->device_name);
185 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191 gst_oss_src_init (GstOssSrc * osssrc)
193 GST_DEBUG ("initializing osssrc");
196 osssrc->device = g_strdup ("/dev/dsp");
200 gst_oss_src_getcaps (GstBaseSrc * bsrc)
205 osssrc = GST_OSS_SRC (bsrc);
207 if (osssrc->fd == -1) {
208 caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
211 caps = gst_oss_helper_probe_caps (osssrc->fd);
220 /* well... hacker's delight explains... */
226 x = x - ((x >> 1) & 0x55555555);
227 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
228 x = (x + (x >> 4)) & 0x0f0f0f0f;
231 return (x & 0x0000003f) - 1;
234 #define SET_PARAM(_oss, _label, _name, _val) \
237 if (ioctl(_oss->fd, _name, &_tmp) == -1) { \
241 GST_DEBUG_OBJECT (_oss, _label " %d", _tmp); \
244 #define GET_PARAM(oss, label, name, val) \
246 if (ioctl(oss->fd, name, val) == -1) { \
253 gst_oss_src_get_format (GstBufferFormat fmt)
259 result = AFMT_MU_LAW;
265 result = AFMT_IMA_ADPCM;
271 result = AFMT_S16_LE;
274 result = AFMT_S16_BE;
280 result = AFMT_U16_LE;
283 result = AFMT_U16_BE;
296 gst_oss_src_open (GstAudioSrc * asrc)
301 oss = GST_OSS_SRC (asrc);
306 oss->fd = open (oss->device, mode, 0);
308 perror (oss->device);
316 gst_oss_src_close (GstAudioSrc * asrc)
318 close (GST_OSS_SRC (asrc)->fd);
323 gst_oss_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
326 struct audio_buf_info info;
330 oss = GST_OSS_SRC (asrc);
332 mode = fcntl (oss->fd, F_GETFL);
334 if (fcntl (oss->fd, F_SETFL, mode) == -1) {
335 perror (oss->device);
339 tmp = gst_oss_src_get_format (spec->format);
343 tmp = ilog2 (spec->segsize);
344 tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
345 GST_DEBUG ("set segsize: %d, segtotal: %d, value: %08x", spec->segsize,
346 spec->segtotal, tmp);
348 SET_PARAM (oss, "SETFRAGMENT", SNDCTL_DSP_SETFRAGMENT, tmp);
350 SET_PARAM (oss, "RESET", SNDCTL_DSP_RESET, 0);
352 SET_PARAM (oss, "SETFMT", SNDCTL_DSP_SETFMT, tmp);
353 if (spec->channels == 2)
354 SET_PARAM (oss, "STEREO", SNDCTL_DSP_STEREO, 1);
355 SET_PARAM (oss, "CHANNELS", SNDCTL_DSP_CHANNELS, spec->channels);
356 SET_PARAM (oss, "SPEED", SNDCTL_DSP_SPEED, spec->rate);
358 GET_PARAM (oss, "GETISPACE", SNDCTL_DSP_GETISPACE, &info);
360 spec->segsize = info.fragsize;
361 spec->segtotal = info.fragstotal;
362 spec->bytes_per_sample = 4;
363 oss->bytes_per_sample = 4;
364 memset (spec->silence_sample, 0, spec->bytes_per_sample);
366 GST_DEBUG ("got segsize: %d, segtotal: %d, value: %08x", spec->segsize,
367 spec->segtotal, tmp);
373 GST_DEBUG ("wrong format %d\n", spec->format);
379 gst_oss_src_unprepare (GstAudioSrc * asrc)
381 /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
383 if (!gst_oss_src_close (asrc))
386 if (!gst_oss_src_open (asrc))
393 GST_DEBUG ("Could not close the audio device");
398 GST_DEBUG ("Could not reopen the audio device");
404 gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length)
406 return read (GST_OSS_SRC (asrc)->fd, data, length);
410 gst_oss_src_delay (GstAudioSrc * asrc)
416 oss = GST_OSS_SRC (asrc);
418 #ifdef SNDCTL_DSP_GETODELAY
419 ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
426 ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
428 delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
430 return delay / oss->bytes_per_sample;
434 gst_oss_src_reset (GstAudioSrc * asrc)
440 oss = GST_OSS_SRC (asrc);
442 /* deadlocks on my machine... */
443 //ret = ioctl (oss->fd, SNDCTL_DSP_RESET, 0);