mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
[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:
parent
fe966a972d
commit
85cbe2887b
11 changed files with 201 additions and 33 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -182,6 +182,7 @@ mxdMessage(
|
|||
|
||||
case MXDM_INIT :
|
||||
{
|
||||
Result = MMSYSERR_NOERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 :
|
||||
{
|
||||
|
||||
|
|
Loading…
Reference in a new issue