2010-02-09 05:18:39 +01:00
// Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones
// This file is part of the "cAudio Engine"
// For conditions of distribution and use, see copyright notice in cAudio.h
2009-06-21 05:24:30 +02:00
# include "../Headers/cAudioManager.h"
# include "../Headers/cFileSource.h"
# include "../Headers/cMemorySource.h"
# include "../Headers/cUtils.h"
# include "../Headers/cOggAudioDecoderFactory.h"
2009-12-07 23:25:08 +01:00
# include "../Headers/cWavAudioDecoderFactory.h"
2009-08-11 19:57:20 +02:00
# include "../Headers/cRawAudioDecoderFactory.h"
2009-08-29 13:24:31 +02:00
# include "../Headers/cThread.h"
# include "../include/cAudioSleep.h"
2009-11-20 04:39:56 +01:00
# include "../Headers/cLogger.h"
2010-02-09 06:58:27 +01:00
# include "../Headers/cPluginManager.h"
2010-02-09 07:08:46 +01:00
# include "../include/cAudioPlatform.h"
2010-02-13 06:48:19 +01:00
# include "../Headers/cFileSourceFactory.h"
2009-11-20 04:39:56 +01:00
2010-02-09 06:33:32 +01:00
# include <string.h>
2010-02-13 06:48:19 +01:00
# include <algorithm>
2010-02-09 06:33:32 +01:00
2010-02-13 03:34:50 +01:00
# ifdef CAUDIO_EFX_ENABLED
2010-02-09 07:08:46 +01:00
# ifdef CAUDIO_PLATFORM_WIN
2010-02-09 06:33:32 +01:00
# include <AL/efx.h>
# include <AL/efx-creative.h>
# include <AL/xram.h>
# endif
2010-02-09 07:08:46 +01:00
# ifdef CAUDIO_PLATFORM_LINUX
2010-02-09 06:33:32 +01:00
# include <AL/alext.h>
# endif
2009-06-21 05:24:30 +02:00
2010-02-13 03:34:50 +01:00
# endif
2009-06-21 05:24:30 +02:00
namespace cAudio
{
2009-11-20 04:39:56 +01:00
static bool RunAudioManagerThread ( false ) ;
# ifdef CAUDIO_COMPILE_WITH_OGG_DECODER
static cOggAudioDecoderFactory OggDecoderFactory ;
# endif
# ifdef CAUDIO_COMPILE_WITH_WAV_DECODER
static cWavAudioDecoderFactory WavDecoderFactory ;
# endif
2010-02-13 03:34:50 +01:00
2009-11-20 04:39:56 +01:00
static cRawAudioDecoderFactory RawDecoderFactory ;
2010-03-05 02:52:25 +01:00
# ifdef CAUDIO_COMPILE_WITH_FILE_SOURCE
2010-02-13 06:48:19 +01:00
static cFileSourceFactory FileSourceFactory ;
2010-03-05 02:52:25 +01:00
# endif
2010-02-13 06:48:19 +01:00
2009-11-20 04:39:56 +01:00
//Note: OpenAL is threadsafe, so a mutex only needs to protect the class state
# ifdef CAUDIO_USE_INTERNAL_THREAD
static cAudioMutex AudioManagerObjectsMutex ;
2010-03-14 23:58:03 +01:00
static cAudioSet < IAudioManager * > : : Type AudioManagerObjects ;
2009-06-21 05:24:30 +02:00
2009-11-20 04:39:56 +01:00
CAUDIO_DECLARE_THREAD_FUNCTION ( AudioManagerUpdateThread )
2009-08-29 13:24:31 +02:00
{
2009-11-20 04:39:56 +01:00
while ( RunAudioManagerThread )
2009-08-29 13:24:31 +02:00
{
2009-11-20 04:39:56 +01:00
AudioManagerObjectsMutex . lock ( ) ;
2010-03-14 23:58:03 +01:00
cAudioSet < IAudioManager * > : : Type : : iterator it ;
2009-11-20 04:39:56 +01:00
for ( it = AudioManagerObjects . begin ( ) ; it ! = AudioManagerObjects . end ( ) ; it + + )
2009-08-29 13:24:31 +02:00
{
2009-11-20 04:39:56 +01:00
( * it ) - > update ( ) ;
2009-08-29 13:24:31 +02:00
}
2009-11-20 04:39:56 +01:00
AudioManagerObjectsMutex . unlock ( ) ;
2009-08-29 13:24:31 +02:00
cAudioSleep ( 1 ) ;
}
2009-11-20 04:39:56 +01:00
return 0 ;
2009-08-29 13:24:31 +02:00
}
2009-11-20 04:39:56 +01:00
# endif
2009-08-29 13:24:31 +02:00
2009-11-20 04:39:56 +01:00
bool cAudioManager : : initialize ( const char * deviceName , int outputFrequency , int eaxEffectSlots )
2009-06-21 05:24:30 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
if ( Initialized )
2010-01-11 01:39:08 +01:00
return false ;
2009-11-20 04:39:56 +01:00
//Stores the context attributes (MAX of 4, with 2 zeros to terminate)
ALint attribs [ 6 ] = { 0 } ;
unsigned int currentAttrib = 0 ;
if ( outputFrequency > 0 )
{
attribs [ currentAttrib + + ] = ALC_FREQUENCY ;
attribs [ currentAttrib + + ] = outputFrequency ;
}
2010-02-13 03:34:50 +01:00
# ifdef CAUDIO_EFX_ENABLED
2009-11-20 04:39:56 +01:00
if ( eaxEffectSlots > 0 )
{
attribs [ currentAttrib + + ] = ALC_MAX_AUXILIARY_SENDS ;
attribs [ currentAttrib + + ] = eaxEffectSlots ;
}
2010-02-13 03:34:50 +01:00
# endif
2009-11-20 04:39:56 +01:00
2009-08-27 01:46:18 +02:00
//Create a new device
2009-11-20 04:39:56 +01:00
Device = alcOpenDevice ( deviceName ) ;
2009-08-27 01:46:18 +02:00
//Check if device can be created
2009-11-20 04:39:56 +01:00
if ( Device = = NULL )
{
getLogger ( ) - > logError ( " AudioManager " , " Failed to Create OpenAL Device. " ) ;
checkError ( ) ;
return false ;
2009-11-15 18:11:38 +01:00
}
2009-08-08 07:51:32 +02:00
2009-11-20 04:39:56 +01:00
Context = alcCreateContext ( Device , attribs ) ;
if ( Context = = NULL )
{
getLogger ( ) - > logError ( " AudioManager " , " Failed to Create OpenAL Context. " ) ;
checkError ( ) ;
2009-12-07 23:25:08 +01:00
alcCloseDevice ( Device ) ;
Device = NULL ;
2009-11-20 04:39:56 +01:00
return false ;
}
2009-09-03 05:00:03 +02:00
2009-11-20 04:39:56 +01:00
if ( ! alcMakeContextCurrent ( Context ) )
{
getLogger ( ) - > logError ( " AudioManager " , " Failed to make OpenAL Context current. " ) ;
checkError ( ) ;
2009-12-07 23:25:08 +01:00
alcDestroyContext ( Context ) ;
alcCloseDevice ( Device ) ;
Context = NULL ;
Device = NULL ;
2009-11-20 04:39:56 +01:00
return false ;
}
2009-08-08 07:51:32 +02:00
2010-01-11 01:39:08 +01:00
# ifdef CAUDIO_EFX_ENABLED
initEffects . getEFXInterface ( ) - > Mutex . lock ( ) ;
EFXSupported = initEffects . getEFXInterface ( ) - > CheckEFXSupport ( Device ) ;
initEffects . getEFXInterface ( ) - > Mutex . unlock ( ) ;
initEffects . checkEFXSupportDetails ( ) ;
# endif
2009-11-20 04:39:56 +01:00
getLogger ( ) - > logInfo ( " AudioManager " , " OpenAL Version: %s " , alGetString ( AL_VERSION ) ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Vendor: %s " , alGetString ( AL_VENDOR ) ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Renderer: %s " , alGetString ( AL_RENDERER ) ) ;
2010-01-11 01:39:08 +01:00
# ifdef CAUDIO_EFX_ENABLED
2009-12-07 23:25:08 +01:00
if ( EFXSupported )
{
int EFXMajorVersion = 0 ;
int EFXMinorVersion = 0 ;
alcGetIntegerv ( Device , ALC_EFX_MAJOR_VERSION , 1 , & EFXMajorVersion ) ;
alcGetIntegerv ( Device , ALC_EFX_MINOR_VERSION , 1 , & EFXMinorVersion ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " EFX Version: %i.%i " , EFXMajorVersion , EFXMinorVersion ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " EFX supported and enabled. " ) ;
}
else
{
getLogger ( ) - > logWarning ( " AudioManager " , " EFX is not supported, EFX disabled. " ) ;
}
# endif
2009-11-20 04:39:56 +01:00
getLogger ( ) - > logInfo ( " AudioManager " , " Supported Extensions: %s " , alGetString ( AL_EXTENSIONS ) ) ;
2009-08-11 19:57:20 +02:00
2009-12-07 23:25:08 +01:00
Initialized = true ;
2009-11-20 04:39:56 +01:00
return true ;
2009-06-21 05:24:30 +02:00
}
2010-02-13 06:48:19 +01:00
IAudioSource * cAudioManager : : create ( const char * name , const char * filename , bool stream )
2009-06-21 05:24:30 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-12-01 02:41:15 +01:00
2010-03-14 23:58:03 +01:00
cAudioString audioName = safeCStr ( name ) ;
cAudioString path = safeCStr ( filename ) ;
2009-12-01 02:41:15 +01:00
2010-03-14 23:58:03 +01:00
cAudioString ext = getExt ( path ) ;
2009-12-07 23:25:08 +01:00
IAudioDecoderFactory * factory = getAudioDecoderFactory ( ext . c_str ( ) ) ;
2010-02-13 06:48:19 +01:00
2009-12-07 23:25:08 +01:00
if ( factory )
2009-12-01 02:41:15 +01:00
{
2010-02-13 06:48:19 +01:00
for ( int i = 0 ; i < dataSourcePriorityList . size ( ) ; + + i )
2009-12-07 23:25:08 +01:00
{
2010-02-13 06:48:19 +01:00
IDataSourceFactory * dataFactory = datasourcemap [ dataSourcePriorityList [ i ] . second ] ;
if ( dataFactory )
2009-08-11 19:57:20 +02:00
{
2010-02-13 06:48:19 +01:00
IDataSource * source = dataFactory - > CreateDataSource ( filename , stream ) ;
if ( source & & source - > isValid ( ) )
2009-12-07 23:25:08 +01:00
{
IAudioDecoder * decoder = factory - > CreateAudioDecoder ( source ) ;
source - > drop ( ) ;
2010-02-13 06:48:19 +01:00
if ( decoder & & decoder - > isValid ( ) )
2009-12-07 23:25:08 +01:00
{
2010-02-13 03:34:50 +01:00
# ifdef CAUDIO_EFX_ENABLED
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context , initEffects . getEFXInterface ( ) ) ;
2010-02-13 03:34:50 +01:00
# else
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context ) ;
2010-02-13 03:34:50 +01:00
# endif
2010-02-13 06:48:19 +01:00
decoder - > drop ( ) ;
2009-12-07 23:25:08 +01:00
2010-02-13 06:48:19 +01:00
if ( audio & & audio - > isValid ( ) )
{
if ( ! audioName . empty ( ) )
audioIndex [ audioName ] = audio ;
audioSources . push_back ( audio ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Source (%s) created from file %s from Data Source %s. " , audioName . c_str ( ) , path . c_str ( ) , dataSourcePriorityList [ i ] . second . c_str ( ) ) ;
return audio ;
2009-12-07 23:25:08 +01:00
}
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Error creating audio source. " , audioName . c_str ( ) ) ;
audio - > drop ( ) ;
2009-12-07 23:25:08 +01:00
return NULL ;
}
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder. " , audioName . c_str ( ) , ext . c_str ( ) ) ;
decoder - > drop ( ) ;
2009-12-07 23:25:08 +01:00
return NULL ;
}
2010-02-13 06:48:19 +01:00
if ( source )
source - > drop ( ) ;
2009-12-07 23:25:08 +01:00
}
}
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): File could not be found (.%s). " , audioName . c_str ( ) , path . c_str ( ) ) ;
return NULL ;
2009-12-07 23:25:08 +01:00
}
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): No decoder could be found for (.%s). " , audioName . c_str ( ) , ext . c_str ( ) ) ;
2009-12-07 23:25:08 +01:00
return NULL ;
2009-06-21 05:24:30 +02:00
}
2010-02-10 22:57:09 +01:00
IAudioSource * cAudioManager : : createFromMemory ( const char * name , const char * data , size_t length , const char * extension )
2009-06-21 05:24:30 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-12-01 02:41:15 +01:00
2010-03-14 23:58:03 +01:00
cAudioString audioName = safeCStr ( name ) ;
cAudioString ext = safeCStr ( extension ) ;
2009-12-07 23:25:08 +01:00
IAudioDecoderFactory * factory = getAudioDecoderFactory ( ext . c_str ( ) ) ;
if ( factory )
{
2010-03-08 05:56:56 +01:00
cMemorySource * source = CAUDIO_NEW cMemorySource ( data , length , true ) ;
2009-12-07 23:25:08 +01:00
if ( source )
{
if ( source - > isValid ( ) )
{
IAudioDecoder * decoder = factory - > CreateAudioDecoder ( source ) ;
source - > drop ( ) ;
if ( decoder )
{
if ( decoder - > isValid ( ) )
{
2010-02-13 03:34:50 +01:00
# ifdef CAUDIO_EFX_ENABLED
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context , initEffects . getEFXInterface ( ) ) ;
2010-02-13 03:34:50 +01:00
# else
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context ) ;
2010-02-13 03:34:50 +01:00
# endif
2009-12-07 23:25:08 +01:00
decoder - > drop ( ) ;
if ( audio )
{
if ( audio - > isValid ( ) )
{
if ( ! audioName . empty ( ) )
audioIndex [ audioName ] = audio ;
audioSources . push_back ( audio ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Source (%s) successfully created from memory. " , audioName . c_str ( ) ) ;
2010-02-13 06:48:19 +01:00
2009-12-07 23:25:08 +01:00
return audio ;
}
audio - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Error creating audio source. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory. " , audioName . c_str ( ) ) ;
return NULL ;
}
decoder - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder. " , audioName . c_str ( ) , ext . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory for decoder. " , audioName . c_str ( ) ) ;
return NULL ;
}
source - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data is corrupt. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Codec (.%s) is not supported. " , audioName . c_str ( ) , ext . c_str ( ) ) ;
return NULL ;
2009-06-21 05:24:30 +02:00
}
2010-02-10 22:57:09 +01:00
IAudioSource * cAudioManager : : createFromRaw ( const char * name , const char * data , size_t length , unsigned int frequency , AudioFormats format )
2009-08-11 19:57:20 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-12-01 02:41:15 +01:00
2010-03-14 23:58:03 +01:00
cAudioString audioName = safeCStr ( name ) ;
2009-12-07 23:25:08 +01:00
IAudioDecoderFactory * factory = getAudioDecoderFactory ( " raw " ) ;
if ( factory )
2010-02-13 06:48:19 +01:00
{
2010-03-08 05:56:56 +01:00
cMemorySource * source = CAUDIO_NEW cMemorySource ( data , length , true ) ;
2009-12-07 23:25:08 +01:00
if ( source )
{
if ( source - > isValid ( ) )
{
IAudioDecoder * decoder = ( ( cRawAudioDecoderFactory * ) factory ) - > CreateAudioDecoder ( source , frequency , format ) ;
source - > drop ( ) ;
if ( decoder )
{
if ( decoder - > isValid ( ) )
{
2010-02-13 03:34:50 +01:00
# ifdef CAUDIO_EFX_ENABLED
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context , initEffects . getEFXInterface ( ) ) ;
2010-02-13 03:34:50 +01:00
# else
2010-03-08 05:56:56 +01:00
IAudioSource * audio = CAUDIO_NEW cAudioSource ( decoder , Context ) ;
2010-02-13 03:34:50 +01:00
# endif
2009-12-07 23:25:08 +01:00
decoder - > drop ( ) ;
if ( audio )
{
if ( audio - > isValid ( ) )
{
if ( ! audioName . empty ( ) )
audioIndex [ audioName ] = audio ;
audioSources . push_back ( audio ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Source (%s) successfully created from raw data. " , audioName . c_str ( ) ) ;
2010-02-13 06:48:19 +01:00
2009-12-07 23:25:08 +01:00
return audio ;
}
audio - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Error creating audio source. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory. " , audioName . c_str ( ) ) ;
return NULL ;
}
decoder - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data could not be decoded by (.%s) decoder. " , audioName . c_str ( ) , " raw " ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory for decoder. " , audioName . c_str ( ) ) ;
return NULL ;
}
source - > drop ( ) ;
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Audio data is corrupt. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Could not allocate enough memory. " , audioName . c_str ( ) ) ;
return NULL ;
}
getLogger ( ) - > logError ( " AudioManager " , " Failed to create Audio Source (%s): Codec (.%s) is not supported. " , audioName . c_str ( ) , " raw " ) ;
return NULL ;
2009-08-11 19:57:20 +02:00
}
2010-02-13 06:48:19 +01:00
bool cAudioManager : : registerAudioDecoder ( IAudioDecoderFactory * factory , const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString ext = safeCStr ( extension ) ;
2010-02-13 06:48:19 +01:00
decodermap [ ext ] = factory ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Decoder for extension .%s registered. " , ext . c_str ( ) ) ;
return true ;
}
2010-02-11 16:29:40 +01:00
2010-02-13 06:48:19 +01:00
void cAudioManager : : unRegisterAudioDecoder ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString ext = safeCStr ( extension ) ;
2010-03-08 05:56:56 +01:00
decodermapIterator it = decodermap . find ( ext ) ;
2010-02-13 06:48:19 +01:00
if ( it ! = decodermap . end ( ) )
2010-02-11 16:29:40 +01:00
{
2010-02-13 06:48:19 +01:00
decodermap . erase ( it ) ;
getLogger ( ) - > logInfo ( " AudioManager " , " Audio Decoder for extension .%s unregistered. " , ext . c_str ( ) ) ;
}
}
2010-02-11 16:29:40 +01:00
2010-02-13 06:48:19 +01:00
bool cAudioManager : : isAudioDecoderRegistered ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString ext = safeCStr ( extension ) ;
2010-03-08 05:56:56 +01:00
decodermapIterator it = decodermap . find ( ext ) ;
2010-02-13 06:48:19 +01:00
return ( it ! = decodermap . end ( ) ) ;
}
2010-02-11 16:29:40 +01:00
2010-02-13 06:48:19 +01:00
IAudioDecoderFactory * cAudioManager : : getAudioDecoderFactory ( const char * extension )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString ext = safeCStr ( extension ) ;
2010-03-08 05:56:56 +01:00
decodermapIterator it = decodermap . find ( ext ) ;
2010-02-13 06:48:19 +01:00
if ( it ! = decodermap . end ( ) )
{
return it - > second ;
2010-02-11 16:29:40 +01:00
}
return NULL ;
}
2010-02-13 06:48:19 +01:00
void cAudioManager : : unRegisterAllAudioDecoders ( )
2010-02-11 16:29:40 +01:00
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-02-13 06:48:19 +01:00
decodermap . clear ( ) ;
}
2010-02-11 16:29:40 +01:00
2010-03-14 23:58:03 +01:00
bool compareDataSourcePriorities ( std : : pair < int , cAudioString > left , std : : pair < int , cAudioString > right )
2010-02-13 06:48:19 +01:00
{
return ( left . first > right . first ) ;
2010-02-11 16:29:40 +01:00
}
2010-02-13 06:48:19 +01:00
bool cAudioManager : : registerDataSource ( IDataSourceFactory * factory , const char * name , int priority )
2010-02-11 16:29:40 +01:00
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString safeName = safeCStr ( name ) ;
2010-02-13 06:48:19 +01:00
datasourcemap [ safeName ] = factory ;
2010-03-14 23:58:03 +01:00
dataSourcePriorityList . push_back ( std : : pair < int , cAudioString > ( priority , safeName ) ) ;
2010-02-13 06:48:19 +01:00
std : : sort ( dataSourcePriorityList . begin ( ) , dataSourcePriorityList . end ( ) , compareDataSourcePriorities ) ;
2010-02-11 16:29:40 +01:00
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logInfo ( " AudioManager " , " Data Source named %s registered (Priority %i). " , safeName . c_str ( ) , priority ) ;
return true ;
2010-02-11 16:29:40 +01:00
}
2010-02-13 06:48:19 +01:00
void cAudioManager : : unRegisterDataSource ( const char * name )
2010-02-11 16:29:40 +01:00
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString safeName = safeCStr ( name ) ;
2010-03-08 05:56:56 +01:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
2010-02-11 16:29:40 +01:00
if ( it ! = datasourcemap . end ( ) )
{
datasourcemap . erase ( it ) ;
2010-02-13 06:48:19 +01:00
getLogger ( ) - > logInfo ( " AudioManager " , " Data Source named %s unregistered. " , safeName . c_str ( ) ) ;
2010-02-11 16:29:40 +01:00
}
2010-02-13 06:48:19 +01:00
for ( int i = 0 ; i < dataSourcePriorityList . size ( ) ; + + i )
{
if ( dataSourcePriorityList [ i ] . second = = safeName )
{
dataSourcePriorityList . erase ( dataSourcePriorityList . begin ( ) + i ) ;
break ;
}
}
std : : sort ( dataSourcePriorityList . begin ( ) , dataSourcePriorityList . end ( ) , compareDataSourcePriorities ) ;
2010-02-11 16:29:40 +01:00
}
2010-02-13 06:48:19 +01:00
bool cAudioManager : : isDataSourceRegistered ( const char * name )
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString safeName = safeCStr ( name ) ;
2010-03-08 05:56:56 +01:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
2010-02-13 06:48:19 +01:00
return ( it ! = datasourcemap . end ( ) ) ;
}
2009-06-21 05:24:30 +02:00
2010-02-13 06:48:19 +01:00
IDataSourceFactory * cAudioManager : : getDataSourceFactory ( const char * name )
2009-08-11 19:57:20 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString safeName = safeCStr ( name ) ;
2010-03-08 05:56:56 +01:00
datasourcemapIterator it = datasourcemap . find ( safeName ) ;
2010-02-13 06:48:19 +01:00
if ( it ! = datasourcemap . end ( ) )
2009-08-11 19:57:20 +02:00
{
2010-02-13 06:48:19 +01:00
return it - > second ;
2009-08-11 19:57:20 +02:00
}
2010-02-13 06:48:19 +01:00
return NULL ;
2009-08-11 19:57:20 +02:00
}
2010-02-13 06:48:19 +01:00
void cAudioManager : : unRegisterAllDataSources ( )
2009-08-11 19:57:20 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2010-02-13 06:48:19 +01:00
datasourcemap . clear ( ) ;
dataSourcePriorityList . clear ( ) ;
2009-08-11 19:57:20 +02:00
}
2010-02-13 05:47:59 +01:00
void cAudioManager : : registerEventHandler ( IManagerEventHandler * handler )
{
if ( handler )
{
eventHandlerList . push_back ( handler ) ;
}
}
void cAudioManager : : unRegisterEventHandler ( IManagerEventHandler * handler )
{
if ( handler )
{
eventHandlerList . remove ( handler ) ;
}
}
void cAudioManager : : unRegisterAllEventHandlers ( )
{
2010-02-15 00:33:10 +01:00
eventHandlerList . clear ( ) ;
2010-02-13 05:47:59 +01:00
}
void cAudioManager : : signalEvent ( Events sevent )
{
2010-02-18 03:22:50 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioList < IManagerEventHandler * > : : Type : : iterator it = eventHandlerList . begin ( ) ;
2010-02-13 05:47:59 +01:00
2010-02-13 06:48:19 +01:00
if ( it ! = eventHandlerList . end ( ) )
{
switch ( sevent )
{
2010-02-13 05:47:59 +01:00
case ON_INIT :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onInit ( ) ;
}
break ;
case ON_UPDATE :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onUpdate ( ) ;
}
break ;
case ON_RELEASE :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onRelease ( ) ;
}
break ;
case ON_SOURCECREATE :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onSourceCreate ( ) ;
}
break ;
case ON_DECODERREGISTER :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onDecoderRegister ( ) ;
}
break ;
case ON_DATASOURCEREGISTER :
2010-02-13 06:48:19 +01:00
for ( it ; it ! = eventHandlerList . end ( ) ; it + + )
{
2010-02-13 05:47:59 +01:00
( * it ) - > onDataSourceRegister ( ) ;
}
break ;
}
}
}
2010-02-10 22:57:09 +01:00
IAudioSource * cAudioManager : : getSoundByName ( const char * name )
2009-06-21 05:24:30 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-14 23:58:03 +01:00
cAudioString audioName = safeCStr ( name ) ;
2010-03-08 05:56:56 +01:00
audioIndexIterator i = audioIndex . find ( audioName ) ;
2009-12-01 02:41:15 +01:00
if ( i = = audioIndex . end ( ) )
2009-08-29 13:24:31 +02:00
{
return NULL ;
}
2009-06-21 05:24:30 +02:00
return i - > second ;
}
2010-02-13 06:48:19 +01:00
void cAudioManager : : releaseAllSources ( )
2009-06-21 05:24:30 +02:00
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-12-01 02:41:15 +01:00
for ( unsigned int i = 0 ; i < audioSources . size ( ) ; + + i )
{
2010-02-10 22:57:09 +01:00
IAudioSource * source = audioSources [ i ] ;
2009-12-01 02:41:15 +01:00
if ( source )
2009-12-07 23:25:08 +01:00
source - > drop ( ) ;
2009-12-01 02:41:15 +01:00
}
audioSources . clear ( ) ;
audioIndex . clear ( ) ;
2009-06-21 05:24:30 +02:00
}
2010-02-10 22:57:09 +01:00
void cAudioManager : : release ( IAudioSource * source )
2010-01-19 05:04:40 +01:00
{
if ( source )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-03-08 05:56:56 +01:00
audioIndexIterator it = audioIndex . begin ( ) ;
2010-01-19 05:04:40 +01:00
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 ] )
{
source - > drop ( ) ;
audioSources . erase ( audioSources . begin ( ) + i ) ;
break ;
}
}
}
}
2009-06-21 05:24:30 +02:00
void cAudioManager : : update ( )
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-12-01 02:41:15 +01:00
for ( unsigned int i = 0 ; i < audioSources . size ( ) ; + + i )
{
2010-02-10 22:57:09 +01:00
IAudioSource * source = audioSources [ i ] ;
2009-12-01 02:41:15 +01:00
if ( source - > isValid ( ) )
2009-06-21 05:24:30 +02:00
{
2009-12-01 02:41:15 +01:00
if ( source - > update ( ) )
2009-06-21 05:24:30 +02:00
{
}
}
}
}
void cAudioManager : : shutDown ( )
{
2009-12-07 23:25:08 +01:00
if ( Initialized )
{
cAudioMutexBasicLock lock ( Mutex ) ;
2010-02-13 06:48:19 +01:00
releaseAllSources ( ) ;
2009-12-07 23:25:08 +01:00
//Reset context to null
alcMakeContextCurrent ( NULL ) ;
//Delete the context
alcDestroyContext ( Context ) ;
Context = NULL ;
//Close the device
alcCloseDevice ( Device ) ;
Device = NULL ;
Initialized = false ;
getLogger ( ) - > logInfo ( " AudioManager " , " Manager successfully shutdown. " ) ;
}
2009-06-21 05:24:30 +02:00
}
2010-01-11 01:39:08 +01:00
bool cAudioManager : : checkError ( )
2009-11-20 04:39:56 +01:00
{
int error = alGetError ( ) ;
const char * errorString ;
if ( error ! = AL_NO_ERROR )
{
errorString = alGetString ( error ) ;
getLogger ( ) - > logError ( " AudioManager " , " OpenAL Error: %s. " , errorString ) ;
2010-01-11 01:39:08 +01:00
return true ;
2009-11-20 04:39:56 +01:00
}
if ( Device )
{
error = alcGetError ( Device ) ;
if ( error ! = AL_NO_ERROR )
{
errorString = alGetString ( error ) ;
getLogger ( ) - > logError ( " AudioManager " , " OpenAL Error: %s. " , errorString ) ;
2010-01-11 01:39:08 +01:00
return true ;
2009-11-20 04:39:56 +01:00
}
}
2010-01-11 01:39:08 +01:00
return false ;
2009-11-20 04:39:56 +01:00
}
void cAudioManager : : getAvailableDevices ( )
{
// Get list of available Playback Devices
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-11-20 04:39:56 +01:00
if ( alcIsExtensionPresent ( NULL , " ALC_ENUMERATE_ALL_EXT " ) = = AL_TRUE )
{
const char * deviceList = alcGetString ( NULL , ALC_ALL_DEVICES_SPECIFIER ) ;
if ( deviceList )
{
while ( * deviceList )
{
2010-03-14 23:58:03 +01:00
cAudioString device ( deviceList ) ;
2009-11-20 04:39:56 +01:00
AvailableDevices . push_back ( device ) ;
deviceList + = strlen ( deviceList ) + 1 ;
}
}
// Get the name of the 'default' capture device
DefaultDevice = alcGetString ( NULL , ALC_DEFAULT_ALL_DEVICES_SPECIFIER ) ;
}
else if ( alcIsExtensionPresent ( NULL , " ALC_ENUMERATION_EXT " ) = = AL_TRUE )
{
const char * deviceList = alcGetString ( NULL , ALC_DEVICE_SPECIFIER ) ;
if ( deviceList )
{
while ( * deviceList )
{
2010-03-14 23:58:03 +01:00
cAudioString device ( deviceList ) ;
2009-11-20 04:39:56 +01:00
AvailableDevices . push_back ( device ) ;
deviceList + = strlen ( deviceList ) + 1 ;
}
}
// Get the name of the 'default' capture device
DefaultDevice = alcGetString ( NULL , ALC_DEFAULT_DEVICE_SPECIFIER ) ;
}
}
2009-06-21 05:24:30 +02:00
2009-11-20 04:39:56 +01:00
const char * cAudioManager : : getAvailableDeviceName ( unsigned int index )
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
2009-11-20 04:39:56 +01:00
if ( ! AvailableDevices . empty ( ) )
{
//Bounds check
if ( index > ( AvailableDevices . size ( ) - 1 ) ) index = ( AvailableDevices . size ( ) - 1 ) ;
const char * deviceName = AvailableDevices [ index ] . c_str ( ) ;
return deviceName ;
}
return " " ;
}
unsigned int cAudioManager : : getAvailableDeviceCount ( )
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
return AvailableDevices . size ( ) ;
2009-11-20 04:39:56 +01:00
}
const char * cAudioManager : : getDefaultDeviceName ( )
{
2009-12-07 23:25:08 +01:00
cAudioMutexBasicLock lock ( Mutex ) ;
return DefaultDevice . empty ( ) ? " " : DefaultDevice . c_str ( ) ;
2009-11-20 04:39:56 +01:00
}
CAUDIO_API IAudioManager * createAudioManager ( bool initializeDefault )
{
2010-03-08 05:56:56 +01:00
cAudioManager * manager = CAUDIO_NEW cAudioManager ;
2009-11-20 04:39:56 +01:00
if ( manager )
{
if ( initializeDefault )
manager - > initialize ( ) ;
manager - > getAvailableDevices ( ) ;
2010-02-20 04:19:59 +01:00
# ifdef CAUDIO_COMPILE_WITH_OGG_DECODER
manager - > registerAudioDecoder ( & OggDecoderFactory , " ogg " ) ;
# endif
# ifdef CAUDIO_COMPILE_WITH_WAV_DECODER
manager - > registerAudioDecoder ( & WavDecoderFactory , " wav " ) ;
# endif
manager - > registerAudioDecoder ( & RawDecoderFactory , " raw " ) ;
2010-03-05 02:52:25 +01:00
# ifdef CAUDIO_COMPILE_WITH_FILE_SOURCE
2010-02-20 04:19:59 +01:00
manager - > registerDataSource ( & FileSourceFactory , " FileSystem " , 0 ) ;
2010-03-05 02:52:25 +01:00
# endif
2010-02-20 04:19:59 +01:00
2010-02-28 00:58:18 +01:00
# ifdef CAUDIO_COMPILE_WITH_PLUGIN_SUPPORT
2010-03-14 23:58:03 +01:00
cAudioVector < IAudioPlugin * > : : Type plugins = cPluginManager : : Instance ( ) - > getPluginList ( ) ;
2010-02-09 06:58:27 +01:00
for ( unsigned int i = 0 ; i < plugins . size ( ) ; + + i )
{
plugins [ i ] - > onCreateAudioManager ( manager ) ;
}
2010-02-28 00:58:18 +01:00
# endif
2010-02-09 06:58:27 +01:00
2009-11-20 04:39:56 +01:00
# ifdef CAUDIO_USE_INTERNAL_THREAD
AudioManagerObjectsMutex . lock ( ) ;
AudioManagerObjects . insert ( manager ) ;
//First time launch of thread
if ( ! RunAudioManagerThread & & AudioManagerObjects . size ( ) > 0 )
RunAudioManagerThread = ( cAudioThread : : SpawnThread ( AudioManagerUpdateThread , NULL ) = = 0 ) ;
AudioManagerObjectsMutex . unlock ( ) ;
# endif
}
return manager ;
}
CAUDIO_API void destroyAudioManager ( IAudioManager * manager )
{
if ( manager )
{
# ifdef CAUDIO_USE_INTERNAL_THREAD
AudioManagerObjectsMutex . lock ( ) ;
AudioManagerObjects . erase ( manager ) ;
//Kill the thread if there are no objects to process anymore
if ( RunAudioManagerThread & & AudioManagerObjects . empty ( ) )
RunAudioManagerThread = false ;
AudioManagerObjectsMutex . unlock ( ) ;
# endif
2010-02-28 00:58:18 +01:00
# ifdef CAUDIO_COMPILE_WITH_PLUGIN_SUPPORT
2010-03-14 23:58:03 +01:00
cAudioVector < IAudioPlugin * > : : Type plugins = cPluginManager : : Instance ( ) - > getPluginList ( ) ;
2010-02-09 06:58:27 +01:00
for ( unsigned int i = 0 ; i < plugins . size ( ) ; + + i )
{
plugins [ i ] - > onDestroyAudioManager ( manager ) ;
}
2010-02-28 00:58:18 +01:00
# endif
2010-02-20 04:19:59 +01:00
manager - > unRegisterAllAudioDecoders ( ) ;
manager - > unRegisterAllDataSources ( ) ;
manager - > unRegisterAllEventHandlers ( ) ;
2010-02-10 05:46:00 +01:00
manager - > shutDown ( ) ;
2010-02-09 06:58:27 +01:00
2010-03-08 05:56:56 +01:00
CAUDIO_DELETE manager ;
2009-11-20 04:39:56 +01:00
manager = NULL ;
}
}
CAUDIO_API bool isAudioManagerThreadRunning ( )
{
return RunAudioManagerThread ;
}
2009-06-21 05:24:30 +02:00
2009-11-20 04:39:56 +01:00
} ;