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.

362 lines
10 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dvclient.c
  6. * Content: Implements functions for the DirectXVoiceClient interface
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/02/99 rodtoll Created It
  12. * 07/26/99 rodtoll Updated QueryInterface to support IDirectXVoiceNotify
  13. * 08/25/99 rodtoll General Cleanup/Modifications to support new
  14. * compression sub-system.
  15. * Added new parameter to GetCompressionTypes
  16. * 09/03/99 rodtoll Updated parameters for DeleteUserBuffer
  17. * 09/07/99 rodtoll Updated EnumCompressionTypes so that object doesn't
  18. * need to be Initialized.
  19. * 09/10/99 rodtoll Object validity checking
  20. * 09/14/99 rodtoll Added DVC_SetNotifyMask
  21. * 10/05/99 rodtoll Reversed destruction order to destroy object before
  22. * transport. Fixes crash in some situations
  23. * 10/18/99 rodtoll Fix: Passing NULL in QueryInterface casues crash
  24. * rodtoll Fix: Calling Initialize twice passes
  25. * 10/19/99 rodtoll Fix: Bug #113904 - Shutdown issues
  26. * - Added reference count for notify interface, allows
  27. * determination if disconnect should be called from release
  28. * 10/25/99 rodtoll Fix: Bug #114098 - Release/Addref failure from multiple threads
  29. * 11/17/99 rodtoll Fix: Bug #117447 - Removed checks for initialization because
  30. * DirectVoiceCLientEngine members already do this.
  31. * 12/16/99 rodtoll Bug #117405 - 3D Sound APIs misleading - 3d sound apis renamed
  32. * The Delete3DSoundBuffer was re-worked to match the create
  33. * 01/14/2000 rodtoll Updated parameters to Get/SetTransmitTargets
  34. * rodtoll Added new API call GetSoundDeviceConfig
  35. * 01/27/2000 rodtoll Bug #129934 - Update Create3DSoundBuffer to take DSBUFFERDESC
  36. * 03/28/2000 rodtoll Removed reference to removed header file.
  37. * 06/21/2000 rodtoll Bug #35767 - Update Create3DSoundBuffer to take DIRECTSOUNDBUFFERs
  38. * 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE!
  39. * 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
  40. *
  41. ***************************************************************************/
  42. #include "dxvoicepch.h"
  43. #undef DPF_MODNAME
  44. #define DPF_MODNAME "DVC_Release"
  45. STDAPI DVC_Release(LPDIRECTVOICECLIENTOBJECT lpDV )
  46. {
  47. HRESULT hr=S_OK;
  48. LONG rc;
  49. if( !DV_ValidDirectXVoiceClientObject( lpDV ) )
  50. return DVERR_INVALIDOBJECT;
  51. DNEnterCriticalSection( &lpDV->csCountLock );
  52. if (lpDV->lIntRefCnt == 0)
  53. {
  54. DNLeaveCriticalSection( &lpDV->csCountLock );
  55. return 0;
  56. }
  57. // dec the interface count
  58. lpDV->lIntRefCnt--;
  59. // Special case: Releasing object without stopping session
  60. // May be more then one transport thread indicating in us
  61. if( (lpDV->lIntRefCnt == 0) && lpDV->lpDVClientEngine->GetCurrentState() != DVCSTATE_IDLE )
  62. {
  63. DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing interface without calling Disconnect" );
  64. lpDV->lIntRefCnt = 0;
  65. // We must release the lock because stopsession may call back into this function
  66. DNLeaveCriticalSection( &lpDV->csCountLock );
  67. hr = lpDV->lpDVClientEngine->Disconnect( DVFLAGS_SYNC );
  68. DNEnterCriticalSection( &lpDV->csCountLock );
  69. if( hr != DV_OK && hr != DVERR_SESSIONLOST )
  70. {
  71. DPFX(DPFPREP, DVF_INFOLEVEL, "Disconnect Failed hr=0x%x", hr );
  72. }
  73. }
  74. rc = lpDV->lIntRefCnt;
  75. if ( lpDV->lIntRefCnt == 0 )
  76. {
  77. // Leave the critical section, we may call back into this func.
  78. // (Shouldn't though).
  79. DNLeaveCriticalSection( &lpDV->csCountLock );
  80. delete lpDV->lpDVClientEngine;
  81. lpDV->lpDVClientEngine = NULL;
  82. if( lpDV->lpDVTransport != 0 )
  83. {
  84. DNASSERT( lpDV->lpDVTransport->m_lRefCount == 0 );
  85. delete lpDV->lpDVTransport;
  86. lpDV->lpDVTransport = NULL;
  87. }
  88. DNDeleteCriticalSection( &lpDV->csCountLock );
  89. DNFree(lpDV);
  90. DecrementObjectCount();
  91. }
  92. else
  93. {
  94. DNLeaveCriticalSection( &lpDV->csCountLock );
  95. }
  96. return rc;
  97. }
  98. #undef DPF_MODNAME
  99. #define DPF_MODNAME "DVC_QueryInterface"
  100. STDMETHODIMP DVC_QueryInterface(LPDIRECTVOICECLIENTOBJECT lpDVC, REFIID riid, LPVOID * ppvObj)
  101. {
  102. HRESULT hr = S_OK;
  103. if( ppvObj == NULL ||
  104. !DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) )
  105. {
  106. DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" );
  107. return DVERR_INVALIDPOINTER;
  108. }
  109. *ppvObj=NULL;
  110. if( !DV_ValidDirectXVoiceClientObject( lpDVC ) )
  111. {
  112. return DVERR_INVALIDOBJECT;
  113. }
  114. // hmmm, switch would be cleaner...
  115. if( IsEqualIID(riid, IID_IUnknown) ||
  116. IsEqualIID(riid, IID_IDirectPlayVoiceClient ) )
  117. {
  118. *ppvObj = lpDVC;
  119. DV_AddRef(lpDVC);
  120. }
  121. else if( IsEqualIID(riid, IID_IDirectPlayVoiceNotify ) )
  122. {
  123. *ppvObj = &lpDVC->dvNotify;
  124. DV_Notify_AddRef(&lpDVC->dvNotify);
  125. }
  126. else
  127. {
  128. hr = E_NOINTERFACE;
  129. }
  130. return hr;
  131. }//DVC_QueryInterface
  132. #undef DPF_MODNAME
  133. #define DPF_MODNAME "DVC_Connect"
  134. STDMETHODIMP DVC_Connect(LPDIRECTVOICECLIENTOBJECT This, LPDVSOUNDDEVICECONFIG lpSoundDeviceConfig, LPDVCLIENTCONFIG lpClientConfig, DWORD dwFlags )
  135. {
  136. DNASSERT( This != NULL );
  137. DNASSERT( This->lpDVEngine != NULL );
  138. if( !DV_ValidDirectXVoiceClientObject( This ) )
  139. {
  140. return DVERR_INVALIDOBJECT;
  141. }
  142. return This->lpDVClientEngine->Connect( lpSoundDeviceConfig, lpClientConfig, dwFlags );
  143. }
  144. #undef DPF_MODNAME
  145. #define DPF_MODNAME "DVC_Disconnect"
  146. STDMETHODIMP DVC_Disconnect(LPDIRECTVOICECLIENTOBJECT This, DWORD dwFlags)
  147. {
  148. DNASSERT( This != NULL );
  149. DNASSERT( This->lpDVEngine != NULL );
  150. if( !DV_ValidDirectXVoiceClientObject( This ) )
  151. {
  152. return DVERR_INVALIDOBJECT;
  153. }
  154. return This->lpDVClientEngine->Disconnect( dwFlags );
  155. }
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "DVC_GetSessionDesc"
  158. STDMETHODIMP DVC_GetSessionDesc(LPDIRECTVOICECLIENTOBJECT This, LPDVSESSIONDESC lpSessionDesc )
  159. {
  160. DNASSERT( This != NULL );
  161. DNASSERT( This->lpDVEngine != NULL );
  162. if( !DV_ValidDirectXVoiceClientObject( This ) )
  163. {
  164. return DVERR_INVALIDOBJECT;
  165. }
  166. return This->lpDVClientEngine->GetSessionDesc( lpSessionDesc );
  167. }
  168. #undef DPF_MODNAME
  169. #define DPF_MODNAME "DVC_GetSoundDeviceConfig"
  170. STDAPI DVC_GetSoundDeviceConfig( LPDIRECTVOICECLIENTOBJECT This, PDVSOUNDDEVICECONFIG pSoundDeviceConfig, PDWORD pdwBufferSize )
  171. {
  172. DNASSERT( This != NULL );
  173. DNASSERT( This->lpDVEngine != NULL );
  174. if( !DV_ValidDirectXVoiceClientObject( This ) )
  175. {
  176. return DVERR_INVALIDOBJECT;
  177. }
  178. return This->lpDVClientEngine->GetSoundDeviceConfig( pSoundDeviceConfig, pdwBufferSize );
  179. }
  180. #undef DPF_MODNAME
  181. #define DPF_MODNAME "DVC_GetClientConfig"
  182. STDMETHODIMP DVC_GetClientConfig(LPDIRECTVOICECLIENTOBJECT This, LPDVCLIENTCONFIG lpClientConfig )
  183. {
  184. DNASSERT( This != NULL );
  185. DNASSERT( This->lpDVEngine != NULL );
  186. if( !DV_ValidDirectXVoiceClientObject( This ) )
  187. {
  188. return DVERR_INVALIDOBJECT;
  189. }
  190. return This->lpDVClientEngine->GetClientConfig( lpClientConfig );
  191. }
  192. #undef DPF_MODNAME
  193. #define DPF_MODNAME "DVC_SetClientConfig"
  194. STDMETHODIMP DVC_SetClientConfig(LPDIRECTVOICECLIENTOBJECT This, LPDVCLIENTCONFIG lpClientConfig )
  195. {
  196. DNASSERT( This != NULL );
  197. DNASSERT( This->lpDVEngine != NULL );
  198. if( !DV_ValidDirectXVoiceClientObject( This ) )
  199. {
  200. return DVERR_INVALIDOBJECT;
  201. }
  202. return This->lpDVClientEngine->SetClientConfig( lpClientConfig );
  203. }
  204. #undef DPF_MODNAME
  205. #define DPF_MODNAME "DVC_GetCaps"
  206. STDMETHODIMP DVC_GetCaps(LPDIRECTVOICECLIENTOBJECT This, LPDVCAPS lpdvCaps )
  207. {
  208. DNASSERT( This != NULL );
  209. DNASSERT( This->lpDVEngine != NULL );
  210. if( !DV_ValidDirectXVoiceClientObject( This ) )
  211. {
  212. return DVERR_INVALIDOBJECT;
  213. }
  214. return This->lpDVClientEngine->GetCaps( lpdvCaps );
  215. }
  216. #undef DPF_MODNAME
  217. #define DPF_MODNAME "DVC_GetCompressionTypes"
  218. STDMETHODIMP DVC_GetCompressionTypes( LPDIRECTVOICECLIENTOBJECT This, LPVOID lpDataBuffer, LPDWORD lpdwSize, LPDWORD lpdwNumElements, DWORD dwFlags)
  219. {
  220. DNASSERT( This != NULL );
  221. DNASSERT( This->lpDVEngine != NULL );
  222. if( !DV_ValidDirectXVoiceClientObject( This ) )
  223. {
  224. return DVERR_INVALIDOBJECT;
  225. }
  226. return This->lpDVClientEngine->GetCompressionTypes( lpDataBuffer, lpdwSize, lpdwNumElements, dwFlags );
  227. }
  228. #undef DPF_MODNAME
  229. #define DPF_MODNAME "DVC_SetTransmitTarget"
  230. STDMETHODIMP DVC_SetTransmitTarget( LPDIRECTVOICECLIENTOBJECT This, PDVID pdvidTargets, DWORD dwNumTargets, DWORD dwFlags )
  231. {
  232. DNASSERT( This != NULL );
  233. DNASSERT( This->lpDVEngine != NULL );
  234. if( !DV_ValidDirectXVoiceClientObject( This ) )
  235. {
  236. return DVERR_INVALIDOBJECT;
  237. }
  238. return This->lpDVClientEngine->SetTransmitTarget( pdvidTargets, dwNumTargets, dwFlags );
  239. }
  240. #undef DPF_MODNAME
  241. #define DPF_MODNAME "DVC_GetTransmitTarget"
  242. STDMETHODIMP DVC_GetTransmitTarget( LPDIRECTVOICECLIENTOBJECT This, LPDVID lpdvidTargets, PDWORD pdwNumElements, DWORD dwFlags )
  243. {
  244. DNASSERT( This != NULL );
  245. DNASSERT( This->lpDVEngine != NULL );
  246. if( !DV_ValidDirectXVoiceClientObject( This ) )
  247. {
  248. return DVERR_INVALIDOBJECT;
  249. }
  250. return This->lpDVClientEngine->GetTransmitTarget( lpdvidTargets, pdwNumElements, dwFlags );
  251. }
  252. #undef DPF_MODNAME
  253. #define DPF_MODNAME "DVC_Create3DSoundBuffer"
  254. STDMETHODIMP DVC_Create3DSoundBuffer( LPDIRECTVOICECLIENTOBJECT This, DVID dvidEntity, LPDIRECTSOUNDBUFFER lpdsBuffer, DWORD dwPriority, DWORD dwFlags, LPDIRECTSOUND3DBUFFER *lpSoundBuffer )
  255. {
  256. DNASSERT( This != NULL );
  257. DNASSERT( This->lpDVEngine != NULL );
  258. if( !DV_ValidDirectXVoiceClientObject( This ) )
  259. {
  260. return DVERR_INVALIDOBJECT;
  261. }
  262. return This->lpDVClientEngine->Create3DSoundBuffer( dvidEntity, lpdsBuffer, dwPriority, dwFlags, lpSoundBuffer );
  263. }
  264. #undef DPF_MODNAME
  265. #define DPF_MODNAME "DVC_Delete3DSoundBuffer"
  266. STDMETHODIMP DVC_Delete3DSoundBuffer( LPDIRECTVOICECLIENTOBJECT This, DVID dvidBuffer, LPDIRECTSOUND3DBUFFER *lpSoundBuffer )
  267. {
  268. DNASSERT( This != NULL );
  269. DNASSERT( This->lpDVEngine != NULL );
  270. if( !DV_ValidDirectXVoiceClientObject( This ) )
  271. {
  272. return DVERR_INVALIDOBJECT;
  273. }
  274. return This->lpDVClientEngine->Delete3DSoundBuffer( dvidBuffer, lpSoundBuffer );
  275. }
  276. #undef DPF_MODNAME
  277. #define DPF_MODNAME "DVC_SetNotifyMask"
  278. STDMETHODIMP DVC_SetNotifyMask( LPDIRECTVOICECLIENTOBJECT This, LPDWORD lpdwMessages, DWORD dwNumElements )
  279. {
  280. DNASSERT( This != NULL );
  281. DNASSERT( This->lpDVEngine != NULL );
  282. if( !DV_ValidDirectXVoiceClientObject( This ) )
  283. return DVERR_INVALIDOBJECT;
  284. return This->lpDVClientEngine->SetNotifyMask( lpdwMessages, dwNumElements );
  285. }