gstosssink.c 14.9 KB
Newer Older
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1 2
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3
 *               2000,2005 Wim Taymans <wim@fluendo.com>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * gstosssink.c: 
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

23 24 25 26
/**
 * SECTION:element-osssink
 *
 * This element lets you output sound using the Open Sound System (OSS).
27
 *
28 29 30 31
 * Note that you should almost always use generic audio conversion elements
 * like audioconvert and audioresample in front of an audiosink to make sure
 * your pipeline works under all circumstances (those conversion elements will
 * act in passthrough-mode if no conversion is necessary).
32 33
 *
 * <refsect2>
34
 * <title>Example pipelines</title>
35
 * |[
36
 * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.1 ! osssink
37
 * ]| will output a sine wave (continuous beep sound) to your sound card (with
38
 * a very low volume as precaution).
39
 * |[
40
 * gst-launch -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! osssink
41
 * ]| will play an Ogg/Vorbis audio file and output it using the Open Sound System.
42 43 44
 * </refsect2>
 */

45 46 47
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48
#include <sys/ioctl.h>
49
#include <fcntl.h>
50
#include <errno.h>
51
#include <unistd.h>
52
#include <string.h>
53

54 55 56 57 58 59 60 61 62 63 64 65 66
#ifdef HAVE_OSS_INCLUDE_IN_SYS
# include <sys/soundcard.h>
#else
# ifdef HAVE_OSS_INCLUDE_IN_ROOT
#  include <soundcard.h>
# else
#  ifdef HAVE_OSS_INCLUDE_IN_MACHINE
#   include <machine/soundcard.h>
#  else
#   error "What to include?"
#  endif /* HAVE_OSS_INCLUDE_IN_MACHINE */
# endif /* HAVE_OSS_INCLUDE_IN_ROOT */
#endif /* HAVE_OSS_INCLUDE_IN_SYS */
67

68
#include "common.h"
69
#include "gstosssink.h"
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
70

71 72
#include <gst/gst-i18n-plugin.h>

73 74 75
GST_DEBUG_CATEGORY_EXTERN (oss_debug);
#define GST_CAT_DEFAULT oss_debug

76
/* elementfactory information */
77
static const GstElementDetails gst_oss_sink_details =
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
78 79 80 81 82 83
GST_ELEMENT_DETAILS ("Audio Sink (OSS)",
    "Sink/Audio",
    "Output to a sound card via OSS",
    "Erik Walthinsen <omega@cse.ogi.edu>, "
    "Wim Taymans <wim.taymans@chello.be>");

84 85 86
static void gst_oss_sink_base_init (gpointer g_class);
static void gst_oss_sink_class_init (GstOssSinkClass * klass);
static void gst_oss_sink_init (GstOssSink * osssink);
87

88
static void gst_oss_sink_dispose (GObject * object);
89
static void gst_oss_sink_finalise (GObject * object);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
90

91 92 93 94 95
static void gst_oss_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_oss_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);

