direcsoundsink: Port element to 0.11

This commit is contained in:
Andoni Morales Alastruey 2012-01-27 16:37:19 +01:00 committed by Sebastian Dröge
parent 9095f455d5
commit 83090f6530
2 changed files with 149 additions and 229 deletions

View file

@ -52,6 +52,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include <gst/base/gstbasesink.h>
#include <gst/audio/streamvolume.h>
#include "gstdirectsoundsink.h" #include "gstdirectsoundsink.h"
#include <math.h> #include <math.h>
@ -63,229 +65,85 @@
#endif #endif
#endif #endif
#define DEFAULT_MUTE FALSE
GST_DEBUG_CATEGORY_STATIC (directsoundsink_debug); GST_DEBUG_CATEGORY_STATIC (directsoundsink_debug);
#define GST_CAT_DEFAULT directsoundsink_debug #define GST_CAT_DEFAULT directsoundsink_debug
static void gst_directsound_sink_finalise (GObject * object); static void gst_directsound_sink_finalize (GObject * object);
static void gst_directsound_sink_set_property (GObject * object, guint prop_id, static void gst_directsound_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_directsound_sink_get_property (GObject * object, guint prop_id, static void gst_directsound_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GstCaps *gst_directsound_sink_getcaps (GstBaseSink * bsink); static GstCaps *gst_directsound_sink_getcaps (GstBaseSink * bsink,
GstCaps * filter);
static gboolean gst_directsound_sink_prepare (GstAudioSink * asink, static gboolean gst_directsound_sink_prepare (GstAudioSink * asink,
GstRingBufferSpec * spec); GstAudioRingBufferSpec * spec);
static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink); static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink);
static gboolean gst_directsound_sink_open (GstAudioSink * asink); static gboolean gst_directsound_sink_open (GstAudioSink * asink);
static gboolean gst_directsound_sink_close (GstAudioSink * asink); static gboolean gst_directsound_sink_close (GstAudioSink * asink);
static guint gst_directsound_sink_write (GstAudioSink * asink, gpointer data, static gint gst_directsound_sink_write (GstAudioSink * asink,
guint length); gpointer data, guint length);
static guint gst_directsound_sink_delay (GstAudioSink * asink); static guint gst_directsound_sink_delay (GstAudioSink * asink);
static void gst_directsound_sink_reset (GstAudioSink * asink); static void gst_directsound_sink_reset (GstAudioSink * asink);
static GstCaps *gst_directsound_probe_supported_formats (GstDirectSoundSink * static GstCaps *gst_directsound_probe_supported_formats (GstDirectSoundSink *
dsoundsink, const GstCaps * template_caps); dsoundsink, const GstCaps * template_caps);
/* interfaces */ static void gst_directsound_sink_set_volume (GstDirectSoundSink * sink,
static void gst_directsound_sink_interfaces_init (GType type); gdouble volume, gboolean store);
static void static gdouble gst_directsound_sink_get_volume (GstDirectSoundSink * sink);
gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass * static void gst_directsound_sink_set_mute (GstDirectSoundSink * sink,
iface); gboolean mute);
static void gst_directsound_sink_mixer_interface_init (GstMixerInterface * static gboolean gst_directsound_sink_get_mute (GstDirectSoundSink * sink);
iface);
static GstStaticPadTemplate directsoundsink_sink_factory = static GstStaticPadTemplate directsoundsink_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, " GST_STATIC_CAPS ("audio/x-raw, "
"signed = (boolean) TRUE, " "format = (string) S16LE, "
"width = (int) 16, " "layout = (string) interleaved, "
"depth = (int) 16, "
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
"audio/x-raw-int, " "audio/x-raw, "
"signed = (boolean) FALSE, " "format = (string) S8, "
"width = (int) 8, " "layout = (string) interleaved, "
"depth = (int) 8, "
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];" "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];"
"audio/x-iec958")); "audio/x-iec958"));
enum enum
{ {
PROP_0, PROP_0,
PROP_VOLUME PROP_VOLUME,
PROP_MUTE
}; };
GST_BOILERPLATE_FULL (GstDirectSoundSink, gst_directsound_sink, GstAudioSink, #define gst_directsound_sink_parent_class parent_class
GST_TYPE_AUDIO_SINK, gst_directsound_sink_interfaces_init); G_DEFINE_TYPE_WITH_CODE (GstDirectSoundSink, gst_directsound_sink,
GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL)
/* interfaces stuff */ );
static void
gst_directsound_sink_interfaces_init (GType type)
{
static const GInterfaceInfo implements_interface_info = {
(GInterfaceInitFunc) gst_directsound_sink_implements_interface_init,
NULL,
NULL,
};
static const GInterfaceInfo mixer_interface_info = {
(GInterfaceInitFunc) gst_directsound_sink_mixer_interface_init,
NULL,
NULL,
};
g_type_add_interface_static (type,
GST_TYPE_IMPLEMENTS_INTERFACE, &implements_interface_info);
g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_interface_info);
}
static gboolean
gst_directsound_sink_interface_supported (GstImplementsInterface * iface,
GType iface_type)
{
g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
/* for the sake of this example, we'll always support it. However, normally,
* you would check whether the device you've opened supports mixers. */
return TRUE;
}
static void static void
gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass * gst_directsound_sink_finalize (GObject * object)
iface)
{ {
iface->supported = gst_directsound_sink_interface_supported;
}
/*
* This function returns the list of support tracks (inputs, outputs)
* on this element instance. Elements usually build this list during
* _init () or when going from NULL to READY.
*/
static const GList *
gst_directsound_sink_mixer_list_tracks (GstMixer * mixer)
{
GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);
return dsoundsink->tracks;
}
static void
gst_directsound_sink_set_volume (GstDirectSoundSink * dsoundsink)
{
if (dsoundsink->pDSBSecondary) {
/* DirectSound controls volume using units of 100th of a decibel,
* ranging from -10000 to 0. We use a linear scale of 0 - 100
* here, so remap.
*/
long dsVolume;
if (dsoundsink->volume == 0)
dsVolume = -10000;
else
dsVolume = 100 * (long) (20 * log10 ((double) dsoundsink->volume / 100.));
dsVolume = CLAMP (dsVolume, -10000, 0);
GST_DEBUG_OBJECT (dsoundsink,
"Setting volume on secondary buffer to %d from %d", (int) dsVolume,
(int) dsoundsink->volume);
IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, dsVolume);
}
}
/*
* Set volume. volumes is an array of size track->num_channels, and
* each value in the array gives the wanted volume for one channel
* on the track.
*/
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_mixer_get_volume (GstMixer * mixer,
GstMixerTrack * track, gint * volumes)
{
GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (mixer);
volumes[0] = dsoundsink->volume;
}
static void
gst_directsound_sink_mixer_interface_init (GstMixerInterface * iface)
{
/* the mixer interface requires a definition of the mixer type:
* hardware or software? */
GST_MIXER_TYPE (iface) = GST_MIXER_SOFTWARE;
/* virtual function pointers */
iface->list_tracks = gst_directsound_sink_mixer_list_tracks;
iface->set_volume = gst_directsound_sink_mixer_set_volume;
iface->get_volume = gst_directsound_sink_mixer_get_volume;
}
static void
gst_directsound_sink_finalise (GObject * object)
{
GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (object);
g_mutex_free (dsoundsink->dsound_lock);
if (dsoundsink->tracks) {
g_list_foreach (dsoundsink->tracks, (GFunc) g_object_unref, NULL);
g_list_free (dsoundsink->tracks);
dsoundsink->tracks = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void
gst_directsound_sink_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details_simple (element_class,
"Direct Sound Audio Sink", "Sink/Audio",
"Output to a sound card via Direct Sound",
"Sebastien Moutte <sebastien@moutte.net>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&directsoundsink_sink_factory));
}
static void static void
gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass) gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *gstelement_class; GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
GstBaseSinkClass *gstbasesink_class; GstAudioSinkClass *gstaudiosink_class = GST_AUDIO_SINK_CLASS (klass);
GstBaseAudioSinkClass *gstbaseaudiosink_class; GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GstAudioSinkClass *gstaudiosink_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass;
gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
gstaudiosink_class = (GstAudioSinkClass *) klass;
GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0, GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0,
"DirectSound sink"); "DirectSound sink");
parent_class = g_type_class_peek_parent (klass); parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gst_directsound_sink_finalise; gobject_class->finalize = gst_directsound_sink_finalize;
gobject_class->set_property = gst_directsound_sink_set_property; gobject_class->set_property = gst_directsound_sink_set_property;
gobject_class->get_property = gst_directsound_sink_get_property; gobject_class->get_property = gst_directsound_sink_get_property;
@ -307,23 +165,27 @@ gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass)
g_param_spec_double ("volume", "Volume", g_param_spec_double ("volume", "Volume",
"Volume of this stream", 0.0, 1.0, 1.0, "Volume of this stream", 0.0, 1.0, 1.0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_MUTE,
g_param_spec_boolean ("mute", "Mute",
"Mute state of this stream", DEFAULT_MUTE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_details_simple (element_class,
"Direct Sound Audio Sink", "Sink/Audio",
"Output to a sound card via Direct Sound",
"Sebastien Moutte <sebastien@moutte.net>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&directsoundsink_sink_factory));
} }
static void static void
gst_directsound_sink_init (GstDirectSoundSink * dsoundsink, gst_directsound_sink_init (GstDirectSoundSink * dsoundsink)
GstDirectSoundSinkClass * g_class)
{ {
GstMixerTrack *track = NULL; dsoundsink->volume = 100;
dsoundsink->mute = FALSE;
dsoundsink->tracks = NULL;
track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
track->label = g_strdup ("DSoundTrack");
track->num_channels = 2;
track->min_volume = 0;
track->max_volume = 100;
track->flags = GST_MIXER_TRACK_OUTPUT;
dsoundsink->tracks = g_list_append (dsoundsink->tracks, track);
dsoundsink->pDS = NULL; dsoundsink->pDS = NULL;
dsoundsink->cached_caps = NULL; dsoundsink->cached_caps = NULL;
dsoundsink->pDSBSecondary = NULL; dsoundsink->pDSBSecondary = NULL;
@ -342,8 +204,10 @@ gst_directsound_sink_set_property (GObject * object,
switch (prop_id) { switch (prop_id) {
case PROP_VOLUME: case PROP_VOLUME:
sink->volume = (int) (g_value_get_double (value) * 100); gst_directsound_sink_set_volume (sink, g_value_get_double (value), TRUE);
gst_directsound_sink_set_volume (sink); break;
case PROP_MUTE:
gst_directsound_sink_set_mute (sink, g_value_get_boolean (value));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -359,7 +223,10 @@ gst_directsound_sink_get_property (GObject * object,
switch (prop_id) { switch (prop_id) {
case PROP_VOLUME: case PROP_VOLUME:
g_value_set_double (value, (double) sink->volume / 100.); g_value_set_double (value, gst_directsound_sink_get_volume (sink));
break;
case PROP_MUTE:
g_value_set_boolean (value, gst_directsound_sink_get_mute (sink));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -368,7 +235,7 @@ gst_directsound_sink_get_property (GObject * object,
} }
static GstCaps * static GstCaps *
gst_directsound_sink_getcaps (GstBaseSink * bsink) gst_directsound_sink_getcaps (GstBaseSink * bsink, GstCaps * filter)
{ {
GstElementClass *element_class; GstElementClass *element_class;
GstPadTemplate *pad_template; GstPadTemplate *pad_template;
@ -410,9 +277,11 @@ gst_directsound_sink_getcaps (GstBaseSink * bsink)
static gboolean static gboolean
gst_directsound_sink_open (GstAudioSink * asink) gst_directsound_sink_open (GstAudioSink * asink)
{ {
GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink); GstDirectSoundSink *dsoundsink;
HRESULT hRes; HRESULT hRes;
dsoundsink = GST_DIRECTSOUND_SINK (asink);
/* create and initialize a DirecSound object */ /* create and initialize a DirecSound object */
if (FAILED (hRes = DirectSoundCreate (NULL, &dsoundsink->pDS, NULL))) { if (FAILED (hRes = DirectSoundCreate (NULL, &dsoundsink->pDS, NULL))) {
GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ, GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
@ -433,26 +302,29 @@ gst_directsound_sink_open (GstAudioSink * asink)
} }
static gboolean static gboolean
gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) gst_directsound_sink_prepare (GstAudioSink * asink,
GstAudioRingBufferSpec * spec)
{ {
GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (asink); GstDirectSoundSink *dsoundsink;
HRESULT hRes; HRESULT hRes;
DSBUFFERDESC descSecondary; DSBUFFERDESC descSecondary;
WAVEFORMATEX wfx; WAVEFORMATEX wfx;
dsoundsink = GST_DIRECTSOUND_SINK (asink);
/*save number of bytes per sample and buffer format */ /*save number of bytes per sample and buffer format */
dsoundsink->bytes_per_sample = spec->bytes_per_sample; dsoundsink->bytes_per_sample = spec->info.bpf;
dsoundsink->buffer_format = spec->format; dsoundsink->type = spec->type;
/* fill the WAVEFORMATEX structure with spec params */ /* fill the WAVEFORMATEX structure with spec params */
memset (&wfx, 0, sizeof (wfx)); memset (&wfx, 0, sizeof (wfx));
if (spec->format != GST_IEC958) { if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IEC958) {
wfx.cbSize = sizeof (wfx); wfx.cbSize = sizeof (wfx);
wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = spec->channels; wfx.nChannels = spec->info.channels;
wfx.nSamplesPerSec = spec->rate; wfx.nSamplesPerSec = spec->info.rate;
wfx.wBitsPerSample = (spec->bytes_per_sample * 8) / wfx.nChannels; wfx.wBitsPerSample = (spec->info.bpf * 8) / wfx.nChannels;
wfx.nBlockAlign = spec->bytes_per_sample; wfx.nBlockAlign = spec->info.bpf;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
/* Create directsound buffer with size based on our configured /* Create directsound buffer with size based on our configured
@ -461,19 +333,19 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->buffer_time, gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->buffer_time,
GST_MSECOND); GST_MSECOND);
/* Make sure we make those numbers multiple of our sample size in bytes */ /* Make sure we make those numbers multiple of our sample size in bytes */
dsoundsink->buffer_size += dsoundsink->buffer_size % spec->bytes_per_sample; dsoundsink->buffer_size += dsoundsink->buffer_size % spec->info.bpf;
spec->segsize = spec->segsize =
gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->latency_time, gst_util_uint64_scale_int (wfx.nAvgBytesPerSec, spec->latency_time,
GST_MSECOND); GST_MSECOND);
spec->segsize += spec->segsize % spec->bytes_per_sample; spec->segsize += spec->segsize % spec->info.bpf;
spec->segtotal = dsoundsink->buffer_size / spec->segsize; spec->segtotal = dsoundsink->buffer_size / spec->segsize;
} else { } else {
#ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF #ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF
wfx.cbSize = 0; wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
wfx.nChannels = 2; wfx.nChannels = 2;
wfx.nSamplesPerSec = spec->rate; wfx.nSamplesPerSec = spec->info.rate;
wfx.wBitsPerSample = 16; wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
@ -491,15 +363,15 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
GST_INFO_OBJECT (dsoundsink, GST_INFO_OBJECT (dsoundsink,
"GstRingBufferSpec->channels: %d, GstRingBufferSpec->rate: %d, GstRingBufferSpec->bytes_per_sample: %d\n" "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" "WAVEFORMATEX.nSamplesPerSec: %ld, WAVEFORMATEX.wBitsPerSample: %d, WAVEFORMATEX.nBlockAlign: %d, WAVEFORMATEX.nAvgBytesPerSec: %ld\n"
"Size of dsound circular buffer=>%d\n", spec->channels, spec->rate, "Size of dsound circular buffer=>%d\n", spec->info.channels,
spec->bytes_per_sample, wfx.nSamplesPerSec, wfx.wBitsPerSample, spec->info.rate, spec->info.bpf, wfx.nSamplesPerSec, wfx.wBitsPerSample,
wfx.nBlockAlign, wfx.nAvgBytesPerSec, dsoundsink->buffer_size); wfx.nBlockAlign, wfx.nAvgBytesPerSec, dsoundsink->buffer_size);
/* create a secondary directsound buffer */ /* create a secondary directsound buffer */
memset (&descSecondary, 0, sizeof (DSBUFFERDESC)); memset (&descSecondary, 0, sizeof (DSBUFFERDESC));
descSecondary.dwSize = sizeof (DSBUFFERDESC); descSecondary.dwSize = sizeof (DSBUFFERDESC);
descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
if (spec->format != GST_IEC958) if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IEC958)
descSecondary.dwFlags |= DSBCAPS_CTRLVOLUME; descSecondary.dwFlags |= DSBCAPS_CTRLVOLUME;
descSecondary.dwBufferBytes = dsoundsink->buffer_size; descSecondary.dwBufferBytes = dsoundsink->buffer_size;
@ -514,7 +386,7 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
return FALSE; return FALSE;
} }
gst_directsound_sink_set_volume (dsoundsink); gst_directsound_sink_set_volume (dsoundsink, dsoundsink->volume, FALSE);
return TRUE; return TRUE;
} }
@ -552,7 +424,7 @@ gst_directsound_sink_close (GstAudioSink * asink)
return TRUE; return TRUE;
} }
static guint static gint
gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length) gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length)
{ {
GstDirectSoundSink *dsoundsink; GstDirectSoundSink *dsoundsink;
@ -565,7 +437,7 @@ gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length)
dsoundsink = GST_DIRECTSOUND_SINK (asink); dsoundsink = GST_DIRECTSOUND_SINK (asink);
/* Fix endianness */ /* Fix endianness */
if (dsoundsink->buffer_format == GST_IEC958) if (dsoundsink->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IEC958)
_swab (data, data, length); _swab (data, data, length);
GST_DSOUND_LOCK (dsoundsink); GST_DSOUND_LOCK (dsoundsink);
@ -768,7 +640,7 @@ gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink,
"(IDirectSound_CreateSoundBuffer returned: %s)\n", "(IDirectSound_CreateSoundBuffer returned: %s)\n",
DXGetErrorString9 (hRes)); DXGetErrorString9 (hRes));
caps = caps =
gst_caps_subtract (caps, gst_caps_new_simple ("audio/x-iec958", NULL)); gst_caps_subtract (caps, gst_caps_new_empty_simple ("audio/x-iec958"));
} else { } else {
GST_INFO_OBJECT (dsoundsink, "AC3 passthrough supported"); GST_INFO_OBJECT (dsoundsink, "AC3 passthrough supported");
hRes = IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary); hRes = IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary);
@ -784,3 +656,53 @@ gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink,
return caps; return caps;
} }
static void
gst_directsound_sink_set_volume (GstDirectSoundSink * dsoundsink,
gdouble dvolume, gboolean store)
{
glong volume;
volume = dvolume * 100;
if (store)
dsoundsink->volume = volume;
if (dsoundsink->pDSBSecondary) {
/* DirectSound controls volume using units of 100th of a decibel,
* ranging from -10000 to 0. We use a linear scale of 0 - 100
* here, so remap.
*/
long dsVolume;
if (dsoundsink->volume == 0)
dsVolume = -10000;
else
dsVolume = 100 * (long) (20 * log10 ((double) dsoundsink->volume / 100.));
dsVolume = CLAMP (dsVolume, -10000, 0);
GST_DEBUG_OBJECT (dsoundsink,
"Setting volume on secondary buffer to %d from %d", (int) dsVolume,
(int) dsoundsink->volume);
IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, dsVolume);
}
}
gdouble
gst_directsound_sink_get_volume (GstDirectSoundSink * dsoundsink)
{
return (gdouble) dsoundsink->volume / 100;
}
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 gboolean
gst_directsound_sink_get_mute (GstDirectSoundSink * dsoundsink)
{
return FALSE;
}

