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.

670 lines
17 KiB

  1. #include "stdafx.h"
  2. #include "Direct.h"
  3. #include "dms.h"
  4. #include "dPlayVoiceServerObj.h"
  5. #include "dvoice.h"
  6. extern BSTR GUIDtoBSTR(LPGUID pGuid);
  7. extern HRESULT DPLAYBSTRtoGUID(LPGUID,BSTR);
  8. extern void *g_dxj_DirectPlayVoiceServer;
  9. #define SAFE_DELETE(p) { if(p) { delete (p); p=NULL; } }
  10. #define SAFE_RELEASE(p) { __try { if(p) { int i = 0; i = (p)->Release(); DPF1(1,"--DirectPlayVoiceServer SafeRelease (RefCount = %d)\n",i); if (!i) { (p)=NULL;}} } __except(EXCEPTION_EXECUTE_HANDLER) { (p) = NULL;} }
  11. ///////////////////////////////////////////////////////////////////
  12. // InternalAddRef
  13. ///////////////////////////////////////////////////////////////////
  14. DWORD C_dxj_DirectPlayVoiceServerObject::InternalAddRef(){
  15. DWORD i;
  16. i=CComObjectRoot::InternalAddRef();
  17. DPF1(1,"------ DXVB: DirectPlayVoiceServer AddRef %d \n",i);
  18. return i;
  19. }
  20. ///////////////////////////////////////////////////////////////////
  21. // InternalRelease
  22. ///////////////////////////////////////////////////////////////////
  23. DWORD C_dxj_DirectPlayVoiceServerObject::InternalRelease(){
  24. DWORD i;
  25. i=CComObjectRoot::InternalRelease();
  26. DPF1(1,"DirectPlayVoiceServer Release %d \n",i);
  27. return i;
  28. }
  29. ///////////////////////////////////////////////////////////////////
  30. // C_dxj_DirectPlayVoiceServerObject
  31. ///////////////////////////////////////////////////////////////////
  32. C_dxj_DirectPlayVoiceServerObject::C_dxj_DirectPlayVoiceServerObject(){
  33. DPF(1,"------ DXVB: Constructor Creation DirectPlayVoiceServer Object \n ");
  34. m__dxj_DirectPlayVoiceServer = NULL;
  35. m_pEventStream=NULL;
  36. m_fInit = FALSE;
  37. m_fHandleVoiceClientEvents = FALSE;
  38. m_dwMsgCount = 0;
  39. }
  40. ///////////////////////////////////////////////////////////////////
  41. // ~C_dxj_DirectPlayVoiceServerObject
  42. ///////////////////////////////////////////////////////////////////
  43. C_dxj_DirectPlayVoiceServerObject::~C_dxj_DirectPlayVoiceServerObject()
  44. {
  45. DPF(1,"------ DXVB: Entering ~C_dxj_DirectPlayVoiceServerObject destructor \n");
  46. m_fHandleVoiceClientEvents = FALSE;
  47. FlushBuffer(0);
  48. SAFE_RELEASE(m__dxj_DirectPlayVoiceServer);
  49. SAFE_RELEASE(m_pEventStream);
  50. }
  51. HRESULT C_dxj_DirectPlayVoiceServerObject::InternalGetObject(IUnknown **pUnk){
  52. *pUnk=(IUnknown*)m__dxj_DirectPlayVoiceServer;
  53. return S_OK;
  54. }
  55. HRESULT C_dxj_DirectPlayVoiceServerObject::InternalSetObject(IUnknown *pUnk){
  56. m__dxj_DirectPlayVoiceServer=(LPDIRECTPLAYVOICESERVER)pUnk;
  57. return S_OK;
  58. }
  59. HRESULT CALLBACK VoiceMessageHandlerServer(LPVOID lpvUserContext, DWORD dwMessageType,
  60. LPVOID lpMessage)
  61. {
  62. HRESULT hr=S_OK;
  63. // User context for the message handler is a pointer to our class module.
  64. C_dxj_DirectPlayVoiceServerObject *lpPeer = (C_dxj_DirectPlayVoiceServerObject*)lpvUserContext;
  65. DPF2(1,"-----Entering (VoiceServer) MessageHandler call... (Current msg count=%d) MSGID = %d\n", lpPeer->m_dwMsgCount, dwMessageType );
  66. //Increment the msg count
  67. InterlockedIncrement(&lpPeer->m_dwMsgCount);
  68. if (!lpPeer)
  69. {
  70. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  71. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (No lpPeer member)...\n");
  72. return E_FAIL;
  73. }
  74. if (!lpPeer->m_pEventStream)
  75. {
  76. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  77. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (No stream)...\n");
  78. return E_FAIL;
  79. }
  80. if (!lpPeer->m_fHandleVoiceClientEvents)
  81. {
  82. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  83. DPF(1,"-----Leaving (VoiceServer) MessageHandler call (Not handling events)...\n");
  84. return S_OK;
  85. }
  86. // First we need to set our stream seek back to the beginning
  87. // We will do this every time we enter this function since we don't know if
  88. // we are on the same thread or not...
  89. LARGE_INTEGER l;
  90. I_dxj_DPVoiceEvent *lpEvent = NULL;
  91. l.QuadPart = 0;
  92. lpPeer->m_pEventStream->Seek(l, STREAM_SEEK_SET, NULL);
  93. hr = CoUnmarshalInterface(lpPeer->m_pEventStream, IID_I_dxj_DPVoiceEvent, (void**)&lpEvent);
  94. if (!lpEvent)
  95. {
  96. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  97. return hr;
  98. }
  99. switch (dwMessageType)
  100. {
  101. case DVMSGID_LOCALHOSTSETUP:
  102. {
  103. DVMSG_LOCALHOSTSETUP *msg = (DVMSG_LOCALHOSTSETUP*)lpMessage;
  104. msg->pvContext = lpvUserContext;
  105. msg->pMessageHandler = VoiceMessageHandlerServer;
  106. break;
  107. }
  108. case DVMSGID_SESSIONLOST:
  109. {
  110. DVMSG_SESSIONLOST *msg = (DVMSG_SESSIONLOST*)lpMessage;
  111. lpEvent->SessionLost(msg->hrResult);
  112. break;
  113. }
  114. case DVMSGID_HOSTMIGRATED:
  115. {
  116. DVMSG_HOSTMIGRATED *msg = (DVMSG_HOSTMIGRATED*)lpMessage;
  117. I_dxj_DirectPlayVoiceServer *lpServer = NULL;
  118. INTERNAL_CREATE_ADDRESS(_dxj_DirectPlayVoiceServer, msg->pdvServerInterface, &lpServer);
  119. lpEvent->HostMigrated(msg->dvidNewHostID, lpServer);
  120. break;
  121. }
  122. case DVMSGID_RECORDSTART:
  123. {
  124. DVMSG_RECORDSTART *pMsg = (DVMSG_RECORDSTART*)lpMessage;
  125. lpEvent->RecordStart(pMsg->dwPeakLevel);
  126. break;
  127. }
  128. case DVMSGID_RECORDSTOP:
  129. {
  130. DVMSG_RECORDSTOP *pMsg = (DVMSG_RECORDSTOP*)lpMessage;
  131. lpEvent->RecordStop(pMsg->dwPeakLevel);
  132. break;
  133. }
  134. case DVMSGID_PLAYERVOICESTART:
  135. {
  136. DVMSG_PLAYERVOICESTART *pMsg = (DVMSG_PLAYERVOICESTART*)lpMessage;
  137. lpEvent->PlayerVoiceStart(pMsg->dvidSourcePlayerID);
  138. break;
  139. }
  140. case DVMSGID_PLAYERVOICESTOP:
  141. {
  142. DVMSG_PLAYERVOICESTOP *pMsg = (DVMSG_PLAYERVOICESTOP*)lpMessage;
  143. lpEvent->PlayerVoiceStop(pMsg->dvidSourcePlayerID);
  144. break;
  145. }
  146. case DVMSGID_CONNECTRESULT:
  147. {
  148. DVMSG_CONNECTRESULT *msg = (DVMSG_CONNECTRESULT*)lpMessage;
  149. lpEvent->ConnectResult(msg->hrResult);
  150. break;
  151. }
  152. case DVMSGID_DISCONNECTRESULT:
  153. {
  154. DVMSG_DISCONNECTRESULT *pMsg = (DVMSG_DISCONNECTRESULT*)lpMessage;
  155. lpEvent->DisconnectResult(pMsg->hrResult);
  156. break;
  157. }
  158. case DVMSGID_INPUTLEVEL:
  159. {
  160. DVMSG_INPUTLEVEL *pMsg = (DVMSG_INPUTLEVEL*)lpMessage;
  161. lpEvent->InputLevel(pMsg->dwPeakLevel,pMsg->lRecordVolume);
  162. break;
  163. }
  164. case DVMSGID_OUTPUTLEVEL:
  165. {
  166. DVMSG_OUTPUTLEVEL *pMsg = (DVMSG_OUTPUTLEVEL*)lpMessage;
  167. lpEvent->OutputLevel(pMsg->dwPeakLevel,pMsg->lOutputVolume);
  168. break;
  169. }
  170. case DVMSGID_PLAYEROUTPUTLEVEL:
  171. {
  172. DVMSG_PLAYEROUTPUTLEVEL *pMsg = (DVMSG_PLAYEROUTPUTLEVEL*)lpMessage;
  173. lpEvent->PlayerOutputLevel(pMsg->dvidSourcePlayerID,pMsg->dwPeakLevel);
  174. break;
  175. }
  176. case DVMSGID_CREATEVOICEPLAYER:
  177. {
  178. DVMSG_CREATEVOICEPLAYER *pMsg = (DVMSG_CREATEVOICEPLAYER*)lpMessage;
  179. lpEvent->CreateVoicePlayer(pMsg->dvidPlayer, pMsg->dwFlags);
  180. break;
  181. }
  182. case DVMSGID_DELETEVOICEPLAYER:
  183. {
  184. DVMSG_DELETEVOICEPLAYER *pMsg = (DVMSG_DELETEVOICEPLAYER*)lpMessage;
  185. lpEvent->DeleteVoicePlayer(pMsg->dvidPlayer);
  186. break;
  187. }
  188. case DVMSGID_SETTARGETS:
  189. break;
  190. }
  191. __try {
  192. if (lpPeer->m_pEventStream)
  193. // clean up marshaled packet
  194. CoReleaseMarshalData(lpPeer->m_pEventStream);
  195. }
  196. __except(EXCEPTION_EXECUTE_HANDLER)
  197. {
  198. lpPeer->m_fHandleVoiceClientEvents = FALSE;
  199. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  200. return S_OK;
  201. }
  202. DPF(1,"-----Leaving (VoiceServer) MessageHandler call...\n");
  203. InterlockedDecrement(&lpPeer->m_dwMsgCount);
  204. return S_OK;
  205. }
  206. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::Initialize (
  207. IUnknown *DplayObj,
  208. long lFlags)
  209. {
  210. HRESULT hr;
  211. IUnknown *lpDplay = NULL;
  212. I_dxj_DirectPlayPeer *lpPeer = NULL;
  213. I_dxj_DirectPlayClient *lpClient = NULL;
  214. I_dxj_DirectPlayServer *lpServer = NULL;
  215. __try {
  216. DPF(1,"-----Entering (VoiceServer) Initialize call...\n");
  217. // First we need to get our IUnknown pointer from whatever we pass in
  218. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayPeer, (void**)&lpPeer);
  219. if (SUCCEEDED(hr))
  220. {
  221. lpPeer->InternalGetObject(&lpDplay);
  222. SAFE_RELEASE(lpPeer);
  223. }
  224. else
  225. {
  226. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayClient, (void**)&lpClient);
  227. if (SUCCEEDED(hr))
  228. {
  229. lpClient->InternalGetObject(&lpDplay);
  230. SAFE_RELEASE(lpClient);
  231. }
  232. else
  233. {
  234. hr = DplayObj->QueryInterface(IID_I_dxj_DirectPlayServer, (void**)&lpServer);
  235. if (SUCCEEDED(hr))
  236. {
  237. lpServer->InternalGetObject(&lpDplay);
  238. SAFE_RELEASE(lpServer);
  239. }
  240. }
  241. }
  242. if (!lpDplay)
  243. return E_INVALIDARG;
  244. if (!m_fInit)
  245. {
  246. if (FAILED( hr=m__dxj_DirectPlayVoiceServer->Initialize(lpDplay, &VoiceMessageHandlerServer,
  247. this,0,(DWORD)lFlags)))
  248. return hr;
  249. m_fInit = TRUE;
  250. }
  251. }
  252. __except(EXCEPTION_EXECUTE_HANDLER)
  253. {
  254. return E_FAIL;
  255. }
  256. return S_OK;
  257. }
  258. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StartSession (
  259. DVSESSIONDESC_CDESC *SessionDesc,
  260. long lFlags)
  261. {
  262. DVSESSIONDESC dvSession;
  263. HRESULT hr;
  264. GUID pguidCT;
  265. __try {
  266. DPF(1,"-----Entering (VoiceServer) StartSession call...\n");
  267. FlushBuffer(0);
  268. ZeroMemory(&dvSession, sizeof(DVSESSIONDESC));
  269. dvSession.dwSize = sizeof(DVSESSIONDESC);
  270. dvSession.dwBufferAggressiveness = SessionDesc->lBufferAggressiveness;
  271. dvSession.dwBufferQuality = SessionDesc->lBufferQuality;
  272. dvSession.dwFlags = SessionDesc->lFlags;
  273. dvSession.dwSessionType = SessionDesc->lSessionType;
  274. if ( SessionDesc->guidCT == NULL )
  275. dvSession.guidCT = DPVCTGUID_DEFAULT;
  276. else
  277. {
  278. hr = DPLAYBSTRtoGUID(&pguidCT, SessionDesc->guidCT);
  279. dvSession.guidCT = pguidCT;
  280. }
  281. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->StartSession( &dvSession, (DWORD)lFlags)))
  282. return hr;
  283. }
  284. __except(EXCEPTION_EXECUTE_HANDLER)
  285. {
  286. return E_FAIL;
  287. }
  288. return S_OK;
  289. }
  290. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StopSession (
  291. long lFlags)
  292. {
  293. HRESULT hr;
  294. __try {
  295. DPF(1,"-----Entering (VoiceServer) StopSession call...\n");
  296. FlushBuffer(0);
  297. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->StopSession((DWORD)lFlags)))
  298. return hr;
  299. }
  300. __except(EXCEPTION_EXECUTE_HANDLER)
  301. {
  302. return E_FAIL;
  303. }
  304. return S_OK;
  305. }
  306. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetSessionDesc (
  307. DVSESSIONDESC_CDESC *SessionDesc)
  308. {
  309. HRESULT hr;
  310. DVSESSIONDESC dvSession;
  311. __try {
  312. DPF(1,"-----Entering (VoiceServer) GetSessionDesc call...\n");
  313. FlushBuffer(0);
  314. dvSession.dwSize = sizeof(DVSESSIONDESC);
  315. //Now get the buffer
  316. if ( FAILED(hr = m__dxj_DirectPlayVoiceServer->GetSessionDesc(&dvSession)))
  317. return hr;
  318. //Cast into return buffer
  319. SessionDesc->lFlags = (long)dvSession.dwFlags;
  320. SessionDesc->lSessionType = (long)dvSession.dwSessionType;
  321. SessionDesc->guidCT = GUIDtoBSTR(&dvSession.guidCT);
  322. SessionDesc->lBufferQuality = (long)dvSession.dwBufferQuality;
  323. SessionDesc->lBufferAggressiveness = (long)dvSession.dwBufferAggressiveness;
  324. }
  325. __except(EXCEPTION_EXECUTE_HANDLER)
  326. {
  327. return E_FAIL;
  328. }
  329. return S_OK;
  330. }
  331. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::SetSessionDesc (
  332. DVSESSIONDESC_CDESC *SessionDesc)
  333. {
  334. DVSESSIONDESC dvSession;
  335. HRESULT hr;
  336. GUID pguidCT;
  337. __try {
  338. DPF(1,"-----Entering (VoiceServer) SetSessionDesc call...\n");
  339. FlushBuffer(0);
  340. ZeroMemory(&dvSession, sizeof(DVSESSIONDESC));
  341. dvSession.dwSize = sizeof(DVSESSIONDESC);
  342. dvSession.dwBufferAggressiveness = SessionDesc->lBufferAggressiveness;
  343. dvSession.dwBufferQuality = SessionDesc->lBufferQuality;
  344. dvSession.dwFlags = SessionDesc->lFlags;
  345. dvSession.dwSessionType = SessionDesc->lSessionType;
  346. if ( SessionDesc->guidCT == NULL )
  347. dvSession.guidCT = DPVCTGUID_DEFAULT;
  348. else
  349. {
  350. hr = DPLAYBSTRtoGUID(&pguidCT, SessionDesc->guidCT);
  351. dvSession.guidCT = pguidCT;
  352. }
  353. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->SetSessionDesc(&dvSession)))
  354. return hr;
  355. }
  356. __except(EXCEPTION_EXECUTE_HANDLER)
  357. {
  358. return E_FAIL;
  359. }
  360. return S_OK;
  361. }
  362. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCaps (
  363. DVCAPS_CDESC *Caps)
  364. {
  365. HRESULT hr;
  366. __try {
  367. DPF(1,"-----Entering (VoiceServer) GetCaps call...\n");
  368. FlushBuffer(0);
  369. Caps->lSize=sizeof(DVCAPS);
  370. if (FAILED ( hr = m__dxj_DirectPlayVoiceServer->GetCaps((DVCAPS*)Caps)))
  371. return hr;
  372. }
  373. __except(EXCEPTION_EXECUTE_HANDLER)
  374. {
  375. return E_FAIL;
  376. }
  377. return S_OK;
  378. }
  379. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCompressionTypeCount (
  380. long *retval)
  381. {
  382. HRESULT hr;
  383. DWORD dwSize = 0;
  384. DWORD dwNumElements = 0;
  385. __try {
  386. DPF(1,"-----Entering (VoiceServer) GetCompressionTypeCount call...\n");
  387. FlushBuffer(0);
  388. hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(NULL, &dwSize, &dwNumElements ,0);
  389. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  390. return hr;
  391. *retval = (long)dwNumElements;
  392. }
  393. __except(EXCEPTION_EXECUTE_HANDLER)
  394. {
  395. return E_FAIL;
  396. }
  397. return S_OK;
  398. }
  399. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetCompressionType (
  400. long lIndex,
  401. DVCOMPRESSIONINFO_CDESC *Data,
  402. long lFlags)
  403. {
  404. HRESULT hr;
  405. LPBYTE pBuffer = NULL;
  406. DWORD dwSize = 0;
  407. DWORD dwNumElements = 0;
  408. LPDVCOMPRESSIONINFO pdvCompressionInfo;
  409. LPGUID pGuid;
  410. __try {
  411. DPF(1,"-----Entering (VoiceServer) GetCompressionType call...\n");
  412. FlushBuffer(0);
  413. hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements ,0);
  414. if ( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) ) //We didn't expect this error
  415. return hr;
  416. pBuffer = new BYTE[dwSize];
  417. if (!pBuffer)
  418. return E_OUTOFMEMORY;
  419. if ( FAILED ( hr = m__dxj_DirectPlayVoiceServer->GetCompressionTypes(pBuffer, &dwSize, &dwNumElements, (DWORD)lFlags)))
  420. return hr;
  421. if (lIndex > (long)dwNumElements)
  422. return DVERR_INVALIDPARAM;
  423. pdvCompressionInfo = (LPDVCOMPRESSIONINFO) pBuffer;
  424. pGuid = new GUID;
  425. if (!pGuid)
  426. return E_OUTOFMEMORY;
  427. // Ok, fill up our struct
  428. ZeroMemory(Data, sizeof(DVCOMPRESSIONINFO_CDESC));
  429. Data->lSize = sizeof(DVCOMPRESSIONINFO_CDESC);
  430. Data->lFlags = pdvCompressionInfo[lIndex-1].dwFlags;
  431. Data->lMaxBitsPerSecond = pdvCompressionInfo[lIndex-1].dwMaxBitsPerSecond;
  432. Data->strDescription = SysAllocString(pdvCompressionInfo[lIndex-1].lpszDescription);
  433. Data->strName = SysAllocString(pdvCompressionInfo[lIndex-1].lpszName);
  434. (*pGuid) = pdvCompressionInfo[lIndex-1].guidType;
  435. Data->guidType = GUIDtoBSTR(pGuid);
  436. SAFE_DELETE(pGuid);
  437. SAFE_DELETE(pBuffer);
  438. }
  439. __except(EXCEPTION_EXECUTE_HANDLER)
  440. {
  441. return E_FAIL;
  442. }
  443. return S_OK;
  444. }
  445. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::SetTransmitTargets (
  446. long playerSourceID,
  447. SAFEARRAY **playerTargetIDs,
  448. long lFlags)
  449. {
  450. HRESULT hr;
  451. DWORD dwNumTarget = ((SAFEARRAY*)*playerTargetIDs)->rgsabound[0].cElements;
  452. __try {
  453. DPF(1,"-----Entering (VoiceServer) SetTransmitTargets call...\n");
  454. FlushBuffer(0);
  455. if (FAILED( hr = m__dxj_DirectPlayVoiceServer->SetTransmitTargets((DVID)playerSourceID ,
  456. (DVID*)((SAFEARRAY*)*playerTargetIDs)->pvData, dwNumTarget, (DWORD) lFlags )))
  457. return hr;
  458. }
  459. __except(EXCEPTION_EXECUTE_HANDLER)
  460. {
  461. return E_FAIL;
  462. }
  463. return S_OK;
  464. }
  465. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::GetTransmitTargets (
  466. long playerSourceID,
  467. long lFlags,
  468. SAFEARRAY **ret)
  469. {
  470. HRESULT hr;
  471. DVID *dwPlayers = NULL;
  472. DWORD dwNumPlayers=0;
  473. SAFEARRAY *lpData = NULL;
  474. SAFEARRAYBOUND rgsabound[1];
  475. __try {
  476. DPF(1,"-----Entering (VoiceServer) GetTransmitTargets call...\n");
  477. FlushBuffer(0);
  478. hr =m__dxj_DirectPlayVoiceServer->GetTransmitTargets((DVID)playerSourceID, NULL, &dwNumPlayers, (DWORD) lFlags );
  479. if (FAILED(hr) && ( hr != DVERR_BUFFERTOOSMALL))
  480. return hr;
  481. dwPlayers = (DVID*)new BYTE[sizeof(DVID) * dwNumPlayers];
  482. if (!dwPlayers)
  483. return E_OUTOFMEMORY;
  484. if (FAILED( hr = m__dxj_DirectPlayVoiceServer->GetTransmitTargets((DVID)playerSourceID, dwPlayers, &dwNumPlayers, (DWORD) lFlags )))
  485. return hr;
  486. if (dwNumPlayers)
  487. {
  488. // Now let's create a safearray to pass back
  489. rgsabound[0].lLbound = 0;
  490. rgsabound[0].cElements = dwNumPlayers;
  491. lpData = SafeArrayCreate(VT_UI4, 1, rgsabound);
  492. memcpy(lpData->pvData,dwPlayers,sizeof(DVID) * dwNumPlayers);
  493. }
  494. *ret = lpData;
  495. SAFE_DELETE(dwPlayers);
  496. }
  497. __except(EXCEPTION_EXECUTE_HANDLER)
  498. {
  499. return E_FAIL;
  500. }
  501. return S_OK;
  502. }
  503. STDMETHODIMP C_dxj_DirectPlayVoiceServerObject::StartServerNotification(I_dxj_DPVoiceEvent *event)
  504. {
  505. HRESULT hr=S_OK;
  506. LPSTREAM pStm=NULL;
  507. if (!event) return E_INVALIDARG;
  508. DPF(1,"-----Entering (VoiceServer) StartServerNotification call...\n");
  509. SAFE_RELEASE(m_pEventStream);
  510. // Create a global stream. The stream needs to be global so we can
  511. // marshal once, and unmarshal as many times as necessary
  512. hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
  513. if FAILED(hr) return hr;
  514. // Now we can marshal our IUnknown interface. We use MSHLFLAGS_TABLEWEAK
  515. // so we can unmarshal any number of times
  516. hr = CoMarshalInterface(pStm, IID_I_dxj_DPVoiceEvent, event, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
  517. if FAILED(hr) return hr;
  518. // Now we need to set the seek location of the stream to the beginning
  519. LARGE_INTEGER l;
  520. l.QuadPart = 0;
  521. pStm->Seek(l, STREAM_SEEK_SET, NULL);
  522. m_pEventStream=pStm;
  523. m_fHandleVoiceClientEvents = TRUE;
  524. return hr;
  525. }
  526. HRESULT C_dxj_DirectPlayVoiceServerObject::UnRegisterMessageHandler()
  527. {
  528. DPF(1,"-----Entering (VoiceServer) UnregisterMessageHandler call...\n");
  529. m_fHandleVoiceClientEvents = FALSE;
  530. FlushBuffer(0);
  531. return S_OK;
  532. }
  533. HRESULT C_dxj_DirectPlayVoiceServerObject::FlushBuffer(LONG dwNumMessagesLeft)
  534. {
  535. DWORD dwTime = GetTickCount();
  536. DPF(1,"-----Entering (VoiceServer) FlushBuffer call...\n");
  537. //Clear out the messages currently waiting
  538. while (m_dwMsgCount > dwNumMessagesLeft)
  539. {
  540. if (GetTickCount() - dwTime > 5000)
  541. {
  542. // Don't let FlushBuffer wait more than 5 seconds
  543. DPF1(1,"-----Leaving (VoiceServer) FlushBuffer call (All messages *not* flushed - %d remained)...\n", m_dwMsgCount);
  544. return S_OK;
  545. }
  546. //Give another thread a chance
  547. Sleep(0);
  548. }
  549. DPF(1,"-----Leaving (VoiceServer) FlushBuffer call (All messages flushed)...\n");
  550. return S_OK;
  551. }