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; }