[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;
}
/* Now start the stream */
DeviceInfo.u.State = KSSTATE_RUN;
SyncOverlappedDeviceIoControl(KernelHandle,
IOCTL_SETDEVICE_STATE,
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
NULL);
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
{
/* Now start the stream */
DeviceInfo.u.State = KSSTATE_RUN;
SyncOverlappedDeviceIoControl(KernelHandle,
IOCTL_SETDEVICE_STATE,
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
(LPVOID) &DeviceInfo,
sizeof(WDMAUD_DEVICE_INFO),
NULL);
}
return MMSYSERR_NOERROR;
}
@ -502,13 +504,56 @@ WriteFileEx_Committer2(
else if (DeviceType == WAVE_IN_DEVICE_TYPE)
{
Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
if (Ret)
WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
//if (Ret)
// WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
}
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
GetWdmPosition(
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
@ -682,6 +727,11 @@ PopulateWdmDeviceList(
FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
}
if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
{
FuncTable.SetState = SetWdmWaveState;
}
FuncTable.Open = OpenWdmSoundDevice;
FuncTable.Close = CloseWdmSoundDevice;
#ifndef USERMODE_MIXER

View file

@ -2150,6 +2150,12 @@ UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps,
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)
return MMSYSERR_BADDEVICEID;
@ -2543,6 +2549,13 @@ UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSi
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)
return MMSYSERR_BADDEVICEID;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,6 +15,47 @@
#include <sndtypes.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
defines "interesting things" as device open, close, and buffer

View file

@ -170,6 +170,7 @@ CompleteIO(
PWAVEHDR WaveHdr;
PWAVEHDR_EXTENSION HdrExtension;
MMRESULT Result;
DWORD Bytes;
WaveHdr = (PWAVEHDR) SoundOverlapped->Header;
SND_ASSERT( WaveHdr );
@ -187,18 +188,48 @@ CompleteIO(
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
SND_ASSERT( MMSUCCESS(Result) );
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
do
{
/* We have an available buffer now */
-- SoundDeviceInstance->OutstandingBuffers;
/* We have an available buffer now */
-- SoundDeviceInstance->OutstandingBuffers;
/* Did we finish a WAVEHDR and aren't looping? */
if ( HdrExtension->BytesCompleted == WaveHdr->dwBufferLength &&
SoundOverlapped->PerformCompletion )
{
CompleteWaveHeader(SoundDeviceInstance, WaveHdr);
}
/* Did we finish a WAVEHDR and aren't looping? */
if ( HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
SoundOverlapped->PerformCompletion )
{
/* 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);

View file

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