www.pudn.com > tapi3.zip > TAPICALL.CPP
// tapicall.cpp : implementation file for CTapiCall // (c) Dialogic corp 1995, 1996 #include "stdafx.h" #include#include "tapiapp.h" #include "tapiline.h" #include #include "wavstate.h" #include "wavex.h" //#include "wavexg.h" #include "tapicall.h" #include "devspec.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif char g_szDigits[128]; //static DWORD dwStateTrans[] = {MAKELONG(IDLE, MAKING), MAKELONG(MAKING, CONNECTED), // MAKELONG(MAKING, DROPPING), MAKELONG(CONNECTED, HOLD), MAKELONG(HOLD, CONNECTED), // MAKELONG(CONNECTED, DISCONNECTED), MAKELONG(HOLD, IDLE), MAKELONG(HOLD, DISCONNECTED), // MAKELONG(CONNECTED, DROPPING), MAKELONG(HOLD, DROPPING)} ///////////////////////////////////////////////////////////////////////////// // CTapiCall IMPLEMENT_DYNCREATE(CTapiCall, CObject) CTapiCall::CTapiCall() { m_pctLine = NULL; m_hCall = NULL; m_CallState.wCallState = IDLE; m_CallState.wCallDirection = IDLE; m_CallState.dwTapiCallState = 0L; m_CallState.dwErrors = 0L; m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE"); m_MonitorState.wState = IDLE; m_MonitorState.dwGatherResult = 0; m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR"); m_pWave = NULL; m_hStatusWnd = NULL; m_hCallAlertWnd = NULL; m_dwCallAlert = NULL; } CTapiCall::CTapiCall(HCALL hCall, CTapiLine *lpLine) { m_pctLine = lpLine; m_hCall = hCall; m_CallState.wCallState = IDLE; m_CallState.wCallDirection = IDLE; m_CallState.dwTapiCallState = 0L; m_CallState.dwErrors = 0L; m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE"); m_MonitorState.dwGatherResult = 0; m_MonitorState.wState = IDLE; m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR"); m_pWave = NULL; m_hStatusWnd = NULL; m_hCallAlertWnd = NULL; m_dwCallAlert = NULL; } CTapiCall::~CTapiCall() { ResetWave(); WaitForSingleObject(m_hMonitorStateSem, 2000); CloseHandle(m_hMonitorStateSem); } // verify & update the state BOOL CTapiCall::UpdateCallState(WORD wCallState, WORD wDirection, DWORD dwTapiCallState, DWORD dwErrors) { // put some protection & verification here TRACE("*** TALKER32 ***: UpdateCallState hCall=%lx state=%d TAPIstate=%lx entering wait for sem\n", m_hCall, wCallState, dwTapiCallState); DWORD dwrc = WaitForSingleObject(m_hStateSem, 15000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Update Call state wait for sem failed rc=%lx\n",dwrc); return FALSE; } if(wCallState != 0xffff) m_CallState.wCallState = wCallState; if(wDirection != 0xffff) m_CallState.wCallDirection = wDirection; if(dwTapiCallState != 0xffff) m_CallState.dwTapiCallState = dwTapiCallState; m_CallState.dwErrors |= dwErrors; TRACE("*** TALKER32 ***: UpdateCallState releasing mutex\n"); ReleaseMutex(m_hStateSem); return TRUE; } // Start or end monitoring LONG CTapiCall::MonitorDigits(DWORD dwMode) { LONG lrc = lineMonitorDigits(m_hCall, dwMode); if(lrc) return lrc; UpdateMonitorState(dwMode ? MONITOR_DIGITS:RESET_MONITOR_DIGITS, 0, 0); // start return lrc; } LONG CTapiCall::GatherDigits(DWORD dwNumDigits, LPCSTR lpszTermDigits, DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout, LPSTR lpBuf) { LONG lrc; if(lpBuf == NULL) { lpBuf = m_szDigits; // default to internal buffer if(dwNumDigits >= sizeof(m_szDigits)) // safety is first!!! { AfxMessageBox("Number of digits requested is more than default buffer size, resetting to 31"); dwNumDigits = sizeof(m_szDigits) - 1; } } if(!dwNumDigits) // cancel current { TRACE("***: Cancelling Gather!!! \n"); return lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, NULL, 1, "", 100, 100); } //UpdateMonitorState(START_GATHER, 0, 0); // start TRACE("***: Calling Gather num=%d, Term=%s, buf=%lx\n",dwNumDigits, lpszTermDigits, lpBuf); //memset(lpBuf, 0, dwNumDigits); // init buffer lrc = lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, lpBuf, dwNumDigits, lpszTermDigits,dwFirstDigitTimeout, dwInterDigitTimeout); if(lrc) return lrc; UpdateMonitorState(START_GATHER, 0, 0); // start return lrc; } // read the monitor state BOOL CTapiCall::GetMonitorState(PMONITORSTATE pMonState) { if(pMonState == NULL) return FALSE; //user-supplied TRACE("*** TALKER32 ***: GetMonitorState hCall=%lx entering wait for sem\n", m_hCall); DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Get Monitor state wait for sem failed rc=%lx\n",dwrc); return FALSE; } memcpy((LPBYTE)pMonState, (LPBYTE)&m_MonitorState, sizeof(MONITORSTATE)); //copy the whole thing TRACE("*** TALKER32 ***: GetMonitorState releasing mutex,state=%lx\n",m_MonitorState.wState); ReleaseMutex(m_hMonitorStateSem); return TRUE; } // verify & update the state BOOL CTapiCall::UpdateMonitorState(WORD wType, DWORD dwDigit, DWORD dwMode) { // protection & verification here TRACE("*** TALKER32 ***: UpdateMonitorState hCall=%lx old=%x new=%x entering wait for sem\n", m_hCall, m_MonitorState.wState,wType); DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Update Monitor state wait for sem failed rc=%lx\n",dwrc); return FALSE; } // Reset gather result if state is not gathering if(!(m_MonitorState.wState & START_GATHER)) m_MonitorState.dwGatherResult = 0L; if(wType & MONITOR_DIGITS) // a digit arrived; called from outside { m_MonitorState.wState |= MONITOR_DIGITS; // confirm status m_MonitorState.wLastDigit = LOWORD(dwDigit); // record digit m_MonitorState.dwDigitMode = dwMode; // record mode if(LOWORD(dwDigit)) m_MonitorState.wMonitorCount++; // unclaimed digits counter else m_MonitorState.wMonitorCount = 0; } else if(wType & RESET_MONITOR_DIGITS) // reset flag; called from inside { m_MonitorState.wState &= ~MONITOR_DIGITS; // reset m_MonitorState.dwDigitMode = 0L; m_MonitorState.wMonitorCount = 0; } if(wType & START_GATHER) // start, set flag reset result & buffer; from inside { m_MonitorState.wState |= START_GATHER; m_MonitorState.dwGatherResult = 0L; } else if(wType & END_GATHER_DIGITS) // end gather, reset flag & post result; from outside { m_MonitorState.wState &= ~START_GATHER; m_MonitorState.dwGatherResult = dwDigit; } else if(wType & RESET_GATHER_RESULT) // end gather, reset flag & post result; from outside { m_MonitorState.wState &= ~START_GATHER; m_MonitorState.dwGatherResult = 0L; } TRACE("*** TALKER32 ***: UpdateMonitorState releasing mutex\n"); ReleaseMutex(m_hMonitorStateSem); return TRUE; } // initialize WAVE functionality for the call BOOL CTapiCall::InitWave() { if(m_pWave != NULL) return TRUE; // already done m_pWave = new CTapiWave((LPVOID) m_pctLine, (LPVOID)this, m_pctLine->ctlGetLineID()); if(m_pWave == NULL) return FALSE; return TRUE; } // check WAVE state before deallocating BOOL CTapiCall::ResetWave() { if(m_pWave == NULL) return TRUE; if(IDLE != m_pWave->ctwGetState()) return FALSE; //can't do it yet delete m_pWave; return TRUE; } BOOL CTapiCall::Play(LPSTR lpName) { if(m_pWave) return m_pWave->ctwPlay(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), lpName); //::WavexPlay(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), lpName); return FALSE; } // Pause playing BOOL CTapiCall::Pause() { if(m_pWave) return m_pWave->ctwPause(); return FALSE; } // Resume paused playing BOOL CTapiCall::Resume() { if(m_pWave) return m_pWave->ctwResume(); return FALSE; } // Stop whatever is going on BOOL CTapiCall::StopWave() { if(m_pWave) return m_pWave->ctwStop(); DWORD dwStat = m_pctLine->ctlGetDevSpecStatus(); if(dwStat != DEVSPEC_STARTING && dwStat != DEVSPEC_PROGRESS) return FALSE; DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc(); if(dwFunc != PLAY_WAVE && dwFunc != RECORD_WAVE) return FALSE; if(dwFunc == PLAY_WAVE) PlayEx(NULL); else if(dwFunc == RECORD_WAVE) RecordEx(NULL, 0); return TRUE; } BOOL CTapiCall::Record(int nFormatID, DWORD dwSize) { BOOL brc; if(m_pWave) { brc = m_pWave->ctwRecord(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), nFormatID, dwSize); TRACE("*** TALKER32 ***: Record returned %d, hWaveIn=%lx\n", brc, m_pWave->ctwGetHWave(WAVEIN)); return brc; } //::WavexRecord(AfxGetMainWnd()->GetSafeHwnd(), (UINT)m_pctLine->ctlGetWaveOutID()); return FALSE; } DWORD CTapiCall::GetHWaveIn() {return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEIN);} DWORD CTapiCall::GetHWaveOut() {return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEOUT);} // Override this for MT implementation void CTapiCall::FinishPlay(WPARAM wParam, LPARAM lParam) {if(m_pWave != NULL) m_pWave->ctwFinishPlay(wParam, lParam);} //{::WavexFinishPlay(wParam, lParam);} // Override this for MT implementation void CTapiCall::FinishRecord(WPARAM wParam, LPARAM lParam, LPSTR lpName) { char szName[16]; sprintf(szName, "record%.2d.wav", m_pctLine->ctlGetLineID()); if(m_pWave != NULL) m_pWave->ctwFinishRecord(wParam, lParam, NULL); //::WavexFinishRecord(wParam, lParam, NULL); } DWORD CTapiCall::GetWaveStatus() {return m_pWave==NULL ? WAVE_DISFUNCTIONAL : m_pWave->ctwGetState();} void CTapiCall::SetWaveVolume(DWORD dwVol) {if(m_pWave != NULL) m_pWave->ctwSetVolume(dwVol);} DWORD CTapiCall::GetWaveVolume() {if(m_pWave != NULL) return m_pWave->ctwGetVolume(); return MAX_ABS_VOLUME;} // Play WAVE using LineDevSpec BOOL CTapiCall::PlayEx(LPCTSTR lpName) { DWORD dwSize; //= sizeof(DXXXDEVSPEC) + 2; if(lpName) dwSize = lstrlen(lpName)+16; else dwSize = 512; if(dwSize > 512) return FALSE; char szTemp[512]; PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp; if(!pDS) return FALSE; pDS->dwCode = PLAY_WAVE; pDS->dwRecTime = 0; // a special way to stop: send the file name with 0 first char if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName); else pDS->pbData[0] = 0; m_pctLine->ctlLineDevSpecific(PLAY_WAVE, 0, 0, (LPVOID)pDS, dwSize); return TRUE; } // Record WAVE using LineDevSpec BOOL CTapiCall::RecordEx(LPCTSTR lpName, DWORD dwRecTime, int nFormatID) { DWORD dwSize; // = sizeof(DXXXDEVSPEC) + 2; if(lpName) dwSize = lstrlen(lpName)+16; else dwSize = 512; if(dwSize > 512) return FALSE; char szTemp[512]; PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp; pDS->dwCode = RECORD_WAVE; pDS->dwRecTime = dwRecTime; //in seconds // a special way to stop: send the file name with 0 first char if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName); else pDS->pbData[0] = 0; m_pctLine->ctlLineDevSpecific(RECORD_WAVE, 0, 0, (LPVOID)pDS, dwSize); return TRUE; } // if playing/recording using DevSpec, return the most current WAVE status DWORD CTapiCall::GetRecPlayStatus() { DWORD dwStat = m_pctLine->ctlGetDevSpecStatus(); DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc(); switch(dwStat) { case DEVSPEC_SUCCESS: case DEVSPEC_IDLE: return WAVE_IDLE; case DEVSPEC_STARTING: return dwFunc == PLAY_WAVE ? PREPARING_TO_PLAY : PREPARING_TO_RECORD; case DEVSPEC_STARTFAILED: return FAILED_START; case DEVSPEC_PROGRESS: return dwFunc == PLAY_WAVE ? PLAYING : dwFunc == RECORD_WAVE ? RECORDING :WAVE_IDLE; case DEVSPEC_RESULTFAILED: return WAVE_FAILED; default: return WAVE_IDLE; } }