Leaked source code of windows server 2003
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.

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