caudio/cAudio/src/cAudioManager.cpp

497 lines
12 KiB
C++

// Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari
// This file is part of the "cAudio Engine"
// For conditions of distribution and use, see copyright notice in cAudio.h
#include "cAudioManager.h"
#include "cAudio.h"
#include "cAudioSource.h"
#include "cAudioPlatform.h"
#include "cAudioSleep.h"
#include "cUtils.h"
#include "cThread.h"
#include "cLogger.h"
#include "cPluginManager.h"
#include "cThread.h"
#include "cMemorySource.h"
#include "cRawAudioDecoderFactory.h"
#include <string.h>
#include <algorithm>
#include "cOpenALDeviceContext.h"
namespace cAudio
{
cAudioManager::~cAudioManager()
{
shutDown();
}
bool cAudioManager::initialize(const char* deviceName, int outputFrequency, int eaxEffectSlots)
{
cAudioMutexBasicLock lock(Mutex);
if(Initialized)
return false;
AudioContext = CAUDIO_NEW cOpenALDeviceContext(this);
if(!AudioContext->initialize(deviceName, outputFrequency, eaxEffectSlots))
return false;
#ifdef CAUDIO_USE_INTERNAL_THREAD
if (!AudioThread)
{
AudioThread = new cAudioThread(this);
}
AudioThread->start();
#endif
Initialized = true;
return true;
}
void cAudioManager::shutDown()
{
if(Initialized)
{
if (AudioThread) // First wait for our update thread to finish up
{
AudioThread->join();
delete AudioThread;
AudioThread = NULL;
}
cAudioMutexBasicLock lock(Mutex);
releaseAllSources();
if (AudioContext)
{
AudioContext->shutDown();
CAUDIO_DELETE AudioContext;
AudioContext = NULL;
}
Initialized = false;
getLogger()->logInfo("AudioManager", "Manager successfully shutdown.");
}
}
void cAudioManager::update()
{
cAudioMutexBasicLock lock(Mutex);
size_t count = audioSources.size();
for(unsigned int i=0; i<count; i++)
{
IAudioSource* source = audioSources[i];
if (source->isValid())
{
source->update();
}
}
}
void cAudioManager::run()
{
if(!audioSources.empty())
update();
cAudioSleep(1);
}
bool cAudioManager::isUpdateThreadRunning()
{
return (AudioThread != NULL && AudioThread->isRunning());
}
IAudioEffects* cAudioManager::getEffects()
{
if (AudioContext)
{
return AudioContext->getEffects();
}
return NULL;
}
IAudioSource* cAudioManager::createAudioSource(IAudioDecoder* decoder, const cAudioString& audioName, const cAudioString& dataSource)
{
if(decoder && decoder->isValid())
{
#if CAUDIO_EFX_ENABLED == 1
IAudioSource* audio = CAUDIO_NEW cAudioSource(decoder, ((cOpenALDeviceContext*)AudioContext)->getOpenALContext(), ((cAudioEffects*)getEffects())->getEFXInterface());
#else
IAudioSource* audio = CAUDIO_NEW cAudioSource(decoder, ((cOpenALDeviceContext*)AudioContext)->getOpenALContext());
#endif
decoder->drop();
if(audio && audio->isValid())
{
if(!audioName.empty())
audioIndex[audioName] = audio;
audioSources.push_back(audio);
getLogger()->logInfo("AudioManager", "Audio Source (%s) created from Data Source %s.", audioName.c_str(), dataSource.c_str());
return audio;
}
getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Error creating audio source.", audioName.c_str());
audio->drop();
return NULL;
}
getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder.", audioName.c_str(), decoder->getType());
decoder->drop();
return NULL;
}
IAudioSource* cAudioManager::create(const char* name, const char* filename, bool stream)
{
if(!Initialized) return NULL;
cAudioMutexBasicLock lock(Mutex);
cAudioString audioName = safeCStr(name);
cAudioString path = safeCStr(filename);
cAudioString ext = getExt(path);
IAudioDecoderFactory* factory = getAudioDecoderFactory(ext.c_str());
if(!factory) {
getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): No decoder could be found for (.%s).", audioName.c_str(), ext.c_str());
return NULL;
}
for(size_t i=0; i<dataSourcePriorityList.size(); ++i)
{
const cAudioString dataSourceName = dataSourcePriorityList[i].second;
IDataSourceFactory* dataFactory = datasourcemap[dataSourceName];
if(dataFactory)
{
IDataSource* source = dataFactory->CreateDataSource(filename, stream);
if(source && source->isValid())
{
IAudioDecoder* decoder = factory->CreateAudioDecoder(source);
source->drop();
IAudioSource* audio = createAudioSource(decoder, audioName, dataSourceName);
if(audio != NULL)
return audio;
if(source)
source->drop();
return NULL;
}
}
}
return NULL;
}
IAudioSource* cAudioManager::createFromMemory(const char* name, const char* data, size_t length, const char* extension)
{
if(!Initialized) return NULL;
cAudioMutexBasicLock lock(Mutex);
cAudioString audioName = safeCStr(name);
cAudioString ext = safeCStr(extension);
IAudioDecoderFactory* factory = getAudioDecoderFactory(ext.c_str());
if(!factory) {
getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Codec (.%s) is not supported.", audioName.c_str(), ext.c_str());
return NULL;
}
cMemorySource* source = CAUDIO_NEW cMemorySource(data, length, true);
if(source && source->isValid())
{
IAudioDecoder* decoder = factory->CreateAudioDecoder(source);
source->drop();
IAudioSource* audio = createAudioSource(decoder, audioName, "cMemorySource");
if(audio != NULL)
return audio;
if(source)
source->drop();
}
return NULL;
}
IAudioSource* cAudioManager::createFromRaw(const char* name, const char* data, size_t length, unsigned int frequency, AudioFormats format)
{
if(!Initialized) return NULL;
cAudioMutexBasicLock lock(Mutex);
cAudioString audioName = safeCStr(name);
IAudioDecoderFactory* factory = getAudioDecoderFactory("raw");
if(!factory) {
getLogger()->logError("AudioManager", "Failed to create Audio Source (%s): Codec (.raw) is not supported.", audioName.c_str());
return NULL;
}
cMemorySource* source = CAUDIO_NEW cMemorySource(data, length, true);
if(source && source->isValid())
{
IAudioDecoder* decoder = ((cRawAudioDecoderFactory*)factory)->CreateAudioDecoder(source, frequency, format);
source->drop();
IAudioSource* audio = createAudioSource(decoder, audioName, "cMemorySource");
if(audio != NULL)
return audio;
if(source)
source->drop();
}
return NULL;
}
bool cAudioManager::registerAudioDecoder(IAudioDecoderFactory* factory, const char* extension)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString ext = safeCStr(extension);
decodermap[ext] = factory;
getLogger()->logInfo("AudioManager", "Audio Decoder for extension .%s registered.", ext.c_str());
return true;
}
void cAudioManager::unRegisterAudioDecoder(const char* extension)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString ext = safeCStr(extension);
decodermapIterator it = decodermap.find(ext);
if(it != decodermap.end())
{
decodermap.erase(it);
getLogger()->logInfo("AudioManager", "Audio Decoder for extension .%s unregistered.", ext.c_str());
}
}
bool cAudioManager::isAudioDecoderRegistered(const char* extension)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString ext = safeCStr(extension);
decodermapIterator it = decodermap.find(ext);
return (it != decodermap.end());
}
IAudioDecoderFactory* cAudioManager::getAudioDecoderFactory(const char* extension)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString ext = safeCStr(extension);
decodermapIterator it = decodermap.find(ext);
if(it != decodermap.end())
{
return it->second;
}
return NULL;
}
void cAudioManager::unRegisterAllAudioDecoders()
{
cAudioMutexBasicLock lock(Mutex);
decodermap.clear();
}
bool compareDataSourcePriorities(std::pair<int, cAudioString> left, std::pair<int, cAudioString> right)
{
return (left.first > right.first);
}
bool cAudioManager::registerDataSource(IDataSourceFactory* factory, const char* name, int priority)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString safeName = safeCStr(name);
datasourcemap[safeName] = factory;
dataSourcePriorityList.push_back(std::pair<int, cAudioString>(priority, safeName));
std::sort(dataSourcePriorityList.begin(), dataSourcePriorityList.end(), compareDataSourcePriorities);
getLogger()->logInfo("AudioManager", "Data Source named %s registered (Priority %i).", safeName.c_str(), priority);
return true;
}
void cAudioManager::unRegisterDataSource(const char* name)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString safeName = safeCStr(name);
datasourcemapIterator it = datasourcemap.find(safeName);
if(it != datasourcemap.end())
{
datasourcemap.erase(it);
getLogger()->logInfo("AudioManager", "Data Source named %s unregistered.", safeName.c_str());
}
for(size_t i=0; i<dataSourcePriorityList.size(); ++i)
{
if(dataSourcePriorityList[i].second == safeName)
{
dataSourcePriorityList.erase(dataSourcePriorityList.begin()+i);
break;
}
}
std::sort(dataSourcePriorityList.begin(), dataSourcePriorityList.end(), compareDataSourcePriorities);
}
bool cAudioManager::isDataSourceRegistered(const char* name)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString safeName = safeCStr(name);
datasourcemapIterator it = datasourcemap.find(safeName);
return (it != datasourcemap.end());
}
IDataSourceFactory* cAudioManager::getDataSourceFactory(const char* name)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString safeName = safeCStr(name);
datasourcemapIterator it = datasourcemap.find(safeName);
if(it != datasourcemap.end())
{
return it->second;
}
return NULL;
}
void cAudioManager::unRegisterAllDataSources()
{
cAudioMutexBasicLock lock(Mutex);
datasourcemap.clear();
dataSourcePriorityList.clear();
}
void cAudioManager::registerEventHandler(IManagerEventHandler* handler)
{
if(handler)
{
eventHandlerList.push_back(handler);
}
}
void cAudioManager::unRegisterEventHandler(IManagerEventHandler* handler)
{
if(handler)
{
eventHandlerList.remove(handler);
}
}
void cAudioManager::unRegisterAllEventHandlers()
{
eventHandlerList.clear();
}
void cAudioManager::signalEvent(Events sevent)
{
cAudioMutexBasicLock lock(Mutex);
cAudioList<IManagerEventHandler*>::Type::iterator it = eventHandlerList.begin();
if(it != eventHandlerList.end())
{
switch(sevent)
{
case ON_INIT:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onInit();
}
break;
case ON_UPDATE:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onUpdate();
}
break;
case ON_RELEASE:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onRelease();
}
break;
case ON_SOURCECREATE:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onSourceCreate();
}
break;
case ON_DECODERREGISTER:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onDecoderRegister();
}
break;
case ON_DATASOURCEREGISTER:
for(it; it != eventHandlerList.end(); it++)
{
(*it)->onDataSourceRegister();
}
break;
}
}
}
IAudioSource* cAudioManager::getSoundByName(const char* name)
{
cAudioMutexBasicLock lock(Mutex);
cAudioString audioName = safeCStr(name);
audioIndexIterator i = audioIndex.find(audioName);
if (i == audioIndex.end())
{
return NULL;
}
return i->second;
}
void cAudioManager::releaseAllSources()
{
cAudioMutexBasicLock lock(Mutex);
for(unsigned int i=0; i<audioSources.size(); ++i)
{
IAudioSource* source = audioSources[i];
if(source)
source->drop();
}
audioSources.clear();
audioIndex.clear();
}
void cAudioManager::release(IAudioSource* source)
{
if(source)
{
cAudioMutexBasicLock lock(Mutex);
audioIndexIterator it = audioIndex.begin();
for ( it=audioIndex.begin(); it != audioIndex.end(); it++ )
{
if( it->second == source )
{
audioIndex.erase(it);
break;
}
}
for(unsigned int i=0; i<audioSources.size(); ++i)
{
if(source == audioSources[i])
{
audioSources.erase(audioSources.begin()+i);
source->drop();
break;
}
}
}
}
};