B
Barzo
Hi,
In the following code, I have a _BLOCK_TYPE_IS_VALID assertion when
the CDeviceManager destructor is called.
The 'IAudioCallBackDevice *caller' argument is an object created and
destroyed outside this code.
Could someone give me some suggestion? I cannot find where is the
mistake!
class IAudioCallBackDevice;
class CDeviceManager;
template<class T>
class Singleton : private boost::noncopyable
{
public:
static T& instance()
{
boost::call_once(init, flag);
return *t;
}
static void init() // never throws
{
t.reset(new T());
}
protected:
~Singleton() {}
Singleton() {}
private:
static boost::scoped_ptr<T> t;
static boost:nce_flag flag;
};
template<class T> boost::scoped_ptr<T> Singleton<T>::t(0);
template<class T> boost:nce_flag Singleton<T>::flag =
BOOST_ONCE_INIT;
//----------------------------------------------------------------------------
class CDevicesManager : public Singleton<CDevicesManager>
{
friend class Singleton<CDevicesManager>;
typedef std::map<LONG, CDeviceManager*> TManagersMap;
public:
EAudioLibRetVal InitDevice(LONG device_id,
RtAudio::Api audio_api,
IAudioCallBackDevice *caller);
~CDevicesManager();
private:
TManagersMap Managers_; // A manager for each phisical device
};
//----------------------------------------------------------------------------
class CDeviceManager
{
struct TAudioDevParams
{
RtAudio::StreamParameters OutParams;
RtAudio::StreamParameters InParams;
RtAudioFormat Format;
unsigned int SampleRate;
unsigned int BufferFrames;
RtAudio::StreamOptions Options;
};
struct TCallbackUserData
{
CDeviceManager* ptrThis;
RtAudio::Api CurrentApi;
};
typedef RtAudio* pAudioDev;
typedef IAudioCallBackDevice* pListener;
typedef std::map<INT, pListener> TListeners;
typedef std::map<RtAudio::Api, TListeners> TListenersMap;
typedef std::map<RtAudio::Api, pAudioDev> TAudioDevsMap;
typedef std::map<RtAudio::Api, TAudioDevParams>
TAudioDevParamsMap;
typedef std::map<RtAudio::Api, TCallbackUserData>
TCallbackUserDataMap;
public:
void
NotifyDeviceHandlerDestroy(IAudioCallBackDevice *caller);
EAudioLibRetVal InitDevice(RtAudio::Api audio_api,
IAudioCallBackDevice *caller);
CDeviceManager(CDevicesManager* Manager, LONG DeviceID) :
Manager_(Manager),
DeviceID_(DeviceID) {};
~CDeviceManager();
private:
CDevicesManager* Manager_;
LONG DeviceID_; // The Device ID which
the manager refers to
TAudioDevsMap Devs_; // From
RtAudio::Api::LINUX_ALSA to RtAudio::Api::WINDOWS_DS
TListenersMap ListenersMap_; // From
RtAudio::Api::LINUX_ALSA to RtAudio::Api::WINDOWS_DS
};
//----------------------------------------------------------------------------
class IAudioCallBackDevice
{
public:
IAudioCallBackDevice()
{
srand((unsigned)time(0));
id_ = rand();
};
~IAudioCallBackDevice()
{ // Notify to the Manager when a Device handler is destroyed
if (dev_manager_)
dev_manager_->NotifyDeviceHandlerDestroy(this);
};
inline void SetDeviceManager(CDeviceManager* dev_manager,
RtAudio::Api audio_api)
{ // Sets the Device handler Manager
dev_manager_ = dev_manager;
audio_api_ = audio_api;
};
inline RtAudio::Api GetApi() { return audio_api_; }
virtual INT AudioCallBack(void *AudioBuffer,
UINT nFrames,
double streamTime,
RtAudioStreamStatus status) = 0;
inline CDeviceManager* getDeviceManager() { return
dev_manager_; };
inline INT GetID() { return id_; };
inline bool operator!=(const IAudioCallBackDevice& obj) const {
return (this->id_ != obj.id_);
}
inline bool operator==(const IAudioCallBackDevice& obj) const {
return (this->id_ == obj.id_);
}
private:
CDeviceManager* dev_manager_;
RtAudio::Api audio_api_;
INT id_;
};
The implementation...
//----------------------------------------------------------------------------
EAudioLibRetVal CDevicesManager::InitDevice(LONG
device_id,
RtAudio::Api
audio_api,
IAudioCallBackDevice
*caller)
{
// First of all check if already exist a DeviceManager for device_id
// and if it doesn't, create it
if ( Managers_.find(device_id) == Managers_.end() )
Managers_[device_id] = new CDeviceManager(this, device_id);
// Set the caller's DeviceManager
(caller)->SetDeviceManager( Managers_[device_id], audio_api );
return Managers_[device_id]->InitDevice( audio_api, caller );
};
//----------------------------------------------------------------------------
CDevicesManager::~CDevicesManager()
{
for( TManagersMap::iterator it = Managers_.begin(); it !=
Managers_.end(); it++ )
delete it->second;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
CDeviceManager::~CDeviceManager()
{
//for(TAudioDevsMap::iterator it = Devs_.begin(); it != Devs_.end();
it++ )
TAudioDevsMap::iterator dev = Devs_.begin();
while(dev != Devs_.end())
{
if (dev->second->isStreamRunning()) dev->second->stopStream();
delete dev->second;
Devs_.erase( dev );
dev = Devs_.begin();
}
TListenersMap::iterator it = ListenersMap_.begin();
while(it != ListenersMap_.end())
{
// Remove all listeners
TListeners listeners = it->second;
while (listeners.size() > 0)
listeners.erase(listeners.begin());
//Remove the listeners map
ListenersMap_.erase( it );
it = ListenersMap_.begin();
}
}
//----------------------------------------------------------------------------
EAudioLibRetVal CDeviceManager::InitDevice(RtAudio::Api
audio_api,
IAudioCallBackDevice
*caller)
{
try {
// Searching if the RtAudio class exists for the given Api
// If not, crete it
if ( Devs_.find(audio_api) == Devs_.end() )
Devs_[audio_api] = new RtAudio(audio_api);
DeviceInfo_ = Devs_[audio_api]->getDeviceInfo(DeviceID_);
TListeners lst = ListenersMap_[audio_api];
// Add the listeners
if ( lst.find( caller->GetID() ) == lst.end() )
lst[caller->GetID()] = caller;
// Return a pointer to the device
return RV_NO_ERROR;
}
catch (RtError& e) { return
static_cast<EAudioLibRetVal>(e.getType()); }
}
//----------------------------------------------------------------------------
void CDeviceManager::NotifyDeviceHandlerDestroy(IAudioCallBackDevice*
caller)
{
// When a device handler is destroyed, I remove it from the
listeners list
ListenersMap_[ caller->GetApi() ].erase( caller->GetID() );
};
In the following code, I have a _BLOCK_TYPE_IS_VALID assertion when
the CDeviceManager destructor is called.
The 'IAudioCallBackDevice *caller' argument is an object created and
destroyed outside this code.
Could someone give me some suggestion? I cannot find where is the
mistake!
class IAudioCallBackDevice;
class CDeviceManager;
template<class T>
class Singleton : private boost::noncopyable
{
public:
static T& instance()
{
boost::call_once(init, flag);
return *t;
}
static void init() // never throws
{
t.reset(new T());
}
protected:
~Singleton() {}
Singleton() {}
private:
static boost::scoped_ptr<T> t;
static boost:nce_flag flag;
};
template<class T> boost::scoped_ptr<T> Singleton<T>::t(0);
template<class T> boost:nce_flag Singleton<T>::flag =
BOOST_ONCE_INIT;
//----------------------------------------------------------------------------
class CDevicesManager : public Singleton<CDevicesManager>
{
friend class Singleton<CDevicesManager>;
typedef std::map<LONG, CDeviceManager*> TManagersMap;
public:
EAudioLibRetVal InitDevice(LONG device_id,
RtAudio::Api audio_api,
IAudioCallBackDevice *caller);
~CDevicesManager();
private:
TManagersMap Managers_; // A manager for each phisical device
};
//----------------------------------------------------------------------------
class CDeviceManager
{
struct TAudioDevParams
{
RtAudio::StreamParameters OutParams;
RtAudio::StreamParameters InParams;
RtAudioFormat Format;
unsigned int SampleRate;
unsigned int BufferFrames;
RtAudio::StreamOptions Options;
};
struct TCallbackUserData
{
CDeviceManager* ptrThis;
RtAudio::Api CurrentApi;
};
typedef RtAudio* pAudioDev;
typedef IAudioCallBackDevice* pListener;
typedef std::map<INT, pListener> TListeners;
typedef std::map<RtAudio::Api, TListeners> TListenersMap;
typedef std::map<RtAudio::Api, pAudioDev> TAudioDevsMap;
typedef std::map<RtAudio::Api, TAudioDevParams>
TAudioDevParamsMap;
typedef std::map<RtAudio::Api, TCallbackUserData>
TCallbackUserDataMap;
public:
void
NotifyDeviceHandlerDestroy(IAudioCallBackDevice *caller);
EAudioLibRetVal InitDevice(RtAudio::Api audio_api,
IAudioCallBackDevice *caller);
CDeviceManager(CDevicesManager* Manager, LONG DeviceID) :
Manager_(Manager),
DeviceID_(DeviceID) {};
~CDeviceManager();
private:
CDevicesManager* Manager_;
LONG DeviceID_; // The Device ID which
the manager refers to
TAudioDevsMap Devs_; // From
RtAudio::Api::LINUX_ALSA to RtAudio::Api::WINDOWS_DS
TListenersMap ListenersMap_; // From
RtAudio::Api::LINUX_ALSA to RtAudio::Api::WINDOWS_DS
};
//----------------------------------------------------------------------------
class IAudioCallBackDevice
{
public:
IAudioCallBackDevice()
{
srand((unsigned)time(0));
id_ = rand();
};
~IAudioCallBackDevice()
{ // Notify to the Manager when a Device handler is destroyed
if (dev_manager_)
dev_manager_->NotifyDeviceHandlerDestroy(this);
};
inline void SetDeviceManager(CDeviceManager* dev_manager,
RtAudio::Api audio_api)
{ // Sets the Device handler Manager
dev_manager_ = dev_manager;
audio_api_ = audio_api;
};
inline RtAudio::Api GetApi() { return audio_api_; }
virtual INT AudioCallBack(void *AudioBuffer,
UINT nFrames,
double streamTime,
RtAudioStreamStatus status) = 0;
inline CDeviceManager* getDeviceManager() { return
dev_manager_; };
inline INT GetID() { return id_; };
inline bool operator!=(const IAudioCallBackDevice& obj) const {
return (this->id_ != obj.id_);
}
inline bool operator==(const IAudioCallBackDevice& obj) const {
return (this->id_ == obj.id_);
}
private:
CDeviceManager* dev_manager_;
RtAudio::Api audio_api_;
INT id_;
};
The implementation...
//----------------------------------------------------------------------------
EAudioLibRetVal CDevicesManager::InitDevice(LONG
device_id,
RtAudio::Api
audio_api,
IAudioCallBackDevice
*caller)
{
// First of all check if already exist a DeviceManager for device_id
// and if it doesn't, create it
if ( Managers_.find(device_id) == Managers_.end() )
Managers_[device_id] = new CDeviceManager(this, device_id);
// Set the caller's DeviceManager
(caller)->SetDeviceManager( Managers_[device_id], audio_api );
return Managers_[device_id]->InitDevice( audio_api, caller );
};
//----------------------------------------------------------------------------
CDevicesManager::~CDevicesManager()
{
for( TManagersMap::iterator it = Managers_.begin(); it !=
Managers_.end(); it++ )
delete it->second;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
CDeviceManager::~CDeviceManager()
{
//for(TAudioDevsMap::iterator it = Devs_.begin(); it != Devs_.end();
it++ )
TAudioDevsMap::iterator dev = Devs_.begin();
while(dev != Devs_.end())
{
if (dev->second->isStreamRunning()) dev->second->stopStream();
delete dev->second;
Devs_.erase( dev );
dev = Devs_.begin();
}
TListenersMap::iterator it = ListenersMap_.begin();
while(it != ListenersMap_.end())
{
// Remove all listeners
TListeners listeners = it->second;
while (listeners.size() > 0)
listeners.erase(listeners.begin());
//Remove the listeners map
ListenersMap_.erase( it );
it = ListenersMap_.begin();
}
}
//----------------------------------------------------------------------------
EAudioLibRetVal CDeviceManager::InitDevice(RtAudio::Api
audio_api,
IAudioCallBackDevice
*caller)
{
try {
// Searching if the RtAudio class exists for the given Api
// If not, crete it
if ( Devs_.find(audio_api) == Devs_.end() )
Devs_[audio_api] = new RtAudio(audio_api);
DeviceInfo_ = Devs_[audio_api]->getDeviceInfo(DeviceID_);
TListeners lst = ListenersMap_[audio_api];
// Add the listeners
if ( lst.find( caller->GetID() ) == lst.end() )
lst[caller->GetID()] = caller;
// Return a pointer to the device
return RV_NO_ERROR;
}
catch (RtError& e) { return
static_cast<EAudioLibRetVal>(e.getType()); }
}
//----------------------------------------------------------------------------
void CDeviceManager::NotifyDeviceHandlerDestroy(IAudioCallBackDevice*
caller)
{
// When a device handler is destroyed, I remove it from the
listeners list
ListenersMap_[ caller->GetApi() ].erase( caller->GetID() );
};