Author: silverblade
Date: Wed Feb 18 13:10:02 2009
New Revision: 39667
URL:
http://svn.reactos.org/svn/reactos?rev=39667&view=rev
Log:
Removed hooks for prepare/unprepare/stream of WAVEHDR. These are handled
internally by MME-Buddy. Instead, it simply provides a hook to do the
actual streaming, complete with an OVERLAPPED structure and I/O completion
routine. Also started imlpementation of wdmaud.drv to begin interaction
with code janderwald is working on.
Added:
trunk/reactos/lib/drivers/sound/mmebuddy/wave/streaming.c (with props)
Modified:
trunk/reactos/dll/win32/sndblst/sndblst.c
trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c
trunk/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild
trunk/reactos/include/reactos/libs/sound/mmebuddy.h
trunk/reactos/lib/drivers/sound/mmebuddy/deviceinstance.c
trunk/reactos/lib/drivers/sound/mmebuddy/mmebuddy.rbuild
trunk/reactos/lib/drivers/sound/mmebuddy/wave/header.c
trunk/reactos/lib/drivers/sound/mmebuddy/wave/wodMessage.c
trunk/reactos/lib/drivers/sound/mment4/control.c
Modified: trunk/reactos/dll/win32/sndblst/sndblst.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/sndblst/sndblst.…
==============================================================================
--- trunk/reactos/dll/win32/sndblst/sndblst.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/sndblst/sndblst.c [iso-8859-1] Wed Feb 18 13:10:02 2009
@@ -98,9 +98,8 @@
FuncTable.SetWaveFormat = SetNt4WaveDeviceFormat;
FuncTable.Open = OpenNt4SoundDevice;
FuncTable.Close = CloseNt4SoundDevice;
- FuncTable.PrepareWaveHeader = NULL;
- FuncTable.UnprepareWaveHeader = NULL;
- FuncTable.SubmitWaveHeader = NULL;
+ FuncTable.CommitWaveBuffer = WriteFileEx_Committer;
+ //FuncTable.SubmitWaveHeaderToDevice = SubmitWaveHeaderToDevice;
SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
Modified: trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wdmaud.drv/wdmau…
==============================================================================
--- trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wdmaud.drv/wdmaud.c [iso-8859-1] Wed Feb 18 13:10:02 2009
@@ -1,243 +1,145 @@
/*
+ * PROJECT: ReactOS Sound System
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: dll/win32/wdmaud.drv/wdmaud.c
*
- * PROJECT: ReactOS WDM Audio driver mapper
- * FILE: dll/win32/wdmaud.drv/wdmaud.c
- * PURPOSE: wdmaud.drv
- * PROGRAMMER: Dmitry Chapyshev (dmitry(a)reactos.org)
+ * PURPOSE: WDM Audio Driver (User-mode part)
+ * PROGRAMMERS: Andrew Greenwood (silverblade(a)reactos.org)
*
- * UPDATE HISTORY:
- * 25/05/2008 Created
+ * NOTES: Looking for wodMessage & co? You won't find them here. Try
+ * the MME Buddy library, which is where these routines are
+ * actually implemented.
+ *
*/
-#include <stdarg.h>
+#include <windows.h>
+#include <ntddsnd.h>
+#include <sndtypes.h>
+#include <mmddk.h>
+#include <mmebuddy.h>
-#include <windows.h>
-#include <mmsystem.h>
-#include <mmddk.h>
-#include <mmreg.h>
-#include <debug.h>
+#define KERNEL_DEVICE_NAME L"\\\\Device\\wdmaud"
-DWORD APIENTRY
-mxdMessage(UINT uDevice,
- UINT uMsg,
- DWORD dwUser,
- DWORD dwParam1,
- DWORD dwParam2)
+HANDLE KernelHandle = INVALID_HANDLE_VALUE;
+
+APIENTRY LONG
+DriverProc(
+ DWORD DriverId,
+ HANDLE DriverHandle,
+ UINT Message,
+ LONG Parameter1,
+ LONG Parameter2)
{
- DPRINT1("mxdMessage(%04X, %04X, %08X, %08X, %08X);\n", uDevice, uMsg,
dwUser, dwParam1, dwParam2);
+ MMRESULT Result;
- switch (uMsg)
+ switch ( Message )
{
- case MXDM_INIT:
- break;
+ case DRV_LOAD :
+ {
+ SND_TRACE(L"DRV_LOAD\n");
- case MXDM_GETNUMDEVS:
- break;
+ Result = InitEntrypointMutexes();
- case MXDM_GETDEVCAPS:
- break;
+ if ( ! MMSUCCESS(Result) )
+ return 0L;
- case MXDM_OPEN:
- break;
+ KernelHandle = CreateFile(KERNEL_DEVICE_NAME,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE, // ok?
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL);
- case MXDM_CLOSE:
- break;
+ if ( KernelHandle == INVALID_HANDLE_VALUE )
+ {
+ SND_ERR(L"Failed to open %s", KERNEL_DEVICE_NAME);
+ CleanupEntrypointMutexes();
- case MXDM_GETLINEINFO:
- break;
+ UnlistAllSoundDevices();
- case MXDM_GETLINECONTROLS:
- break;
+ return 0L;
+ }
- case MXDM_GETCONTROLDETAILS:
- break;
+ SND_TRACE(L"Initialisation complete\n");
- case MXDM_SETCONTROLDETAILS:
- break;
+ return 1L;
+ }
+
+ case DRV_FREE :
+ {
+ SND_TRACE(L"DRV_FREE\n");
+
+ if ( KernelHandle != INVALID_HANDLE_VALUE )
+ {
+ CloseHandle(KernelHandle);
+ KernelHandle = INVALID_HANDLE_VALUE;
+ }
+
+ /* TODO: Clean up the path names! */
+ UnlistAllSoundDevices();
+
+ CleanupEntrypointMutexes();
+
+ SND_TRACE(L"Unfreed memory blocks: %d\n",
+ GetMemoryAllocationCount());
+
+ return 1L;
+ }
+
+ case DRV_ENABLE :
+ case DRV_DISABLE :
+ {
+ SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
+ return 1L;
+ }
+
+ case DRV_OPEN :
+ case DRV_CLOSE :
+ {
+ SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
+ return 1L;
+ }
+
+ case DRV_QUERYCONFIGURE :
+ {
+ SND_TRACE(L"DRV_QUERYCONFIGURE");
+ return 0L;
+ }
+ case DRV_CONFIGURE :
+ return DRVCNF_OK;
+
+ default :
+ SND_TRACE(L"Unhandled message %d\n", Message);
+ return DefDriverProc(DriverId,
+ DriverHandle,
+ Message,
+ Parameter1,
+ Parameter2);
}
-
- return MMSYSERR_NOTSUPPORTED;
}
-DWORD APIENTRY
-auxMessage(UINT uDevice,
- UINT uMsg,
- DWORD dwUser,
- DWORD dwParam1,
- DWORD dwParam2)
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
{
- DPRINT1("auxMessage(%04X, %04X, %08X, %08X, %08X);\n", uDevice, uMsg,
dwUser, dwParam1, dwParam2);
-
- switch (uMsg)
+ switch ( fdwReason )
{
- case AUXDM_GETDEVCAPS:
-
- break;
-
- case AUXDM_GETNUMDEVS:
-
- break;
-
- case AUXDM_GETVOLUME:
-
- break;
-
- case AUXDM_SETVOLUME:
-
- break;
-
- default:
- return MMSYSERR_NOTSUPPORTED;
- }
-
- return MMSYSERR_NOTSUPPORTED;
-}
-
-DWORD APIENTRY
-wodMessage(UINT uDevice,
- UINT uMsg,
- DWORD dwUser,
- DWORD dwParam1,
- DWORD dwParam2)
-{
- DPRINT1("wodMessage(%04X, %04X, %08X, %08X, %08X);\n", uDevice, uMsg,
dwUser, dwParam1, dwParam2);
-
- switch (uMsg)
- {
- case WODM_GETNUMDEVS:
- break;
-
- case WODM_GETDEVCAPS:
- break;
-
- case WODM_OPEN:
- break;
-
- case WODM_CLOSE:
- break;
-
- case WODM_WRITE:
- break;
-
- case WODM_PAUSE:
- break;
-
- case WODM_RESTART:
- break;
-
- case WODM_RESET:
- break;
-
- case WODM_BREAKLOOP:
- break;
-
- case WODM_GETPOS:
- break;
-
- case WODM_SETPITCH:
- break;
-
- case WODM_SETVOLUME:
- break;
-
- case WODM_SETPLAYBACKRATE:
- break;
-
- case WODM_GETPITCH:
- break;
-
- case WODM_GETVOLUME:
- break;
-
- case WODM_GETPLAYBACKRATE:
- break;
-
- default:
- return MMSYSERR_NOTSUPPORTED;
- }
-
- return MMSYSERR_NOTSUPPORTED;
-}
-
-DWORD APIENTRY
-widMessage(UINT uDevice,
- UINT uMsg,
- DWORD dwUser,
- DWORD dwParam1,
- DWORD dwParam2)
-{
- DPRINT1("widMessage(%04X, %04X, %08X, %08X, %08X);\n", uDevice, uMsg,
dwUser, dwParam1, dwParam2);
-
- switch (uMsg)
- {
- case WIDM_GETNUMDEVS:
- break;
-
- case WIDM_GETDEVCAPS:
- break;
-
- case WIDM_OPEN:
- break;
-
- case WIDM_CLOSE:
- break;
-
- case WIDM_ADDBUFFER:
- break;
-
- case WIDM_STOP:
- break;
-
- case WIDM_START:
- break;
-
- case WIDM_RESET:
- break;
-
- case WIDM_GETPOS:
- break;
-
- default:
- return MMSYSERR_NOTSUPPORTED;
- }
-
- return MMSYSERR_NOTSUPPORTED;
-}
-
-DWORD APIENTRY
-modMessage(UINT uDevice,
- UINT uMsg,
- DWORD dwUser,
- DWORD dwParam1,
- DWORD dwParam2)
-{
- DPRINT1("modMessage(%04X, %04X, %08X, %08X, %08X);\n", uDevice, uMsg,
dwUser, dwParam1, dwParam2);
-
- return MMSYSERR_NOTSUPPORTED;
-}
-
-LRESULT APIENTRY
-DriverProc(DWORD dwDriverID,
- HDRVR hDriver,
- UINT uiMessage,
- LPARAM lParam1,
- LPARAM lParam2)
-{
- return DefDriverProc(dwDriverID, hDriver, uiMessage, lParam1, lParam2);
-}
-
-BOOL WINAPI
-DllMain(IN HINSTANCE hinstDLL,
- IN DWORD dwReason,
- IN LPVOID lpvReserved)
-{
- switch (dwReason)
- {
- case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hinstDLL);
+ case DLL_PROCESS_ATTACH :
+ SND_TRACE(L"WDMAUD.DRV - Process attached\n");
+ break;
+ case DLL_PROCESS_DETACH :
+ SND_TRACE(L"WDMAUD.DRV - Process detached\n");
+ break;
+ case DLL_THREAD_ATTACH :
+ SND_TRACE(L"WDMAUD.DRV - Thread attached\n");
+ break;
+ case DLL_THREAD_DETACH :
+ SND_TRACE(L"WDMAUD.DRV - Thread detached\n");
break;
}
return TRUE;
}
-
Modified: trunk/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wdmaud.drv/wdmau…
==============================================================================
--- trunk/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild [iso-8859-1] Wed Feb 18 13:10:02
2009
@@ -1,12 +1,14 @@
-<module name="wdmaud.drv" type="win32dll"
baseaddress="${BASEADDRESS_WDMAUD}" installbase="system32"
installname="wdmaud.drv">
+<module name="wdmaud.drv" type="win32dll"
baseaddress="${BASEADDRESS_WDMAUD}" installbase="system32"
installname="wdmaud.drv" unicode="yes">
<importlibrary definition="wdmaud.spec" />
<include base="wdmaud.drv">.</include>
- <define name="_DISABLE_TIDENTS" />
- <library>advapi32</library>
+ <include base="ReactOS">include/reactos/libs/sound</include>
+ <define name="DEBUG_NT4" /><!-- Use custom debug routines -->
+ <library>mmebuddy</library>
+ <library>ntdll</library>
<library>kernel32</library>
- <library>winmm</library>
<library>user32</library>
<library>winmm</library>
+ <library>advapi32</library>
<file>wdmaud.c</file>
<file>wdmaud.rc</file>
</module>
Modified: trunk/reactos/include/reactos/libs/sound/mmebuddy.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/sound…
==============================================================================
--- trunk/reactos/include/reactos/libs/sound/mmebuddy.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/libs/sound/mmebuddy.h [iso-8859-1] Wed Feb 18 13:10:02
2009
@@ -32,7 +32,7 @@
MessageBox(0, dbg_popup_msg, dbg_popup_title, MB_OK | MB_TASKMODAL); \
}
-#ifdef DEBUG_NT4
+#ifndef NDEBUG
#define SND_ERR(...) \
{ \
WCHAR dbg_popup_msg[1024]; \
@@ -62,11 +62,24 @@
} \
}
+ #define DUMP_WAVEHDR_QUEUE(sound_device_instance) \
+ { \
+ PWAVEHDR CurrDumpHdr = sound_device_instance->HeadWaveHeader; \
+ SND_TRACE(L"-- Current wave header list --\n"); \
+ while ( CurrDumpHdr ) \
+ { \
+ SND_TRACE(L"%x | %d bytes | flags: %x\n",
CurrDumpHdr->lpData, \
+ CurrDumpHdr->dwBufferLength, \
+ CurrDumpHdr->dwFlags); \
+ CurrDumpHdr = CurrDumpHdr->lpNext; \
+ } \
+ }
+
#else
- #define SND_ERR(...) while ( 0 ) do {}
- #define SND_WARN(...) while ( 0 ) do {}
- #define SND_TRACE(...) while ( 0 ) do {}
- #define SND_ASSERT(condition) while ( 0 ) do {}
+ #define SND_ERR(...) do {} while ( 0 )
+ #define SND_WARN(...) do {} while ( 0 )
+ #define SND_TRACE(...) do {} while ( 0 )
+ #define SND_ASSERT(condition) do {} while ( 0 )
#endif
/*
@@ -157,6 +170,28 @@
struct _SOUND_DEVICE;
struct _SOUND_DEVICE_INSTANCE;
+
+/*
+ By extending the OVERLAPPED structure, it becomes possible to provide the
+ I/O completion routines with additional information.
+*/
+
+typedef struct _SOUND_OVERLAPPED
+{
+ OVERLAPPED Standard;
+ struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
+ PWAVEHDR Header;
+} SOUND_OVERLAPPED, *PSOUND_OVERLAPPED;
+
+typedef MMRESULT (*WAVE_COMMIT_FUNC)(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+ IN PVOID OffsetPtr,
+ IN DWORD Bytes,
+ IN PSOUND_OVERLAPPED Overlap,
+ IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
+
+
+
typedef MMRESULT (*MMWAVEQUERYFORMATSUPPORT_FUNC)(
IN struct _SOUND_DEVICE* Device,
IN PWAVEFORMATEX WaveFormat,
@@ -178,6 +213,11 @@
typedef MMRESULT (*MMWAVEHEADER_FUNC)(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
IN PWAVEHDR WaveHeader);
+
+typedef MMRESULT (*MMBUFFER_FUNC)(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+ IN PVOID Buffer,
+ IN DWORD Length);
typedef struct _MMFUNCTION_TABLE
{
@@ -196,10 +236,18 @@
MMWAVEQUERYFORMATSUPPORT_FUNC QueryWaveFormatSupport;
MMWAVESETFORMAT_FUNC SetWaveFormat;
- MMWAVEHEADER_FUNC PrepareWaveHeader;
- MMWAVEHEADER_FUNC UnprepareWaveHeader;
- MMWAVEHEADER_FUNC SubmitWaveHeader;
+ WAVE_COMMIT_FUNC CommitWaveBuffer;
+
+ // Redundant
+ //MMWAVEHEADER_FUNC PrepareWaveHeader;
+ //MMWAVEHEADER_FUNC UnprepareWaveHeader;
+ //MMWAVEHEADER_FUNC WriteWaveHeader;
+
+ //MMWAVEHEADER_FUNC SubmitWaveHeaderToDevice;
+ //MMBUFFER_FUNC CompleteBuffer;
} MMFUNCTION_TABLE, *PMMFUNCTION_TABLE;
+
+
typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER)(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
@@ -252,7 +300,31 @@
DWORD ClientCallback;
DWORD ClientCallbackInstanceData;
} WinMM;
+
+ /* DO NOT TOUCH THESE OUTSIDE OF THE SOUND THREAD */
+
+ union
+ {
+ PWAVEHDR HeadWaveHeader;
+ };
+
+ union
+ {
+ PWAVEHDR TailWaveHeader;
+ };
+
+ PWAVEHDR WaveLoopStart;
+ PWAVEHDR CurrentWaveHeader;
+ DWORD OutstandingBuffers;
} SOUND_DEVICE_INSTANCE, *PSOUND_DEVICE_INSTANCE;
+
+/* This lives in WAVEHDR.reserved */
+typedef struct _WAVEHDR_EXTENSION
+{
+ DWORD BytesCommitted;
+ DWORD BytesCompleted;
+} WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION;
+
/*
reentrancy.c
@@ -308,8 +380,8 @@
#define MmeUnprepareWaveHeader(private_handle, header) \
UnprepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
-#define MmeEnqueueWaveHeader(private_handle, header) \
- EnqueueWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
+#define MmeWriteWaveHeader(private_handle, header) \
+ WriteWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)
/*
@@ -494,6 +566,16 @@
*/
MMRESULT
+EnqueueWaveHeader(
+ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PVOID Parameter);
+
+VOID
+CompleteWaveHeader(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PWAVEHDR Header);
+
+MMRESULT
PrepareWaveHeader(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN PWAVEHDR Header);
@@ -504,9 +586,38 @@
IN PWAVEHDR Header);
MMRESULT
-EnqueueWaveHeader(
+WriteWaveHeader(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN PWAVEHDR Header);
+
+
+/*
+ wave/streaming.c
+*/
+
+MMRESULT
+DoWaveStreaming(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance);
+
+VOID CALLBACK
+CompleteIO(
+ IN DWORD dwErrorCode,
+ IN DWORD dwNumberOfBytesTransferred,
+ IN LPOVERLAPPED lpOverlapped);
+
+MMRESULT
+CommitWaveHeaderToKernelDevice(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PWAVEHDR Header,
+ IN WAVE_COMMIT_FUNC CommitFunction);
+
+MMRESULT
+WriteFileEx_Committer(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PVOID OffsetPtr,
+ IN DWORD Length,
+ IN PSOUND_OVERLAPPED Overlap,
+ IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
/*
Modified: trunk/reactos/lib/drivers/sound/mmebuddy/deviceinstance.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmebuddy…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmebuddy/deviceinstance.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmebuddy/deviceinstance.c [iso-8859-1] Wed Feb 18
13:10:02 2009
@@ -186,6 +186,14 @@
(*SoundDeviceInstance)->WinMM.ClientCallbackInstanceData = 0;
(*SoundDeviceInstance)->WinMM.Flags = 0;
+ /* Initialise the members of the struct used by the sound thread */
+ (*SoundDeviceInstance)->HeadWaveHeader = NULL;
+ (*SoundDeviceInstance)->TailWaveHeader = NULL;
+
+ (*SoundDeviceInstance)->CurrentWaveHeader = NULL;
+ (*SoundDeviceInstance)->OutstandingBuffers = 0;
+ // TODO: Loop
+
/* Create the streaming thread (TODO - is this for wave only?) */
Result = CreateSoundThread(&(*SoundDeviceInstance)->Thread);
if ( ! MMSUCCESS(Result) )
Modified: trunk/reactos/lib/drivers/sound/mmebuddy/mmebuddy.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmebuddy…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmebuddy/mmebuddy.rbuild [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmebuddy/mmebuddy.rbuild [iso-8859-1] Wed Feb 18
13:10:02 2009
@@ -16,7 +16,8 @@
<file>widMessage.c</file>
<file>wodMessage.c</file>
<file>format.c</file>
- <file>header.c</file>
+ <file>header.c</file>
+ <file>streaming.c</file>
</directory>
<directory name="midi">
<file>midMessage.c</file>
Modified: trunk/reactos/lib/drivers/sound/mmebuddy/wave/header.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmebuddy…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmebuddy/wave/header.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmebuddy/wave/header.c [iso-8859-1] Wed Feb 18
13:10:02 2009
@@ -1,9 +1,9 @@
/*
* PROJECT: ReactOS Sound System "MME Buddy" Library
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: lib/drivers/sound/mmebuddy/header.c
+ * FILE: lib/drivers/sound/mmebuddy/wave/header.c
*
- * PURPOSE: Wave header preparation routines
+ * PURPOSE: Wave header preparation and submission routines
*
* PROGRAMMERS: Andrew Greenwood (silverblade(a)reactos.org)
*/
@@ -13,6 +13,7 @@
#include <mmddk.h>
#include <ntddsnd.h>
#include <mmebuddy.h>
+#include <sndtypes.h>
/*
@@ -60,6 +61,25 @@
/*
+ SanitizeWaveHeader
+ Clean up a header / reinitialize
+*/
+
+VOID
+SanitizeWaveHeader(
+ PWAVEHDR Header)
+{
+ PWAVEHDR_EXTENSION Extension = (PWAVEHDR_EXTENSION) Header->reserved;
+ SND_ASSERT( Extension );
+
+ Header->dwBytesRecorded = 0;
+
+ Extension->BytesCommitted = 0;
+ Extension->BytesCompleted = 0;
+}
+
+
+/*
The following routines are basically handlers for:
- WODM_PREPARE
- WODM_UNPREPARE
@@ -78,6 +98,7 @@
MMRESULT Result;
PSOUND_DEVICE SoundDevice;
PMMFUNCTION_TABLE FunctionTable;
+ PWAVEHDR_EXTENSION Extension;
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
VALIDATE_MMSYS_PARAMETER( Header );
@@ -92,12 +113,18 @@
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
- if ( ! FunctionTable->PrepareWaveHeader )
- return MMSYSERR_NOTSUPPORTED;
-
- return WaveHeaderOperation(FunctionTable->PrepareWaveHeader,
- SoundDeviceInstance,
- Header);
+ Extension = AllocateStruct(WAVEHDR_EXTENSION);
+ if ( ! Extension )
+ return MMSYSERR_NOMEM;
+
+ Header->reserved = (DWORD_PTR) Extension;
+ Extension->BytesCommitted = 0;
+ Extension->BytesCompleted = 0;
+
+ /* Configure the flags */
+ Header->dwFlags |= WHDR_PREPARED;
+
+ return MMSYSERR_NOERROR;
}
MMRESULT
@@ -108,6 +135,7 @@
MMRESULT Result;
PSOUND_DEVICE SoundDevice;
PMMFUNCTION_TABLE FunctionTable;
+ PWAVEHDR_EXTENSION Extension;
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
VALIDATE_MMSYS_PARAMETER( Header );
@@ -122,16 +150,18 @@
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
- if ( ! FunctionTable->UnprepareWaveHeader )
- return MMSYSERR_NOTSUPPORTED;
-
- return WaveHeaderOperation(FunctionTable->UnprepareWaveHeader,
- SoundDeviceInstance,
- Header);
-}
-
-MMRESULT
-EnqueueWaveHeader(
+ SND_ASSERT( Header->reserved );
+ Extension = (PWAVEHDR_EXTENSION) Header->reserved;
+ FreeMemory(Extension);
+
+ /* Configure the flags */
+ Header->dwFlags &= ~WHDR_PREPARED;
+
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+WriteWaveHeader(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
IN PWAVEHDR Header)
{
@@ -152,7 +182,7 @@
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
- if ( ! FunctionTable->SubmitWaveHeader )
+ if ( ! FunctionTable->CommitWaveBuffer )
return MMSYSERR_NOTSUPPORTED;
/*
@@ -164,20 +194,160 @@
VALIDATE_MMSYS_PARAMETER( Header->dwFlags & WHDR_PREPARED );
VALIDATE_MMSYS_PARAMETER( ! (Header->dwFlags & WHDR_INQUEUE) );
+ SanitizeWaveHeader(Header);
+
/* Clear the "done" flag for the buffer */
Header->dwFlags &= ~WHDR_DONE;
- Result = WaveHeaderOperation(FunctionTable->SubmitWaveHeader,
- SoundDeviceInstance,
- Header);
-
- if ( ! MMSUCCESS(Result) )
- {
- return Result;
- }
-
- /* Set the "in queue" flag if everything was OK */
- Header->dwFlags |= WHDR_INQUEUE;
+ Result = CallSoundThread(SoundDeviceInstance,
+ EnqueueWaveHeader,
+ Header);
+
+ return Result;
+}
+
+
+/*
+ EnqueueWaveHeader
+ Put the header in the record/playback queue. This is performed within
+ the context of the sound thread, it must NEVER be called from another
+ thread.
+
+ CompleteWaveHeader
+ Set the header information to indicate that it has finished playing,
+ and return it to the client application. This again must be called
+ within the context of the sound thread.
+*/
+
+MMRESULT
+EnqueueWaveHeader(
+ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PVOID Parameter)
+{
+ VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
+ VALIDATE_MMSYS_PARAMETER( Parameter );
+
+ PWAVEHDR WaveHeader = (PWAVEHDR) Parameter;
+
+ /* Initialise */
+ WaveHeader->lpNext = NULL;
+
+ /* Set the "in queue" flag */
+ WaveHeader->dwFlags |= WHDR_INQUEUE;
+
+ if ( ! SoundDeviceInstance->TailWaveHeader )
+ {
+ /* This is the first header in the queue */
+ SND_TRACE(L"Enqueued first wave header\n");
+ SoundDeviceInstance->HeadWaveHeader = WaveHeader;
+ SoundDeviceInstance->TailWaveHeader = WaveHeader;
+
+ DoWaveStreaming(SoundDeviceInstance);
+ }
+ else
+ {
+ /* There are already queued headers - make this one the tail */
+ SND_TRACE(L"Enqueued next wave header\n");
+ SoundDeviceInstance->TailWaveHeader->lpNext = WaveHeader;
+ SoundDeviceInstance->TailWaveHeader = WaveHeader;
+
+ DoWaveStreaming(SoundDeviceInstance);
+ }
+
+ DUMP_WAVEHDR_QUEUE(SoundDeviceInstance);
return MMSYSERR_NOERROR;
}
+
+VOID
+CompleteWaveHeader(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PWAVEHDR Header)
+{
+ PWAVEHDR PrevHdr = NULL, CurrHdr = NULL;
+ PWAVEHDR_EXTENSION Extension;
+ PSOUND_DEVICE SoundDevice;
+ MMDEVICE_TYPE DeviceType;
+ MMRESULT Result;
+
+ SND_TRACE(L"BUFFER COMPLETE :)\n");
+
+ // TODO: Set header flags?
+ // TODO: Call client
+ // TODO: Streaming
+
+ //DoWaveStreaming(SoundDeviceInstance);
+
+ Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+ SND_ASSERT( MMSUCCESS(Result) );
+ Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+ SND_ASSERT( MMSUCCESS(Result) );
+
+ Extension = (PWAVEHDR_EXTENSION)Header->reserved;
+ SND_ASSERT( Extension );
+
+ /* Remove the header from the queue, like so */
+ if ( SoundDeviceInstance->HeadWaveHeader == Header )
+ {
+ SoundDeviceInstance->HeadWaveHeader = Header->lpNext;
+
+ SND_TRACE(L"Dropping head node\n");
+
+ /* If nothing after the head, then there is no tail */
+ if ( Header->lpNext == NULL )
+ {
+ SND_TRACE(L"Dropping tail node\n");
+ SoundDeviceInstance->TailWaveHeader = NULL;
+ }
+ }
+ else
+ {
+ PrevHdr = NULL;
+ CurrHdr = SoundDeviceInstance->HeadWaveHeader;
+
+ SND_TRACE(L"Relinking nodes\n");
+
+ while ( CurrHdr != Header )
+ {
+ PrevHdr = CurrHdr;
+ CurrHdr = CurrHdr->lpNext;
+ SND_ASSERT( CurrHdr );
+ }
+
+ SND_ASSERT( PrevHdr );
+
+ PrevHdr->lpNext = CurrHdr->lpNext;
+
+ /* If this is the tail node, update the tail */
+ if ( Header->lpNext == NULL )
+ {
+ SND_TRACE(L"Updating tail node\n");
+ SoundDeviceInstance->TailWaveHeader = PrevHdr;
+ }
+ }
+
+ /* Make sure we're not using this as the current buffer any more, either! */
+ if ( SoundDeviceInstance->CurrentWaveHeader == Header )
+ {
+ SoundDeviceInstance->CurrentWaveHeader = Header->lpNext;
+ }
+
+ DUMP_WAVEHDR_QUEUE(SoundDeviceInstance);
+
+ SND_TRACE(L"Returning buffer to client...\n");
+
+ /* Update the header */
+ Header->dwFlags &= ~WHDR_INQUEUE;
+ Header->dwFlags |= WHDR_DONE;
+
+ if ( DeviceType == WAVE_IN_DEVICE_TYPE )
+ {
+ // FIXME: We won't be called on incomplete buffer!
+ Header->dwBytesRecorded = Extension->BytesCompleted;
+ }
+
+ /* Safe to do this without thread protection, as we're done with the header */
+ NotifyMmeClient(SoundDeviceInstance,
+ DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_DONE : WIM_DATA,
+ (DWORD) Header);
+}
Added: trunk/reactos/lib/drivers/sound/mmebuddy/wave/streaming.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmebuddy…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmebuddy/wave/streaming.c (added)
+++ trunk/reactos/lib/drivers/sound/mmebuddy/wave/streaming.c [iso-8859-1] Wed Feb 18
13:10:02 2009
@@ -1,0 +1,229 @@
+/*
+ * PROJECT: ReactOS Sound System "MME Buddy" Library
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: lib/drivers/sound/mmebuddy/wave/streaming.c
+ *
+ * PURPOSE: Wave streaming
+ *
+ * PROGRAMMERS: Andrew Greenwood (silverblade(a)reactos.org)
+*/
+
+#include <windows.h>
+#include <mmsystem.h>
+#include <mmddk.h>
+#include <ntddsnd.h>
+#include <mmebuddy.h>
+#include <sndtypes.h>
+
+
+/*
+ Restrain ourselves from flooding the kernel device!
+*/
+
+#define SOUND_KERNEL_BUFFER_COUNT 10
+#define SOUND_KERNEL_BUFFER_SIZE 200000
+
+
+/*
+ DoWaveStreaming
+ Check if there is streaming to be done, and if so, do it.
+*/
+
+MMRESULT
+DoWaveStreaming(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
+{
+ MMRESULT Result;
+ PSOUND_DEVICE SoundDevice;
+ PMMFUNCTION_TABLE FunctionTable;
+
+ Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+ SND_ASSERT( MMSUCCESS(Result) );
+
+ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
+ SND_ASSERT( MMSUCCESS(Result) );
+ SND_ASSERT( FunctionTable );
+ SND_ASSERT( FunctionTable->CommitWaveBuffer );
+
+ // HACK
+ SND_TRACE(L"Calling buffer submit routine\n");
+
+ if ( ! SoundDeviceInstance->CurrentWaveHeader )
+ {
+ /* Start from the beginning (always a good idea) */
+ SoundDeviceInstance->CurrentWaveHeader =
SoundDeviceInstance->HeadWaveHeader;
+ }
+
+ if ( SoundDeviceInstance->CurrentWaveHeader )
+ {
+ /* Stream or continue streaming this header */
+
+ Result = CommitWaveHeaderToKernelDevice(SoundDeviceInstance,
+
SoundDeviceInstance->CurrentWaveHeader,
+ FunctionTable->CommitWaveBuffer);
+ }
+ else
+ {
+ SND_TRACE(L"NOTHING TO DO - REC/PLAY STOPPED\n");
+ }
+
+ return Result;
+}
+
+
+/*
+ CompleteIO
+ An APC called as a result of a call to CommitWaveHeaderToKernelDevice.
+ This will count up the number of bytes which have been dealt with,
+ and when the entire wave header has been dealt with, will call
+ CompleteWaveHeader to have the wave header returned to the client.
+
+ CommitWaveHeaderToKernelDevice
+ Sends portions of the buffer described by the wave header to a kernel
+ device. This must only be called from within the context of the sound
+ thread. The caller supplies either their own commit routine, or uses
+ WriteFileEx_Committer. The committer is called with portions of the
+ buffer specified in the wave header.
+
+ WriteFileEx_Committer
+ Commit buffers using the WriteFileEx API.
+*/
+
+VOID CALLBACK
+CompleteIO(
+ IN DWORD dwErrorCode,
+ IN DWORD dwNumberOfBytesTransferred,
+ IN LPOVERLAPPED lpOverlapped)
+{
+ PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
+ PSOUND_OVERLAPPED SoundOverlapped = (PSOUND_OVERLAPPED) lpOverlapped;
+ PWAVEHDR WaveHdr;
+ PWAVEHDR_EXTENSION HdrExtension;
+
+ WaveHdr = (PWAVEHDR) SoundOverlapped->Header;
+ SND_ASSERT( WaveHdr );
+
+ HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
+ SND_ASSERT( HdrExtension );
+
+ SoundDeviceInstance = SoundOverlapped->SoundDeviceInstance;
+
+ HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
+ SND_TRACE(L"%d/%d bytes of wavehdr completed\n",
HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
+
+ /* We have an available buffer now */
+ -- SoundDeviceInstance->OutstandingBuffers;
+
+ if ( HdrExtension->BytesCompleted == WaveHdr->dwBufferLength )
+ {
+ CompleteWaveHeader(SoundDeviceInstance, WaveHdr);
+ }
+
+ DoWaveStreaming(SoundDeviceInstance);
+
+ //CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
+
+ FreeMemory(lpOverlapped);
+}
+
+MMRESULT
+CommitWaveHeaderToKernelDevice(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PWAVEHDR Header,
+ IN WAVE_COMMIT_FUNC CommitFunction)
+{
+ PSOUND_OVERLAPPED Overlap;
+ DWORD BytesToWrite, BytesRemaining;
+ PWAVEHDR_EXTENSION HdrExtension;
+ LPVOID Offset;
+
+ VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
+ VALIDATE_MMSYS_PARAMETER( Header );
+ VALIDATE_MMSYS_PARAMETER( CommitFunction );
+
+ HdrExtension = (PWAVEHDR_EXTENSION) Header->reserved;
+ VALIDATE_MMSYS_PARAMETER( HdrExtension );
+
+ /* Loop whilst there is data and sufficient available buffers */
+ while ( ( SoundDeviceInstance->OutstandingBuffers < SOUND_KERNEL_BUFFER_COUNT )
&&
+ ( HdrExtension->BytesCommitted < Header->dwBufferLength ) )
+ {
+ /* Is this the start of a loop? */
+ SoundDeviceInstance->WaveLoopStart = Header;
+
+ /* Where to start pulling the data from within the buffer */
+ Offset = Header->lpData + HdrExtension->BytesCommitted;
+
+ /* How much of this header is not committed? */
+ BytesRemaining = Header->dwBufferLength - HdrExtension->BytesCommitted;
+
+ /* We can write anything up to the buffer size limit */
+ BytesToWrite = BytesRemaining > SOUND_KERNEL_BUFFER_SIZE ?
+ SOUND_KERNEL_BUFFER_SIZE :
+ BytesRemaining;
+
+ /* If there's nothing left in the current header, move to the next */
+ if ( BytesToWrite == 0 )
+ {
+ Header = Header->lpNext;
+ HdrExtension = (PWAVEHDR_EXTENSION) Header->reserved;
+ SND_ASSERT( HdrExtension );
+ SND_ASSERT( HdrExtension->BytesCommitted == 0 );
+ SND_ASSERT( HdrExtension->BytesCompleted == 0 );
+ continue;
+ }
+
+ HdrExtension->BytesCommitted += BytesToWrite;
+
+ /* We're using up a buffer so update this */
+ ++ SoundDeviceInstance->OutstandingBuffers;
+
+ SND_TRACE(L"COMMIT: Offset 0x%x amount %d remain %d totalcommit %d",
+ Offset, BytesToWrite, BytesRemaining,
HdrExtension->BytesCommitted);
+
+ /* We need a new overlapped info structure for each buffer */
+ Overlap = AllocateStruct(SOUND_OVERLAPPED);
+
+ if ( Overlap )
+ {
+ ZeroMemory(Overlap, sizeof(SOUND_OVERLAPPED));
+ Overlap->SoundDeviceInstance = SoundDeviceInstance;
+ Overlap->Header = Header;
+
+
+ if ( ! MMSUCCESS(CommitFunction(SoundDeviceInstance, Offset, BytesToWrite,
Overlap, CompleteIO)) )
+ {
+ /* Just pretend it played if we fail... Show must go on, etc. etc. */
+ SND_WARN(L"FAILED\n");
+ HdrExtension->BytesCompleted += BytesToWrite;
+ }
+ }
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+WriteFileEx_Committer(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+ IN PVOID OffsetPtr,
+ IN DWORD Length,
+ IN PSOUND_OVERLAPPED Overlap,
+ IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
+{
+ HANDLE Handle;
+
+ VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
+ VALIDATE_MMSYS_PARAMETER( OffsetPtr );
+ VALIDATE_MMSYS_PARAMETER( Overlap );
+ VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
+
+ GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+
+ if ( ! WriteFileEx(Handle, OffsetPtr, Length, (LPOVERLAPPED)Overlap,
CompletionRoutine) )
+ {
+ // TODO
+ }
+
+ return MMSYSERR_NOERROR;
+}
Propchange: trunk/reactos/lib/drivers/sound/mmebuddy/wave/streaming.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/lib/drivers/sound/mmebuddy/wave/wodMessage.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmebuddy…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmebuddy/wave/wodMessage.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmebuddy/wave/wodMessage.c [iso-8859-1] Wed Feb 18
13:10:02 2009
@@ -94,7 +94,7 @@
case WODM_WRITE :
{
- Result = MmeEnqueueWaveHeader(PrivateHandle, Parameter1);
+ Result = MmeWriteWaveHeader(PrivateHandle, Parameter1);
break;
}
Modified: trunk/reactos/lib/drivers/sound/mment4/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mment4/c…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mment4/control.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mment4/control.c [iso-8859-1] Wed Feb 18 13:10:02
2009
@@ -8,6 +8,8 @@
* PROGRAMMERS: Andrew Greenwood (silverblade(a)reactos.org)
*/
+#define NDEBUG
+
#include <windows.h>
#include <mmsystem.h>
#include <mmddk.h>