www.pudn.com > tapi3.zip > TAPICALL.CPP


// tapicall.cpp : implementation file for CTapiCall 
// (c) Dialogic corp 1995, 1996 
 
#include "stdafx.h" 
#include  
#include "tapiapp.h" 
#include "tapiline.h" 
#include  
#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;	 
	} 
}