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_WITH_INTERFACE (GstOssSrc, gst_oss_src, GstAudioSrc,
51 GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_oss_src_mixer);
53 GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssSrc, gst_oss_src_mixer);
55 static void gst_oss_src_get_property (GObject * object, guint prop_id,
56 GValue * value, GParamSpec * pspec);
57 static void gst_oss_src_set_property (GObject * object, guint prop_id,
58 const GValue * value, GParamSpec * pspec);
60 static void gst_oss_src_dispose (GObject * object);
62 static GstCaps *gst_oss_src_getcaps (GstBaseSrc * bsrc);
64 static gboolean gst_oss_src_open (GstAudioSrc * asrc);
65 static gboolean gst_oss_src_close (GstAudioSrc * asrc);
66 static gboolean gst_oss_src_prepare (GstAudioSrc * asrc,
67 GstRingBufferSpec * spec);
68 static gboolean gst_oss_src_unprepare (GstAudioSrc * asrc);
69 static guint gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length);
70 static guint gst_oss_src_delay (GstAudioSrc * asrc);
71 static void gst_oss_src_reset (GstAudioSrc * asrc);
75 static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
78 GST_STATIC_CAPS ("audio/x-raw-int, "
79 "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
80 "signed = (boolean) { TRUE, FALSE }, "
83 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
85 "signed = (boolean) { TRUE, FALSE }, "
88 "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
93 gst_oss_src_dispose (GObject * object)
95 G_OBJECT_CLASS (parent_class)->dispose (object);
99 gst_oss_src_base_init (gpointer g_class)
101 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
103 gst_element_class_set_details (element_class, &gst_oss_src_details);
105 gst_element_class_add_pad_template (element_class,
106 gst_static_pad_template_get (&osssrc_src_factory));
109 gst_oss_src_class_init (GstOssSrcClass * klass)
111 GObjectClass *gobject_class;
112 GstElementClass *gstelement_class;
113 GstBaseSrcClass *gstbasesrc_class;
114 GstBaseAudioSrcClass *gstbaseaudiosrc_class;
115 GstAudioSrcClass *gstaudiosrc_class;
117 gobject_class = (GObjectClass *) klass;
118 gstelement_class = (GstElementClass *) klass;
119 gstbasesrc_class = (GstBaseSrcClass *) klass;
120 gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
121 gstaudiosrc_class = (GstAudioSrcClass *) klass;
123 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss_src_dispose);
124 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss_src_get_property);
125 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss_src_set_property);
127 gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_src_getcaps);
129 gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss_src_open);
130 gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_src_prepare);
131 gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_src_unprepare);
132 gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss_src_close);
133 gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss_src_read);
134 gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss_src_delay);
135 gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss_src_reset);
137 g_object_class_install_property (gobject_class, PROP_DEVICE,
138 g_param_spec_string ("device", "Device",
139 "OSS device (usually /dev/dspN)", "/dev/dsp", G_PARAM_READWRITE));
141 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
142 g_param_spec_string ("device-name", "Device name",
143 "Human-readable name of the sound device", "", G_PARAM_READABLE));
147 gst_oss_src_set_property (GObject * object, guint prop_id,
148 const GValue * value, GParamSpec * pspec)
152 src = GST_OSS_SRC (object);
157 g_free (src->device);
158 src->device = g_strdup (g_value_get_string (value));
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167 gst_oss_src_get_property (GObject * object, guint prop_id,
168 GValue * value, GParamSpec * pspec)
172 src = GST_OSS_SRC (object);
176 g_value_set_string (value, src->device);
178 case PROP_DEVICE_NAME:
179 g_value_set_string (value, src->device_name);
182 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
188 gst_oss_src_init (GstOssSrc * osssrc)
190 GST_DEBUG ("initializing osssrc");
193 osssrc->device = g_strdup ("/dev/dsp");
197 gst_oss_src_getcaps (GstBaseSrc * bsrc)
202 osssrc = GST_OSS_SRC (bsrc);
204 if (osssrc->fd == -1) {
205 caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
208 caps = gst_oss_helper_probe_caps (osssrc->fd);
217 /* well... hacker's delight explains... */
223 x = x - ((x >> 1) & 0x55555555);
224 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
225 x = (x + (x >> 4)) & 0x0f0f0f0f;
228 return (x & 0x0000003f) - 1;
231 #define SET_PARAM(_oss, _label, _name, _val) \
234 if (ioctl(_oss->fd, _name, &_tmp) == -1) { \
238 GST_DEBUG_OBJECT (_oss, _label " %d", _tmp); \
241 #define GET_PARAM(oss, label, name, val) \
243 if (ioctl(oss->fd, name, val) == -1) { \
250 gst_oss_src_get_format (GstBufferFormat fmt)
256 result = AFMT_MU_LAW;
262 result = AFMT_IMA_ADPCM;
268 result = AFMT_S16_LE;
271 result = AFMT_S16_BE;
277 result = AFMT_U16_LE;
280 result = AFMT_U16_BE;
293 gst_oss_src_open (GstAudioSrc * asrc)
298 oss = GST_OSS_SRC (asrc);
303 oss->fd = open (oss->device, mode, 0);
305 perror (oss->device);
310 oss->mixer = gst_ossmixer_new ("/dev/mixer", GST_OSS_MIXER_CAPTURE);
316 gst_oss_src_close (GstAudioSrc * asrc)
320 oss = GST_OSS_SRC (asrc);
325 gst_ossmixer_free (oss->mixer);
333 gst_oss_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
336 struct audio_buf_info info;
340 oss = GST_OSS_SRC (asrc);
342 mode = fcntl (oss->fd, F_GETFL);
344 if (fcntl (oss->fd, F_SETFL, mode) == -1) {
345 perror (oss->device);
349 tmp = gst_oss_src_get_format (spec->format);
353 tmp = ilog2 (spec->segsize);
354 tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
355 GST_DEBUG ("set segsize: %d, segtotal: %d, value: %08x", spec->segsize,
356 spec->segtotal, tmp);
358 SET_PARAM (oss, "SETFRAGMENT", SNDCTL_DSP_SETFRAGMENT, tmp);
360 SET_PARAM (oss, "RESET", SNDCTL_DSP_RESET, 0);
362 SET_PARAM (oss, "SETFMT", SNDCTL_DSP_SETFMT, tmp);
363 if (spec->channels == 2)
364 SET_PARAM (oss, "STEREO", SNDCTL_DSP_STEREO, 1);
365 SET_PARAM (oss, "CHANNELS", SNDCTL_DSP_CHANNELS, spec->channels);
366 SET_PARAM (oss, "SPEED", SNDCTL_DSP_SPEED, spec->rate);
368 GET_PARAM (oss, "GETISPACE", SNDCTL_DSP_GETISPACE, &info);
370 spec->segsize = info.fragsize;
371 spec->segtotal = info.fragstotal;
372 spec->bytes_per_sample = 4;
373 oss->bytes_per_sample = 4;
374 memset (spec->silence_sample, 0, spec->bytes_per_sample);
376 GST_DEBUG ("got segsize: %d, segtotal: %d, value: %08x", spec->segsize,
377 spec->segtotal, tmp);
383 GST_DEBUG ("wrong format %d\n", spec->format);
389 gst_oss_src_unprepare (GstAudioSrc * asrc)
391 /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
393 if (!gst_oss_src_close (asrc))
396 if (!gst_oss_src_open (asrc))
403 GST_DEBUG ("Could not close the audio device");
408 GST_DEBUG ("Could not reopen the audio device");
414 gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length)
416 return read (GST_OSS_SRC (asrc)->fd, data, length);
420 gst_oss_src_delay (GstAudioSrc * asrc)
426 oss = GST_OSS_SRC (asrc);
428 #ifdef SNDCTL_DSP_GETODELAY
429 ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
436 ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
438 delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
440 return delay / oss->bytes_per_sample;
444 gst_oss_src_reset (GstAudioSrc * asrc)
450 oss = GST_OSS_SRC (asrc);
452 /* deadlocks on my machine... */
453 //ret = ioctl (oss->fd, SNDCTL_DSP_RESET, 0);