Ken Thomases : winecoreaudio: Implement widOpen and widClose.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Dec 29 06:47:18 CST 2006


Module: wine
Branch: master
Commit: 5432adaaac04ca76891f396b3d0966918db08a89
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5432adaaac04ca76891f396b3d0966918db08a89

Author: Ken Thomases <ken at codeweavers.com>
Date:   Thu Dec 28 11:05:31 2006 -0600

winecoreaudio: Implement widOpen and widClose.

---

 dlls/winmm/winecoreaudio/audio.c |  132 +++++++++++++++++++++++++++++++++++--
 1 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/dlls/winmm/winecoreaudio/audio.c b/dlls/winmm/winecoreaudio/audio.c
index 0ab9109..51e71a8 100644
--- a/dlls/winmm/winecoreaudio/audio.c
+++ b/dlls/winmm/winecoreaudio/audio.c
@@ -160,6 +160,8 @@ typedef struct {
 typedef struct {
     /* Access to the following fields is synchronized across threads. */
     volatile int    state;
+    LPWAVEHDR       lpQueuePtr;
+    DWORD           dwTotalRecorded;
 
     /* Synchronization mechanism to protect above fields */
     OSSpinLock      lock;
@@ -170,15 +172,20 @@ typedef struct {
     /* Record the arguments used when opening the device. */
     WAVEOPENDESC    waveDesc;
     WORD            wFlags;
+    PCMWAVEFORMAT   format;
+
+    AudioUnit       audioUnit;
+
+    /* Record state of debug channels at open.  Used to control fprintf's since
+     * we can't use Wine debug channel calls in non-Wine AudioUnit threads. */
+    BOOL            trace_on;
+    BOOL            warn_on;
+    BOOL            err_on;
 
 /* These fields aren't used. */
 #if 0
     CoreAudio_Device *cadev;
-    PCMWAVEFORMAT   format;
-    LPWAVEHDR       lpQueuePtr;
-    DWORD           dwTotalRecorded;
 
-    AudioUnit                   audioUnit;
     AudioStreamBasicDescription streamDescription;
 #endif
 } WINE_WAVEIN;
@@ -202,6 +209,9 @@ extern OSStatus AudioUnitUninitialize(Au
 extern int AudioUnit_SetVolume(AudioUnit au, float left, float right);
 extern int AudioUnit_GetVolume(AudioUnit au, float *left, float *right);
 
+extern int AudioUnit_CreateInputUnit(void* wwi, AudioUnit* out_au,
+        WORD nChannels, DWORD nSamplesPerSec, WORD wBitsPerSample);
+
 OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon, 
                                      AudioUnitRenderActionFlags *ioActionFlags, 
                                      const AudioTimeStamp *inTimeStamp, 
@@ -1510,6 +1520,8 @@ static DWORD widGetDevCaps(WORD wDevID,
  */
 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
 {
+    WINE_WAVEIN* wwi;
+
     TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
     if (lpDesc == NULL)
     {
@@ -1522,8 +1534,72 @@ static DWORD widOpen(WORD wDevID, LPWAVE
         return MMSYSERR_BADDEVICEID;
     }
 
-    FIXME("unimplemented\n");
-    return MMSYSERR_NOTENABLED;
+    TRACE("Format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
+          lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
+          lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
+
+    if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
+        lpDesc->lpFormat->nChannels == 0 ||
+        lpDesc->lpFormat->nSamplesPerSec == 0
+        )
+    {
+        WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d wBitsPerSample=%d !\n",
+             lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
+             lpDesc->lpFormat->nSamplesPerSec, lpDesc->lpFormat->wBitsPerSample);
+        return WAVERR_BADFORMAT;
+    }
+
+    if (dwFlags & WAVE_FORMAT_QUERY)
+    {
+        TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
+              lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
+              lpDesc->lpFormat->nSamplesPerSec);
+        return MMSYSERR_NOERROR;
+    }
+
+    wwi = &WInDev[wDevID];
+    if (!OSSpinLockTry(&wwi->lock))
+        return MMSYSERR_ALLOCATED;
+
+    if (wwi->state != WINE_WS_CLOSED)
+    {
+        OSSpinLockUnlock(&wwi->lock);
+        return MMSYSERR_ALLOCATED;
+    }
+
+    wwi->state = WINE_WS_STOPPED;
+    wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
+
+    memcpy(&wwi->waveDesc, lpDesc,              sizeof(WAVEOPENDESC));
+    memcpy(&wwi->format,   lpDesc->lpFormat,    sizeof(PCMWAVEFORMAT));
+
+    if (wwi->format.wBitsPerSample == 0)
+    {
+        WARN("Resetting zeroed wBitsPerSample\n");
+        wwi->format.wBitsPerSample = 8 *
+            (wwi->format.wf.nAvgBytesPerSec /
+            wwi->format.wf.nSamplesPerSec) /
+            wwi->format.wf.nChannels;
+    }
+
+    wwi->dwTotalRecorded = 0;
+
+    wwi->trace_on = TRACE_ON(wave);
+    wwi->warn_on  = WARN_ON(wave);
+    wwi->err_on   = ERR_ON(wave);
+
+    if (!AudioUnit_CreateInputUnit(wwi, &wwi->audioUnit,
+        wwi->format.wf.nChannels, wwi->format.wf.nSamplesPerSec,
+        wwi->format.wBitsPerSample))
+    {
+        ERR("AudioUnit_CreateInputUnit failed\n");
+        OSSpinLockUnlock(&wwi->lock);
+        return MMSYSERR_ERROR;
+    }
+
+    OSSpinLockUnlock(&wwi->lock);
+
+    return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
 }
 
 
@@ -1532,6 +1608,9 @@ static DWORD widOpen(WORD wDevID, LPWAVE
  */
 static DWORD widClose(WORD wDevID)
 {
+    DWORD           ret = MMSYSERR_NOERROR;
+    WINE_WAVEIN*    wwi;
+
     TRACE("(%u);\n", wDevID);
 
     if (wDevID >= MAX_WAVEINDRV)
@@ -1540,8 +1619,45 @@ static DWORD widClose(WORD wDevID)
         return MMSYSERR_BADDEVICEID;
     }
 
-    FIXME("unimplemented\n");
-    return MMSYSERR_NOTENABLED;
+    wwi = &WInDev[wDevID];
+    OSSpinLockLock(&wwi->lock);
+    if (wwi->state == WINE_WS_CLOSED)
+    {
+        WARN("Device already closed.\n");
+        ret = MMSYSERR_INVALHANDLE;
+    }
+    else if (wwi->lpQueuePtr)
+    {
+        WARN("Buffers in queue.\n");
+        ret = WAVERR_STILLPLAYING;
+    }
+    else
+    {
+        wwi->state = WINE_WS_CLOSED;
+    }
+
+    OSSpinLockUnlock(&wwi->lock);
+
+    if (ret == MMSYSERR_NOERROR)
+    {
+        OSStatus err = AudioUnitUninitialize(wwi->audioUnit);
+        if (err)
+        {
+            ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
+                                                           (char) (err >> 16),
+                                                           (char) (err >> 8),
+                                                           (char) err);
+        }
+
+        if (!AudioUnit_CloseAudioUnit(wwi->audioUnit))
+        {
+            ERR("Can't close AudioUnit\n");
+        }
+
+        ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
+    }
+
+    return ret;
 }
 
 




More information about the wine-cvs mailing list