Module: wine
Branch: master
Commit: 959ec2aa446df10ec142095f1b6c984793d6533f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=959ec2aa446df10ec142095f1…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Thu Dec 28 11:07:08 2006 -0600
winecoreaudio: Implement widStart.
---
dlls/winmm/winecoreaudio/audio.c | 37 +++++++++++++++++++++++++++++++++++--
1 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/dlls/winmm/winecoreaudio/audio.c b/dlls/winmm/winecoreaudio/audio.c
index b8e060e..ee1a62f 100644
--- a/dlls/winmm/winecoreaudio/audio.c
+++ b/dlls/winmm/winecoreaudio/audio.c
@@ -1868,6 +1868,9 @@ static DWORD widAddBuffer(WORD wDevID, L
*/
static DWORD widStart(WORD wDevID)
{
+ DWORD ret = MMSYSERR_NOERROR;
+ WINE_WAVEIN* wwi;
+
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEINDRV)
{
@@ -1875,8 +1878,38 @@ static DWORD widStart(WORD wDevID)
return MMSYSERR_INVALHANDLE;
}
- FIXME("unimplemented\n");
- return MMSYSERR_NOTENABLED;
+ /* The order of the following operations is important since we can't hold
+ * the mutex while we make an Audio Unit call. Set the PLAYING state
+ * before starting the Audio Unit. In widStop, the order is reversed.
+ * This guarantees that we can't get into a situation where the state is
+ * PLAYING but the Audio Unit isn't running. Although we can be in STOPPED
+ * state with the Audio Unit still running, that's harmless because the
+ * input callback will just throw away the sound data.
+ */
+ wwi = &WInDev[wDevID];
+ OSSpinLockLock(&wwi->lock);
+
+ if (wwi->state == WINE_WS_CLOSED)
+ {
+ WARN("Trying to start closed device.\n");
+ ret = MMSYSERR_INVALHANDLE;
+ }
+ else
+ wwi->state = WINE_WS_PLAYING;
+
+ OSSpinLockUnlock(&wwi->lock);
+
+ if (ret == MMSYSERR_NOERROR)
+ {
+ /* Start pulling for audio data */
+ OSStatus err = AudioOutputUnitStart(wwi->audioUnit);
+ if (err != noErr)
+ ERR("Failed to start AU: %08lx\n", err);
+
+ TRACE("Recording started...\n");
+ }
+
+ return ret;
}
Module: wine
Branch: master
Commit: c47c82a20b2945cca2fd7085c5d5a2508c841218
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c47c82a20b2945cca2fd7085c…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Thu Dec 28 11:07:02 2006 -0600
winecoreaudio: Implement widStop.
---
dlls/winmm/winecoreaudio/audio.c | 52 ++++++++++++++++++++++++++++++++++++-
1 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/dlls/winmm/winecoreaudio/audio.c b/dlls/winmm/winecoreaudio/audio.c
index 63d18ce..b8e060e 100644
--- a/dlls/winmm/winecoreaudio/audio.c
+++ b/dlls/winmm/winecoreaudio/audio.c
@@ -1885,6 +1885,11 @@ static DWORD widStart(WORD wDevID)
*/
static DWORD widStop(WORD wDevID)
{
+ DWORD ret = MMSYSERR_NOERROR;
+ WINE_WAVEIN* wwi;
+ WAVEHDR* lpWaveHdr = NULL;
+ OSStatus err;
+
TRACE("(%u);\n", wDevID);
if (wDevID >= MAX_WAVEINDRV)
{
@@ -1892,8 +1897,51 @@ static DWORD widStop(WORD wDevID)
return MMSYSERR_INVALHANDLE;
}
- FIXME("unimplemented\n");
- return MMSYSERR_NOTENABLED;
+ wwi = &WInDev[wDevID];
+
+ /* The order of the following operations is important since we can't hold
+ * the mutex while we make an Audio Unit call. Stop the Audio Unit before
+ * setting the STOPPED state. In widStart, the order is reversed. This
+ * guarantees that we can't get into a situation where the state is
+ * PLAYING but the Audio Unit isn't running. Although we can be in STOPPED
+ * state with the Audio Unit still running, that's harmless because the
+ * input callback will just throw away the sound data.
+ */
+ err = AudioOutputUnitStop(wwi->audioUnit);
+ if (err != noErr)
+ WARN("Failed to stop AU: %08lx\n", err);
+
+ TRACE("Recording stopped.\n");
+
+ OSSpinLockLock(&wwi->lock);
+
+ if (wwi->state == WINE_WS_CLOSED)
+ {
+ WARN("Trying to stop closed device.\n");
+ ret = MMSYSERR_INVALHANDLE;
+ }
+ else if (wwi->state != WINE_WS_STOPPED)
+ {
+ wwi->state = WINE_WS_STOPPED;
+ /* If there's a buffer in progress, it's done. Remove it from the
+ * queue so that we can return it to the app, below. */
+ if (wwi->lpQueuePtr)
+ {
+ lpWaveHdr = wwi->lpQueuePtr;
+ wwi->lpQueuePtr = lpWaveHdr->lpNext;
+ }
+ }
+
+ OSSpinLockUnlock(&wwi->lock);
+
+ if (lpWaveHdr)
+ {
+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
+ lpWaveHdr->dwFlags |= WHDR_DONE;
+ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
+ }
+
+ return ret;
}