📄 wavepdd.cxx
字号:
static MMRESULT
PddMsg_Open(
WAPI_INOUT apidir,
LPWAVEFORMATEX lpFormat,
BOOL bQueryFormatOnly
)
{
BSS_FUNC_WPDD("+PddMsg_Open");
BOOL fBadFormat = TRUE;
if (apidir == WAPI_OUT) {
if ((lpFormat->wFormatTag == WAVE_FORMAT_PCM) &&
(lpFormat->nChannels == 2) &&
(lpFormat->nSamplesPerSec == 8000) &&
(lpFormat->wBitsPerSample == 16)) {
fBadFormat = FALSE;
}
}
else {
if ((lpFormat->wFormatTag == WAVE_FORMAT_PCM) &&
(lpFormat->nChannels == 1) &&
(lpFormat->nSamplesPerSec == 8000) &&
((lpFormat->wBitsPerSample == 8) || (lpFormat->wBitsPerSample == 16))) {
fBadFormat = FALSE;
}
}
if (fBadFormat) {
return WAVERR_BADFORMAT;
}
//
// Only checking if format is supported
//
if (bQueryFormatOnly) {
BSS_FUNC_WPDD("-PddMsg_Open");
return MMSYSERR_NOERROR;
}
// If driver is not ready, return error immediately
DWORD dwRet = WaitForSingleObject(g_hReadyEvent, 0);
if (WAIT_OBJECT_0 != dwRet) {
SetLastError(ERROR_NOT_READY);
return MMSYSERR_NOTENABLED;
}
LOCK_STREAM_INFO(apidir);
if (g_StreamInfo[apidir].bOpened) {
UNLOCK_STREAM_INFO(apidir);
BSS_FUNC_WPDD("-PddMsg_Open");
return MMSYSERR_ALLOCATED;
}
if (! g_fInitSco) {
// SCO has not been initialized.
UNLOCK_STREAM_INFO(apidir);
SetLastError(ERROR_NOT_READY);
return MMSYSERR_NOTENABLED;
}
g_StreamInfo[apidir].bOpened = TRUE;
g_StreamInfo[apidir].wfx = *lpFormat;
UNLOCK_STREAM_INFO(apidir);
return MMSYSERR_NOERROR;
}
// -----------------------------------------------------------------------------
// PddMsg_Close
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_Close(
WAPI_INOUT apidir
)
{
BSS_FUNC_WPDD("+PddMsg_Close");
LOCK_STREAM_INFO(apidir);
g_StreamInfo[apidir].bOpened = FALSE;
UNLOCK_STREAM_INFO(apidir);
BSS_FUNC_WPDD("-PddMsg_Close");
return MMSYSERR_NOERROR;
}
// -----------------------------------------------------------------------------
// PddMsg_OutGetVolume
// TODO: send a volume control command to the device.
// see docs for waveOutSetVolume on how to intepret ulVolume
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_OutGetVolume(
PULONG pulVolume
)
{
BSS_FUNC_WPDD("+PddMsg_OutGetVolume");
*pulVolume = g_dwVolume;
BSS_FUNC_WPDD("-PddMsg_OutGetVolume");
return MMSYSERR_NOERROR;
}
// -----------------------------------------------------------------------------
// PddMsg_OutSetVolume
// TODO: send a volume control command to the device.
// see docs for waveOutSetVolume on how to intepret ulVolume
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_OutSetVolume(
ULONG ulVolume
)
{
BSS_FUNC_WPDD("+PddMsg_OutSetVolume :: doesn't actually do any real work");
g_dwVolume = ulVolume;
BSS_FUNC_WPDD("-PddMsg_OutSetVolume");
return MMSYSERR_NOERROR;
}
// -----------------------------------------------------------------------------
// PDD_AudioPowerHandler
// -----------------------------------------------------------------------------
VOID
PDD_AudioPowerHandler(
BOOL power_down
)
{
//
// Handle any power up/down issues here.
//
}
DWORD WINAPI
ScoInitThread(
LPVOID pv
)
{
//
// init SCO layer
//
int ret = sco_InitializeOnce();
if (ret) {
BSS_ERRMSG1("sco_InitializeOnce FAILED %d", ret);
return ret;
}
//
// create SCO layer instance
//
ret = sco_CreateDriverInstance();
if (ret) {
BSS_ERRMSG1("sco_CreateDriverInstance FAILED %d", ret);
return ret;
}
//
// install callbacks and get interface functions
//
SCO_CALLBACKS callbacks = {0};
callbacks.DataPacketDown = PddSco_DataPacketDown;
callbacks.DataPacketUp = PddSco_DataPacketUp;
callbacks.PacketsCompleted = NULL;
callbacks.StackEvent = PddSco_StackEvent;
ret = sco_Bind(NULL, &callbacks, &g_ScoIntf);
if (ret) {
BSS_ERRMSG1("sco_Bind FAILED %d", ret);
return ret;
}
SetEvent(g_hReadyEvent);
return 0;
}
// -----------------------------------------------------------------------------
// PDD_AudioInitialize
// -----------------------------------------------------------------------------
BOOL
PDD_AudioInitialize(
DWORD dwIndex
)
{
BSS_FUNC_WPDD("+PDD_AudioInitialize");
LPTSTR pszRegKey = (LPTSTR) dwIndex;
memset(g_StreamInfo, 0, sizeof(g_StreamInfo));
memset(g_hAudioEvents, 0, sizeof(g_hAudioEvents));
g_hReadyEvent = 0;
g_dwVolume = 0;
g_dwRxBufferLen = 0;
g_dwRxBufferStart = 0;
g_dwTxPacketsToSend = 0;
g_dwScoPacketSize = 0;
g_usScoConnHandle = 0;
g_pTxBuffer = NULL;
g_fInitSco = FALSE;
InitializeCriticalSection(&(g_csStreamInfo[WAPI_IN]));
InitializeCriticalSection(&(g_csStreamInfo[WAPI_OUT]));
InitializeCriticalSection(&g_csRxBuffer);
InitializeCriticalSection(&g_csTxBuffer);
InitializeCriticalSection(&g_csPddWaveProcLock);
//
// create events
//
int i;
for (i = 0; i < NUM_AUDIO_EVENTS; i++)
{
g_hAudioEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!g_hAudioEvents[i]) {
BSS_ERRMSG("CreateEvent FAILED");
return FALSE;
}
}
g_hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (! g_hReadyEvent) {
BSS_ERRMSG("CreateEvent FAILED");
// Clean up what has already been initialized
for (i = 0; i < NUM_AUDIO_EVENTS; i++)
CloseHandle(g_hAudioEvents[i]);
return FALSE;
}
//
// Start SCO Initialization thread
//
HANDLE hThread = CreateThread(NULL, 0, ScoInitThread, NULL, 0, NULL);
if (NULL == hThread) {
BSS_ERRMSG("CreateThread FAILED");
// Clean up what has already been initialized
for (i = 0; i < NUM_AUDIO_EVENTS; i++)
CloseHandle(g_hAudioEvents[i]);
CloseHandle(g_hReadyEvent);
return FALSE;
}
CloseHandle(hThread);
BSS_FUNC_WPDD("-PDD_AudioInitialize (SUCCESS)");
return TRUE;
}
// -----------------------------------------------------------------------------
// PDD_AudioDeinitialize
// -----------------------------------------------------------------------------
VOID
PDD_AudioDeinitialize(
VOID
)
{
int i;
BSS_FUNC_WPDD("-PDD_AudioDeinitialize");
DeinitSco ();
sco_Unbind();
sco_CloseDriverInstance();
sco_UninitializeOnce();
memset(&g_ScoIntf, 0, sizeof(g_ScoIntf));
for (i = 0; i < NUM_AUDIO_EVENTS; i++)
{
if (g_hAudioEvents[i]) {
CloseHandle(g_hAudioEvents[i]);
g_hAudioEvents[i] = NULL;
}
}
CloseHandle(g_hReadyEvent);
g_hReadyEvent = NULL;
DeleteCriticalSection(&g_csPddWaveProcLock);
DeleteCriticalSection(&g_csTxBuffer);
DeleteCriticalSection(&g_csRxBuffer);
DeleteCriticalSection(&(g_csStreamInfo[WAPI_OUT]));
DeleteCriticalSection(&(g_csStreamInfo[WAPI_IN]));
BSS_FUNC_WPDD("-PDD_AudioDeinitialize");
}
// -----------------------------------------------------------------------------
// PDD_WaveProc
// -----------------------------------------------------------------------------
MMRESULT
PDD_WaveProc(
WAPI_INOUT apidir,
DWORD dwCode,
DWORD dwParam1,
DWORD dwParam2
)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
EnterCriticalSection(&g_csPddWaveProcLock);
switch (dwCode)
{
case WPDM_OPEN:
mmRet = PddMsg_Open(apidir, (LPWAVEFORMATEX) dwParam1, (BOOL) dwParam2);
break;
case WPDM_CLOSE:
mmRet = PddMsg_Close(apidir);
break;
case WPDM_RESTART: // WPDM_RESTART is more accurately thought of as "resume" (w.r.t. WPDM_PAUSE)
case WPDM_START:
mmRet = PddMsg_Start(apidir, (PWAVEHDR) dwParam1);
break;
case WPDM_PAUSE:
case WPDM_STOP:
mmRet = PddMsg_Stop(apidir);
break;
case WPDM_GETVOLUME:
mmRet = PddMsg_OutGetVolume((PULONG) dwParam1);
break;
case WPDM_SETVOLUME:
mmRet = PddMsg_OutSetVolume(dwParam1);
break;
case WPDM_GETDEVCAPS:
mmRet = PddMsg_GetDevCaps(apidir, (PVOID) dwParam1, (UINT) dwParam2);
break;
case WPDM_ENDOFDATA:
case WPDM_STANDBY:
case WPDM_CONTINUE:
default :
mmRet = MMSYSERR_NOTSUPPORTED;
break;
}
LeaveCriticalSection(&g_csPddWaveProcLock);
return mmRet;
}
// -----------------------------------------------------------------------------
// PDD_AudioMessage
// -----------------------------------------------------------------------------
DWORD
PDD_AudioMessage(
UINT uMsg,
DWORD dwParam1,
DWORD dwParam2
)
{
//
// Handle any custom WAVEIN or WAVEOUT messages
//
return MMSYSERR_NOTSUPPORTED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -