Module: wine Branch: master Commit: ef87a050c6966d43fe1b457e80faa8b0bb31755d URL: http://source.winehq.org/git/wine.git/?a=commit;h=ef87a050c6966d43fe1b457e80...
Author: Ken Thomases ken@codeweavers.com Date: Sun Oct 11 14:13:23 2009 -0500
winecoreaudio: Allow opening multiple wave-out instances.
---
dlls/winecoreaudio.drv/audio.c | 66 +++++++++++++++++++-------------------- 1 files changed, 32 insertions(+), 34 deletions(-)
diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c index a966dfd..639c100 100644 --- a/dlls/winecoreaudio.drv/audio.c +++ b/dlls/winecoreaudio.drv/audio.c @@ -50,6 +50,7 @@ #include "wine/unicode.h" #include "wine/library.h" #include "wine/debug.h" +#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(wave);
@@ -99,7 +100,7 @@ AudioUnitRender( AudioUnit ci, * | (any) | pause() | PAUSING | PAUSED | * | PAUSED | restart() | RESTARTING | PLAYING | * | (any) | reset() | RESETTING | PLAYING | -* | (any) | close() | CLOSING | CLOSED | +* | (any) | close() | CLOSING | <deallocated> | * +---------+-------------+---------------+---------------------------------+ */
@@ -107,7 +108,7 @@ AudioUnitRender( AudioUnit ci, #define WINE_WS_PLAYING 0 /* for waveOut: lpPlayPtr == NULL -> stopped */ #define WINE_WS_PAUSED 1 #define WINE_WS_STOPPED 2 /* Not used for waveOut */ -#define WINE_WS_CLOSED 3 +#define WINE_WS_CLOSED 3 /* Not used for waveOut */ #define WINE_WS_OPENING 4 #define WINE_WS_CLOSING 5
@@ -143,6 +144,8 @@ typedef struct tagCoreAudio_Device { static CoreAudio_Device CoreAudio_DefaultDevice;
typedef struct { + struct list entry; + volatile int state; /* one of the WINE_WS_ manifest constants */ WAVEOPENDESC waveDesc; WORD wFlags; @@ -172,7 +175,8 @@ typedef struct { BOOL warn_on; BOOL err_on;
- WINE_WAVEOUT_INSTANCE instance; + struct list instances; + OSSpinLock lock; /* guards the instances list */ } WINE_WAVEOUT;
typedef struct { @@ -578,9 +582,8 @@ LONG CoreAudio_WaveInit(void) static const WCHAR wszWaveOutFormat[] = {'C','o','r','e','A','u','d','i','o',' ','W','a','v','e','O','u','t',' ','%','d',0};
- WOutDev[i].instance.state = WINE_WS_CLOSED; + list_init(&WOutDev[i].instances); WOutDev[i].cadev = &CoreAudio_DefaultDevice; - WOutDev[i].instance.woID = i;
memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps));
@@ -617,7 +620,7 @@ LONG CoreAudio_WaveInit(void) WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16;
- WOutDev[i].instance.lock = 0; /* initialize the mutex */ + WOutDev[i].lock = 0; /* initialize the mutex */ }
/* FIXME: implement sample rate conversion on input */ @@ -856,31 +859,23 @@ static DWORD wodOpen(WORD wDevID, WINE_WAVEOUT_INSTANCE** pInstance, LPWAVEOPEND }
/* We proceed in three phases: - * o Reserve the device for us, marking it as unavailable (not closed) + * o Allocate the device instance, marking it as opening * o Create, configure, and start the Audio Unit. To avoid deadlock, * this has to be done without holding wwo->lock. - * o If that was successful, finish setting up our device info and - * mark the device as ready. - * Otherwise, clean up and mark the device as available. + * o If that was successful, finish setting up our instance and add it + * to the device's list. + * Otherwise, clean up and deallocate the instance. */ - wwo = &WOutDev[wDevID].instance; - if (!OSSpinLockTry(&wwo->lock)) - return MMSYSERR_ALLOCATED; - - if (wwo->state != WINE_WS_CLOSED) - { - OSSpinLockUnlock(&wwo->lock); - return MMSYSERR_ALLOCATED; - } + wwo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wwo)); + if (!wwo) + return MMSYSERR_NOMEM;
+ wwo->woID = wDevID; wwo->state = WINE_WS_OPENING; - wwo->audioUnit = NULL; - OSSpinLockUnlock(&wwo->lock); -
if (!AudioUnit_CreateDefaultAudioUnit((void *) wwo, &audioUnit)) { - ERR("CoreAudio_CreateDefaultAudioUnit(%p) failed\n", wwo); + ERR("CoreAudio_CreateDefaultAudioUnit(0x%04x) failed\n", wDevID); ret = MMSYSERR_ERROR; goto error; } @@ -914,7 +909,8 @@ static DWORD wodOpen(WORD wDevID, WINE_WAVEOUT_INSTANCE** pInstance, LPWAVEOPEND * lock before calling it and the callback grabs wwo->lock. This would * deadlock if we were holding wwo->lock. * Also, the callback has to safely do nothing in that case, because - * wwo hasn't been completely filled out, yet. */ + * wwo hasn't been completely filled out, yet. This is assured by state + * being WINE_WS_OPENING. */ ret = AudioOutputUnitStart(audioUnit); if (ret) { @@ -936,8 +932,6 @@ static DWORD wodOpen(WORD wDevID, WINE_WAVEOUT_INSTANCE** pInstance, LPWAVEOPEND
wwo->waveDesc = *lpDesc; copyFormat(lpDesc->lpFormat, &wwo->format); - - wwo->dwPlayedTotal = 0;
WOutDev[wDevID].trace_on = TRACE_ON(wave); WOutDev[wDevID].warn_on = WARN_ON(wave); @@ -945,6 +939,10 @@ static DWORD wodOpen(WORD wDevID, WINE_WAVEOUT_INSTANCE** pInstance, LPWAVEOPEND
OSSpinLockUnlock(&wwo->lock);
+ OSSpinLockLock(&WOutDev[wDevID].lock); + list_add_head(&WOutDev[wDevID].instances, &wwo->entry); + OSSpinLockUnlock(&WOutDev[wDevID].lock); + *pInstance = wwo; TRACE("opened instance %p\n", wwo);
@@ -962,8 +960,8 @@ error:
OSSpinLockLock(&wwo->lock); assert(wwo->state == WINE_WS_OPENING); - wwo->state = WINE_WS_CLOSED; - OSSpinLockUnlock(&wwo->lock); + /* OSSpinLockUnlock(&wwo->lock); *//* No need, about to free */ + HeapFree(GetProcessHeap(), 0, wwo);
return ret; } @@ -1014,12 +1012,13 @@ static DWORD wodClose(WORD wDevID, WINE_WAVEOUT_INSTANCE* wwo) return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ }
- OSSpinLockLock(&wwo->lock); - assert(wwo->state == WINE_WS_CLOSING); - wwo->state = WINE_WS_CLOSED; /* mark the device as closed */ - OSSpinLockUnlock(&wwo->lock); + OSSpinLockLock(&WOutDev[wDevID].lock); + list_remove(&wwo->entry); + OSSpinLockUnlock(&WOutDev[wDevID].lock);
ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L); + + HeapFree(GetProcessHeap(), 0, wwo); }
return ret; @@ -1353,8 +1352,7 @@ static DWORD wodReset(WORD wDevID, WINE_WAVEOUT_INSTANCE* wwo)
OSSpinLockLock(&wwo->lock);
- if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_CLOSING || - wwo->state == WINE_WS_OPENING) + if (wwo->state == WINE_WS_CLOSING || wwo->state == WINE_WS_OPENING) { OSSpinLockUnlock(&wwo->lock); WARN("resetting a closed device\n");