Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

489 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. rcacall.cpp
  5. Abstract:
  6. This module contains implementation of CRCAMSPCall.
  7. Author:
  8. Zoltan Szilagyi (zoltans) September 7, 1998
  9. --*/
  10. #include "stdafx.h"
  11. ///////////////////////////////////////////////////////////////////////////////
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //
  14. CRCAMSPCall::CRCAMSPCall() : CMSPCallMultiGraph()
  15. {
  16. LOG((MSP_TRACE, "CRCAMSPCall::CRCAMSPCall entered."));
  17. m_pRenderStream = NULL;
  18. m_pCaptureStream = NULL;
  19. LOG((MSP_TRACE, "CRCAMSPCall::CRCAMSPCall exited."));
  20. }
  21. ///////////////////////////////////////////////////////////////////////////////
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. CRCAMSPCall::~CRCAMSPCall()
  25. {
  26. LOG((MSP_TRACE, "CRCAMSPCall::~CRCAMSPCall entered."));
  27. LOG((MSP_TRACE, "CRCAMSPCall::~CRCAMSPCall exited."));
  28. }
  29. ULONG CRCAMSPCall::MSPCallAddRef(void)
  30. {
  31. return MSPAddRefHelper(this);
  32. }
  33. ULONG CRCAMSPCall::MSPCallRelease(void)
  34. {
  35. return MSPReleaseHelper(this);
  36. }
  37. ///////////////////////////////////////////////////////////////////////////////
  38. ///////////////////////////////////////////////////////////////////////////////
  39. //
  40. HRESULT CRCAMSPCall::Init(
  41. IN CMSPAddress * pMSPAddress,
  42. IN MSP_HANDLE htCall,
  43. IN DWORD dwReserved,
  44. IN DWORD dwMediaType
  45. )
  46. {
  47. // No need to acquire locks on this call because it is called only
  48. // once when the object is created. No other calls can be made on
  49. // this object at this point.
  50. LOG((MSP_TRACE, "CRCAMSPCall::Init - enter"));
  51. //
  52. // First do the base class method. We are adding to the functionality,
  53. // not replacing it.
  54. //
  55. HRESULT hr;
  56. hr = CMSPCallMultiGraph::Init(pMSPAddress,
  57. htCall,
  58. dwReserved,
  59. dwMediaType);
  60. if (FAILED(hr))
  61. {
  62. LOG((MSP_ERROR, "CRCAMSPCall::Init - "
  63. "base class method failed: %x", hr));
  64. return hr;
  65. }
  66. //
  67. // Our calls always come with two streams. Create them now. Use the base class
  68. // methods, as our overriden methods (exposed to the user) purposely fail in order
  69. // to keep the user from creating or removing streams themselves.
  70. // These methods return a pointer to the ITStream. They get saved in our list of
  71. // ITStreams, and we also save them here as CRCAMSPStream pointers.
  72. //
  73. ITStream * pStream;
  74. //
  75. // Create the capture stream.
  76. //
  77. hr = InternalCreateStream (dwMediaType,
  78. TD_CAPTURE,
  79. &pStream);
  80. if (FAILED(hr))
  81. {
  82. LOG((MSP_ERROR, "CRCAMSPCall::Init - "
  83. "couldn't create capture stream: %x", hr));
  84. return hr;
  85. }
  86. m_pCaptureStream = dynamic_cast<CRCAMSPStream *> (pStream);
  87. if ( m_pCaptureStream == NULL )
  88. {
  89. LOG((MSP_ERROR, "CRCAMSPCall::Init - "
  90. "couldn't dynamic_cast capture stream - exit E_FAIL"));
  91. return E_FAIL;
  92. }
  93. pStream->Release();
  94. //
  95. // Create the render stream.
  96. //
  97. hr = InternalCreateStream (dwMediaType,
  98. TD_RENDER,
  99. &pStream);
  100. if (FAILED(hr))
  101. {
  102. LOG((MSP_ERROR, "CRCAMSPCall::Init - "
  103. "couldn't create capture stream: %x", hr));
  104. return hr;
  105. }
  106. m_pRenderStream = dynamic_cast<CRCAMSPStream *> (pStream);
  107. if ( m_pRenderStream == NULL )
  108. {
  109. LOG((MSP_ERROR, "CRCAMSPCall::Init - "
  110. "couldn't dynamic_cast render stream - exit E_FAIL"));
  111. return E_FAIL;
  112. }
  113. pStream->Release();
  114. LOG((MSP_TRACE, "CRCAMSPCall::Init - exit S_OK"));
  115. return S_OK;
  116. }
  117. ///////////////////////////////////////////////////////////////////////////////
  118. ///////////////////////////////////////////////////////////////////////////////
  119. //
  120. // We override this to make sure the number of
  121. // streams we have is constant.
  122. //
  123. STDMETHODIMP CRCAMSPCall::CreateStream (
  124. IN long lMediaType,
  125. IN TERMINAL_DIRECTION Direction,
  126. IN OUT ITStream ** ppStream
  127. )
  128. {
  129. LOG((MSP_TRACE, "CRCAMSPCall::CreateStream entered."));
  130. LOG((MSP_TRACE, "CRCAMSPCall::CreateStream - "
  131. "we have a fixed set of streams - exit TAPI_E_MAXSTREAMS"));
  132. return TAPI_E_MAXSTREAMS;
  133. }
  134. ///////////////////////////////////////////////////////////////////////////////
  135. ///////////////////////////////////////////////////////////////////////////////
  136. //
  137. // We override this to make sure the number of
  138. // streams we have is constant.
  139. //
  140. STDMETHODIMP CRCAMSPCall::RemoveStream (
  141. IN ITStream * pStream
  142. )
  143. {
  144. LOG((MSP_TRACE, "CRCAMSPCall::RemoveStream entered."));
  145. LOG((MSP_TRACE, "CRCAMSPCall::RemoveStream - "
  146. "we have a fixed set of streams - exit TAPI_E_NOTSUPPORTED"));
  147. return TAPI_E_NOTSUPPORTED;
  148. }
  149. ///////////////////////////////////////////////////////////////////////////////
  150. ///////////////////////////////////////////////////////////////////////////////
  151. //
  152. // This is our override to create the right kind of stream on stream creation.
  153. // The base class checks the arguments for us.
  154. //
  155. HRESULT CRCAMSPCall::CreateStreamObject(
  156. IN DWORD dwMediaType,
  157. IN TERMINAL_DIRECTION Direction,
  158. IN IMediaEvent * pGraph,
  159. IN ITStream ** ppStream
  160. )
  161. {
  162. LOG((MSP_TRACE, "CRCAMSPCall::CreateStreamObject - enter"));
  163. HRESULT hr;
  164. CMSPComObject<CRCAMSPStream> * pStream;
  165. hr = CMSPComObject<CRCAMSPStream>::CreateInstance( &pStream );
  166. if ( FAILED(hr) )
  167. {
  168. LOG((MSP_ERROR, "CRCAMSPCall::CreateStreamObject - "
  169. "can't create stream object - 0x%08x", hr));
  170. return hr;
  171. }
  172. hr = pStream->_InternalQueryInterface( IID_ITStream,
  173. (void **) ppStream );
  174. if ( FAILED(hr) )
  175. {
  176. LOG((MSP_ERROR, "CRCAMSPCall::CreateStreamObject - "
  177. "can't get ITStream interface - 0x%08x", hr));
  178. delete pStream;
  179. return hr;
  180. }
  181. hr = pStream->Init( (MSP_HANDLE) m_pMSPAddress,
  182. this,
  183. pGraph,
  184. dwMediaType,
  185. Direction);
  186. if ( FAILED(hr) )
  187. {
  188. LOG((MSP_ERROR, "CRCAMSPCall::CreateStreamObject - "
  189. "can't Init stream object - 0x%08x", hr));
  190. (*ppStream)->Release();
  191. return hr;
  192. }
  193. LOG((MSP_TRACE, "CRCAMSPCall::CreateStreamObject - exit S_OK"));
  194. return S_OK;
  195. }
  196. ///////////////////////////////////////////////////////////////////////////////
  197. ///////////////////////////////////////////////////////////////////////////////
  198. //
  199. // First DWORD = Command Second DWORD Reply needed?
  200. // ------------- ------- ------------ -------------
  201. // 0 Set VC handle VC handle no
  202. // 1 Start streaming <ignored> no
  203. // 2 Stop streaming <ignored> no
  204. // 3 Are you there? <ignored> yes
  205. //
  206. // The method returns S_OK even if an individual stream failed to
  207. // start, stop, or initialize. We generate events to note these
  208. // failures.
  209. //
  210. HRESULT CRCAMSPCall::ReceiveTSPCallData(
  211. IN PBYTE pBuffer,
  212. IN DWORD dwSize
  213. )
  214. {
  215. LOG((MSP_TRACE, "CRCAMSPCall::ReceiveTSPCallData - enter"));
  216. //
  217. // Check that the buffer is as big as advertised.
  218. //
  219. if ( IsBadWritePtr(pBuffer, sizeof(BYTE) * dwSize) )
  220. {
  221. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  222. "bad buffer - exit E_POINTER"));
  223. return E_POINTER;
  224. }
  225. //
  226. // Check if we have a command DWORD.
  227. //
  228. if ( dwSize < sizeof(DWORD) )
  229. {
  230. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  231. "need a DWORD for command - exit E_INVALIDARG"));
  232. return E_INVALIDARG;
  233. }
  234. //
  235. // We are going to access the streams lists -- grab the lock
  236. //
  237. CLock lock(m_lock);
  238. _ASSERTE( m_Streams.GetSize() == 2 );
  239. int i;
  240. HRESULT hr;
  241. //
  242. // Based on the command, take action:
  243. //
  244. switch ( ((DWORD *) pBuffer) [0] )
  245. {
  246. case 0: // set the VC handle
  247. {
  248. if ( dwSize < 2 * sizeof(DWORD) )
  249. {
  250. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  251. "need another DWORD for VC handle - exit E_INVALIDARG"));
  252. return E_INVALIDARG;
  253. }
  254. LOG((MSP_INFO, "CRCAMSPCall::ReceiveTSPCallData - "
  255. "setting VCHandle=%d", ((DWORD *) pBuffer) [1]));
  256. //
  257. // Use our saved class pointers to access the private method,
  258. // and also to conveniently differentiate between render and
  259. // capture. Note that the capture stream is the one with a
  260. // capture terminal, and thus we need to give it the wave out id,
  261. // and we need to give the render terminal the wave in ID.
  262. //
  263. hr = m_pRenderStream ->SetVCHandle( ((DWORD *) pBuffer) [1] );
  264. if ( FAILED(hr) )
  265. {
  266. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  267. "render stream SetVCHandle failed 0x%08x - "
  268. "firing CALL_STREAM_FAIL", hr));
  269. m_pRenderStream->FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_UNKNOWN);
  270. }
  271. hr = m_pCaptureStream->SetVCHandle( ((DWORD *) pBuffer) [1] );
  272. if ( FAILED(hr) )
  273. {
  274. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  275. "capture stream SetVCHandle failed 0x%08x - "
  276. "firing CALL_STREAM_FAIL", hr));
  277. m_pCaptureStream->FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_UNKNOWN);
  278. }
  279. }
  280. break;
  281. case 1: // start streaming
  282. {
  283. for ( i = 0; i < m_Streams.GetSize(); i++ )
  284. {
  285. hr = m_Streams[i]->StartStream();
  286. }
  287. }
  288. break;
  289. case 2: // stop streaming
  290. {
  291. for ( i = 0; i < m_Streams.GetSize(); i++ )
  292. {
  293. hr = m_Streams[i]->StopStream();
  294. }
  295. }
  296. break;
  297. case 3: // Are you there?
  298. {
  299. //
  300. // "Are you there?" Must reply to indicate we are here.
  301. // Create the event structure.
  302. //
  303. // Note:
  304. //
  305. // the size of the allocated memory =
  306. //
  307. // sizeof(LIST_ENTRY)
  308. //
  309. // +
  310. //
  311. // sizeof(MSP_EVENT_INFO) (LIST_ENTRY and MSP_EVENT_INFO make a
  312. // MSPEVENTITEM structure)
  313. // +
  314. //
  315. // sizeof(DWORD) (for the one-DWORD buffer following the
  316. // variable-size MSP_EVENT_INFO structure)
  317. //
  318. MSPEVENTITEM * pEventItem = AllocateEventItem( sizeof(DWORD) );
  319. if ( pEventItem == NULL )
  320. {
  321. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  322. "can't create MSPEVENTITEM structure - exit E_OUTOFMEMORY"));
  323. return E_OUTOFMEMORY;
  324. }
  325. //
  326. // Fill in the necessary fields for the event structure.
  327. // Messages we send to our TSP consist of at least a single DWORD
  328. // for the opcode. (Similar to tsp->msp messages.) In this case
  329. // we just have the opcode zero and no other data.
  330. //
  331. // please send to tsp
  332. pEventItem->MSPEventInfo.Event = ME_TSP_DATA;
  333. // pertains to this call handle
  334. pEventItem->MSPEventInfo.hCall = m_htCall;
  335. // size of event structure
  336. pEventItem->MSPEventInfo.dwSize = sizeof(MSP_EVENT_INFO) +
  337. sizeof(DWORD);
  338. // size of opaque buffer within event structure
  339. pEventItem->MSPEventInfo.MSP_TSP_DATA.dwBufferSize = sizeof(DWORD);
  340. // contents of opaque buffer within event structure
  341. ((DWORD *) pEventItem->MSPEventInfo.MSP_TSP_DATA.pBuffer)[0] = 0;
  342. //
  343. // Send the event to the TSP.
  344. //
  345. hr = m_pMSPAddress->PostEvent(pEventItem);
  346. if ( FAILED(hr) )
  347. {
  348. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  349. "PostEvent failed - returning 0x%08x", hr));
  350. FreeEventItem(pEventItem);
  351. return hr;
  352. }
  353. }
  354. break;
  355. default:
  356. LOG((MSP_ERROR, "CRCAMSPCall::ReceiveTSPCallData - "
  357. "invalid command - exit E_INVALIDARG"));
  358. return E_INVALIDARG;
  359. }
  360. LOG((MSP_TRACE, "CRCAMSPCall::ReceiveTSPCallData - exit S_OK"));
  361. return S_OK;
  362. }
  363. //////////////////////////////////////////////////////////////////////////////
  364. //////////////////////////////////////////////////////////////////////////////
  365. //
  366. // UseMulaw
  367. //
  368. // Helper function called when we need to decide if to use Mulaw or Alaw.
  369. // This is simply delegated to the address.
  370. //
  371. BOOL CRCAMSPCall::UseMulaw( void )
  372. {
  373. return ( (CRCAMSP *) m_pMSPAddress )->UseMulaw();
  374. }
  375. // eof