www.pudn.com > tapi3.zip > CALLINFO.CPP
// callinfo.cpp : implementation file for callinfo class // (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 "callinfo.h" #include "lineinfo.h" #include "helpid.h" #include "tonedlg.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define CALLINFO_TIMER_ID 1 #define WAVE_TIMER_ID 2 UINT uiMsg; ///////////////////////////////////////////////////////////////////////////// // CCallInfo property page IMPLEMENT_DYNCREATE(CCallInfo, CPropertyPage) CCallInfo::CCallInfo() : CPropertyPage(CCallInfo::IDD) { //{{AFX_DATA_INIT(CCallInfo) m_csCallInfo = _T(""); m_csCallState = _T(""); m_csCallAction = _T(""); m_csGathered = _T(""); m_csLastDigit = _T(""); m_csGatherRes = _T(""); //}}AFX_DATA_INIT m_pWaveName = NULL; m_nRecTime = 0; m_uiMsg = RegisterWindowMessage("TALKER32 callinfo alert"); uiMsg = m_uiMsg; SetHelpID(HIDD_TALKER32_DialogCallInfo); } CCallInfo::~CCallInfo() { } void CCallInfo::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCallInfo) DDX_Control(pDX, IDC_CALLALERT, m_btnCallAlert); DDX_Control(pDX, IDC_VOLUME, m_ctlVolume); DDX_Control(pDX, IDC_STOP, m_btnStop); DDX_Control(pDX, IDC_PAUSE, m_btnPause); DDX_Control(pDX, IDC_GATHER, m_btnGather); DDX_Control(pDX, IDC_MONITOR, m_btnMonitor); DDX_Control(pDX, IDC_RECORD, m_btnRecord); DDX_Control(pDX, IDC_PLAY, m_btnPlay); DDX_Text(pDX, IDC_CALLINFO, m_csCallInfo); DDX_Text(pDX, IDC_STATE, m_csCallState); DDX_Text(pDX, IDC_ACTIVITY, m_csCallAction); DDX_Text(pDX, IDC_GATHERED, m_csGathered); DDX_Text(pDX, IDC_LASTDIGIT, m_csLastDigit); DDX_Text(pDX, IDC_GATHERRES, m_csGatherRes); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CCallInfo, CPropertyPage) //{{AFX_MSG_MAP(CCallInfo) ON_BN_CLICKED(IDC_PLAY, OnPlay) ON_BN_CLICKED(IDC_RECORD, OnRecord) ON_BN_CLICKED(IDC_REFRESH, OnRefresh) ON_WM_CLOSE() ON_WM_TIMER() ON_BN_CLICKED(IDC_INFOBTN, OnInfobtn) ON_BN_CLICKED(IDC_MONITOR, OnMonitor) ON_WM_DESTROY() ON_BN_CLICKED(IDC_CALLALERT, OnCallalert) ON_BN_CLICKED(IDC_GATHER, OnGather) ON_BN_CLICKED(IDC_PAUSE, OnPause) ON_BN_CLICKED(IDC_STOP, OnStop) ON_WM_HSCROLL() ON_REGISTERED_MESSAGE(uiMsg, OnDynamicAlert) ON_BN_CLICKED(IDC_GENTONE, OnGentone) ON_WM_SETFOCUS() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CCallInfo::DisplayCallInfo(BOOL bUpdateCallInfo) { if(m_pCall == NULL) return; if(NULL == m_pLine->ctlGetActiveCall()) // call no longer active { if(m_pCall) { m_pCall->m_hStatusWnd = NULL; m_pCall->m_hCallAlertWnd = NULL; m_pCall->m_uiAlertMsg = NULL; } m_pCall = NULL; ::PostMessage(::GetParent(m_hWnd), WM_CLOSE, 0, NULL); KillTimer(CALLINFO_TIMER_ID); return; } // display status WORD wState = m_pCall->GetCallState(); WORD wDir = m_pCall->GetCallDirection(); CString csTemp; m_csCallState = "State ="; switch(wState) { case IDLE: csTemp = "idle"; break; case MAKING: csTemp = "making"; break; case STOP_MAKING: csTemp = "stop making"; break; case PROGRESS: csTemp = "progress"; break; case DIALING: csTemp = "dialing"; break; case OFFERING: csTemp = "offering"; break; case ANSWERING: csTemp = "answering"; break; case CONNECTED: csTemp = "connected"; break; case HOLD: csTemp = "hold"; break; case DROPPING: csTemp = "dropping"; break; case DISCONNECTED: csTemp = "disconnected"; break; default: csTemp = "undefined"; break; } m_csCallState += csTemp; DWORD dwWaveStatus = m_pCall->GetWaveStatus(); DWORD dwPRStatus; switch(dwWaveStatus) { case WAVE_IDLE: csTemp = "Idle"; m_btnPause.SetWindowText("Pause"); m_btnStop.EnableWindow(FALSE); KillTimer(WAVE_TIMER_ID); m_nRecTime = 0; break; case PREPARING_TO_PLAY: case PLAYING: case FINISHING_PLAY: csTemp = "Playing"; m_btnPause.SetWindowText("Pause"); m_btnStop.EnableWindow(); break; case PAUSED: csTemp = "Paused"; m_btnPause.SetWindowText("Resume"); break; case PREPARING_TO_RECORD: case RECORDING: case FINISHING_RECORD: csTemp.Format("Recording, %d seconds left", m_nRecTime); m_btnStop.EnableWindow(); break; case WAVE_DISFUNCTIONAL: csTemp = "Wave disabled"; m_btnStop.EnableWindow(FALSE); // m_nRecTime = 0; // check the dev specific play/record status dwPRStatus = m_pCall->GetRecPlayStatus(); switch(dwPRStatus) // all possible cases for dev specific play/record { case WAVE_IDLE: KillTimer(WAVE_TIMER_ID); m_nRecTime = 0; break; case PREPARING_TO_RECORD: case RECORDING: csTemp.Format("Recording, %d seconds left", m_nRecTime); m_btnStop.EnableWindow(); break; case PREPARING_TO_PLAY: case PLAYING: case FINISHING_PLAY: csTemp = "Playing"; m_btnStop.EnableWindow(); break; case FAILED_START: csTemp = "Wave disabled"; m_pLine->ctlUpdateDevSpecStatus(DEVSPEC_IDLE); MessageBox("WAVE function failed to start", NULL, MB_ICONSTOP); m_btnStop.EnableWindow(FALSE); break; case WAVE_FAILED: csTemp = "Wave disabled"; m_pLine->ctlUpdateDevSpecStatus(DEVSPEC_IDLE); MessageBox("WAVE function failed to complete", NULL, MB_ICONSTOP); m_btnStop.EnableWindow(FALSE); break; } break; default: csTemp = "Not available"; m_btnStop.EnableWindow(FALSE); m_nRecTime = 0; break; } //end-switch m_csCallAction = "Action:"; m_csCallAction += csTemp; if(wState != CONNECTED) m_btnStop.EnableWindow(FALSE); // Determine if WAVE play/record are available thru TAPI extensions // Make it available if: local system, wave driver not installed OR remote system if(dwWaveStatus == WAVE_DISFUNCTIONAL && m_bRunningOnNT) { m_btnPlay.SetWindowText("PlayX"); m_btnRecord.SetWindowText("RecordX"); m_btnPlay.EnableWindow(wState == CONNECTED); m_btnRecord.EnableWindow(wState == CONNECTED); } else { m_btnPlay.EnableWindow(wState == CONNECTED && dwWaveStatus == WAVE_IDLE); m_btnRecord.EnableWindow(wState == CONNECTED && dwWaveStatus == WAVE_IDLE); } m_btnPause.EnableWindow(dwWaveStatus==PREPARING_TO_PLAY || dwWaveStatus==PLAYING || // dwWaveStatus==WAVE_IDLE || dwWaveStatus== PAUSED); //PREPARING_TO_RECORD || dwWaveStatus==RECORDING); UpdateData(FALSE); if(!bUpdateCallInfo) return; //UpdateDigitsMonitorStatus(); // do not read gathered m_csCallInfo.Empty(); LPLINECALLSTATUS lpLCI = ((CTalkApp *)AfxGetApp())->GetCallStatus(m_pCall->m_hCall); if(lpLCI == NULL) return; // failed for some reason char szState[48]; if(!((CTalkApp *)AfxGetApp())->Code2CallState(lpLCI->dwCallState, szState, 46)) csTemp.Format("state = %lx\r\nstatemode = %lx\r\nprivilege = %lx\r\nfeatures = %lx\r\n", lpLCI->dwCallState, lpLCI->dwCallStateMode, lpLCI->dwCallPrivilege,lpLCI->dwCallFeatures); else csTemp.Format("state = %s\r\nstatemode = %lx\r\nprivilege = %lx\r\nfeatures = %lx\r\n", szState, lpLCI->dwCallStateMode, lpLCI->dwCallPrivilege,lpLCI->dwCallFeatures); m_csCallInfo += csTemp; m_btnMonitor.EnableWindow(lpLCI->dwCallState == LINECALLSTATE_CONNECTED || lpLCI->dwCallState == LINECALLSTATE_DIALTONE); m_btnGather.EnableWindow(lpLCI->dwCallState == LINECALLSTATE_CONNECTED); UpdateData(FALSE); delete (PBYTE) lpLCI; } void CCallInfo::UpdateDigitsMonitorStatus(BOOL bReadGathered, UINT wParam, LONG lParam) { MONITORSTATE msMonState ={0, 0, 0L, 0L, 0}; BOOL bUpdateMon = FALSE; // Check/update monitor & gather state here if(lParam) // this is always != 0 for the parametrized alert { if(wParam) // Monitor result { msMonState.wState |= MONITOR_DIGITS; msMonState.wLastDigit = (WORD) wParam; bUpdateMon = TRUE; } else // gather result { msMonState.dwGatherResult = lParam; msMonState.wState &= ~START_GATHER; } } else if(!wParam) // non-parametrized alert { m_pCall->GetMonitorState(&msMonState); bUpdateMon = TRUE; } if(bUpdateMon) { if(msMonState.wState & MONITOR_DIGITS) { m_btnMonitor.SetWindowText("Stop Monitor"); m_csLastDigit.Format("%c", LOBYTE(msMonState.wLastDigit)); } else m_btnMonitor.SetWindowText("Monitor Digits"); } if(msMonState.wState & START_GATHER) // gathering in progress m_btnGather.SetWindowText("Stop Gather"); else if(bReadGathered && msMonState.dwGatherResult) // read result if available { if(msMonState.dwGatherResult != LINEGATHERTERM_CANCEL) { m_pCall->m_szDigits[20] = 0; m_csGathered = m_pCall->m_szDigits; int i; for(i=0; i m_szDigits); i++) { if(m_pCall->m_szDigits[i] != '*' && m_pCall->m_szDigits[i] != '#' && !isdigit(m_pCall->m_szDigits[i])) { m_csGathered.Empty(); break; } } } m_csGatherRes.Format("%d",msMonState.dwGatherResult); m_pCall->UpdateMonitorState(RESET_GATHER_RESULT, 0L, 0L); m_btnGather.SetWindowText("Gather Digits"); } UpdateData(FALSE); //from data to controls } ///////////////////////////////////////////////////////////////////////////// // CCallInfo message handlers BOOL CCallInfo::OnInitDialog() { CPropertyPage::OnInitDialog(); SetHelpID(HIDD_TALKER32_DialogCallInfo); if(!m_csCaption.IsEmpty()) SetWindowText(m_csCaption); m_ctlVolume.SetRange(0, MAX_REL_VOLUME); if(m_pCall) m_ctlVolume.SetPos((int) ((MAX_REL_VOLUME * (int) (m_pCall->GetWaveVolume()))/MAX_ABS_VOLUME)); else m_ctlVolume.SetPos(MAX_REL_VOLUME); SetTimer(CALLINFO_TIMER_ID, 2000, NULL); DisplayCallInfo(TRUE); UpdateDigitsMonitorStatus(TRUE, 0, 0); // get monitoring & gathering result from the status structure if(m_pCall) { m_pCall->m_hStatusWnd = m_hWnd; // register self to the pCall m_pCall->m_hCallAlertWnd = m_btnCallAlert.GetSafeHwnd(); // register self to the pCall m_pCall->m_dwCallAlert = IDC_CALLALERT; m_pCall->m_uiAlertMsg = m_uiMsg; } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CCallInfo::OnPlay() { long lrc; if(m_pWaveName == NULL || m_pWaveName->IsEmpty()) { AfxMessageBox("No file to play"); return; } if(m_pCall) { SetTimer(WAVE_TIMER_ID, 500, NULL); if(WAVE_DISFUNCTIONAL == m_pCall->GetWaveStatus()) // use devspecific { lrc = m_pCall->PlayEx(m_pWaveName->GetBuffer(128)); if(lrc < 0) AfxMessageBox("Failed to start playing"); } else m_pCall->Play(m_pWaveName->GetBuffer(128)); } DisplayCallInfo(); } void CCallInfo::OnRecord() { if(m_pCall) { if(*m_pnWaveFormatID == 0 ) m_nRecTime = *m_pdwRecFileSize/3000; else if(*m_pnWaveFormatID == 1 ) m_nRecTime = *m_pdwRecFileSize/4000; else if(*m_pnWaveFormatID == 2 || *m_pnWaveFormatID == 5 || *m_pnWaveFormatID == 8) m_nRecTime = *m_pdwRecFileSize/6000; else if(*m_pnWaveFormatID == 3 || *m_pnWaveFormatID == 6 || *m_pnWaveFormatID == 9) m_nRecTime = *m_pdwRecFileSize/8000; else m_nRecTime = *m_pdwRecFileSize/11000; SetTimer(WAVE_TIMER_ID, 1000, NULL); if(WAVE_DISFUNCTIONAL == m_pCall->GetWaveStatus()) // use devspecific { if(m_pWaveRecName->IsEmpty()) m_pWaveRecName->Format("%s","C:\\WINNT35\\SYSTEM32\\TESTREC.WAV"); TRACE("Recording into %s\n", m_pWaveRecName->GetBuffer(120)); m_pCall->RecordEx(m_pWaveRecName->GetBuffer(120), m_nRecTime, *m_pnWaveFormatID); } else m_pCall->Record(*m_pnWaveFormatID, *m_pdwRecFileSize); } DisplayCallInfo(); } void CCallInfo::OnRefresh() { DisplayCallInfo(TRUE); // update=FALSE by default } void CCallInfo::OnClose() { KillTimer(CALLINFO_TIMER_ID); CPropertyPage::OnClose(); } void CCallInfo::OnTimer(UINT nIDEvent) { //if(nIDEvent == CALLINFO_TIMER_ID && !m_nRecTime) DisplayCallInfo(TRUE); if(nIDEvent == WAVE_TIMER_ID) { if(m_nRecTime >1) m_nRecTime -=1; else m_nRecTime = 0; DisplayCallInfo(); } CPropertyPage::OnTimer(nIDEvent); } // Get call info void CCallInfo::OnInfobtn() { CString csTemp; m_csCallInfo.Empty(); LPLINECALLINFO lpLCI = ((CTalkApp *)AfxGetApp())->GetCallInfo(m_pCall->m_hCall); if(lpLCI == NULL) return; // failed for some reason csTemp.Format("hLine = %lx\r\ndwLineDeviceID = %d\r\ndwBearerMode = %lx\r\n", lpLCI->hLine, lpLCI->dwLineDeviceID, lpLCI->dwBearerMode); m_csCallInfo += csTemp; csTemp.Format("dwMediaMode = %lx\r\ndwCallStates = %lx\r\ndwMonitorDigitModes = %lx\r\nCallerID flags = %lx\r\nCalledID flags = %lx\r\n", lpLCI->dwMediaMode, lpLCI->dwCallStates, lpLCI->dwMonitorDigitModes,lpLCI->dwCallerIDFlags,lpLCI->dwCalledIDFlags); m_csCallInfo += csTemp; if (lpLCI->dwCallerIDFlags & LINECALLPARTYID_NAME && lpLCI->dwCallerIDNameSize) { csTemp.Format("Caller name=%s\r\n",(LPSTR)(((LPSTR)(lpLCI))+lpLCI->dwCallerIDNameOffset)); m_csCallInfo += csTemp; } if (lpLCI->dwCallerIDFlags & LINECALLPARTYID_ADDRESS && lpLCI->dwCallerIDSize) { csTemp.Format("Caller number=%s\r\n", (LPSTR)(((LPSTR)(lpLCI))+lpLCI->dwCallerIDOffset)); m_csCallInfo += csTemp; } UpdateData(FALSE); delete (PBYTE) lpLCI; } void CCallInfo::OnMonitor() { LONG lrc; CString csTemp; HCALL hCall; if(m_pCall) hCall = m_pCall->m_hCall; // protect this m_btnMonitor.GetWindowText(csTemp); if(!csTemp.CompareNoCase("Monitor Digits")) // currently not monitoring { lrc = m_pCall->MonitorDigits(LINEDIGITMODE_DTMF); if(!lrc) m_btnMonitor.SetWindowText("Stop Monitor"); } else { lrc = m_pCall->MonitorDigits(0); m_btnMonitor.SetWindowText("Monitor Digits"); } } void CCallInfo::OnDestroy() { CPropertyPage::OnDestroy(); if(m_pCall) { m_pCall->m_hStatusWnd = NULL; m_pCall->m_hCallAlertWnd = NULL; m_pCall->m_dwCallAlert = NULL; m_pCall->m_uiAlertMsg = m_uiMsg; } } // Alert message w/o parameters void CCallInfo::OnCallalert() { UpdateDigitsMonitorStatus(TRUE); // get monitoring & gathering result } // Alert message w/parameters LONG CCallInfo::OnDynamicAlert(UINT wParam, LONG lParam) { if(!wParam) // gather result UpdateDigitsMonitorStatus(TRUE, 0, lParam); // get gathering result else UpdateDigitsMonitorStatus(FALSE, wParam, lParam); // get monitoring result return 0; } void CCallInfo::OnGather() { CString csTemp; LONG lrc; char szErr[48]; if(m_pCall == NULL) return; m_btnGather.GetWindowText(csTemp); if(!csTemp.CompareNoCase("Gather Digits")) // currently not gathering { m_csGathered.Empty(); m_csGatherRes.Empty(); UpdateData(FALSE); lrc = m_pCall->GatherDigits(20, "*#", 10000, 5000, NULL); if(lrc) { if(!((CTalkApp *)AfxGetApp())->Code2Error(lrc, szErr, 46)) csTemp.Format("lineGatherDigits failed reason=%lx", lrc); else csTemp.Format("lineGatherDigits failed reason=%s", szErr); AfxMessageBox(csTemp); } else m_btnGather.SetWindowText("Stop Gather"); } else // user said stop { lrc = m_pCall->GatherDigits(0, "", 0, 0, NULL); if(lrc) { if(!((CTalkApp *)AfxGetApp())->Code2Error(lrc, szErr, 46)) csTemp.Format("attempt to cancel lineGatherDigits failed reason=%lx", lrc); else csTemp.Format("attempt to cancel lineGatherDigits failed reason=%s", szErr); AfxMessageBox(csTemp); } // else m_btnGather.SetWindowText("Gather Digits"); // consider it done... } } void CCallInfo::OnPause() { if(!m_pCall) return; DWORD dwWaveStatus = m_pCall->GetWaveStatus(); if(dwWaveStatus == PLAYING) m_pCall->Pause(); else if(dwWaveStatus == PAUSED) m_pCall->Resume(); DisplayCallInfo(); } void CCallInfo::OnStop() { m_pCall->StopWave(); DisplayCallInfo(); } void CCallInfo::OnSetFocus(CWnd* pOldWnd) { CPropertyPage::OnSetFocus(pOldWnd); ((CTalkApp *)AfxGetApp())->SetHelpId(HIDD_TALKER32_DialogCallInfo); } void CCallInfo::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { int nP; if(nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK) nP = nPos; else nP = m_ctlVolume.GetPos(); if(m_pCall) m_pCall->SetWaveVolume((DWORD) ((MAX_ABS_VOLUME/MAX_REL_VOLUME) * nP)); CPropertyPage::OnHScroll(nSBCode, nPos, pScrollBar); } void CCallInfo::OnGentone() { // display tone selection dialog CToneDlg dlg(this); //LPLINEGENERATETONE lplgT = NULL; dlg.m_bRunningOnNT = m_bRunningOnNT; if(IDCANCEL == dlg.DoModal()) return; if(dlg.m_bBeep) lineGenerateTone(m_pCall->m_hCall, LINETONEMODE_BEEP, dlg.m_dwDur, 0, 0); else { LINEGENERATETONE lgt[2]; DWORD dwNum = 1; LONG lrc; // lplgT = (LPLINEGENERATETONE)new char[200*sizeof(LINEGENERATETONE)]; // if(!lplgT) return; lgt[0].dwFrequency = dlg.m_dwF1; lgt[0].dwVolume = dlg.m_dwA1; lgt[0].dwCadenceOn = dlg.m_dwDur/2; lgt[0].dwCadenceOff = dlg.m_dwDur/2; if(dlg.m_dwF2) { lgt[1].dwFrequency = dlg.m_dwF2; lgt[1].dwVolume = dlg.m_dwA2; lgt[1].dwCadenceOn = dlg.m_dwDur/2; lgt[1].dwCadenceOff = dlg.m_dwDur/2; dwNum++; } if(lrc = lineGenerateTone(m_pCall->m_hCall, LINETONEMODE_CUSTOM, dlg.m_dwDur, dwNum, lgt)) { CString csTemp; csTemp.Format("lineGenerateTone failed rc=%lx", lrc); AfxMessageBox(csTemp); } // if(lplgT) delete lplgT; } } /* #define SB_LINEUP 0 #define SB_LINELEFT 0 #define SB_LINEDOWN 1 #define SB_LINERIGHT 1 #define SB_PAGEUP 2 #define SB_PAGELEFT 2 #define SB_PAGEDOWN 3 #define SB_PAGERIGHT 3 #define SB_THUMBPOSITION 4 #define SB_THUMBTRACK 5 #define SB_TOP 6 #define SB_LEFT 6 #define SB_BOTTOM 7 #define SB_RIGHT 7 #define SB_ENDSCROLL 8 */