#ifndef __NmChannel_h__ #define __NmChannel_h__ #include "imsconf3.h" class CNmConferenceObj; template class ATL_NO_VTABLE CNmChannel : public T { friend class CNmChannelDataObj; friend class CNmChannelAudioObj; friend class CNmChannelVideoObj; friend class CNmChannelFtObj; friend class CNmChannelAppShareObj; public: CNmChannel() : m_bActive(false), m_pConfObj(NULL) { ; } ~CNmChannel() { DBGENTRY(CNmChannel::~CNmChannel); RemoveMembers(); DBGEXIT(CNmChannel::~CNmChannel); } // INmChannel methods STDMETHOD(IsSameAs)(INmChannel *pChannel); STDMETHOD(IsActive)(void); STDMETHOD(SetActive)(BOOL fActive); STDMETHOD(GetConference)(INmConference **ppConference); STDMETHOD(GetInterface)(IID *_piid); STDMETHOD(GetNmch)(ULONG *puCh); STDMETHOD(EnumMember)(IEnumNmMember **ppEnum); STDMETHOD(GetMemberCount)(ULONG * puCount); // INmChannelNotify STDMETHOD(NmUI)(CONFN uNotify); STDMETHOD(MemberChanged)(NM_MEMBER_NOTIFY uNotify, INmMember *pInternalMember); STDMETHOD(NotifySinksOfAllMembers)() { for(int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { Fire_MemberChanged(NM_MEMBER_ADDED, m_SDKMemberObjs[i]); } return S_OK; } STDMETHOD(NotifySinksOfLocalMember)() { Fire_MemberChanged(NM_MEMBER_ADDED, GetConfObj()->GetLocalSDKMember()); return S_OK; } virtual bool IsChannelValid() { if(m_pConfObj) { NM_CONFERENCE_STATE state; if(SUCCEEDED(m_pConfObj->GetState(&state)) && (NM_CONFERENCE_IDLE != state)) { return true; } } return false; } virtual CNmConferenceObj* GetConfObj() { return m_pConfObj; } virtual BOOL GetbActive() { return m_bActive; } virtual void RemoveMembers() { // Free our conferencing objects while(m_SDKMemberObjs.GetSize()) { Fire_MemberChanged(NM_MEMBER_REMOVED, m_SDKMemberObjs[0]); CComPtr sp = m_SDKMemberObjs[0]; m_SDKMemberObjs.RemoveAt(0); sp.p->Release(); } } STDMETHOD(Activate)(BOOL bActive) { if(m_bActive != ((bActive) ? TRUE : FALSE)) { m_bActive = ((bActive) ? TRUE : FALSE); _OnActivate(bActive ? true : false); } return S_OK; } STDMETHOD(SDKMemberAdded)(INmMember* pSDKMember) { HRESULT hr = S_FALSE; if(!_MemberInChannel(pSDKMember)) { // Add the member pSDKMember->AddRef(); m_SDKMemberObjs.Add(pSDKMember); // Notify the sinks Fire_MemberChanged(NM_MEMBER_ADDED, pSDKMember); hr = S_OK; } return hr; } STDMETHOD(SDKMemberRemoved)(INmMember* pSDKMember) { HRESULT hr = S_FALSE; for(int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { CComPtr spMember = m_SDKMemberObjs[i]; if(spMember.IsEqualObject(pSDKMember)) { m_SDKMemberObjs.RemoveAt(i); Fire_MemberChanged(NM_MEMBER_REMOVED, spMember); spMember.p->Release(); hr = S_OK; break; } } return hr; } STDMETHOD(SDKMemberChanged)(INmMember* pSDKMember) { return Fire_MemberChanged(NM_MEMBER_UPDATED, pSDKMember); } void NotifySinkOfMembers(INmChannelNotify* pNotify) { for(int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { pNotify->MemberChanged(NM_MEMBER_ADDED, m_SDKMemberObjs[i]); } } STDMETHOD(FireNotificationsToSyncState)() { for(int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { Fire_MemberChanged(NM_MEMBER_ADDED, m_SDKMemberObjs[i]); } return S_OK; } protected: // Helper Fns INmMember* _GetSDKMemberFromInternalMember(INmMember* pInternalMember); HRESULT _RemoveMember(INmMember* pInternalMember); virtual bool _MemberInChannel(INmMember* pSDKMember); private: CSimpleArray m_SDKMemberObjs; CNmConferenceObj* m_pConfObj; BOOL m_bActive; }; /////////////////////////////////////////////////////////////////// // INmChannel /////////////////////////////////////////////////////////////////// template STDMETHODIMP CNmChannel::IsSameAs(INmChannel *pChannel) { DBGENTRY(CNmChannel::IsSameAs); HRESULT hr = E_NOTIMPL; CComPtr pUnk(GetUnknown()); hr = pUnk.IsEqualObject(pChannel) ? S_OK : S_FALSE; DBGEXIT_HR(CNmChannel::IsSameAs,hr); return hr; } template STDMETHODIMP CNmChannel::IsActive(void) { DBGENTRY(CNmChannel::IsActive); HRESULT hr = _IsActive(); DBGEXIT_HR(CNmChannel::IsActive,hr); return hr; } template STDMETHODIMP CNmChannel::SetActive(BOOL fActive) { DBGENTRY(CNmChannel::SetActive); HRESULT hr = _SetActive(fActive); DBGEXIT_HR(CNmChannel::SetActive,hr); return hr; } template STDMETHODIMP CNmChannel::GetConference(INmConference **ppConference) { DBGENTRY(CNmChannel::GetConference); HRESULT hr = S_OK; if(m_pConfObj) { IUnknown* pUnk = m_pConfObj->GetUnknown(); if(pUnk) { hr = pUnk->QueryInterface(IID_INmConference,reinterpret_cast(ppConference)); } else { hr = S_FALSE; } } DBGEXIT_HR(CNmChannel::GetConference,hr); return hr; } template STDMETHODIMP CNmChannel::GetInterface(IID *_piid) { DBGENTRY(CNmChannel::GetInterface); HRESULT hr = S_OK; if(piid) { *_piid = *piid; } else { hr = E_POINTER; } DBGEXIT_HR(CNmChannel::GetInterface,hr); return hr; } template STDMETHODIMP CNmChannel::GetNmch(ULONG *puCh) { DBGENTRY(CNmChannel::GetNmch); HRESULT hr = S_OK; if(puCh) { *puCh = dwCh; } else { hr = E_POINTER; } DBGEXIT_HR(CNmChannel::GetNmch,hr); return hr; } template STDMETHODIMP CNmChannel::EnumMember(IEnumNmMember **ppEnum) { DBGENTRY(CNmChannel::EnumMember); HRESULT hr = S_OK; hr = CreateEnumFromSimpleAryOfInterface(m_SDKMemberObjs, ppEnum); DBGEXIT_HR(CNmChannel::EnumMember,hr); return hr; } template STDMETHODIMP CNmChannel::GetMemberCount(ULONG * puCount) { DBGENTRY(CNmChannel::GetMemberCount); HRESULT hr = S_OK; if(puCount) { *puCount = m_SDKMemberObjs.GetSize(); } else { hr = E_POINTER; } DBGEXIT_HR(CNmChannel::GetMemberCount,hr); return hr; } /////////////////////////////////////////////////////////////////// // INmChannelNotify /////////////////////////////////////////////////////////////////// template STDMETHODIMP CNmChannel::NmUI(CONFN uNotify) { DBGENTRY(CNmChannel::NmUI); HRESULT hr = S_OK; DBGEXIT_HR(CNmChannel::NmUI,hr); return hr; } template STDMETHODIMP CNmChannel::MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pInternalMember) { DBGENTRY(CNmChannel::MemberChanged); HRESULT hr = S_OK; if(pInternalMember && m_pConfObj) { INmMember* pMember = NULL; if(NM_MEMBER_ADDED == uNotify) { // Only add it if we haven't added it yet if(!(pMember = _GetSDKMemberFromInternalMember(pInternalMember))) { pMember = m_pConfObj->GetSDKMemberFromInternalMember(pInternalMember); ASSERT(pMember); pMember->AddRef(); m_SDKMemberObjs.Add(pMember); } else { // We already have this member goto end; } } if(!pMember) { pMember = _GetSDKMemberFromInternalMember(pInternalMember); } // It is possable that the member has already been removed.. if(pMember) { if(NM_MEMBER_REMOVED == uNotify) { _RemoveMember(pInternalMember); } else { Fire_MemberChanged(uNotify, pMember); } } } else { ERROR_OUT(("The member is not in the conference yet!!!")); hr = E_UNEXPECTED; } end: DBGEXIT_HR(CNmChannel::MemberChanged,hr); return hr; } template INmMember* CNmChannel::_GetSDKMemberFromInternalMember(INmMember* pInternalMember) { INmMember* pRet = NULL; for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { CComQIPtr spInternal = m_SDKMemberObjs[i]; ASSERT(spInternal); CComPtr spMember; if(SUCCEEDED(spInternal->GetInternalINmMember(&spMember))) { if(spMember.IsEqualObject(pInternalMember)) { pRet = m_SDKMemberObjs[i]; break; } } } return pRet; } template HRESULT CNmChannel::_RemoveMember(INmMember* pInternalMember) { HRESULT hr = E_FAIL; for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { CComQIPtr spSDKObj = m_SDKMemberObjs[i]; CComPtr spSDKMember = m_SDKMemberObjs[i]; ASSERT(spSDKObj); CComPtr spMember; if(SUCCEEDED(spSDKObj->GetInternalINmMember(&spMember))) { // Worst case we return S_FALSE to indicate that there is no such member hr = S_FALSE; if(spMember.IsEqualObject(pInternalMember)) { m_SDKMemberObjs.RemoveAt(i); Fire_MemberChanged(NM_MEMBER_REMOVED, spSDKMember); spSDKMember.p->Release(); hr = S_OK; break; } } } return hr; } template bool CNmChannel::_MemberInChannel(INmMember* pSDKMember) { for( int i = 0; i < m_SDKMemberObjs.GetSize(); ++i) { CComPtr spMember = m_SDKMemberObjs[i]; if(spMember.IsEqualObject(pSDKMember)) { return true; } } return false; } #endif // __NmChannel_h__