Object Name |
Interface |
Connection Point |
Description |
Conference Manager |
INmManager |
INmManagerNotify |
Manager of the overall conferencing system. |
Call |
INmCall |
INmCallNotify |
Monitors and controls an incoming or outgoing call. |
Conference |
INmConference |
INmConferenceNotify |
Manages an instance of a conference. |
Channel |
INmChannel |
INmChannelNotify |
Base object for all the channels. A conduit for a specific type of media (application sharing, audio, data, file transfer, and video). |
Audio Channel |
INmChannelAudio |
INmChannelAudioNotify |
A conduit for audio-type media. |
Video Channel |
INmChannelVideo |
INmChannelVideoNotify |
A conduit for video-type media. |
File Transfer Channel |
INmChannelFt |
INmChannelFtNotify |
Manager of file transfer activity. |
Application Sharing Channel |
INmChannelAppShare |
INmChannelAppShareNotify |
Manager of shared applications. |
Data Channel |
INmChannelData |
INmChannelDataNotify |
A conduit for sending and receiving data between conference participants. |
Local System |
INmSysInfo |
|
Information about the local user and local computer. |
Member |
INmMember |
|
A participant in a conference. |
Figure 4 CNMManager
class CNMManager
{
// Attributes
protected:
//NetMeeting Interface pointer
CComPtr<INmManager> m_pManager;
//Connection point cookie
DWORD m_dwManagerCookie;
// Implementation
public:
CNMManager ();
~CNMManager ();
// Initializes the conferencing system and sets up the
// connection point
HRESULT Initialize (ULONG uchCaps = NMCH_ALL,
ULONG uOptions = NM_INIT_CONTROL);
//Connection point support functions
void OnNmUI();
HRESULT OnConferenceCreated(INmConference * pIConference);
HRESULT OnCallCreated(INmCall* pICall);
//Wrapper routines
HRESULT CreateConference(BSTR bstrName,
BSTR bstrPassword = NULL,
ULONG uchCaps = NMCH_ALL);
HRESULT CreateCall(NM_ADDR_TYPE uType,
BSTR bstrAddr,
INmConference * pConference = NULL);
};
Figure 5 CNMManagerEventSink
class CNMManagerEventSink :
public CComObjectRoot,
public INmManagerNotify
{
// Construction
public:
CNMManagerEventSink();
// Attributes
protected:
CNMManager* m_pManager;
// Operations
public:
BEGIN_COM_MAP(CNMManagerEventSink)
COM_INTERFACE_ENTRY(INmManagerNotify)
END_COM_MAP()
// Implementation
public:
virtual ~CNMManagerEventSink();
void Initialize (CNMManager* pManager)
{m_pManager = pManager;}
// INmManagerNotify
STDMETHOD(NmUI)(CONFN uNotify);
STDMETHOD(ConferenceCreated)(INmConference *pConference);
STDMETHOD(CallCreated)(INmCall *pCall);
};
Figure 6 CNMManager Initialization
HRESULT CNMManager::Initialize (ULONG uchCaps, ULONG uOptions)
{
HRESULT hr = E_FAIL;
ATLTRACE( "CNMManager::Initialize\n" );
// Create a conference manager instance
hr = CoCreateInstance(CLSID_NmManager, NULL, CLSCTX_ALL,
IID_INmManager, (void**)&m_pManager);
_ASSERTE(m_pManager != NULL);
if (FAILED(hr))
{
//Error handling
}
else
{
//establish the connection point
CComObject<CNMManagerEventSink>* pSink;
CComObject<CNMManagerEventSink>::CreateInstance(&pSink);
pSink->Initialize (this);
AtlAdvise(m_pManager, pSink->GetUnknown(),
IID_INmManagerNotify, &m_dwManagerCookie);
// Initialize the data
hr = m_pManager->Initialize(&uOptions, &uchCaps);
}
return hr;
}
Figure 7 NetMeeting Control Options
Value |
Description |
NM_INIT_NORMAL |
NetMeeting user interface will be visible. |
NM_INIT_CONTROL |
NetMeeting UI will not be visible. You will control the UI in the application. |
NM_INIT_NO_LAUNCH |
NetMeeting will not be started if it isn't already running. |
Figure 8 Notification Support
HRESULT CNMManager::OnConferenceCreated(INmConference * pIConference)
{
ATLTRACE( "CNMManager::OnConferenceCreated\n" );
if (NULL != pIConference)
{
m_pConference = new CNMConference(pIConference);
m_pConference->Initialize();
}
return S_OK;
}
HRESULT CNMManager::OnCallCreated(INmCall* pICall)
{
ATLTRACE( "CNMManager::OnCallCreated\n" );
if (NULL != pICall)
{
m_pCall = new CNMCall(pICall);
m_pCall->Initialize();
}
return S_OK;
}
Figure 9 CNMConference
using namespace std;
class CNMConference
{
// Attributes
protected:
CComPtr<INmConference> m_pConference;
DWORD m_dwConferenceCookie;
CNMAppShare* m_pChannelAppShare;
vector <CNMChannelVideo*> m_pChannelVideoVector;
//Other Channels go here.
// Implementation
public:
CNMConference (INmConference* pConference);
~CNMConference ();
void Initialize ();
CNMAppShare* GetAppShareChannel()
{return m_pChannelAppShare;}
CNMChannelVideo* GetVideoChannel(BOOL bIncoming = TRUE);
//Other channel access functions go here
//Notification support functions
void OnNmUI();
void OnStateChanged();
void OnMemberChanged();
//Channel management support functions
HRESULT OnAddChannel(INmChannel* pIChannel);
HRESULT OnRemoveChannel(INmChannel* pIChannel);
HRESULT OnUpdateChannel(INmChannel* pIChannel);
//Application Remote launching support.
HRESULT LaunchRemote(GUID* pguidApp);
};
Figure 10 CNMConferenceEventSink
class CNMConferenceEventSink :
public CComObjectRoot,
public INmConferenceNotify
{
// Construction
public:
CNMConferenceEventSink();
// Attributes
protected:
CNMConference* m_pConference;
// Operations
public:
BEGIN_COM_MAP(CNMConferenceEventSink)
COM_INTERFACE_ENTRY(INmConferenceNotify)
END_COM_MAP()
// Implementation
public:
virtual ~CNMConferenceEventSink();
//Interface Manager pointer for call back.
void Initialize (CNMConference* pConference)
{m_pConference = pConference;}
// INmConferenceNotify
STDMETHOD(NmUI)(CONFN uNotify);
STDMETHOD(StateChanged)(NM_CONFERENCE_STATE uState);
STDMETHOD(MemberChanged)(NM_MEMBER_NOTIFY uNotify,
INmMember *pfMember);
STDMETHOD(ChannelChanged)(NM_CHANNEL_NOTIFY uNotify,
INmChannel *pChannel);
};
Figure 11 CNMConference Destructor
CNMConference::~CNMConference ()
{
ATLTRACE( "CNMConference::~CNMConference\n" );
int nIndex = 0;
int nSize = m_pChannelVideoVector.size();
//Clean-up all of the channel information
if (NULL != m_pChannelAppShare)
delete m_pChannelAppShare;
for (nIndex = 0; nIndex < nSize; nIndex++)
{
delete m_pChannelVideoVector.at(nIndex);
}
m_pChannelVideoVector.clear();
//Release the sink
AtlUnadvise(m_pConference,
IID_INmConferenceNotify,
m_dwConferenceCookie);
}
Figure 12 ChannelChanged
HRESULT CNMConferenceEventSink::ChannelChanged(
NM_CHANNEL_NOTIFY uNotify,
INmChannel *pChannel)
{
ATLTRACE( "CNMConferenceEventSink::ChannelChanged\n");
HRESULT hr = E_FAIL;
If (NULL != pConference)
{
switch (uNotify)
{
case NM_CHANNEL_ADDED:
hr = m_pConference->OnAddChannel(pChannel);
break;
case NM_CHANNEL_REMOVED:
hr = m_pConference->OnRemoveChannel(pChannel);
break;
case NM_CHANNEL_UPDATED:
hr = m_pConference->OnUpdateChannel(pChannel);
break;
}
}
return hr;
}
Figure 13 Channel Manipulation
HRESULT CNMConference::OnAddChannel(INmChannel* pIChannel)
{
ATLTRACE( "CNMConference::OnAddChannel\n");
HRESULT hr = E_FAIL;
ULONG uChannel = NMCH_DATA;
hr = pIChannel->GetNmch(&uChannel);
if (SUCCEEDED(hr))
{
switch (uChannel)
{
...
case NMCH_SHARE:
m_pChannelAppShare = new CNMAppShare (pIChannel);
m_pChannelAppShare->Initialize();
break;
case NMCH_VIDEO:
{
CNMChannelVideo* pChannelVideo =
new CNMChannelVideo (pIChannel);
pChannelVideo->Initialize();
m_pChannelVideoVector.push_back(pChannelVideo);
}
break;
}
}
return hr;
}
//===================================================================
HRESULT CNMConference::OnRemoveChannel(INmChannel* pIChannel)
{
ATLTRACE( "CNMConference::OnRemoveChannel\n");
HRESULT hr = E_FAIL;
ULONG uChannel = NMCH_DATA;
hr = pIChannel->GetNmch(&uChannel);
if (SUCCEEDED(hr))
{
switch (uChannel)
{
...
case NMCH_SHARE:
if ((NULL != m_pChannelAppShare)
&& (S_OK == m_pChannelAppShare->GetInterface()
->IsSameAs(pChannel)))
{
delete m_pChannelAppShare;
m_pChannelAppShare = NULL;
}
break;
case NMCH_VIDEO:
{
int nIndex = 0;
int nSize = m_pChannelVideoVector.size();
CNMChannelVideo* pChannelVideo = NULL;
for (nIndex = 0; nIndex < nSize; nIndex++)
{
pChannelVideo =
m_pChannelVideoVector.at(nIndex);
if ((NULL != pChannelVideo) &&
pChannelVideo->GetInterface()
->IsSameAs(pIChannel))
{
delete pChannelVideo;
pChannelVideo = NULL;
m_pChannelVideoVector.erase(
m_pChannelVideoVector.begin()
+ nIndex);
break;
}
}
}
break;
}
}
return hr;
}
Figure 14 CNMAppShare
class CNMAppShare
{
// Attributes
protected:
CComPtr< INmChannelAppShare > m_pAppShare;
DWORD m_dwAppShareCookie;
// Implementation
public:
CNMAppShare (INmChannel* pAppShare);
~CNMAppShare ();
HRESULT Initialize ();
INmChannelAppShare* GetInterface()
{return m_pAppShare;}
HRESULT OnNmUI();
HRESULT OnMemberChanged();
HRESULT OnStateChanged();
HRESULT SetAppShareState(HWND hWnd, NM_SHAPP_STATE uState);
HRESULT SetState(NM_SHARE_STATE uState)
{ m_pAppShare->SetState(uState);}
};
Figure 15 SetState Levels
Value |
Description |
NM_SHARE_COLLABORATING |
All the conference members can work in all applications the local user has shared. |
NM_SHARE_IN_CONTROL |
Gives the local user control of the cursor. If the user is working alone, this will also grant others permission to take control of this shared application. |
NM_SHARE_WORKING_ALONE |
The local user is working alone. Other conference members can see applications that the local user has shared, but they cannot work in them. |
Figure 16 SetAppShareState Method
HRESULT CNMAppShare::SetAppShareState(HWND hWnd, NM_SHAPP_STATE uState)
{
ATLTRACE( "CNMAppShare::SetAppShareState\n");
HRESULT hr = E_FAIL;
HWND hWndApp = NULL;
IEnumNmSharableApp * pEnum = NULL;
INmSharableApp * pApp = NULL;
if (NULL != m_pAppShare)
{
hr = m_pAppShare->EnumSharableApp(&pEnum);
if (FAILED(hr))
{
for ( ; ; )
{
hr = pEnum->Next(1, &pApp, NULL);
if (SUCCEEDED(hr))
{
pApp->GetHwnd(&hWndApp);
if (hWndApp == hWnd)
{
hr = pApp->SetState(uState);
pApp->Release();
break;
}
pApp->Release();
}
else
break;
}
}
pEnum->Release();
}
return hr;
}
Figure 17 CNMAppShareEventSink
class CNMAppShareEventSink :
public CComObjectRoot,
public INmChannelAppShareNotify
{
// Construction
public:
CNMAppShareEventSink();
// Attributes
protected:
CNMAppShare* m_pAppShare;
// Operations
public:
BEGIN_COM_MAP(CNMAppShareEventSink)
COM_INTERFACE_ENTRY(INmChannelAppShareNotify)
END_COM_MAP()
// Implementation
public:
virtual ~CNMAppShareEventSink();
void Initialize (CNMAppShare* pAppShare)
{m_pAppShare = pAppShare;}
// INmChannelAppShareNotify
STDMETHOD(NmUI)(CONFN uNotify);
STDMETHOD(MemberChanged)(NM_MEMBER_NOTIFY uNotify,
INmMember * pMember);
STDMETHOD(StateChanged)(NM_SHAPP_STATE uNotify,
INmSharableApp *pApp);
};
Figure 18 GetVideoChannel Method
CNMChannelVideo* CNMConference::GetVideoChannel(BOOL bIncoming)
{
int nIndex = 0;
int nSize = m_pChannelVideoVector.size();
CNMChannelVideo* pChannelVideo = NULL;
for (nIndex; nIndex < nSize; nIndex++)
{
pChannelVideo = m_pChannelVideoVector.at(nIndex);
if ((NULL != pChannelVideo) &&
(pChannelVideo->IsIncoming() == bIncoming))
{
break;
}
}
return pChannelVideo;
}
Figure 19 Video Channel Properties
uID Value |
Description |
wLow |
wHigh |
NM_VIDPROP_PAUSE |
Pauses/resumes the video |
0 or 1 |
|
NM_VIDPROP_WINDOW_AUTO_SIZE |
Sets the window size as a percentage of the image size |
0 to 400% |
|
NM_VIDPROP_WINDOW_SIZE |
Sets the window size |
Desired width |
Desired height |
NM_VIDPROP_WINDOW_TOP_MOST |
Sets the window as the topmost window |
0 or 1 |
|
NM_VIDPROP_WINDOW_POSITION |
Sets the window position |
Desired x-coordinate value |
Desired y-coordinate value |
NM_VIDPROP_WINDOW_VISIBLE |
Sets the window visible |
0 or 1 |
|
NM_VIDPROP_IMAGE_PREFERRED_SIZE |
Sets the image size |
NM_VIDEO_SMALL, NM_VIDEO_MEDIUM, or NM_VIDEO_LARGE |
|
NM_VIDPROP_IMAGE_QUALITY |
Sets the image quality |
0 to 31 |
|
NM_VIDPROP_CAMERA_DIALOG |
Sets the dialog used by the capture device |
NM_VIDEO_FORMAT_ DIALOG or NM_VIDEO_ SOURCE_DIALOG |
|
Figure 20 ShareMe Method
void CNMDemoDoc::OnToolsShareMe()
{
CNMAppShare * pAppShare = m_pManager->GetCurrentConference()
->GetAppShareChannel();
if (m_bShared)
{
pAppShare->SetAppShareState(AfxGetMainWnd()->m_hWnd,
NM_SHAPP_NOT_SHARED);
m_bShared = FALSE;
}
else
{
m_bShared = TRUE;
pAppShare->SetAppShareState(AfxGetMainWnd()->m_hWnd,
NM_SHAPP_SHARED);
}
}