96
static GstCaps *gst_oss_sink_getcaps (GstBaseSink * bsink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
97

98
static gboolean gst_oss_sink_open (GstAudioSink * asink);
99
static gboolean gst_oss_sink_close (GstAudioSink * asink);
100 101 102
static gboolean gst_oss_sink_prepare (GstAudioSink * asink,
    GstRingBufferSpec * spec);
static gboolean gst_oss_sink_unprepare (GstAudioSink * asink);
103
static guint gst_oss_sink_write (GstAudioSink * asink, gpointer data,
104
    guint length);
105 106
static guint gst_oss_sink_delay (GstAudioSink * asink);
static void gst_oss_sink_reset (GstAudioSink * asink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
107 108

/* OssSink signals and args */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
109 110
enum
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
111 112 113
  LAST_SIGNAL
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
114
#define DEFAULT_DEVICE  "/dev/dsp"
115 116 117 118 119 120
enum
{
  PROP_0,
  PROP_DEVICE,
};

David Schleef's avatar
David Schleef committed
121
static GstStaticPadTemplate osssink_sink_factory =
122
    GST_STATIC_PAD_TEMPLATE ("sink",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
123 124 125
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-raw-int, "
126 127
        "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
        "signed = (boolean) { TRUE, FALSE }, "
128
        "width = (int) 16, "
129
        "depth = (int) 16, "
130 131 132 133 134
        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
        "audio/x-raw-int, "
        "signed = (boolean) { TRUE, FALSE }, "
        "width = (int) 8, "
        "depth = (int) 8, "
135
        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
136
    );
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
137 138

static GstElementClass *parent_class = NULL;
139

140
/* static guint gst_oss_sink_signals[LAST_SIGNAL] = { 0 }; */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
141 142

GType
143
gst_oss_sink_get_type (void)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
144 145 146 147 148
{
  static GType osssink_type = 0;

  if (!osssink_type) {
    static const GTypeInfo osssink_info = {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
149
      sizeof (GstOssSinkClass),
150
      gst_oss_sink_base_init,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
151
      NULL,
152
      (GClassInitFunc) gst_oss_sink_class_init,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
153 154
      NULL,
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
155
      sizeof (GstOssSink),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
156
      0,
157
      (GInstanceInitFunc) gst_oss_sink_init,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
158
    };
159

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
160
    osssink_type =
161
        g_type_register_static (GST_TYPE_AUDIO_SINK, "GstOssSink",
162
        &osssink_info, 0);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
163 164 165 166 167
  }

  return osssink_type;
}

168
static void
169
gst_oss_sink_dispose (GObject * object)
170
{
171 172 173 174 175 176 177
  GstOssSink *osssink = GST_OSSSINK (object);

  if (osssink->probed_caps) {
    gst_caps_unref (osssink->probed_caps);
    osssink->probed_caps = NULL;
  }

178 179 180
  G_OBJECT_CLASS (parent_class)->dispose (object);
}

181
static void
182
gst_oss_sink_base_init (gpointer g_class)
183 184
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
185

186
  gst_element_class_set_details (element_class, &gst_oss_sink_details);
187

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
188 189
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&osssink_sink_factory));
190
}
191

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
192
static void
193
gst_oss_sink_class_init (GstOssSinkClass * klass)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
194 195 196
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
197 198 199
  GstBaseSinkClass *gstbasesink_class;
  GstBaseAudioSinkClass *gstbaseaudiosink_class;
  GstAudioSinkClass *gstaudiosink_class;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
200

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
201 202
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
203 204 205 206
  gstbasesink_class = (GstBaseSinkClass *) klass;
  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
  gstaudiosink_class = (GstAudioSinkClass *) klass;

207
  parent_class = g_type_class_peek_parent (klass);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
208

209
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss_sink_dispose);
210
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_oss_sink_finalise);
211 212 213 214 215 216
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss_sink_get_property);
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss_sink_set_property);

  g_object_class_install_property (gobject_class, PROP_DEVICE,
      g_param_spec_string ("device", "Device",
          "OSS device (usually /dev/dspN)", DEFAULT_DEVICE, G_PARAM_READWRITE));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
217

218
  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_sink_getcaps);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
219

220 221
  gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_oss_sink_open);
  gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_oss_sink_close);
222 223
  gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_sink_prepare);
  gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_sink_unprepare);
224 225 226
  gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss_sink_write);
  gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss_sink_delay);
  gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss_sink_reset);
Wim Taymans's avatar
Wim Taymans committed
227 228
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
229
static void
230
gst_oss_sink_init (GstOssSink * osssink)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
231
{
232 233
  const gchar *device;

234
  GST_DEBUG_OBJECT (osssink, "initializing osssink");
235

236 237 238 239
  device = g_getenv ("AUDIODEV");
  if (device == NULL)
    device = DEFAULT_DEVICE;
  osssink->device = g_strdup (device);
240
  osssink->fd = -1;
241
}
242

243 244 245 246 247 248
static void
gst_oss_sink_finalise (GObject * object)
{
  GstOssSink *osssink = GST_OSSSINK (object);

  g_free (osssink->device);
249 250

  G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (object));
251 252
}

253 254 255 256 257 258 259 260 261 262 263 264
static void
gst_oss_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstOssSink *sink;

  sink = GST_OSSSINK (object);

  switch (prop_id) {
    case PROP_DEVICE:
      g_free (sink->device);
      sink->device = g_value_dup_string (value);
265 266 267 268
      if (sink->probed_caps) {
        gst_caps_unref (sink->probed_caps);
        sink->probed_caps = NULL;
      }
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_oss_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstOssSink *sink;

  sink = GST_OSSSINK (object);

  switch (prop_id) {
    case PROP_DEVICE:
      g_value_set_string (value, sink->device);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

294
static GstCaps *
295
gst_oss_sink_getcaps (GstBaseSink * bsink)
296
{
297
  GstOssSink *osssink;
298 299
  GstCaps *caps;

300 301
  osssink = GST_OSSSINK (bsink);

302 303
  if (osssink->fd == -1) {
    caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
304
            (bsink)));
305 306
  } else if (osssink->probed_caps) {
    caps = gst_caps_copy (osssink->probed_caps);
307
  } else {
308
    caps = gst_oss_helper_probe_caps (osssink->fd);
309 310 311
    if (caps && !gst_caps_is_empty (caps)) {
      osssink->probed_caps = gst_caps_copy (caps);
    }
312 313 314 315 316
  }

  return caps;
}

