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

📄 amstate.cpp

📁 VC写的用TAPI实现的自动应答系统(Answering Machine).
💻 CPP
字号:
#include <windows.h>      
#include <mmsystem.h>
#include <stdio.h>
#include <conio.h>
#include <TAPI.h>
#include "AM.h"
#include "AMState.h"
#include "Wave.h"

char *pszOwnerID="1234";
//---------------------------------------------------------------------------
void OnGatherDigit(LPLINEINFO pLineData)
{
	if ( strcmp(pLineData->pszLoginID, pszOwnerID) == 0 ) //chech gather digits is 1234 or not
	{
		MMRESULT mmrc;

		printf("\nLine %d receive code is : %s",pLineData->nLineID,	pLineData->pszLoginID);

		pLineData->dwCallState &= ~TAPI_PLAYGREET;		 //clear stop play greet flag
		pLineData->dwCallState |= TAPI_PREPAREPLAYICM;	 //set begin play ICM
		pLineData->dwWaveStage = 0;

		if ( mmrc = waveOutReset(pLineData->hWaveOut) )
		{
			printf("\n###Line %d Can't reset wave out error #%x",pLineData->nLineID,mmrc);
			pLineData->dwCallState = TAPI_HANGUP;
			OnHangUp(pLineData->hCall,pLineData->nLineID);
		}	
		else
		{
			printf("\nLine %d wave Out reset success.",pLineData->nLineID);
			FinishPlay(pLineData); //finish play greet.wav,then play ICM
		}

		strcpy(pLineData->pszLoginID,"    ");
	}
	else
	{
		printf("\nLine %d receive incorrect code is : %s",pLineData->nLineID,pLineData->pszLoginID);
		strcpy(pLineData->pszLoginID,"    ");
	}
}
//---------------------------------------------------------------------------
void OnHangUp(HCALL hCall, DWORD ID)
{
	LONG tr = lineDrop(hCall, 0, 0);	   // drop a call
	if( tr > 0 )
	{
		printf("\nLine %d Call dropping...",ID);
	}
	else
	{
		printf("\n###Line %d Can't drop call error#%x.",ID,tr);
	}
}
//---------------------------------------------------------------------------
void FinishPlay(LPLINEINFO pLineData)
{                                  // FinishPlay do waveOutUnprepareHeader
	MMRESULT mmrc;				   // and mmioClose first, then waveOutClose
								   // at last free lpwavehdr
	if (!pLineData->hWaveOut)
	{
		printf("\n###Line %d wave Out Handle is Null",pLineData->nLineID);
		return;
	}
	mmrc =waveOutUnprepareHeader(pLineData->hWaveOut,pLineData->lpWaveHdr, sizeof(WAVEHDR));
	mmrc =waveOutUnprepareHeader(pLineData->hWaveOut,pLineData->lpWaveHdr2, sizeof(WAVEHDR));
	mmrc =mmioClose(pLineData->hmmioH, 0);
	mmrc = waveOutClose(pLineData->hWaveOut);
	if ( mmrc )
	{
		printf("\n###Line %d wave Out close error #%x!",pLineData->nLineID,mmrc);
	}	else
	{
		printf("\nLine %d wave Out close success",pLineData->nLineID);	
	}
	pLineData->hWaveOut = NULL;
	free (pLineData->lpWaveHdr); 
	free (pLineData->lpWaveHdr2); 

	return;	
}
//---------------------------------------------------------------------------
void FinishRecord(LPLINEINFO pLineData)
{   			     // waveInStop first ,then call mmiowrite write wave data into hmmioH
	MMRESULT mmrc;	 // waveInUnprepareHeader,waveInClose,then free lpwavehdr

	if (!pLineData->hWaveIn)
	{
		printf("\n###Line %d wave In Handle is Null",pLineData->nLineID);
		return;
	}
	waveInStop(pLineData->hWaveIn);
	if ( pLineData->wWaveBufState )	//check buf state
	{
		mmioWrite(pLineData->hmmioH, pLineData->lpWaveHdr2->lpData, pLineData->lpWaveHdr2->dwBytesRecorded);
		mmioWrite(pLineData->hmmioH, pLineData->lpWaveHdr->lpData, pLineData->lpWaveHdr->dwBytesRecorded);
	}
	else
	{
		mmioWrite(pLineData->hmmioH, pLineData->lpWaveHdr->lpData, pLineData->lpWaveHdr->dwBytesRecorded);
		mmioWrite(pLineData->hmmioH, pLineData->lpWaveHdr2->lpData, pLineData->lpWaveHdr2->dwBytesRecorded);
	}
	waveInUnprepareHeader(pLineData->hWaveIn, pLineData->lpWaveHdr, sizeof(WAVEHDR));
	waveInUnprepareHeader(pLineData->hWaveIn, pLineData->lpWaveHdr2, sizeof(WAVEHDR));
	mmioAscend(pLineData->hmmioH, &pLineData->mmSubchunk,0); //ascend data chunk
	mmioAscend(pLineData->hmmioH, &pLineData->mmParent, 0);	 //ascend RIFF chunk
	mmrc = mmioClose(pLineData->hmmioH, 0);					 //close hmmioH
	mmrc = waveInClose(pLineData->hWaveIn);					 //close Wave In header
	if ( mmrc )
	{
		printf("\n###Line %d wave In close error# %x!",pLineData->nLineID,mmrc);
	}
	else
	{
		printf("\nLine %d wave In close success",pLineData->nLineID);
	}
	pLineData->hWaveIn = NULL;
	free(pLineData->lpWaveHdr);
	free(pLineData->lpWaveHdr2);

	return;	
}
//---------------------------------------------------------------------------
void OnCallState(LPLINEINFO pLineData) //when ADmorelineCallbackFunc receive 
{									   //LINE_CALLSTATE event ,call this function
	MMRESULT mmrc;
	LONG tr;

	ADCALLBACK pCall = pLineData->pCallBack;
	HCALL hCall = (HCALL)pCall.dwDevice;
	DWORD nCallState = pCall.dwParam1;
	DWORD dwParam2 = pCall.dwParam2;
	DWORD nCallPrivilege = pCall.dwParam3;

	//printf("\nhcall=%X d1=%X d2=%X d3=%X",hCall,nCallState,dwParam2,nCallPrivilege);
	pLineData->hCall = hCall;
	struct FlagMap { DWORD nFlag; LPCSTR szFlag; };
	static FlagMap aFlags[] = 				//callstate event
	{
		{LINECALLSTATE_IDLE,		"idle"},
		{LINECALLSTATE_ACCEPTED,    "accepted"},
		{LINECALLSTATE_DIALTONE,    "dial tone detected"},
		{LINECALLSTATE_DIALING,		"dialing"},
		{LINECALLSTATE_RINGBACK,	"ring-back detected"},
		{LINECALLSTATE_BUSY,		"busy detected"},
		{LINECALLSTATE_SPECIALINFO, "error detected"},
		{LINECALLSTATE_CONNECTED,   "connected"},
		{LINECALLSTATE_PROCEEDING,  "proceeding"},
		{LINECALLSTATE_DISCONNECTED,"disconnected"},
		{LINECALLSTATE_OFFERING,    "offering"}
	};

	for (int i=0; i < 11; i++)
	{
		if ( aFlags[i].nFlag == nCallState )
		{
			printf("\nLine %d Call %s", pLineData->nLineID, aFlags[i].szFlag);
			break;
		}
	}

	switch( nCallState )
	{
		case LINECALLSTATE_DISCONNECTED:
			switch ( pLineData->dwCallState )
			{
				case TAPI_PLAYGREET:		 //play greet.wav ?
				case TAPI_PLAYICM:			 //play Income.wav (ICM)?
					pLineData->dwCallState = TAPI_HANGUP;
					pLineData->dwWaveStage = 0;
					if ( mmrc = waveOutReset(pLineData->hWaveOut) )
					{
						printf("\n###Line %d Can't reset wave out error #%x",pLineData->nLineID,mmrc);
					}
					else
					{
						printf("\nLine %d wave Out reset success.",pLineData->nLineID);
						FinishPlay(pLineData);
					}
					OnHangUp(hCall,pLineData->nLineID);
					break;
				case TAPI_RECORDICM:		 //Record Income.wav? (ICM)
					pLineData->dwCallState = TAPI_HANGUP;
					pLineData->dwWaveStage = 0;
					if ( mmrc = waveInReset(pLineData->hWaveIn) )
					{
						printf("\n###Line %d Can't reset wave in error #%x",pLineData->nLineID,mmrc);
					}
					else
					{
						printf("\nLine %d wave In reset success.",pLineData->nLineID);
						FinishRecord(pLineData);
					}
					OnHangUp(hCall,pLineData->nLineID);
					break;
				case TAPI_PREPAREPLAYICM:	 //Reppare play ICM now?
					pLineData->dwCallState = TAPI_HANGUP;
					OnHangUp(hCall,pLineData->nLineID);
					break;
			} //end switch ( pLineData->dwCallState )
			break;

		case LINECALLSTATE_IDLE:	 
			lineSetAppSpecific(pLineData->hCall, TAPI_SETAPP_NONE);	//set dwAppSpeicfic to 0
			tr = lineDeallocateCall(pLineData->hCall);//deallocate Call
			if ( tr == NOERR )
				printf("\nLine %d linedellocateCall", pLineData->nLineID);
			else
				printf("\nLine %d linedellocateCall error#%x",pLineData->nLineID,tr);
		
			printf("\nLine %d to wait for income call...", pLineData->nLineID);
			break;

		case LINECALLSTATE_BUSY:
			OnHangUp(pLineData->hCall,pLineData->nLineID);
			break;

		case LINECALLSTATE_OFFERING:	// line get the ring
			pLineData->dwCallState = 0;
			tr = lineAnswer(hCall,0,0); // answer the call one this line
			if( tr > 0 )
			{
				printf("\nLine %d answer....",pLineData->nLineID);
			}
			else
			{
				printf("\n###Line %d answer error #%x....",pLineData->nLineID,tr);
			}
			pLineData->hCall = hCall;
			break;

		case LINECALLSTATE_CONNECTED:  //line connect message receive after line answer
			//gether the digit in pszLoginID[5]			
			//lineGatherDigits(pLineData->hCall,LINEDIGITMODE_DTMF,
			//						pLineData->pszLoginID, 4, "*#", 5000, 1500);

			//call WavePlay to play Greet.wav in DeviceID
			pLineData->hWaveOut = WavePlay(pLineData->dwWaveID,"Greet.wav",pLineData);
			if ( pLineData->hWaveOut == NULL )		  // wave out open fail
			{
				OnHangUp(hCall,pLineData->nLineID);
				break;
			}	
			pLineData->dwCallState |= TAPI_PLAYGREET;
			//gether the digit in pszLoginID[5]			
			tr=lineGatherDigits(pLineData->hCall,LINEDIGITMODE_DTMF,
									pLineData->pszLoginID, 4, "*#", 5000, 1500);
			printf("\nLine %d press '1234' to receive Income message...",pLineData->nLineID);
			break;
	}//end switch case
}
//---------------------------------------------------------------------------
long ADmorelineGetCallInfo(HCALL hCall,LINECALLINFO** ppd)
{													//get LINECALLINFO
	DWORD	dwNeededSize = sizeof(LINECALLINFO);	
	LONG    tr = 0;
	do
	{
		//Get some more memory if we don't have enough
		if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
		{
			*ppd = (LPLINECALLINFO)::realloc(*ppd, dwNeededSize);

			if( *ppd )
			{
				(*ppd)->dwTotalSize = dwNeededSize;
			}
			else
			{
				return LINEERR_NOMEM;
			}
		}

		//Fill in the buffer
		tr = lineGetCallInfo(hCall, *ppd);

		//check how much memory we need 
		//because TSPs succeed even if the data size is too small
		if( (tr == LINEERR_STRUCTURETOOSMALL ) ||
			( tr ==	0 && (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
		{
			dwNeededSize = (*ppd)->dwNeededSize;
			tr = LINEERR_STRUCTURETOOSMALL;
		}					 

	}
	while( tr == LINEERR_STRUCTURETOOSMALL );

	return tr;
}
//---------------------------------------------------------------------------
long ADmoreGetLineDevCaps(HLINEAPP hLineApp, DWORD nApiVersion, DWORD nLineID,
							LPLINEINFO pLineInfo, LINEDEVCAPS** ppd)
{													   //get LINEDEVCAPS
	DWORD	dwNeededSize = sizeof(LINEDEVCAPS);
	LONG    tr = 0;

	do
	{
		//Get some more memory if we don't have enough
		if( !*ppd || (*ppd)->dwTotalSize < dwNeededSize )
		{
			*ppd = (LPLINEDEVCAPS)::realloc(*ppd, dwNeededSize);

			if( *ppd )
			{
				(*ppd)->dwTotalSize = dwNeededSize;
			}
			else
			{
				return LINEERR_NOMEM;
			}
		}

		//Fill in the buffer
		tr = lineGetDevCaps(hLineApp, nLineID, nApiVersion, 0, *ppd);

		//check how much memory we need 
		//because TSPs succeed even if the data size is too small
		if( (tr == LINEERR_STRUCTURETOOSMALL ) ||
			( tr ==	0 && (*ppd)->dwTotalSize < (*ppd)->dwNeededSize) )
		{
			dwNeededSize = (*ppd)->dwNeededSize;
			tr = LINEERR_STRUCTURETOOSMALL;
		}					 

	}
	while( tr == LINEERR_STRUCTURETOOSMALL );

	if (((*ppd) -> dwLineNameSize) &&
        ((*ppd) -> dwLineNameOffset) &&
	    ((*ppd) -> dwStringFormat == STRINGFORMAT_ASCII))
    {							   //get line Name on dwLineOffset
        strcpy(pLineInfo->szLineName,
			           ((char *) (*ppd)) + (*ppd) -> dwLineNameOffset);
    }
	else
    {
        strcpy(pLineInfo->szLineName,"UnknowName");
    }

	return tr;

}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void OpenLine(LPLINEINFO pLineData)	   //open voice line
{	
	LINEDEVCAPS* pldc = 0;
	DWORD nLineID = pLineData->nLineID;
	if((ADmoreGetLineDevCaps(m_hLineApp,		  //get line device capability in pldc
								pLineData->dwApiVersion,
								nLineID,
								pLineData,
								&pldc)==0) &&
		(pldc->dwBearerModes & LINEBEARERMODE_VOICE) &&
		(pldc->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) &&
		(pldc->dwLineFeatures & LINEFEATURE_MAKECALL) )	
	{
		if( lineOpen(m_hLineApp, nLineID, &pLineData->hLine, pLineData->dwApiVersion,
					 0, 0, LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE, NULL)==0 )
		{
		    //easy for user look ch1 ~ ch(m_nLines), not ch0 ~ ch(m_nLines-1)
			pLineData->nLineID++;
			/*get line device ID */
			lpDeviceID->dwTotalSize =  sizeof (VARSTRING) + 64;	      			 
			lineGetID(pLineData->hLine, 0, 0, LINECALLSELECT_LINE, lpDeviceID,"tapi/line");
			pLineData->dwLineID = (DWORD) *((BYTE*)lpDeviceID+sizeof(VARSTRING)); 
			FillMemory(lpDeviceID,sizeof (VARSTRING) + 64, 'f');  //fill lpdevice with 'f' byte
			/*get wave device ID */
			lpDeviceID->dwTotalSize =  sizeof (VARSTRING) + 64;	      			 
			lineGetID(pLineData->hLine, 0, 0, LINECALLSELECT_LINE, lpDeviceID,"wave/out");
			pLineData->dwWaveID = (DWORD) *((BYTE*)lpDeviceID+sizeof(VARSTRING)); 
			FillMemory(lpDeviceID,sizeof (VARSTRING) + 64, 'f');  //fill lpdevice with 'f' byte
			//delete lpDeviceID;
		    printf("\nOpen Line %d to wait for income call...(%s)",
										pLineData->nLineID,pLineData->szLineName);
		}
		else
		{
			printf("\n### Line %d open fail ! (%s)", 
						++pLineData->nLineID,pLineData->szLineName);
    	}
	}
	else
	{
		printf("\n### Line %d is not device for interactive voice ! (%s)", 
					++pLineData->nLineID,pLineData->szLineName);
	}
	free(pldc);	
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -