From f41100e832c64f75fbe1f30e6db983fab7a2e6ee Mon Sep 17 00:00:00 2001 From: Joni Valtanen Date: Wed, 29 Jul 2009 15:35:03 +0200 Subject: directsoundsrc: Add DirectSound source plugin Fixes bug #344129. --- sys/directsound/Makefile.am | 12 + sys/directsound/gstdirectsoundplugin.c | 49 +++ sys/directsound/gstdirectsoundsrc.c | 587 +++++++++++++++++++++++++++++++++ sys/directsound/gstdirectsoundsrc.h | 112 +++++++ 4 files changed, 760 insertions(+) create mode 100644 sys/directsound/Makefile.am create mode 100644 sys/directsound/gstdirectsoundplugin.c create mode 100644 sys/directsound/gstdirectsoundsrc.c create mode 100644 sys/directsound/gstdirectsoundsrc.h (limited to 'sys/directsound') diff --git a/sys/directsound/Makefile.am b/sys/directsound/Makefile.am new file mode 100644 index 00000000..31994014 --- /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 00000000..e3816967 --- /dev/null +++ b/sys/directsound/gstdirectsoundplugin.c @@ -0,0 +1,49 @@ +/* GStreamer +* Copyright (C) 2005 Sebastien Moutte +* Copyright (C) 2007 Pioneers of the Inevitable +* +* 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 00000000..429d6b85 --- /dev/null +++ b/sys/directsound/gstdirectsoundsrc.c @@ -0,0 +1,587 @@ +/* + * GStreamer + * Copyright 2005 Thomas Vander Stichele + * Copyright 2005 Ronald S. Bultje + * Copyright 2005 Sébastien Moutte + * Copyright 2006 Joni Valtanen + * + * 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 +#include + +#include "gstdirectsoundsrc.h" + +#include +#include + 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 "); + +/* 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 00000000..2d164fc8 --- /dev/null +++ b/sys/directsound/gstdirectsoundsrc.h @@ -0,0 +1,112 @@ +/* + * GStreamer + * Copyright 2005 Thomas Vander Stichele + * Copyright 2005 Ronald S. Bultje + * Copyright 2005 Sébastien Moutte + * Copyright 2006 Joni Valtanen + * + * 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 +#include + +#include +#include + +/* 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__ */ -- cgit v1.2.1