From 877b1be83af339df7884d4cbc56498ba45394ae9 Mon Sep 17 00:00:00 2001 From: Sébastien Moutte Date: Wed, 23 May 2007 22:44:12 +0000 Subject: docs/plugins/gst-plugins-bad-plugins.args: Remove directsoundsink property doc as this sink use the mixer interface now. Original commit message from CVS: * docs/plugins/gst-plugins-bad-plugins.args: Remove directsoundsink property doc as this sink use the mixer interface now. * docs/plugins/gst-plugins-bad-plugins.interfaces: Add interfaces implemented by Windows sinks. * sys/directsound/gstdirectsoundsink.c: * sys/directsound/gstdirectsoundsink.h: Remove directsoundsink property and implement the mixer interface. * win32/vs6/gst_plugins_bad.dsw: * win32/vs6/libgstdirectsound.dsp: Update project files. * gst-libs/gst/dshow/gstdshow.cpp: * gst-libs/gst/dshow/gstdshow.h: * gst-libs/gst/dshow/gstdshowfakesink.cpp: * gst-libs/gst/dshow/gstdshowfakesink.h: * gst-libs/gst/dshow/gstdshowfakesrc.cpp: * gst-libs/gst/dshow/gstdshowfakesrc.h: * gst-libs/gst/dshow/gstdshowinterface.cpp: * gst-libs/gst/dshow/gstdshowinterface.h: * win32/common/libgstdshow.def: * win32/vs6/libgstdshow.dsp: Add a new gst library which allow to create internal Direct Show graph (pipelines) to wrap Windows sources, decoders or encoders. It includes a DirectShow fake source and sink and utility functions. * sys/dshowsrcwrapper/gstdshowaudiosrc.c: * sys/dshowsrcwrapper/gstdshowaudiosrc.h: * sys/dshowsrcwrapper/gstdshowsrcwrapper.c: * sys/dshowsrcwrapper/gstdshowsrcwrapper.h: * sys/dshowsrcwrapper/gstdshowvideosrc.c: * sys/dshowsrcwrapper/gstdshowvideosrc.h: * win32/vs6/libdshowsrcwrapper.dsp: Add a new plugin to wrap DirectShow sources on Windows. It gets data from any webcam, dv cam, micro. We could add tv tunner card later. --- sys/directsound/gstdirectsoundsink.c | 197 ++++++++++++++++++++++------------- sys/directsound/gstdirectsoundsink.h | 14 ++- 2 files changed, 133 insertions(+), 78 deletions(-) (limited to 'sys/directsound') diff --git a/sys/directsound/gstdirectsoundsink.c b/sys/directsound/gstdirectsoundsink.c index e0b262ed..97127bdb 100644 --- a/sys/directsound/gstdirectsoundsink.c +++ b/sys/directsound/gstdirectsoundsink.c @@ -76,13 +76,8 @@ static void gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass); static void gst_directsound_sink_init (GstDirectSoundSink * dsoundsink, GstDirectSoundSinkClass * g_class); static void gst_directsound_sink_finalise (GObject * object); -static void gst_directsound_sink_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_directsound_sink_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); static GstCaps *gst_directsound_sink_getcaps (GstBaseSink * bsink); - static gboolean gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec); static gboolean gst_directsound_sink_unprepare (GstAudioSink * asink); @@ -94,6 +89,12 @@ static guint gst_directsound_sink_write (GstAudioSink * asink, gpointer data, static guint gst_directsound_sink_delay (GstAudioSink * asink); static void gst_directsound_sink_reset (GstAudioSink * asink); +/* interfaces */ +static void gst_directsound_sink_interfaces_init (GType type); +static void +gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass * + iface); +static void gst_directsound_sink_mixer_interface_init (GstMixerClass * iface); static GstStaticPadTemplate directsoundsink_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -110,22 +111,108 @@ static GstStaticPadTemplate directsoundsink_sink_factory = "depth = (int) 8, " "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")); -enum +GST_BOILERPLATE_FULL (GstDirectSoundSink, gst_directsound_sink, GstAudioSink, + GST_TYPE_AUDIO_SINK, gst_directsound_sink_interfaces_init); + +/* 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) { - PROP_0, - PROP_ATTENUATION -}; + 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 -_do_init (GType directsoundsink_type) +gst_directsound_sink_implements_interface_init (GstImplementsInterfaceClass * + iface) { - GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0, - "DirectSound sink"); + iface->supported = gst_directsound_sink_interface_supported; } -GST_BOILERPLATE_FULL (GstDirectSoundSink, gst_directsound_sink, GstAudioSink, - GST_TYPE_AUDIO_SINK, _do_init); +/* + * 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; +} + +/* + * 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]; + + if (dsoundsink->pDSBSecondary) { + /* DirectSound is using attenuation in the following range + * (DSBVOLUME_MIN=-10000, DSBVOLUME_MAX=0) */ + glong ds_attenuation = DSBVOLUME_MIN + (dsoundsink->volume * 100); + + IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, ds_attenuation); + } + } +} + +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 (GstMixerClass * 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) @@ -134,6 +221,12 @@ gst_directsound_sink_finalise (GObject * 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); } @@ -162,13 +255,12 @@ gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass) gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass; gstaudiosink_class = (GstAudioSinkClass *) klass; + GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0, + "DirectSound sink"); + parent_class = g_type_class_peek_parent (klass); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_directsound_sink_finalise); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_directsound_sink_get_property); - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_directsound_sink_set_property); gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_directsound_sink_getcaps); @@ -182,69 +274,28 @@ gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass) gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_directsound_sink_write); gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_directsound_sink_delay); gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_directsound_sink_reset); - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ATTENUATION, - g_param_spec_long ("attenuation", "Attenuation of the sound", - "The attenuation for the directsound buffer (default is 0 so the directsound buffer will not be attenuated)", - -10000, 0, 0, G_PARAM_READWRITE)); -} - -static void -gst_directsound_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDirectSoundSink *dsoundsink; - - dsoundsink = GST_DIRECTSOUND_SINK (object); - - switch (prop_id) { - case PROP_ATTENUATION: - { - glong attenuation = g_value_get_long (value); - - if (attenuation != dsoundsink->attenuation) { - dsoundsink->attenuation = attenuation; - - if (dsoundsink->pDSBSecondary) - IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, - dsoundsink->attenuation); - } - - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_directsound_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDirectSoundSink *dsoundsink; - - dsoundsink = GST_DIRECTSOUND_SINK (object); - - switch (prop_id) { - case PROP_ATTENUATION: - g_value_set_long (value, dsoundsink->attenuation); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } } static void gst_directsound_sink_init (GstDirectSoundSink * dsoundsink, GstDirectSoundSinkClass * g_class) { + GstMixerTrack *track = NULL; + + 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->pDSBSecondary = NULL; dsoundsink->current_circular_offset = 0; dsoundsink->buffer_size = DSBSIZE_MIN; - dsoundsink->attenuation = 0; + dsoundsink->volume = 100; dsoundsink->dsound_lock = g_mutex_new (); dsoundsink->first_buffer_after_reset = FALSE; } @@ -335,10 +386,6 @@ gst_directsound_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) return FALSE; } - if (dsoundsink->attenuation != 0) - IDirectSoundBuffer_SetVolume (dsoundsink->pDSBSecondary, - dsoundsink->attenuation); - return TRUE; } diff --git a/sys/directsound/gstdirectsoundsink.h b/sys/directsound/gstdirectsoundsink.h index ea7ccbdf..6acf92b4 100644 --- a/sys/directsound/gstdirectsoundsink.h +++ b/sys/directsound/gstdirectsoundsink.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -51,20 +52,27 @@ struct _GstDirectSoundSink { GstAudioSink sink; + /* directsound object interface pointer */ LPDIRECTSOUND pDS; + /* directsound sound object interface pointer */ LPDIRECTSOUNDBUFFER pDSBSecondary; - /*DirectSound buffer size */ + /* directSound buffer size */ guint buffer_size; - /*Offset of the circular buffer where we must write next */ + /* offset of the circular buffer where we must write next */ guint current_circular_offset; guint bytes_per_sample; - glong attenuation; + /* current volume setup by mixer interface */ + glong volume; + /* tracks list of our mixer interface implementation */ + GList *tracks; + + /* lock used to protect writes and resets */ GMutex *dsound_lock; gboolean first_buffer_after_reset; -- cgit