317 318
static gint
ilog2 (gint x)
319
{
320 321 322 323 324 325 326 327 328 329 330 331
  /* well... hacker's delight explains... */
  x = x | (x >> 1);
  x = x | (x >> 2);
  x = x | (x >> 4);
  x = x | (x >> 8);
  x = x | (x >> 16);
  x = x - ((x >> 1) & 0x55555555);
  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
  x = (x + (x >> 4)) & 0x0f0f0f0f;
  x = x + (x >> 8);
  x = x + (x >> 16);
  return (x & 0x0000003f) - 1;
332 333
}

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
static gint
gst_oss_sink_get_format (GstBufferFormat fmt)
{
  gint result;

  switch (fmt) {
    case GST_MU_LAW:
      result = AFMT_MU_LAW;
      break;
    case GST_A_LAW:
      result = AFMT_A_LAW;
      break;
    case GST_IMA_ADPCM:
      result = AFMT_IMA_ADPCM;
      break;
    case GST_U8:
      result = AFMT_U8;
      break;
    case GST_S16_LE:
      result = AFMT_S16_LE;
      break;
    case GST_S16_BE:
      result = AFMT_S16_BE;
      break;
    case GST_S8:
      result = AFMT_S8;
      break;
    case GST_U16_LE:
      result = AFMT_U16_LE;
      break;
    case GST_U16_BE:
      result = AFMT_U16_BE;
      break;
    case GST_MPEG:
      result = AFMT_MPEG;
      break;
    default:
      result = 0;
      break;
  }
  return result;
}

377
static gboolean
378
gst_oss_sink_open (GstAudioSink * asink)
Wim Taymans's avatar
Wim Taymans committed
379
{
380
  GstOssSink *oss;
381
  int mode;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
382

383
  oss = GST_OSSSINK (asink);
Wim Taymans's avatar
Wim Taymans committed
384

385 386
  mode = O_WRONLY;
  mode |= O_NONBLOCK;
Wim Taymans's avatar
Wim Taymans committed
387

388
  oss->fd = open (oss->device, mode, 0);
389 390 391 392
  if (oss->fd == -1) {
    switch (errno) {
      case EBUSY:
        goto busy;
393 394
      case EACCES:
        goto no_permission;
395 396 397 398
      default:
        goto open_failed;
    }
  }
399 400

  return TRUE;
401

Wim Taymans's avatar
Wim Taymans committed
402
  /* ERRORS */
403 404
busy:
  {
405 406 407 408 409 410 411 412
    GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
        (_("Could not open audio device for playback. "
                "Device is being used by another application.")), (NULL));
    return FALSE;
  }
no_permission:
  {
    GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
413
        (_("Could not open audio device for playback. "
414 415
                "You don't have permission to open the device.")),
        GST_ERROR_SYSTEM);
416 417
    return FALSE;
  }
418 419
open_failed:
  {
420 421
    GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
        (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM);
422 423
    return FALSE;
  }
424 425 426 427 428 429
}

static gboolean
gst_oss_sink_close (GstAudioSink * asink)
{
  close (GST_OSSSINK (asink)->fd);
430
  GST_OSSSINK (asink)->fd = -1;
431 432 433 434 435 436 437 438 439 440 441 442 443
  return TRUE;
}

