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.
24 #include <sys/types.h>
26 #include <sys/ioctl.h>
28 #include <sys/soundcard.h>
32 //#define DEBUG_ENABLED
34 #include <gstaudiosink.h>
35 #include <gst/meta/audioraw.h>
38 GstElementDetails gst_audiosink_details = {
41 "Output to a sound card via OSS",
43 "Erik Walthinsen <omega@cse.ogi.edu>",
47 static void gst_audiosink_class_init (GstAudioSinkClass *klass);
48 static void gst_audiosink_init (GstAudioSink *audiosink);
50 static gboolean gst_audiosink_open_audio (GstAudioSink *sink);
51 static void gst_audiosink_close_audio (GstAudioSink *sink);
52 static GstElementStateReturn gst_audiosink_change_state (GstElement *element);
54 static void gst_audiosink_set_arg (GtkObject *object, GtkArg *arg, guint id);
55 static void gst_audiosink_get_arg (GtkObject *object, GtkArg *arg, guint id);
57 static void gst_audiosink_chain (GstPad *pad,GstBuffer *buf);
59 /* AudioSink signals and args */
74 static GstPadFactory audiosink_sink_factory = {
77 GST_PAD_FACTORY_ALWAYS,
78 GST_PAD_FACTORY_CAPS (
81 "format", GST_PROPS_INT (AFMT_S16_LE),
82 "depth", GST_PROPS_LIST (
86 "rate", GST_PROPS_INT_RANGE (8000, 48000),
87 "channels", GST_PROPS_INT_RANGE (1, 2)
92 #define GST_TYPE_AUDIOSINK_FORMATS (gst_audiosink_formats_get_type())
95 gst_audiosink_formats_get_type(void) {
96 static GtkType audiosink_formats_type = 0;
97 static GtkEnumValue audiosink_formats[] = {
99 {16, "16", "16 Bits"},
102 if (!audiosink_formats_type) {
103 audiosink_formats_type = gtk_type_register_enum("GstAudiosinkFormats", audiosink_formats);
105 return audiosink_formats_type;
108 #define GST_TYPE_AUDIOSINK_CHANNELS (gst_audiosink_channels_get_type())
111 gst_audiosink_channels_get_type(void) {
112 static GtkType audiosink_channels_type = 0;
113 static GtkEnumValue audiosink_channels[] = {
118 if (!audiosink_channels_type) {
119 audiosink_channels_type = gtk_type_register_enum("GstAudiosinkChannels", audiosink_channels);
121 return audiosink_channels_type;
125 static GstElementClass *parent_class = NULL;
126 static guint gst_audiosink_signals[LAST_SIGNAL] = { 0 };
128 static GstPadTemplate *gst_audiosink_sink_template;
131 gst_audiosink_get_type (void)
133 static GtkType audiosink_type = 0;
135 if (!audiosink_type) {
136 static const GtkTypeInfo audiosink_info = {
138 sizeof(GstAudioSink),
139 sizeof(GstAudioSinkClass),
140 (GtkClassInitFunc)gst_audiosink_class_init,
141 (GtkObjectInitFunc)gst_audiosink_init,
144 (GtkClassInitFunc)NULL,
146 audiosink_type = gtk_type_unique (GST_TYPE_ELEMENT, &audiosink_info);
149 return audiosink_type;
153 gst_audiosink_class_init (GstAudioSinkClass *klass)
155 GtkObjectClass *gtkobject_class;
156 GstElementClass *gstelement_class;
158 gtkobject_class = (GtkObjectClass*)klass;
159 gstelement_class = (GstElementClass*)klass;
161 parent_class = gtk_type_class(GST_TYPE_ELEMENT);
163 gtk_object_add_arg_type ("GstAudioSink::mute", GTK_TYPE_BOOL,
164 GTK_ARG_READWRITE, ARG_MUTE);
165 gtk_object_add_arg_type ("GstAudioSink::format", GST_TYPE_AUDIOSINK_FORMATS,
166 GTK_ARG_READWRITE, ARG_FORMAT);
167 gtk_object_add_arg_type ("GstAudioSink::channels", GST_TYPE_AUDIOSINK_CHANNELS,
168 GTK_ARG_READWRITE, ARG_CHANNELS);
169 gtk_object_add_arg_type ("GstAudioSink::frequency", GTK_TYPE_INT,
170 GTK_ARG_READWRITE, ARG_FREQUENCY);
172 gtkobject_class->set_arg = gst_audiosink_set_arg;
173 gtkobject_class->get_arg = gst_audiosink_get_arg;
175 gst_audiosink_signals[SIGNAL_HANDOFF] =
176 gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type,
177 GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff),
178 gtk_marshal_NONE__NONE,GTK_TYPE_NONE,0);
180 gtk_object_class_add_signals(gtkobject_class,gst_audiosink_signals,
183 gstelement_class->change_state = gst_audiosink_change_state;
187 gst_audiosink_init (GstAudioSink *audiosink)
189 audiosink->sinkpad = gst_pad_new_from_template (gst_audiosink_sink_template, "sink");
190 gst_element_add_pad (GST_ELEMENT (audiosink), audiosink->sinkpad);
192 gst_pad_set_chain_function (audiosink->sinkpad, gst_audiosink_chain);
195 audiosink->clock = gst_clock_get_system();
196 audiosink->format = 16;
197 audiosink->channels = 2;
198 audiosink->frequency = 44100;
200 gst_clock_register (audiosink->clock, GST_OBJECT (audiosink));
202 GST_FLAG_SET (audiosink, GST_ELEMENT_THREAD_SUGGESTED);
206 gst_audiosink_sync_parms (GstAudioSink *audiosink)
208 audio_buf_info ospace;
211 g_return_if_fail (audiosink != NULL);
212 g_return_if_fail (GST_IS_AUDIOSINK (audiosink));
214 if (audiosink->fd == -1) return;
216 ioctl (audiosink->fd, SNDCTL_DSP_RESET, 0);
218 ioctl (audiosink->fd, SNDCTL_DSP_SETFMT, &audiosink->format);
219 ioctl (audiosink->fd, SNDCTL_DSP_CHANNELS, &audiosink->channels);
220 ioctl (audiosink->fd, SNDCTL_DSP_SPEED, &audiosink->frequency);
221 ioctl (audiosink->fd, SNDCTL_DSP_GETBLKSIZE, &frag);
223 ioctl (audiosink->fd, SNDCTL_DSP_GETOSPACE, &ospace);
225 g_print("audiosink: setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
226 audiosink->frequency, audiosink->format,
227 (audiosink->channels == 2) ? "stereo" : "mono", ospace.bytes, frag);
232 gst_audiosink_chain (GstPad *pad, GstBuffer *buf)
234 GstAudioSink *audiosink;
237 audio_buf_info ospace;
239 g_return_if_fail (pad != NULL);
240 g_return_if_fail (GST_IS_PAD (pad));
241 g_return_if_fail (buf != NULL);
244 /* this has to be an audio buffer */
245 // g_return_if_fail(((GstMeta *)buf->meta)->type !=
246 //gst_audiosink_type_audio);
247 audiosink = GST_AUDIOSINK (pad->parent);
248 // g_return_if_fail(GST_FLAG_IS_SET(audiosink,GST_STATE_RUNNING));
250 if ((in_flush = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLUSH))) {
251 GST_DEBUG (0,"audiosink: flush\n");
252 ioctl (audiosink->fd, SNDCTL_DSP_RESET, 0);
256 meta = (MetaAudioRaw *)gst_buffer_get_first_meta (buf);
258 if ((meta->format != audiosink->format) ||
259 (meta->channels != audiosink->channels) ||
260 (meta->frequency != audiosink->frequency))
262 audiosink->format = meta->format;
263 audiosink->channels = meta->channels;
264 audiosink->frequency = meta->frequency;
265 gst_audiosink_sync_parms (audiosink);
266 g_print("audiosink: sound device set to format %d, %d channels, %dHz\n",
267 audiosink->format, audiosink->channels, audiosink->frequency);
271 gtk_signal_emit (GTK_OBJECT (audiosink), gst_audiosink_signals[SIGNAL_HANDOFF],
274 if (GST_BUFFER_DATA (buf) != NULL) {
275 gst_trace_add_entry(NULL, 0, buf, "audiosink: writing to soundcard");
276 //g_print("audiosink: writing to soundcard\n");
277 if (audiosink->fd >= 0) {
278 if (!audiosink->mute) {
279 gst_clock_wait (audiosink->clock, GST_BUFFER_TIMESTAMP (buf), GST_OBJECT (audiosink));
280 ioctl (audiosink->fd, SNDCTL_DSP_GETOSPACE, &ospace);
281 GST_DEBUG (0,"audiosink: (%d bytes buffer) %d %p %d\n", ospace.bytes,
282 audiosink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
283 write (audiosink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
284 //write(STDOUT_FILENO,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
288 gst_buffer_unref (buf);
292 gst_audiosink_set_arg (GtkObject *object, GtkArg *arg, guint id)
294 GstAudioSink *audiosink;
296 /* it's not null if we got it, but it might not be ours */
297 g_return_if_fail (GST_IS_AUDIOSINK (object));
299 audiosink = GST_AUDIOSINK (object);
303 audiosink->mute = GTK_VALUE_BOOL (*arg);
306 audiosink->format = GTK_VALUE_ENUM (*arg);
307 gst_audiosink_sync_parms (audiosink);
310 audiosink->channels = GTK_VALUE_ENUM (*arg);
311 gst_audiosink_sync_parms (audiosink);
314 audiosink->frequency = GTK_VALUE_INT (*arg);
315 gst_audiosink_sync_parms (audiosink);
323 gst_audiosink_get_arg (GtkObject *object, GtkArg *arg, guint id)
325 GstAudioSink *audiosink;
327 /* it's not null if we got it, but it might not be ours */
328 g_return_if_fail (GST_IS_AUDIOSINK (object));
330 audiosink = GST_AUDIOSINK (object);
334 GTK_VALUE_BOOL (*arg) = audiosink->mute;
337 GTK_VALUE_ENUM (*arg) = audiosink->format;
340 GTK_VALUE_ENUM (*arg) = audiosink->channels;
343 GTK_VALUE_INT (*arg) = audiosink->frequency;
351 gst_audiosink_open_audio (GstAudioSink *sink)
353 g_return_val_if_fail (sink->fd == -1, FALSE);
355 g_print ("audiosink: attempting to open sound device\n");
357 /* first try to open the sound card */
358 sink->fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK);
359 if (errno == EBUSY) {
360 g_print ("audiosink: unable to open the sound device (in use ?)\n");
364 /* re-open the sound device in blocking mode */
366 sink->fd = open("/dev/dsp", O_WRONLY);
368 /* if we have it, set the default parameters and go have fun */
371 sink->format = AFMT_S16_LE;
372 sink->channels = 2; /* stereo */
373 sink->frequency = 44100;
374 gst_audiosink_sync_parms (sink);
375 ioctl(sink->fd, SNDCTL_DSP_GETCAPS, &sink->caps);
377 g_print("audiosink: Capabilities\n");
379 if (sink->caps & DSP_CAP_DUPLEX) g_print("audiosink: Full duplex\n");
380 if (sink->caps & DSP_CAP_REALTIME) g_print("audiosink: Realtime\n");
381 if (sink->caps & DSP_CAP_BATCH) g_print("audiosink: Batch\n");
382 if (sink->caps & DSP_CAP_COPROC) g_print("audiosink: Has coprocessor\n");
383 if (sink->caps & DSP_CAP_TRIGGER) g_print("audiosink: Trigger\n");
384 if (sink->caps & DSP_CAP_MMAP) g_print("audiosink: Direct access\n");
386 g_print("audiosink: opened audio with fd=%d\n", sink->fd);
387 GST_FLAG_SET (sink, GST_AUDIOSINK_OPEN);
396 gst_audiosink_close_audio (GstAudioSink *sink)
398 if (sink->fd < 0) return;
403 GST_FLAG_UNSET (sink, GST_AUDIOSINK_OPEN);
405 g_print("audiosink: closed sound device\n");
408 static GstElementStateReturn
409 gst_audiosink_change_state (GstElement *element)
411 g_return_val_if_fail (GST_IS_AUDIOSINK (element), FALSE);
413 /* if going down into NULL state, close the file if it's open */
414 if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
415 if (GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN))
416 gst_audiosink_close_audio (GST_AUDIOSINK (element));
417 /* otherwise (READY or higher) we need to open the sound card */
419 if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) {
420 if (!gst_audiosink_open_audio (GST_AUDIOSINK (element)))
421 return GST_STATE_FAILURE;
425 if (GST_ELEMENT_CLASS (parent_class)->change_state)
426 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
427 return GST_STATE_SUCCESS;
431 gst_audiosink_factory_init (GstElementFactory *factory)
433 gst_audiosink_sink_template = gst_padtemplate_new (&audiosink_sink_factory);
434 gst_elementfactory_add_padtemplate (factory, gst_audiosink_sink_template);