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.

936 lines
27 KiB

  1. #include "stdafx.h"
  2. #include "Direct.h"
  3. #include "dms.h"
  4. #include "dPlayVoiceClientObj.h"
  5. #include "dPlayVoiceServerObj.h"
  6. #include "dvoice.h"
  7. #include "dSound3DBuffer.h"
  8. extern void *g_dxj_DirectPlayVoiceClient;
  9. extern BSTR GUIDtoBSTR(LPGUID pGuid);
  10. extern HRESULT DPLAYBSTRtoGUID(LPGUID,BSTR);
  11. #define SAFE_DELETE(p) { if(p) { delete (p); p=NULL; } }
  12. #define SAFE_RELEASE(p) { __try { if(p) { DPF(1,"------ DXVB: SafeRelease About to call release:"); int i = 0; i = (p)->Release(); DPF1(1,"--DirectPlayVoiceClient SafeRelease (RefCount = %d)\n",i); if (!i) { (p)=NULL;}} } __except(EXCEPTION_EXECUTE_HANDLER) { DPF(1,"------ DXVB: SafeRelease Exception Handler hit(??):") (p) = NULL;} }
  13. ///////////////////////////////////////////////////////////////////
  14. // InternalAddRef
  15. ///////////////////////////////////////////////////////////////////
  16. DWORD C_dxj_DirectPlayVoiceClientObject::InternalAddRef(){
  17. DWORD i;
  18. i=CComObjectRoot::InternalAddRef();
  19. DPF1(1,"------ DXVB: DirectPlayVoiceClient AddRef %d \n",i);
  20. return i;
  21. }
  22. ///////////////////////////////////////////////////////////////////
  23. // InternalRelease
  24. ///////////////////////////////////////////////////////////////////
  25. DWORD C_dxj_DirectPlayVoiceClientObject::InternalRelease(){
  26. DWORD i;
  27. i=CComObjectRoot::InternalRelease();
  28. DPF1(1,"DirectPlayVoiceClient Release %d \n",i);
  29. return i;
  30. }
  31. ///////////////////////////////////////////////////////////////////
  32. // C_dxj_DirectPlayVoiceClientObject
  33. ///////////////////////////////////////////////////////////////////
  34. C_dxj_DirectPlayVoiceClientObject::C_dxj_DirectPlayVoiceClientObject(){
  35. DPF(1,"------ DXVB: Constructor Creation DirectPlayVoiceClient Object\n ");
  36. m__dxj_DirectPlayVoiceClient = NULL;
  37. m__dxj_DirectSound = NULL;
  38. m__dxj_DirectSoundCapture = NULL;
  39. m_pEventStream=NULL;
  40. m_fInit = FALSE;
  41. m_fHandleVoiceClientEvents = FALSE;
  42. m_dwMsgCount = 0;
  43. }
  44. ///////////////////////////////////////////////////////////////////
  45. // ~C_dxj_DirectPlayVoiceClientObject
  46. ///////////////////////////////////////////////////////////////////
  47. C_dxj_DirectPlayVoiceClientObject::~C_dxj_DirectPlayVoiceClientObject()
  48. {
  49. DPF(1,"------ DXVB: Entering ~C_dxj_DirectPlayVoiceClientObject destructor \n");
  50. DPF(1,"------ DXVB: Turning off message handling\n");
  51. m_fHandleVoiceClientEvents = FALSE;
  52. DPF(1,"------ DXVB: Releasing Stream\n");
  53. SAFE_RELEASE(m_pEventStream);
  54. FlushBuffer(0);
  55. /*DPF(1,"------ DXVB: Releasing DirectSoundObject\n");
  56. SAFE_RELEASE(m__dxj_DirectSound);
  57. DPF(1,"------ DXVB: Releasing DirectSoundCaptureObject\n");
  58. SAFE_RELEASE(m__dxj_DirectSoundCapture);
  59. DPF(1,"------ DXVB: Releasing DPVoiceClient\n");*/
  60. SAFE_RELEASE(m__dxj_DirectPlayVoiceClient);
  61. DPF(1,"------ DXVB: Leaving ~C_dxj_DirectPlayVoiceClientObject destructor \n");
  62. }
  63. HRESULT C_dxj_DirectPlayVoiceClientObject::InternalGetObject(IUnknown **pUnk){
  64. *pUnk=(IUnknown*)m__dxj_DirectPlayVoiceClient;
  65. return S_OK;
  66. }
  67. HRESULT C_dxj_DirectPlayVoiceClientObject::InternalSetObject(IUnknown *pUnk){
  68. m__dxj_DirectPlayVoiceClient=(LPDIRECTPLAYVOICECLIENT)pUnk;
  69. return S_OK;
  70. }
  71. HRESULT CALLBACK VoiceMessageHandlerClient(LPVOID lpvUserContext, DWORD dwMessageType, LPVOID lpMessage)
  72. {
  73. HRESULT hr=S_OK;
  74. // User context for the message handler is a pointer to our class module.
  75. C_dxj_DirectPlayVoiceClientObject *lpPeer = (C_dxj_DirectPlayVoiceClientObject*)lpvUserContext;
  76. DPF2(1,"-----Entering (VoiceClient) MessageHandler call... (Current msg count=%d) MSGID = %d\n", lpPeer->m_dwMsgCount, dwMessageType );
  77. //Increment the msg count
  78. InterlockedIncrement(&lpPeer->m_dwMsgCount);
  79. if (!lpPeer)
  80. {
  81. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  82. DPF(1,"-----Leaving (VoiceClient) MessageHandler call (No lpPeer member)...\n");
  83. return E_FAIL;
  84. }
  85. if (!lpPeer->m_pEventStream)
  86. {
  87. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  88. DPF(1,"-----Leaving (VoiceClient) MessageHandler call (No stream)...\n");
  89. return E_FAIL;
  90. }
  91. if (!lpPeer->m_fHandleVoiceClientEvents)
  92. {
  93. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  94. DPF(1,"-----Leaving (VoiceClient) MessageHandler call (Not handling events)...\n");
  95. return S_OK;
  96. }
  97. if (!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST))
  98. {
  99. DPF(1,"-----(VoiceClient) SetThreadPri Failed... \n");
  100. }
  101. // First we need to set our stream seek back to the beginning
  102. // We will do this every time we enter this function since we don't know if
  103. // we are on the same thread or not...
  104. LARGE_INTEGER l;
  105. I_dxj_DPVoiceEvent *lpEvent = NULL;
  106. l.QuadPart = 0;
  107. lpPeer->m_pEventStream->Seek(l, STREAM_SEEK_SET, NULL);
  108. DPF(1,"-----(VoiceClient) About to CoUnmarshal the interface... \n");
  109. hr = CoUnmarshalInterface(lpPeer->m_pEventStream, IID_I_dxj_DPVoiceEvent, (void**)&lpEvent);
  110. if (!lpEvent)
  111. {
  112. DPF(1,"-----(VoiceClient) CoUnmarshal Failed... \n");
  113. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  114. return hr;
  115. }
  116. switch (dwMessageType)
  117. {
  118. case DVMSGID_LOCALHOSTSETUP:
  119. {
  120. DVMSG_LOCALHOSTSETUP *msg = (DVMSG_LOCALHOSTSETUP*)lpMessage;
  121. DPF(1,"-----(VoiceClient) Receive LocalHostSetup Msg... \n");
  122. msg->pvContext = lpvUserContext;
  123. msg->pMessageHandler = VoiceMessageHandlerClient;
  124. break;
  125. }
  126. case DVMSGID_SESSIONLOST:
  127. {
  128. DVMSG_SESSIONLOST *msg = (DVMSG_SESSIONLOST*)lpMessage;
  129. DPF(1,"-----(VoiceClient) Receive SessionLost Msg... \n");
  130. lpEvent->SessionLost(msg->hrResult);
  131. DPF(1,"-----(VoiceClient) Returning from VB - SessionLost Msg... \n");
  132. break;
  133. }
  134. case DVMSGID_HOSTMIGRATED:
  135. {
  136. DVMSG_HOSTMIGRATED *msg = (DVMSG_HOSTMIGRATED*)lpMessage;
  137. I_dxj_DirectPlayVoiceServer *lpServer = NULL;
  138. INTERNAL_CREATE_ADDRESS(_dxj_DirectPlayVoiceServer, msg->pdvServerInterface, &lpServer);
  139. DPF(1,"-----(VoiceClient) Receive HostMigrated Msg... \n");
  140. lpEvent->HostMigrated(msg->dvidNewHostID, lpServer);
  141. DPF(1,"-----(VoiceClient) Returning from VB - HostMigrated Msg... \n");
  142. break;
  143. }
  144. case DVMSGID_RECORDSTART:
  145. {
  146. DVMSG_RECORDSTART *pMsg = (DVMSG_RECORDSTART*)lpMessage;
  147. DPF(1,"-----(VoiceClient) Receive RecordStart Msg... \n");
  148. lpEvent->RecordStart(pMsg->dwPeakLevel);
  149. DPF(1,"-----(VoiceClient) Returning from VB - RecordStart Msg... \n");
  150. break;
  151. }
  152. case DVMSGID_RECORDSTOP:
  153. {
  154. DVMSG_RECORDSTOP *pMsg = (DVMSG_RECORDSTOP*)lpMessage;
  155. DPF(1,"-----(VoiceClient) Receive RecordStop Msg... \n");
  156. lpEvent->RecordStop(pMsg->dwPeakLevel);
  157. DPF(1,"-----(VoiceClient) Returning from VB - RecordStop Msg... \n");
  158. break;
  159. }
  160. case DVMSGID_PLAYERVOICESTART:
  161. {
  162. DVMSG_PLAYERVOICESTART *pMsg = (DVMSG_PLAYERVOICESTART*)lpMessage;
  163. DPF(1,"-----(VoiceClient) Receive PlayerVoiceStart Msg... \n");
  164. lpEvent->PlayerVoiceStart(pMsg->dvidSourcePlayerID);
  165. DPF(1,"-----(VoiceClient) Returning from VB - PlayerVoiceStart Msg... \n");
  166. break;
  167. }
  168. case DVMSGID_PLAYERVOICESTOP:
  169. {
  170. DVMSG_PLAYERVOICESTOP *pMsg = (DVMSG_PLAYERVOICESTOP*)lpMessage;
  171. DPF(1,"-----(VoiceClient) Receive PlayerVoiceStop Msg... \n");
  172. lpEvent->PlayerVoiceStop(pMsg->dvidSourcePlayerID);
  173. DPF(1,"-----(VoiceClient) Returning from VB - PlayerVoiceStop Msg... \n");
  174. break;
  175. }
  176. case DVMSGID_CONNECTRESULT:
  177. {
  178. DVMSG_CONNECTRESULT *msg = (DVMSG_CONNECTRESULT*)lpMessage;
  179. DPF(1,"-----(VoiceClient) Receive ConnectResult Msg... \n");
  180. lpEvent->ConnectResult(msg->hrResult);
  181. DPF(1,"-----(VoiceClient) Returning from VB - ConnectResult Msg... \n");
  182. break;
  183. }
  184. case DVMSGID_DISCONNECTRESULT:
  185. {
  186. DVMSG_DISCONNECTRESULT *pMsg = (DVMSG_DISCONNECTRESULT*)lpMessage;
  187. DPF(1,"-----(VoiceClient) Receive DisconnectResult Msg... \n");
  188. lpEvent->DisconnectResult(pMsg->hrResult);
  189. DPF(1,"-----(VoiceClient) Returning from VB - DisconnectResult Msg... \n");
  190. break;
  191. }
  192. case DVMSGID_INPUTLEVEL:
  193. {
  194. DVMSG_INPUTLEVEL *pMsg = (DVMSG_INPUTLEVEL*)lpMessage;
  195. DPF(1,"-----(VoiceClient) Receive InputLevel Msg... \n");
  196. lpEvent->InputLevel(pMsg->dwPeakLevel,pMsg->lRecordVolume);
  197. DPF(1,"-----(VoiceClient) Returning from VB - InputLevel Msg... \n");
  198. break;
  199. }
  200. case DVMSGID_OUTPUTLEVEL:
  201. {
  202. DVMSG_OUTPUTLEVEL *pMsg = (DVMSG_OUTPUTLEVEL*)lpMessage;
  203. DPF(1,"-----(VoiceClient) Receive Output Level Msg... \n");
  204. lpEvent->OutputLevel(pMsg->dwPeakLevel,pMsg->lOutputVolume);
  205. DPF(1,"-----(VoiceClient) Returning from VB - Output Level Msg... \n");
  206. break;
  207. }
  208. case DVMSGID_PLAYEROUTPUTLEVEL:
  209. {
  210. DVMSG_PLAYEROUTPUTLEVEL *pMsg = (DVMSG_PLAYEROUTPUTLEVEL*)lpMessage;
  211. DPF(1,"-----(VoiceClient) Receive PlayerOutputLevel Msg... \n");
  212. lpEvent->PlayerOutputLevel(pMsg->dvidSourcePlayerID,pMsg->dwPeakLevel);
  213. DPF(1,"-----(VoiceClient) Returning from VB - PlayerOutputLevel Msg... \n");
  214. break;
  215. }
  216. case DVMSGID_CREATEVOICEPLAYER:
  217. {
  218. DVMSG_CREATEVOICEPLAYER *pMsg = (DVMSG_CREATEVOICEPLAYER*)lpMessage;
  219. DPF(1,"-----(VoiceClient) Receive CreateVoicePlayer Msg... \n");
  220. lpEvent->CreateVoicePlayer(pMsg->dvidPlayer, pMsg->dwFlags);
  221. DPF(1,"-----(VoiceClient) Returning from VB - CreateVoicePlayer Msg... \n");
  222. break;
  223. }
  224. case DVMSGID_DELETEVOICEPLAYER:
  225. {
  226. DVMSG_DELETEVOICEPLAYER *pMsg = (DVMSG_DELETEVOICEPLAYER*)lpMessage;
  227. DPF(1,"-----(VoiceClient) Receive DeleteVoicePlayer Msg... \n");
  228. lpEvent->DeleteVoicePlayer(pMsg->dvidPlayer);
  229. DPF(1,"-----(VoiceClient) Returning from VB - DeleteVoicePlayer Msg... \n");
  230. break;
  231. }
  232. case DVMSGID_SETTARGETS:
  233. DPF(1,"-----(VoiceClient) Receive SetTargets Msg... \n");
  234. break;
  235. }
  236. __try {
  237. DPF(1,"-----(VoiceClient) Releasing MarshalData... \n");
  238. if (lpPeer->m_pEventStream)
  239. // clean up marshaled packet
  240. CoReleaseMarshalData(lpPeer->m_pEventStream);
  241. }
  242. __except(EXCEPTION_EXECUTE_HANDLER)
  243. {
  244. lpPeer->m_fHandleVoiceClientEvents = FALSE;
  245. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  246. return S_OK;
  247. }
  248. DPF(1,"-----Leaving (VoiceClient) MessageHandler call...\n");
  249. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  250. return S_OK;
  251. }
  252. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::Initialize (
  253. IUnknown *DplayObj,
  254. long lFlags)
  255. {
  256. HRESULT hr;
  257. IUnknown *lpDplay = NULL;
  258. I_dxj_DirectPlayPeer *lpPeer = NULL;
  259. I_dxj_DirectPlayClient *lpClient = NULL;
  260. I_dxj_DirectPlayServer *lpServer = NULL;
  261. __try {
  262. DPF(1,"-----Entering (VoiceClient) Initialize call...\n");
  263. // First we need to get our IUnknown pointer from whatever we pass in
  264. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayPeer, (void**)&lpPeer);
  265. if (SUCCEEDED(hr))
  266. {
  267. lpPeer->InternalGetObject(&lpDplay);
  268. SAFE_RELEASE(lpPeer);
  269. }
  270. else
  271. {
  272. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayClient, (void**)&lpClient);
  273. if (SUCCEEDED(hr))
  274. {
  275. lpClient->InternalGetObject(&lpDplay);
  276. SAFE_RELEASE(lpClient);
  277. }
  278. else
  279. {
  280. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayServer, (void**)&lpServer);
  281. if (SUCCEEDED(hr))
  282. {
  283. lpServer->InternalGetObject(&lpDplay);
  284. SAFE_RELEASE(lpServer);
  285. }
  286. }
  287. }
  288. if (!lpDplay)
  289. return E_INVALIDARG;
  290. if (!m_fInit)
  291. {
  292. if (FAILED( hr=m__dxj_DirectPlayVoiceClient->Initialize(lpDplay, &VoiceMessageHandlerClient,
  293. this,0,(DWORD)lFlags)))
  294. return hr;
  295. m_fInit = TRUE;
  296. }
  297. }
  298. __except(EXCEPTION_EXECUTE_HANDLER)
  299. {
  300. return E_FAIL;
  301. }
  302. return S_OK;
  303. }
  304. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::Connect (
  305. DVSOUNDDEVICECONFIG_CDESC *SoundDeviceConfig,
  306. DVCLIENTCONFIG_CDESC *ClientConfig,
  307. long lFlags)
  308. {
  309. HRESULT hr;
  310. DVCLIENTCONFIG dvClient;
  311. DVSOUNDDEVICECONFIG dvSound;
  312. GUID guidPlayback;
  313. GUID guidCapture;
  314. LPDIRECTSOUND8 lpDSoundOut = NULL;
  315. LPDIRECTSOUNDCAPTURE8 lpDSoundCaptureOut = NULL;
  316. __try {
  317. DPF(1,"-----Entering (VoiceClient) Connect call...\n");
  318. //FlushBuffer(0);
  319. //Set up the sound config
  320. ZeroMemory ( &dvSound, sizeof(DVSOUNDDEVICECONFIG));
  321. dvSound.dwSize = sizeof(DVSOUNDDEVICECONFIG);
  322. dvSound.dwFlags = (DWORD)SoundDeviceConfig->lFlags;
  323. //Set up the default playback device (or whatever they picked)
  324. if (SoundDeviceConfig->guidPlaybackDevice == NULL)
  325. dvSound.guidPlaybackDevice = DSDEVID_DefaultVoicePlayback;
  326. else
  327. {
  328. hr = DPLAYBSTRtoGUID(&guidPlayback, SoundDeviceConfig->guidPlaybackDevice);
  329. dvSound.guidPlaybackDevice = guidPlayback;
  330. }
  331. // Set up the default capture device (or whatever they picked)
  332. if (SoundDeviceConfig->guidCaptureDevice == NULL)
  333. dvSound.guidCaptureDevice = DSDEVID_DefaultVoiceCapture;
  334. else
  335. {
  336. hr = DPLAYBSTRtoGUID(&guidCapture, SoundDeviceConfig->guidCaptureDevice);
  337. dvSound.guidCaptureDevice = guidCapture;
  338. }
  339. // Is there a current Playback device?
  340. if (m__dxj_DirectSound)
  341. dvSound.lpdsPlaybackDevice = m__dxj_DirectSound;
  342. else
  343. dvSound.lpdsPlaybackDevice = NULL;
  344. // Is there a current Capture device?
  345. if (m__dxj_DirectSoundCapture)
  346. dvSound.lpdsCaptureDevice = m__dxj_DirectSoundCapture;
  347. else
  348. dvSound.lpdsCaptureDevice = NULL;
  349. dvSound.lpdsPlaybackDevice = lpDSoundOut;
  350. dvSound.lpdsCaptureDevice = lpDSoundCaptureOut;
  351. dvSound.hwndAppWindow = (HWND)SoundDeviceConfig->hwndAppWindow;
  352. if (SoundDeviceConfig->MainSoundBuffer)
  353. {
  354. DO_GETOBJECT_NOTNULL( LPDIRECTSOUNDBUFFER8, lpDSoundBuffer, SoundDeviceConfig->MainSoundBuffer);
  355. dvSound.lpdsMainBuffer = lpDSoundBuffer;
  356. dvSound.dwMainBufferFlags = SoundDeviceConfig->lMainBufferFlags;
  357. dvSound.dwMainBufferPriority = SoundDeviceConfig->lMainBufferPriority;
  358. }
  359. //Set up the client config
  360. ZeroMemory ( &dvClient, sizeof(DVCLIENTCONFIG) );
  361. dvClient.dwSize = sizeof(DVCLIENTCONFIG);
  362. dvClient.dwFlags = ClientConfig->lFlags;
  363. dvClient.lRecordVolume = ClientConfig->lRecordVolume;
  364. dvClient.lPlaybackVolume = ClientConfig->lPlaybackVolume;
  365. dvClient.dwThreshold = ClientConfig->lThreshold;
  366. dvClient.dwBufferQuality = ClientConfig->lBufferQuality;
  367. dvClient.dwBufferAggressiveness = ClientConfig->lBufferAggressiveness;
  368. dvClient.dwNotifyPeriod = ClientConfig->lNotifyPeriod;
  369. if (FAILED ( hr = m__dxj_DirectPlayVoiceClient->Connect(&dvSound, &dvClient, (DWORD)lFlags)))
  370. return hr;
  371. //Now set the devices that were used.
  372. m__dxj_DirectSound = lpDSoundOut;
  373. m__dxj_DirectSoundCapture = lpDSoundCaptureOut;
  374. }
  375. __except(EXCEPTION_EXECUTE_HANDLER)
  376. {
  377. return E_FAIL;
  378. }
  379. return S_OK;
  380. }
  381. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::Disconnect (
  382. long lFlags)
  383. {
  384. HRESULT hr;
  385. __try {
  386. DPF(1,"-----Entering (VoiceClient) Disconnect call...\n");
  387. FlushBuffer(0);
  388. if (FAILED (hr = m__dxj_DirectPlayVoiceClient->Disconnect((DWORD)lFlags)))
  389. return hr;
  390. }
  391. __except(EXCEPTION_EXECUTE_HANDLER)
  392. {
  393. return E_FAIL;
  394. }
  395. return S_OK;
  396. }
  397. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetSessionDesc (
  398. DVSESSIONDESC_CDESC *SessionDesc)
  399. {
  400. HRESULT hr;
  401. DVSESSIONDESC dvSession;
  402. __try {
  403. DPF(1,"-----Entering (VoiceClient) GetSessionDesc call...\n");
  404. //FlushBuffer(0);
  405. dvSession.dwSize = sizeof(DVSESSIONDESC);
  406. //Now get the buffer
  407. if ( FAILED(hr = m__dxj_DirectPlayVoiceClient->GetSessionDesc(&dvSession)))
  408. return hr;
  409. //Cast into return buffer
  410. SessionDesc->lFlags = (long)dvSession.dwFlags;
  411. SessionDesc->lSessionType = (long)dvSession.dwSessionType;
  412. SessionDesc->guidCT = GUIDtoBSTR(&dvSession.guidCT);
  413. SessionDesc->lBufferQuality = (long)dvSession.dwBufferQuality;
  414. SessionDesc->lBufferAggressiveness = (long)dvSession.dwBufferAggressiveness;
  415. }
  416. __except(EXCEPTION_EXECUTE_HANDLER)
  417. {
  418. return E_FAIL;
  419. }
  420. return S_OK;
  421. }
  422. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetClientConfig (
  423. DVCLIENTCONFIG_CDESC *ClientConfig)
  424. {
  425. HRESULT hr;
  426. __try {
  427. DPF(1,"-----Entering (VoiceClient) GetClientConfig call...\n");
  428. //FlushBuffer(0);
  429. ClientConfig->lSize = sizeof(DVCLIENTCONFIG);
  430. if (FAILED ( hr = m__dxj_DirectPlayVoiceClient->GetClientConfig((DVCLIENTCONFIG*)ClientConfig)))
  431. return hr;
  432. }
  433. __except(EXCEPTION_EXECUTE_HANDLER)
  434. {
  435. return E_FAIL;
  436. }
  437. return S_OK;
  438. }
  439. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::SetClientConfig (
  440. DVCLIENTCONFIG_CDESC *ClientConfig)
  441. {
  442. HRESULT hr;
  443. DVCLIENTCONFIG dvClient;
  444. __try {
  445. DPF(1,"-----Entering (VoiceClient) SetClientConfig call...\n");
  446. //FlushBuffer(0);
  447. ZeroMemory ( &dvClient, sizeof(DVCLIENTCONFIG) );
  448. // Fill our copy of DVCLIENTCONFIG
  449. dvClient.dwSize = sizeof(DVCLIENTCONFIG);
  450. dvClient.dwFlags = ClientConfig->lFlags;
  451. dvClient.lRecordVolume = ClientConfig->lRecordVolume;
  452. dvClient.lPlaybackVolume = ClientConfig->lPlaybackVolume;
  453. dvClient.dwThreshold = ClientConfig->lThreshold;
  454. dvClient.dwBufferQuality = ClientConfig->lBufferQuality;
  455. dvClient.dwBufferAggressiveness = ClientConfig->lBufferAggressiveness;
  456. dvClient.dwNotifyPeriod = ClientConfig->lNotifyPeriod;
  457. if (FAILED ( hr = m__dxj_DirectPlayVoiceClient->SetClientConfig(&dvClient)))
  458. return hr;
  459. }
  460. __except(EXCEPTION_EXECUTE_HANDLER)
  461. {
  462. return E_FAIL;
  463. }
  464. return S_OK;
  465. }
  466. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetCaps (
  467. DVCAPS_CDESC *Caps)
  468. {
  469. HRESULT hr;
  470. __try {
  471. DPF(1,"-----Entering (VoiceClient) GetCaps call...\n");
  472. //FlushBuffer(0);
  473. Caps->lSize = sizeof(DVCAPS);
  474. if (FAILED ( hr = m__dxj_DirectPlayVoiceClient->GetCaps((DVCAPS*)Caps)))
  475. return hr;
  476. }
  477. __except(EXCEPTION_EXECUTE_HANDLER)
  478. {
  479. return E_FAIL;
  480. }
  481. return S_OK;
  482. }
  483. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetCompressionTypeCount (
  484. long *retval)
  485. {
  486. HRESULT hr;
  487. DWORD dwSize = 0;
  488. DWORD dwNumElements = 0;
  489. __try {
  490. DPF(1,"-----Entering (VoiceClient) GetCompressionTypeCount call...\n");
  491. //FlushBuffer(0);
  492. hr = m__dxj_DirectPlayVoiceClient->GetCompressionTypes(NULL, &dwSize, &dwNumElements ,0);
  493. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  494. return hr;
  495. *retval = (long)dwNumElements;
  496. }
  497. __except(EXCEPTION_EXECUTE_HANDLER)
  498. {
  499. return E_FAIL;
  500. }
  501. return S_OK;
  502. }
  503. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetCompressionType (
  504. long lIndex,
  505. DVCOMPRESSIONINFO_CDESC *Data,
  506. long lFlags)
  507. {
  508. HRESULT hr;
  509. LPBYTE pBuffer = NULL;
  510. DWORD dwSize = 0;
  511. DWORD dwNumElements = 0;
  512. LPDVCOMPRESSIONINFO pdvCompressionInfo;
  513. LPGUID pGuid;
  514. __try {
  515. DPF(1,"-----Entering (VoiceClient) GetCompressionTypes call...\n");
  516. //FlushBuffer(0);
  517. hr = m__dxj_DirectPlayVoiceClient->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements ,0);
  518. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  519. return hr;
  520. pBuffer = new BYTE[dwSize];
  521. if (!pBuffer)
  522. return E_OUTOFMEMORY;
  523. if ( FAILED ( hr = m__dxj_DirectPlayVoiceClient->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements, (DWORD)lFlags)))
  524. return hr;
  525. if (lIndex > (long)dwNumElements)
  526. return DVERR_INVALIDPARAM;
  527. pdvCompressionInfo = (LPDVCOMPRESSIONINFO) pBuffer;
  528. pGuid = new GUID;
  529. if (!pGuid)
  530. return E_OUTOFMEMORY;
  531. // Ok, fill up our struct
  532. ZeroMemory(Data, sizeof(DVCOMPRESSIONINFO_CDESC));
  533. Data->lSize = sizeof(DVCOMPRESSIONINFO_CDESC);
  534. Data->lFlags = pdvCompressionInfo[lIndex-1].dwFlags;
  535. Data->lMaxBitsPerSecond = pdvCompressionInfo[lIndex-1].dwMaxBitsPerSecond;
  536. Data->strDescription = SysAllocString(pdvCompressionInfo[lIndex-1].lpszDescription);
  537. Data->strName = SysAllocString(pdvCompressionInfo[lIndex-1].lpszName);
  538. (*pGuid) = pdvCompressionInfo[lIndex-1].guidType;
  539. Data->guidType = GUIDtoBSTR(pGuid);
  540. SAFE_DELETE(pGuid);
  541. SAFE_DELETE(pBuffer);
  542. }
  543. __except(EXCEPTION_EXECUTE_HANDLER)
  544. {
  545. return E_FAIL;
  546. }
  547. return S_OK;
  548. }
  549. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::SetTransmitTargets (
  550. SAFEARRAY **playerIDs,
  551. long lFlags)
  552. {
  553. HRESULT hr;
  554. DWORD dwNumTarget = ((SAFEARRAY*)*playerIDs)->rgsabound[0].cElements;
  555. __try {
  556. DPF(1,"-----Entering (VoiceClient) SetTransmitTargets call...\n");
  557. //FlushBuffer(0);
  558. if (FAILED( hr = m__dxj_DirectPlayVoiceClient->SetTransmitTargets((DVID*)(((SAFEARRAY*)*playerIDs)->pvData),
  559. dwNumTarget, (DWORD) lFlags )))
  560. return hr;
  561. }
  562. __except(EXCEPTION_EXECUTE_HANDLER)
  563. {
  564. return E_FAIL;
  565. }
  566. return S_OK;
  567. }
  568. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetTransmitTargets (
  569. long lFlags,
  570. SAFEARRAY **ret)
  571. {
  572. HRESULT hr;
  573. DVID *dwPlayers = NULL;
  574. DWORD dwNumPlayers=0;
  575. SAFEARRAY *lpData = NULL;
  576. SAFEARRAYBOUND rgsabound[1];
  577. BYTE *lpByte = NULL;
  578. __try {
  579. DPF(1,"-----Entering (VoiceClient) GetTransmitTargets call...\n");
  580. //FlushBuffer(0);
  581. hr =m__dxj_DirectPlayVoiceClient->GetTransmitTargets(NULL, &dwNumPlayers, (DWORD) lFlags );
  582. if (FAILED(hr) && ( hr != DVERR_BUFFERTOOSMALL))
  583. return hr;
  584. dwPlayers = (DVID*)new BYTE[sizeof(DVID) * dwNumPlayers];
  585. if (!dwPlayers)
  586. return E_OUTOFMEMORY;
  587. if (FAILED( hr = m__dxj_DirectPlayVoiceClient->GetTransmitTargets(dwPlayers, &dwNumPlayers, (DWORD) lFlags )))
  588. return hr;
  589. if (dwNumPlayers)
  590. {
  591. // Now let's create a safearray to pass back
  592. rgsabound[0].lLbound = 0;
  593. rgsabound[0].cElements = dwNumPlayers;
  594. lpData = SafeArrayCreate(VT_UI4, 1, rgsabound);
  595. memcpy(lpData->pvData,dwPlayers,sizeof(DVID) * dwNumPlayers);
  596. }
  597. *ret = lpData;
  598. SAFE_DELETE(dwPlayers);
  599. }
  600. __except(EXCEPTION_EXECUTE_HANDLER)
  601. {
  602. return E_FAIL;
  603. }
  604. return S_OK;
  605. }
  606. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::SetCurrentSoundDevices (
  607. I_dxj_DirectSound *DirectSoundObj,
  608. I_dxj_DirectSoundCapture *DirectCaptureObj)
  609. {
  610. __try {
  611. DPF(1,"-----Entering (VoiceClient) SetCurrentSoundDevices call...\n");
  612. //FlushBuffer(0);
  613. DO_GETOBJECT_NOTNULL( LPDIRECTSOUND8, lpSound, DirectSoundObj);
  614. DO_GETOBJECT_NOTNULL( LPDIRECTSOUNDCAPTURE8, lpSoundCapture, DirectCaptureObj);
  615. m__dxj_DirectSound = lpSound;
  616. m__dxj_DirectSoundCapture = lpSoundCapture;
  617. }
  618. __except(EXCEPTION_EXECUTE_HANDLER)
  619. {
  620. return E_FAIL;
  621. }
  622. return S_OK;
  623. }
  624. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetSoundDevices (
  625. I_dxj_DirectSound *DirectSoundObj,
  626. I_dxj_DirectSoundCapture *DirectCaptureObj)
  627. {
  628. __try {
  629. DPF(1,"-----Entering (VoiceClient) GetSoundDevices call...\n");
  630. //FlushBuffer(0);
  631. if (m__dxj_DirectSound)
  632. INTERNAL_CREATE_NOADDREF(_dxj_DirectSound,m__dxj_DirectSound,&DirectSoundObj);
  633. if (m__dxj_DirectSoundCapture)
  634. INTERNAL_CREATE_NOADDREF(_dxj_DirectSoundCapture ,m__dxj_DirectSoundCapture,&DirectCaptureObj);
  635. }
  636. __except(EXCEPTION_EXECUTE_HANDLER)
  637. {
  638. return E_FAIL;
  639. }
  640. return S_OK;
  641. }
  642. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::Create3DSoundBuffer (
  643. long playerID,
  644. I_dxj_DirectSoundBuffer *Buffer,
  645. long lPriority,
  646. long lFlags,
  647. I_dxj_DirectSound3dBuffer **UserBuffer)
  648. {
  649. HRESULT hr;
  650. IDirectSound3DBuffer *lpDSound3DBuffer = NULL;
  651. __try {
  652. DPF(1,"-----Entering (VoiceClient) Create3DSoundBuffer call...\n");
  653. //FlushBuffer(0);
  654. if (Buffer)
  655. {
  656. DO_GETOBJECT_NOTNULL( LPDIRECTSOUNDBUFFER8, lpDSoundBuffer, Buffer);
  657. //First let's go ahead and get the real DirectSoundBuffer
  658. if ( FAILED ( hr = m__dxj_DirectPlayVoiceClient->Create3DSoundBuffer(
  659. (DVID)playerID, lpDSoundBuffer, (DWORD)lPriority, (DWORD) lFlags, &lpDSound3DBuffer)))
  660. return hr;
  661. }
  662. else
  663. {
  664. //First let's go ahead and get the real DirectSoundBuffer
  665. if ( FAILED ( hr = m__dxj_DirectPlayVoiceClient->Create3DSoundBuffer(
  666. (DVID)playerID, NULL, 0, 0, &lpDSound3DBuffer)))
  667. return hr;
  668. }
  669. //We need to do an AddRef() on this buffer so when we release it, it will go away
  670. lpDSound3DBuffer->AddRef();
  671. // Now let's get a I_dxj_DirectSound3dBuffer to pass back..
  672. INTERNAL_CREATE_ADDRESS(_dxj_DirectSound3dBuffer,lpDSound3DBuffer,UserBuffer);
  673. }
  674. __except(EXCEPTION_EXECUTE_HANDLER)
  675. {
  676. return E_FAIL;
  677. }
  678. return S_OK;
  679. }
  680. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::Delete3DSoundBuffer (
  681. long playerID,
  682. I_dxj_DirectSound3dBuffer *UserBuffer)
  683. {
  684. HRESULT hr;
  685. __try {
  686. DPF(1,"-----Entering (VoiceClient) Delete3DSoundBuffer call...\n");
  687. //FlushBuffer(0);
  688. DO_GETOBJECT_NOTNULL( LPDIRECTSOUND3DBUFFER, lpBuffer, UserBuffer);
  689. DPF(1,"-----Calling Delete3DSoundBuffer on core obj...\n");
  690. if (FAILED( hr=m__dxj_DirectPlayVoiceClient->Delete3DSoundBuffer((DVID)playerID, &lpBuffer)))
  691. return hr;
  692. /*int i = UserBuffer->AddRef();
  693. DPF1(1,"-----New Ref: %d...\n",i);*/
  694. }
  695. __except(EXCEPTION_EXECUTE_HANDLER)
  696. {
  697. DPF(1,"-----Leaving (VoiceClient) Delete3DSoundBuffer call (Exception Handler)...\n");
  698. return E_FAIL;
  699. }
  700. DPF(1,"-----Leaving (VoiceClient) Delete3DSoundBuffer call (No error)...\n");
  701. return S_OK;
  702. }
  703. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::GetSoundDeviceConfig(DVSOUNDDEVICECONFIG_CDESC *SoundDeviceConfig)
  704. {
  705. HRESULT hr;
  706. DWORD dwSize = 0;
  707. DVSOUNDDEVICECONFIG *pdvConfig = NULL;
  708. DPF(1,"-----Entering (VoiceClient) GetSoundDeviceConfig call...\n");
  709. __try {
  710. //FlushBuffer(0);
  711. hr = m__dxj_DirectPlayVoiceClient->GetSoundDeviceConfig(NULL, &dwSize);
  712. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  713. return hr;
  714. pdvConfig = (DVSOUNDDEVICECONFIG*) new BYTE[dwSize];
  715. if (!pdvConfig)
  716. return E_OUTOFMEMORY;
  717. pdvConfig->dwSize = sizeof(DVSOUNDDEVICECONFIG);
  718. hr = m__dxj_DirectPlayVoiceClient->GetSoundDeviceConfig(pdvConfig, &dwSize);
  719. if ( FAILED(hr) ) //We didn't expect this error
  720. return hr;
  721. SoundDeviceConfig->lSize = (long)pdvConfig->dwSize;
  722. SoundDeviceConfig->lFlags = (long)pdvConfig->dwFlags;
  723. #ifdef _WIN64
  724. SoundDeviceConfig->hwndAppWindow = pdvConfig->hwndAppWindow;
  725. #else
  726. SoundDeviceConfig->hwndAppWindow = (long)pdvConfig->hwndAppWindow;
  727. #endif
  728. SoundDeviceConfig->guidPlaybackDevice = GUIDtoBSTR(&pdvConfig->guidPlaybackDevice);
  729. SoundDeviceConfig->guidCaptureDevice = GUIDtoBSTR(&pdvConfig->guidCaptureDevice);
  730. SAFE_DELETE(pdvConfig);
  731. }
  732. __except(EXCEPTION_EXECUTE_HANDLER)
  733. {
  734. return E_FAIL;
  735. }
  736. return S_OK;
  737. }
  738. STDMETHODIMP C_dxj_DirectPlayVoiceClientObject::StartClientNotification(I_dxj_DPVoiceEvent *event)
  739. {
  740. HRESULT hr=S_OK;
  741. LPSTREAM pStm=NULL;
  742. IUnknown *pUnk=NULL;
  743. DPF(1,"-----Entering (VoiceClient) StartClientNotification call...\n");
  744. if (!event) return E_INVALIDARG;
  745. SAFE_RELEASE(m_pEventStream);
  746. // Create a global stream. The stream needs to be global so we can
  747. // marshal once, and unmarshal as many times as necessary
  748. hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
  749. if FAILED(hr) return hr;
  750. // Now we can marshal our IUnknown interface. We use MSHLFLAGS_TABLEWEAK
  751. // so we can unmarshal any number of times
  752. hr = CoMarshalInterface(pStm, IID_I_dxj_DPVoiceEvent, event, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
  753. if FAILED(hr) return hr;
  754. // Now we need to set the seek location of the stream to the beginning
  755. LARGE_INTEGER l;
  756. l.QuadPart = 0;
  757. pStm->Seek(l, STREAM_SEEK_SET, NULL);
  758. m_pEventStream=pStm;
  759. m_fHandleVoiceClientEvents = TRUE;
  760. return hr;
  761. }
  762. HRESULT C_dxj_DirectPlayVoiceClientObject::UnRegisterMessageHandler()
  763. {
  764. DPF(1,"-----Entering (VoiceClient) UnregisterMessageHandler call...\n");
  765. m_fHandleVoiceClientEvents = FALSE;
  766. FlushBuffer(0);
  767. return S_OK;
  768. }
  769. HRESULT C_dxj_DirectPlayVoiceClientObject::FlushBuffer(LONG dwNumMessagesLeft)
  770. {
  771. DWORD dwTime = GetTickCount();
  772. DPF(1,"-----Entering (VoiceClient) FlushBuffer call...\n");
  773. //Clear out the messages currently waiting
  774. while (m_dwMsgCount > dwNumMessagesLeft)
  775. {
  776. if (GetTickCount() - dwTime > 5000)
  777. {
  778. // Don't let FlushBuffer wait more than 5 seconds
  779. DPF1(1,"-----Leaving (VoiceClient) FlushBuffer call (All messages *not* flushed - %d remained)...\n", m_dwMsgCount);
  780. return S_OK;
  781. }
  782. Sleep(0);
  783. }
  784. DPF(1,"-----Leaving (VoiceClient) FlushBuffer call (All messages flushed)...\n");
  785. return S_OK;
  786. }