mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-06-11 01:04:20 +00:00
os2 audio refactoring and capture support
- Fixed audio device detection and usage. - Implemented audio capture support - Refactored buffer handling to separate pointers to fill and drain buffers. Based on patches by josch1710 and Lars Erdmann: https://github.com/bitwiseworks/SDL2-os2/pull/7
This commit is contained in:
parent
ba0c270c7a
commit
890bee64a4
|
@ -30,17 +30,12 @@
|
||||||
#include "../SDL_audio_c.h"
|
#include "../SDL_audio_c.h"
|
||||||
#include "SDL_os2audio.h"
|
#include "SDL_os2audio.h"
|
||||||
|
|
||||||
/*
|
static PMCI_MIX_BUFFER _getNextBuffer(SDL_PrivateAudioData *pAData, PMCI_MIX_BUFFER pBuffer)
|
||||||
void lockIncr(volatile int *piVal);
|
{
|
||||||
#pragma aux lockIncr = \
|
PMCI_MIX_BUFFER pFirstBuffer = &pAData->aMixBuffers[0];
|
||||||
"lock add [eax], 1 "\
|
PMCI_MIX_BUFFER pLastBuffer = &pAData->aMixBuffers[pAData->cMixBuffers -1];
|
||||||
parm [eax];
|
return (pBuffer == pLastBuffer ? pFirstBuffer : pBuffer+1);
|
||||||
|
}
|
||||||
void lockDecr(volatile int *piVal);
|
|
||||||
#pragma aux lockDecr = \
|
|
||||||
"lock sub [eax], 1 "\
|
|
||||||
parm [eax];
|
|
||||||
*/
|
|
||||||
|
|
||||||
static ULONG _getEnvULong(const char *name, ULONG ulMax, ULONG ulDefault)
|
static ULONG _getEnvULong(const char *name, ULONG ulMax, ULONG ulDefault)
|
||||||
{
|
{
|
||||||
|
@ -64,7 +59,7 @@ static int _MCIError(const char *func, ULONG ulResult)
|
||||||
|
|
||||||
static void _mixIOError(const char *function, ULONG ulRC)
|
static void _mixIOError(const char *function, ULONG ulRC)
|
||||||
{
|
{
|
||||||
debug_os2("%s() - failed, rc = 0x%X (%s)",
|
debug_os2("%s() - failed, rc = 0x%lX (%s)",
|
||||||
function, ulRC,
|
function, ulRC,
|
||||||
(ulRC == MCIERR_INVALID_MODE) ? "Mixer mode does not match request" :
|
(ulRC == MCIERR_INVALID_MODE) ? "Mixer mode does not match request" :
|
||||||
(ulRC == MCIERR_INVALID_BUFFER) ? "Caller sent an invalid buffer" : "unknown");
|
(ulRC == MCIERR_INVALID_BUFFER) ? "Caller sent an invalid buffer" : "unknown");
|
||||||
|
@ -73,18 +68,33 @@ static void _mixIOError(const char *function, ULONG ulRC)
|
||||||
static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
||||||
ULONG ulFlags)
|
ULONG ulFlags)
|
||||||
{
|
{
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
|
SDL_AudioDevice *_this = (SDL_AudioDevice *)pBuffer->ulUserParm;
|
||||||
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
|
|
||||||
if (ulFlags != MIX_WRITE_COMPLETE) {
|
debug_os2("cbAudioWriteEvent: ulStatus = %lu, pBuffer = %p, ulFlags = %#lX",ulStatus,pBuffer,ulFlags);
|
||||||
debug_os2("flags = 0x%X", ulFlags);
|
|
||||||
|
if (pAData->ulState == 2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ulFlags != MIX_WRITE_COMPLETE) {
|
||||||
|
debug_os2("flags = 0x%lX", ulFlags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAData->pDrainBuffer = pBuffer;
|
||||||
|
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
|
||||||
|
pAData->pDrainBuffer, 1);
|
||||||
|
if (ulRC != MCIERR_SUCCESS) {
|
||||||
|
_mixIOError("pmixWrite", ulRC);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*lockDecr((int *)&pAData->ulQueuedBuf);*/
|
|
||||||
ulRC = DosPostEventSem(pAData->hevBuf);
|
ulRC = DosPostEventSem(pAData->hevBuf);
|
||||||
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
|
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
|
||||||
debug_os2("DosPostEventSem(), rc = %u", ulRC);
|
debug_os2("DosPostEventSem(), rc = %lu", ulRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* return value doesn't seem to matter. */
|
return 1; /* return value doesn't seem to matter. */
|
||||||
|
@ -93,19 +103,36 @@ static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
||||||
static LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
static LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
||||||
ULONG ulFlags)
|
ULONG ulFlags)
|
||||||
{
|
{
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
|
SDL_AudioDevice *_this = (SDL_AudioDevice *)pBuffer->ulUserParm;
|
||||||
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
|
|
||||||
if (ulFlags != MIX_READ_COMPLETE) {
|
debug_os2("cbAudioReadEvent: ulStatus = %lu, pBuffer = %p, ulFlags = %#lX",ulStatus,pBuffer,ulFlags);
|
||||||
debug_os2("flags = 0x%X", ulFlags);
|
|
||||||
|
if (pAData->ulState == 2)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle, pBuffer, 1);
|
if (ulFlags != MIX_READ_COMPLETE) {
|
||||||
|
debug_os2("flags = 0x%lX", ulFlags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAData->pFillBuffer = pBuffer;
|
||||||
|
if (pAData->pFillBuffer == pAData->aMixBuffers)
|
||||||
|
{
|
||||||
|
ulRC = pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle,
|
||||||
|
pAData->pFillBuffer, pAData->cMixBuffers);
|
||||||
|
if (ulRC != MCIERR_SUCCESS) {
|
||||||
|
_mixIOError("pmixRead", ulRC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ulRC = DosPostEventSem(pAData->hevBuf);
|
ulRC = DosPostEventSem(pAData->hevBuf);
|
||||||
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
|
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
|
||||||
debug_os2("DosPostEventSem(), rc = %u", ulRC);
|
debug_os2("DosPostEventSem(), rc = %lu", ulRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -120,31 +147,36 @@ static void OS2_DetectDevices(void)
|
||||||
MCI_SYSINFO_LOGDEVICE stLogDevice;
|
MCI_SYSINFO_LOGDEVICE stLogDevice;
|
||||||
MCI_SYSINFO_PARMS stSysInfoParams;
|
MCI_SYSINFO_PARMS stSysInfoParams;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
ULONG ulHandle = 0;
|
ULONG ulNumber;
|
||||||
|
MCI_GETDEVCAPS_PARMS stDevCapsParams;
|
||||||
|
MCI_OPEN_PARMS stMCIOpen;
|
||||||
|
MCI_GENERIC_PARMS stMCIGenericParams;
|
||||||
|
|
||||||
|
SDL_memset(&stMCISysInfo, 0, sizeof(stMCISysInfo));
|
||||||
acBuf[0] = '\0';
|
acBuf[0] = '\0';
|
||||||
stMCISysInfo.pszReturn = acBuf;
|
stMCISysInfo.pszReturn = acBuf;
|
||||||
stMCISysInfo.ulRetSize = sizeof(acBuf);
|
stMCISysInfo.ulRetSize = sizeof(acBuf);
|
||||||
stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||||
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
|
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
|
||||||
&stMCISysInfo, 0);
|
&stMCISysInfo, 0);
|
||||||
if (ulRC != NO_ERROR) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%X", ulRC);
|
debug_os2("MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%hX", LOUSHORT(ulRC));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulDevicesNum = SDL_strtoul(stMCISysInfo.pszReturn, NULL, 10);
|
ulDevicesNum = SDL_strtoul(stMCISysInfo.pszReturn, NULL, 10);
|
||||||
|
|
||||||
for (stSysInfoParams.ulNumber = 0; stSysInfoParams.ulNumber < ulDevicesNum;
|
for (ulNumber = 1; ulNumber <= ulDevicesNum;
|
||||||
stSysInfoParams.ulNumber++) {
|
ulNumber++) {
|
||||||
/* Get device install name. */
|
/* Get device install name. */
|
||||||
|
stSysInfoParams.ulNumber = ulNumber;
|
||||||
stSysInfoParams.pszReturn = acBuf;
|
stSysInfoParams.pszReturn = acBuf;
|
||||||
stSysInfoParams.ulRetSize = sizeof(acBuf);
|
stSysInfoParams.ulRetSize = sizeof(acBuf);
|
||||||
stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||||
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
|
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
|
||||||
&stSysInfoParams, 0);
|
&stSysInfoParams, 0);
|
||||||
if (ulRC != NO_ERROR) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%X", ulRC);
|
debug_os2("MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%hX", LOUSHORT(ulRC));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,15 +186,45 @@ static void OS2_DetectDevices(void)
|
||||||
SDL_strlcpy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME);
|
SDL_strlcpy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME);
|
||||||
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
|
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
|
||||||
&stSysInfoParams, 0);
|
&stSysInfoParams, 0);
|
||||||
if (ulRC != NO_ERROR) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%X", ulRC);
|
debug_os2("MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%hX", LOUSHORT(ulRC));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulHandle++;
|
SDL_AddAudioDevice(0, stLogDevice.szProductInfo, NULL, (void *)ulNumber);
|
||||||
SDL_AddAudioDevice(0, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
|
|
||||||
ulHandle++;
|
/* Open audio device for querying its capabilities */
|
||||||
SDL_AddAudioDevice(1, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
|
/* at this point we HAVE TO OPEN the waveaudio device and not the ampmix device */
|
||||||
|
/* because only the waveaudio device (tied to the ampmix device) supports querying for playback/record capability */
|
||||||
|
SDL_memset(&stMCIOpen, 0, sizeof(stMCIOpen));
|
||||||
|
stMCIOpen.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_WAVEFORM_AUDIO,LOUSHORT(ulNumber));
|
||||||
|
ulRC = mciSendCommand(0, MCI_OPEN,MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,&stMCIOpen, 0);
|
||||||
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
|
debug_os2("MCI_OPEN (getDevCaps) - failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for recording capability */
|
||||||
|
SDL_memset(&stDevCapsParams, 0, sizeof(stDevCapsParams));
|
||||||
|
stDevCapsParams.ulItem = MCI_GETDEVCAPS_CAN_RECORD;
|
||||||
|
ulRC = mciSendCommand(stMCIOpen.usDeviceID, MCI_GETDEVCAPS, MCI_WAIT | MCI_GETDEVCAPS_ITEM,
|
||||||
|
&stDevCapsParams, 0);
|
||||||
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
|
debug_os2("MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM - failed, rc = 0x%hX", LOUSHORT(ulRC));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (stDevCapsParams.ulReturn) {
|
||||||
|
SDL_AddAudioDevice(1, stLogDevice.szProductInfo, NULL, (void *)(ulNumber | 0x80000000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the audio device, we are done querying its capabilities */
|
||||||
|
SDL_memset(&stMCIGenericParams, 0, sizeof(stMCIGenericParams));
|
||||||
|
ulRC = mciSendCommand(stMCIOpen.usDeviceID, MCI_CLOSE, MCI_WAIT,
|
||||||
|
&stMCIGenericParams, 0);
|
||||||
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
|
debug_os2("MCI_CLOSE (getDevCaps) - failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,52 +233,145 @@ static void OS2_WaitDevice(_THIS)
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
|
|
||||||
|
debug_os2("Enter");
|
||||||
|
|
||||||
/* Wait for an audio chunk to finish */
|
/* Wait for an audio chunk to finish */
|
||||||
ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
|
ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
|
||||||
if (ulRC != NO_ERROR) {
|
if (ulRC != NO_ERROR) {
|
||||||
debug_os2("DosWaitEventSem(), rc = %u", ulRC);
|
debug_os2("DosWaitEventSem(), rc = %lu", ulRC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint8 *OS2_GetDeviceBuf(_THIS)
|
static Uint8 *OS2_GetDeviceBuf(_THIS)
|
||||||
{
|
{
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
return (Uint8 *) pAData->aMixBuffers[pAData->ulNextBuf].pBuffer;
|
|
||||||
|
debug_os2("Enter");
|
||||||
|
|
||||||
|
return (Uint8 *) pAData->pFillBuffer->pBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OS2_PlayDevice(_THIS)
|
static void OS2_PlayDevice(_THIS)
|
||||||
{
|
{
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
PMCI_MIX_BUFFER pMixBuffer = &pAData->aMixBuffers[pAData->ulNextBuf];
|
PMCI_MIX_BUFFER pMixBuffer = NULL;
|
||||||
|
|
||||||
/* Queue it up */
|
debug_os2("Enter");
|
||||||
/*lockIncr((int *)&pAData->ulQueuedBuf);*/
|
|
||||||
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
|
pMixBuffer = pAData->pDrainBuffer;
|
||||||
pMixBuffer, 1);
|
pAData->pFillBuffer = _getNextBuffer(pAData, pAData->pFillBuffer);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (!pAData->ulState && pAData->pFillBuffer != pMixBuffer)
|
||||||
_mixIOError("pmixWrite", ulRC);
|
{
|
||||||
} else {
|
/*
|
||||||
pAData->ulNextBuf = (pAData->ulNextBuf + 1) % pAData->cMixBuffers;
|
* this buffer was filled but we have not yet filled all buffers
|
||||||
|
* so just signal event sem so that OS2_WaitDevice does not need
|
||||||
|
* to block
|
||||||
|
*/
|
||||||
|
ulRC = DosPostEventSem(pAData->hevBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pAData->ulState && (pAData->pFillBuffer == pMixBuffer) )
|
||||||
|
{
|
||||||
|
debug_os2("!hasStarted");
|
||||||
|
pAData->ulState = 1;
|
||||||
|
|
||||||
|
/* Write buffers to kick off the amp mixer */
|
||||||
|
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
|
||||||
|
pMixBuffer, pAData->cMixBuffers);
|
||||||
|
|
||||||
|
if (ulRC != MCIERR_SUCCESS) {
|
||||||
|
_mixIOError("pmixWrite", ulRC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int OS2_CaptureFromDevice(_THIS,void *buffer,int buflen)
|
||||||
|
{
|
||||||
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
|
ULONG ulRC;
|
||||||
|
PMCI_MIX_BUFFER pMixBuffer = NULL;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (!pAData->ulState)
|
||||||
|
{
|
||||||
|
pAData->ulState = 1;
|
||||||
|
ulRC = pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle,
|
||||||
|
pAData->aMixBuffers, pAData->cMixBuffers);
|
||||||
|
if (ulRC != MCIERR_SUCCESS) {
|
||||||
|
_mixIOError("pmixRead", ulRC);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for an audio chunk to finish */
|
||||||
|
ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
|
||||||
|
if (ulRC != NO_ERROR)
|
||||||
|
{
|
||||||
|
debug_os2("DosWaitEventSem(), rc = %lu", ulRC);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pMixBuffer = pAData->pDrainBuffer;
|
||||||
|
len = SDL_min((int)pMixBuffer->ulBufferLength, buflen);
|
||||||
|
SDL_memcpy(buffer,pMixBuffer->pBuffer, len);
|
||||||
|
pAData->pDrainBuffer = _getNextBuffer(pAData, pMixBuffer);
|
||||||
|
|
||||||
|
debug_os2("buflen = %u, ulBufferLength = %lu",buflen,pMixBuffer->ulBufferLength);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OS2_FlushCapture(_THIS)
|
||||||
|
{
|
||||||
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
|
ULONG ulIdx;
|
||||||
|
|
||||||
|
debug_os2("Enter");
|
||||||
|
|
||||||
|
/* Fill all device buffers with data */
|
||||||
|
for (ulIdx = 0; ulIdx < pAData->cMixBuffers; ulIdx++) {
|
||||||
|
pAData->aMixBuffers[ulIdx].ulFlags = 0;
|
||||||
|
pAData->aMixBuffers[ulIdx].ulBufferLength = _this->spec.size;
|
||||||
|
pAData->aMixBuffers[ulIdx].ulUserParm = (ULONG)_this;
|
||||||
|
|
||||||
|
SDL_memset(((PMCI_MIX_BUFFER)pAData->aMixBuffers)[ulIdx].pBuffer,
|
||||||
|
_this->spec.silence, _this->spec.size);
|
||||||
|
}
|
||||||
|
pAData->pFillBuffer = pAData->aMixBuffers;
|
||||||
|
pAData->pDrainBuffer = pAData->aMixBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void OS2_CloseDevice(_THIS)
|
static void OS2_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
|
||||||
MCI_GENERIC_PARMS sMCIGenericParms;
|
MCI_GENERIC_PARMS sMCIGenericParms;
|
||||||
ULONG ulRC;
|
ULONG ulRC;
|
||||||
|
|
||||||
|
debug_os2("Enter");
|
||||||
|
|
||||||
if (pAData == NULL)
|
if (pAData == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pAData->ulState = 2;
|
||||||
|
|
||||||
/* Close up audio */
|
/* Close up audio */
|
||||||
if (pAData->usDeviceId != (USHORT)~0) { /* Device is open. */
|
if (pAData->usDeviceId != (USHORT)~0) { /* Device is open. */
|
||||||
|
SDL_zero(sMCIGenericParms);
|
||||||
|
|
||||||
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_STOP,
|
||||||
|
MCI_WAIT,
|
||||||
|
&sMCIGenericParms, 0);
|
||||||
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
|
debug_os2("MCI_STOP - failed" );
|
||||||
|
}
|
||||||
|
|
||||||
if (pAData->stMCIMixSetup.ulBitsPerSample != 0) { /* Mixer was initialized. */
|
if (pAData->stMCIMixSetup.ulBitsPerSample != 0) { /* Mixer was initialized. */
|
||||||
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
|
||||||
MCI_WAIT | MCI_MIXSETUP_DEINIT,
|
MCI_WAIT | MCI_MIXSETUP_DEINIT,
|
||||||
&pAData->stMCIMixSetup, 0);
|
&pAData->stMCIMixSetup, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed");
|
debug_os2("MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,14 +385,14 @@ static void OS2_CloseDevice(_THIS)
|
||||||
|
|
||||||
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
|
||||||
MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0);
|
MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed");
|
debug_os2("MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ulRC = mciSendCommand(pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
|
||||||
&sMCIGenericParms, 0);
|
&sMCIGenericParms, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
debug_os2("MCI_CLOSE - failed");
|
debug_os2("MCI_CLOSE - failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,6 +413,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
|
||||||
ULONG ulIdx;
|
ULONG ulIdx;
|
||||||
BOOL new_freq;
|
BOOL new_freq;
|
||||||
SDL_bool iscapture = _this->iscapture;
|
SDL_bool iscapture = _this->iscapture;
|
||||||
|
ULONG ulHandle = (ULONG)_this->handle;
|
||||||
|
|
||||||
new_freq = FALSE;
|
new_freq = FALSE;
|
||||||
SDL_zero(stMCIAmpOpen);
|
SDL_zero(stMCIAmpOpen);
|
||||||
|
@ -279,20 +435,21 @@ static int OS2_OpenDevice(_THIS, const char *devname)
|
||||||
|
|
||||||
ulRC = DosCreateEventSem(NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE);
|
ulRC = DosCreateEventSem(NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE);
|
||||||
if (ulRC != NO_ERROR) {
|
if (ulRC != NO_ERROR) {
|
||||||
debug_os2("DosCreateEventSem() failed, rc = %u", ulRC);
|
debug_os2("DosCreateEventSem() failed, rc = %lu", ulRC);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open audio device */
|
/* Open audio device */
|
||||||
stMCIAmpOpen.usDeviceID = (_this->handle != NULL) ? ((ULONG)_this->handle - 1) : 0;
|
stMCIAmpOpen.usDeviceID = 0;
|
||||||
stMCIAmpOpen.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
|
stMCIAmpOpen.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX,LOUSHORT(ulHandle));
|
||||||
ulRC = mciSendCommand(0, MCI_OPEN,
|
ulRC = mciSendCommand(0, MCI_OPEN,
|
||||||
(_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
|
(_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
|
||||||
MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE :
|
MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE :
|
||||||
MCI_WAIT | MCI_OPEN_TYPE_ID,
|
MCI_WAIT | MCI_OPEN_TYPE_ID,
|
||||||
&stMCIAmpOpen, 0);
|
&stMCIAmpOpen, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
stMCIAmpOpen.usDeviceID = (USHORT)~0;
|
DosCloseEventSem(pAData->hevBuf);
|
||||||
|
pAData->usDeviceId = (USHORT)~0;
|
||||||
return _MCIError("MCI_OPEN", ulRC);
|
return _MCIError("MCI_OPEN", ulRC);
|
||||||
}
|
}
|
||||||
pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
|
pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
|
||||||
|
@ -355,7 +512,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
|
||||||
|
|
||||||
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
|
||||||
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
|
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS && _this->spec.freq > 44100) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS && _this->spec.freq > 44100) {
|
||||||
new_freq = TRUE;
|
new_freq = TRUE;
|
||||||
pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
|
pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
|
||||||
_this->spec.freq = 44100;
|
_this->spec.freq = 44100;
|
||||||
|
@ -363,7 +520,7 @@ static int OS2_OpenDevice(_THIS, const char *devname)
|
||||||
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
|
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_os2("Setup mixer [BPS: %u, Freq.: %u, Channels: %u]: %s",
|
debug_os2("Setup mixer [BPS: %lu, Freq.: %lu, Channels: %lu]: %s",
|
||||||
pAData->stMCIMixSetup.ulBitsPerSample,
|
pAData->stMCIMixSetup.ulBitsPerSample,
|
||||||
pAData->stMCIMixSetup.ulSamplesPerSec,
|
pAData->stMCIMixSetup.ulSamplesPerSec,
|
||||||
pAData->stMCIMixSetup.ulChannels,
|
pAData->stMCIMixSetup.ulChannels,
|
||||||
|
@ -394,29 +551,25 @@ static int OS2_OpenDevice(_THIS, const char *devname)
|
||||||
|
|
||||||
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
|
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
|
||||||
MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0);
|
MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0);
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
if (LOUSHORT(ulRC) != MCIERR_SUCCESS) {
|
||||||
return _MCIError("MCI_BUFFER", ulRC);
|
return _MCIError("MCI_BUFFER", ulRC);
|
||||||
}
|
}
|
||||||
pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
|
pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
|
||||||
_this->spec.size = stMCIBuffer.ulBufferSize;
|
_this->spec.size = stMCIBuffer.ulBufferSize;
|
||||||
|
|
||||||
|
debug_os2("%s, number of mix buffers: %lu",iscapture ? "capture": "play",pAData->cMixBuffers);
|
||||||
|
|
||||||
/* Fill all device buffers with data */
|
/* Fill all device buffers with data */
|
||||||
for (ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++) {
|
for (ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++) {
|
||||||
pAData->aMixBuffers[ulIdx].ulFlags = 0;
|
pAData->aMixBuffers[ulIdx].ulFlags = 0;
|
||||||
pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
|
pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
|
||||||
pAData->aMixBuffers[ulIdx].ulUserParm = (ULONG)pAData;
|
pAData->aMixBuffers[ulIdx].ulUserParm = (ULONG)_this;
|
||||||
|
|
||||||
SDL_memset(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
|
SDL_memset(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
|
||||||
_this->spec.silence, stMCIBuffer.ulBufferSize);
|
_this->spec.silence, stMCIBuffer.ulBufferSize);
|
||||||
}
|
}
|
||||||
|
pAData->pFillBuffer = pAData->aMixBuffers;
|
||||||
/* Write buffers to kick off the amp mixer */
|
pAData->pDrainBuffer = pAData->aMixBuffers;
|
||||||
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
|
|
||||||
pAData->aMixBuffers, 1);
|
|
||||||
if (ulRC != MCIERR_SUCCESS) {
|
|
||||||
_mixIOError("pmixWrite", ulRC);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -431,12 +584,10 @@ static SDL_bool OS2_Init(SDL_AudioDriverImpl * impl)
|
||||||
impl->WaitDevice = OS2_WaitDevice;
|
impl->WaitDevice = OS2_WaitDevice;
|
||||||
impl->GetDeviceBuf = OS2_GetDeviceBuf;
|
impl->GetDeviceBuf = OS2_GetDeviceBuf;
|
||||||
impl->CloseDevice = OS2_CloseDevice;
|
impl->CloseDevice = OS2_CloseDevice;
|
||||||
|
impl->CaptureFromDevice = OS2_CaptureFromDevice ;
|
||||||
/* TODO: IMPLEMENT CAPTURE SUPPORT:
|
impl->FlushCapture = OS2_FlushCapture;
|
||||||
impl->CaptureFromDevice = ;
|
|
||||||
impl->FlushCapture = ;
|
|
||||||
impl->HasCaptureSupport = SDL_TRUE;
|
impl->HasCaptureSupport = SDL_TRUE;
|
||||||
*/
|
|
||||||
return SDL_TRUE; /* this audio target is available. */
|
return SDL_TRUE; /* this audio target is available. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,11 @@ typedef struct SDL_PrivateAudioData
|
||||||
BYTE _pad[2];
|
BYTE _pad[2];
|
||||||
MCI_MIXSETUP_PARMS stMCIMixSetup;
|
MCI_MIXSETUP_PARMS stMCIMixSetup;
|
||||||
HEV hevBuf;
|
HEV hevBuf;
|
||||||
ULONG ulNextBuf;
|
PMCI_MIX_BUFFER pFillBuffer;
|
||||||
|
PMCI_MIX_BUFFER pDrainBuffer;
|
||||||
|
ULONG ulState;
|
||||||
ULONG cMixBuffers;
|
ULONG cMixBuffers;
|
||||||
MCI_MIX_BUFFER aMixBuffers[NUM_BUFFERS];
|
MCI_MIX_BUFFER aMixBuffers[NUM_BUFFERS];
|
||||||
/* ULONG ulQueuedBuf;*/
|
|
||||||
} SDL_PrivateAudioData;
|
} SDL_PrivateAudioData;
|
||||||
|
|
||||||
#endif /* SDL_os2mm_h_ */
|
#endif /* SDL_os2mm_h_ */
|
||||||
|
|
Loading…
Reference in a new issue