summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoni Valtanen <joni.valtanen@movial.com>2009-07-29 15:35:03 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-07-29 15:37:08 +0200
commitf41100e832c64f75fbe1f30e6db983fab7a2e6ee (patch)
tree8867250539e95be76a8e309be087be7f3aabcb19
parent7fa5cba6f029aa89aa6f508f327aba9f6f8489f4 (diff)
directsoundsrc: Add DirectSound source plugin
Fixes bug #344129.
-rw-r--r--configure.ac16
-rw-r--r--sys/Makefile.am10
-rw-r--r--sys/directsound/Makefile.am12
-rw-r--r--sys/directsound/gstdirectsoundplugin.c49
-rw-r--r--sys/directsound/gstdirectsoundsrc.c587
-rw-r--r--sys/directsound/gstdirectsoundsrc.h112
6 files changed, 784 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 370886bcf..9a0637ab1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -354,6 +354,20 @@ fi
dnl *** sys plug-ins ***
+dnl DirectSound
+translit(dnm, m, l) AM_CONDITIONAL(USE_DIRECTSOUND, true)
+GST_CHECK_FEATURE(DIRECTSOUND, [DirectSound], [directsound], [
+ AC_CHECK_HEADER(dsound.h, HAVE_DIRECTSOUND="yes", HAVE_DIRECTSOUND="no")
+])
+
+AC_CHECK_LIB( dsound, DXGetErrorString9, [
+ echo "Errorstrings in DirectSoundSink - enabled"
+ AM_CONDITIONAL( DSOUND9, true )
+], [
+ echo "Errorstrings in DirectSoundSink - disabled"
+ AM_CONDITIONAL( DSOUND9, false )
+] )
+
dnl DirectDraw
translit(dnm, m, l) AM_CONDITIONAL(USE_DIRECTDRAW, true)
AG_GST_CHECK_FEATURE(DIRECTDRAW, [DirectDraw plug-in], directdrawsink, [
@@ -1516,6 +1530,7 @@ AM_CONDITIONAL(USE_CELT, false)
AM_CONDITIONAL(USE_DC1394, false)
AM_CONDITIONAL(USE_DIRECTFB, false)
AM_CONDITIONAL(USE_DIRECTDRAW, false)
+AM_CONDITIONAL(USE_DIRECTSOUND, false)
AM_CONDITIONAL(USE_DTS, false)
AM_CONDITIONAL(USE_DIRAC, false)
AM_CONDITIONAL(USE_DIVX, false)
@@ -1683,6 +1698,7 @@ sys/dshowdecwrapper/Makefile
sys/acmenc/Makefile
sys/acmmp3dec/Makefile
sys/directdraw/Makefile
+sys/directsound/Makefile
sys/dshowsrcwrapper/Makefile
sys/dshowvideosink/Makefile
sys/dvb/Makefile
diff --git a/sys/Makefile.am b/sys/Makefile.am
index 15c89e179..5608a8e74 100644
--- a/sys/Makefile.am
+++ b/sys/Makefile.am
@@ -28,6 +28,12 @@ else
DIRECTDRAW_DIR=
endif
+if USE_DIRECTSOUND
+DIRECTSOUND_DIR=directsound
+else
+DIRECTSOUND_DIR=
+endif
+
if USE_FBDEV
FBDEV_DIR=fbdev
else
@@ -76,8 +82,8 @@ else
VDPAU_DIR=
endif
-SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSS4_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR)
+SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSS4_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR)
-DIST_SUBDIRS = acmenc acmmp3dec directdraw dvb fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
+DIST_SUBDIRS = acmenc acmmp3dec directdraw directsound dvb fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \
oss4 osxvideo qtwrapper vcd vdpau wasapi wininet winks winscreencap
diff --git a/sys/directsound/Makefile.am b/sys/directsound/Makefile.am
new file mode 100644
index 000000000..319940148
--- /dev/null
+++ b/sys/directsound/Makefile.am
@@ -0,0 +1,12 @@
+plugin_LTLIBRARIES = libgstdirectsoundsrc.la
+
+libgstdirectsoundsrc_la_SOURCES = gstdirectsoundsrc.c gstdirectsoundplugin.c
+libgstdirectsoundsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
+ $(GST_PLUGINS_BASE_CFLAGS)
+libgstdirectsoundsrc_la_LIBADD = $(DIRECTDRAW_LIBS) \
+ $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \
+ -lgstinterfaces-$(GST_MAJORMINOR) -ldsound
+libgstdirectsoundsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTDRAW_LDFLAGS)
+libgstdirectsoundsrc_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS= gstdirectsoundsrc.h
diff --git a/sys/directsound/gstdirectsoundplugin.c b/sys/directsound/gstdirectsoundplugin.c
new file mode 100644
index 000000000..e3816967c
--- /dev/null
+++ b/sys/directsound/gstdirectsoundplugin.c
@@ -0,0 +1,49 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+* Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+*
+* gstdirectsoundplugin.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.
+*
+*
+* The development of this code was made possible due to the involvement
+* of Pioneers of the Inevitable, the creators of the Songbird Music player
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectsoundsrc.h"
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "directsoundsrc", GST_RANK_PRIMARY,
+ GST_TYPE_DIRECTSOUND_SRC))
+ return FALSE;
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "directsoundsrc",
+ "Direct Sound Source plugin library",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/directsound/gstdirectsoundsrc.c b/sys/directsound/gstdirectsoundsrc.c
new file mode 100644
index 000000000..429d6b85e
--- /dev/null
+++ b/sys/directsound/gstdirectsoundsrc.c
@@ -0,0 +1,587 @@
+/*
+ * GStreamer
+ * Copyright 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright 2005 Sébastien Moutte <sebastien@moutte.net>
+ * Copyright 2006 Joni Valtanen <joni.valtanen@movial.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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.
+ */
+
+/*
+ TODO: add device selection and check rate etc.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* */
+
+#include <gst/gst.h>
+#include <gst/audio/gstbaseaudiosrc.h>
+
+#include "gstdirectsoundsrc.h"
+
+#include <windows.h>
+#include <dsound.h>
+ GST_DEBUG_CATEGORY_STATIC (directsoundsrc_debug);
+
+#define GST_CAT_DEFAULT directsoundsrc_debug
+ static GstElementDetails gst_directsound_src_details =
+ GST_ELEMENT_DETAILS ("Audio Source (DIRECTCSOUND)", "Source/Audio",
+ "Capture from a soundcard via DIRECTSOUND",
+ "Joni Valtanen <joni.valtanen@movial.fi>");
+
+/* defaults here */
+#define DEFAULT_DEVICE 0
+
+/* properties */
+ enum
+{ PROP_0, PROP_DEVICE
+};
+ static HRESULT (WINAPI * pDSoundCaptureCreate) (LPGUID,
+ LPDIRECTSOUNDCAPTURE *, LPUNKNOWN);
+ static void gst_directsound_src_finalise (GObject * object);
+ static void gst_directsound_src_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+ static void gst_directsound_src_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+ static gboolean gst_directsound_src_open (GstAudioSrc * asrc);
+ static gboolean gst_directsound_src_close (GstAudioSrc * asrc);
+ static gboolean gst_directsound_src_prepare (GstAudioSrc * asrc,
+ GstRingBufferSpec * spec);
+ static gboolean gst_directsound_src_unprepare (GstAudioSrc * asrc);
+ static void gst_directsound_src_reset (GstAudioSrc * asrc);
+ static GstCaps *gst_directsound_src_getcaps (GstBaseSrc * bsrc);
+ static guint gst_directsound_src_read (GstAudioSrc * asrc, gpointer data,
+ guint length);
+ static void gst_directsound_src_dispose (GObject * object);
+ static void gst_directsound_src_do_init (GType type);
+ static guint gst_directsound_src_delay (GstAudioSrc * asrc);
+ static GstStaticPadTemplate directsound_src_src_factory =
+ GST_STATIC_PAD_TEMPLATE ( "src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+ "signed = (boolean) { TRUE, FALSE }, " "width = (int) 16, "
+ "depth = (int) 16, " "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 2 ]; " "audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, " "width = (int) 8, "
+ "depth = (int) 8, " "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, 2 ]"));
+ static void
+gst_directsound_src_do_init (GType type)
+{
+ GST_DEBUG_CATEGORY_INIT (directsoundsrc_debug, "directsoundsrc", 0,
+ "DirectSound Src");
+ } GST_BOILERPLATE_FULL (GstDirectSoundSrc, gst_directsound_src,
+ GstAudioSrc, GST_TYPE_AUDIO_SRC, gst_directsound_src_do_init);
+ static void
+gst_directsound_src_dispose (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+ } static void
+
+gst_directsound_src_finalise (GObject * object)
+{
+ GstDirectSoundSrc * dsoundsrc = GST_DIRECTSOUND_SRC (object);
+ g_mutex_free (dsoundsrc->dsound_lock);
+ } static void
+
+gst_directsound_src_base_init (gpointer g_class)
+{
+ GstElementClass * element_class = GST_ELEMENT_CLASS (g_class);
+ GST_DEBUG ("initializing directsoundsrc base\n");
+ gst_element_class_set_details (element_class, &gst_directsound_src_details);
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&directsound_src_src_factory));
+ }
+
+/* initialize the plugin's class */
+static void
+gst_directsound_src_class_init (GstDirectSoundSrcClass * klass)
+{
+ GObjectClass * gobject_class;
+ GstElementClass * gstelement_class;
+ GstBaseSrcClass * gstbasesrc_class;
+ GstBaseAudioSrcClass * gstbaseaudiosrc_class;
+ GstAudioSrcClass * gstaudiosrc_class;
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
+ gstaudiosrc_class = (GstAudioSrcClass *) klass;
+ GST_DEBUG ("initializing directsoundsrc class\n");
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_directsound_src_finalise);
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_directsound_src_dispose);
+ gobject_class->get_property =
+ GST_DEBUG_FUNCPTR (gst_directsound_src_get_property);
+ gobject_class->set_property =
+ GST_DEBUG_FUNCPTR (gst_directsound_src_set_property);
+ gstbasesrc_class->get_caps =
+ GST_DEBUG_FUNCPTR (gst_directsound_src_getcaps);
+ gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_directsound_src_open);
+ gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_directsound_src_close);
+ gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_directsound_src_read);
+ gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_directsound_src_prepare);
+ gstaudiosrc_class->unprepare =
+ GST_DEBUG_FUNCPTR (gst_directsound_src_unprepare);
+ gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_directsound_src_delay);
+ gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_directsound_src_reset);
+ } static GstCaps *
+
+gst_directsound_src_getcaps (GstBaseSrc * bsrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ GstCaps * caps = NULL;
+ GST_DEBUG ("get caps\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (bsrc);
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
+ (bsrc)));
+ return caps;
+ }
+
+ static void
+gst_directsound_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+
+ // GstDirectSoundSrc *src = GST_DIRECTSOUND_SRC (object);
+ GST_DEBUG ("set property\n");
+ switch (prop_id)
+ {
+
+#if 0
+ /* FIXME */
+ case PROP_DEVICE:
+ src->device = g_value_get_uint (value);
+ break;
+
+#endif /* */
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+
+ static void
+gst_directsound_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+
+#if 0
+ GstDirectSoundSrc * src = GST_DIRECTSOUND_SRC (object);
+
+#endif /* */
+ GST_DEBUG ("get property\n");
+ switch (prop_id) {
+
+#if 0
+ /* FIXME */
+ case PROP_DEVICE:
+ g_value_set_uint (value, src->device);
+ break;
+
+#endif /* */
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set functions
+ * initialize structure
+ */
+static void
+gst_directsound_src_init (GstDirectSoundSrc * src,
+ GstDirectSoundSrcClass * gclass)
+{
+ GST_DEBUG ("initializing directsoundsrc\n");
+ src->dsound_lock = g_mutex_new ();
+ } static gboolean
+
+gst_directsound_src_open (GstAudioSrc * asrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ HRESULT hRes; /* Result for windows functions */
+ GST_DEBUG ("initializing directsoundsrc\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+
+ /* Open dsound.dll */
+ dsoundsrc->DSoundDLL = LoadLibrary ("dsound.dll");
+ if (!dsoundsrc->DSoundDLL) {
+ goto dsound_open;
+ }
+
+ /* Building the DLL Calls */
+ pDSoundCaptureCreate =
+ (void *) GetProcAddress (dsoundsrc->DSoundDLL,
+ TEXT ("DirectSoundCaptureCreate"));
+
+ /* If everything is not ok */
+ if (!pDSoundCaptureCreate) {
+ goto capture_function;
+ }
+
+ /* FIXME: add here device selection */
+ /* Create capture object */
+ hRes = pDSoundCaptureCreate (NULL, &dsoundsrc->pDSC, NULL);
+ if (FAILED (hRes)) {
+ goto capture_object;
+ }
+ return TRUE;
+ capture_function: {
+ FreeLibrary (dsoundsrc->DSoundDLL);
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unable to get capturecreate function"), (NULL));
+ return FALSE;
+ }
+ capture_object: {
+ FreeLibrary (dsoundsrc->DSoundDLL);
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unable to create capture object"), (NULL));
+ return FALSE;
+ }
+ dsound_open: {
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unable to open dsound.dll"), (NULL));
+ return FALSE;
+ }
+ }
+
+ static gboolean
+gst_directsound_src_close (GstAudioSrc * asrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ HRESULT hRes; /* Result for windows functions */
+ GST_DEBUG ("initializing directsoundsrc\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+
+ /* Release capture handler */
+ hRes = IDirectSoundCapture_Release (dsoundsrc->pDSC);
+
+ /* Close library */
+ FreeLibrary (dsoundsrc->DSoundDLL);
+ return TRUE;
+ }
+
+ static gboolean
+gst_directsound_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ WAVEFORMATEX wfx; /* Wave format structure */
+ HRESULT hRes; /* Result for windows functions */
+ DSCBUFFERDESC descSecondary; /* Capturebuffer decsiption */
+ int fmt = 0; /* audio format */
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+ GST_DEBUG ("initializing directsoundsrc\n");
+
+ /* Define buffer */
+ memset (&wfx, 0, sizeof (WAVEFORMATEX));
+ wfx.wFormatTag = WAVE_FORMAT_PCM; /* should be WAVE_FORMAT_PCM */
+ wfx.nChannels = spec->channels;
+ wfx.nSamplesPerSec = spec->rate; /* 8000|11025|22050|44100 */
+ wfx.wBitsPerSample = spec->width; // 8|16;
+ wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ wfx.cbSize = 0; /* This size is allways for PCM-format */
+
+ /* 1 or 2 Channels etc...
+ FIXME: Never really tested. Is this ok?
+ */
+ if (spec->width == 16 && spec->channels == 1) {
+ spec->format = GST_S16_LE;
+ } else if (spec->width == 16 && spec->channels == 2) {
+ spec->format = GST_U16_LE;
+ } else if (spec->width == 8 && spec->channels == 1) {
+ spec->format = GST_S8;
+ } else if (spec->width == 8 && spec->channels == 2) {
+ spec->format = GST_U8;
+ }
+
+ /* Set the buffer size to two seconds.
+ This should never reached.
+ */
+ dsoundsrc->buffer_size = wfx.nAvgBytesPerSec * 2;
+
+ //notifysize * 16; //spec->width; /*original 16*/
+ GST_DEBUG ("Buffer size: %d", dsoundsrc->buffer_size);
+
+ /* Init secondary buffer desciption */
+ memset (&descSecondary, 0, sizeof (DSCBUFFERDESC));
+ descSecondary.dwSize = sizeof (DSCBUFFERDESC);
+ descSecondary.dwFlags = 0;
+ descSecondary.dwReserved = 0;
+
+ /* This is not primary buffer so have to set size */
+ descSecondary.dwBufferBytes = dsoundsrc->buffer_size;
+ descSecondary.lpwfxFormat = &wfx;
+
+ /* Create buffer */
+ hRes =
+ IDirectSoundCapture_CreateCaptureBuffer (dsoundsrc->pDSC, &descSecondary,
+ &dsoundsrc->pDSBSecondary, NULL);
+ if (hRes != DS_OK) {
+ goto capture_buffer;
+ }
+ spec->channels = wfx.nChannels;
+ spec->rate = wfx.nSamplesPerSec;
+ spec->bytes_per_sample = (spec->width / 8) * spec->channels;
+ dsoundsrc->bytes_per_sample = spec->bytes_per_sample;
+ GST_DEBUG ("latency time: %llu - buffer time: %llu", spec->latency_time,
+ spec->buffer_time);
+
+ /* Buffer-time should be allways more than 2*latency */
+ if (spec->buffer_time < spec->latency_time * 2) {
+ spec->buffer_time = spec->latency_time * 2;
+ GST_WARNING ("buffer-time was less than latency");
+ }
+
+ /* Save the times */
+ dsoundsrc->buffer_time = spec->buffer_time;
+ dsoundsrc->latency_time = spec->latency_time;
+ dsoundsrc->latency_size =
+ (gint) wfx.nAvgBytesPerSec * dsoundsrc->latency_time / 1000000.0;
+ spec->segsize =
+ (guint) (((double) spec->buffer_time / 1000000.0) * wfx.nAvgBytesPerSec);
+
+ /* just in case */
+ if (spec->segsize < 1)
+ spec->segsize = 1;
+ spec->segtotal = spec->width * (wfx.nAvgBytesPerSec / spec->segsize);
+ GST_DEBUG ("bytes/sec: %d, buffer size: %d, segsize: %d, segtotal: %d",
+ wfx.nAvgBytesPerSec, dsoundsrc->buffer_size, spec->segsize,
+ spec->segtotal);
+ spec->silence_sample[0] = 0;
+ spec->silence_sample[1] = 0;
+ spec->silence_sample[2] = 0;
+ spec->silence_sample[3] = 0;
+ if (spec->width != 16 && spec->width != 8)
+ goto dodgy_width;
+
+ /* Not readed anything yet */
+ dsoundsrc->current_circular_offset = 0;
+ GST_DEBUG ("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", spec->channels, spec->rate, spec->bytes_per_sample, wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nBlockAlign, wfx.nAvgBytesPerSec);
+ return TRUE;
+ wrong_format: {
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unable to get format %d", spec->format), (NULL));
+ return FALSE;
+ }
+ capture_buffer: {
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unable to create capturebuffer"), (NULL));
+ return FALSE;
+ }
+ dodgy_width: {
+ GST_ELEMENT_ERROR (dsoundsrc, RESOURCE, OPEN_READ,
+ ("Unexpected width %d", spec->width), (NULL));
+ return FALSE;
+ }
+ }
+
+ static gboolean
+gst_directsound_src_unprepare (GstAudioSrc * asrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ HRESULT hRes; /* Result for windows functions */
+
+ /* Resets */
+ GST_DEBUG ("unpreparing directsoundsrc");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+
+ /* Stop capturing */
+ hRes = IDirectSoundCaptureBuffer_Stop (dsoundsrc->pDSBSecondary);
+
+ /* Release buffer */
+ hRes = IDirectSoundCaptureBuffer_Release (dsoundsrc->pDSBSecondary);
+ return TRUE;
+ }
+
+
+/*
+return number of readed bytes */
+static guint
+gst_directsound_src_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ HRESULT hRes; /* Result for windows functions */
+ DWORD dwCurrentCaptureCursor = 0;
+ DWORD dwBufferSize = 0;
+ LPVOID pLockedBuffer1 = NULL;
+ LPVOID pLockedBuffer2 = NULL;
+ DWORD dwSizeBuffer1 = 0;
+ DWORD dwSizeBuffer2 = 0;
+ DWORD dwStatus = 0;
+ GST_DEBUG ("reading directsoundsrc\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+ GST_DSOUND_LOCK (dsoundsrc);
+
+ /* Get current buffer status */
+ hRes =
+ IDirectSoundCaptureBuffer_GetStatus (dsoundsrc->pDSBSecondary,
+ &dwStatus);
+
+ /* Starting capturing if not allready */
+ if (!(dwStatus & DSCBSTATUS_CAPTURING)) {
+ hRes =
+ IDirectSoundCaptureBuffer_Start (dsoundsrc->pDSBSecondary,
+ DSCBSTART_LOOPING);
+
+ // Sleep (dsoundsrc->latency_time/1000);
+ GST_DEBUG ("capture started");
+ }
+
+ // calculate_buffersize:
+ while (length > dwBufferSize) {
+ Sleep (dsoundsrc->latency_time / 1000);
+ hRes =
+ IDirectSoundCaptureBuffer_GetCurrentPosition (dsoundsrc->pDSBSecondary,
+ &dwCurrentCaptureCursor, NULL);
+
+ /* calculate the buffer */
+ if (dwCurrentCaptureCursor < dsoundsrc->current_circular_offset) {
+ dwBufferSize = dsoundsrc->buffer_size -
+ (dsoundsrc->current_circular_offset - dwCurrentCaptureCursor);
+ } else {
+ dwBufferSize =
+ dwCurrentCaptureCursor - dsoundsrc->current_circular_offset;
+ }
+ } // while (...
+
+ /* Lock the buffer */
+ hRes =
+ IDirectSoundCaptureBuffer_Lock (dsoundsrc->pDSBSecondary,
+ dsoundsrc->current_circular_offset, length, &pLockedBuffer1,
+ &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L);
+
+ /* Copy buffer data to another buffer */
+ if (hRes == DS_OK) {
+ memcpy (data, pLockedBuffer1, dwSizeBuffer1);
+ }
+
+ /* ...and if something is in another buffer */
+ if (pLockedBuffer2 != NULL) {
+ memcpy ((data + dwSizeBuffer1), pLockedBuffer2, dwSizeBuffer2);
+ }
+ dsoundsrc->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2;
+ dsoundsrc->current_circular_offset %= dsoundsrc->buffer_size;
+ IDirectSoundCaptureBuffer_Unlock (dsoundsrc->pDSBSecondary, pLockedBuffer1,
+ dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2);
+ GST_DSOUND_UNLOCK (dsoundsrc);
+
+ /* return length (readed data size in bytes) */
+ return length;
+ }
+
+ static guint
+gst_directsound_src_delay (GstAudioSrc * asrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ HRESULT hRes;
+ DWORD dwCurrentCaptureCursor;
+ DWORD dwBytesInQueue = 0;
+ gint nNbSamplesInQueue = 0;
+ GST_DEBUG ("Delay\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+
+ /* evaluate the number of samples in queue in the circular buffer */
+ hRes =
+ IDirectSoundCaptureBuffer_GetCurrentPosition (dsoundsrc->pDSBSecondary,
+ &dwCurrentCaptureCursor, NULL);
+
+ /* FIXME: Check is this calculated right */
+ if (hRes == S_OK) {
+ if (dwCurrentCaptureCursor < dsoundsrc->current_circular_offset) {
+ dwBytesInQueue =
+ dsoundsrc->buffer_size - (dsoundsrc->current_circular_offset -
+ dwCurrentCaptureCursor);
+ } else {
+ dwBytesInQueue =
+ dwCurrentCaptureCursor - dsoundsrc->current_circular_offset;
+ }
+ nNbSamplesInQueue = dwBytesInQueue / dsoundsrc->bytes_per_sample;
+ }
+ return nNbSamplesInQueue;
+ }
+
+ static void
+gst_directsound_src_reset (GstAudioSrc * asrc)
+{
+ GstDirectSoundSrc * dsoundsrc;
+ LPVOID pLockedBuffer = NULL;
+ DWORD dwSizeBuffer = 0;
+ GST_DEBUG ("reset directsoundsrc\n");
+ dsoundsrc = GST_DIRECTSOUND_SRC (asrc);
+
+#if 0
+ IDirectSoundCaptureBuffer_Stop (dsoundsrc->pDSBSecondary);
+
+#endif /* */
+ GST_DSOUND_LOCK (dsoundsrc);
+ if (dsoundsrc->pDSBSecondary) {
+
+ /*stop capturing */
+ HRESULT hRes =
+ IDirectSoundCaptureBuffer_Stop (dsoundsrc->pDSBSecondary);
+
+ /*reset position */
+ /* hRes = IDirectSoundCaptureBuffer_SetCurrentPosition (dsoundsrc->pDSBSecondary, 0); */
+
+ /*reset the buffer */
+ hRes =
+ IDirectSoundCaptureBuffer_Lock (dsoundsrc->pDSBSecondary,
+ dsoundsrc->current_circular_offset, dsoundsrc->buffer_size,
+ pLockedBuffer, &dwSizeBuffer, NULL, NULL, 0L);
+ if (SUCCEEDED (hRes)) {
+ memset (pLockedBuffer, 0, dwSizeBuffer);
+ hRes =
+ IDirectSoundCaptureBuffer_Unlock (dsoundsrc->pDSBSecondary,
+ pLockedBuffer, dwSizeBuffer, NULL, 0);
+ }
+ dsoundsrc->current_circular_offset = 0;
+ }
+ GST_DSOUND_UNLOCK (dsoundsrc);
+ }
+
+
diff --git a/sys/directsound/gstdirectsoundsrc.h b/sys/directsound/gstdirectsoundsrc.h
new file mode 100644
index 000000000..2d164fc81
--- /dev/null
+++ b/sys/directsound/gstdirectsoundsrc.h
@@ -0,0 +1,112 @@
+/*
+ * GStreamer
+ * Copyright 2005 Thomas Vander Stichele <thomas@apestaart.org>
+ * Copyright 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright 2005 Sébastien Moutte <sebastien@moutte.net>
+ * Copyright 2006 Joni Valtanen <joni.valtanen@movial.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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.
+ */
+
+#ifndef __GST_DIRECTSOUNDSRC_H__
+#define __GST_DIRECTSOUNDSRC_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+
+#include <windows.h>
+#include <dsound.h>
+
+/* add here some headers if needed */
+
+
+G_BEGIN_DECLS
+
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_DIRECTSOUND_SRC (gst_directsound_src_get_type())
+#define GST_DIRECTSOUND_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECTSOUND_SRC,GstDirectSoundSrc))
+#define GST_DIRECTSOUND_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECTSOUND_SRC,GstDirectSoundSrcClass))
+#define GST_IS_DIRECTSOUND_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECTSOUND_SRC))
+#define GST_IS_DIRECTSOUND_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECTSOUND_SRC))
+
+typedef struct _GstDirectSoundSrc GstDirectSoundSrc;
+typedef struct _GstDirectSoundSrcClass GstDirectSoundSrcClass;
+
+#define GST_DSOUND_LOCK(obj) (g_mutex_lock (obj->dsound_lock))
+#define GST_DSOUND_UNLOCK(obj) (g_mutex_unlock (obj->dsound_lock))
+
+struct _GstDirectSoundSrc
+{
+
+ GstAudioSrc src;
+
+ HINSTANCE DSoundDLL; /* DLL instance */
+ LPDIRECTSOUNDCAPTURE pDSC; /* DirectSoundCapture*/
+ LPDIRECTSOUNDCAPTUREBUFFER pDSBSecondary; /*Secondaty capturebuffer*/
+ DWORD current_circular_offset;
+
+ HANDLE rghEvent;
+ DWORD notifysize;
+
+ guint buffer_size;
+ guint latency_size;
+ guint bytes_per_sample;
+
+ guint buffer_time;
+ guint latency_time;
+
+
+#if 0
+ guint device;
+#endif
+
+ GMutex *dsound_lock;
+
+};
+
+struct _GstDirectSoundSrcClass
+{
+ GstAudioSrcClass parent_class;
+};
+
+GType gst_directsound_src_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_DIRECTSOUNDSRC_H__ */