www.pudn.com > DIAL.rar > DIAL.CPP


#include  
#include  
#include  
#include  
#include  
#include "Dial.h" 
#include "WavePlay.h" 
 
HLINEAPP    m_hLineApp; 
DWORD	    m_nLines; 
LPLINEINFO	pLineInfo; 
LPVARSTRING lpDeviceID; 
DWORD		dwActiveChn; 
LINEDEVCAPS* pldc = 0; 
//--------------------------------------------------------------------------- 
void FinishPlay(LPLINEINFO pLineData) 
{                                      
	MMRESULT mmrc; 
 
	if (!pLineData->hWaveOut) return; 
	waveOutUnprepareHeader(pLineData->hWaveOut,pLineData->lpWaveHdr, sizeof(WAVEHDR)); 
	if ( mmrc = waveOutClose(pLineData->hWaveOut) )	 
	{ 
		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; 
	LocalUnlock((HLOCAL)pLineData->lpWaveDataAlloc); //unlock the memory 
	free (pLineData->lpWaveHdr);  
	 
	return;	 
} 
//--------------------------------------------------------------------------- 
//--------------------------------------------------------------------------- 
void OnHangUp(HCALL hCall, DWORD ID) 
{ 
	LONG tr = lineDrop(hCall, 0, 0); 
	if( tr > 0 ) 
	{ 
		printf("\nLine %d Call dropping...",ID); 
	} 
	else 
	{ 
		printf("\n###Line %d Can't drop call.",ID); 
	} 
} 
//--------------------------------------------------------------------------- 
void OnCallState(LPLINEINFO pLineData) 
{ 
	MMRESULT mmrc; 
 
	ADCALLBACK pCall = pLineData->pCallBack; 
	HCALL hCall = (HCALL)pCall.dwDevice; 
	DWORD nCallState = pCall.dwParam1; 
	DWORD dwParam2 = pCall.dwParam2; 
	DWORD nCallPrivilege = pCall.dwParam3; 
 
	struct FlagMap { DWORD nFlag; LPCSTR szFlag; }; 
	static FlagMap aFlags[] =  
	{ 
		{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"}, 
	}; 
 
	for (int i=0; i < 10; i++) 
	{ 
		if ( aFlags[i].nFlag == nCallState ) 
		{ 
			printf("\nLine %d Call %s", pLineData->nLineID, aFlags[i].szFlag); 
			break; 
		} 
	} 
 
	switch( nCallState ) 
	{ 
		case LINECALLSTATE_DISCONNECTED: 
			switch( dwParam2 ) 
			{ 
				case LINEDISCONNECTMODE_NODIALTONE: 
					printf("\nLine %d No dial tone",pLineData->nLineID); 
					OnHangUp(hCall,pLineData->dwLineID); 
					break; 
				case LINEDISCONNECTMODE_NOANSWER:	//this call is no answer 
					printf("\nLine %d No answer.",pLineData->nLineID); 
					OnHangUp(hCall,pLineData->dwLineID); 
					break; 
				default: 
					if (pLineData->dwCallState & TAPI_PLAYGREET)  //hang up when play hello.wav 
					{ 
						pLineData->dwCallState = TAPI_HANGUP; 
						if ( mmrc = waveOutReset(pLineData->hWaveOut) ) 
							printf("\n###Line %d Can't reset wave out error #%x",pLineData->nLineID,mmrc); 
						else 
							FinishPlay(pLineData); 
						OnHangUp(pLineData->hCall,pLineData->dwLineID); 
					} 
					break;							 
			} 
			break; 
 
		case LINECALLSTATE_IDLE: 
			lineDeallocateCall(hCall); 
			printf("\nLine %d linedellocateCall", pLineData->nLineID); 
			lineClose(pLineData->hLine); 
			printf("\nLine %d lineclose\n", pLineData->nLineID); 
 
			SelectChn(); 
			while(!OpenLine(&pLineInfo[dwActiveChn])) SelectChn(); 
			break; 
 
		case LINECALLSTATE_BUSY: 
			OnHangUp(hCall,pLineInfo->dwLineID); 
			break; 
		case LINECALLSTATE_PROCEEDING: 
			break; 
		case LINECALLSTATE_CONNECTED: 
			pLineData->hCall = hCall; 
			//call WavePlay to play hello.wave in DeviceID 
			pLineData->hWaveOut=WavePlay(pLineData->dwWaveID,"hello.wav", pLineData); 
			pLineData->dwCallState |= TAPI_PLAYGREET; 
			break; 
	} 
} 
//--------------------------------------------------------------------------- 
void CALLBACK ADmorelineCallbackFunc(DWORD dwDevice, DWORD nMsg, DWORD dwCallbackInstance, 
									DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) 
{ 
	lpDeviceID->dwTotalSize =  sizeof (VARSTRING) + 64;	      			  
	lineGetID(0, 0, (HCALL)dwDevice, LINECALLSELECT_CALL, lpDeviceID,"tapi/line"); 
	DWORD dwID = (DWORD) *((BYTE*)lpDeviceID+sizeof(VARSTRING)); // get id for wave out 
	FillMemory(lpDeviceID,sizeof (VARSTRING) + 64, 'f');  //fill lpdevice with 'f' byte 
 
	if ( dwID >= m_nLines )	  //chech device range 
		return; 
 
	ADCALLBACK pCall={dwDevice,nMsg,dwCallbackInstance,dwParam1,dwParam2,dwParam3};	 
 
	switch( nMsg ) 
	{ 
		case LINE_REPLY: 
			printf("\nLine %d Call Back ------>LINE_REPLY",dwID); 
			break;	  
		case LINE_CALLSTATE: 
			printf("\nLine %d Call Back ------>LINE CALLSTATE",dwID); 
			pLineInfo[dwID].pCallBack =	pCall; 
			OnCallState(&pLineInfo[dwID]); 
            break; 
		case LINE_CLOSE: 
            // Line has been shut down. 
            printf("\nLine %d Call Back ------>LINE_CLOSE",dwID); 
            OnHangUp((HCALL)dwDevice,dwID);   // all handles invalidated by this time 
            break; 
        case LINE_CREATE: 
            printf("\nLine %d Call Back ------>LINE_CREATE",dwID); 
            break; 
        case LINE_GATHERDIGITS : 
            printf("\nLine %d Call Back ------>LINE_LINE_GATHERDIGITS",dwID); 
            break; 
		case LINE_CALLINFO : 
			printf("\nLine %d Call Back ------>LINE_CALLINFO",dwID); 
			ADmorelineGetCallInfo(pLineInfo[dwID].hCall,&pLineInfo[dwID].lpCallInfo); 
			if ((dwParam1==LINECALLINFOSTATE_APPSPECIFIC) &&    //check dwAppSpecific state 
				(pLineInfo[dwID].dwCallState!=TAPI_HANGUP) &&	//check call is alive 
				(pLineInfo[dwID].lpCallInfo->dwAppSpecific==TAPI_SETAPP_ENDPLAYGREET)) 
			{ 
					pLineInfo[dwID].dwCallState &= ~TAPI_PLAYGREET; 
					FinishPlay(&pLineInfo[dwID]);	      //then call WaveRecord Rec ICM 
					OnHangUp(pLineInfo[dwID].hCall,pLineInfo[dwID].nLineID); 
			} 
			break; 
        default: 
            printf("\nLine %d Call Back ------>lineCallbackFunc message ignored",dwID); 
            break; 
	} 
}	 
//--------------------------------------------------------------------------- 
long ADmorelineGetCallInfo(HCALL hCall,LINECALLINFO** ppd) 
{ 
	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, 
							LINEDEVCAPS** ppd) 
{ 
	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[nLineID].szLineName, 
			           ((char *) (*ppd)) + (*ppd) -> dwLineNameOffset); 
    } 
	else 
    { 
        strcpy(pLineInfo[nLineID].szLineName,"UnknowName"); 
    } 
	return tr; 
 
} 
//--------------------------------------------------------------------------- 
LPVOID ReAllocBuffer(LPVOID lpBuffer,size_t sizeBufferMinimum) 
{ 
    size_t sizeBuffer; 
    if (lpBuffer == NULL)   // allocate the buffer if necessary 
    { 
        sizeBuffer = sizeBufferMinimum; 
        lpBuffer = (LPVOID) LocalAlloc (LPTR, sizeBuffer); 
        if (lpBuffer == NULL) 
        { 
            printf("\nLocalAlloc failed in CheckAndReAllocBuffer."); 
            return NULL; 
        } 
    } 
    else   // if the structure already exists, make sure it is good 
    { 
        sizeBuffer = LocalSize((HLOCAL) lpBuffer); 
        if (sizeBuffer == 0)   // bad pointer? 
        { 
            printf("\nBad pointer"); 
            return NULL; 
        } 
        // Was the buffer big enough for the structure? 
        if (sizeBuffer < sizeBufferMinimum) 
        { 
            LocalFree(lpBuffer); 
            return ReAllocBuffer(NULL, sizeBufferMinimum); 
        } 
    } 
    // Set the dwTotalSize field to the size of the buffer or the call will 
    // fail. 
    memset(lpBuffer, 0, sizeBuffer); 
   ((LPVARSTRING) lpBuffer ) -> dwTotalSize = (DWORD) sizeBuffer; 
    return lpBuffer; 
} 
//--------------------------------------------------------------------------- 
LPLINECALLPARAMS CreateCallParams (LPLINECALLPARAMS lpCallParams,  
								   LPCSTR lpszDisplayableAddress) 
{ 
    size_t sizeDisplayableAddress; 
 
    if (lpszDisplayableAddress == NULL) 
        lpszDisplayableAddress = ""; 
 
    sizeDisplayableAddress = strlen(lpszDisplayableAddress) + 1; 
 
    lpCallParams = (LPLINECALLPARAMS) ReAllocBuffer( 
        (LPVOID) lpCallParams, 
        sizeof(LINECALLPARAMS) + sizeDisplayableAddress); 
 
    if (lpCallParams == NULL) 
        return NULL; 
 
    // This is where we configure the line. 
    lpCallParams -> dwBearerMode = LINEBEARERMODE_VOICE; 
    lpCallParams -> dwMediaMode  = LINEMEDIAMODE_INTERACTIVEVOICE ;//LINEMEDIAMODE_DATAMODEM; 
 
    // This specifies that we want to use only IDLE calls and 
    // don't want to cut into a call that might not be IDLE (ie, in use). 
    lpCallParams -> dwCallParamFlags = LINECALLPARAMFLAGS_IDLE; 
 
    // If there are multiple addresses on line, use first anyway. 
    // It will take a more complex application than a simple tty app 
    // to use multiple addresses on a line anyway. 
    lpCallParams -> dwAddressMode = LINEADDRESSMODE_ADDRESSID; 
 
    //lpCallParams -> dwNoAnswerTimeout = 5; 
 
    // Address we are dialing. 
    lpCallParams -> dwDisplayableAddressOffset = sizeof(LINECALLPARAMS); 
    lpCallParams -> dwDisplayableAddressSize = sizeDisplayableAddress; 
    strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS), 
                                lpszDisplayableAddress); 
 
    return lpCallParams; 
}   
//--------------------------------------------------------------------------- 
void SelectChn() 
{ 
	do 
	{ 
		printf("\nSelect 0~%d Channel to make a call : ",(m_nLines-1)); 
		scanf("%d", &dwActiveChn); 
	} while (dwActiveChn >= m_nLines); 
	/* input phone number for channel you select to dial*/	 
	printf("Enter phone number of CH<%d> [%s] : ",dwActiveChn,pLineInfo[dwActiveChn].szLineName); 
	scanf("%s",pLineInfo[dwActiveChn].tcDialNo);	 
} 
//--------------------------------------------------------------------------- 
void CallOut(LPLINEINFO pLineData) 
{ 
	HCALL  m_hCall; 
	LPLINECALLPARAMS lpCallParams; 
 
	lpCallParams=NULL; 
	lpCallParams=CreateCallParams(lpCallParams,pLineData->tcDialNo); 
 
	LONG tr = lineMakeCall(pLineData->hLine, 
							&m_hCall, 
							pLineData->tcDialNo, 
							0, 
							lpCallParams); 
	 
	if (tr > 0) 
	{ 
		pLineData->hCall = m_hCall; 
		printf("\nLine %d Placing a call to %s ...",pLineData->nLineID,pLineData->tcDialNo); 
	} 
	else 
	{ 
		pLineData->hCall = 0; 
		printf("\nLine %d Can't make a call on line ...",pLineData->nLineID); 
		lineClose(pLineData->hLine); 
	} 
} 
//--------------------------------------------------------------------------- 
BOOL OpenLine(LPLINEINFO pLineData) 
{	 
	HLINE	m_hLine; 
	DWORD nLineID = pLineData->nLineID; 
 
	if((ADmoreGetLineDevCaps(m_hLineApp, 
								pLineData->dwApiVersion, 
								nLineID, 
								&pldc)==0) && 
		(pldc->dwBearerModes & LINEBEARERMODE_VOICE) && 
		(pldc->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) && 
		(pldc->dwLineFeatures & LINEFEATURE_MAKECALL) )	 
	{ 
		if( lineOpen(m_hLineApp, nLineID, &m_hLine, pLineData->dwApiVersion, 
					 0, 0, LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE, NULL)==0 ) 
        { 
		    printf("\nLine %d open ...", pLineData->nLineID); 
        	pLineData->hLine = m_hLine; 
			/*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 
 
			CallOut(pLineData); 
			return TRUE; 
        } 
        else 
		{ 
            printf("\n###Cannot Open Line %d (%s)!\n\n", nLineID,pLineData->szLineName); 
			return FALSE; 
    	} 
	} 
	else 
	{ 
		printf("\n### Line %d is not device for interactive voice ! (%s)\n\n",  
												nLineID,pLineData->szLineName); 
		return FALSE; 
	} 
} 
//--------------------------------------------------------------------------- 
long InitializeLines(DWORD dwLoVersion, DWORD dwHiVersion) 
{ 
	DWORD m_aApiVersions; 
	 
 
	LONG tr = lineInitialize(&m_hLineApp, 
								NULL, 
								ADmorelineCallbackFunc, 
								"Duncan", 
								&m_nLines); 
	if ( tr == 0 )										  
	{											  
		/* Allocation a block memory to all channel */ 
		pLineInfo = new LINEINFO[m_nLines]; 
		ZeroMemory(pLineInfo,sizeof(LINEINFO)*m_nLines); 
 
		if( m_nLines ) 
		{ 
			//Negotiate the API versions 
			LINEEXTENSIONID extid; 
			for(WORD nLineID=0; nLineID < m_nLines; nLineID++)		 //m_nLines 
			{ 
				tr = lineNegotiateAPIVersion(m_hLineApp, 
												nLineID, 
												dwLoVersion, 
												dwHiVersion, 
												&m_aApiVersions, 
												&extid); 
				if( tr < 0 ) 
				{ 
					pLineInfo[nLineID].dwApiVersion = 0; 
					tr = 0; 
				} 
				else 
				{ 
					pLineInfo[nLineID].dwApiVersion = m_aApiVersions; 
				} 
 
				ADmoreGetLineDevCaps(m_hLineApp,  
								pLineInfo[nLineID].dwApiVersion, nLineID,&pldc); 
					 
 
				pLineInfo[nLineID].lpWaveDataAlloc = (HPSTR) LocalAlloc(LMEM_MOVEABLE, 0);  //123000 
				pLineInfo[nLineID].nLineID = nLineID; 
			} 
		} 
	} 
	return tr; 
} 
//=========================================================================== 
// Main Program 
//=========================================================================== 
int main(int argc,char **argv) 
{ 
	MSG msg; 
 
	BOOL fSuccess; 
	 
	lpDeviceID = (LPVARSTRING) new char[sizeof(VARSTRING) + 64];	 
	lpDeviceID->dwTotalSize =  sizeof (VARSTRING) + 64;	      			  
 
	fSuccess = SetConsoleCtrlHandler((PHANDLER_ROUTINE) ExitCtrlHandler	  //handle function 
		                                                    , TRUE);  //add to list 
	if (!fSuccess) printf("\nCound not set control handler."); 
	SetProcessShutdownParameters(0x280, SHUTDOWN_NORETRY);//terminates without displaying  
														  //a retry dialog box for the user. 
 
	if (InitializeLines(TAPI_VERSION_1_0, TAPI_VERSION_2_0) != NOERR) 
	{ 
		printf("\n\r###Fail to initialize driver !"); 
		exit(1); 
	} 
 
    if ( m_nLines > 0 ) 
		printf("\nTotal %d channels supported.", m_nLines); 
	else 
	{ 
		printf("\nNo channels supported."); 
		printf("\nPress any key to exit.\n"); 
		getch(); 
		return 1; 
	} 
 
	for (DWORD i=0 ; i < m_nLines; i++) 
		printf("\nChannel %d   Name: [%s]",i,pLineInfo[i].szLineName); 
 
	printf("\npress Ctrl-C to exit."); 
	SelectChn(); 
	while(!OpenLine(&pLineInfo[dwActiveChn])) SelectChn(); 
	 
	while (GetMessage(&msg, NULL, 0, 0)) 
    {  
		TranslateMessage(&msg); 
        DispatchMessage(&msg);  
    } 
	/* program exits in ExitCtrlHandler*/	 
	return 1;		//satisfy compiler only 
} 
//--------------------------------------------------------------------------- 
// End Main 
//--------------------------------------------------------------------------- 
BOOL ExitCtrlHandler(DWORD fdwCtrlType) 
{	 
	delete lpDeviceID; 
 
	lineShutdown(m_hLineApp); 
	printf("\nLine Shutdown."); 
 
	for (DWORD i = 0; i < m_nLines; i++) 
		if (pLineInfo[i].lpWaveDataAlloc) 
			LocalFree(pLineInfo[i].lpWaveDataAlloc); 
 
	delete pLineInfo; 
	ExitProcess(1); 
 
	return FALSE;  
}