WindowsXP-SP1/enduser/netmeeting/core/ichnlaud.cpp
2020-09-30 16:53:49 +02:00

495 lines
9.6 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// File: ichnlaud.cpp
#include "precomp.h"
#include "ichnlaud.h"
static const IID * g_apiidCP[] =
{
{&IID_INmChannelNotify},
{&IID_INmChannelAudioNotify}
};
CNmChannelAudio::CNmChannelAudio(BOOL fIncoming) :
CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)),
m_cMembers (0),
m_dwFlags(0),
m_pAudioChannel(NULL),
m_pAudioDevice(NULL),
m_pCommChannel(NULL),
m_fIncoming(fIncoming),
m_AudioControl(!fIncoming /* fLocal */),
m_MediaFormat(INVALID_MEDIA_FORMAT)
{
IMediaChannel *pMC = NULL;
HRESULT hr;
if (NULL != g_pH323UI)
{
IMediaChannelBuilder * pMCProvider = g_pH323UI->GetStreamProvider();
ASSERT(NULL != pMCProvider);
// create the channel, and get the device interface
pMCProvider->CreateMediaChannel(MCF_AUDIO | (fIncoming ? MCF_RECV : MCF_SEND), &pMC);
if (NULL != pMC)
{
pMCProvider->QueryInterface(IID_IAudioDevice, (void**)&m_pAudioDevice);
pMC->QueryInterface(IID_IAudioChannel, (void**)&m_pAudioChannel);
ASSERT(m_pAudioChannel);
ASSERT(m_pAudioDevice);
pMC->Release();
}
else
{
WARNING_OUT(("CreateMediaChannel failed"));
}
pMCProvider->Release();
}
DbgMsg(iZONE_OBJECTS, "Obj: %08X created CNmChannelAudio", this);
}
CNmChannelAudio::~CNmChannelAudio()
{
if (NULL != m_pCommChannel)
{
m_pCommChannel->Release();
}
if (NULL != m_pAudioChannel)
{
m_pAudioChannel->Release();
}
if (NULL != m_pAudioDevice)
{
m_pAudioDevice->Release();
}
DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CNmChannelAudio", this);
}
VOID CNmChannelAudio::CommChannelOpened(ICommChannel *pCommChannel)
{
ASSERT(NULL == m_pCommChannel);
m_pCommChannel = pCommChannel;
pCommChannel->AddRef();
}
VOID CNmChannelAudio::CommChannelActive(ICommChannel *pCommChannel)
{
ASSERT(m_pCommChannel == pCommChannel);
}
VOID CNmChannelAudio::CommChannelClosed()
{
if (NULL != m_pCommChannel)
{
m_pCommChannel->Release();
m_pCommChannel = NULL;
}
}
VOID CNmChannelAudio::OnMemberAdded(CNmMember *pMember)
{
// Don't add to the channel if we already belong.
if (0 != (pMember->GetNmchCaps() & NMCH_AUDIO))
{
return;
}
++m_cMembers;
pMember->AddNmchCaps(NMCH_AUDIO);
CConfObject *pco = ::GetConfObject();
pco->OnMemberUpdated(pMember);
NotifySink((INmMember *) pMember, OnNotifyChannelMemberAdded);
}
VOID CNmChannelAudio::OnMemberRemoved(CNmMember *pMember)
{
// If member does not belong to this channel, don't remove it.
if (0 == (pMember->GetNmchCaps() & NMCH_AUDIO))
{
return;
}
--m_cMembers;
pMember->RemoveNmchCaps(NMCH_AUDIO);
CConfObject *pco = ::GetConfObject();
pco->OnMemberUpdated(pMember);
NotifySink((INmMember *) pMember, OnNotifyChannelMemberRemoved);
}
VOID CNmChannelAudio::OnMemberUpdated(CNmMember *pMember)
{
NotifySink((INmMember *) pMember, OnNotifyChannelMemberUpdated);
}
DWORD CNmChannelAudio::GetLevel()
{
UINT uLevel = 0;
if (NULL != m_pAudioChannel)
{
m_pAudioChannel->GetSignalLevel(&uLevel);
}
return uLevel;
}
BOOL CNmChannelAudio::IsAutoMixing()
{
BOOL bOn=FALSE;
if ((NULL != m_pAudioChannel) && (!m_fIncoming))
{
bOn = m_pAudioDevice->GetAutoMix(&bOn);
}
return bOn;
}
BOOL CNmChannelAudio::IsPaused()
{
BOOL fPaused = TRUE;
if (NULL != m_pCommChannel)
{
DWORD dwOn = FALSE;
UINT uSize = sizeof(dwOn);
DWORD dwPropID = m_fIncoming ? PROP_PLAY_ON : PROP_RECORD_ON;
m_pCommChannel->GetProperty(dwPropID, &dwOn, &uSize);
fPaused = (0 == dwOn);
}
return fPaused;
}
VOID CNmChannelAudio::Open()
{
ASSERT(m_MediaFormat != INVALID_MEDIA_FORMAT);
m_AudioControl.Open(m_MediaFormat);
}
VOID CNmChannelAudio::Close()
{
m_AudioControl.Close();
}
STDMETHODIMP_(ULONG) CNmChannelAudio::AddRef(void)
{
return RefCount::AddRef();
}
STDMETHODIMP_(ULONG) CNmChannelAudio::Release(void)
{
return RefCount::Release();
}
STDMETHODIMP CNmChannelAudio::QueryInterface(REFIID riid, PVOID *ppv)
{
HRESULT hr = S_OK;
if ((riid == IID_INmChannelAudio) || (riid == IID_INmChannel) || (riid == IID_IUnknown))
{
*ppv = (INmChannel *)this;
DbgMsgApi("CNmChannelAudio::QueryInterface()");
}
else if (riid == IID_IConnectionPointContainer)
{
*ppv = (IConnectionPointContainer *) this;
DbgMsgApi("CNmChannelAudio::QueryInterface(): Returning IConnectionPointContainer.");
}
else
{
hr = E_NOINTERFACE;
*ppv = NULL;
DbgMsgApi("CNmChannelAudio::QueryInterface(): Called on unknown interface.");
}
if (S_OK == hr)
{
AddRef();
}
return hr;
}
STDMETHODIMP CNmChannelAudio::IsSameAs(INmChannel *pChannel)
{
return (((INmChannel *) this) == pChannel) ? S_OK : S_FALSE;
}
STDMETHODIMP CNmChannelAudio::IsActive()
{
return (NULL != m_pCommChannel) ? S_OK : S_FALSE;
}
STDMETHODIMP CNmChannelAudio::SetActive(BOOL fActive)
{
return E_FAIL;
}
STDMETHODIMP CNmChannelAudio::GetConference(INmConference **ppConference)
{
return ::GetConference(ppConference);
}
STDMETHODIMP CNmChannelAudio::GetInterface(IID *piid)
{
HRESULT hr = E_POINTER;
if (NULL != piid)
{
*piid = IID_INmChannelAudio;
hr = S_OK;
}
return hr;
}
STDMETHODIMP CNmChannelAudio::GetNmch(ULONG *puCh)
{
HRESULT hr = E_POINTER;
if (NULL != puCh)
{
*puCh = NMCH_AUDIO;
hr = S_OK;
}
return hr;
}
STDMETHODIMP CNmChannelAudio::EnumMember(IEnumNmMember **ppEnum)
{
HRESULT hr = E_POINTER;
if (NULL != ppEnum)
{
int cMembers = 0;
COBLIST MemberList;
COBLIST* pPartList = ::GetMemberList();
if (NULL != pPartList)
{
POSITION pos = pPartList->GetHeadPosition();
while (pos)
{
CNmMember * pMember = (CNmMember *) pPartList->GetNext(pos);
ASSERT(NULL != pMember);
if (NMCH_AUDIO & pMember->GetNmchCaps())
{
MemberList.AddTail(pMember);
pMember->AddRef();
cMembers++;
}
}
}
*ppEnum = new CEnumNmMember(&MemberList, cMembers);
while (!MemberList.IsEmpty())
{
INmMember *pMember = (INmMember *) (CNmMember *) MemberList.RemoveHead();
pMember->Release();
}
hr = (NULL != *ppEnum)? S_OK : E_OUTOFMEMORY;
}
return hr;
}
STDMETHODIMP CNmChannelAudio::GetMemberCount(ULONG * puCount)
{
HRESULT hr = E_POINTER;
if (NULL != puCount)
{
*puCount = m_cMembers;
hr = S_OK;
}
return hr;
}
STDMETHODIMP CNmChannelAudio::IsIncoming(void)
{
return m_fIncoming ? S_OK : S_FALSE;
}
STDMETHODIMP CNmChannelAudio::GetState(NM_AUDIO_STATE *puState)
{
HRESULT hr = E_POINTER;
if (NULL != puState)
{
if (NULL != m_pCommChannel)
{
if (IsPaused())
{
*puState = NM_AUDIO_LOCAL_PAUSED;
}
else
{
*puState = NM_AUDIO_TRANSFERRING;
}
}
else
{
*puState = NM_AUDIO_IDLE;
}
hr = S_OK;
}
return hr;
}
IMediaChannel* CNmChannelAudio::GetMediaChannelInterface(void)
{
IMediaChannel *pMC=NULL;
if (m_pAudioChannel)
{
m_pAudioChannel->QueryInterface(IID_IMediaChannel, (void**)&pMC);
}
return pMC;
}
STDMETHODIMP CNmChannelAudio::GetProperty(NM_AUDPROP uID, ULONG_PTR *puValue)
{
HRESULT hr = E_POINTER;
if (NULL != puValue)
{
switch (uID)
{
case NM_AUDPROP_LEVEL:
*puValue = GetLevel();
hr = S_OK;
break;
case NM_AUDPROP_PAUSE:
*puValue = IsPaused();
hr = S_OK;
break;
case NM_AUDPROP_AUTOMIX:
*puValue = IsAutoMixing();
hr = S_OK;
break;
default:
hr = E_FAIL;
break;
}
}
return hr;
}
HRESULT OnNotifyPropertyChanged(IUnknown *pAudioChannelNotify, PVOID pv, REFIID riid)
{
ASSERT(NULL != pAudioChannelNotify);
((INmChannelAudioNotify*)pAudioChannelNotify)->PropertyChanged((DWORD)((DWORD_PTR)pv));
return S_OK;
}
HRESULT OnNotifyStateChanged(IUnknown *pAudioChannelNotify, PVOID pv, REFIID riid)
{
ASSERT(NULL != pAudioChannelNotify);
((INmChannelAudioNotify*)pAudioChannelNotify)->StateChanged(static_cast<NM_AUDIO_STATE>((DWORD)((DWORD_PTR)pv)));
return S_OK;
}
STDMETHODIMP CNmChannelAudio::SetProperty(NM_AUDPROP uID, ULONG_PTR uValue)
{
HRESULT hr = E_FAIL;
if ((NULL != m_pAudioDevice) && (NULL != m_pAudioChannel))
{
switch (uID)
{
case NM_AUDPROP_PAUSE:
{
DWORD dwOn = (0 == uValue);
DWORD dwPropID = m_fIncoming ? PROP_PLAY_ON : PROP_RECORD_ON;
if (m_pCommChannel)
{
hr = m_pCommChannel->SetProperty(dwPropID, &dwOn, sizeof(dwOn));
if(S_OK == hr)
{
// The Mute state has changed
NotifySink((void*)NM_AUDPROP_PAUSE, OnNotifyPropertyChanged);
// The Channel state has changed
NM_AUDIO_STATE uState;
if(SUCCEEDED(GetState(&uState)))
{
NotifySink((void*)uState, OnNotifyStateChanged);
}
}
}
break;
}
case NM_AUDPROP_LEVEL:
{
hr = m_pAudioDevice->SetSilenceLevel(uValue);
break;
}
case NM_AUDPROP_FULL_DUPLEX:
{
DWORD dwDuplex = uValue;
hr = m_pAudioDevice->SetDuplex((BOOL)uValue);
break;
}
case NM_AUDPROP_WAVE_DEVICE:
{
if (m_fIncoming)
{
hr = m_pAudioDevice->SetPlaybackID(uValue);
}
else
{
hr = m_pAudioDevice->SetRecordID(uValue);
}
break;
}
case NM_AUDPROP_AUTOMIX:
{
hr = m_pAudioDevice->SetAutoMix((BOOL)uValue);
break;
}
case NM_AUDPROP_DTMF_DIGIT:
{
IDTMFSend *pDTMF=NULL;
if (!m_fIncoming)
{
hr = m_pAudioChannel->QueryInterface(IID_IDTMFSend, (void**)&pDTMF);
if (SUCCEEDED(hr))
{
hr = pDTMF->AddDigit((int)uValue);
pDTMF->Release();
}
}
}
default:
break;
}
}
return hr;
}