int     sa_stream_drain(sa_stream_t *s)
{
  int       status = SA_SUCCESS;
  char      buf[32];

  if (!s)
    return os2_error(SA_ERROR_NO_INIT, "sa_stream_drain", "s is null", 0);

  /* keep os2_mixer_event() from reacting to buffer under-runs */
  s->usedMin = 0;

  /* perform the smallest possible write to force any
   * partially-filled buffer to be written to the device */
  memset(buf, 0, sizeof(buf));
  s->bufMin = 0;
  sa_stream_write(s, buf, s->nchannels * SAOS2_SAMPLE_SIZE);

  /* DART won't start playing until 2 buffers have been written,
   * so write a dummy 2nd buffer if writePos is still zero */
  if (!s->writePos)
    s->writePos += __atomic_xchg(&s->writeNew, 0);
  if (!s->writePos)
    sa_stream_write(s, buf, s->nchannels * SAOS2_SAMPLE_SIZE);

  /* wait for all buffers to become free */
  if (!status)
    status = os2_get_free_count(s, s->bufCnt);
  s->playing = FALSE;

  /* stop the device so it doesn't misbehave due to an under-run */
  os2_stop_device(s->hwDeviceID);

  return status;
}
int
sa_stream_drain(sa_stream_t *s)
{
  if (s == NULL || s->output_unit == NULL) {
    return SA_ERROR_NO_INIT;
  }

  if (snd_pcm_state(s->output_unit) == SND_PCM_STATE_PREPARED) {
    size_t min_samples = 0;
    size_t min_bytes = 0;
    void *buf;

    if (sa_stream_get_min_write(s, &min_samples) < 0)
      return SA_ERROR_SYSTEM;
    min_bytes = snd_pcm_frames_to_bytes(s->output_unit, min_samples);    

    buf = malloc(min_bytes);
    if (!buf)
      return SA_ERROR_SYSTEM;
    memset(buf, 0, min_bytes);
    sa_stream_write(s, buf, min_bytes);
    free(buf);
  }

  if (snd_pcm_state(s->output_unit) != SND_PCM_STATE_RUNNING) {
    return SA_ERROR_INVALID;
  }
  snd_pcm_drain(s->output_unit);
  return SA_SUCCESS;
}
nsresult nsNativeAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames)
{
  NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block");

  if (mInError)
    return NS_ERROR_FAILURE;

  uint32_t samples = aFrames * mChannels;
  nsAutoArrayPtr<short> s_data(new short[samples]);

  float scaled_volume = float(GetVolumeScale() * mVolume);
  ConvertAudioSamplesWithScale(aBuf, s_data.get(), samples, scaled_volume);

  if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
                      s_data.get(),
                      samples * sizeof(short)) != SA_SUCCESS)
  {
    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
    mInError = true;
    return NS_ERROR_FAILURE;
  }
  return NS_OK;
}