www.pudn.com > tapi3.zip > TALKER32.CPP
// talker32.cpp : Defines the class behaviors for the application. // (c) Dialogic corp 1995, 1996 #include "stdafx.h" #include#include "tapiapp.h" #include "tapiline.h" #include "tapicall.h" #include "talker32.h" #include "talkdlg.h" #include "helpid.h" #include "devspec.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CTalkApp BEGIN_MESSAGE_MAP(CTalkApp, CTapiApp) //{{AFX_MSG_MAP(CTalkApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! ON_COMMAND(ID_HELP, OnHelp) //}}AFX_MSG END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTalkApp construction CTalkApp::CTalkApp() { m_dwTapiAlert = 0; } ///////////////////////////////////////////////////////////////////////////// // The one and only CTalkApp object CTalkApp theApp; ///////////////////////////////////////////////////////////////////////////// // CTalkApp initialization BOOL CTalkApp::InitInstance() { DWORD i, dwrc; CString csTemp, csAA; if(!CTapiApp::InitInstance()) // failed to initialize return FALSE; memset((PBYTE)m_ctlLines, 0, sizeof(m_ctlLines)); CStatusBox sbDlg; sbDlg.m_csStatus = "Initializing TAPI..."; sbDlg.Create(IDD_STATUSDLG); if(m_dwLines > MAXLINES) { AfxMessageBox("This program supports up to 16 lines", MB_ICONEXCLAMATION); m_dwLines = MAXLINES; } // Read optional info memset((LPBYTE)m_wLineOptions, 0, sizeof(m_wLineOptions)); SetRegistryKey("Dialogic\\SystemRelease 4.x"); for(i = 0; i < m_dwLines; i++) { dwrc = 0L; if(NULL == (m_ctlLines[i] = new CTapiLine(i))) //constructor dn open the line MessageBox(NULL, "Failed to get Cline", NULL, MB_OK); else dwrc = m_ctlLines[i]->ctlLineOpen(i); if(dwrc) { char szErr[48]; if(!Code2Error(dwrc, szErr, 46)) csTemp.Format("Failed to open line %d reason=%lx", i, dwrc); else csTemp.Format("Failed to open line %d, reason=%s", i, szErr); MessageBox(NULL, (LPCTSTR)csTemp, NULL, MB_ICONSTOP); } else sbDlg.m_csStatus.Format("Line %d opened", i); sbDlg.UpdateData(FALSE); csTemp.Format("Line%d", i); csAA = GetProfileString((LPCTSTR)csTemp, "AutoAnswer", ""); if(!csAA.IsEmpty()) // Default mode is no autoanswer { csAA.MakeUpper(); if((-1 != csAA.Find("YES")) || (-1 != csAA.Find("ON"))) m_wLineOptions[i] |= AUTOANSWER; // set bit } csAA = GetProfileString((LPCTSTR)csTemp, "AutoPlay", ""); if(!csAA.IsEmpty()) // Default mode is no autoplay { csAA.MakeUpper(); if((-1 != csAA.Find("YES")) || (-1 != csAA.Find("ON"))) m_wLineOptions[i] |= AUTOPLAY; // set bit } } sbDlg.DestroyWindow(); CTalkDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } // Check for active calls, close them properly; called from the front end before shutting down the app void CTalkApp::Cleanup() { DWORD i; for(i=0; i ctlLineDrop(); } // close the lines; if there are active calls shut them int CTalkApp::ExitInstance() { DWORD i; for(i=0; i ctlGetHLine() == hLine) { return m_ctlLines[i]; } } return NULL; } // Get CTapiLine by hcall CTapiLine * CTalkApp::GetLineByCall(HCALL hCall) { LPLINECALLINFO lpLCI = GetCallInfo(hCall); if(lpLCI == NULL) return NULL; // failed for some reason // implement additional logic here to search thru inactive calls CTapiLine *pLine = GetLineByHLine(lpLCI->hLine); delete (LPBYTE) lpLCI; return pLine; } // Find pCall by specified parameter LPVOID CTalkApp::GetCallByParm(WORD wKey, DWORD dwValue) { DWORD i; CTapiCall *pCall; for(i=0; i< m_dwLines; i++) { if(NULL == m_ctlLines[i] || (NULL == (pCall = m_ctlLines[i]->ctlGetActiveCall()))) continue; switch(wKey) { case KEY_LINE: if(m_ctlLines[i] == (CTapiLine *)dwValue) return (LPVOID)pCall; break; case KEY_WAVEINHANDLE: if(NULL != dwValue && pCall->GetHWaveIn() == dwValue) return (LPVOID)pCall; break; case KEY_WAVEOUTHANDLE: if(NULL != dwValue && pCall->GetHWaveOut() == dwValue) return (LPVOID)pCall; break; default: break; } } return NULL; // not found } // override of CTapiApp implementation void CTalkApp::OnLineReply(DWORD dwCallback, DWORD dwRequest, DWORD dwStatus) { // first, find the request TRACE("*** TALKER32 *** :enter OnReply ID=%lx Status=%lx\n", dwRequest, dwStatus); PASYNCCALL pAC = FindAsyncID(dwRequest, FIND_ID); if(pAC == NULL) // not found for some reason (???) { TRACE1("*** TALKER32 *** :Request ID=%lx not found!\n", dwRequest); return; } ASSERT(pAC->dwID == dwRequest); // sanity check CTapiLine *pCurLine = (CTapiLine *) pAC->pvLine; switch (pAC->wFunction) { case FUNCTION_MAKECALL: if(dwStatus & 0x80000000) // makecall failed, try to drop { TRACE("*** TALKER32 *** :MakeCall ID=%lx failed, err=%lx\n", dwRequest, dwStatus); // notify the line, let it find out what to do } pCurLine->ctlUpdateCallStatus(pAC->wFunction, dwStatus, (CTapiCall *)(pAC->pvCall)); break; case FUNCTION_DROP: if(dwStatus & 0x80000000) // drop failed TRACE("*** TALKER32 *** :Drop ID=%lx failed, err=%lx\n", dwRequest, dwStatus); // notify the line, let it find out what to do pCurLine->ctlUpdateCallStatus(pAC->wFunction, dwStatus, (CTapiCall *)(pAC->pvCall)); break; case FUNCTION_ANSWER: // Answer succeeded?... if(dwStatus & 0x80000000) // answer failed TRACE("*** TALKER32 *** :Answer ID=%lx failed, err=%lx\n", dwRequest, dwStatus); pCurLine->ctlUpdateCallStatus(pAC->wFunction, dwStatus, (CTapiCall *)(pAC->pvCall)); break; case FUNCTION_DIAL: if(dwStatus & 0x80000000) // answer failed TRACE("*** TALKER32 *** :Dial ID=%lx failed, err=%lx\n", dwRequest, dwStatus); pCurLine->ctlUpdateCallStatus(pAC->wFunction, dwStatus, (CTapiCall *)(pAC->pvCall)); break; case FUNCTION_DEVSPEC: // device specific... if(dwStatus & 0x80000000) TRACE("*** TALKER32 *** :Devspec ID=%lx failed, err=%lx\n", dwRequest, dwStatus); pCurLine->ctlUpdateCallStatus(pAC->wFunction, dwStatus, (CTapiCall *)(pAC->pvCall)); break; default: TRACE("*** TALKER32 ***: Undefined async function call\n"); break; } // end of switch(wFunction) TRACE("*** TALKER32 *** :exit OnReply ID=%lx\n", dwRequest); FindAsyncID(dwRequest, REMOVE_ID); // Done, remove the ID from list } // Override of CTapiApp OnLineCallInfo implementation void CTalkApp::OnLineCallInfo(HCALL hCall, DWORD dwCallBack, DWORD dwParm) { BOOL brc, bFound = FALSE; DWORD i; LPLINECALLINFO lpCI = GetCallInfo(hCall); TRACE("*** TALKER32 *** :OnLineCallinfo hCall=%lx, DevID=%d\n", hCall, lpCI->dwLineDeviceID); if(lpCI == NULL) return; for(i=0; i < m_dwLines; i++) { if(m_ctlLines[i] && m_ctlLines[i]->ctlGetHLine() == lpCI->hLine) { bFound = TRUE; break; } } if(bFound) brc = m_ctlLines[i]->ctlUpdateCallInfo(hCall, lpCI); if(!bFound || (bFound && brc == FALSE)) delete lpCI; } // Override of CTapiApp OnCallState implementation void CTalkApp::OnCallState(HCALL hCall, DWORD hCallback, DWORD dwCallState, DWORD dwCallStateDetail, DWORD dwCallPrivilege) { // May issue lineGetCallStatus here to get info CString csTemp; DWORD dwDiscMode; LONG lrc; TRACE("*** TALKER32 *** :OnLineCallState hCall=%lx, state=%lx, detail=%lx\n", hCall, dwCallState, dwCallStateDetail); CTapiLine *pclTemp = GetLineByCall(hCall); if(pclTemp == NULL) // line not found { TRACE("*** TALKER32 ***: OnCallState failed to find line\n"); return; } CTapiCall *pCall = pclTemp->ctlGetActiveCall(); if(pCall == NULL && dwCallState != LINECALLSTATE_OFFERING && dwCallState != LINECALLSTATE_ACCEPTED ) // call not found - probably offering { TRACE("*** TALKER32 ***: OnCallState failed to find call\n"); return; } switch(dwCallState) { case LINECALLSTATE_DIALING: case LINECALLSTATE_DIALTONE: case LINECALLSTATE_PROCEEDING: // not clear what to do if this collides w/Drop -so do nothing TRACE("*** TALKER32 ***: Callstate = %s\n", dwCallState==LINECALLSTATE_DIALTONE ? "Dialtone" : dwCallState==LINECALLSTATE_DIALING ? "Dialing" : "Proceeding"); // pCall->UpdateCallState(CONNECTED, 0xffff, dwCallState); NotifyFrontEnd(pclTemp->ctlGetLineID()); break; case LINECALLSTATE_OFFERING: case LINECALLSTATE_ACCEPTED: TRACE("*** TALKER32 ***: Callstate = %s\n", dwCallState==LINECALLSTATE_OFFERING ? "Offering" : "Accepted"); if(pCall) { TRACE("*** TALKER32 ***: Cannot answer, another call is active on this line\n"); csTemp.Format("Cannot answer call on line %d, another call still active\n", pclTemp->ctlGetLineID()); m_pMainWnd->MessageBox(csTemp); } else if(pclTemp != NULL) pclTemp->ctlOfferCall(hCall); // line allocates call & alerts front end break; case LINECALLSTATE_CONNECTED: TRACE("*** TALKER32 ***: Callstate = Connected\n"); pCall->UpdateCallState(CONNECTED, 0xffff, dwCallState); m_wLineOptions[pclTemp->ctlGetLineID()] |= PLAY_ONCE; NotifyFrontEnd(pclTemp->ctlGetLineID()); break; case LINECALLSTATE_DISCONNECTED: case LINECALLSTATE_SPECIALINFO: case LINECALLSTATE_BUSY: if (dwCallState == LINECALLSTATE_DISCONNECTED) TRACE("*** TALKER32 ***: Callstate = Disconnected, reason=%lx\n", dwCallStateDetail); else if (dwCallState == LINECALLSTATE_BUSY) TRACE("*** TALKER32 ***: Callstate = BUSY, mode = %lx\n", dwCallStateDetail); else if (dwCallState == LINECALLSTATE_SPECIALINFO) TRACE("*** TALKER32 ***: Callstate = SPECIALINFO, mode = %lx\n", dwCallStateDetail); dwDiscMode = dwCallStateDetail; if (dwDiscMode == 0) dwDiscMode = LINEDISCONNECTMODE_NORMAL; pCall->UpdateCallState(DISCONNECTED, 0xffff, dwCallState); /* fCallOK = (discMode == LINEDISCONNECTMODE_NORMAL || discMode == LINEDISCONNECTMODE_UNKNOWN || discMode == LINEDISCONNECTMODE_PICKUP || discMode == LINEDISCONNECTMODE_FORWARDED || discMode == LINEDISCONNECTMODE_UNAVAIL); */ lrc = pclTemp->ctlLineDrop(pCall); // which will notify front end if(lrc <0) TRACE("*** TALKER32 ***: lineDrop failed rc = %lx\n", lrc); break; case LINECALLSTATE_IDLE: TRACE("*** TALKER32 ***: Callstate IDLE for hcall=%lx\n", hCall); pCall->UpdateCallState(IDLE, IDLE, dwCallState); pclTemp->ctlLineDeallocateCall(pCall); break; default: break; } // switch CALLSTATE } // LINE_MONITORDIGITS processor void CTalkApp::OnMonitorDigits(HCALL hCall, DWORD dwCallBack, DWORD dwDigit, DWORD dwDigitMode) { TRACE("***: OnMonitorDigits digit = %lx\n", dwDigit); CTapiLine *pclTemp = GetLineByCall(hCall); if(pclTemp == NULL) // line not found { TRACE("*** TALKER32 ***: OnMonitorDigits failed to find line\n"); return; } CTapiCall *pCall = pclTemp->ctlGetActiveCall(); if(pCall == NULL) { TRACE("*** TALKER32 ***: OnMonitorDigits failed to find call\n"); return; } pCall->UpdateMonitorState(MONITOR_DIGITS, dwDigit, dwDigitMode); // new status pCall->NotifyCallWindow((UINT)dwDigit, (LONG)dwDigitMode); // post a message that status has changed } // LINE_GATHERDIGITS processor void CTalkApp::OnGatherDigits(HCALL hCall, DWORD dwCallBack, DWORD dwTermination) { CString csTemp; CTapiLine *pclTemp = GetLineByCall(hCall); TRACE("***: OnGatherDigits term = %lx\n", dwTermination); if(pclTemp == NULL) // line not found { TRACE("*** TALKER32 ***: OnGatherDigits failed to find line\n"); return; } CTapiCall *pCall = pclTemp->ctlGetActiveCall(); if(pCall == NULL) { TRACE("*** TALKER32 ***: OnGatherDigits failed to find call\n"); return; } pCall->UpdateMonitorState(END_GATHER_DIGITS, dwTermination, 0L); // new status // pCall->NotifyCallWindow(); // post a message that status has changed pCall->NotifyCallWindow(0, (LONG)dwTermination); // post a message that status has changed } // Process LINE_MONITORMEDIA callback void CTalkApp::OnMonitorMedia(DWORD hCall, DWORD dwCallBack, DWORD dwParm1, DWORD dwParm2, DWORD dwParm3) { // This is a temp workaround until MS fixes remotesp.tsp to process Devspecific & Generate events if(dwParm1) return; switch(dwParm2) { case PLAY_WAVE: case RECORD_WAVE: OnLineDevSpec(hCall, dwCallBack, dwParm2, dwParm3==55 ? 0 : dwParm3, 1111); return; default: return; } } // Process LINE_DEVSPECIFIC callback void CTalkApp::OnLineDevSpec(DWORD hCall, DWORD dwCallBack, DWORD dwParm1, DWORD dwParm2, DWORD dwParm3) { // the action depends on the meaning of parm1 if(dwParm1 != PLAY_WAVE && dwParm1 != RECORD_WAVE) return; CTapiLine *pLine = (dwParm3 == 1111 ? GetLineByCall((HCALL) hCall) : GetLineByHLine((HLINE)hCall)); if(pLine) pLine->ctlUpdateDevSpecStatus(dwParm2 ? DEVSPEC_RESULTFAILED : DEVSPEC_IDLE); } // translate code into verbal call state BOOL CTalkApp::Code2CallState(DWORD dwState, LPSTR lpBuf, int nSize) { BOOL brc = TRUE; switch(dwState) { case LINECALLSTATE_IDLE: strncpy(lpBuf, "LINECALLSTATE_IDLE", nSize); break; case LINECALLSTATE_OFFERING: strncpy(lpBuf, "LINECALLSTATE_OFFERING", nSize); break; case LINECALLSTATE_ACCEPTED: strncpy(lpBuf, "LINECALLSTATE_ACCEPTED", nSize); break; case LINECALLSTATE_DIALTONE: strncpy(lpBuf, "LINECALLSTATE_DIALTONE", nSize); break; case LINECALLSTATE_DIALING: strncpy(lpBuf, "LINECALLSTATE_DIALING", nSize); break; case LINECALLSTATE_RINGBACK: strncpy(lpBuf, "LINECALLSTATE_RINGBACK", nSize); break; case LINECALLSTATE_BUSY: strncpy(lpBuf, "LINECALLSTATE_BUSY", nSize); break; case LINECALLSTATE_SPECIALINFO: strncpy(lpBuf, "LINECALLSTATE_SPECIALINFO", nSize); break; case LINECALLSTATE_CONNECTED: strncpy(lpBuf, "LINECALLSTATE_CONNECTED", nSize); break; case LINECALLSTATE_PROCEEDING: strncpy(lpBuf, "LINECALLSTATE_PROCEEDING", nSize); break; case LINECALLSTATE_ONHOLD: strncpy(lpBuf, "LINECALLSTATE_ONHOLD", nSize); break; case LINECALLSTATE_DISCONNECTED: strncpy(lpBuf, "LINECALLSTATE_DISCONNECTED", nSize); break; case LINECALLSTATE_UNKNOWN: strncpy(lpBuf, "LINECALLSTATE_UNKNOWN", nSize); break; case LINECALLSTATE_ONHOLDPENDTRANSFER: strncpy(lpBuf, "LINECALLSTATE_ONHOLDPENDTRANSFER", nSize); break; default: brc = FALSE; // not found break; } return brc; } BOOL CTalkApp::Code2Error(DWORD dwErr, LPSTR lpBuf, int nSize) { BOOL brc = TRUE; switch(dwErr) { case LINEERR_BADDEVICEID: strncpy(lpBuf, "LINEERR_BADDEVICEID", nSize); break; case LINEERR_INCOMPATIBLEAPIVERSION: strncpy(lpBuf, "LINEERR_INCOMPATIBLEAPIVERSION", nSize); break; case LINEERR_INCOMPATIBLEEXTVERSION: strncpy(lpBuf, "LINEERR_INCOMPATIBLEEXTVERSION", nSize); break; case LINEERR_INUSE: strncpy(lpBuf, "LINEERR_INUSE", nSize); break; case LINEERR_INVALCALLHANDLE: strncpy(lpBuf, "LINEERR_INVALCALLHANDLE", nSize); break; case LINEERR_INVALCALLPRIVILEGE: strncpy(lpBuf, "LINEERR_INVALCALLPRIVILEGE", nSize); break; case LINEERR_INVALCALLSTATE: strncpy(lpBuf, "LINEERR_INVALCALLSTATE", nSize); break; case LINEERR_INVALMEDIAMODE: strncpy(lpBuf, "LINEERR_INVALMEDIAMODE", nSize); break; case LINEERR_INVALPARAM: strncpy(lpBuf, "LINEERR_INVALPARAM", nSize); break; case LINEERR_INVALPOINTER: strncpy(lpBuf, "LINEERR_INVALPOINTER", nSize); break; case LINEERR_OPERATIONFAILED: strncpy(lpBuf, "LINEERR_OPERATIONFAILED", nSize); break; case LINEERR_OPERATIONUNAVAIL: strncpy(lpBuf, "LINEERR_OPERATIONUNAVAIL", nSize); break; default: brc = FALSE; // not found break; } return brc; } void CTalkApp::OnHelp() { // if(m_pMainWnd->GetSafeHwnd() == ::GetActiveWindow()) // WinHelp(HIDD_TALKER32_DialogMain, HELP_CONTEXT); // else // WinHelp(HIDD_TALKER32_DialogLineInfo, HELP_CONTEXT); WinHelp(m_nHelpId, HELP_CONTEXT); } ///////////////////////////////////////////////////////////////////////////// // CStatusBox dialog CStatusBox::CStatusBox(CWnd* pParent /*=NULL*/) : CDialog(CStatusBox::IDD, pParent) { //{{AFX_DATA_INIT(CStatusBox) m_csStatus = _T(""); //}}AFX_DATA_INIT } void CStatusBox::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CStatusBox) DDX_Text(pDX, IDC_STATUS, m_csStatus); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CStatusBox, CDialog) //{{AFX_MSG_MAP(CStatusBox) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CStatusBox message handlers BOOL CStatusBox::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }