[WDMAUD.DRV]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 26 Oct 2009 00:15:22 +0000 (00:15 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 26 Oct 2009 00:15:22 +0000 (00:15 +0000)
- 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

reactos/dll/win32/wdmaud.drv/wdmaud.c
reactos/dll/win32/winmm/winmm.c
reactos/dll/win32/winmm/winmm.rbuild
reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp
reactos/drivers/wdm/audio/legacy/wdmaud/control.c
reactos/drivers/wdm/audio/sysaudio/pin.c
reactos/include/reactos/libs/sound/mmebuddy.h
reactos/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c
reactos/lib/drivers/sound/mmebuddy/mmewrap.c
reactos/lib/drivers/sound/mmebuddy/wave/streaming.c
reactos/lib/drivers/sound/mmebuddy/wave/widMessage.c

index 7050ca7..27c38a5 100644 (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
index 07e22e6..2a1c705 100644 (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;
 
index 1231b37..52688da 100644 (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>
index 5b4c8b1..f3b1d7b 100644 (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))
index 241b3f4..73b4b70 100644 (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);
 
index ef1a4df..234f43c 100644 (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);
index f8b2d8d..b815800 100644 (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)
index 7e25ac9..88190cb 100644 (file)
@@ -182,6 +182,7 @@ mxdMessage(
 
         case MXDM_INIT :
         {
+            Result = MMSYSERR_NOERROR;
             break;
         }
 
index a5a4a6d..f63e55a 100644 (file)
 #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
index e611a0b..f910bf9 100644 (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);
 
index 366ab3c..de9e353 100644 (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 :
         {