static gboolean
gst_oss_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
{
  GstOssSink *oss;
  struct audio_buf_info info;
  int mode;
  int tmp;

  oss = GST_OSSSINK (asink);

444 445
  /* we opened non-blocking so that we can detect if the device is available
   * without hanging forever. We now want to remove the non-blocking flag. */
446 447
  mode = fcntl (oss->fd, F_GETFL);
  mode &= ~O_NONBLOCK;
448 449 450 451 452 453 454
  if (fcntl (oss->fd, F_SETFL, mode) == -1) {
    /* some drivers do no support unsetting the non-blocking flag, try to
     * close/open the device then. This is racy but we error out properly. */
    gst_oss_sink_close (asink);
    if ((oss->fd = open (oss->device, O_WRONLY, 0)) == -1)
      goto non_block;
  }
Wim Taymans's avatar
Wim Taymans committed
455

456 457 458 459
  tmp = gst_oss_sink_get_format (spec->format);
  if (tmp == 0)
    goto wrong_format;

460 461 462
  if (spec->width != 16 && spec->width != 8)
    goto dodgy_width;

463
  SET_PARAM (oss, SNDCTL_DSP_SETFMT, tmp, "SETFMT");
464
  if (spec->channels == 2)
465 466 467
    SET_PARAM (oss, SNDCTL_DSP_STEREO, 1, "STEREO");
  SET_PARAM (oss, SNDCTL_DSP_CHANNELS, spec->channels, "CHANNELS");
  SET_PARAM (oss, SNDCTL_DSP_SPEED, spec->rate, "SPEED");
468

469 470
  tmp = ilog2 (spec->segsize);
  tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
471 472
  GST_DEBUG_OBJECT (oss, "set segsize: %d, segtotal: %d, value: %08x",
      spec->segsize, spec->segtotal, tmp);
Wim Taymans's avatar
Wim Taymans committed
473

474 475
  SET_PARAM (oss, SNDCTL_DSP_SETFRAGMENT, tmp, "SETFRAGMENT");
  GET_PARAM (oss, SNDCTL_DSP_GETOSPACE, &info, "GETOSPACE");
Ronald S. Bultje's avatar
Ronald S. Bultje committed
476

477 478
  spec->segsize = info.fragsize;
  spec->segtotal = info.fragstotal;
479 480 481

  spec->bytes_per_sample = (spec->width / 8) * spec->channels;
  oss->bytes_per_sample = (spec->width / 8) * spec->channels;
482

483 484
  GST_DEBUG_OBJECT (oss, "got segsize: %d, segtotal: %d, value: %08x",
      spec->segsize, spec->segtotal, tmp);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
485

486
  return TRUE;
487

Wim Taymans's avatar
Wim Taymans committed
488
  /* ERRORS */
489 490
non_block:
  {
491
    GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
492
        ("Unable to set device %s in non blocking mode: %s",
493
            oss->device, g_strerror (errno)));
494 495
    return FALSE;
  }
496 497
wrong_format:
  {
498 499
    GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
        ("Unable to get format %d", spec->format));
500 501
    return FALSE;
  }
502 503
dodgy_width:
  {
504 505
    GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
        ("unexpected width %d", spec->width));
506 507
    return FALSE;
  }
508 509
}

510
static gboolean
511
gst_oss_sink_unprepare (GstAudioSink * asink)
512
{
513 514 515 516 517 518 519 520
  /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */

  if (!gst_oss_sink_close (asink))
    goto couldnt_close;

  if (!gst_oss_sink_open (asink))
    goto couldnt_reopen;

521
  return TRUE;
522

Wim Taymans's avatar
Wim Taymans committed
523
  /* ERRORS */
524 525
couldnt_close:
  {
526
    GST_DEBUG_OBJECT (asink, "Could not close the audio device");
527 528 529 530
    return FALSE;
  }
couldnt_reopen:
  {
531
    GST_DEBUG_OBJECT (asink, "Could not reopen the audio device");
532 533
    return FALSE;
  }
534 535
}

536
static guint
537
gst_oss_sink_write (GstAudioSink * asink, gpointer data, guint length)
538
{
539
  return write (GST_OSSSINK (asink)->fd, data, length);
540 541
}

542
static guint
543
gst_oss_sink_delay (GstAudioSink * asink)
544
{
545 546 547
  GstOssSink *oss;
  gint delay = 0;
  gint ret;
548

549
  oss = GST_OSSSINK (asink);
550

551 552 553 554 555 556 557
#ifdef SNDCTL_DSP_GETODELAY
  ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
#else
  ret = -1;
#endif
  if (ret < 0) {
    audio_buf_info info;
558

559
    ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
560

561
    delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
562
  }
563
  return delay / oss->bytes_per_sample;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
564 565
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
566
static void
567
gst_oss_sink_reset (GstAudioSink * asink)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
568
{
569 570 571
  /* There's nothing we can do here really: OSS can't handle access to the
   * same device/fd from multiple threads and might deadlock or blow up in
   * other ways if we try an ioctl SNDCTL_DSP_RESET or similar */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
572
}