winecoreaudio: Implement widOpen and widClose.

This commit is contained in:
Ken Thomases 2006-12-28 11:05:31 -06:00 committed by Alexandre Julliard
parent 30a1b29351
commit 5432adaaac
1 changed files with 124 additions and 8 deletions

View File

@ -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(AudioUnit 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, LPWAVEINCAPSW lpCaps, DWORD dwSize)
*/
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, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
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, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
*/
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;
}