📄 tapicall.cpp
字号:
// tapicall.cpp : implementation file for CTapiCall
// (c) Dialogic corp 1995, 1996
#include "stdafx.h"
#include <tapi.h>
#include "tapiapp.h"
#include "tapiline.h"
#include <mmsystem.h>
#include "wavstate.h"
#include "wavex.h"
//#include "wavexg.h"
#include "tapicall.h"
#include "devspec.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
char g_szDigits[128];
//static DWORD dwStateTrans[] = {MAKELONG(IDLE, MAKING), MAKELONG(MAKING, CONNECTED),
// MAKELONG(MAKING, DROPPING), MAKELONG(CONNECTED, HOLD), MAKELONG(HOLD, CONNECTED),
// MAKELONG(CONNECTED, DISCONNECTED), MAKELONG(HOLD, IDLE), MAKELONG(HOLD, DISCONNECTED),
// MAKELONG(CONNECTED, DROPPING), MAKELONG(HOLD, DROPPING)}
/////////////////////////////////////////////////////////////////////////////
// CTapiCall
IMPLEMENT_DYNCREATE(CTapiCall, CObject)
CTapiCall::CTapiCall()
{
m_pctLine = NULL;
m_hCall = NULL;
m_CallState.wCallState = IDLE;
m_CallState.wCallDirection = IDLE;
m_CallState.dwTapiCallState = 0L;
m_CallState.dwErrors = 0L;
m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE");
m_MonitorState.wState = IDLE;
m_MonitorState.dwGatherResult = 0;
m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR");
m_pWave = NULL;
m_hStatusWnd = NULL;
m_hCallAlertWnd = NULL;
m_dwCallAlert = NULL;
}
CTapiCall::CTapiCall(HCALL hCall, CTapiLine *lpLine)
{
m_pctLine = lpLine;
m_hCall = hCall;
m_CallState.wCallState = IDLE;
m_CallState.wCallDirection = IDLE;
m_CallState.dwTapiCallState = 0L;
m_CallState.dwErrors = 0L;
m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE");
m_MonitorState.dwGatherResult = 0;
m_MonitorState.wState = IDLE;
m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR");
m_pWave = NULL;
m_hStatusWnd = NULL;
m_hCallAlertWnd = NULL;
m_dwCallAlert = NULL;
}
CTapiCall::~CTapiCall()
{
ResetWave();
WaitForSingleObject(m_hMonitorStateSem, 2000);
CloseHandle(m_hMonitorStateSem);
}
// verify & update the state
BOOL CTapiCall::UpdateCallState(WORD wCallState, WORD wDirection,
DWORD dwTapiCallState, DWORD dwErrors)
{
// put some protection & verification here
TRACE("*** TALKER32 ***: UpdateCallState hCall=%lx state=%d TAPIstate=%lx entering wait for sem\n",
m_hCall, wCallState, dwTapiCallState);
DWORD dwrc = WaitForSingleObject(m_hStateSem, 15000);
if(dwrc != WAIT_OBJECT_0)
{
TRACE("*** TALKER32 ***: Update Call state wait for sem failed rc=%lx\n",dwrc);
return FALSE;
}
if(wCallState != 0xffff) m_CallState.wCallState = wCallState;
if(wDirection != 0xffff) m_CallState.wCallDirection = wDirection;
if(dwTapiCallState != 0xffff) m_CallState.dwTapiCallState = dwTapiCallState;
m_CallState.dwErrors |= dwErrors;
TRACE("*** TALKER32 ***: UpdateCallState releasing mutex\n");
ReleaseMutex(m_hStateSem);
return TRUE;
}
// Start or end monitoring
LONG CTapiCall::MonitorDigits(DWORD dwMode)
{
LONG lrc = lineMonitorDigits(m_hCall, dwMode);
if(lrc) return lrc;
UpdateMonitorState(dwMode ? MONITOR_DIGITS:RESET_MONITOR_DIGITS, 0, 0); // start
return lrc;
}
LONG CTapiCall::GatherDigits(DWORD dwNumDigits, LPCSTR lpszTermDigits,
DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout, LPSTR lpBuf)
{
LONG lrc;
if(lpBuf == NULL)
{
lpBuf = m_szDigits; // default to internal buffer
if(dwNumDigits >= sizeof(m_szDigits)) // safety is first!!!
{
AfxMessageBox("Number of digits requested is more than default buffer size, resetting to 31");
dwNumDigits = sizeof(m_szDigits) - 1;
}
}
if(!dwNumDigits) // cancel current
{
TRACE("***: Cancelling Gather!!! \n");
return lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, NULL, 1, "", 100, 100);
}
//UpdateMonitorState(START_GATHER, 0, 0); // start
TRACE("***: Calling Gather num=%d, Term=%s, buf=%lx\n",dwNumDigits, lpszTermDigits, lpBuf);
//memset(lpBuf, 0, dwNumDigits); // init buffer
lrc = lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, lpBuf,
dwNumDigits, lpszTermDigits,dwFirstDigitTimeout, dwInterDigitTimeout);
if(lrc) return lrc;
UpdateMonitorState(START_GATHER, 0, 0); // start
return lrc;
}
// read the monitor state
BOOL CTapiCall::GetMonitorState(PMONITORSTATE pMonState)
{
if(pMonState == NULL) return FALSE; //user-supplied
TRACE("*** TALKER32 ***: GetMonitorState hCall=%lx entering wait for sem\n", m_hCall);
DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000);
if(dwrc != WAIT_OBJECT_0)
{
TRACE("*** TALKER32 ***: Get Monitor state wait for sem failed rc=%lx\n",dwrc);
return FALSE;
}
memcpy((LPBYTE)pMonState, (LPBYTE)&m_MonitorState, sizeof(MONITORSTATE)); //copy the whole thing
TRACE("*** TALKER32 ***: GetMonitorState releasing mutex,state=%lx\n",m_MonitorState.wState);
ReleaseMutex(m_hMonitorStateSem);
return TRUE;
}
// verify & update the state
BOOL CTapiCall::UpdateMonitorState(WORD wType, DWORD dwDigit, DWORD dwMode)
{
// protection & verification here
TRACE("*** TALKER32 ***: UpdateMonitorState hCall=%lx old=%x new=%x entering wait for sem\n", m_hCall, m_MonitorState.wState,wType);
DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000);
if(dwrc != WAIT_OBJECT_0)
{
TRACE("*** TALKER32 ***: Update Monitor state wait for sem failed rc=%lx\n",dwrc);
return FALSE;
}
// Reset gather result if state is not gathering
if(!(m_MonitorState.wState & START_GATHER))
m_MonitorState.dwGatherResult = 0L;
if(wType & MONITOR_DIGITS) // a digit arrived; called from outside
{
m_MonitorState.wState |= MONITOR_DIGITS; // confirm status
m_MonitorState.wLastDigit = LOWORD(dwDigit); // record digit
m_MonitorState.dwDigitMode = dwMode; // record mode
if(LOWORD(dwDigit)) m_MonitorState.wMonitorCount++; // unclaimed digits counter
else m_MonitorState.wMonitorCount = 0;
}
else if(wType & RESET_MONITOR_DIGITS) // reset flag; called from inside
{
m_MonitorState.wState &= ~MONITOR_DIGITS; // reset
m_MonitorState.dwDigitMode = 0L;
m_MonitorState.wMonitorCount = 0;
}
if(wType & START_GATHER) // start, set flag reset result & buffer; from inside
{
m_MonitorState.wState |= START_GATHER;
m_MonitorState.dwGatherResult = 0L;
}
else if(wType & END_GATHER_DIGITS) // end gather, reset flag & post result; from outside
{
m_MonitorState.wState &= ~START_GATHER;
m_MonitorState.dwGatherResult = dwDigit;
}
else if(wType & RESET_GATHER_RESULT) // end gather, reset flag & post result; from outside
{
m_MonitorState.wState &= ~START_GATHER;
m_MonitorState.dwGatherResult = 0L;
}
TRACE("*** TALKER32 ***: UpdateMonitorState releasing mutex\n");
ReleaseMutex(m_hMonitorStateSem);
return TRUE;
}
// initialize WAVE functionality for the call
BOOL CTapiCall::InitWave()
{
if(m_pWave != NULL) return TRUE; // already done
m_pWave = new CTapiWave((LPVOID) m_pctLine, (LPVOID)this, m_pctLine->ctlGetLineID());
if(m_pWave == NULL) return FALSE;
return TRUE;
}
// check WAVE state before deallocating
BOOL CTapiCall::ResetWave()
{
if(m_pWave == NULL) return TRUE;
if(IDLE != m_pWave->ctwGetState()) return FALSE; //can't do it yet
delete m_pWave;
return TRUE;
}
BOOL CTapiCall::Play(LPSTR lpName)
{
if(m_pWave) return m_pWave->ctwPlay(AfxGetMainWnd()->GetSafeHwnd(),
m_pctLine->ctlGetWaveOutID(), lpName);
//::WavexPlay(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), lpName);
return FALSE;
}
// Pause playing
BOOL CTapiCall::Pause()
{
if(m_pWave) return m_pWave->ctwPause();
return FALSE;
}
// Resume paused playing
BOOL CTapiCall::Resume()
{
if(m_pWave) return m_pWave->ctwResume();
return FALSE;
}
// Stop whatever is going on
BOOL CTapiCall::StopWave()
{
if(m_pWave) return m_pWave->ctwStop();
DWORD dwStat = m_pctLine->ctlGetDevSpecStatus();
if(dwStat != DEVSPEC_STARTING && dwStat != DEVSPEC_PROGRESS) return FALSE;
DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc();
if(dwFunc != PLAY_WAVE && dwFunc != RECORD_WAVE) return FALSE;
if(dwFunc == PLAY_WAVE)
PlayEx(NULL);
else if(dwFunc == RECORD_WAVE)
RecordEx(NULL, 0);
return TRUE;
}
BOOL CTapiCall::Record(int nFormatID, DWORD dwSize)
{
BOOL brc;
if(m_pWave)
{
brc = m_pWave->ctwRecord(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), nFormatID, dwSize);
TRACE("*** TALKER32 ***: Record returned %d, hWaveIn=%lx\n", brc, m_pWave->ctwGetHWave(WAVEIN));
return brc;
}
//::WavexRecord(AfxGetMainWnd()->GetSafeHwnd(), (UINT)m_pctLine->ctlGetWaveOutID());
return FALSE;
}
DWORD CTapiCall::GetHWaveIn()
{return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEIN);}
DWORD CTapiCall::GetHWaveOut()
{return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEOUT);}
// Override this for MT implementation
void CTapiCall::FinishPlay(WPARAM wParam, LPARAM lParam)
{if(m_pWave != NULL) m_pWave->ctwFinishPlay(wParam, lParam);}
//{::WavexFinishPlay(wParam, lParam);}
// Override this for MT implementation
void CTapiCall::FinishRecord(WPARAM wParam, LPARAM lParam, LPSTR lpName)
{
char szName[16];
sprintf(szName, "record%.2d.wav", m_pctLine->ctlGetLineID());
if(m_pWave != NULL) m_pWave->ctwFinishRecord(wParam, lParam, NULL);
//::WavexFinishRecord(wParam, lParam, NULL);
}
DWORD CTapiCall::GetWaveStatus()
{return m_pWave==NULL ? WAVE_DISFUNCTIONAL : m_pWave->ctwGetState();}
void CTapiCall::SetWaveVolume(DWORD dwVol)
{if(m_pWave != NULL) m_pWave->ctwSetVolume(dwVol);}
DWORD CTapiCall::GetWaveVolume()
{if(m_pWave != NULL) return m_pWave->ctwGetVolume(); return MAX_ABS_VOLUME;}
// Play WAVE using LineDevSpec
BOOL CTapiCall::PlayEx(LPCTSTR lpName)
{
DWORD dwSize; //= sizeof(DXXXDEVSPEC) + 2;
if(lpName) dwSize = lstrlen(lpName)+16;
else dwSize = 512;
if(dwSize > 512) return FALSE;
char szTemp[512];
PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp;
if(!pDS) return FALSE;
pDS->dwCode = PLAY_WAVE;
pDS->dwRecTime = 0;
// a special way to stop: send the file name with 0 first char
if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName);
else pDS->pbData[0] = 0;
m_pctLine->ctlLineDevSpecific(PLAY_WAVE, 0, 0, (LPVOID)pDS, dwSize);
return TRUE;
}
// Record WAVE using LineDevSpec
BOOL CTapiCall::RecordEx(LPCTSTR lpName, DWORD dwRecTime, int nFormatID)
{
DWORD dwSize; // = sizeof(DXXXDEVSPEC) + 2;
if(lpName) dwSize = lstrlen(lpName)+16;
else dwSize = 512;
if(dwSize > 512) return FALSE;
char szTemp[512];
PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp;
pDS->dwCode = RECORD_WAVE;
pDS->dwRecTime = dwRecTime; //in seconds
// a special way to stop: send the file name with 0 first char
if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName);
else pDS->pbData[0] = 0;
m_pctLine->ctlLineDevSpecific(RECORD_WAVE, 0, 0, (LPVOID)pDS, dwSize);
return TRUE;
}
// if playing/recording using DevSpec, return the most current WAVE status
DWORD CTapiCall::GetRecPlayStatus()
{
DWORD dwStat = m_pctLine->ctlGetDevSpecStatus();
DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc();
switch(dwStat)
{
case DEVSPEC_SUCCESS:
case DEVSPEC_IDLE:
return WAVE_IDLE;
case DEVSPEC_STARTING:
return dwFunc == PLAY_WAVE ? PREPARING_TO_PLAY : PREPARING_TO_RECORD;
case DEVSPEC_STARTFAILED:
return FAILED_START;
case DEVSPEC_PROGRESS:
return dwFunc == PLAY_WAVE ? PLAYING : dwFunc == RECORD_WAVE ? RECORDING :WAVE_IDLE;
case DEVSPEC_RESULTFAILED:
return WAVE_FAILED;
default:
return WAVE_IDLE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -