[WDMAUD.DRV]

- Set the audio pin to KSSTATE_RUN if it is wave-out pin
- Implement support for manually starting / stopping a pin, which is used for recording
[WINMM]
- Add a hack for handling requests with WAVE_MAPPER
[PORTCLS]
- Pass correct flags to KsProbeStreamIrp when the irp has not already been probed (DirectKs)
[WDMAUD]
- Set correct irp dispatch code
[SYSAUDIO]
- Remove a hack
[MMEBUDDY]
- Return no error for MXDM_INIT message
- Add support for completing multiple wave headers at once
- Use new functions to implement WIDM_START / WIDM_STOP
- ReactOS now "supports" wave in recording. Tested with Audacity / sndrec32 @ XP, WIP


svn path=/trunk/; revision=43765
This commit is contained in:
Johannes Anderwald 2009-10-26 00:15:22 +00:00
parent fe966a972d
commit 85cbe2887b
11 changed files with 201 additions and 33 deletions

View file

@ -428,16 +428,18 @@ SetWdmWaveDeviceFormat(
Instance->BufferCount = 100; Instance->BufferCount = 100;
} }
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
/* Now start the stream */ {
DeviceInfo.u.State = KSSTATE_RUN; /* Now start the stream */
SyncOverlappedDeviceIoControl(KernelHandle, DeviceInfo.u.State = KSSTATE_RUN;
IOCTL_SETDEVICE_STATE, SyncOverlappedDeviceIoControl(KernelHandle,
(LPVOID) &DeviceInfo, IOCTL_SETDEVICE_STATE,
sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo,
(LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO),
sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo,
NULL); sizeof(WDMAUD_DEVICE_INFO),
NULL);
}
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
} }
@ -502,13 +504,56 @@ WriteFileEx_Committer2(
else if (DeviceType == WAVE_IN_DEVICE_TYPE) else if (DeviceType == WAVE_IN_DEVICE_TYPE)
{ {
Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine); Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
if (Ret) //if (Ret)
WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
} }
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
} }
MMRESULT
SetWdmWaveState(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
IN BOOL bStart)
{
MMRESULT Result;
PSOUND_DEVICE SoundDevice;
WDMAUD_DEVICE_INFO DeviceInfo;
MMDEVICE_TYPE DeviceType;
HANDLE Handle;
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
if ( ! MMSUCCESS(Result) )
{
return TranslateInternalMmResult(Result);
}
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
SND_ASSERT( Result == MMSYSERR_NOERROR );
Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
SND_ASSERT( Result == MMSYSERR_NOERROR );
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
DeviceInfo.hDevice = Handle;
DeviceInfo.DeviceType = DeviceType;
if (bStart)
DeviceInfo.u.State = KSSTATE_RUN;
else
DeviceInfo.u.State = KSSTATE_PAUSE;
Result = SyncOverlappedDeviceIoControl(KernelHandle,
IOCTL_SETDEVICE_STATE,
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
NULL);
return Result;
}
MMRESULT MMRESULT
GetWdmPosition( GetWdmPosition(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
@ -682,6 +727,11 @@ PopulateWdmDeviceList(
FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat; FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
} }
if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
{
FuncTable.SetState = SetWdmWaveState;
}
FuncTable.Open = OpenWdmSoundDevice; FuncTable.Open = OpenWdmSoundDevice;
FuncTable.Close = CloseWdmSoundDevice; FuncTable.Close = CloseWdmSoundDevice;
#ifndef USERMODE_MIXER #ifndef USERMODE_MIXER

View file

@ -2150,6 +2150,12 @@ UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps,
if (lpCaps == NULL) return MMSYSERR_INVALPARAM; if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
if (uDeviceID == WAVE_MAPPER)
{
FIXME("Support WAVE_MAPPER\n");
uDeviceID = 0;
}
if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEOUT, TRUE)) == NULL) if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEOUT, TRUE)) == NULL)
return MMSYSERR_BADDEVICEID; return MMSYSERR_BADDEVICEID;
@ -2543,6 +2549,13 @@ UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSi
if (lpCaps == NULL) return MMSYSERR_INVALPARAM; if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
if (uDeviceID == WAVE_MAPPER)
{
FIXME("Support WAVE_MAPPER\n");
uDeviceID = 0;
}
if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEIN, TRUE)) == NULL) if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEIN, TRUE)) == NULL)
return MMSYSERR_BADDEVICEID; return MMSYSERR_BADDEVICEID;

