⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapicall.cpp

📁 TAPI编程应用
💻 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 + -