static void
gst_directsound_sink_set_mute (GstDirectSoundSink * dsoundsink, gboolean mute)
{
  if (mute)
    gst_directsound_sink_set_volume (dsoundsink, 0, FALSE);
  else
    gst_directsound_sink_set_volume (dsoundsink, dsoundsink->volume, FALSE);
}
static void
gst_directsound_sink_mixer_set_volume (GstMixer * mixer,
    GstMixerTrack * track, gint * volumes)
{
  GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);

  if (volumes[0] != dsoundsink->volume) {
    dsoundsink->volume = volumes[0];

    gst_directsound_sink_set_volume (dsoundsink);
  }
}
static void
gst_directsound_sink_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{
  GstDirectSoundSink *sink = GST_DIRECTSOUND_SINK (object);

  switch (prop_id) {
    case PROP_VOLUME:
      sink->volume = (int) (g_value_get_double (value) * 100);
      gst_directsound_sink_set_volume (sink);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static gboolean
gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
{
  GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink);
  HRESULT hRes;
  DSBUFFERDESC descSecondary;
  WAVEFORMATEX wfx;

  /*save number of bytes per sample and buffer format */
  dsoundsink->bytes_per_sample = spec->bytes_per_sample;
  dsoundsink->buffer_format = spec->format;

  /* fill the WAVEFORMATEX structure with spec params */
  memset (&wfx, 0, sizeof (wfx));
  if (spec->format != GST_IEC958) {
    wfx.cbSize = sizeof (wfx);
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = spec->channels;
    wfx.nSamplesPerSec = spec->rate;
    wfx.wBitsPerSample = (spec->bytes_per_sample * 8) / wfx.nChannels;
    wfx.nBlockAlign = spec->bytes_per_sample;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

    /* Create directsound buffer with size based on our configured  
     * buffer_size (which is 200 ms by default) */
    dsoundsink->buffer_size =
        gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->buffer_time,
        GST_MSECOND);
    /* Make sure we make those numbers multiple of our sample size in bytes */
    dsoundsink->buffer_size += dsoundsink->buffer_size % spec->bytes_per_sample;

    spec->segsize =
        gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->latency_time,
        GST_MSECOND);
    spec->segsize += spec->segsize % spec->bytes_per_sample;
    spec->segtotal = dsoundsink->buffer_size / spec->segsize;
  } else {
    wfx.cbSize = 0;
    wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
    wfx.nChannels = 2;
    wfx.nSamplesPerSec = spec->rate;
    wfx.wBitsPerSample = 16;
    wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

    spec->segsize = 6144;
    spec->segtotal = 10;
  }

  // Make the final buffer size be an integer number of segments
  dsoundsink->buffer_size = spec->segsize * spec->segtotal;

  GST_INFO_OBJECT (dsoundsink,
      "GstRingBufferSpec->channels: %d, GstRingBufferSpec->rate: %d, GstRingBufferSpec->bytes_per_sample: %d\n"
      "WAVEFORMATEX.nSamplesPerSec: %ld, WAVEFORMATEX.wBitsPerSample: %d, WAVEFORMATEX.nBlockAlign: %d, WAVEFORMATEX.nAvgBytesPerSec: %ld\n"
      "Size of dsound circular buffer=>%d\n", spec->channels, spec->rate,
      spec->bytes_per_sample, wfx.nSamplesPerSec, wfx.wBitsPerSample,
      wfx.nBlockAlign, wfx.nAvgBytesPerSec, dsoundsink->buffer_size);

  /* create a secondary directsound buffer */
  memset (&descSecondary, 0, sizeof (DSBUFFERDESC));
  descSecondary.dwSize = sizeof (DSBUFFERDESC);
  descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
  if (spec->format != GST_IEC958)
    descSecondary.dwFlags |= DSBCAPS_CTRLVOLUME;

  descSecondary.dwBufferBytes = dsoundsink->buffer_size;
  descSecondary.lpwfxFormat = (WAVEFORMATEX *) & wfx;

  hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary,
      &dsoundsink->pDSBSecondary, NULL);
  if (FAILED (hRes)) {
    GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
        ("gst_directsound_sink_prepare: IDirectSound_CreateSoundBuffer: %s",
            DXGetErrorString9 (hRes)), (NULL));
    return FALSE;
  }

  gst_directsound_sink_set_volume (dsoundsink);

  return TRUE;
}