TAPICALL.CPP
上传用户:chinamans
上传日期:2013-03-17
资源大小:202k
文件大小:11k
源码类别:

TAPI编程

开发平台:

Visual C++

  1. // tapicall.cpp : implementation file for CTapiCall
  2. // (c) Dialogic corp 1995, 1996
  3. #include "stdafx.h"
  4. #include <tapi.h>
  5. #include "tapiapp.h"
  6. #include "tapiline.h"
  7. #include <mmsystem.h>
  8. #include "wavstate.h" 
  9. #include "wavex.h" 
  10. //#include "wavexg.h"
  11. #include "tapicall.h"
  12. #include "devspec.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char BASED_CODE THIS_FILE[] = __FILE__;
  16. #endif
  17. char g_szDigits[128];
  18. //static DWORD dwStateTrans[] = {MAKELONG(IDLE, MAKING), MAKELONG(MAKING, CONNECTED),
  19. // MAKELONG(MAKING, DROPPING), MAKELONG(CONNECTED, HOLD), MAKELONG(HOLD, CONNECTED),
  20. // MAKELONG(CONNECTED, DISCONNECTED), MAKELONG(HOLD, IDLE), MAKELONG(HOLD, DISCONNECTED), 
  21. // MAKELONG(CONNECTED, DROPPING), MAKELONG(HOLD, DROPPING)} 
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CTapiCall
  24. IMPLEMENT_DYNCREATE(CTapiCall, CObject)
  25. CTapiCall::CTapiCall()
  26. {
  27. m_pctLine = NULL;
  28. m_hCall = NULL;
  29.     m_CallState.wCallState = IDLE;
  30. m_CallState.wCallDirection = IDLE;
  31. m_CallState.dwTapiCallState = 0L;
  32. m_CallState.dwErrors = 0L;
  33. m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE");
  34. m_MonitorState.wState = IDLE;
  35. m_MonitorState.dwGatherResult = 0;
  36. m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR");
  37. m_pWave = NULL;
  38. m_hStatusWnd = NULL;
  39. m_hCallAlertWnd = NULL;
  40. m_dwCallAlert = NULL;
  41. }
  42.    
  43. CTapiCall::CTapiCall(HCALL hCall, CTapiLine *lpLine)
  44. {
  45. m_pctLine = lpLine;
  46. m_hCall = hCall;
  47.     m_CallState.wCallState = IDLE;
  48. m_CallState.wCallDirection = IDLE;
  49. m_CallState.dwTapiCallState = 0L;
  50. m_CallState.dwErrors = 0L;
  51. m_hStateSem = CreateMutex(NULL, FALSE, "TALKER32_CALL_STATE");
  52. m_MonitorState.dwGatherResult = 0;
  53. m_MonitorState.wState = IDLE;
  54. m_hMonitorStateSem = CreateMutex(NULL, FALSE, "TALKER32_DIGITS_MONITOR");
  55. m_pWave = NULL;
  56. m_hStatusWnd = NULL;
  57. m_hCallAlertWnd = NULL;
  58. m_dwCallAlert = NULL;
  59. }
  60. CTapiCall::~CTapiCall()
  61. {
  62. ResetWave();
  63. WaitForSingleObject(m_hMonitorStateSem, 2000);
  64. CloseHandle(m_hMonitorStateSem);
  65. }
  66. // verify & update the state
  67. BOOL CTapiCall::UpdateCallState(WORD wCallState, WORD wDirection, 
  68. DWORD dwTapiCallState, DWORD dwErrors)
  69. {
  70. // put some protection  & verification here
  71. TRACE("*** TALKER32 ***: UpdateCallState hCall=%lx state=%d TAPIstate=%lx entering wait for semn",
  72.  m_hCall, wCallState, dwTapiCallState);
  73. DWORD dwrc = WaitForSingleObject(m_hStateSem, 15000);
  74. if(dwrc != WAIT_OBJECT_0) 
  75. {
  76. TRACE("*** TALKER32 ***: Update Call state wait for sem failed rc=%lxn",dwrc);
  77. return FALSE;
  78. if(wCallState != 0xffff) m_CallState.wCallState = wCallState;   
  79. if(wDirection != 0xffff) m_CallState.wCallDirection = wDirection;
  80. if(dwTapiCallState != 0xffff) m_CallState.dwTapiCallState = dwTapiCallState;
  81. m_CallState.dwErrors |= dwErrors;
  82. TRACE("*** TALKER32 ***: UpdateCallState releasing mutexn");
  83. ReleaseMutex(m_hStateSem);
  84. return TRUE;
  85. }
  86. // Start or end monitoring
  87. LONG CTapiCall::MonitorDigits(DWORD dwMode)
  88. {
  89. LONG lrc = lineMonitorDigits(m_hCall, dwMode);
  90. if(lrc) return lrc;
  91. UpdateMonitorState(dwMode ? MONITOR_DIGITS:RESET_MONITOR_DIGITS, 0, 0); // start
  92. return lrc;
  93. }
  94. LONG CTapiCall::GatherDigits(DWORD dwNumDigits, LPCSTR lpszTermDigits, 
  95.      DWORD dwFirstDigitTimeout, DWORD dwInterDigitTimeout, LPSTR lpBuf)
  96. {
  97. LONG lrc;
  98. if(lpBuf == NULL) 
  99. {
  100. lpBuf = m_szDigits;   // default to internal buffer
  101. if(dwNumDigits >= sizeof(m_szDigits)) // safety is first!!!
  102. {
  103. AfxMessageBox("Number of digits requested is more than default buffer size, resetting to 31"); 
  104. dwNumDigits = sizeof(m_szDigits) - 1;
  105. }
  106. }
  107. if(!dwNumDigits)  // cancel current
  108. {
  109. TRACE("***: Cancelling Gather!!! n");
  110. return lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, NULL, 1, "", 100, 100);
  111. }
  112. //UpdateMonitorState(START_GATHER, 0, 0); // start
  113. TRACE("***: Calling Gather num=%d, Term=%s, buf=%lxn",dwNumDigits, lpszTermDigits, lpBuf);
  114. //memset(lpBuf, 0, dwNumDigits); // init buffer
  115. lrc = lineGatherDigits(m_hCall, LINEDIGITMODE_DTMF, lpBuf,
  116. dwNumDigits, lpszTermDigits,dwFirstDigitTimeout, dwInterDigitTimeout);
  117. if(lrc) return lrc;
  118. UpdateMonitorState(START_GATHER, 0, 0); // start
  119. return lrc;
  120. }
  121. // read the monitor state
  122. BOOL CTapiCall::GetMonitorState(PMONITORSTATE pMonState)
  123. {
  124. if(pMonState == NULL) return FALSE; //user-supplied 
  125. TRACE("*** TALKER32 ***: GetMonitorState hCall=%lx entering wait for semn", m_hCall);
  126. DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000);
  127. if(dwrc != WAIT_OBJECT_0) 
  128. {
  129. TRACE("*** TALKER32 ***: Get Monitor state wait for sem failed rc=%lxn",dwrc);
  130. return FALSE;
  131. }
  132. memcpy((LPBYTE)pMonState, (LPBYTE)&m_MonitorState, sizeof(MONITORSTATE)); //copy the whole thing
  133. TRACE("*** TALKER32 ***: GetMonitorState releasing mutex,state=%lxn",m_MonitorState.wState);
  134. ReleaseMutex(m_hMonitorStateSem);
  135. return TRUE;
  136. }
  137. // verify & update the state
  138. BOOL CTapiCall::UpdateMonitorState(WORD wType, DWORD dwDigit, DWORD dwMode)
  139. {
  140. // protection  & verification here
  141. TRACE("*** TALKER32 ***: UpdateMonitorState hCall=%lx old=%x new=%x entering wait for semn", m_hCall, m_MonitorState.wState,wType);
  142. DWORD dwrc = WaitForSingleObject(m_hMonitorStateSem, 5000);
  143. if(dwrc != WAIT_OBJECT_0) 
  144. {
  145. TRACE("*** TALKER32 ***: Update Monitor state wait for sem failed rc=%lxn",dwrc);
  146. return FALSE;
  147. }
  148. // Reset gather result if state is not gathering
  149. if(!(m_MonitorState.wState & START_GATHER))
  150. m_MonitorState.dwGatherResult = 0L;
  151.  
  152. if(wType & MONITOR_DIGITS) // a digit arrived; called from outside 
  153. {
  154. m_MonitorState.wState |= MONITOR_DIGITS; // confirm status
  155. m_MonitorState.wLastDigit = LOWORD(dwDigit); // record digit
  156. m_MonitorState.dwDigitMode = dwMode;  // record mode
  157. if(LOWORD(dwDigit)) m_MonitorState.wMonitorCount++; // unclaimed digits counter
  158. else m_MonitorState.wMonitorCount = 0;
  159. }
  160. else if(wType & RESET_MONITOR_DIGITS) // reset flag; called from inside
  161. {
  162. m_MonitorState.wState &= ~MONITOR_DIGITS; // reset
  163. m_MonitorState.dwDigitMode = 0L;
  164. m_MonitorState.wMonitorCount = 0;
  165. }
  166. if(wType & START_GATHER) // start, set flag reset result & buffer; from inside
  167. {
  168. m_MonitorState.wState |= START_GATHER;
  169. m_MonitorState.dwGatherResult = 0L;
  170. }
  171. else if(wType & END_GATHER_DIGITS) // end gather, reset flag & post result; from outside
  172. {
  173. m_MonitorState.wState &= ~START_GATHER;
  174. m_MonitorState.dwGatherResult = dwDigit;
  175. }
  176. else if(wType & RESET_GATHER_RESULT) // end gather, reset flag & post result; from outside
  177. {
  178. m_MonitorState.wState &= ~START_GATHER;
  179. m_MonitorState.dwGatherResult = 0L;
  180. }
  181. TRACE("*** TALKER32 ***: UpdateMonitorState releasing mutexn");
  182. ReleaseMutex(m_hMonitorStateSem);
  183. return TRUE;
  184. }
  185. // initialize WAVE functionality for the call 
  186. BOOL CTapiCall::InitWave()
  187. {
  188. if(m_pWave != NULL) return TRUE; // already done
  189. m_pWave = new CTapiWave((LPVOID) m_pctLine, (LPVOID)this, m_pctLine->ctlGetLineID());
  190. if(m_pWave == NULL) return FALSE;
  191. return TRUE;
  192. }
  193. // check WAVE state before deallocating
  194. BOOL CTapiCall::ResetWave()
  195. {
  196. if(m_pWave == NULL) return TRUE;
  197. if(IDLE != m_pWave->ctwGetState()) return FALSE; //can't do it yet
  198. delete m_pWave;
  199. return TRUE; 
  200. }
  201. BOOL CTapiCall::Play(LPSTR lpName)
  202. {
  203. if(m_pWave) return m_pWave->ctwPlay(AfxGetMainWnd()->GetSafeHwnd(), 
  204. m_pctLine->ctlGetWaveOutID(), lpName);
  205. //::WavexPlay(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), lpName);
  206. return FALSE;
  207. }
  208. // Pause playing
  209. BOOL CTapiCall::Pause()
  210. {
  211. if(m_pWave) return m_pWave->ctwPause();
  212. return FALSE;
  213. }
  214. // Resume paused playing
  215. BOOL CTapiCall::Resume()
  216. {
  217. if(m_pWave) return m_pWave->ctwResume();
  218. return FALSE;
  219. }
  220. // Stop whatever is going on
  221. BOOL CTapiCall::StopWave()
  222. {
  223. if(m_pWave) return m_pWave->ctwStop();
  224. DWORD dwStat = m_pctLine->ctlGetDevSpecStatus();
  225. if(dwStat != DEVSPEC_STARTING && dwStat != DEVSPEC_PROGRESS) return FALSE;
  226. DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc();
  227. if(dwFunc != PLAY_WAVE && dwFunc != RECORD_WAVE) return FALSE;
  228. if(dwFunc == PLAY_WAVE) 
  229. PlayEx(NULL);
  230. else if(dwFunc == RECORD_WAVE)
  231. RecordEx(NULL, 0);
  232. return TRUE;
  233. }
  234. BOOL CTapiCall::Record(int nFormatID, DWORD dwSize)
  235. {
  236. BOOL brc;
  237. if(m_pWave) 
  238. {
  239. brc = m_pWave->ctwRecord(AfxGetMainWnd()->GetSafeHwnd(), m_pctLine->ctlGetWaveOutID(), nFormatID, dwSize);
  240. TRACE("*** TALKER32 ***: Record returned %d, hWaveIn=%lxn", brc, m_pWave->ctwGetHWave(WAVEIN));
  241. return brc;
  242. }
  243. //::WavexRecord(AfxGetMainWnd()->GetSafeHwnd(), (UINT)m_pctLine->ctlGetWaveOutID());
  244. return FALSE;
  245. }
  246. DWORD CTapiCall::GetHWaveIn()
  247. {return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEIN);}
  248. DWORD CTapiCall::GetHWaveOut()
  249. {return m_pWave == NULL ? NULL : (DWORD)m_pWave->ctwGetHWave(WAVEOUT);}
  250. // Override this for MT implementation
  251. void CTapiCall::FinishPlay(WPARAM wParam, LPARAM lParam)
  252. {if(m_pWave != NULL) m_pWave->ctwFinishPlay(wParam, lParam);}
  253. //{::WavexFinishPlay(wParam, lParam);}
  254. // Override this for MT implementation
  255. void CTapiCall::FinishRecord(WPARAM wParam, LPARAM lParam, LPSTR lpName)
  256. {
  257. char szName[16];
  258. sprintf(szName, "record%.2d.wav", m_pctLine->ctlGetLineID());
  259. if(m_pWave != NULL) m_pWave->ctwFinishRecord(wParam, lParam, NULL);
  260. //::WavexFinishRecord(wParam, lParam, NULL);
  261. }
  262. DWORD CTapiCall::GetWaveStatus()
  263. {return m_pWave==NULL ? WAVE_DISFUNCTIONAL : m_pWave->ctwGetState();}
  264. void CTapiCall::SetWaveVolume(DWORD dwVol)
  265. {if(m_pWave != NULL) m_pWave->ctwSetVolume(dwVol);}
  266. DWORD CTapiCall::GetWaveVolume()
  267. {if(m_pWave != NULL) return m_pWave->ctwGetVolume(); return MAX_ABS_VOLUME;}
  268. // Play WAVE using LineDevSpec
  269. BOOL CTapiCall::PlayEx(LPCTSTR lpName)
  270. {
  271. DWORD dwSize; //= sizeof(DXXXDEVSPEC) + 2;
  272. if(lpName) dwSize = lstrlen(lpName)+16;
  273. else dwSize = 512;
  274. if(dwSize > 512) return FALSE;
  275. char szTemp[512];
  276. PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp;
  277. if(!pDS) return FALSE;
  278. pDS->dwCode = PLAY_WAVE;
  279. pDS->dwRecTime = 0;
  280. // a special way to stop: send the file name with 0 first char
  281. if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName); 
  282. else pDS->pbData[0] = 0;
  283. m_pctLine->ctlLineDevSpecific(PLAY_WAVE, 0, 0, (LPVOID)pDS, dwSize);
  284. return TRUE;
  285. }
  286. // Record WAVE using LineDevSpec
  287. BOOL CTapiCall::RecordEx(LPCTSTR lpName, DWORD dwRecTime, int nFormatID)
  288. {
  289. DWORD dwSize; // = sizeof(DXXXDEVSPEC) + 2;
  290. if(lpName) dwSize = lstrlen(lpName)+16;
  291. else dwSize = 512;
  292. if(dwSize > 512) return FALSE;
  293. char szTemp[512];
  294. PDXXXDEVSPEC pDS = (PDXXXDEVSPEC) szTemp;
  295. pDS->dwCode = RECORD_WAVE;
  296. pDS->dwRecTime = dwRecTime; //in seconds
  297. // a special way to stop: send the file name with 0 first char
  298. if(lpName) lstrcpy((LPSTR)&pDS->pbData[0], lpName); 
  299. else pDS->pbData[0] = 0;
  300. m_pctLine->ctlLineDevSpecific(RECORD_WAVE, 0, 0, (LPVOID)pDS, dwSize);
  301. return TRUE;
  302. }
  303. // if playing/recording using DevSpec, return the most current WAVE status
  304. DWORD CTapiCall::GetRecPlayStatus()
  305. {
  306. DWORD dwStat = m_pctLine->ctlGetDevSpecStatus();
  307. DWORD dwFunc = m_pctLine->ctlGetDevSpecFunc();
  308. switch(dwStat)
  309. {
  310. case DEVSPEC_SUCCESS:
  311. case DEVSPEC_IDLE:
  312. return WAVE_IDLE;
  313. case DEVSPEC_STARTING:
  314. return dwFunc == PLAY_WAVE ? PREPARING_TO_PLAY : PREPARING_TO_RECORD;
  315. case DEVSPEC_STARTFAILED:
  316. return FAILED_START;
  317. case DEVSPEC_PROGRESS:
  318. return dwFunc == PLAY_WAVE ? PLAYING : dwFunc == RECORD_WAVE ? RECORDING :WAVE_IDLE;
  319. case DEVSPEC_RESULTFAILED:
  320. return WAVE_FAILED;
  321. default:
  322. return WAVE_IDLE;
  323. }
  324. }