View file

@ -21,9 +21,9 @@
<file>mci.c</file> <file>mci.c</file>
<file>mmio.c</file> <file>mmio.c</file>
<file>playsound.c</file> <file>playsound.c</file>
<file>registry.c</file>
<file>time.c</file> <file>time.c</file>
<file>winmm.c</file> <file>winmm.c</file>
<file>registry.c</file>
<file>winmm_res.rc</file> <file>winmm_res.rc</file>
</module> </module>
</group> </group>

View file

@ -133,9 +133,11 @@ CIrpQueue::AddMapping(
// Wdmaud already probes buffers, therefore no need to probe it again // Wdmaud already probes buffers, therefore no need to probe it again
// probe the stream irp // probe the stream irp
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0); Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
else else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
Status = KsProbeStreamIrp(Irp, KSSTREAM_READ| KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0); Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
else
PC_ASSERT(0);
// check for success // check for success
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))

View file

@ -291,6 +291,7 @@ WdmAudReadWrite(
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
ULONG Length; ULONG Length;
PMDL Mdl; PMDL Mdl;
BOOLEAN Read = TRUE;
/* get current irp stack location */ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
@ -318,6 +319,7 @@ WdmAudReadWrite(
if (IoStack->MajorFunction == IRP_MJ_WRITE) if (IoStack->MajorFunction == IRP_MJ_WRITE)
{ {
/* probe the write stream irp */ /* probe the write stream irp */
Read = FALSE;
Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
} }
else else
@ -353,13 +355,22 @@ WdmAudReadWrite(
/* get next stack location */ /* get next stack location */
IoStack = IoGetNextIrpStackLocation(Irp); IoStack = IoGetNextIrpStackLocation(Irp);
if (Read)
{
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_READ_STREAM;
}
else
{
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_WRITE_STREAM;
}
/* attach file object */ /* attach file object */
IoStack->FileObject = FileObject; IoStack->FileObject = FileObject;
IoStack->Parameters.Write.Length = Length; IoStack->Parameters.Write.Length = Length;
IoStack->MajorFunction = IRP_MJ_WRITE; IoStack->MajorFunction = IRP_MJ_WRITE;
/* mark irp as pending */ /* mark irp as pending */
IoMarkIrpPending(Irp); // IoMarkIrpPending(Irp);
/* call the driver */ /* call the driver */
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);

View file

@ -73,13 +73,10 @@ Pin_fnWrite(
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
NTSTATUS Status; NTSTATUS Status;
ULONG Length;
/* Get current stack location */ /* Get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp);
Length = IoStack->Parameters.Write.Length;
/* The dispatch context is stored in the FsContext member */ /* The dispatch context is stored in the FsContext member */
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext;
@ -113,9 +110,7 @@ Pin_fnWrite(
/* store file object of next device object */ /* store file object of next device object */
IoStack->FileObject = FileObject; IoStack->FileObject = FileObject;
IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_WRITE_STREAM; //FIXME //ASSERT(Irp->AssociatedIrp.SystemBuffer);
IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
ASSERT(Irp->AssociatedIrp.SystemBuffer);
/* now call the driver */ /* now call the driver */
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);

View file

@ -236,6 +236,12 @@ typedef MMRESULT(*MMGETPOS_FUNC)(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
IN MMTIME* Time); IN MMTIME* Time);
typedef MMRESULT(*MMSETSTATE_FUNC)(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
IN BOOL bStart);
typedef struct _MMFUNCTION_TABLE typedef struct _MMFUNCTION_TABLE
{ {
union union
@ -258,6 +264,7 @@ typedef struct _MMFUNCTION_TABLE
WAVE_COMMIT_FUNC CommitWaveBuffer; WAVE_COMMIT_FUNC CommitWaveBuffer;
MMGETPOS_FUNC GetPos; MMGETPOS_FUNC GetPos;
MMSETSTATE_FUNC SetState;
// Redundant // Redundant
//MMWAVEHEADER_FUNC PrepareWaveHeader; //MMWAVEHEADER_FUNC PrepareWaveHeader;
@ -407,6 +414,11 @@ MmeGetPosition(
IN MMTIME* Time, IN MMTIME* Time,
IN DWORD Size); IN DWORD Size);
MMRESULT
MmeSetState(
IN DWORD PrivateHandle,
IN BOOL bStart);
#define MmePrepareWaveHeader(private_handle, header) \ #define MmePrepareWaveHeader(private_handle, header) \
PrepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header) PrepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header)

View file

@ -182,6 +182,7 @@ mxdMessage(
case MXDM_INIT : case MXDM_INIT :
{ {
Result = MMSYSERR_NOERROR;
break; break;
} }

View file

@ -15,6 +15,47 @@
#include <sndtypes.h> #include <sndtypes.h>
#include <mmebuddy.h> #include <mmebuddy.h>
/*
Sets the device into running or stopped state
*/
MMRESULT
MmeSetState(
IN DWORD PrivateHandle,
IN BOOL bStart)
{
MMRESULT Result;
PMMFUNCTION_TABLE FunctionTable;
PSOUND_DEVICE SoundDevice;
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
VALIDATE_MMSYS_PARAMETER( PrivateHandle );
SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
/* Get the function table, and validate it */
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
if ( ! MMSUCCESS(Result) )
return TranslateInternalMmResult(Result);
SND_ASSERT( FunctionTable->SetState );
if ( FunctionTable->SetState == NULL )
{
/* FIXME */
return MMSYSERR_NOTSUPPORTED;
}
/* Try change state */
Result = FunctionTable->SetState(SoundDeviceInstance, bStart);
return Result;
}
/* /*
Call the client application when something interesting happens (MME API Call the client application when something interesting happens (MME API
defines "interesting things" as device open, close, and buffer defines "interesting things" as device open, close, and buffer

View file

@ -170,6 +170,7 @@ CompleteIO(
PWAVEHDR WaveHdr; PWAVEHDR WaveHdr;
PWAVEHDR_EXTENSION HdrExtension; PWAVEHDR_EXTENSION HdrExtension;
MMRESULT Result; MMRESULT Result;
DWORD Bytes;
WaveHdr = (PWAVEHDR) SoundOverlapped->Header; WaveHdr = (PWAVEHDR) SoundOverlapped->Header;
SND_ASSERT( WaveHdr ); SND_ASSERT( WaveHdr );
@ -187,18 +188,48 @@ CompleteIO(
Result = GetSoundDeviceType(SoundDevice, &DeviceType); Result = GetSoundDeviceType(SoundDevice, &DeviceType);
SND_ASSERT( MMSUCCESS(Result) ); SND_ASSERT( MMSUCCESS(Result) );
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred; do
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength); {
/* We have an available buffer now */ /* We have an available buffer now */
-- SoundDeviceInstance->OutstandingBuffers; -- SoundDeviceInstance->OutstandingBuffers;
/* Did we finish a WAVEHDR and aren't looping? */ /* Did we finish a WAVEHDR and aren't looping? */
if ( HdrExtension->BytesCompleted == WaveHdr->dwBufferLength && if ( HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
SoundOverlapped->PerformCompletion ) SoundOverlapped->PerformCompletion )
{ {
CompleteWaveHeader(SoundDeviceInstance, WaveHdr); /* Wave buffer fully completed */
} Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted;
HdrExtension->BytesCompleted += Bytes;
dwNumberOfBytesTransferred -= Bytes;
CompleteWaveHeader(SoundDeviceInstance, WaveHdr);
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
}
else
{
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
/* Partially completed */
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
break;
}
/* Move to next wave header */
WaveHdr = WaveHdr->lpNext;
if (!WaveHdr)
{
/* No following WaveHdr */
SND_ASSERT(dwNumberOfBytesTransferred == 0);
break;
}
HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
SND_ASSERT( HdrExtension );
}while(dwNumberOfBytesTransferred);
DoWaveStreaming(SoundDeviceInstance); DoWaveStreaming(SoundDeviceInstance);

View file

@ -45,6 +45,18 @@ widMessage(
break; break;
} }
case WIDM_START :
{
Result = MmeSetState(PrivateHandle, TRUE);
break;
}
case WIDM_STOP :
{
Result = MmeSetState(PrivateHandle, FALSE);
break;
}
case WIDM_GETDEVCAPS : case WIDM_GETDEVCAPS :
{ {