Re: How to work with COM classes and std::map
On 13 Ott, 02:45, "Igor Tandetnik" <itandet...@mvps.org> wrote:
Also, when I terminate the application the CAudioPlayer::FinalRelease
() is called but CWaveStream::FinalRelease() is not!
It's possible for the client to release all references on CAudioPlayer but keep around its references to IWaveStream. There's nothing in your code that would prevent an instance of CWaveStream from outliving that of CAudioPlayer.
Hi Igor,
thanks for your time..
Ok, I post the entire code.
This ActiveX is a wrapper around a C++ static library (Namespace
EuroAudioLib).
I replicate the same behaviour of the library creating "same" classes,
so the CWaveStream holds a pointer to a EuroAudioLib::WaveStream
object.
The CAudioPlayer simply holds a collection of streams stored in a
std::map like I wrote in the previous post.
WaveStream.h
-------------
// WaveStream.h : Declaration of the CWaveStream
#pragma once
#include "resource.h" // main symbols
#include "AxAudioLib4_i.h"
#include "_IWaveStreamEvents_CP.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined
(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on
Windows CE platform, such as the Windows Mobile platforms that do not
include full DCOM support. Define
_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support
creating single-thread COM object's and allow use of it's single-
threaded COM object implementations. The threading model in your rgs
file was set to 'Free' as that is the only threading model supported
in non DCOM Windows CE platforms."
#endif
class CWaveStream;
/////////////////////////////////////////////////////////////////////////////
// WaveStreamEvents
class WaveStreamEvents : public EuroAudioLib::IWaveStreamEvents
{
public:
WaveStreamEvents(CWaveStream &WaveStreamObj);
void OnStreamStateChanged(EuroAudioLib::IWaveStream* Sender, int
new_state);
void OnStreamDebugMsg(EuroAudioLib::IWaveStream* Sender, std::string
msg);
void OnStreamEnd(EuroAudioLib::IWaveStream* Sender);
private:
CWaveStream& WaveStreamObj_;
};
// CWaveStream
class ATL_NO_VTABLE CWaveStream :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CWaveStream, &CLSID_WaveStream>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CWaveStream>,
public CProxy_IWaveStreamEvents<CWaveStream>,
public IDispatchImpl<IWaveStream, &IID_IWaveStream,
&LIBID_AxAudioLib4, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CWaveStream();
DECLARE_REGISTRY_RESOURCEID(IDR_WAVESTREAM)
BEGIN_COM_MAP(CWaveStream)
COM_INTERFACE_ENTRY(IWaveStream)
//COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CWaveStream)
CONNECTION_POINT_ENTRY(__uuidof(_IWaveStreamEvents))
END_CONNECTION_POINT_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct();
void FinalRelease();
public:
void SetStreamObj(EuroAudioLib::IWaveStream *stream);
STDMETHOD(get_DebugEnabled)(/*[out, retval]*/ VARIANT_BOOL*);
STDMETHOD(put_DebugEnabled)(/*[in]*/ VARIANT_BOOL mode);
STDMETHOD(get_Compression)(/*[out, retval]*/ short*);
STDMETHOD(put_Compression)(/*[in]*/ short compression);
STDMETHOD(get_StreamType)(/*[out, retval]*/ E_STREAM_TYPE*);
//STDMETHOD(LocalIPList(TIpList* ip_list);
STDMETHOD(get_LocalPort)(/*[out, retval]*/ short*);
STDMETHOD(put_LocalPort)(/*[in]*/ short port);
STDMETHOD(get_RemotePort)(/*[out, retval]*/ short*);
STDMETHOD(put_RemotePort)(/*[in]*/ short port);
STDMETHOD(get_RxTimerIterval)(/*[out, retval]*/ short*);
STDMETHOD(put_RxTimerIterval)(/*[in]*/ short value);
STDMETHOD(get_TxIP)(/*[out, retval]*/ BSTR*);
STDMETHOD(put_TxIP)(/*[in]*/ BSTR ip_address);
STDMETHOD(get_RxIP)(/*[out, retval]*/ BSTR*);
STDMETHOD(put_RxIP)(/*[in]*/ BSTR ip_address);
STDMETHOD(get_EnableRTX)(/*[out, retval]*/ VARIANT_BOOL*);
STDMETHOD(put_EnableRTX)(/*[in]*/ VARIANT_BOOL value);
STDMETHOD(get_StreamState)(/*[out, retval]*/ E_STREAM_STATE*);
STDMETHOD(get_Key)(/*[out, retval]*/ BSTR*);
STDMETHOD(GetLastError)(/*[out, retval]*/ short*);
STDMETHOD(GetLastErrorStr)(/*[out, retval]*/ BSTR*);
STDMETHOD(Bind)(/*[in, defaultvalue(0)]*/ short local_port,
/*[out, retval]*/ E_AUDIOLIB_RET_VAL *pVal);
STDMETHOD(SendRTPPacket)(/*[in]*/ long lpData,
/*[in]*/ short len,
/*[in, defaultvalue(0)]*/ short pt,
/*[in, defaultvalue(0)]*/ VARIANT_BOOL
mark,
/*[in, defaultvalue(0)]*/ long
timestampinc,
/*[out, retval]*/ short*);
STDMETHOD(SendRTPPacketEx)(/*[in]*/ long lpData,
/*[in]*/ short len,
/*[in, defaultvalue(0)]*/ short
hdrextID,
/*[in, defaultvalue(0)]*/ long
lphdrextdata,
/*[in, defaultvalue(0)]*/ short
numhdrextwords,
/*[in, defaultvalue(0)]*/ short pt,
/*[in, defaultvalue(0)]*/ VARIANT_BOOL
mark,
/*[in, defaultvalue(0)]*/ long
timestampinc,
/*[out, retval]*/ short*);
private:
EuroAudioLib::IWaveStream *stream_;
WaveStreamEvents stream_ev_;
};
// This object is 'noncreatable' so we change the Object entry
// so the object is noncreatable but the control is registered
//OBJECT_ENTRY_AUTO(__uuidof(WaveStream), CWaveStream)
OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO(__uuidof(WaveStream), CWaveStream)
---------------------------
CWaveStream.cpp
---------------------------
// WaveStream.cpp : Implementation of CWaveStream
#include "stdafx.h"
#include "WaveStream.h"
//------------------------------------------------------------------------------
// WaveStreamEvents Implementation
//------------------------------------------------------------------------------
WaveStreamEvents::WaveStreamEvents(CWaveStream &WaveStreamObj) :
WaveStreamObj_(WaveStreamObj)
{
};
//------------------------------------------------------------------------------
void WaveStreamEvents::OnStreamStateChanged(EuroAudioLib::IWaveStream*
Sender, int new_state)
{
WaveStreamObj_.Fire_OnStreamStateChanged(&WaveStreamObj_,
new_state);
};
//------------------------------------------------------------------------------
void WaveStreamEvents::OnStreamEnd(EuroAudioLib::IWaveStream* Sender)
{
WaveStreamObj_.Fire_OnStreamEnd(&WaveStreamObj_);
};
//------------------------------------------------------------------------------
void WaveStreamEvents::OnStreamDebugMsg(EuroAudioLib::IWaveStream*
Sender, std::string msg)
{
_bstr_t b_msg(msg.c_str());
WaveStreamObj_.Fire_OnStreamDebugMsg( &WaveStreamObj_, b_msg.copy
() );
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// CWaveStream
STDMETHODIMP CWaveStream::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IWaveStream
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
//------------------------------------------------------------------------------
HRESULT CWaveStream::FinalConstruct()
{
return S_OK;
}
//------------------------------------------------------------------------------
void CWaveStream::FinalRelease()
{
}
//------------------------------------------------------------------------------
CWaveStream::CWaveStream() : stream_ev_(*this), stream_(NULL)
{
};
//------------------------------------------------------------------------------
void CWaveStream::SetStreamObj(EuroAudioLib::IWaveStream *stream)
{
stream_ = stream;
//I register my stream_ev_ member like event handler
stream_->AttachEventHandler(&stream_ev_);
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_DebugEnabled(VARIANT_BOOL* pVal)
{
if (stream_) *pVal = stream_->getDebugMode();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_DebugEnabled(VARIANT_BOOL mode)
{
if (stream_) stream_->setDebugMode(mode);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_Compression(short* pVal)
{
if (stream_) *pVal = stream_->getCompression();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_Compression(short compression)
{
if (stream_) stream_->setCompression(compression);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_StreamType( E_STREAM_TYPE* pVal)
{
if (stream_) *pVal = static_cast<E_STREAM_TYPE>(stream_-
getStreamType());
return S_OK;
};
//------------------------------------------------------------------------------
//STDMETHODIMP CWaveStream::LocalIPList(TIpList* ip_list)
//{
//};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_LocalPort(short* pVal)
{
if (stream_) *pVal = stream_->getLocalPort();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_LocalPort(short port)
{
if (stream_) stream_->setLocalPort(port);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_RemotePort(short* pVal)
{
if (stream_) *pVal = stream_->getRemotePort();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_RemotePort(short port)
{
if (stream_) stream_->setRemotePort(port);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_RxTimerIterval(short* pVal)
{
if (stream_) *pVal = stream_->getRxTimerIterval();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_RxTimerIterval(short value)
{
if (stream_) stream_->setRxTimerIterval(value);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_TxIP(BSTR* pVal)
{
if (stream_) {
_bstr_t* sIP = new _bstr_t( stream_->getTxIP().c_str() );
*pVal = sIP->copy();
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_TxIP(BSTR ip_address)
{
if (stream_) {
std::string sIP((char*)_bstr_t(ip_address));
stream_->setTxIP(sIP);
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_RxIP(BSTR* pVal)
{
if (stream_) {
_bstr_t* sIP = new _bstr_t( stream_->getTxIP().c_str() );
*pVal = sIP->copy();
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_RxIP(BSTR ip_address)
{
if (stream_) {
std::string sIP((char*)_bstr_t(ip_address));
stream_->setRxIP(sIP);
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_EnableRTX(VARIANT_BOOL* pVal)
{
if (stream_) *pVal = stream_->getEnableRTX();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::put_EnableRTX(VARIANT_BOOL value)
{
if (stream_) stream_->setEnableRTX(value);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_StreamState(E_STREAM_STATE* pVal)
{
if (stream_) *pVal = static_cast<E_STREAM_STATE>(stream_-
getStreamState());
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::get_Key(BSTR* pVal)
{
if (stream_) {
_bstr_t* bstr = new _bstr_t(stream_->Key().c_str());
*pVal = bstr->copy();
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::GetLastError(short* pVal)
{
if (stream_) *pVal = stream_->GetLastError();
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::GetLastErrorStr(BSTR* pVal)
{
if (stream_) {
_bstr_t* bstr = new _bstr_t(stream_->GetLastErrorStr().c_str());
*pVal = bstr->copy();
}
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::Bind(short local_port, E_AUDIOLIB_RET_VAL
*pVal)
{
if (stream_) *pVal = static_cast<E_AUDIOLIB_RET_VAL>(stream_->Bind
(local_port));
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::SendRTPPacket(long lpData,
short len,
short pt,
VARIANT_BOOL mark,
long timestampinc,
short* pVal)
{
if (stream_) *pVal = stream_->SendRTPPacket((const void*)lpData,
len, pt, mark, timestampinc);
return S_OK;
};
//------------------------------------------------------------------------------
STDMETHODIMP CWaveStream::SendRTPPacketEx(long lpData,
short len,
short hdrextID,
long lphdrextdata,
short
numhdrextwords,
short pt,
VARIANT_BOOL mark,
long timestampinc,
short* pVal)
{
return S_FALSE;
};
//------------------------------------------------------------------------------
The VB6 client code is simply a test:
Dim p As AudioPlayer
Private Sub Form_Load()
Dim ws As WaveStream
PrintLog "CREATE A WAVE STREAM1"
Set ws = p.CreateStream("STREAM1")
PrintLog "ActiveStream.Key = " & p.GetActiveStream.Key
PrintLog "RxIP = " & ws.RxIP
PrintLog "TxIP = " & ws.TxIP
PrintLog "CREATE A WAVE STREAM2"
Set ws = p.CreateStream("STREAM2")
PrintLog "ActiveStream.Key = " & p.GetActiveStream.Key
PrintLog "DELETE STREAM 2": p.DeleteStream "STREAM2"
PrintLog "ActiveStream.Key = " & p.GetActiveStream.Key
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set p = Nothing
End Sub
I hope someone can find my error...
Thanks,
Daniele.