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.

1859 lines
38 KiB

  1. #include "precomp.h"
  2. #include "wbguid.h"
  3. #include "confroom.h"
  4. // SDK Includes
  5. #include "NmEnum.h"
  6. #include "SDKInternal.h"
  7. #include "NmManager.h"
  8. #include "NmConference.h"
  9. #include "NmMember.h"
  10. #include "NmCall.h"
  11. #include "SDKWindow.h"
  12. #include "NmChannelData.h"
  13. #include "NmChannelFt.h"
  14. #include "NmChannelAudio.h"
  15. #include "NmChannelVideo.h"
  16. #include "NmChannelAppShare.h"
  17. #include "NmSharableApp.h"
  18. #include "FtHook.h"
  19. extern INmManager2* g_pInternalNmManager;
  20. /////////////////////////////////////////////////////////
  21. // Construction/destruction
  22. /////////////////////////////////////////////////////////
  23. CNmConferenceObj::CNmConferenceObj()
  24. : m_dwInternalINmConferenceAdvise( 0 ),
  25. m_State(NM_CONFERENCE_IDLE),
  26. m_bFTHookedUp(false)
  27. {
  28. DBGENTRY(CNmConferenceObj::CNmConferenceObj);
  29. DBGEXIT(CNmConferenceObj::CNmConferenceObj);
  30. }
  31. CNmConferenceObj::~CNmConferenceObj()
  32. {
  33. DBGENTRY(CNmConferenceObj::~CNmConferenceObj);
  34. CFt::UnAdvise(this);
  35. m_bFTHookedUp = false;
  36. // this will protect us form re-deleting ourselves
  37. ++m_dwRef;
  38. _FreeInternalStuff();
  39. // We don't have to release because we didn't addref
  40. // This is safe because our lifetime is contianed in the CNmManageObj's lifetime
  41. m_pManagerObj = NULL;
  42. DBGEXIT(CNmConferenceObj::~CNmConferenceObj);
  43. }
  44. HRESULT CNmConferenceObj::FinalConstruct()
  45. {
  46. DBGENTRY(CNmConferenceObj::FinalConstruct);
  47. HRESULT hr = S_OK;
  48. if(m_spInternalINmConference)
  49. {
  50. hr = AtlAdvise(m_spInternalINmConference, GetUnknown(), IID_INmConferenceNotify2, &m_dwInternalINmConferenceAdvise);
  51. }
  52. else
  53. {
  54. hr = E_UNEXPECTED;
  55. }
  56. DBGEXIT_HR(CNmConferenceObj::FinalConstruct,hr);
  57. return hr;
  58. }
  59. ULONG CNmConferenceObj::InternalRelease()
  60. {
  61. ATLASSERT(m_dwRef > 0);
  62. --m_dwRef;
  63. if((1 == m_dwRef) && m_dwInternalINmConferenceAdvise)
  64. {
  65. ++m_dwRef;
  66. DWORD dwAdvise = m_dwInternalINmConferenceAdvise;
  67. CComPtr<INmConference> spConf = m_spInternalINmConference;
  68. m_spInternalINmConference = NULL;
  69. // This keeps us from getting here twice!
  70. m_dwInternalINmConferenceAdvise = 0;
  71. AtlUnadvise(spConf, IID_INmConferenceNotify2, dwAdvise);
  72. --m_dwRef;
  73. }
  74. return m_dwRef;
  75. }
  76. /*static*/ HRESULT CNmConferenceObj::InitSDK()
  77. {
  78. DBGENTRY(CNmConferenceObj::InitSDK);
  79. HRESULT hr = S_OK;
  80. DBGEXIT_HR(CNmConferenceObj::InitSDK,hr);
  81. return hr;
  82. }
  83. /*static*/void CNmConferenceObj::CleanupSDK()
  84. {
  85. DBGENTRY(CNmConferenceObj::CleanupSDK);
  86. DBGEXIT(CNmConferenceObj::CleanupSDK);
  87. }
  88. /*static*/
  89. HRESULT CNmConferenceObj::CreateInstance(CNmManagerObj* pManagerObj, INmConference* pInternalINmConferenece, INmConference** ppConference)
  90. {
  91. DBGENTRY(CNmConferenceObj::CreateInstance);
  92. HRESULT hr = S_OK;
  93. CComObject<CNmConferenceObj>* p = NULL;
  94. p = new CComObject<CNmConferenceObj>(NULL);
  95. if (p != NULL)
  96. {
  97. if(SUCCEEDED(hr))
  98. {
  99. CNmConferenceObj* pThis = static_cast<CNmConferenceObj*>(p);
  100. pThis->m_spInternalINmConference = pInternalINmConferenece;
  101. if(pInternalINmConferenece)
  102. {
  103. pInternalINmConferenece->GetState(&pThis->m_State);
  104. }
  105. // We don't have to RefCount this because our lifetime is
  106. // contained in the CNMManageuObj's lifetime
  107. pThis->m_pManagerObj = pManagerObj;
  108. }
  109. hr = _CreateInstanceGuts(p, ppConference);
  110. }
  111. DBGEXIT_HR(CNmConferenceObj::CreateInstance,hr);
  112. return hr;
  113. }
  114. /*static*/
  115. HRESULT CNmConferenceObj::_CreateInstanceGuts(CComObject<CNmConferenceObj> *p, INmConference** ppConference)
  116. {
  117. DBGENTRY(CNmConferenceObj::_CreateInstanceGuts);
  118. HRESULT hr = S_OK;
  119. if(ppConference)
  120. {
  121. if(p != NULL)
  122. {
  123. p->SetVoid(NULL);
  124. // We do this so that we don't accidentally Release out of memory
  125. ++p->m_dwRef;
  126. hr = p->FinalConstruct();
  127. --p->m_dwRef;
  128. if(hr == S_OK)
  129. hr = p->QueryInterface(IID_INmConference, reinterpret_cast<void**>(ppConference));
  130. if(FAILED(hr))
  131. { *ppConference = NULL;
  132. delete p;
  133. }
  134. }
  135. else
  136. {
  137. hr = E_UNEXPECTED;
  138. }
  139. }
  140. else
  141. {
  142. hr = E_POINTER;
  143. }
  144. DBGEXIT_HR(CNmConferenceObj::_CreateInstanceGuts,hr);
  145. return hr;
  146. }
  147. /////////////////////////////////////////////////////////
  148. // INmConference methods
  149. /////////////////////////////////////////////////////////
  150. STDMETHODIMP CNmConferenceObj::GetName(BSTR *pbstrName)
  151. {
  152. DBGENTRY(CNmConferenceObj::GetName);
  153. HRESULT hr = S_OK;
  154. if(m_spInternalINmConference)
  155. {
  156. hr = m_spInternalINmConference->GetName(pbstrName);
  157. }
  158. else
  159. {
  160. hr = E_UNEXPECTED;
  161. }
  162. return hr;
  163. }
  164. STDMETHODIMP CNmConferenceObj::GetID(ULONG * puID)
  165. {
  166. HRESULT hr = S_OK;
  167. if(m_spInternalINmConference)
  168. {
  169. hr = m_spInternalINmConference->GetID(puID);
  170. }
  171. else
  172. {
  173. hr = E_UNEXPECTED;
  174. }
  175. return hr;
  176. }
  177. STDMETHODIMP CNmConferenceObj::GetState(NM_CONFERENCE_STATE *pState)
  178. {
  179. DBGENTRY(CNmConferenceObj::GetState);
  180. HRESULT hr = S_OK;
  181. if(m_spInternalINmConference)
  182. {
  183. hr = m_spInternalINmConference->GetState(pState);
  184. }
  185. else
  186. {
  187. hr = E_UNEXPECTED;
  188. }
  189. DBGEXIT_HR(CNmConferenceObj::GetState,hr);
  190. return hr;
  191. }
  192. STDMETHODIMP CNmConferenceObj::GetNmchCaps(ULONG *puchCaps)
  193. {
  194. HRESULT hr = S_OK;
  195. if(m_spInternalINmConference)
  196. {
  197. hr = m_spInternalINmConference->GetNmchCaps(puchCaps);
  198. }
  199. else
  200. {
  201. hr = E_UNEXPECTED;
  202. }
  203. return hr;
  204. }
  205. STDMETHODIMP CNmConferenceObj::GetTopProvider(INmMember **ppMember)
  206. {
  207. HRESULT hr = E_FAIL;
  208. if(ppMember)
  209. { *ppMember = NULL;
  210. if(m_spInternalINmConference)
  211. {
  212. INmMember* pInternalMember;
  213. if(SUCCEEDED(m_spInternalINmConference->GetTopProvider(&pInternalMember)))
  214. {
  215. *ppMember = GetSDKMemberFromInternalMember(pInternalMember);
  216. if(*ppMember)
  217. {
  218. (*ppMember)->AddRef();
  219. hr = S_OK;
  220. }
  221. // This is commented out for clairity.
  222. // the GetTopProvider method in nmcom does not
  223. // actually addref the pointer (!)
  224. //pInternalMember->Release
  225. }
  226. }
  227. }
  228. else
  229. {
  230. hr = E_POINTER;
  231. }
  232. return hr;
  233. }
  234. STDMETHODIMP CNmConferenceObj::EnumMember(IEnumNmMember **ppEnum)
  235. {
  236. DBGENTRY(CNmConferenceObj::EnumMember);
  237. HRESULT hr = S_OK;
  238. if(ppEnum)
  239. {
  240. hr = CreateEnumFromSimpleAryOfInterface<IEnumNmMember, INmMember>(m_SDKMemberObjs, ppEnum);
  241. }
  242. else
  243. {
  244. hr = E_POINTER;
  245. }
  246. DBGEXIT_HR(CNmConferenceObj::EnumMember,hr);
  247. return hr;
  248. }
  249. STDMETHODIMP CNmConferenceObj::GetMemberCount(ULONG *puCount)
  250. {
  251. DBGENTRY(CNmConferenceObj::GetMemberCount);
  252. HRESULT hr = S_OK;
  253. if(puCount)
  254. {
  255. *puCount = m_SDKMemberObjs.GetSize();
  256. }
  257. else
  258. {
  259. hr = E_POINTER;
  260. }
  261. DBGEXIT_HR(CNmConferenceObj::GetMemberCount,hr);
  262. return hr;
  263. }
  264. STDMETHODIMP CNmConferenceObj::CreateChannel(INmChannel **ppChannel, ULONG uNmCh, INmMember *pMember)
  265. {
  266. ATLTRACENOTIMPL(_T("CNmConferenceObj::GetName"));
  267. }
  268. STDMETHODIMP CNmConferenceObj::EnumChannel(IEnumNmChannel **ppEnum)
  269. {
  270. DBGENTRY(CNmConferenceObj::EnumChannel);
  271. HRESULT hr = E_NOTIMPL;
  272. if(ppEnum)
  273. {
  274. hr = CreateEnumFromSimpleAryOfInterface<IEnumNmChannel, INmChannel>(m_SDKChannelObjs, ppEnum);
  275. }
  276. else
  277. {
  278. hr = E_POINTER;
  279. }
  280. DBGEXIT_HR(CNmConferenceObj::EnumChannel,hr);
  281. return hr;
  282. }
  283. STDMETHODIMP CNmConferenceObj::GetChannelCount(ULONG *puCount)
  284. {
  285. DBGENTRY(CNmConferenceObj::GetChannelCount);
  286. HRESULT hr = S_OK;
  287. if(puCount)
  288. {
  289. *puCount = m_SDKChannelObjs.GetSize();
  290. }
  291. else
  292. {
  293. hr = E_POINTER;
  294. }
  295. DBGEXIT_HR(CNmConferenceObj::GetChannelCount,hr);
  296. return hr;
  297. }
  298. // NetMeeting 2.0 chat guid: {340F3A60-7067-11D0-A041-444553540000}
  299. const GUID g_guidNM2Chat =
  300. { 0x340f3a60, 0x7067, 0x11d0, { 0xa0, 0x41, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } };
  301. STDMETHODIMP CNmConferenceObj::CreateDataChannel(INmChannelData **ppChannel, REFGUID rguid)
  302. {
  303. HRESULT hr = S_OK;
  304. if(m_spInternalINmConference)
  305. {
  306. if(!InlineIsEqualGUID(rguid, g_guidNM2Chat))
  307. {
  308. GUID g = rguid;
  309. if(!_IsGuidInDataChannelList(g))
  310. {
  311. m_DataChannelGUIDList.Add(g);
  312. }
  313. CComPtr<INmChannelData> spInternalDataChannel;
  314. hr = m_spInternalINmConference->CreateDataChannel(&spInternalDataChannel, rguid);
  315. if(SUCCEEDED(hr))
  316. {
  317. INmChannel* pSDKChannel = GetSDKChannelFromInternalChannel(spInternalDataChannel);
  318. if(pSDKChannel && ppChannel)
  319. {
  320. *ppChannel = com_cast<INmChannelData>(pSDKChannel);
  321. if(*ppChannel)
  322. {
  323. (*ppChannel)->AddRef();
  324. }
  325. else
  326. {
  327. hr = E_UNEXPECTED;
  328. }
  329. }
  330. }
  331. else
  332. {
  333. m_DataChannelGUIDList.Remove(g);
  334. }
  335. }
  336. else
  337. {
  338. hr = NM_E_CHANNEL_ALREADY_EXISTS;
  339. }
  340. }
  341. else
  342. {
  343. hr = NM_E_NO_T120_CONFERENCE;
  344. }
  345. return hr;
  346. }
  347. STDMETHODIMP CNmConferenceObj::Host(void)
  348. {
  349. HRESULT hr = S_OK;
  350. if(m_spInternalINmConference)
  351. {
  352. hr = m_spInternalINmConference->Host();
  353. }
  354. else
  355. {
  356. hr = E_UNEXPECTED;
  357. }
  358. return hr;
  359. }
  360. STDMETHODIMP CNmConferenceObj::Leave(void)
  361. {
  362. DBGENTRY(CNmConferenceObj::Leave);
  363. HRESULT hr = S_OK;
  364. if(m_spInternalINmConference)
  365. {
  366. hr = m_spInternalINmConference->Leave();
  367. _FreeInternalStuff();
  368. if(!m_pManagerObj->OfficeMode())
  369. {
  370. StateChanged(NM_CONFERENCE_IDLE);
  371. }
  372. }
  373. else
  374. {
  375. hr = E_UNEXPECTED;
  376. }
  377. DBGEXIT_HR(CNmConferenceObj::Leave,hr);
  378. return hr;
  379. }
  380. STDMETHODIMP CNmConferenceObj::IsHosting(void)
  381. {
  382. HRESULT hr = E_UNEXPECTED;
  383. if(m_spInternalINmConference)
  384. {
  385. hr = m_spInternalINmConference->IsHosting();
  386. }
  387. return hr;
  388. }
  389. STDMETHODIMP CNmConferenceObj::LaunchRemote(REFGUID rguid, INmMember *pMember)
  390. {
  391. HRESULT hr = E_UNEXPECTED;
  392. if(m_spInternalINmConference)
  393. {
  394. CComPtr<INmMember> spInternalMember;
  395. if(pMember)
  396. {
  397. CComPtr<IInternalMemberObj> spObj = com_cast<IInternalMemberObj>(pMember);
  398. ASSERT(spObj);
  399. spObj->GetInternalINmMember(&spInternalMember);
  400. }
  401. hr = m_spInternalINmConference->LaunchRemote(rguid, spInternalMember);
  402. }
  403. return hr;
  404. }
  405. /////////////////////////////////////////////////
  406. // INmConferenceNotify2 methods:
  407. /////////////////////////////////////////////////
  408. STDMETHODIMP CNmConferenceObj::NmUI(CONFN uNotify)
  409. {
  410. DBGENTRY(CNmConferenceObj::NmUI);
  411. HRESULT hr = S_OK;
  412. hr = Fire_NmUI(uNotify);
  413. DBGEXIT_HR(CNmConferenceObj::NmUI,hr);
  414. return hr;
  415. }
  416. void CNmConferenceObj::_EnsureSentConferenceCreatedNotification()
  417. {
  418. if(m_pManagerObj && !m_pManagerObj->m_bSentConferenceCreated)
  419. {
  420. // If we have not sent conference created, send it now!
  421. CComQIPtr<INmConference> spConf(GetUnknown());
  422. m_pManagerObj->Fire_ConferenceCreated(spConf);
  423. }
  424. }
  425. STDMETHODIMP CNmConferenceObj::StateChanged(NM_CONFERENCE_STATE uState)
  426. {
  427. DBGENTRY(CNmConferenceObj::StateChanged);
  428. HRESULT hr = S_OK;
  429. if(m_State != uState)
  430. {
  431. m_State = uState;
  432. if(m_State == NM_CONFERENCE_IDLE)
  433. {
  434. if(m_bFTHookedUp)
  435. {
  436. CFt::UnAdvise(this);
  437. m_bFTHookedUp = false;
  438. }
  439. if(m_pManagerObj)
  440. {
  441. m_pManagerObj->m_bSentConferenceCreated = false;
  442. }
  443. _FreeInternalStuff();
  444. }
  445. else if(NM_CONFERENCE_ACTIVE == m_State)
  446. {
  447. EnsureFTChannel();
  448. }
  449. hr = Fire_StateChanged(uState);
  450. if(NM_CONFERENCE_WAITING == m_State)
  451. {
  452. _EnsureSentConferenceCreatedNotification();
  453. }
  454. }
  455. DBGEXIT_HR(CNmConferenceObj::StateChanged,hr);
  456. return hr;
  457. }
  458. void CNmConferenceObj::AddMemberToAsChannel(INmMember* pSDKMember)
  459. {
  460. INmChannel* pChannel = _GetAppSharingChannel();
  461. if(pChannel)
  462. {
  463. com_cast<IInternalChannelObj>(pChannel)->SDKMemberAdded(pSDKMember);
  464. }
  465. }
  466. void CNmConferenceObj::RemoveMemberFromAsChannel(INmMember* pSDKMember)
  467. {
  468. INmChannel* pChannel = _GetAppSharingChannel();
  469. if(pChannel)
  470. {
  471. com_cast<IInternalChannelObj>(pChannel)->SDKMemberRemoved(pSDKMember);
  472. }
  473. }
  474. void CNmConferenceObj::AddMemberToFtChannel(INmMember* pSDKMember)
  475. {
  476. INmChannel* pChannel = _GetFtChannel();
  477. if(pChannel)
  478. {
  479. com_cast<IInternalChannelObj>(pChannel)->SDKMemberAdded(pSDKMember);
  480. }
  481. }
  482. void CNmConferenceObj::RemoveMemberFromFtChannel(INmMember* pSDKMember)
  483. {
  484. INmChannel* pChannel = _GetFtChannel();
  485. if(pChannel)
  486. {
  487. com_cast<IInternalChannelObj>(pChannel)->SDKMemberRemoved(pSDKMember);
  488. }
  489. }
  490. STDMETHODIMP CNmConferenceObj::MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pInternalMember)
  491. {
  492. DBGENTRY(CNmConferenceObj::MemberChanged);
  493. HRESULT hr = S_OK;
  494. if(pInternalMember)
  495. {
  496. CComPtr<INmMember> spMember;
  497. if(NM_MEMBER_ADDED == uNotify)
  498. {
  499. if(NULL == _GetAppSharingChannel())
  500. {
  501. // We don't get notified of this channel, so
  502. // we have to add it manually
  503. _AddAppShareChannel();
  504. }
  505. // We actually get this notification multiple times, so just check to make sure...
  506. if(!GetSDKMemberFromInternalMember(pInternalMember))
  507. {
  508. hr = CNmMemberObj::CreateInstance(this, pInternalMember, &spMember);
  509. if(SUCCEEDED(hr))
  510. {
  511. spMember.p->AddRef();
  512. m_SDKMemberObjs.Add(spMember.p);
  513. }
  514. }
  515. }
  516. CComPtr<INmMember> spSDKMember = GetSDKMemberFromInternalMember(pInternalMember);
  517. if(NM_MEMBER_REMOVED == uNotify)
  518. {
  519. _RemoveMember(pInternalMember);
  520. }
  521. Fire_MemberChanged(uNotify, spSDKMember);
  522. if((NM_MEMBER_ADDED == uNotify) || (NM_MEMBER_UPDATED == uNotify))
  523. {
  524. // Add the member to the AS Channel iff they have NMCH_DATA
  525. ASSERT(spSDKMember);
  526. ULONG uchCaps = 0;
  527. if(SUCCEEDED(spSDKMember->GetNmchCaps(&uchCaps)))
  528. {
  529. if(NMCH_DATA & uchCaps)
  530. {
  531. // This method will handle being called multiple times for the same member
  532. AddMemberToAsChannel(spSDKMember);
  533. }
  534. }
  535. }
  536. if(SUCCEEDED(hr) && (uNotify != NM_MEMBER_REMOVED))
  537. {
  538. ULONG ulGCCid;
  539. if(SUCCEEDED(spSDKMember->GetID(&ulGCCid)))
  540. {
  541. if(CFt::IsMemberInFtSession(static_cast<T120NodeID>(ulGCCid)))
  542. {
  543. // Make sure that the user is in the channel
  544. AddMemberToFtChannel(spSDKMember);
  545. }
  546. }
  547. _EnsureMemberHasAVChannelsIfNeeded(spSDKMember);
  548. }
  549. }
  550. else
  551. {
  552. WARNING_OUT(("Why are we pased a NULL member?"));
  553. }
  554. DBGEXIT_HR(CNmConferenceObj::MemberChanged,hr);
  555. return hr;
  556. }
  557. STDMETHODIMP CNmConferenceObj::FireNotificationsToSyncState()
  558. {
  559. // this is no longer used...
  560. ASSERT(0);
  561. return S_OK;
  562. }
  563. STDMETHODIMP CNmConferenceObj::EnsureFTChannel()
  564. {
  565. if(m_pManagerObj && m_pManagerObj->FileTransferNotifications())
  566. {
  567. if(!m_bFTHookedUp)
  568. {
  569. // When the conference is active, we should add ourselves
  570. CFt::Advise(this);
  571. _EnsureFtChannelAdded();
  572. m_bFTHookedUp = true;
  573. if(CFt::IsFtActive())
  574. {
  575. // This means that the channel is Active
  576. INmChannel* pChannel = _GetFtChannel();
  577. if(pChannel)
  578. {
  579. com_cast<IInternalChannelObj>(pChannel)->Activate(true);
  580. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  581. }
  582. }
  583. }
  584. }
  585. return S_OK;
  586. }
  587. STDMETHODIMP CNmConferenceObj::AudioChannelActiveState(BOOL bActive, BOOL bIsIncoming)
  588. {
  589. INmChannel* pChannel = _GetAudioChannel(bIsIncoming);
  590. if(pChannel && ((pChannel->IsActive() == S_OK) != bActive))
  591. {
  592. com_cast<IInternalChannelObj>(pChannel)->Activate(bActive);
  593. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  594. }
  595. return S_OK;
  596. }
  597. STDMETHODIMP CNmConferenceObj::VideoChannelActiveState(BOOL bActive, BOOL bIsIncoming)
  598. {
  599. INmChannel* pChannel = _GetVideoChannel(bIsIncoming);
  600. if(pChannel && ((pChannel->IsActive() == S_OK) != bActive))
  601. {
  602. com_cast<IInternalChannelObj>(pChannel)->Activate(bActive);
  603. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  604. }
  605. return S_OK;
  606. }
  607. STDMETHODIMP CNmConferenceObj::VideoChannelPropChanged(DWORD dwProp, BOOL bIsIncoming)
  608. {
  609. INmChannel* pChannel = _GetVideoChannel(bIsIncoming);
  610. if(pChannel)
  611. {
  612. com_cast<INmChannelVideoNotify>(pChannel)->PropertyChanged(dwProp);
  613. }
  614. return S_OK;
  615. }
  616. STDMETHODIMP CNmConferenceObj::VideoChannelStateChanged(NM_VIDEO_STATE uState, BOOL bIsIncoming)
  617. {
  618. INmChannel* pChannel = _GetVideoChannel(bIsIncoming);
  619. if(pChannel)
  620. {
  621. com_cast<INmChannelVideoNotify>(pChannel)->StateChanged(uState);
  622. }
  623. return S_OK;
  624. }
  625. STDMETHODIMP CNmConferenceObj::ChannelChanged(NM_CHANNEL_NOTIFY uNotify, INmChannel *pInternalChannel)
  626. {
  627. DBGENTRY(CNmConferenceObj::ChannelChanged);
  628. HRESULT hr = S_OK;
  629. if(pInternalChannel)
  630. {
  631. if(NM_CHANNEL_ADDED == uNotify)
  632. {
  633. ULONG ulCh = NMCH_NONE;
  634. hr = pInternalChannel->GetNmch(&ulCh);
  635. if(SUCCEEDED(hr))
  636. {
  637. CComPtr<INmChannel> spChannel;
  638. hr = E_UNEXPECTED;
  639. switch(ulCh)
  640. {
  641. case NMCH_VIDEO:
  642. // this means that the channel is "Active"
  643. {
  644. BOOL bIncoming = (S_OK == com_cast<INmChannelVideo>(pInternalChannel)->IsIncoming());
  645. INmChannel* pVidChannel = _GetVideoChannel(bIncoming);
  646. if(pVidChannel)
  647. {
  648. com_cast<IInternalChannelObj>(pVidChannel)->Activate(true);
  649. }
  650. else
  651. {
  652. if(bIncoming)
  653. {
  654. m_bRemoteVideoActive = true;
  655. }
  656. else
  657. {
  658. m_bLocalVideoActive = true;
  659. }
  660. }
  661. }
  662. break;
  663. case NMCH_AUDIO:
  664. // this means that the channel is "Active"
  665. {
  666. BOOL bIncoming = (S_OK == com_cast<INmChannelAudio>(pInternalChannel)->IsIncoming());
  667. INmChannel* pAudioChannel = _GetAudioChannel(bIncoming);
  668. if(pAudioChannel)
  669. {
  670. com_cast<IInternalChannelObj>(pAudioChannel)->Activate(true);
  671. }
  672. }
  673. break;
  674. case NMCH_DATA:
  675. if(m_pManagerObj && m_pManagerObj->DataNotifications())
  676. {
  677. if(pInternalChannel)
  678. {
  679. CComPtr<INmChannelData> spDataChannel = com_cast<INmChannelData>(pInternalChannel);
  680. GUID g;
  681. if(spDataChannel && SUCCEEDED(spDataChannel->GetGuid(&g)))
  682. {
  683. if(_IsGuidInDataChannelList(g))
  684. {
  685. // We only do this if this GUID is in our list
  686. hr = CNmChannelDataObj::CreateInstance(this, pInternalChannel, &spChannel);
  687. }
  688. }
  689. }
  690. }
  691. break;
  692. case NMCH_FT:
  693. break;
  694. case NMCH_SHARE:
  695. // Currently, we don't get notified of the App Sharing "channel"
  696. default:
  697. ERROR_OUT(("Unknown channel type"));
  698. break;
  699. }
  700. if(SUCCEEDED(hr))
  701. {
  702. spChannel.p->AddRef();
  703. m_SDKChannelObjs.Add(spChannel.p);
  704. Fire_ChannelChanged(NM_CHANNEL_ADDED, spChannel);
  705. // Add all the members from the internal channel
  706. CComPtr<IEnumNmMember> spEnumMember;
  707. if(SUCCEEDED(pInternalChannel->EnumMember(&spEnumMember)))
  708. {
  709. INmMember* pMember = NULL;
  710. ULONG ulFetched = 0;
  711. while(S_OK == spEnumMember->Next(1, &pMember, &ulFetched))
  712. {
  713. CComPtr<INmMember> spSDKMember = GetSDKMemberFromInternalMember(pMember);
  714. if(spSDKMember)
  715. {
  716. com_cast<IInternalChannelObj>(spChannel)->SDKMemberAdded(spSDKMember);
  717. }
  718. else
  719. {
  720. ERROR_OUT(("We should not have members of a channel before they are in the conference"));
  721. }
  722. pMember->Release();
  723. pMember = NULL;
  724. }
  725. }
  726. }
  727. }
  728. }
  729. else
  730. {
  731. INmChannel* pChannel = GetSDKChannelFromInternalChannel(pInternalChannel);
  732. if(SUCCEEDED(hr) && pChannel)
  733. {
  734. if(NM_CHANNEL_REMOVED == uNotify)
  735. {
  736. _RemoveChannel(pChannel);
  737. }
  738. else
  739. {
  740. Fire_ChannelChanged(uNotify, pChannel);
  741. }
  742. }
  743. }
  744. }
  745. else
  746. {
  747. hr = E_UNEXPECTED;
  748. ERROR_OUT(("ChannelChanged was passed a NULL INmChannel"));
  749. }
  750. DBGEXIT_HR(CNmConferenceObj::ChannelChanged,hr);
  751. return hr;
  752. }
  753. STDMETHODIMP CNmConferenceObj::StreamEvent(NM_STREAMEVENT uEvent, UINT uSubCode, INmChannel *pInternalChannel)
  754. {
  755. DBGENTRY(CNmConferenceObj::StreamEvent);
  756. HRESULT hr = S_OK;
  757. DBGEXIT_HR(CNmConferenceObj::StreamEvent,hr);
  758. return hr;
  759. }
  760. // IMbftEvent Interface
  761. STDMETHODIMP CNmConferenceObj::OnInitializeComplete(void)
  762. {
  763. // This means that the channel is Active
  764. INmChannel* pChannel = _GetFtChannel();
  765. if(pChannel)
  766. {
  767. com_cast<IInternalChannelObj>(pChannel)->Activate(true);
  768. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  769. }
  770. return S_OK;
  771. }
  772. STDMETHODIMP CNmConferenceObj::OnPeerAdded(MBFT_PEER_INFO *pInfo)
  773. {
  774. CComPtr<INmMember> spMember;
  775. HRESULT hr = E_FAIL;
  776. if(CFt::IsMemberInFtSession(pInfo->NodeID))
  777. {
  778. hr = GetMemberFromNodeID(pInfo->NodeID, &spMember);
  779. if(SUCCEEDED(hr))
  780. {
  781. AddMemberToFtChannel(spMember);
  782. }
  783. }
  784. return hr;
  785. }
  786. STDMETHODIMP CNmConferenceObj::OnPeerRemoved(MBFT_PEER_INFO *pInfo)
  787. {
  788. CComPtr<INmMember> spMember;
  789. HRESULT hr = GetMemberFromNodeID(pInfo->NodeID, &spMember);
  790. if(SUCCEEDED(hr))
  791. {
  792. RemoveMemberFromFtChannel(spMember);
  793. }
  794. return S_OK;
  795. }
  796. STDMETHODIMP CNmConferenceObj::OnFileOffer(MBFT_FILE_OFFER *pOffer)
  797. {
  798. // The FT Channel and FT Object will handle this
  799. return S_OK;
  800. }
  801. STDMETHODIMP CNmConferenceObj::OnFileProgress(MBFT_FILE_PROGRESS *pProgress)
  802. {
  803. // The FT Channel and FT Object will handle this
  804. return S_OK;
  805. }
  806. STDMETHODIMP CNmConferenceObj::OnFileEnd(MBFTFILEHANDLE hFile)
  807. {
  808. // The FT Channel and FT Object will handle this
  809. return S_OK;
  810. }
  811. STDMETHODIMP CNmConferenceObj::OnFileError(MBFT_EVENT_ERROR *pEvent)
  812. {
  813. // The FT Channel and FT Object will handle this
  814. return S_OK;
  815. }
  816. STDMETHODIMP CNmConferenceObj::OnFileEventEnd(MBFTEVENTHANDLE hEvent)
  817. {
  818. // The FT Channel and FT Object will handle this
  819. return S_OK;
  820. }
  821. STDMETHODIMP CNmConferenceObj::OnSessionEnd(void)
  822. {
  823. // This means that the channel is Active
  824. INmChannel* pChannel = _GetFtChannel();
  825. if(pChannel)
  826. {
  827. com_cast<IInternalChannelObj>(pChannel)->Activate(false);
  828. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  829. _RemoveChannel(pChannel);
  830. }
  831. CFt::UnAdvise(this);
  832. m_bFTHookedUp = false;
  833. return S_OK;
  834. }
  835. ////////////////////////////////////////////////////////////////////////
  836. //IInternalConferenceObj
  837. ////////////////////////////////////////////////////////////////////////
  838. STDMETHODIMP CNmConferenceObj::GetInternalINmConference(INmConference** ppConference)
  839. {
  840. DBGENTRY(CNmConferenceObj::GetInternalINmConference);
  841. HRESULT hr = S_OK;
  842. ASSERT(ppConference);
  843. *ppConference = m_spInternalINmConference;
  844. if(*ppConference)
  845. {
  846. (*ppConference)->AddRef();
  847. }
  848. DBGEXIT_HR(CNmConferenceObj::GetInternalINmConference,hr);
  849. return hr;
  850. }
  851. STDMETHODIMP CNmConferenceObj::GetMemberFromNodeID(DWORD dwNodeID, INmMember** ppMember)
  852. {
  853. HRESULT hr = E_POINTER;
  854. if(ppMember)
  855. {
  856. hr = E_FAIL;
  857. for(int i = 0; i < m_SDKMemberObjs.GetSize(); ++i)
  858. {
  859. DWORD dwGCCID;
  860. HRESULT hrRes;
  861. if(SUCCEEDED(hrRes = m_SDKMemberObjs[i]->GetID(&dwGCCID)))
  862. {
  863. if(dwGCCID == dwNodeID)
  864. {
  865. *ppMember = m_SDKMemberObjs[i];
  866. (*ppMember)->AddRef();
  867. hr = S_OK;
  868. }
  869. }
  870. else hr = hrRes;
  871. }
  872. }
  873. return hr;
  874. }
  875. STDMETHODIMP CNmConferenceObj::RemoveAllMembersAndChannels()
  876. {
  877. HRESULT hr = S_OK;
  878. _FreeInternalStuff();
  879. return hr;
  880. }
  881. STDMETHODIMP CNmConferenceObj::AppSharingChannelChanged()
  882. {
  883. HRESULT hr = E_UNEXPECTED;
  884. INmChannel* pChannel = _GetAppSharingChannel();
  885. if(pChannel)
  886. {
  887. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  888. }
  889. return hr;
  890. }
  891. STDMETHODIMP CNmConferenceObj::FireNotificationsToSyncToInternalObject()
  892. {
  893. if(m_spInternalINmConference)
  894. {
  895. // Add all the members from the internal conference
  896. CComPtr<IEnumNmMember> spEnumMember;
  897. if(SUCCEEDED(m_spInternalINmConference->EnumMember(&spEnumMember)))
  898. {
  899. INmMember* pMember = NULL;
  900. ULONG ulFetched = 0;
  901. while(S_OK == spEnumMember->Next(1, &pMember, &ulFetched))
  902. {
  903. MemberChanged(NM_MEMBER_ADDED, pMember);
  904. pMember->Release();
  905. pMember = NULL;
  906. }
  907. }
  908. // Fire the CHANNEL_ADDED notifications
  909. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  910. {
  911. Fire_ChannelChanged(NM_CHANNEL_ADDED, m_SDKChannelObjs[i]);
  912. // Tell the channel to fire the MEMBER_ADDED notificaitnos, etc.
  913. com_cast<IInternalChannelObj>(m_SDKChannelObjs[i])->FireNotificationsToSyncState();
  914. }
  915. if(0 != m_SDKMemberObjs.GetSize())
  916. {
  917. if(NULL == _GetAppSharingChannel())
  918. {
  919. // We don't get notified of this channel, so
  920. // we have to add it manually
  921. _AddAppShareChannel();
  922. }
  923. EnsureFTChannel();
  924. for(i = 0; i < m_SDKMemberObjs.GetSize(); ++i)
  925. {
  926. ULONG uchCaps = 0;
  927. if(SUCCEEDED(m_SDKMemberObjs[i]->GetNmchCaps(&uchCaps)))
  928. {
  929. if(NMCH_DATA & uchCaps)
  930. {
  931. // This method will handle being called multiple times for the same member
  932. AddMemberToAsChannel(m_SDKMemberObjs[i]);
  933. }
  934. }
  935. ULONG ulGCCid;
  936. if(SUCCEEDED(m_SDKMemberObjs[i]->GetID(&ulGCCid)))
  937. {
  938. if(CFt::IsMemberInFtSession(static_cast<T120NodeID>(ulGCCid)))
  939. {
  940. // Make sure that the user is in the channel
  941. AddMemberToFtChannel(m_SDKMemberObjs[i]);
  942. }
  943. }
  944. }
  945. }
  946. }
  947. return S_OK;
  948. }
  949. STDMETHODIMP CNmConferenceObj::AppSharingStateChanged(BOOL bActive)
  950. {
  951. HRESULT hr = E_UNEXPECTED;
  952. INmChannel* pChannel = _GetAppSharingChannel();
  953. if(pChannel)
  954. {
  955. com_cast<IInternalChannelObj>(pChannel)->Activate(bActive);
  956. Fire_ChannelChanged(NM_CHANNEL_UPDATED, pChannel);
  957. }
  958. return hr;
  959. }
  960. INmChannel* CNmConferenceObj::_GetAppSharingChannel()
  961. {
  962. INmChannel* pChannel = NULL;
  963. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  964. {
  965. ULONG ulch;
  966. if(SUCCEEDED(m_SDKChannelObjs[i]->GetNmch(&ulch)))
  967. {
  968. if(NMCH_SHARE == ulch)
  969. {
  970. pChannel = m_SDKChannelObjs[i];
  971. break;
  972. }
  973. }
  974. }
  975. return pChannel;
  976. }
  977. INmChannel* CNmConferenceObj::_GetFtChannel()
  978. {
  979. INmChannel* pChannel = NULL;
  980. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  981. {
  982. ULONG ulch;
  983. if(SUCCEEDED(m_SDKChannelObjs[i]->GetNmch(&ulch)))
  984. {
  985. if(NMCH_FT == ulch)
  986. {
  987. pChannel = m_SDKChannelObjs[i];
  988. break;
  989. }
  990. }
  991. }
  992. return pChannel;
  993. }
  994. INmChannel* CNmConferenceObj::_GetAudioChannel(BOOL bIncoming)
  995. {
  996. INmChannel* pChannel = NULL;
  997. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  998. {
  999. ULONG ulch;
  1000. if(SUCCEEDED(m_SDKChannelObjs[i]->GetNmch(&ulch)))
  1001. {
  1002. if((NMCH_AUDIO == ulch) && ((S_OK == com_cast<INmChannelAudio>(m_SDKChannelObjs[i])->IsIncoming()) == bIncoming))
  1003. {
  1004. pChannel = m_SDKChannelObjs[i];
  1005. break;
  1006. }
  1007. }
  1008. }
  1009. return pChannel;
  1010. }
  1011. INmChannel* CNmConferenceObj::_GetVideoChannel(BOOL bIncoming)
  1012. {
  1013. INmChannel* pChannel = NULL;
  1014. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  1015. {
  1016. ULONG ulch;
  1017. if(SUCCEEDED(m_SDKChannelObjs[i]->GetNmch(&ulch)))
  1018. {
  1019. if((NMCH_VIDEO == ulch) && ((S_OK == com_cast<INmChannelVideo>(m_SDKChannelObjs[i])->IsIncoming()) == bIncoming))
  1020. {
  1021. pChannel = m_SDKChannelObjs[i];
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. return pChannel;
  1027. }
  1028. STDMETHODIMP CNmConferenceObj::SharableAppStateChanged(HWND hWnd, NM_SHAPP_STATE state)
  1029. {
  1030. INmChannel* pChannelAs = _GetAppSharingChannel();
  1031. HRESULT hr = S_OK;
  1032. if(pChannelAs)
  1033. {
  1034. CComPtr<INmSharableApp> spSharableApp;
  1035. TCHAR szName[MAX_PATH];
  1036. hr = CNmChannelAppShareObj::GetSharableAppName(hWnd, szName, CCHMAX(szName));
  1037. if(SUCCEEDED(hr))
  1038. {
  1039. hr = CNmSharableAppObj::CreateInstance(hWnd, szName, &spSharableApp);
  1040. if(SUCCEEDED(hr))
  1041. {
  1042. com_cast<INmChannelAppShareNotify>(pChannelAs)->StateChanged(state, spSharableApp);
  1043. }
  1044. }
  1045. }
  1046. return hr;
  1047. }
  1048. STDMETHODIMP CNmConferenceObj::ASLocalMemberChanged()
  1049. {
  1050. return _ASMemberChanged(GetLocalSDKMember());
  1051. }
  1052. STDMETHODIMP CNmConferenceObj::ASMemberChanged(UINT gccID)
  1053. {
  1054. CComPtr<INmMember> spMember;
  1055. HRESULT hr = GetMemberFromNodeID(gccID, &spMember);
  1056. if(SUCCEEDED(hr))
  1057. {
  1058. hr = _ASMemberChanged(spMember);
  1059. }
  1060. return hr;
  1061. }
  1062. HRESULT CNmConferenceObj::_ASMemberChanged(INmMember *pSDKMember)
  1063. {
  1064. if(pSDKMember)
  1065. {
  1066. Fire_MemberChanged(NM_MEMBER_UPDATED, pSDKMember);
  1067. INmChannel* pChannel = _GetAppSharingChannel();
  1068. if(pChannel)
  1069. {
  1070. com_cast<IInternalChannelObj>(pChannel)->SDKMemberChanged(pSDKMember);
  1071. }
  1072. }
  1073. else
  1074. {
  1075. return E_UNEXPECTED;
  1076. }
  1077. return S_OK;
  1078. }
  1079. ////////////////////////////////////////////////////////////////////////
  1080. // Notifications
  1081. ////////////////////////////////////////////////////////////////////////
  1082. HRESULT CNmConferenceObj::Fire_NmUI(CONFN uNotify)
  1083. {
  1084. DBGENTRY(CNmConferenceObj::Fire_NmUI)
  1085. HRESULT hr = S_OK;
  1086. if(!g_bSDKPostNotifications)
  1087. {
  1088. /////////////////////////////////////////////////////
  1089. // INmConferenceNotify
  1090. /////////////////////////////////////////////////////
  1091. IConnectionPointImpl<CNmConferenceObj, &IID_INmConferenceNotify, CComDynamicUnkArray>* pCP = this;
  1092. for(int i = 0; i < pCP->m_vec.GetSize(); ++i )
  1093. {
  1094. INmConferenceNotify* pNotify = reinterpret_cast<INmConferenceNotify*>(pCP->m_vec.GetAt(i));
  1095. if(pNotify)
  1096. {
  1097. pNotify->NmUI(uNotify);
  1098. }
  1099. }
  1100. }
  1101. else
  1102. {
  1103. CSDKWindow::PostConferenceNmUI(this, uNotify);
  1104. }
  1105. DBGEXIT_HR(CNmConferenceObj::Fire_NmUI,hr);
  1106. return hr;
  1107. }
  1108. HRESULT CNmConferenceObj::Fire_StateChanged(NM_CONFERENCE_STATE uState)
  1109. {
  1110. DBGENTRY(CNmConferenceObj::Fire_StateChanged)
  1111. HRESULT hr = S_OK;
  1112. if(!g_bSDKPostNotifications)
  1113. {
  1114. /////////////////////////////////////////////////////
  1115. // INmConferenceNotify
  1116. /////////////////////////////////////////////////////
  1117. IConnectionPointImpl<CNmConferenceObj, &IID_INmConferenceNotify, CComDynamicUnkArray>* pCP = this;
  1118. for(int i = 0; i < pCP->m_vec.GetSize(); ++i )
  1119. {
  1120. INmConferenceNotify* pNotify = reinterpret_cast<INmConferenceNotify*>(pCP->m_vec.GetAt(i));
  1121. if(pNotify)
  1122. {
  1123. pNotify->StateChanged(uState);
  1124. }
  1125. }
  1126. }
  1127. else
  1128. {
  1129. CSDKWindow::PostConferenceStateChanged(this, uState);
  1130. }
  1131. DBGEXIT_HR(CNmConferenceObj::Fire_StateChanged,hr);
  1132. return hr;
  1133. }
  1134. extern bool g_bOfficeModeSuspendNotifications;
  1135. HRESULT CNmConferenceObj::Fire_MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pMember)
  1136. {
  1137. DBGENTRY(CNmConferenceObj::Fire_MemberChanged);
  1138. HRESULT hr = S_OK;
  1139. if(m_pManagerObj->OfficeMode() && g_bOfficeModeSuspendNotifications)
  1140. {
  1141. // We don't have to notify anyone at all...
  1142. return S_OK;
  1143. }
  1144. if(!g_bSDKPostNotifications)
  1145. {
  1146. /////////////////////////////////////////////////////
  1147. // INmConferenceNotify
  1148. /////////////////////////////////////////////////////
  1149. IConnectionPointImpl<CNmConferenceObj, &IID_INmConferenceNotify, CComDynamicUnkArray>* pCP = this;
  1150. for(int i = 0; i < pCP->m_vec.GetSize(); ++i )
  1151. {
  1152. INmConferenceNotify* pNotify = reinterpret_cast<INmConferenceNotify*>(pCP->m_vec.GetAt(i));
  1153. if(pNotify)
  1154. {
  1155. pNotify->MemberChanged(uNotify, pMember);
  1156. }
  1157. }
  1158. }
  1159. else
  1160. {
  1161. CSDKWindow::PostConferenceMemberChanged(this, uNotify, pMember);
  1162. }
  1163. DBGEXIT_HR(CNmConferenceObj::Fire_MemberChanged,hr);
  1164. return hr;
  1165. }
  1166. HRESULT CNmConferenceObj::Fire_ChannelChanged(NM_CHANNEL_NOTIFY uNotify, INmChannel *pChannel)
  1167. {
  1168. DBGENTRY(CNmConferenceObj::Fire_ChannelChanged);
  1169. HRESULT hr = S_OK;
  1170. if(!g_bSDKPostNotifications)
  1171. {
  1172. /////////////////////////////////////////////////////
  1173. // INmConferenceNotify
  1174. /////////////////////////////////////////////////////
  1175. IConnectionPointImpl<CNmConferenceObj, &IID_INmConferenceNotify, CComDynamicUnkArray>* pCP = this;
  1176. for(int i = 0; i < pCP->m_vec.GetSize(); ++i )
  1177. {
  1178. INmConferenceNotify* pNotify = reinterpret_cast<INmConferenceNotify*>(pCP->m_vec.GetAt(i));
  1179. if(pNotify)
  1180. {
  1181. pNotify->ChannelChanged(uNotify, pChannel);
  1182. }
  1183. }
  1184. }
  1185. else
  1186. {
  1187. CSDKWindow::PostConferenceChannelChanged(this, uNotify, pChannel);
  1188. }
  1189. DBGEXIT_HR(CNmConferenceObj::Fire_ChannelChanged,hr);
  1190. return hr;
  1191. }
  1192. /////////////////////////////////////////////////
  1193. // helper Fns
  1194. /////////////////////////////////////////////////
  1195. INmChannel* CNmConferenceObj::GetSDKChannelFromInternalChannel(INmChannel* pInternalChannel)
  1196. {
  1197. DBGENTRY(CNmConferenceObj::GetSDKChannelFromInternalChannel);
  1198. INmChannel* pRet = NULL;
  1199. for( int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  1200. {
  1201. CComQIPtr<IInternalChannelObj> spInternal = m_SDKChannelObjs[i];
  1202. if(spInternal)
  1203. {
  1204. CComPtr<INmChannel> spChannel;
  1205. if(SUCCEEDED(spInternal->GetInternalINmChannel(&spChannel)))
  1206. {
  1207. if(spChannel.IsEqualObject(pInternalChannel))
  1208. {
  1209. pRet = m_SDKChannelObjs[i];
  1210. break;
  1211. }
  1212. }
  1213. }
  1214. }
  1215. DBGEXIT(CNmConferenceObj::GetSDKChannelFromInternalChannel);
  1216. return pRet;
  1217. }
  1218. INmMember* CNmConferenceObj::GetSDKMemberFromInternalMember(INmMember* pInternalMember)
  1219. {
  1220. DBGENTRY(CNmConferenceObj::GetSDKMemberFromInternalMember);
  1221. INmMember* pRet = NULL;
  1222. for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i)
  1223. {
  1224. CComQIPtr<IInternalMemberObj> spInternal = m_SDKMemberObjs[i];
  1225. if(spInternal)
  1226. {
  1227. CComPtr<INmMember> spMember;
  1228. if(SUCCEEDED(spInternal->GetInternalINmMember(&spMember)))
  1229. {
  1230. if(spMember.IsEqualObject(pInternalMember))
  1231. {
  1232. pRet = m_SDKMemberObjs[i];
  1233. break;
  1234. }
  1235. }
  1236. }
  1237. }
  1238. DBGEXIT(CNmConferenceObj::GetSDKMemberFromInternalMember);
  1239. return pRet;
  1240. }
  1241. INmMember* CNmConferenceObj::GetLocalSDKMember()
  1242. {
  1243. INmMember* pRet = NULL;
  1244. for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i)
  1245. {
  1246. if(S_OK == m_SDKMemberObjs[i]->IsSelf())
  1247. {
  1248. pRet = m_SDKMemberObjs[i];
  1249. break;
  1250. }
  1251. }
  1252. return pRet;
  1253. }
  1254. HRESULT CNmConferenceObj::_RemoveMember(INmMember* pInternalMember)
  1255. {
  1256. HRESULT hr = S_OK;
  1257. for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i)
  1258. {
  1259. CComPtr<INmMember> spSDKMember = m_SDKMemberObjs[i];
  1260. CComQIPtr<IInternalMemberObj> spMemberObj = spSDKMember;
  1261. CComPtr<INmMember> spInternal;
  1262. if(SUCCEEDED(spMemberObj->GetInternalINmMember(&spInternal)))
  1263. {
  1264. if(spInternal.IsEqualObject(pInternalMember))
  1265. {
  1266. // Remove the member from each of the channels
  1267. for(int iChan = 0; iChan < m_SDKChannelObjs.GetSize(); ++iChan)
  1268. {
  1269. com_cast<IInternalChannelObj>(m_SDKChannelObjs[iChan])->SDKMemberRemoved(m_SDKMemberObjs[i]);
  1270. }
  1271. // Remove our reference to the member
  1272. m_SDKMemberObjs.RemoveAt(i);
  1273. spSDKMember.p->Release();
  1274. break;
  1275. }
  1276. }
  1277. }
  1278. return hr;
  1279. }
  1280. HRESULT CNmConferenceObj::_RemoveChannel(INmChannel* pSDKChannel)
  1281. {
  1282. HRESULT hr = S_OK;
  1283. for( int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  1284. {
  1285. CComPtr<INmChannel> spChannel = m_SDKChannelObjs[i];
  1286. if(spChannel.IsEqualObject(pSDKChannel))
  1287. {
  1288. m_SDKChannelObjs.RemoveAt(i);
  1289. com_cast<IInternalChannelObj>(spChannel)->ChannelRemoved();
  1290. spChannel.p->Release();
  1291. break;
  1292. }
  1293. }
  1294. return hr;
  1295. }
  1296. void CNmConferenceObj::_EnsureFtChannelAdded()
  1297. {
  1298. if(NULL == _GetFtChannel())
  1299. {
  1300. _AddFileTransferChannel();
  1301. }
  1302. }
  1303. HRESULT CNmConferenceObj::_AddFileTransferChannel()
  1304. {
  1305. HRESULT hr = S_OK;
  1306. if(m_pManagerObj && m_pManagerObj->FileTransferNotifications())
  1307. {
  1308. CComPtr<INmChannel> spChannel;
  1309. hr = CNmChannelFtObj::CreateInstance(this, &spChannel);
  1310. if(SUCCEEDED(hr))
  1311. {
  1312. // Add the channel to our list
  1313. spChannel.p->AddRef();
  1314. m_SDKChannelObjs.Add(spChannel.p);
  1315. // Fire the notification
  1316. Fire_ChannelChanged(NM_CHANNEL_ADDED, spChannel);
  1317. }
  1318. }
  1319. return hr;
  1320. }
  1321. HRESULT CNmConferenceObj::_AddAppShareChannel()
  1322. {
  1323. HRESULT hr = S_OK;
  1324. if(m_pManagerObj && m_pManagerObj->AppSharingNotifications())
  1325. {
  1326. CComPtr<INmChannel> spChannel;
  1327. hr = CNmChannelAppShareObj::CreateInstance(this, &spChannel);
  1328. if(SUCCEEDED(hr))
  1329. {
  1330. // Add the channel to our list
  1331. spChannel.p->AddRef();
  1332. m_SDKChannelObjs.Add(spChannel.p);
  1333. // Fire the notification
  1334. Fire_ChannelChanged(NM_CHANNEL_ADDED, spChannel);
  1335. // If app sharing is arleady active, send the notification
  1336. CConfRoom* pcr = GetConfRoom();
  1337. if(pcr && pcr->FCanShare())
  1338. {
  1339. AppSharingStateChanged(true);
  1340. }
  1341. }
  1342. }
  1343. return hr;
  1344. }
  1345. void CNmConferenceObj::_FreeInternalStuff()
  1346. {
  1347. if(m_dwInternalINmConferenceAdvise)
  1348. {
  1349. AtlUnadvise(m_spInternalINmConference, IID_INmConferenceNotify2, m_dwInternalINmConferenceAdvise);
  1350. m_dwInternalINmConferenceAdvise = 0;
  1351. }
  1352. m_spInternalINmConference = NULL;
  1353. while(m_SDKChannelObjs.GetSize())
  1354. {
  1355. CComPtr<INmChannel> spChannel = m_SDKChannelObjs[0];
  1356. m_SDKChannelObjs[0]->Release();
  1357. m_SDKChannelObjs.RemoveAt(0);
  1358. CComPtr<IInternalChannelObj> spChanObj = com_cast<IInternalChannelObj>(spChannel);
  1359. ASSERT(spChanObj);
  1360. spChanObj->Activate(FALSE);
  1361. Fire_ChannelChanged(NM_CHANNEL_UPDATED, spChannel);
  1362. com_cast<IInternalChannelObj>(spChannel)->ChannelRemoved();
  1363. }
  1364. // Free our Member objects
  1365. while(m_SDKMemberObjs.GetSize())
  1366. {
  1367. INmMember* pMember = m_SDKMemberObjs[0];
  1368. m_SDKMemberObjs.RemoveAt(0);
  1369. Fire_MemberChanged(NM_MEMBER_REMOVED, pMember);
  1370. pMember->Release();
  1371. }
  1372. m_SDKMemberObjs.RemoveAll();
  1373. if(m_pManagerObj)
  1374. {
  1375. m_pManagerObj->RemoveConference(com_cast<INmConference>(GetUnknown()));
  1376. }
  1377. }
  1378. bool CNmConferenceObj::_IsGuidInDataChannelList(GUID& rg)
  1379. {
  1380. return -1 != m_DataChannelGUIDList.Find(rg);
  1381. }
  1382. void CNmConferenceObj::_EnsureMemberHasAVChannelsIfNeeded(INmMember* pSDKMember)
  1383. {
  1384. ULONG ulCaps = 0;
  1385. BOOL bIsSelf = (S_OK == pSDKMember->IsSelf());
  1386. if(bIsSelf || SUCCEEDED(pSDKMember->GetNmchCaps(&ulCaps)))
  1387. {
  1388. if(bIsSelf || (NMCH_AUDIO & ulCaps))
  1389. {
  1390. _EnsureMemberHasAVChannel(NMCH_AUDIO, pSDKMember);
  1391. }
  1392. if(bIsSelf || (NMCH_VIDEO & ulCaps))
  1393. {
  1394. _EnsureMemberHasAVChannel(NMCH_VIDEO, pSDKMember);
  1395. }
  1396. }
  1397. }
  1398. void CNmConferenceObj::_EnsureMemberHasAVChannel(ULONG ulch, INmMember* pSDKMember)
  1399. {
  1400. INmChannel* pChannel = NULL;
  1401. // First we have to check to see if the user has this channel
  1402. for(int i = 0; i < m_SDKChannelObjs.GetSize(); ++i)
  1403. {
  1404. ULONG ulchChannel;
  1405. if(SUCCEEDED(m_SDKChannelObjs[i]->GetNmch(&ulchChannel)))
  1406. {
  1407. if(ulch == ulchChannel)
  1408. {
  1409. INmMember *pChannelMember = NULL;
  1410. CComPtr<IEnumNmMember> spEnum;
  1411. if(SUCCEEDED(m_SDKChannelObjs[i]->EnumMember(&spEnum)))
  1412. {
  1413. ULONG cFetched = 0;
  1414. if(S_OK == spEnum->Next(1, &pChannelMember, &cFetched))
  1415. {
  1416. if(CComPtr<INmMember>(pSDKMember).IsEqualObject(pChannelMember))
  1417. {
  1418. // This means that we already have this member in a channel
  1419. pChannelMember->Release();
  1420. return;
  1421. }
  1422. pChannelMember->Release();
  1423. }
  1424. }
  1425. }
  1426. }
  1427. }
  1428. CComPtr<INmChannel> spChannel;
  1429. // Now we have to add the channel
  1430. if(NMCH_AUDIO == ulch)
  1431. {
  1432. if(m_pManagerObj && m_pManagerObj->AudioNotifications())
  1433. {
  1434. CNmChannelAudioObj::CreateInstance(this, &spChannel, S_FALSE == pSDKMember->IsSelf());
  1435. // Add the channel to our list
  1436. spChannel.p->AddRef();
  1437. m_SDKChannelObjs.Add(spChannel.p);
  1438. Fire_ChannelChanged(NM_CHANNEL_ADDED, spChannel);
  1439. // Add the member to the channel
  1440. com_cast<IInternalChannelObj>(spChannel)->SDKMemberAdded(pSDKMember);
  1441. spChannel = NULL;
  1442. }
  1443. }
  1444. if(NMCH_VIDEO == ulch)
  1445. {
  1446. if(m_pManagerObj && m_pManagerObj->VideoNotifications())
  1447. {
  1448. CNmChannelVideoObj::CreateInstance(this, &spChannel, S_FALSE == pSDKMember->IsSelf());
  1449. // Add the channel to our list
  1450. spChannel.p->AddRef();
  1451. m_SDKChannelObjs.Add(spChannel.p);
  1452. Fire_ChannelChanged(NM_CHANNEL_ADDED, spChannel);
  1453. // Add the member to the channel
  1454. com_cast<IInternalChannelObj>(spChannel)->SDKMemberAdded(pSDKMember);
  1455. }
  1456. }
  1457. // We activate the video channels if the m_bXXXVideoActive flags are set
  1458. if(spChannel && (NMCH_VIDEO == ulch))
  1459. {
  1460. if(S_OK == pSDKMember->IsSelf())
  1461. {
  1462. if(m_bLocalVideoActive)
  1463. {
  1464. // Add the member to the channel
  1465. com_cast<IInternalChannelObj>(spChannel)->Activate(true);
  1466. Fire_ChannelChanged(NM_CHANNEL_UPDATED, spChannel);
  1467. }
  1468. }
  1469. else
  1470. {
  1471. if(m_bRemoteVideoActive)
  1472. {
  1473. // Add the member to the channel
  1474. com_cast<IInternalChannelObj>(spChannel)->Activate(true);
  1475. Fire_ChannelChanged(NM_CHANNEL_UPDATED, spChannel);
  1476. }
  1477. }
  1478. }
  1479. }