View file

@ -31,7 +31,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/audio/gstaudiosink.h> #include <gst/audio/gstaudiosink.h>
#include <gst/interfaces/mixer.h> #include "gstdirectsoundringbuffer.h"
#include <windows.h> #include <windows.h>
#include <dxerr9.h> #include <dxerr9.h>
@ -56,6 +56,7 @@ struct _GstDirectSoundSink
{ {
GstAudioSink sink; GstAudioSink sink;
/* directsound object interface pointer */ /* directsound object interface pointer */
LPDIRECTSOUND pDS; LPDIRECTSOUND pDS;
@ -72,18 +73,15 @@ struct _GstDirectSoundSink
/* current volume setup by mixer interface */ /* current volume setup by mixer interface */
glong volume; glong volume;
gboolean mute;
/* tracks list of our mixer interface implementation */
GList *tracks;
GstCaps *cached_caps; GstCaps *cached_caps;
/* lock used to protect writes and resets */ /* lock used to protect writes and resets */
GMutex *dsound_lock; GMutex *dsound_lock;
gboolean first_buffer_after_reset; gboolean first_buffer_after_reset;
GstBufferFormat buffer_format; GstAudioRingBufferFormatType type;
}; };
struct _GstDirectSoundSinkClass struct _GstDirectSoundSinkClass