Something went wrong on our end
-
Dipl.-Ing. Jonas Stienen authoredDipl.-Ing. Jonas Stienen authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
impl.cpp 146.76 KiB
/*
* --------------------------------------------------------------------------------------------
*
* VVV VVV A Virtual Acoustics (VA) | http://www.virtualacoustics.org
* VVV VVV AAA Licensed under the Apache License, Version 2.0
* VVV VVV AAA
* VVV VVV AAA Copyright 2015-2018
* VVVVVV AAA Institute of Technical Acoustics (ITA)
* VVVV AAA RWTH Aachen University
*
* --------------------------------------------------------------------------------------------
*/
#include "impl.h"
IVAInterface* VACore::CreateCoreInstance( const CVAStruct& oArgs, std::ostream* pOutputStream )
{
VA_TRACE( "Config", oArgs );
return new CVACoreImpl( oArgs, pOutputStream );
}
void VACore::StoreCoreConfigToFile( const CVAStruct& oConfig, const std::string& sConfigFilePath )
{
StoreStructToINIFile( sConfigFilePath, oConfig );
}
CVAStruct VACore::LoadCoreConfigFromFile( const std::string& sConfigFilePath )
{
CVAStruct oFinalCoreConfigStruct, oCurrentConfig;
VistaFileSystemFile oConfigFile( sConfigFilePath );
std::list< VistaFileSystemFile > voConfigFiles;
std::vector< VistaFileSystemDirectory > voIncludePaths;
if( oConfigFile.Exists() && oConfigFile.GetParentDirectory().empty() == false )
voIncludePaths.push_back( oConfigFile.GetParentDirectory() );
voConfigFiles.push_back( VistaFileSystemFile( sConfigFilePath ) );
VA_INFO( "Core", "Working directory: '" << VistaFileSystemDirectory::GetCurrentWorkingDirectory() << "'" );
while( voConfigFiles.empty() == false )
{
VistaFileSystemFile oCurrentConfigFile( voConfigFiles.front() );
voConfigFiles.pop_front();
if( oCurrentConfigFile.Exists() == false )
{
for( size_t n = 0; n < voIncludePaths.size(); n++ )
{
std::string sCombinedFilePath = voIncludePaths[ n ].GetName() + PATH_SEPARATOR + oCurrentConfigFile.GetLocalName();
oCurrentConfigFile.SetName( sCombinedFilePath );
if( oCurrentConfigFile.Exists() && oCurrentConfigFile.IsFile() )
{
VA_INFO( "Config", "Including further configuration file '" + oCurrentConfigFile.GetLocalName() +
"' from include path '" + voIncludePaths[ n ].GetName() + "'" );
break;
}
}
if( !oCurrentConfigFile.Exists() )
{
VA_EXCEPT2( FILE_NOT_FOUND, "Configuration file '" + oCurrentConfigFile.GetLocalName() + "' not found, aborting." );
}
}
VA_VERBOSE( "Config", std::string( "Reading INI file '" ) + oCurrentConfigFile.GetLocalName() + "'" );
LoadStructFromINIFIle( oCurrentConfigFile.GetName(), oCurrentConfig );
if( oCurrentConfig.HasKey( "paths" ) )
{
const CVAStruct& oPaths( oCurrentConfig[ "paths" ] );
CVAStruct::const_iterator it = oPaths.Begin();
while( it != oPaths.End() )
{
const CVAStructValue& oIncludePath( ( it++ )->second );
VistaFileSystemDirectory oNewPathDir( oIncludePath );
if( oNewPathDir.Exists() && oNewPathDir.IsDirectory() )
voIncludePaths.push_back( oNewPathDir );
}
}
if( oCurrentConfig.HasKey( "files" ) )
{
const CVAStruct& oPaths( oCurrentConfig[ "files" ] );
CVAStruct::const_iterator it = oPaths.Begin();
while( it != oPaths.End() )
{
const CVAStructValue& oIncludeFile( ( it++ )->second );
voConfigFiles.push_back( VistaFileSystemFile( oIncludeFile ) );
}
}
oCurrentConfig.RemoveKey( "files" );
// Merge structs (check for uniqueness)
oFinalCoreConfigStruct.Merge( oCurrentConfig, true );
}
return oFinalCoreConfigStruct;
}
#ifdef WIN32
// Trick um DLL-Pfad zu ermitteln
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#endif
std::string VACore::GetCoreLibFilePath()
{
#ifdef WIN32
CHAR pszPath[ MAX_PATH + 1 ] = { 0 };
GetModuleFileNameA( ( HINSTANCE ) &__ImageBase, pszPath, _countof( pszPath ) );
return std::string( pszPath );
#else
VA_EXCEPT2( NOT_IMPLEMENTED, "This function is not implemented for your platform. Sorry." );
return "";
#endif // WIN32
}
CVACoreImpl::CVACoreImpl( const CVAStruct& oArgs, std::ostream* pOutputStream )
: m_pAudioDriverBackend( nullptr )
, m_pGlobalSamplePool( nullptr )
, m_pGlobalSampler( nullptr )
, m_pSignalSourceManager( nullptr )
, m_pDirectivityManager( nullptr )
, m_pSceneManager( nullptr )
, m_pNewSceneState( nullptr )
, m_iCurActiveSoundReceiver( -1 )
, m_iNewActiveSoundReceiver( -1 )
, m_iUpdActiveSoundReceiver( -1 )
, m_pEventManager( nullptr )
, m_pCoreThread( nullptr )
, m_pInputAmp( nullptr )
, m_pR2RPatchbay( nullptr )
, m_pOutputPatchbay( nullptr )
, m_pInputStreamDetector( nullptr )
, m_pOutputStreamDetector( nullptr )
, m_pOutputTracker( nullptr )
, m_pStreamProbeDeviceInput( nullptr )
, m_pStreamProbeDeviceOutput( nullptr )
, m_pCurSceneState( nullptr )
, m_pClock( ITAClock::getDefaultClock() )
, m_pTicker( NULL )
, m_lSyncModOwner( -1 )
, m_lSyncModSpinCount( 0 )
, m_iState( VA_CORESTATE_CREATED )
, m_iGlobalAuralizationMode( IVAInterface::VA_AURAMODE_ALL )
, m_dOutputGain( 1 )
, m_dInputGain( 1 )
, m_bOutputMuted( false )
, m_bInputMuted( false )
, m_dStreamClockOffset( 0 )
, m_fCoreClockOffset( 0 )
, m_oCoreThreadLoopTotalDuration( "Core thread loop" )
{
VA_NO_REENTRANCE;
if( pOutputStream )
SetOutputStream( pOutputStream );
VA_TRY
{
// read configuration
m_oCoreConfig.Init( oArgs );
// register core itself as a module
SetObjectName( "VACore" );
m_oModules.RegisterObject( this );
VA_VERBOSE( "Core", "Registered core module with name '" << GetObjectName() << "'" );
// Der Event-Manager muss immer verfgbar sein,
// unabhnging davon ob der Core initialisiert wurde oder nicht.
m_pEventManager = new CVACoreEventManager;
m_iState = VA_CORESTATE_CREATED;
VA_TRACE( "Core", "CVACoreImpl instance created [" << this << "]" );
}
VA_RETHROW;
}
CVACoreImpl::~CVACoreImpl()
{
VA_NO_REENTRANCE;
// Implizit finalisieren, falls dies nicht durch den Benutzer geschah
if( m_iState == VA_CORESTATE_READY )
{
VA_TRY
{
Finalize();
}
VA_FINALLY
{
// Fehler beim Finalisieren ignorieren
};
}
// Nachricht senden [blocking], das die Kerninstanz gelscht wird.
CVAEvent ev;
ev.iEventType = CVAEvent::DESTROY;
ev.pSender = this;
m_pEventManager->BroadcastEvent( ev );
// Module deregistrieren
m_oModules.Clear();
// Nachrichten-Manager freigeben
VA_TRY
{
delete m_pEventManager;
}
VA_RETHROW;
VA_TRACE( "Core", "CVACoreImpl instance deleted [" << this << "]" );
// Profiling ausgeben
VA_VERBOSE( "Core", m_oCoreThreadLoopTotalDuration.ToString() );
}
void CVACoreImpl::SetOutputStream( std::ostream* posDebug )
{
VALog_setOutputStream( posDebug );
VALog_setErrorStream( posDebug );
}
void CVACoreImpl::GetVersionInfo( CVAVersionInfo* pVersionInfo ) const
{
if( !pVersionInfo )
return;
std::stringstream ss;
ss << VACORE_VERSION_MAJOR << "." << VACORE_VERSION_MINOR;
pVersionInfo->sVersion = ss.str();
ss.clear();
#ifdef VACORE_CMAKE_DATE
ss << VACORE_CMAKE_DATE;
#else
ss << "Unkown date";
#endif
pVersionInfo->sDate = ss.str();
pVersionInfo->sFlags = "";
#ifdef DEBUG
pVersionInfo->sComments = "debug";
#else
pVersionInfo->sComments = "release";
#endif
}
void CVACoreImpl::AttachEventHandler( IVAEventHandler* pCoreEventHandler )
{
VA_TRY
{
// Immer mglich. Unabhngig vom Zustand. Thread-safety wird im Manager geregelt.
m_pEventManager->AttachHandler( pCoreEventHandler );
}
VA_RETHROW;
}
void CVACoreImpl::DetachEventHandler( IVAEventHandler* pCoreEventHandler )
{
VA_TRY
{
// Immer mglich. Unabhngig vom Zustand. Thread-safety wird im Manager geregelt.
m_pEventManager->DetachHandler( pCoreEventHandler );
}
VA_RETHROW;
}
int CVACoreImpl::GetState() const
{
VA_VERBOSE( "Core", "Core state requested, current state is " << m_iState );
return m_iState;
}
void CVACoreImpl::Reset()
{
VA_CHECK_INITIALIZED;
// Wait for core thread
while( !m_pCoreThread->TryBreak() )
VASleep( 20 );
VA_NO_REENTRANCE;
if( GetUpdateLocked() )
{
VA_WARN( "Core", "Encountered locked scene during reset. Please unlock before resetting, skipping." );
m_pCoreThread->Continue();
}
VA_TRY
{
VA_INFO( "Core", "Resetting core" );
// Reset audio renderers
std::vector< CVAAudioRendererDesc >::iterator it = m_voRenderers.begin();
while( it != m_voRenderers.end() )
{
CVAAudioRendererDesc& oRend( *it++ );
oRend.pInstance->Reset();
}
if( m_pCurSceneState )
{
// Referenz entfernen welche in CoreThreadLoop hinzugefgt wurde
m_pCurSceneState->RemoveReference();
m_pCurSceneState = nullptr;
}
// Alle Szenenobjekte lschen
m_pSceneManager->Reset();
m_pSignalSourceManager->Reset();
m_pDirectivityManager->Reset();
// TODO: Check if the pool and sampler must really be recreated
/*
delete m_pGlobalSamplePool;
m_pGlobalSamplePool = nullptr;
m_pGlobalSamplePool = ITASoundSamplePool::Create(1, m_oCoreConfig.oAudioDriverConfig.dSamplerate);
// This causes a crash in patch bay
delete m_pGlobalSampler;
m_pGlobalSampler = nullptr;
m_pGlobalSampler = ITASoundSampler::Create(1, m_oCoreConfig.oAudioDriverConfig.dSamplerate, m_oCoreConfig.oAudioDriverConfig.iBuffersize, m_pGlobalSamplePool);
m_pGlobalSampler->AddMonoTrack();
*/
//m_pGlobalSampler->RemoveAllPlaybacks();
// Werte neusetzen
m_pCurSceneState = m_pSceneManager->GetHeadSceneState();
m_iCurActiveSoundReceiver = -1;
m_iNewActiveSoundReceiver = -1;
m_pCoreThread;
// Core-Thread fortsetzen
m_pCoreThread->Continue();
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::RESET;
ev.pSender = this;
m_pEventManager->BroadcastEvent( ev );
}
VA_FINALLY
{
Tidyup();
throw;
}
}
void CVACoreImpl::Tidyup() {
/*
* Hinweis: Diese Hilfsmethode wird nur innerhalb des Reentrance-Locks
* aufgerufen - daher keine weiter Absicherung ntig.
*/
VA_TRY
{
if( m_pTicker )
{
m_pTicker->StopTicker();
m_pTicker->SetAfterPulseFunctor( NULL );
}
FinalizeAudioDriver();
FinalizeRenderingModules();
FinalizeReproductionModules();
delete m_pTicker;
m_pTicker = nullptr;
delete m_pCoreThread;
m_pCoreThread = nullptr;
delete m_pInputAmp;
m_pInputAmp = nullptr;
delete m_pInputStreamDetector;
m_pInputStreamDetector = nullptr;
delete m_pR2RPatchbay;
m_pR2RPatchbay = nullptr;
delete m_pOutputPatchbay;
m_pOutputPatchbay = nullptr;
delete m_pOutputStreamDetector;
m_pOutputStreamDetector = nullptr;
delete m_pOutputTracker;
m_pOutputTracker = nullptr;
delete m_pStreamProbeDeviceInput;
m_pStreamProbeDeviceInput = nullptr;
delete m_pStreamProbeDeviceOutput;
m_pStreamProbeDeviceOutput = nullptr;
delete m_pSignalSourceManager;
m_pSignalSourceManager = nullptr;
delete m_pGlobalSampler;
m_pGlobalSampler = nullptr;
delete m_pGlobalSamplePool;
m_pGlobalSamplePool = nullptr;
if( m_pDirectivityManager )
m_pDirectivityManager->Finalize();
delete m_pDirectivityManager;
m_pDirectivityManager = nullptr;
if( m_pSceneManager )
m_pSceneManager->Finalize();
delete m_pSceneManager;
m_pSceneManager = nullptr;
m_iState = VA_CORESTATE_CREATED;
}
VA_FINALLY
{
m_iState = VA_CORESTATE_FAIL;
}
}
void CVACoreImpl::Finalize()
{
VA_NO_REENTRANCE;
//VA_TRACE("Core", __FUNCTION__ << " entry");
VA_INFO( "Core", "Finalizing core" );
VA_TRY
{
// Mehrfaches Finialisieren fhrt nicht zu Fehlern
if( m_iState == VA_CORESTATE_CREATED )
return;
if( m_iState == VA_CORESTATE_FAIL )
VA_EXCEPT2( MODAL_ERROR, "Core corrupted, finalization impossible" );
// Core-Thread anhalten (wenn frei ist)
while( !m_pCoreThread->TryBreak() )
VASleep( 10 );
//m_pCoreThread->Break(); << deadlock
// Alle Filterketten lschen und warten bis Zustand sicher bernommen
// Wichtig: Dies muss vor dem Beenden des Streamings geschehen
// Reset audio renderers
for( std::vector<CVAAudioRendererDesc>::iterator it = m_voRenderers.begin(); it != m_voRenderers.end(); ++it )
it->pInstance->Reset();
// Peak-Nachrichten stoppen
m_pTicker->StopTicker();
// Audio-Streaming beenden
m_pAudioDriverBackend->stopStreaming();
InitProgress( "Stopping auralization threads", "", 2 );
// Stop and delete ticker
m_pTicker->SetAfterPulseFunctor( NULL );
delete m_pTicker;
m_pTicker = NULL;
// Hauptthread beenden und freigeben
delete m_pCoreThread;
m_pCoreThread = nullptr;
SetProgress( "Releasing audio hardware", "", 1 );
FinalizeAudioDriver();
FinalizeRenderingModules();
FinalizeReproductionModules();
SetProgress( "Cleaning up resources", "", 2 );
delete m_pInputAmp;
m_pInputAmp = nullptr;
if( m_pInputStreamDetector )
if( m_pInputStreamDetector->GetProfilerEnabled() )
VA_VERBOSE( "Core", "Input stream detector profiler: " << m_pInputStreamDetector->GetProfilerResult() );
delete m_pInputStreamDetector;
m_pInputStreamDetector = nullptr;
m_voReproductionModules.clear();
delete m_pR2RPatchbay;
m_pR2RPatchbay = nullptr;
delete m_pOutputPatchbay;
m_pOutputPatchbay = nullptr;
if( m_pOutputStreamDetector->GetProfilerEnabled() )
VA_VERBOSE( "Core", "Output stream detector profiler: " << m_pOutputStreamDetector->GetProfilerResult() );
delete m_pOutputStreamDetector;
m_pOutputStreamDetector = nullptr;
delete m_pOutputTracker;
m_pOutputTracker = nullptr;
delete m_pStreamProbeDeviceInput;
m_pStreamProbeDeviceInput = nullptr;
delete m_pStreamProbeDeviceOutput;
m_pStreamProbeDeviceOutput = nullptr;
delete m_pSignalSourceManager;
m_pSignalSourceManager = nullptr;
delete m_pGlobalSampler;
m_pGlobalSampler = nullptr;
delete m_pGlobalSamplePool;
m_pGlobalSamplePool = nullptr;
m_pDirectivityManager->Finalize();
delete m_pDirectivityManager;
m_pDirectivityManager = nullptr;
m_pSceneManager->Finalize();
delete m_pSceneManager;
m_pSceneManager = nullptr;
// Finalisierung erfolgreich. Nun wieder im Grundzustand!
m_iState = VA_CORESTATE_CREATED;
FinishProgress();
}
VA_FINALLY
{
// Nochmals versuchen aufzurumen
Tidyup();
// Allgemein: Fehler beim Finalisieren? => Core im Sack
m_iState = VA_CORESTATE_FAIL;
// VAExceptions unverndert nach aussen leiten
throw;
}
}
void CVACoreImpl::RegisterModule( CVAObject* pModule )
{
m_oModules.RegisterObject( pModule );
}
void CVACoreImpl::GetModules( std::vector< CVAModuleInfo >& viModuleInfos ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
#ifdef VACORE_MODULE_INTERFACE_ENABLED
VA_TRY
{
std::vector<CVAObjectInfo> v;
m_oModules.GetObjectInfos( v );
VA_PRINT( "Available modules (" << v.size() << ")" );
viModuleInfos.clear();
viModuleInfos.resize( v.size() );
for( size_t i = 0; i < v.size(); i++ )
{
VA_PRINT( "'" << v[ i ].sName << "'\t\t\t" << v[ i ].sDesc );
viModuleInfos[ i ].sName = v[ i ].sName;
viModuleInfos[ i ].sDesc = v[ i ].sDesc;
}
}
VA_RETHROW;
#else // VACORE_MODULE_INTERFACE_ENABLED
VA_EXCEPT1( "This VACore version does not provide modules" );
#endif // VACORE_MODULE_INTERFACE_ENABLED
}
CVAStruct CVACoreImpl::CallModule( const std::string& sModuleName, const CVAStruct& oArgs )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
#ifdef VACORE_MODULE_INTERFACE_ENABLED
VA_TRY
{
CVAObject* pModule = m_oModules.FindObjectByName( sModuleName );
if( !pModule )
{
VA_EXCEPT2( INVALID_PARAMETER, "Module '" + sModuleName + "' not found" );
}
#ifdef VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
ev.pSender = this;
ev.sObjectID = sModuleName;
ev;
m_pEventManager->BroadcastEvent( ev );
m_pEventManager->
#else // not VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
return pModule->CallObject( oArgs );
#endif // VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
}
VA_RETHROW;
#else // VACORE_MODULE_INTERFACE_ENABLED
#ifdef VACORE_NO_MODULE_INTERFACE_THROW_EXCEPTION
VA_EXCEPT1( "This VACore version does not provide modules" );
#endif // VACORE_NO_MODULE_INTERFACE_THROW_EXCEPTION
#endif // VACORE_MODULE_INTERFACE_ENABLED
}
CVAStruct CVACoreImpl::GetSearchPaths() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
CVAStruct oSearchPaths;
for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
oSearchPaths[ "path_" + std::to_string( long( i ) ) ] = m_oCoreConfig.vsSearchPaths[ i ];
return oSearchPaths;
}
CVAStruct CVACoreImpl::GetCoreConfiguration( const bool bFilterEnabled ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
CVAStruct oCoreConfig;
if( bFilterEnabled )
{
CVAStruct::const_iterator cit = m_oCoreConfig.GetStruct().Begin();
while( cit != m_oCoreConfig.GetStruct().End() )
{
const std::string sKey( cit->first );
const CVAStructValue& oVal( cit->second );
++cit;
if( oVal.IsStruct() )
{
const CVAStruct& oSection( oVal.GetStruct() );
if( oSection.HasKey( "enabled" ) )
if( bool( oSection[ "enabled" ] ) == false )
continue; // Only skip if explicitly not enabled
oCoreConfig[ sKey ] = oVal;
}
}
}
else
{
oCoreConfig = m_oCoreConfig.GetStruct();
}
return oCoreConfig;
}
CVAStruct CVACoreImpl::GetHardwareConfiguration() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_oCoreConfig.oHardwareSetup.GetStruct();
}
CVAStruct CVACoreImpl::GetFileList( const bool bRecursive, const std::string& sFileSuffixFilter ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
CVAStruct oFileList;
for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
{
if( bRecursive )
{
RecursiveFileList( m_oCoreConfig.vsSearchPaths[ i ], oFileList, sFileSuffixFilter );
}
else
{
std::vector< std::string > vsFileList;
FileList( m_oCoreConfig.vsSearchPaths[ i ], vsFileList, sFileSuffixFilter );
CVAStruct oMoreFiles;
for( size_t j = 0; j < vsFileList.size(); j++ )
oMoreFiles[ std::to_string( long( j ) ) ] = vsFileList[ j ];
oFileList[ m_oCoreConfig.vsSearchPaths[ i ] ] = oMoreFiles;
}
}
return oFileList;
}
int CVACoreImpl::CreateDirectivityFromParameters( const CVAStruct& oParams, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
int iDirID = m_pDirectivityManager->CreateDirectivity( oParams, sName );
assert( iDirID != -1 );
CVAEvent ev;
ev.iEventType = CVAEvent::DIRECTIVITY_LOADED;
ev.pSender = this;
ev.iObjectID = iDirID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Directivity successfully created, assigned identifier " << iDirID );
return iDirID;
}
VA_RETHROW;
}
bool CVACoreImpl::DeleteDirectivity( const int iDirID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSuccess = m_pDirectivityManager->DeleteDirectivity( iDirID );
//assert( bSuccess );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::DIRECTIVITY_DELETED;
ev.pSender = this;
ev.iObjectID = iDirID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "FreeDirectivity successful, freed directivity " << iDirID );
return bSuccess;
} VA_RETHROW;
}
CVADirectivityInfo CVACoreImpl::GetDirectivityInfo( int iDirID ) const {
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY{
return m_pDirectivityManager->GetDirectivityInfo( iDirID );
} VA_RETHROW;
}
void CVACoreImpl::GetDirectivityInfos( std::vector<CVADirectivityInfo>& vdiDest ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pDirectivityManager->GetDirectivityInfos( vdiDest );
}
VA_RETHROW;
}
void CVACoreImpl::SetDirectivityName( const int iID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
//m_pDirectivityManager->SetName( iID, sName );
}
VA_RETHROW;
}
std::string CVACoreImpl::GetDirectivityName( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVADirectivityInfo oInfo = m_pDirectivityManager->GetDirectivityInfo( iID );
return oInfo.sName;
}
VA_RETHROW;
}
void CVACoreImpl::SetDirectivityParameters( const int iID, const CVAStruct& oParams )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
//m_pDirectivityManager->SetParameters( iID, oParams );
}
VA_RETHROW;
}
CVAStruct CVACoreImpl::GetDirectivityParameters( const int iID, const CVAStruct& ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVADirectivityInfo oInfo = m_pDirectivityManager->GetDirectivityInfo( iID );
return oInfo.oParams;
// @todo
//return m_pDirectivityManager->GetDirectivityParameters( iID, oParams );
}
VA_RETHROW;
}
int CVACoreImpl::CreateAcousticMaterial( const CVAAcousticMaterial& oMaterial, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::CreateAcousticMaterialFromParameters( const CVAStruct& oParams, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
bool CVACoreImpl::DeleteAcousticMaterial( const int iID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
CVAAcousticMaterial CVACoreImpl::GetAcousticMaterialInfo( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::GetAcousticMaterialInfos( std::vector< CVAAcousticMaterial >& voDest ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetAcousticMaterialName( const int iID, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
std::string CVACoreImpl::GetAcousticMaterialName( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetAcousticMaterialParameters( const int iID, const CVAStruct& oParams )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
CVAStruct CVACoreImpl::GetAcousticMaterialParameters( const int iID, const CVAStruct& oParams ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::CreateGeometryMesh( const CVAGeometryMesh& oMesh, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::CreateGeometryMeshFromParameters( const CVAStruct& oParams, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
bool CVACoreImpl::DeleteGeometryMesh( const int iID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
CVAGeometryMesh CVACoreImpl::GetGeometryMesh( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::GetGeometryMeshIDs( std::vector< int >& viIDs ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetGeometryMeshName( const int iID, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
std::string CVACoreImpl::GetGeometryMeshName( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetGeometryMeshParameters( const int iID, const CVAStruct& oParams )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
CVAStruct CVACoreImpl::GetGeometryMeshParameters( const int iID, const CVAStruct& oParams ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetGeometryMeshEnabled( const int iID, const bool bEnabled )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
bool CVACoreImpl::GetGeometryMeshEnabled( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
std::string CVACoreImpl::CreateSignalSourceBufferFromParameters( const CVAStruct& oParams, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( oParams.HasKey( "filepath" ) )
{
const std::string sFilePath = oParams[ "filepath" ];
const std::string sDestFilePath = FindFilePath( sFilePath );
if( sDestFilePath.empty() )
VA_EXCEPT2( INVALID_PARAMETER, "Looked everywhere, but could not find file '" + sFilePath + "'" );
std::string sID = m_pSignalSourceManager->CreateAudiofileSignalSource( sDestFilePath, sName );
assert( !sID.empty() );
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Created audiofile signal source (ID=" << sID << ", Name=\"" << sName << "\", Filename=\"" << sDestFilePath << "\")" );
return sID;
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret parameter arguments to create a buffer signal source" );
}
}
VA_RETHROW;
}
std::string CVACoreImpl::CreateSignalSourceTextToSpeech( const std::string& sName /*= "" */ )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
std::string sID = m_pSignalSourceManager->CreateTextToSpeechSignalSource( sName );
assert( !sID.empty() );
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Created text-to-speech signal source ( ID=" << sID << ", Name=\"" << sName << "\" )" );
return sID;
}
VA_RETHROW;
}
std::string CVACoreImpl::CreateSignalSourceSequencer( const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
std::string sID = m_pSignalSourceManager->CreateSequencerSignalSource( sName );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Created sequencer signal source (ID=" << sID << ", Name=\"" << sName << "\")" );
return sID;
}
VA_RETHROW;
}
std::string CVACoreImpl::CreateSignalSourceNetworkStream( const std::string& sInterface, const int iPort, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_TRACE( "Core", "Attempting to connect to a netstream signal source on " << sInterface << " with port " << iPort );
std::string sID = m_pSignalSourceManager->CreateNetstreamSignalSource( sInterface, iPort, sName );
assert( !sID.empty() );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Created network stream signal source (ID=" << sID << ", Name='" << sName << "', Interface=" << sInterface << ":" << iPort << ")" );
return sID;
}
VA_RETHROW;
}
std::string CVACoreImpl::CreateSignalSourceEngine( const CVAStruct&, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
std::string sID = m_pSignalSourceManager->CreateEngineSignalSource( sName );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Created engine signal source (ID=" << sID << ", Name=\"" << sName << "\")" );
return sID;
}
VA_RETHROW;
}
std::string CVACoreImpl::CreateSignalSourceMachine( const CVAStruct&, const std::string& sName/*="" */ )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
std::string sID = m_pSignalSourceManager->CreateMachineSignalSource( sName );
return sID;
}
VA_RETHROW;
}
bool CVACoreImpl::DeleteSignalSource( const std::string& sID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSignalSourceManager->DeleteSignalSource( sID );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_DELETED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
VA_INFO( "Core", "Deleted signal source " << sID );
return true;
}
VA_RETHROW;
}
std::string CVACoreImpl::RegisterSignalSource( IVAAudioSignalSource* pSignalSource, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
std::string sID = m_pSignalSourceManager->RegisterSignalSource( pSignalSource, sName, false, false );
assert( !sID.empty() );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_REGISTERED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
return sID;
}
VA_RETHROW;
}
bool CVACoreImpl::UnregisterSignalSource( IVAAudioSignalSource* pSignalSource )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// ID der Quelle suchen
std::string sID = m_pSignalSourceManager->GetSignalSourceID( pSignalSource );
if( sID.empty() )
VA_EXCEPT2( INVALID_ID, "Invalid signal source ID" );
m_pSignalSourceManager->UnregisterSignalSource( sID );
// Ereignis generieren, wenn Operation erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_UNREGISTERED;
ev.pSender = this;
ev.sObjectID = sID;
m_pEventManager->BroadcastEvent( ev );
}
VA_RETHROW;
return true;
}
CVASignalSourceInfo CVACoreImpl::GetSignalSourceInfo( const std::string& sSignalSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASignalSourceInfo ssi = m_pSignalSourceManager->GetSignalSourceInfo( sSignalSourceID );
return ssi;
}
VA_RETHROW;
}
void CVACoreImpl::GetSignalSourceInfos( std::vector<CVASignalSourceInfo>& vssiDest ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSignalSourceManager->GetSignalSourceInfos( vssiDest );
}
VA_RETHROW;
}
int CVACoreImpl::GetSignalSourceBufferPlaybackState( const std::string& sSignalSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
int iState = pAudiofileSource->GetPlaybackState();
m_pSignalSourceManager->ReleaseSignalSource( pSource );
return iState;
} VA_RETHROW;
}
CVAStruct CVACoreImpl::GetSignalSourceParameters( const std::string& sSignalSourceID, const CVAStruct& oParams ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
CVAStruct oRet = pSource->GetParameters( oParams );
m_pSignalSourceManager->ReleaseSignalSource( pSource );
return oRet;
} VA_RETHROW;
}
int CVACoreImpl::AddSignalSourceSequencerSample( const std::string& sSignalSourceID, const CVAStruct& oArgs )
{
VA_EXCEPT_NOT_IMPLEMENTED;
}
void CVACoreImpl::SetSignalSourceParameters( const std::string& sSignalSourceID, const CVAStruct& oParams )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
pSource->SetParameters( oParams );
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
ev.pSender = this;
ev.sObjectID = sSignalSourceID;
m_pEventManager->BroadcastEvent( ev );
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_VERBOSE( "Core", "Changed parameters of signal source " << sSignalSourceID );
} VA_RETHROW;
}
void CVACoreImpl::SetSignalSourceBufferPlaybackAction( const std::string& sSignalSourceID, const int iPlaybackAction )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( !GetSignalSourceBufferPlaybackActionValid( iPlaybackAction ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback action" );
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_EXCEPT2( INVALID_PARAMETER, "Cannot set playback action for this type of signal source" );
}
CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
pAudiofileSource->SetPlaybackAction( iPlaybackAction );
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
ev.pSender = this;
ev.sObjectID = sSignalSourceID;
m_pEventManager->BroadcastEvent( ev );
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_INFO( "Core", "Set audio file signal source '" << sSignalSourceID << "'"
<< " playstate action to " << IVAInterface::GetPlaybackActionStr( iPlaybackAction ) );
} VA_RETHROW;
}
void CVACoreImpl::SetSignalSourceBufferPlaybackPosition( const std::string& sSignalSourceID, const double dPlaybackPosition )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// Parameter berprfen
if( dPlaybackPosition < 0 )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback position" );
// Quelle anfordern (prft auf gltige ID)
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
// Playstate kann man nur bei Dateiquellen setzen
if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_EXCEPT2( INVALID_PARAMETER, "Cannot set playstate for this type of signal source" );
}
/* TODO:
// Sicherstellen das es eine Dateiquelle ist
if (pSource->GetTypeMnemonic() != "af") {
m_pSignalSourceMan->ReleaseSignalSource(pSource);
VA_EXCEPT2(INVALID_PARAMETER, "Invalid auralization mode");
}
*/
// Zustand setzen
CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
try
{
pAudiofileSource->SetCursorSeconds( dPlaybackPosition );
}
catch( ... )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
throw;
}
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_INFO( "Core", "Set audiofile signal source " << sSignalSourceID << " playback position to " << dPlaybackPosition );
} VA_RETHROW;
}
void CVACoreImpl::SetSignalSourceBufferLooping( const std::string& sSignalSourceID, const bool bLooping )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_EXCEPT2( INVALID_PARAMETER, "Cannot set looping mode for this type of signal source" );
}
CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
pAudiofileSource->SetIsLooping( bLooping );
CVAEvent ev;
ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
ev.pSender = this;
ev.sObjectID = sSignalSourceID;
m_pEventManager->BroadcastEvent( ev );
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_INFO( "Core", "Changed audiofile signal source '" << sSignalSourceID << "'"
<< " playstate looping mode to " << ( bLooping ? "looping" : "not looping" ) );
} VA_RETHROW;
}
bool CVACoreImpl::GetSignalSourceBufferLooping( const std::string& sSignalSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_EXCEPT2( INVALID_PARAMETER, "Cannot set looping mode for this type of signal source" );
}
CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
bool bLooping = pAudiofileSource->GetIsLooping();
m_pSignalSourceManager->ReleaseSignalSource( pSource );
return bLooping;
} VA_RETHROW;
}
int CVACoreImpl::AddSignalSourceSequencerPlayback( const std::string& sSignalSourceID, const int iSoundID, const int iFlags, const double dTimecode )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
IVAAudioSignalSource* pSource = nullptr;
VA_TRY
{
// Quelle anfordern (prft auf gltige ID)
pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
// Playbacks kann man nur bei Sequencer-Quellen modifizieren
if( pSource->GetType() != IVAAudioSignalSource::VA_SS_SEQUENCER )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_EXCEPT2( INVALID_PARAMETER, "Playbacks can only be added to sequencer signal sources" );
}
/* TODO:
// Sicherstellen das es eine Sampler ist
if (pSource->GetTypeMnemonic() != "af") {
m_pSignalSourceMan->ReleaseSignalSource(pSource);
VA_EXCEPT2(INVALID_PARAMETER, "Invalid auralization mode");
}
*/
// Zustand setzen
int iPlaybackID;
try
{
CVASequencerSignalSource* pSamplerSource = dynamic_cast< CVASequencerSignalSource* >( pSource );
iPlaybackID = pSamplerSource->AddSoundPlayback( iSoundID, iFlags, dTimecode );
}
catch( ... )
{
m_pSignalSourceManager->ReleaseSignalSource( pSource );
throw;
}
// Signalquelle freigeben
m_pSignalSourceManager->ReleaseSignalSource( pSource );
VA_INFO( "Core", "Added sound playback (Signal source=" << sSignalSourceID << ", Sound=" << iSoundID << ", Flags=" << iFlags << ", Timecode=" << dTimecode << ")" );
return iPlaybackID;
}
VA_FINALLY
{
// Signalquelle freigeben
if( pSource ) m_pSignalSourceManager->ReleaseSignalSource( pSource );
// VAExceptions unverndert nach aussen leiten
throw;
}
}
void CVACoreImpl::RemoveSignalSourceSequencerSample( const std::string& sSignalSourceID, const int iSoundID )
{
VA_EXCEPT_NOT_IMPLEMENTED;
}
bool CVACoreImpl::GetUpdateLocked() const
{
VA_CHECK_INITIALIZED;
return ( m_lSyncModOwner != -1 );
}
void CVACoreImpl::LockUpdate()
{
m_dSyncEntryTime = m_pClock->getTime();
VA_CHECK_INITIALIZED;
VA_LOCK_REENTRANCE;
if( m_lSyncModOwner != -1 )
{
// Thread already owner, increment spin counter
if( getCurrentThreadID() == m_lSyncModOwner )
{
++m_lSyncModSpinCount;
VA_UNLOCK_REENTRANCE;
VA_VERBOSE( "Core", "Attempt to enter synchronized scene modification ignored - already in a synchronized scene modification" );
return;
}
}
VA_UNLOCK_REENTRANCE;
VA_TRACE( "Core", "Beginning synchronized scene modification" );
/*
* Blocking wait des aufrufenden Thread.
* Wichtig: Dies muss ausserhalb des Reentrance-Lock geschehen,
* da sonst kein anderer Thread mehr auf der Schnittstelle aufrufen kann.
*/
m_mxSyncModLock.Lock();
VA_LOCK_REENTRANCE;
m_lSyncModOwner = getCurrentThreadID();
++m_lSyncModSpinCount;
VA_TRY
{
m_pNewSceneState = m_pSceneManager->CreateDerivedSceneState( m_pSceneManager->GetHeadSceneStateID(), m_dSyncEntryTime );
VA_UNLOCK_REENTRANCE;
}
VA_FINALLY
{
m_mxSyncModLock.Unlock();
m_lSyncModOwner = -1;
VA_UNLOCK_REENTRANCE;
throw;
}
}
int CVACoreImpl::UnlockUpdate()
{
VA_CHECK_INITIALIZED;
VA_LOCK_REENTRANCE;
int iNewSceneID = -1;
VA_TRACE( "Core", "Unlocking scene" );
// Sicherheitscheck: Gar nicht innerhalb Synchronisation => Fehler
if( m_lSyncModOwner == -1 )
{
VA_UNLOCK_REENTRANCE;
VA_EXCEPT2( MODAL_ERROR, "Not within a synchronized modification phase" );
}
if( m_lSyncModOwner != getCurrentThreadID() )
{
VA_UNLOCK_REENTRANCE;
VA_EXCEPT2( MODAL_ERROR, "Synchronized modification may only be ended by the same thread that begun it" );
}
if( --m_lSyncModSpinCount > 0 )
{
// Nicht die letzte Freigabe des Token.
VA_UNLOCK_REENTRANCE;
return -1;
}
VA_TRY
{
m_pNewSceneState->Fix();
iNewSceneID = m_pNewSceneState->GetID();
m_pSceneManager->SetHeadSceneState( iNewSceneID );
m_iNewActiveSoundReceiver = m_iUpdActiveSoundReceiver;
m_lSyncModOwner = -1;
m_mxSyncModLock.Unlock();
VA_UNLOCK_REENTRANCE;
}
VA_FINALLY
{
VA_UNLOCK_REENTRANCE;
throw;
}
VA_TRY
{
m_pCoreThread->Trigger();
m_pEventManager->BroadcastEvents();
return iNewSceneID;
}
VA_RETHROW;
}
void CVACoreImpl::GetSoundSourceIDs( std::vector< int >& vSoundSourceIDs )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->GetHeadSceneState()->GetSoundSourceIDs( &vSoundSourceIDs );
}
VA_RETHROW;
}
CVASoundSourceInfo CVACoreImpl::GetSoundSourceInfo( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASoundSourceDesc* oDesc = m_pSceneManager->GetSoundSourceDesc( iID );
CVASoundSourceInfo oInfo;
oInfo.iID = oDesc->iID;
oInfo.bMuted = oDesc->bMuted;
oInfo.dSpoundPower = oDesc->fSoundPower;
oInfo.sName = oDesc->sName;
return oInfo;
}
VA_RETHROW;
}
int CVACoreImpl::CreateSoundSource( const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
const bool bInSyncMode = GetUpdateLocked();
if( !bInSyncMode )
LockUpdate();
VA_TRY
{
if( ( VACORE_MAX_NUM_SOUND_SOURCES != 0 ) && m_pNewSceneState )
{
int iSourcesRemain = VACORE_MAX_NUM_SOUND_SOURCES - m_pNewSceneState->GetNumSoundSources();
if( iSourcesRemain <= 0 )
{
std::stringstream ss;
ss << "Maximum number of sound sources reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_SOURCES << " sound sources.";
VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
}
}
// Schallquelle anlegen
int iSourceID = m_pNewSceneState->AddSoundSource();
assert( iSourceID != -1 );
// HINWEIS: Zunchst hier die statische Beschreibung der Quelle anlegen
CVASoundSourceDesc* pDesc = m_pSceneManager->CreateSoundSourceDesc( iSourceID );
// Keine Signalquelle zugewiesen. Wichtig: Stillepuffer einsetzen!
pDesc->pSignalSourceInputBuf = m_pSignalSourceManager->GetSilenceBuffer();
// Initiale Werte setzen
m_pSceneManager->SetSoundSourceName( iSourceID, sName );
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSourceID );
assert( pSourceState );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CREATED;
ev.pSender = this;
ev.iObjectID = iSourceID;
ev.sName = sName;
m_pEventManager->EnqueueEvent( ev );
if( !bInSyncMode )
UnlockUpdate();
VA_INFO( "Core", "Created sound source '" << sName << "' and assigned ID " << iSourceID );
return iSourceID;
}
VA_FINALLY
{
if( bInSyncMode )
UnlockUpdate();
throw;
}
}
int CVACoreImpl::CreateSoundSourceExplicitRenderer( const std::string& sRendererID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
VA_TRY
{
if( ( VACORE_MAX_NUM_SOUND_SOURCES != 0 ) && m_pNewSceneState )
{
int iSourcesRemain = VACORE_MAX_NUM_SOUND_SOURCES - m_pNewSceneState->GetNumSoundSources();
if( iSourcesRemain <= 0 )
{
std::stringstream ss;
ss << "Maximum number of sound sources reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_SOURCES << " sound sources.";
VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
}
}
int iSourceID = m_pNewSceneState->AddSoundSource();
assert( iSourceID != -1 );
CVASoundSourceDesc* pDesc = m_pSceneManager->CreateSoundSourceDesc( iSourceID );
pDesc->sExplicitRendererID = sRendererID;
pDesc->pSignalSourceInputBuf = m_pSignalSourceManager->GetSilenceBuffer();
m_pSceneManager->SetSoundSourceName( iSourceID, sName );
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSourceID );
assert( pSourceState );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CREATED;
ev.pSender = this;
ev.iObjectID = iSourceID;
ev.sName = sName;
ev.iAuralizationMode = VA_AURAMODE_ALL;
ev.dVolume = 1.0f;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Created sound receiver '" << sName << "' and assigned ID " << iSourceID << " explicitly for renderer '" << sRendererID << "' only" );
return iSourceID;
}
VA_FINALLY
{
if( bSync )
UnlockUpdate();
throw;
}
}
int CVACoreImpl::DeleteSoundSource( const int iSoundSourceID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
VA_TRY
{
m_pNewSceneState->RemoveSoundSource( iSoundSourceID );
// Ereignis generieren, wenn erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_DELETED;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Deleted sound source " << iSoundSourceID );
return 0;
}
VA_FINALLY
{
if( !bSync )
UnlockUpdate();
throw;
}
}
void CVACoreImpl::SetSoundSourceEnabled( const int iSoundSourceID, const bool bEnabled )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
if( pDesc->bEnabled != bEnabled )
{
pDesc->bEnabled = bEnabled;
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_MUTING; // @todo JST new event type
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
//ev.bEnabled = bEnabled; // @todo JST
m_pEventManager->EnqueueEvent( ev );
// Trigger core thread
m_pCoreThread->Trigger();
}
}
VA_RETHROW;
}
bool CVACoreImpl::GetSoundSourceEnabled( const int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
return pDesc->bEnabled;
}
VA_RETHROW;
}
std::string CVACoreImpl::GetSoundSourceName( const int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
return m_pSceneManager->GetSoundSourceName( iSoundSourceID );
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceName( const int iSoundSourceID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->SetSoundSourceName( iSoundSourceID, sName );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_NAME;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.sName = sName;
m_pEventManager->BroadcastEvent( ev );
}
VA_RETHROW;
}
std::string CVACoreImpl::GetSoundSourceSignalSource( int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
if( pDesc->pSignalSource.get() != nullptr )
return m_pSignalSourceManager->GetSignalSourceID( pDesc->pSignalSource );
else
return "";
}
VA_RETHROW;
}
int CVACoreImpl::GetSoundSourceGeometryMesh( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundSourceGeometryMesh( const int iSoundSourceID, const int iGeometryMeshID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundSourceSignalSource( int iSoundSourceID, const std::string& sSignalSourceID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
// Keine Signalquelle zugewiesen. Wichtig: Stillepuffer einsetzen!
IVAAudioSignalSource* pNewSrc( nullptr ); // Neu oder zustzlich ...
const ITASampleBuffer* pNewBuf( m_pSignalSourceManager->GetSilenceBuffer() );
VA_TRY
{
CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
// Sicherstellen, das die Signalquellen ID gltig ist .. dann ID und Qu
if( !sSignalSourceID.empty() )
pNewSrc = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID, &pNewBuf );
// Vorherige Bindung auflsen und Signalquelle freigeben
if( pDesc->pSignalSource.get() != nullptr )
m_pSignalSourceManager->ReleaseSignalSource( pDesc->pSignalSource );
// Vorhandene Signalquelle zu dieser SoundSource zuordnen (atomare Ops)
pDesc->pSignalSource.set( pNewSrc );
pDesc->pSignalSourceInputBuf.set( pNewBuf );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_SIGNALSOURCE;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.sParam = sSignalSourceID;
m_pEventManager->EnqueueEvent( ev );
if( pNewSrc == nullptr )
{
VA_INFO( "Core", "Removed signal source from sound source " << iSoundSourceID << " (now uses silence buffer samples)" );
}
else
{
VA_INFO( "Core", "Set sound source " << iSoundSourceID << " signal source '" << sSignalSourceID << "'" );
}
return;
}
VA_CATCH( ex )
{
// Referenz auf die neue Signalquelle wieder entfernen
if( pNewSrc )
m_pSignalSourceManager->ReleaseSignalSource( pNewSrc );
throw ex;
}
}
int CVACoreImpl::GetSoundSourceAuralizationMode( int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
if( !pSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
return pSourceState->GetAuralizationMode();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceAuralizationMode( int iSoundSourceID, int iAuralizationMode )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// Parameter berprfen
if( !GetAuralizationModeValid( iAuralizationMode ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
bool bSync = GetUpdateLocked();
if( !bSync ) LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
pSourceState->SetAuralizationMode( iAuralizationMode );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_AURALIZATIONMODE;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.iAuralizationMode = iAuralizationMode;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceParameters( int iID, const CVAStruct& oParams )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSoundSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
if( !pSoundSourceState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
pSoundSourceState->SetParameters( oParams );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_NAME; // @todo create own core event "parameter changed"
ev.pSender = this;
ev.iObjectID = iID;
// ev.oStruct @todo: add a struct to the event
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
CVAStruct CVACoreImpl::GetSoundSourceParameters( int iID, const CVAStruct& oArgs ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSoundSourceState = pHeadState->GetSoundSourceState( iID );
if( !pSoundSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
return pSoundSourceState->GetParameters( oArgs );
}
VA_RETHROW;
}
int CVACoreImpl::GetSoundSourceDirectivity( int iSoundSourceID ) const {
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
if( !pSourceState )
// Quelle existiert nicht
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
return pSourceState->GetDirectivityID();
} VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceDirectivity( const int iSoundSourceID, const int iDirectivityID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
if( !pSourceState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
const IVADirectivity* pNewDirectivity = nullptr;
if( iDirectivityID != -1 )
{
pNewDirectivity = m_pDirectivityManager->RequestDirectivity( iDirectivityID );
if( !pNewDirectivity )
{
VA_EXCEPT2( INVALID_PARAMETER, "Invalid directivity ID" );
// TODO: Release des vernderten State?
}
}
pSourceState->SetDirectivityID( iDirectivityID );
pSourceState->SetDirectivityData( pNewDirectivity );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_DIRECTIVITY;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.iParamID = iDirectivityID;
m_pEventManager->EnqueueEvent( ev );
if( !bSync ) UnlockUpdate();
} VA_RETHROW;
}
double CVACoreImpl::GetSoundSourceSoundPower( const int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
if( !pSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
return pSourceState->GetSoundPower();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceSoundPower( const int iSoundSourceID, const double dSoundPower )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// Parameter berprfen
if( !GetVolumeValid( dSoundPower ) )
{
VA_EXCEPT2( INVALID_PARAMETER, "Invalid volume" );
}
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
pSourceState->SetSoundPower( dSoundPower );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_SOUND_POWER;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.dVolume = dSoundPower;
m_pEventManager->EnqueueEvent( ev );
if( !bSync ) UnlockUpdate();
} VA_RETHROW;
}
bool CVACoreImpl::GetSoundSourceMuted( const int iSoundSourceID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
return pDesc->bMuted;
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceMuted( const int iSoundSourceID, const bool bMuted )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
if( pDesc->bMuted != bMuted )
{
pDesc->bMuted = bMuted;
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_MUTING;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.bMuted = bMuted;
m_pEventManager->EnqueueEvent( ev );
// Trigger core thread
m_pCoreThread->Trigger();
}
} VA_RETHROW;
}
void CVACoreImpl::GetSoundSourcePose( const int iSoundSourceID, VAVec3& v3Pos, VAQuat& qOrient ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
if( !pSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
const CVAMotionState* pMotionState = pSourceState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
v3Pos = pMotionState->GetPosition();
qOrient = pMotionState->GetOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourcePose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
pNewMotionState->SetPosition( v3Pos );
pNewMotionState->SetOrientation( qOrient );
m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
ev.vPos = v3Pos;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
VAVec3 CVACoreImpl::GetSoundSourcePosition( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iID );
if( !pSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
const CVAMotionState* pMotionState = pSourceState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetPosition();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourcePosition( const int iID, const VAVec3& v3Pos )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
pNewMotionState->SetPosition( v3Pos );
m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
ev.vPos = v3Pos;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
} VA_RETHROW;
}
VAQuat CVACoreImpl::GetSoundSourceOrientation( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iID );
if( !pSourceState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
const CVAMotionState* pMotionState = pSourceState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundSourceOrientation( const int iID, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
pNewMotionState->SetOrientation( qOrient );
m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
//ev.qOrient = qOrient; // @todo
ConvertQuaternionToViewUp( qOrient, ev.vView, ev.vUp );
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::GetSoundSourceOrientationVU( const int iID, VAVec3& v3View, VAVec3& v3Up ) const
{
ConvertQuaternionToViewUp( GetSoundSourceOrientation( iID ), v3View, v3Up );
}
void CVACoreImpl::SetSoundSourceOrientationVU( const int iSoundSourceID, const VAVec3& v3View, const VAVec3& v3Up )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
if( !pSourceState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
}
CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
pNewMotionState->SetOrientationVU( v3View, v3Up );
m_pSceneManager->GetSoundSourceDesc( iSoundSourceID )->bInitPositionOrientation = true;
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iSoundSourceID;
ev.vView = v3View;
ev.vUp = v3Up;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::GetSoundReceiverIDs( std::vector< int >& vSoundReceiverIDs ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->GetHeadSceneState()->GetListenerIDs( &vSoundReceiverIDs );
}
VA_RETHROW;
}
int CVACoreImpl::CreateSoundReceiver( const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( ( VACORE_MAX_NUM_SOUND_RECEIVERS != 0 ) && m_pNewSceneState )
{
const int iListenersRemain = VACORE_MAX_NUM_SOUND_RECEIVERS - m_pNewSceneState->GetNumListeners();
if( iListenersRemain <= 0 )
{
std::stringstream ss;
ss << "Maximum number of listeners reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_RECEIVERS << " listeners.";
VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
}
}
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
// Hrer anlegen
const int iID = m_pNewSceneState->AddListener();
assert( iID != -1 );
// HINWEIS: Zunchst hier die statische Beschreibung der Quelle anlegen
m_pSceneManager->CreateListenerDesc( iID );
// Initiale Werte setzen
m_pSceneManager->SetListenerName( iID, sName );
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
assert( pListenerState );
// INFO: Set the default position/orientation of the new listener
CVAMotionState* pMotionState = pListenerState->AlterMotionState();
pMotionState->SetPosition( VAVec3( 0, 0, 0 ) ); // Really?
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CREATED;
ev.pSender = this;
ev.iObjectID = iID;
ev.sName = sName;
SetCoreEventParams( ev, pMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Created sound receiver '" << sName << "' and assigned ID " << iID );
return iID;
} VA_RETHROW;
}
int CVACoreImpl::DeleteSoundReceiver( const int iID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
VA_TRY
{
if( iID == m_iCurActiveSoundReceiver )
{
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Cannot delete a sound receiver that is set as active sound receiver" );
}
m_pNewSceneState->RemoveListener( iID );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_DELETED;
ev.pSender = this;
ev.iObjectID = iID;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Deleted sound receiver " << iID );
return 0;
}
VA_RETHROW;
}
CVASoundReceiverInfo CVACoreImpl::GetSoundReceiverInfo( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVAListenerDesc* oDesc = m_pSceneManager->GetListenerDesc( iID );
CVASoundReceiverInfo oInfo;
oInfo.iID = oDesc->iID;
oInfo.sName = oDesc->sName;
return oInfo;
// @todo improve
}
VA_RETHROW;
}
int CVACoreImpl::CreateSoundReceiverExplicitRenderer( const std::string& sRendererID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
VA_TRY
{
if( ( VACORE_MAX_NUM_SOUND_RECEIVERS != 0 ) && m_pNewSceneState )
{
int iListenersRemain = VACORE_MAX_NUM_SOUND_RECEIVERS - m_pNewSceneState->GetNumListeners();
if( iListenersRemain <= 0 )
{
std::stringstream ss;
ss << "Maximum number of listeners reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_RECEIVERS << " listeners.";
VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
}
}
int iListenerID = m_pNewSceneState->AddListener();
assert( iListenerID != -1 );
CVAListenerDesc* pDesc = m_pSceneManager->CreateListenerDesc( iListenerID );
pDesc->sExplicitRendererID = sRendererID;
m_pSceneManager->SetListenerName( iListenerID, sName );
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iListenerID );
assert( pListenerState );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CREATED;
ev.pSender = this;
ev.iObjectID = iListenerID;
ev.sName = sName;
ev.iAuralizationMode = VA_AURAMODE_ALL;
ev.dVolume = 1.0f;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Created sound receiver (ID=" << iListenerID << ", Name=\"" << sName << "\") explicitly for renderer '" << sRendererID << "' only" );
return iListenerID;
}
VA_FINALLY
{
if( bSync )
UnlockUpdate();
throw;
}
}
void CVACoreImpl::SetSoundReceiverEnabled( const int iID, const bool bEnabled )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVAListenerDesc* pDesc = m_pSceneManager->GetListenerDesc( iID );
if( pDesc->bEnabled != bEnabled )
{
pDesc->bEnabled = bEnabled;
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME; // @todo JST new event type
ev.pSender = this;
ev.iObjectID = iID;
//ev.bEnabled = bEnabled; // @todo JST
m_pEventManager->EnqueueEvent( ev );
// Trigger core thread
m_pCoreThread->Trigger();
}
} VA_RETHROW;
}
bool CVACoreImpl::GetSoundReceiverEnabled( const int iSoundReceiverID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const CVAListenerDesc* pDesc = m_pSceneManager->GetListenerDesc( iSoundReceiverID );
return pDesc->bEnabled;
}
VA_RETHROW;
}
void CVACoreImpl::SetActiveSoundReceiverExplicitRenderer( const int iID, const std::string& sRendererID )
{
// @todo JST call renderer and set active listener
VA_EXCEPT2( NOT_IMPLEMENTED, "This method is currently not available (not implented)." );
}
int CVACoreImpl::GetActiveSoundReceiverExplicitRenderer( const std::string& sRendererID ) const
{
// @todo JST call renderer and return active listener
VA_EXCEPT2( NOT_IMPLEMENTED, "This method is currently not available (not implented)." );
}
std::string CVACoreImpl::GetSoundReceiverName( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
return m_pSceneManager->GetListenerName( iID );
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverName( const int iID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->SetListenerName( iID, sName );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME;
ev.pSender = this;
ev.iObjectID = iID;
ev.sName = sName;
m_pEventManager->BroadcastEvent( ev );
} VA_RETHROW;
}
int CVACoreImpl::GetSoundReceiverAuralizationMode( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
// Hrer existiert nicht
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
return pListenerState->GetAuralizationMode();
} VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverAuralizationMode( const int iID, const int iAuralizationMode )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// Parameter berprfen
if( !GetAuralizationModeValid( iAuralizationMode ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
bool bSync = GetUpdateLocked();
if( !bSync ) LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState ) {
// Hrer existiert nicht
if( !bSync ) UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
pListenerState->SetAuralizationMode( iAuralizationMode );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_AURALIZATIONMODE;
ev.pSender = this;
ev.iObjectID = iID;
ev.iAuralizationMode = iAuralizationMode;
m_pEventManager->EnqueueEvent( ev );
if( !bSync ) UnlockUpdate();
} VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverParameters( const int iID, const CVAStruct& oParams )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID " + std::to_string( long( iID ) ) );
}
pListenerState->SetParameters( oParams );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME; // @todo create own core event "parameter changed"
ev.pSender = this;
ev.iObjectID = iID;
// ev.oStruct @todo: add a struct to the event
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
CVAStruct CVACoreImpl::GetSoundReceiverParameters( const int iID, const CVAStruct& oArgs ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
return pListenerState->GetParameters( oArgs );
}
VA_RETHROW;
}
int CVACoreImpl::GetSoundReceiverDirectivity( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
return pListenerState->GetDirectivityID();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverDirectivity( const int iID, const int iDirectivityID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
// Parameter berprfen
const IVADirectivity* pDirectivity = nullptr;
if( iDirectivityID != -1 )
{
pDirectivity = m_pDirectivityManager->RequestDirectivity( iDirectivityID );
if( !pDirectivity )
VA_EXCEPT2( INVALID_ID, "Invalid directivity dataset for ID " + std::to_string( iID ) );
}
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
// Quelle existiert nicht
if( !bSync )
UnlockUpdate();
if( pDirectivity )
m_pDirectivityManager->DeleteDirectivity( iDirectivityID );
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID " + std::to_string( iID ) );
}
pListenerState->SetDirectivityID( iDirectivityID );
pListenerState->SetDirectivity( pDirectivity );
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_DIRECTIVITY;
ev.pSender = this;
ev.iObjectID = iID;
ev.iParamID = iDirectivityID;
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
VA_INFO( "Core", "Linked sound receiver " + std::to_string( long( iID ) ) + " with receiver directivity dataset " + std::to_string( long( iDirectivityID ) ) );
}
VA_RETHROW;
}
int CVACoreImpl::GetSoundReceiverGeometryMesh( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundReceiverGeometryMesh( const int iSoundReceiverID, const int iGeometryMeshID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::GetSoundReceiverPose( const int iID, VAVec3& v3Pos, VAQuat& qOrient ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pListenerState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "SoundReceiver has invalid motion state, probably it has not been positioned, yet?" );
v3Pos = pMotionState->GetPosition();
qOrient = pMotionState->GetOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverPose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pState = m_pNewSceneState->AlterListenerState( iID );
if( !pState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID, not found in scene" );
}
CVAMotionState* pNewMotionState = pState->AlterMotionState();
pNewMotionState->SetPosition( v3Pos );
pNewMotionState->SetOrientation( qOrient );
//m_pSceneManager->GetListenerDesc( iID )->bInitPositionOrientation = true; // @todo
// Ereignis generieren, falls erfolgreich
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
ev.vPos = v3Pos;
//ev.qOrient = qOrient; // @todo
ConvertQuaternionToViewUp( qOrient, ev.vView, ev.vUp );
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
VAVec3 CVACoreImpl::GetSoundReceiverPosition( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pSoundReceiverState = pHeadState->GetReceiverState( iID );
if( !pSoundReceiverState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pSoundReceiverState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "SoundReceiver has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetPosition();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverPosition( const int iID, const VAVec3& v3Pos )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync ) UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
pNewMotionState->SetPosition( v3Pos );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
} VA_RETHROW;
}
void CVACoreImpl::GetSoundReceiverOrientationVU( const int iID, VAVec3& vView, VAVec3& vUp ) const
{
ConvertQuaternionToViewUp( GetSoundReceiverOrientation( iID ), vView, vUp );
}
void CVACoreImpl::SetSoundReceiverOrientationVU( const int iID, const VAVec3& v3View, const VAVec3& v3Up )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
pNewMotionState->SetOrientationVU( v3View, v3Up );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
VAQuat CVACoreImpl::GetSoundReceiverOrientation( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pSoundReceiverState = pHeadState->GetReceiverState( iID );
if( !pSoundReceiverState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pSoundReceiverState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverOrientation( const int iID, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
pNewMotionState->SetOrientation( qOrient );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
VAQuat CVACoreImpl::GetSoundReceiverHeadAboveTorsoOrientation( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pListenerState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetHeadAboveTorsoOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverHeadAboveTorsoOrientation( const int iID, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
pNewMotionState->SetHeadAboveTorsoOrientation( qOrient );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::GetSoundReceiverRealWorldPositionOrientationVU( const int iID, VAVec3& v3Pos, VAVec3& v3View, VAVec3& v3Up ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
// Hrer existiert nicht
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pListenerState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
v3Pos = pMotionState->GetRealWorldPose().vPos;
VAQuat qOrient = pMotionState->GetRealWorldPose().qOrient;
ConvertQuaternionToViewUp( qOrient, v3View, v3Up );
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverRealWorldPositionOrientationVU( const int iID, const VAVec3& v3Pos, const VAVec3& v3View, const VAVec3& v3Up )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
CVAMotionState::CVAPose oNewPose;
oNewPose.vPos = v3Pos;
ConvertViewUpToQuaternion( v3View, v3Up, oNewPose.qOrient );
pNewMotionState->SetRealWorldPose( oNewPose );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_REAL_WORLD_POSE_CHANGED;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::GetSoundReceiverRealWorldPose( const int iID, VAVec3& v3Pos, VAQuat& qOrient ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
// Hrer existiert nicht
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pListenerState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
v3Pos = pMotionState->GetRealWorldPose().vPos;
qOrient = pMotionState->GetRealWorldPose().qOrient;
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverRealWorldPose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
CVAMotionState::CVAPose oNewPose;
oNewPose.vPos = v3Pos;
oNewPose.qOrient = qOrient;
pNewMotionState->SetRealWorldPose( oNewPose );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
VAQuat CVACoreImpl::GetSoundReceiverRealWorldHeadAboveTorsoOrientation( const int iID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
if( !pListenerState )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
const CVAMotionState* pMotionState = pListenerState->GetMotionState();
if( !pMotionState )
VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
return pMotionState->GetRealWorldHeadAboveTorsoOrientation();
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundReceiverRealWorldHeadAboveTorsoOrientation( const int iID, const VAQuat& qOrient )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
const bool bSync = GetUpdateLocked();
if( !bSync )
LockUpdate();
CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
if( !pListenerState )
{
if( !bSync )
UnlockUpdate();
VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
}
CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
pNewMotionState->SetRealWorldHeadAboveTorsoOrientation( qOrient );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
ev.pSender = this;
ev.iObjectID = iID;
SetCoreEventParams( ev, pNewMotionState );
m_pEventManager->EnqueueEvent( ev );
if( !bSync )
UnlockUpdate();
}
VA_RETHROW;
}
void CVACoreImpl::SetHomogeneousMediumSoundSpeed( const double dSoundSpeed )
{
VA_NO_REENTRANCE;
VA_TRY
{
if( dSoundSpeed <= 0.0f )
VA_EXCEPT2( INVALID_PARAMETER, "Speed of sound can not be zero or negative" );
oHomogeneousMedium.dSoundSpeed = dSoundSpeed;
}
VA_RETHROW;
}
double CVACoreImpl::GetHomogeneousMediumSoundSpeed() const
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.dSoundSpeed;
}
void CVACoreImpl::SetHomogeneousMediumTemperature( const double dDegreesCentigrade )
{
VA_NO_REENTRANCE;
VA_TRY
{
if( dDegreesCentigrade <= -270.0f )
VA_EXCEPT2( INVALID_PARAMETER, "Temperature can not be below total zero" );
oHomogeneousMedium.dTemperatureDegreeCentigrade = dDegreesCentigrade;
}
VA_RETHROW;
}
double CVACoreImpl::GetHomogeneousMediumTemperature() const
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.dTemperatureDegreeCentigrade;
}
void CVACoreImpl::SetHomogeneousMediumStaticPressure( const double dPressurePascal )
{
VA_NO_REENTRANCE;
VA_TRY
{
if( dPressurePascal <= 0.0f )
VA_EXCEPT2( INVALID_PARAMETER, "Static pressure can not be zero or negative" );
oHomogeneousMedium.dStaticPressurePascal = dPressurePascal;
}
VA_RETHROW;
}
double CVACoreImpl::GetHomogeneousMediumStaticPressure() const
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.dStaticPressurePascal;
}
void CVACoreImpl::SetHomogeneousMediumRelativeHumidity( const double dRelativeHumidityPercent )
{
VA_NO_REENTRANCE;
VA_TRY
{
if( dRelativeHumidityPercent < 0.0f )
VA_EXCEPT2( INVALID_PARAMETER, "Relative humidity can not be negative" );
oHomogeneousMedium.dRelativeHumidityPercent = dRelativeHumidityPercent;
}
VA_RETHROW;
}
double CVACoreImpl::GetHomogeneousMediumRelativeHumidity()
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.dRelativeHumidityPercent;
}
void CVACoreImpl::SetHomogeneousMediumShiftSpeed( const VAVec3& v3TranslationSpeed )
{
VA_NO_REENTRANCE;
VA_TRY
{
if( v3TranslationSpeed.Length() >= oHomogeneousMedium.dSoundSpeed )
VA_EXCEPT2( INVALID_PARAMETER, "Medium shift can not be equal or faster than sound speed" );
oHomogeneousMedium.v3ShiftSpeed = v3TranslationSpeed;
}
VA_RETHROW;
}
VAVec3 CVACoreImpl::GetHomogeneousMediumShiftSpeed() const
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.v3ShiftSpeed;
}
void CVACoreImpl::SetHomogeneousMediumParameters( const CVAStruct& oParams )
{
VA_NO_REENTRANCE;
oHomogeneousMedium.oParameters = oParams;
}
CVAStruct CVACoreImpl::GetHomogeneousMediumParameters( const CVAStruct& oArgs )
{
VA_NO_REENTRANCE;
return oHomogeneousMedium.oParameters;
}
std::string CVACoreImpl::CreateScene( const CVAStruct& oParams, const std::string& sSceneName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( oParams.HasKey( "filepath" ) )
{
const std::string sFilePath = oParams[ "filepath" ];
VA_INFO( "Core", "Loading scene from file '" << sFilePath << "'" );
std::string sDestFilename = correctPath( m_oCoreConfig.mMacros.SubstituteMacros( sFilePath ) );
for( std::vector<CVAAudioRendererDesc>::iterator it = m_voRenderers.begin(); it != m_voRenderers.end(); ++it )
it->pInstance->LoadScene( sDestFilename );
// @todo: create a scene manager and return a proper scene identifier
return sDestFilename;
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret scene parameters, missing key 'filepath'" );
}
}
VA_RETHROW;
}
CVASceneInfo CVACoreImpl::GetSceneInfo( const std::string& sSceneID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
VA_RETHROW;
}
bool CVACoreImpl::GetSceneEnabled( const std::string& sID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
VA_RETHROW;
}
int CVACoreImpl::CreateSoundPortal( const std::string& sName /*= "" */ )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
//m_pSceneManager->CreatePortalDesc()
}
void CVACoreImpl::GetSceneIDs( std::vector< std::string >& vsIDs ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
std::string CVACoreImpl::GetSceneName( const std::string& sID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSceneName( const std::string& sID, const std::string& sName )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSceneEnabled( const std::string& sID, const bool bEnabled /*= true */ )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::GetSoundPortalIDs( std::vector< int >& vPortalIDs )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->GetHeadSceneState()->GetPortalIDs( &vPortalIDs );
}
VA_RETHROW;
}
CVASoundPortalInfo CVACoreImpl::GetSoundPortalInfo( const int iID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
std::string CVACoreImpl::GetSoundPortalName( const int iPortalID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
return m_pSceneManager->GetPortalName( iPortalID );
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundPortalName( const int iPortalID, const std::string& sName )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
m_pSceneManager->SetPortalName( iPortalID, sName );
CVAEvent ev;
ev.iEventType = CVAEvent::SOUND_PORTAL_CHANGED_NAME;
ev.pSender = this;
ev.iObjectID = iPortalID;
ev.sName = sName;
m_pEventManager->BroadcastEvent( ev );
}
VA_RETHROW;
}
void CVACoreImpl::SetSoundPortalMaterial( const int iSoundPortalID, const int iMaterialID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::GetSoundPortalMaterial( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalNextPortal( const int iSoundPortalID, const int iNextSoundPortalID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::GetSoundPortalNextPortal( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalSoundReceiver( const int iSoundPortalID, const int iSoundReceiverID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::GetSoundPortalSoundReceiver( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalSoundSource( const int iSoundPortalID, const int iSoundSourceID )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
int CVACoreImpl::GetSoundPortalSoundSource( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
bool CVACoreImpl::GetSoundPortalEnabled( const int iPortalID ) const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
VA_RETHROW;
}
CVAStruct CVACoreImpl::GetSoundPortalParameters( const int iID, const CVAStruct& oArgs ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalParameters( const int iID, const CVAStruct& oParams )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalPosition( const int iSoundPortalID, const VAVec3& vPos )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
VAVec3 CVACoreImpl::GetSoundPortalPosition( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalOrientation( const int iSoundPortalID, const VAQuat& qOrient )
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
VAQuat CVACoreImpl::GetSoundPortalOrientation( const int iSoundPortalID ) const
{
VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
}
void CVACoreImpl::SetSoundPortalEnabled( const int iID, const bool bEnabled )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
//m_pSceneManager->SetPortalEnabled( iID, bEnabled );
}
VA_RETHROW;
}
bool CVACoreImpl::GetInputMuted() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_bInputMuted;
}
void CVACoreImpl::SetInputMuted( const bool bMuted )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( m_bInputMuted == bMuted )
return;
m_bInputMuted = bMuted;
if( m_pInputAmp )
{
if( m_bInputMuted )
m_pInputAmp->SetGain( 0.0f );
else
m_pInputAmp->SetGain( ( float ) m_dInputGain );
}
VA_INFO( "Core", "Input mute toggled" );
CVAEvent ev;
ev.iEventType = CVAEvent::INPUT_MUTING_CHANGED;
ev.pSender = this;
ev.bMuted = m_bInputMuted;
m_pEventManager->BroadcastEvent( ev );
}
VA_RETHROW;
}
double CVACoreImpl::GetInputGain() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_dInputGain;
}
void CVACoreImpl::SetInputGain( double dGain )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( !GetVolumeValid( dGain ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid gain" );
if( m_dInputGain == dGain )
return;
m_dInputGain = dGain;
if( m_pInputAmp )
{
if( m_bInputMuted )
m_pInputAmp->SetGain( 0 );
else
m_pInputAmp->SetGain( ( float ) dGain );
}
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::INPUT_GAIN_CHANGED;
ev.pSender = this;
ev.dVolume = dGain;
m_pEventManager->BroadcastEvent( ev );
VA_VERBOSE( "Core", "Set input gain = " << IVAInterface::GetVolumeStrDecibel( dGain ) );
}
VA_RETHROW;
}
double CVACoreImpl::GetOutputGain() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_dOutputGain;
}
void CVACoreImpl::SetOutputGain( const double dGain )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( !GetVolumeValid( dGain ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid gain" );
if( m_dOutputGain == dGain )
return;
m_dOutputGain = dGain;
if( m_pOutputPatchbay )
{
if( m_bOutputMuted )
m_pOutputPatchbay->SetOutputGain( 0, 0.0f );
else
m_pOutputPatchbay->SetOutputGain( 0, dGain );
}
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::OUTPUT_GAIN_CHANGED;
ev.pSender = this;
ev.dVolume = dGain;
m_pEventManager->BroadcastEvent( ev );
VA_VERBOSE( "Core", "Set output gain = " << IVAInterface::GetVolumeStrDecibel( dGain ) );
}
VA_RETHROW;
}
bool CVACoreImpl::GetOutputMuted() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_bOutputMuted;
}
void CVACoreImpl::SetOutputMuted( const bool bMuted )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( m_bOutputMuted == bMuted )
return;
m_bOutputMuted = bMuted;
VA_INFO( "Core", "Output mute toggled" );
if( m_pOutputPatchbay )
m_pOutputPatchbay->SetOutputMuted( 0, bMuted );
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::OUTPUT_MUTING_CHANGED;
ev.pSender = this;
ev.bMuted = m_bOutputMuted;
m_pEventManager->BroadcastEvent( ev );
}
VA_RETHROW;
}
int CVACoreImpl::GetGlobalAuralizationMode() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_iGlobalAuralizationMode;
}
void CVACoreImpl::SetGlobalAuralizationMode( const int iAuralizationMode )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( !GetAuralizationModeValid( iAuralizationMode ) )
VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
if( m_iGlobalAuralizationMode == iAuralizationMode )
{
return;
}
m_iGlobalAuralizationMode = iAuralizationMode;
// Neuberechnung der Schallpfade triggern
m_pCoreThread->Trigger();
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::GLOBAL_AURALIZATION_MODE_CHANGED;
ev.pSender = this;
ev.iAuralizationMode = iAuralizationMode;
m_pEventManager->BroadcastEvent( ev );
VA_VERBOSE( "Core", "Set global auralization mode = " << IVAInterface::GetAuralizationModeStr( iAuralizationMode, true ) );
}
VA_RETHROW;
}
int CVACoreImpl::GetActiveSoundReceiver() const
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
return m_iCurActiveSoundReceiver;
}
void CVACoreImpl::SetActiveSoundReceiver( const int iListenerID )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
bool bSync = false;
VA_TRY
{
LockUpdate();
bSync = true;
// Prfen, ob Hrer in der aktuellen Konfig existiert.
if( !m_pNewSceneState->GetReceiverState( iListenerID ) )
VA_EXCEPT2( INVALID_PARAMETER, "Listener does not existing in head configuration" );
/* TODO: Auch -1 erlauben um Hrer zu entfernen
if (iListenerID != -1) {
if (!m_pNewSceneState->GetListenerState(iListenerID))
VA_EXCEPT2(INVALID_PARAMETER, "Listener does not existing in head configuration");
}
*/
if( iListenerID != m_iUpdActiveSoundReceiver )
{
m_iUpdActiveSoundReceiver = iListenerID;
m_iCurActiveSoundReceiver = iListenerID;
// Ereignis generieren
CVAEvent ev;
ev.iEventType = CVAEvent::ACTIVE_SOUND_RECEIVER_CHANGED;
ev.pSender = this;
ev.iObjectID = iListenerID;
m_pEventManager->EnqueueEvent( ev );
VA_VERBOSE( "Core", "Set sound receiver " << iListenerID << " the active receiver" );
}
bSync = false;
UnlockUpdate();
}
VA_FINALLY
{
if( bSync ) UnlockUpdate();
throw;
}
}
double CVACoreImpl::GetCoreClock() const
{
// Clock ist immer da, reentrance hier erlaubt
double dNow = m_pClock->getTime();
double dOffset = ( double ) m_fCoreClockOffset;
return ( dNow - dOffset );
}
void CVACoreImpl::SetCoreClock( const double dSeconds )
{
VA_NO_REENTRANCE;
VA_CHECK_INITIALIZED;
VA_TRY
{
if( dSeconds < 0 )
VA_EXCEPT2( INVALID_PARAMETER, "Time must not be negative" );
// Aktuelle Zeit holen
double dNow = m_pClock->getTime();
double dOffset = dSeconds - dNow;
// TODO: Sollte eigentlich ber doubles gehen. Leider noch keine AtomicDoubles...
m_fCoreClockOffset = ( float ) dOffset;
VA_VERBOSE( "Core", "Set clock to " << timeToString( dSeconds ) );
}
VA_RETHROW;
}
std::string CVACoreImpl::SubstituteMacros( const std::string& sStr ) const
{
VA_TRY
{
return m_oCoreConfig.mMacros.SubstituteMacros( sStr );
}
VA_RETHROW;
}
std::string CVACoreImpl::FindFilePath( const std::string& sRelativeFilePath ) const
{
VA_TRY
{
std::string sRelativeFilePathSubstituted = SubstituteMacros( sRelativeFilePath );
VistaFileSystemFile oFile( sRelativeFilePathSubstituted );
if( oFile.Exists() && oFile.IsFile() )
return sRelativeFilePathSubstituted;
// Search with paths list
std::string sFinalPathWithSearch;
for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
{
const std::string& sSearchPath( m_oCoreConfig.vsSearchPaths[ i ] );
std::string sCombinedFilePath = correctPath( sSearchPath + PATH_SEPARATOR + sRelativeFilePathSubstituted );
VistaFileSystemFile oFile( sCombinedFilePath );
VA_TRACE( "Core:FindFilePath", "Searching in directory '" + sSearchPath + "' for file '" + sRelativeFilePathSubstituted + "'" );
if( oFile.Exists() && oFile.IsFile() )
{
if( sFinalPathWithSearch.empty() )
{
sFinalPathWithSearch = sCombinedFilePath;
}
else
{
VA_WARN( "Core", "Found ambiguous file path '" + sCombinedFilePath + "' (skipped), using first path '" + sFinalPathWithSearch + "'" );
}
}
}
return sFinalPathWithSearch;
}
VA_RETHROW;
}
void CVACoreImpl::InitializeAudioDriver()
{
#ifdef VACORE_WITH_AUDIO_BACKEND_ASIO
if( m_oCoreConfig.oAudioDriverConfig.sDriver == "ASIO" )
m_pAudioDriverBackend = new CVAASIOBackend( &m_oCoreConfig.oAudioDriverConfig );
#endif
#ifdef VACORE_WITH_AUDIO_BACKEND_PORTAUDIO
if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Portaudio" )
m_pAudioDriverBackend = new CVAPortaudioBackend( &m_oCoreConfig.oAudioDriverConfig );
#endif
#ifdef VACORE_WITH_AUDIO_BACKEND_VIRTUAL
if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Virtual" )
{
if( m_oCoreConfig.oAudioDriverConfig.iBuffersize == -1 )
VA_EXCEPT2( INVALID_PARAMETER, "For a virtual audio device, the buffer size has to be set (AUTO detect not possible)" );
if( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == -1 )
VA_EXCEPT2( INVALID_PARAMETER, "For a virtual audio device, the output channel number has to be set (AUTO detect not possible)" );
m_oCoreConfig.oAudioDriverConfig.iInputChannels = 0; // not allowed, override
CVAVirtualAudioDriverBackend* pAudioDriverBackend = new CVAVirtualAudioDriverBackend( &m_oCoreConfig.oAudioDriverConfig );
RegisterModule( pAudioDriverBackend );
m_pAudioDriverBackend = pAudioDriverBackend;
// Overwride default block pointer by manual clock
CVAVirtualAudioDriverBackend::ManualClock* pManualClock = new CVAVirtualAudioDriverBackend::ManualClock();
RegisterModule( pManualClock );
m_pClock = pManualClock;
}
#else
#endif
if( m_pAudioDriverBackend == nullptr )
VA_EXCEPT2( INVALID_PARAMETER, "Unkown, uninitializable or unsupported audio driver backend '" + m_oCoreConfig.oAudioDriverConfig.sDriver + "'" );
try
{
VA_INFO( "Core", "Initializing audio device '" << m_pAudioDriverBackend->getDeviceName() << "' using '" << m_pAudioDriverBackend->getDriverName() << "' driver" );
VA_TRACE( "Core", "Desired settings: sampling rate " << m_oCoreConfig.oAudioDriverConfig.dSampleRate << " Hz, " <<
( m_oCoreConfig.oAudioDriverConfig.iInputChannels == CVAAudioDriverConfig::AUTO ? "all" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iInputChannels ) ) << " inputs, " <<
( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == CVAAudioDriverConfig::AUTO ? "all" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ) ) << " outputs, " <<
"buffer size = " << ( m_oCoreConfig.oAudioDriverConfig.iBuffersize == 0 ? "auto" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iBuffersize ) ) );
m_pAudioDriverBackend->initialize();
m_oCoreConfig.oAudioDriverConfig.dSampleRate = m_pAudioDriverBackend->getOutputStreamProperties()->dSamplerate;
m_oCoreConfig.oAudioDriverConfig.iInputChannels = m_pAudioDriverBackend->getNumberOfInputs();
m_oCoreConfig.oAudioDriverConfig.iOutputChannels = m_pAudioDriverBackend->getOutputStreamProperties()->uiChannels;
m_oCoreConfig.oAudioDriverConfig.iBuffersize = m_pAudioDriverBackend->getOutputStreamProperties()->uiBlocklength;
VA_INFO( "Core", "Streaming at " << std::fixed << std::setw( 3 ) << std::setprecision( 1 ) << ( m_oCoreConfig.oAudioDriverConfig.dSampleRate / 1000.0f ) << " kHz on " <<
( m_oCoreConfig.oAudioDriverConfig.iInputChannels == 0 ? "no" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iInputChannels ) ) << " inputs and " <<
( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == 0 ? "no" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ) ) <<
" outputs with a buffer size of " << m_oCoreConfig.oAudioDriverConfig.iBuffersize << " samples." );
}
catch( ... )
{
m_pAudioDriverBackend->finalize();
delete m_pAudioDriverBackend;
m_pAudioDriverBackend = nullptr;
throw;
}
}
void CVACoreImpl::FinalizeAudioDriver()
{
if( m_pAudioDriverBackend )
{
VA_INFO( "Core", "Finalizing audio device \"" << m_oCoreConfig.oAudioDriverConfig.sDevice <<
"\" [" << m_oCoreConfig.oAudioDriverConfig.sDriver << "]" );
m_pAudioDriverBackend->finalize();
delete m_pAudioDriverBackend;
m_pAudioDriverBackend = nullptr;
}
}
void CVACoreImpl::FinalizeRenderingModules()
{
for( size_t i = 0; i < m_voRenderers.size(); i++ )
{
m_voRenderers[ i ].Finalize();
}
}
void CVACoreImpl::FinalizeReproductionModules()
{
for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
{
m_voReproductionModules[ i ].Finalize();
}
}
bool CVACoreImpl::IsStreaming() const
{
return ( m_pAudioDriverBackend ? m_pAudioDriverBackend->isStreaming() : false );
}
void CVACoreImpl::InitializeAudioRenderers()
{
CVAAudioRendererRegistry* pRegistry( CVAAudioRendererRegistry::GetInstance() );
const CVAStruct& oConfig( GetCoreConfig()->GetStruct() );
// Parse config for audio renderers and try to instantiate them
CVAStruct::const_iterator cit = oConfig.Begin();
while( cit != oConfig.End() )
{
const std::string& sKey( cit->first );
const CVAStruct& oArgs( cit->second );
std::vector< std::string > vsKeyParts = splitString( sKey, ':' );
if( vsKeyParts.size() == 2 && cit->second.GetDatatype() == CVAStructValue::STRUCT )
{
std::string sCategory( toUppercase( vsKeyParts[ 0 ] ) );
std::string sID( vsKeyParts[ 1 ] );
if( sCategory == "RENDERER" )
{
CVAConfigInterpreter conf( oArgs );
conf.SetErrorPrefix( "Configuration error in section \"" + cit->first + "\"" );
std::string sClass;
conf.ReqString( "Class", sClass );
bool bEnabled;
conf.OptBool( "Enabled", bEnabled, true );
if( !bEnabled )
{
cit++;
continue; // Skip
}
// Initialization parameters
CVAAudioRendererInitParams oParams;
oParams.sID = sID;
oParams.sClass = sClass;
oParams.pCore = this;
oParams.pConfig = &cit->second.GetStruct();
oParams.bOfflineRendering = ( m_oCoreConfig.oAudioDriverConfig.sDriver == "Virtual" ) ? true : false;
conf.ReqStringListRegex( "Reproductions", oParams.vsReproductions, "\\s*,\\s*" );
std::unique( oParams.vsReproductions.begin(), oParams.vsReproductions.end() );
conf.OptBool( "OutputDetectorEnabled", oParams.bOutputLevelMeterEnabled, false );
// Set up rendering output recording
conf.OptBool( "RecordOutputEnabled", oParams.bRecordOutputEnabled, false );
if( oParams.bRecordOutputEnabled )
{
VistaFileSystemFile oRecordOutputFile( "renderer.wav" );
VistaFileSystemDirectory oRecordOutputBaseFolder( "./" );
std::string sFilePathRAWDeprecated;
conf.OptString( "RecordOutputFilePath", sFilePathRAWDeprecated );
if( !sFilePathRAWDeprecated.empty() )
{
VA_WARN( "Core", "The renderer configuration key 'RecordOutputFilePath' is deprecated. Use 'RecordOutputBaseFolder' (optional) and 'RecordOutputFileName' instead." );
std::string sDummy;
if( conf.OptString( "RecordOutputBaseFolder", sDummy ) || conf.OptString( "RecordOutputFileName", sDummy ) )
VA_EXCEPT2( INVALID_PARAMETER, "You have combined old rendering configuration key 'RecordOutputFilePath' with one of the new keys 'RecordOutputBaseFolder' (optional) or 'RecordOutputFileName'. Please use new key only." );
std::string sRecordOutputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAWDeprecated );
oRecordOutputFile.SetName( sRecordOutputFilePath );
oRecordOutputBaseFolder.SetName( oRecordOutputFile.GetParentDirectory() );
}
else
{
std::string sFileNameRAW;
conf.ReqString( "RecordOutputFileName", sFileNameRAW );
std::string sFileName = m_oCoreConfig.mMacros.SubstituteMacros( sFileNameRAW );
oRecordOutputFile.SetName( sFileName );
std::string sBaseFolderRAW;
conf.ReqString( "RecordOutputBaseFolder", sBaseFolderRAW );
std::string sBaseFolder = m_oCoreConfig.mMacros.SubstituteMacros( sBaseFolderRAW );
oRecordOutputBaseFolder.SetName( sBaseFolder );
}
if( !oRecordOutputBaseFolder.Exists() )
{
if( oRecordOutputBaseFolder.CreateWithParentDirectories() )
{
VA_INFO( "Core", "Created renderer record output base folder " << oRecordOutputBaseFolder.GetName() << " with parent directories" );
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent renderer record base folder '" + oRecordOutputBaseFolder.GetName() + "'" );
}
}
oParams.sRecordOutputFileName = oRecordOutputFile.GetLocalName();
oParams.sRecordOutputBaseFolder = oRecordOutputBaseFolder.GetName();
}
// Get factory method to create requested rendering module (if available from registry)
IVAAudioRendererFactory* pFactory = pRegistry->FindFactory( sClass );
if( !pFactory )
conf.Error( "Unknown class \"" + sClass + "\"" );
IVAAudioRenderer* pRenderer = pFactory->Create( oParams );
// TODO: Active umsetzen
CVAAudioRendererDesc oRendererDesc( pRenderer );
oRendererDesc.sID = sID;
oRendererDesc.sClass = sClass;
oRendererDesc.bEnabled = bEnabled;
ITADatasource* pRendererOutputTail = pRenderer->GetOutputDatasource();;
if( oParams.bRecordOutputEnabled )
{
std::string sFilePath = oParams.sRecordOutputBaseFolder + "/" + oParams.sRecordOutputFileName;
if( VistaFileSystemFile( sFilePath ).Exists() )
VA_INFO( "Core", "Rendering record file '" << sFilePath << "' exists, will overwrite" );
VistaFileSystemFile oFile( sFilePath );
oRendererDesc.pOutputRecorder = new ITAStreamProbe( pRendererOutputTail, oFile.GetName() );
pRendererOutputTail = oRendererDesc.pOutputRecorder;
VA_TRACE( "Core", "Rendering module will record output to file '" << oFile.GetName() << "'" );
}
if( oParams.bOutputLevelMeterEnabled )
{
oRendererDesc.pOutputDetector = new ITAStreamDetector( pRendererOutputTail );
pRendererOutputTail = oRendererDesc.pOutputDetector;
}
// Setup the intermediate patchbay input [temporary]
int iInput = m_pR2RPatchbay->AddInput( pRendererOutputTail );
// Create direct output in output patchbay for each output group [todo, not allowed yet]
for( size_t i = 0; i < oParams.vsReproductions.size(); i++ )
{
const std::string& sOutputID( oParams.vsReproductions[ i ] );
const CVAHardwareOutput* pOutput = m_oCoreConfig.oHardwareSetup.GetOutput( sOutputID );
if( pOutput )
{
// Output found, use direct out (no renderer)
VA_EXCEPT2( NOT_IMPLEMENTED, "Direct output to an audio hardware group is currently not supported. Use the Talkthrough reproduction module instead." );
}
}
oRendererDesc.iR2RPatchBayInput = iInput;
oRendererDesc.vsOutputs = oParams.vsReproductions;
m_voRenderers.push_back( oRendererDesc );
}
}
cit++;
}
const size_t nNumRenderingModules = m_voRenderers.size();
if( nNumRenderingModules == 1 )
{
VA_INFO( "Core", "Started one rendering module" );
}
else
{
VA_INFO( "Core", "Started " << nNumRenderingModules << " rendering modules" );
}
for( size_t i = 0; i < nNumRenderingModules; i++ )
{
std::string sReproductionFeedStr = ( m_voRenderers[ i ].vsOutputs.size() == 1 ) ? "one reproduction module." : std::to_string( long( m_voRenderers[ i ].vsOutputs.size() ) ) + " reproduction modules.";
VA_INFO( "Core", " + " << m_voRenderers[ i ].sID << " (" << m_voRenderers[ i ].sClass << ") feeding " << sReproductionFeedStr );
}
}
void CVACoreImpl::InitializeReproductionModules()
{
CVAAudioReproductionRegistry* pRegistry( CVAAudioReproductionRegistry::GetInstance() );
const CVAStruct& oConfig( GetCoreConfig()->GetStruct() );
// Parse config for reproduction modules and try to instantiate them
CVAStruct::const_iterator cit = oConfig.Begin();
while( cit != oConfig.End() )
{
const std::string& sKey( cit->first );
const CVAStruct& oArgs( cit->second );
std::vector< std::string > vsKeyParts = splitString( sKey, ':' );
if( vsKeyParts.size() == 2 && cit->second.GetDatatype() == CVAStructValue::STRUCT )
{
std::string sCategory( toUppercase( vsKeyParts[ 0 ] ) );
if( sCategory == "REPRODUCTION" )
{
CVAConfigInterpreter conf( oArgs );
conf.SetErrorPrefix( "Configuration error in section \"" + cit->first + "\"" );
// Initialization parameters
CVAAudioReproductionInitParams oParams;
oParams.pCore = this;
oParams.pConfig = &cit->second.GetStruct();
oParams.sID = vsKeyParts[ 1 ];
conf.ReqString( "Class", oParams.sClass );
bool bEnabled;
conf.OptBool( "Enabled", bEnabled, true );
if( !bEnabled )
{
cit++;
continue; // Skip this entry
}
conf.OptBool( "InputDetectorEnabled", oParams.bInputDetectorEnabled, false );
conf.OptBool( "OutputDetectorEnabled", oParams.bOutputDetectorEnabled, false );
// Set up reproduction output recording
conf.OptBool( "RecordInputEnabled", oParams.bRecordInputEnabled, false );
if( oParams.bRecordInputEnabled )
{
VistaFileSystemFile oRecordInputFile( "reproduction.wav" );
VistaFileSystemDirectory oRecordInputFolder( "./" );
std::string sFilePathRAWDeprecated;
conf.OptString( "RecordInputFilePath", sFilePathRAWDeprecated );
if( !sFilePathRAWDeprecated.empty() )
{
VA_WARN( "Core", "The reproduction configuration key 'RecordInputFilePath' is deprecated. Use 'RecordInputBaseFolder' (optional) and 'RecordInputFileName' instead." );
std::string sDummy;
if( conf.OptString( "RecordInputBaseFolder", sDummy ) || conf.OptString( "RecordInputFileName", sDummy ) )
VA_EXCEPT2( INVALID_PARAMETER, "You have combined old reproduction configuration key 'RecordInputFilePath' with one of the new keys 'RecordInputBaseFolder' (optional) or 'RecordInputFileName'. Please use new key only." );
std::string sRecordInputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAWDeprecated );
oRecordInputFile.SetName( sRecordInputFilePath );
oRecordInputFolder.SetName( oRecordInputFile.GetParentDirectory() );
}
else
{
std::string sFileNameRAW;
conf.ReqString( "RecordInputFileName", sFileNameRAW );
std::string sFileName = m_oCoreConfig.mMacros.SubstituteMacros( sFileNameRAW );
oRecordInputFile.SetName( sFileName );
std::string sBaseFolderRAW;
conf.ReqString( "RecordInputBaseFolder", sBaseFolderRAW );
std::string sBaseFolder = m_oCoreConfig.mMacros.SubstituteMacros( sBaseFolderRAW );
oRecordInputFolder.SetName( sBaseFolder );
}
if( !oRecordInputFolder.Exists() )
{
if( oRecordInputFolder.CreateWithParentDirectories() )
{
VA_INFO( "Core", "Created reproduction input record base folder " << oRecordInputFolder.GetName() << " with parent directories" );
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent reproduction input record base folder '" + oRecordInputFolder.GetName() + "'" );
}
}
oParams.sRecordInputFileName = oRecordInputFile.GetLocalName();
oParams.sRecordInputBaseFolder = oRecordInputFolder.GetName();
}
// Set up reproduction output recording
conf.OptBool( "RecordOutputEnabled", oParams.bRecordOutputEnabled, false );
if( oParams.bRecordOutputEnabled )
{
VistaFileSystemFile oRecordOutputFile( "reproduction.wav" );
VistaFileSystemDirectory oRecordOutputBaseFolder( "./" );
std::string sFilePathRAWDeprecated;
conf.OptString( "RecordOutputFilePath", sFilePathRAWDeprecated );
if( !sFilePathRAWDeprecated.empty() )
{
VA_WARN( "Core", "The reproduction configuration key 'RecordOutputFilePath' is deprecated. Use 'RecordOutputBaseFolder' (optional) and 'RecordOutputFileName' instead." );
std::string sDummy;
if( conf.OptString( "RecordOutputBaseFolder", sDummy ) || conf.OptString( "RecordOutputFileName", sDummy ) )
VA_EXCEPT2( INVALID_PARAMETER, "You have combined old reproduction configuration key 'RecordOutputFilePath' with one of the new keys 'RecordOutputBaseFolder' (optional) or 'RecordOutputFileName'. Please use new key only." );
std::string sRecordOutputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAWDeprecated );
oRecordOutputFile.SetName( sRecordOutputFilePath );
oRecordOutputBaseFolder.SetName( oRecordOutputFile.GetParentDirectory() );
}
else
{
std::string sFileNameRAW;
conf.ReqString( "RecordOutputFileName", sFileNameRAW );
std::string sFileName = m_oCoreConfig.mMacros.SubstituteMacros( sFileNameRAW );
oRecordOutputFile.SetName( sFileName );
std::string sBaseFolderRAW;
conf.ReqString( "RecordOutputBaseFolder", sBaseFolderRAW );
std::string sBaseFolder = m_oCoreConfig.mMacros.SubstituteMacros( sBaseFolderRAW );
oRecordOutputBaseFolder.SetName( sBaseFolder );
}
if( !oRecordOutputBaseFolder.Exists() )
{
if( oRecordOutputBaseFolder.CreateWithParentDirectories() )
{
VA_INFO( "Core", "Created reproduction output record base folder " << oRecordOutputBaseFolder.GetName() << " with parent directories" );
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent reproduction output record base folder '" + oRecordOutputBaseFolder.GetName() + "'" );
}
}
oParams.sRecordOutputFileName = oRecordOutputFile.GetLocalName();
oParams.sRecordOutputBaseFolder = oRecordOutputBaseFolder.GetName();
}
// Parse outputs
std::vector< std::string > vsOutputs;
conf.ReqStringListRegex( "Outputs", vsOutputs, "\\s*,\\s*" );
std::unique( vsOutputs.begin(), vsOutputs.end() ); // Uniqueness, baby!
// Check outputs in hardware setup
std::vector< std::string >::const_iterator cjt = vsOutputs.begin();
while( cjt != vsOutputs.end() )
{
const std::string& sOutput( *cjt );
const CVAHardwareOutput* pOutput = m_oCoreConfig.oHardwareSetup.GetOutput( sOutput );
if( pOutput == nullptr )
conf.Error( "Referring to unknown output \"" + sOutput + "\"" );
oParams.vpOutputs.push_back( pOutput );
cjt++;
}
// Register this reproduction module
IVAAudioReproductionFactory* pFactory = pRegistry->FindFactory( oParams.sClass );
if( !pFactory )
conf.Error( "Unknown class \"" + oParams.sClass + "\"" );
// Create the module
CVAAudioReproductionModuleDesc oDesc( pFactory->Create( oParams ) );
oDesc.sID = oParams.sID;
oDesc.sClass = oParams.sClass;
oDesc.vpOutputs = oParams.vpOutputs;
oDesc.bEnabled = bEnabled;
// Add output in Renderer-to-Reproduction patch bay
int iReproductionModuleNumInputChannels = oDesc.pInstance->GetNumInputChannels();
oDesc.iR2RPatchBayOutput = m_pR2RPatchbay->AddOutput( iReproductionModuleNumInputChannels );
ITADatasource* pInputTail = m_pR2RPatchbay->GetOutputDatasource( oDesc.iR2RPatchBayOutput );
if( oParams.bInputDetectorEnabled )
{
oDesc.pInputDetector = new ITAStreamDetector( pInputTail );
pInputTail = oDesc.pInputDetector;
}
if( oParams.bRecordInputEnabled )
{
std::string sFilePath = oParams.sRecordInputBaseFolder + "/" + oParams.sRecordInputFileName;
VistaFileSystemFile oFile( sFilePath );
if( oFile.Exists() )
VA_INFO( "Core", "Reproduction input record file '" << oFile.GetName() << "' exists, will overwrite" );
oDesc.pInputRecorder = new ITAStreamProbe( pInputTail, oFile.GetName() );
pInputTail = oDesc.pInputRecorder;
VA_TRACE( "Core", "Reproduction will record input to file '" << oFile.GetName() << "'" );
}
// Assign Renderer-to-Reproduction patch bay output datasource as input for reproduction module
oDesc.pInstance->SetInputDatasource( pInputTail );
ITADatasource* pOutputTail = oDesc.pInstance->GetOutputDatasource();
if( oParams.bOutputDetectorEnabled )
{
oDesc.pOutputDetector = new ITAStreamDetector( pOutputTail );
pOutputTail = oDesc.pOutputDetector;
}
if( oParams.bRecordOutputEnabled )
{
std::string sFilePath = oParams.sRecordOutputBaseFolder + "/" + oParams.sRecordOutputFileName;
VistaFileSystemFile oFile( sFilePath );
if( oFile.Exists() )
VA_INFO( "Core", "Reproduction output record file '" << oFile.GetName() << "' exists, will overwrite" );
oDesc.pOutputRecorder = new ITAStreamProbe( pOutputTail, oFile.GetName() );
pOutputTail = oDesc.pOutputRecorder;
VA_TRACE( "Core", "Reproduction will record output to file '" << oFile.GetName() << "'" );
}
// Add input in output patch bay and assign reproduction module datasource output to this input
oDesc.iOutputPatchBayInput = m_pOutputPatchbay->AddInput( pOutputTail );
// TODO: Active umsetzen ggf. in Params rein
m_voReproductionModules.push_back( oDesc );
}
}
cit++;
}
const size_t nNumReproductionModules = m_voReproductionModules.size();
if( nNumReproductionModules == 1 )
{
VA_INFO( "Core", "Started one reproduction module" );
}
else
{
VA_INFO( "Core", "Started " << nNumReproductionModules << " reproduction modules" );
}
for( size_t i = 0; i < nNumReproductionModules; i++ )
{
std::string sOutputGroupFeedStr = ( m_voReproductionModules[ i ].vpOutputs.size() == 1 ) ? "one output group." : std::to_string( long( m_voReproductionModules[ i ].vpOutputs.size() ) ) + " output groups.";
VA_INFO( "Core", " + " << m_voReproductionModules[ i ].sID << " (" << m_voReproductionModules[ i ].sClass << ") feeding " << sOutputGroupFeedStr );
}
return;
}
void CVACoreImpl::PatchRendererToReproductionModules()
{
std::vector<CVAAudioRendererDesc>::iterator rendit = m_voRenderers.begin();
while( rendit != m_voRenderers.end() )
{
const CVAAudioRendererDesc& renddesc( *rendit );
int iRendererNumOutputChannels = renddesc.pInstance->GetOutputDatasource()->GetNumberOfChannels();
int iRendererR2RPatchBayInput = renddesc.iR2RPatchBayInput;
// Iterate over all target reproduction modules
std::vector< std::string >::const_iterator ocit = renddesc.vsOutputs.begin();
while( ocit != renddesc.vsOutputs.end() )
{
const std::string& sTargetReproductionModule( *ocit );
std::vector< CVAAudioReproductionModuleDesc >::const_iterator repcit = m_voReproductionModules.begin();
while( repcit != m_voReproductionModules.end() )
{
const CVAAudioReproductionModuleDesc& repdesc( *repcit );
if( repdesc.sID == sTargetReproductionModule )
{
// Get R2R patch bay output of target reproduction module and patch channels from renderer input
for( int k = 0; k < iRendererNumOutputChannels; k++ )
m_pR2RPatchbay->ConnectChannels( iRendererR2RPatchBayInput, k, repdesc.iR2RPatchBayOutput, k );
break; // break after target reproduction module is patched and continue with next
}
repcit++;
}
ocit++;
}
rendit++;
}
return;
}
void CVACoreImpl::PatchReproductionModulesToOutput()
{
int iMaxPhysicalChannelsAvailable = m_pOutputPatchbay->GetOutputNumChannels( 0 );
std::vector<CVAAudioReproductionModuleDesc>::iterator it = m_voReproductionModules.begin();
while( it != m_voReproductionModules.end() )
{
CVAAudioReproductionModuleDesc& oRepDesc( *it );
std::vector< const CVAHardwareOutput* >::iterator jt = oRepDesc.vpOutputs.begin();
while( jt != oRepDesc.vpOutputs.end() )
{
const CVAHardwareOutput* pOutput( *jt );
// Only consider outputs for patching, that are set enabled via configuration
if( pOutput->IsEnabled() == false )
{
jt++;
continue;
}
for( size_t k = 0; k < pOutput->GetPhysicalOutputChannels().size(); k++ )
{
int iPhysicalOutputChannel = pOutput->GetPhysicalOutputChannels()[ k ] - 1;
if( iPhysicalOutputChannel < iMaxPhysicalChannelsAvailable )
m_pOutputPatchbay->ConnectChannels( oRepDesc.iOutputPatchBayInput, int( k ), 0, iPhysicalOutputChannel );
else
VA_EXCEPT2( INVALID_PARAMETER, "VACore/ConnectRendererWithReproductionModules: Group '" +
pOutput->sIdentifier + "' output channel out of range for this sound card" );
}
jt++;
}
it++;
}
return;
}
void CVACoreImpl::RecursiveFileList( const std::string& sBasePath, CVAStruct& oFileList, const std::string sFileSuffixMask ) const
{
std::vector< std::string > vsFileList;
FileList( sBasePath, vsFileList, sFileSuffixMask );
CVAStruct oMoreFiles;
for( size_t j = 0; j < vsFileList.size(); j++ )
oMoreFiles[ std::to_string( long( j ) ) ] = vsFileList[ j ];
oFileList[ sBasePath ] = oMoreFiles;
std::vector< std::string > vsFolderList;
FolderList( sBasePath, vsFolderList );
for( size_t j = 0; j < vsFolderList.size(); j++ )
RecursiveFileList( vsFolderList[ j ], oFileList, sFileSuffixMask );
}
void CVACoreImpl::FolderList( const std::string& sBasePath, std::vector< std::string >& vsFolderList ) const
{
vsFolderList.clear();
VistaFileSystemDirectory oFolder( sBasePath );
if( !oFolder.Exists() || !oFolder.IsDirectory() )
return;
VistaFileSystemDirectory::const_iterator cit = oFolder.begin();
while( cit != oFolder.end() )
{
VistaFileSystemNode* pNode( *cit++ );
if( pNode->IsDirectory() && pNode->GetLocalName() != "." && pNode->GetLocalName() != ".." )
vsFolderList.push_back( pNode->GetName() );
}
}
void CVACoreImpl::FileList( const std::string& sBasePath, std::vector< std::string >& vsFileList, const std::string& sFileSuffixMask ) const
{
vsFileList.clear();
VistaFileSystemDirectory oFolder( sBasePath );
if( !oFolder.Exists() || !oFolder.IsDirectory() )
return;
VistaFileSystemDirectory::const_iterator cit = oFolder.begin();
while( cit != oFolder.end() )
{
VistaFileSystemNode* pNode( *cit++ );
if( pNode->IsFile() )
{
const std::string sFileName = pNode->GetLocalName();
if( sFileSuffixMask != "*" && !sFileSuffixMask.empty() )
{
if( sFileName.substr( sFileName.find_last_of( "." ) + 1 ).compare( sFileSuffixMask ) )
vsFileList.push_back( pNode->GetName() );
}
else
vsFileList.push_back( pNode->GetName() );
}
}
}
// --= Progress =---------------------------------------------------
ITACriticalSection m_csProgress;
CVAProgress m_Progress;
void CVACoreImpl::InitProgress( const std::string& sAction, const std::string& sSubaction, const int iMaxStep )
{
m_csProgress.enter();
m_Progress.sAction = sAction;
m_Progress.sSubaction = sSubaction;
m_Progress.iCurrentStep = 0;
m_Progress.iMaxStep = iMaxStep;
// Fortschritts-Ereignis senden
CVAEvent ev;
ev.iEventType = CVAEvent::PROGRESS_UPDATE;
ev.pSender = this;
ev.oProgress = m_Progress;
m_pEventManager->BroadcastEvent( ev );
m_csProgress.leave();
}
void CVACoreImpl::SetProgress( const std::string& sAction, const std::string& sSubaction, const int iCurrentStep )
{
m_csProgress.enter();
m_Progress.sAction = sAction;
m_Progress.sSubaction = sSubaction;
m_Progress.iCurrentStep = iCurrentStep;
// Fortschritts-Ereignis senden
CVAEvent ev;
ev.iEventType = CVAEvent::PROGRESS_UPDATE;
ev.pSender = this;
ev.oProgress = m_Progress;
m_pEventManager->BroadcastEvent( ev );
m_csProgress.leave();
}
void CVACoreImpl::FinishProgress()
{
m_csProgress.enter();
// Die Aktionen bleiben, nur die aktuelle Schritt = maximaler Schritt
m_Progress.iCurrentStep = m_Progress.iMaxStep;
// Fortschritts-Ereignis senden
CVAEvent ev;
ev.iEventType = CVAEvent::PROGRESS_UPDATE;
ev.pSender = this;
ev.oProgress = m_Progress;
m_pEventManager->BroadcastEvent( ev );
m_csProgress.leave();
}
/* +----------------------------------------------------------+ *
* | | *
* | Core-Thread | *
* | | *
* +----------------------------------------------------------+ */
void CVACoreImpl::CoreThreadLoop()
{
m_oCoreThreadLoopTotalDuration.start();
assert( m_pCurSceneState != nullptr );
assert( m_pCurSceneState->GetNumReferences() >= 1 );
// Auf nderungen der Szene berprfen
CVASceneState* pNewSceneState = m_pSceneManager->GetHeadSceneState();
assert( pNewSceneState != nullptr );
assert( pNewSceneState->GetNumReferences() >= 1 );
pNewSceneState->AddReference();
// TODO: Aktiver Hrer wird erstmal ignoriert.
//int iNewActiveListener = m_iNewActiveListener;
if( pNewSceneState != m_pCurSceneState )
{
VA_TRACE( "CoreThread", "Update scene state " << m_pCurSceneState->GetID() << " -> " << pNewSceneState->GetID() );
// Audio renderer
std::vector< CVAAudioRendererDesc >::iterator rendit = m_voRenderers.begin();
while( rendit != m_voRenderers.end() )
{
CVAAudioRendererDesc& rendesc( *rendit );
rendesc.pInstance->UpdateScene( pNewSceneState );
rendit++;
}
// Audio reproduction modules
std::vector< CVAAudioReproductionModuleDesc >::iterator repit = m_voReproductionModules.begin();
while( repit != m_voReproductionModules.end() )
{
CVAAudioReproductionModuleDesc& repdesc( *repit );
repdesc.pInstance->UpdateScene( pNewSceneState );
repit++;
}
}
// nderung des globalen Auralisierungsmodus in den Schallpfaden bercksichtigen
/**
* Da es keine Versionierung des AuraModes gibt, muss der Audio
* Renderer selbst entscheiden, was zu tun ist.
*/
std::vector< CVAAudioRendererDesc >::iterator rendit = m_voRenderers.begin();
while( rendit != m_voRenderers.end() )
{
CVAAudioRendererDesc& rendesc( *rendit );
rendesc.pInstance->UpdateGlobalAuralizationMode( m_iGlobalAuralizationMode );
rendit++;
}
// Referenzen verwalten: Alter Szenezustand wird nun nicht mehr bentigt
if( m_pCurSceneState != pNewSceneState )
{
// Alter Zustand wird nicht mehr bentigt
m_pCurSceneState->RemoveReference();
// Aktuelle Szene ist nun die neu erzeugte (abgeleitete) Szene
m_pCurSceneState = pNewSceneState;
}
else
{
// Remove reference of new/current state again
pNewSceneState->RemoveReference();
}
m_oCoreThreadLoopTotalDuration.stop();
// @todo: signal event to process object calls (in-sync exec with internal core)
return;
}
void CVACoreImpl::SendAudioDeviceDetectorUpdateEvent()
{
CVAEvent ev;
ev.iEventType = CVAEvent::MEASURES_UPDATE;
ev.pSender = this;
if( m_pInputStreamDetector )
{
ev.vfInputPeaks.resize( m_oCoreConfig.oAudioDriverConfig.iInputChannels );
m_pInputStreamDetector->GetPeaks( ev.vfInputPeaks, true );
ev.vfInputRMSs.resize( m_oCoreConfig.oAudioDriverConfig.iInputChannels );
m_pInputStreamDetector->GetRMSs( ev.vfInputRMSs, true );
}
if( m_pOutputStreamDetector )
{
ev.vfOutputPeaks.resize( m_oCoreConfig.oAudioDriverConfig.iOutputChannels );
m_pOutputStreamDetector->GetPeaks( ev.vfOutputPeaks, true );
ev.vfOutputRMSs.resize( m_oCoreConfig.oAudioDriverConfig.iOutputChannels );
m_pOutputStreamDetector->GetRMSs( ev.vfOutputRMSs, true );
}
ev.fSysLoad = 0;
// TODO: Sollte am Ende gemessen werden! => StreamTracker
ev.fDSPLoad = 0;
//ev.fDSPLoad = m_pAudiostreamProcessor->GetDSPLoad();
m_pEventManager->BroadcastEvent( ev );
}
void CVACoreImpl::SendRenderingModuleOutputDetectorsUpdateEvents()
{
for( size_t i = 0; i < m_voRenderers.size(); i++ )
{
CVAAudioRendererDesc& oRenderer( m_voRenderers[ i ] );
CVAEvent ev;
ev.iEventType = CVAEvent::MEASURES_UPDATE;
ev.pSender = this;
ev.sObjectID = oRenderer.sID;
ev.sParam = "RenderingModule"; // Use generic parameter slot to mark rendering module source
if( oRenderer.pOutputDetector )
{
ev.vfOutputRMSs.resize( oRenderer.pOutputDetector->GetNumberOfChannels() );
oRenderer.pOutputDetector->GetRMSs( ev.vfOutputRMSs, true );
ev.vfOutputPeaks.resize( oRenderer.pOutputDetector->GetNumberOfChannels() );
oRenderer.pOutputDetector->GetPeaks( ev.vfOutputPeaks, true );
}
m_pEventManager->BroadcastEvent( ev );
}
}
void CVACoreImpl::SendReproductionModuleOIDetectorsUpdateEvents()
{
for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
{
CVAAudioReproductionModuleDesc& oReproduction( m_voReproductionModules[ i ] );
CVAEvent ev;
ev.iEventType = CVAEvent::MEASURES_UPDATE;
ev.pSender = this;
ev.sObjectID = oReproduction.sID;
ev.sParam = "ReproductionModule"; // Use generic parameter slot to mark reproduction module source
if( oReproduction.pInputDetector )
{
ev.vfInputRMSs.resize( oReproduction.pInputDetector->GetNumberOfChannels() );
oReproduction.pInputDetector->GetRMSs( ev.vfInputRMSs, true );
ev.vfInputPeaks.resize( oReproduction.pInputDetector->GetNumberOfChannels() );
oReproduction.pInputDetector->GetPeaks( ev.vfInputPeaks, true );
}
if( oReproduction.pOutputDetector )
{
ev.vfOutputRMSs.resize( oReproduction.pOutputDetector->GetNumberOfChannels() );
oReproduction.pOutputDetector->GetRMSs( ev.vfOutputRMSs, true );
ev.vfOutputPeaks.resize( oReproduction.pOutputDetector->GetNumberOfChannels() );
oReproduction.pOutputDetector->GetPeaks( ev.vfOutputPeaks, true );
}
m_pEventManager->BroadcastEvent( ev );
}
}
bool CVACoreImpl::operator()()
{
#ifndef DO_NOT_SEND_MEASURE_UPDATE_EVENTS
// Audio device I/O detectors
SendAudioDeviceDetectorUpdateEvent();
// Rendering module output detectors
SendRenderingModuleOutputDetectorsUpdateEvents();
// Rerproduction module I/O detectors
SendReproductionModuleOIDetectorsUpdateEvents();
return true;
#else
return false;
#endif
}
CVAObjectInfo CVACoreImpl::GetObjectInfo() const
{
CVAObjectInfo oCoreModuleInfo;
oCoreModuleInfo.iID = GetObjectID();
oCoreModuleInfo.sName = GetObjectName();
oCoreModuleInfo.sDesc = "VA core module";
return oCoreModuleInfo;
}
// Handle calls to the kernel from the module interface
CVAStruct CVACoreImpl::CallObject( const CVAStruct& oArgs )
{
VA_VERBOSE( "Core", "Core module has been called" );
CVAStruct oReturn;
if( oArgs.HasKey( "help" ) || oArgs.HasKey( "info" ) || oArgs.IsEmpty() )
{
oReturn[ "help" ] = "Get comprehensive help online at http://www.virtualacoustics.org ...";
oReturn[ "version" ] = "Returns version information";
oReturn[ "addsearchpath" ] = "Adds a search path";
oReturn[ "getsearchpaths" ] = "Returns all search paths";
oReturn[ "getloglevel" ] = "Returns current core log level (integer)";
oReturn[ "setloglevel" ] = "Sets current core log level (integer)";
oReturn[ "structrebound" ] = "Rebounds argument of any content to client (for testing VA structs)";
}
if( oArgs.HasKey( "version" ) )
{
CVAVersionInfo oVersionInfo;
GetVersionInfo( &oVersionInfo );
oReturn[ "comments" ] = oVersionInfo.sComments;
oReturn[ "date" ] = oVersionInfo.sDate;
oReturn[ "flags" ] = oVersionInfo.sFlags;
oReturn[ "version" ] = oVersionInfo.sVersion;
oReturn[ "string" ] = oVersionInfo.ToString();
}
if( oArgs.HasKey( "addsearchpath" ) )
{
if( oArgs[ "addsearchpath" ].IsString() )
{
std::string sPath = oArgs[ "addsearchpath" ];
VistaFileSystemDirectory oDir( sPath );
oReturn[ "pathvalid" ] = false;
if( oDir.Exists() )
{
m_oCoreConfig.vsSearchPaths.push_back( sPath );
oReturn[ "pathvalid" ] = true;
}
}
}
if( oArgs.HasKey( "getsearchpaths" ) )
{
CVAStruct oSearchPaths;
for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
oSearchPaths[ "path_" + std::to_string( long( i ) ) ] = m_oCoreConfig.vsSearchPaths[ i ];
oReturn[ "searchpaths" ] = oSearchPaths;
}
if( oArgs.HasKey( "getmacros" ) )
{
CVAStruct oMacros;
for( auto& macro : m_oCoreConfig.mMacros.GetMacroMapCopy() )
oMacros[ macro.first ] = macro.second;
oReturn[ "macros" ] = oMacros;
}
if( oArgs.HasKey( "getloglevel" ) )
{
oReturn[ "loglevel" ] = VALog_GetLogLevel();
}
if( oArgs.HasKey( "setloglevel" ) )
{
int iLogLevel = oArgs[ "setloglevel" ];
VALog_SetLogLevel( iLogLevel );
}
if( oArgs.HasKey( "structrebound" ) )
{
oReturn = oArgs[ "structrebound" ];
}
if( oArgs.HasKey( "shutdown" ) || oArgs.HasKey( "finalize" ) || oArgs.HasKey( "stop" ) )
{
VA_WARN( "Core", "Received shutdown request" );
if( GetCoreConfig()->bRemoteShutdownAllowed )
{
VA_TRACE( "Core", "Accepting remote shutdown request, will broadcast shutdown event" );
CVAEvent ev;
ev.pSender = this;
ev.iEventType = CVAEvent::SHOTDOWN_REQUEST;
ev.sParam = "shutdown";
m_pEventManager->BroadcastEvent( ev );
VA_TRACE( "Core", "Shutdown performed" );
}
else
{
VA_WARN( "Core", "Shutdown request denied, the core configuration does not accept a remote shutdown" );
}
}
bool bUpdateRecordInputPath = false;
if( oArgs.HasKey( "Audio device/RecordInputFileName" ) )
{
m_oCoreConfig.sRecordDeviceInputFileName = oArgs[ "Audio device/RecordInputFileName" ];
bUpdateRecordInputPath = true;
}
if( oArgs.HasKey( "Audio device/RecordInputBaseFolder" ) )
{
m_oCoreConfig.sRecordDeviceInputBaseFolder = oArgs[ "Audio device/RecordInputBaseFolder" ];
bUpdateRecordInputPath = true;
}
if( bUpdateRecordInputPath )
{
VistaFileSystemFile oFile( m_oCoreConfig.sRecordDeviceInputFileName );
VistaFileSystemDirectory oFolder( m_oCoreConfig.sRecordDeviceInputBaseFolder );
VistaFileSystemFile oFilePath( oFolder.GetName() + "/" + oFile.GetLocalName() );
VA_INFO( "Core", "Updating record device input file path to " << oFilePath.GetName() );
if( oFilePath.Exists() )
VA_INFO( "Core", "Record device input file path exists, will overwrite" );
if( !oFolder.Exists() )
if( !oFolder.CreateWithParentDirectories() )
VA_EXCEPT2( INVALID_PARAMETER, "Could not create record device output directory " + oFolder.GetName() );
m_pStreamProbeDeviceInput->SetFilePath( oFilePath.GetName() );
}
bool bUpdateRecordOutputPath = false;
if( oArgs.HasKey( "Audio device/RecordOutputFileName" ) )
{
m_oCoreConfig.sRecordDeviceOutputFileName = oArgs[ "Audio device/RecordOutputFileName" ];
bUpdateRecordOutputPath = true;
}
if( oArgs.HasKey( "Audio device/RecordOutputBaseFolder" ) )
{
m_oCoreConfig.sRecordDeviceOutputBaseFolder = oArgs[ "Audio device/RecordOutputBaseFolder" ];
bUpdateRecordOutputPath = true;
}
if( bUpdateRecordOutputPath )
{
VistaFileSystemFile oFile( m_oCoreConfig.sRecordDeviceOutputFileName );
VistaFileSystemDirectory oFolder( m_oCoreConfig.sRecordDeviceOutputBaseFolder );
VistaFileSystemFile oFilePath( oFolder.GetName() + "/" + oFile.GetLocalName() );
VA_INFO( "Core", "Updating record device output file path to " << oFilePath.GetName() );
if( oFilePath.Exists() )
VA_INFO( "Core", "Record device output file path exists, will overwrite" );
if( !oFolder.Exists() )
if( !oFolder.CreateWithParentDirectories() )
VA_EXCEPT2( INVALID_PARAMETER, "Could not create record device output directory " + oFolder.GetName() );
m_pStreamProbeDeviceOutput->SetFilePath( oFilePath.GetName() );
}
VA_VERBOSE( "Core", "Core module will transmit answer now" );
return oReturn;
}
const CVACoreConfig* CVACoreImpl::GetCoreConfig() const
{
return &m_oCoreConfig;
}
const CVASceneManager* CVACoreImpl::GetSceneManager() const
{
return m_pSceneManager;
}
const CVAAudioSignalSourceManager* CVACoreImpl::GetSignalSourceManager() const
{
return m_pSignalSourceManager;
}
void CVACoreImpl::SetRenderingModuleMuted( const std::string& sModuleID, const bool bMuted )
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
{
m_pR2RPatchbay->SetInputMuted( oRend.iR2RPatchBayInput, bMuted );
return;
}
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
}
void CVACoreImpl::SetRenderingModuleGain( const std::string& sModuleID, const double dGain )
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
{
m_pR2RPatchbay->SetInputGain( oRend.iR2RPatchBayInput, dGain );
return;
}
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
}
double CVACoreImpl::GetRenderingModuleGain( const std::string& sModuleID ) const
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
return m_pR2RPatchbay->GetInputGain( oRend.iR2RPatchBayInput );
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
return 0.0f;
}
void CVACoreImpl::SetRenderingModuleAuralizationMode( const std::string& sModuleID, const int iAM )
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
{
oRend.pInstance->UpdateGlobalAuralizationMode( iAM );
return;
}
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
}
int CVACoreImpl::GetRenderingModuleAuralizationMode( const std::string& sModuleID ) const
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
return oRend.pInstance->GetAuralizationMode();
}
VA_EXCEPT2( INVALID_PARAMETER, "Could not find rendering module '" + sModuleID + "'" );
}
bool CVACoreImpl::GetRenderingModuleMuted( const std::string& sModuleID ) const
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
return m_pR2RPatchbay->IsInputMuted( oRend.iR2RPatchBayInput );
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
return true;
}
void CVACoreImpl::SetReproductionModuleMuted( const std::string& sModuleID, const bool bMuted )
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
if( oRepro.sID == sModuleID )
{
m_pOutputPatchbay->SetInputMuted( oRepro.iOutputPatchBayInput, bMuted );
return;
}
}
VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
}
void CVACoreImpl::SetReproductionModuleGain( const std::string& sModuleID, const double dGain )
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
if( oRepro.sID == sModuleID )
{
m_pOutputPatchbay->SetInputGain( oRepro.iOutputPatchBayInput, dGain );
return;
}
}
VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
}
double CVACoreImpl::GetReproductionModuleGain( const std::string& sModuleID ) const
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
if( oRepro.sID == sModuleID )
return m_pOutputPatchbay->GetInputGain( oRepro.iOutputPatchBayInput );
}
VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
return 0.0f;
}
bool CVACoreImpl::GetReproductionModuleMuted( const std::string& sModuleID ) const
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
if( oRepro.sID == sModuleID )
return m_pOutputPatchbay->IsInputMuted( oRepro.iOutputPatchBayInput );
}
VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
return true;
}
void CVACoreImpl::GetRenderingModules( std::vector< CVAAudioRendererInfo >& vRenderers, const bool bFilterEnabled /* = true */ ) const
{
vRenderers.clear();
for( size_t i = 0; i < m_voRenderers.size(); i++ )
{
const CVAAudioRendererDesc& oRenderer( m_voRenderers[ i ] );
CVAAudioRendererInfo oRendererInfo;
oRendererInfo.sID = oRenderer.sID;
oRendererInfo.sClass = oRenderer.sClass;
oRendererInfo.sDescription = oRendererInfo.sDescription;
oRendererInfo.bEnabled = oRenderer.bEnabled;
oRendererInfo.bOutputDetectorEnabled = oRenderer.bOutputDetectorEnabled;
oRendererInfo.oParams = oRenderer.oParams;
oRendererInfo.sOutputRecordingFilePath = oRenderer.pOutputRecorder->GetFilePath();
if( !bFilterEnabled || oRendererInfo.bEnabled )
vRenderers.push_back( oRendererInfo );
}
}
void CVACoreImpl::SetReproductionModuleParameters( const std::string& sModuleID, const CVAStruct& oParams )
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRep( m_voReproductionModules[ n ] );
if( oRep.sID == sModuleID )
{
// Check for recording parameters and apply if necessary
if( oParams.HasKey( "RecordInputEnabled" ) )
VA_EXCEPT2( INVALID_PARAMETER, "Recording has to be enabled before streaming is active" );
VistaFileSystemFile oFilePath( oRep.pInputRecorder->GetFilePath() );
std::string sFileName = oFilePath.GetLocalName();
std::string sBaseFolder = oFilePath.GetParentDirectory();
bool bUpdateRecordInputPath = false;
if( oParams.HasKey( "RecordInputFileName" ) )
{
sFileName = oParams[ "RecordInputFileName" ];
bUpdateRecordInputPath = true;
}
if( oParams.HasKey( "RecordInputBaseFolder" ) )
{
sBaseFolder = oParams[ "RecordInputBaseFolder" ];
bUpdateRecordInputPath = true;
}
if( bUpdateRecordInputPath )
{
VistaFileSystemFile oFile( sFileName );
VistaFileSystemDirectory oFolder( sBaseFolder );
VistaFileSystemFile oFilePath( oFolder.GetName() + "/" + oFile.GetLocalName() );
VA_INFO( "Core", "Updating reproduction input recording file path to " << oFilePath.GetName() );
if( oFilePath.Exists() )
VA_INFO( "Core", "Record reproduction input recording file path exists, will overwrite" );
if( !oFolder.Exists() )
if( !oFolder.CreateWithParentDirectories() )
VA_EXCEPT2( INVALID_PARAMETER, "Could not create reproduction input recording directory " + oFolder.GetName() );
oRep.pInputRecorder->SetFilePath( oFilePath.GetName() );
}
if( oParams.HasKey( "RecordOutputEnabled" ) )
VA_EXCEPT2( INVALID_PARAMETER, "Recording has to be enabled before streaming is active" );
oFilePath.SetName( oRep.pOutputRecorder->GetFilePath() );
sFileName = oFilePath.GetLocalName();
sBaseFolder = oFilePath.GetParentDirectory();
bool bUpdateRecordOutputPath = false;
if( oParams.HasKey( "RecordOutputFileName" ) )
{
sFileName = oParams[ "RecordOutputFileName" ];
bUpdateRecordOutputPath = true;
}
if( oParams.HasKey( "RecordOutputBaseFolder" ) )
{
sBaseFolder = oParams[ "RecordOutputBaseFolder" ];
bUpdateRecordOutputPath = true;
}
if( bUpdateRecordOutputPath )
{
VistaFileSystemFile oFile( sFileName );
VistaFileSystemDirectory oFolder( sBaseFolder );
VistaFileSystemFile oFilePath( oFolder.GetName() + "/" + oFile.GetLocalName() );
VA_INFO( "Core", "Updating reproduction output recording file path to " << oFilePath.GetName() );
if( oFilePath.Exists() )
VA_INFO( "Core", "Record reproduction output recording file path exists, will overwrite" );
if( !oFolder.Exists() )
if( !oFolder.CreateWithParentDirectories() )
VA_EXCEPT2( INVALID_PARAMETER, "Could not create reproduction output recording directory " + oFolder.GetName() );
oRep.pOutputRecorder->SetFilePath( oFilePath.GetName() );
}
// Propagate parameters
oRep.pInstance->SetParameters( oParams );
return;
}
}
VA_ERROR( "Core", "Could not find Reproduction module '" << sModuleID << "'" );
}
CVAStruct CVACoreImpl::GetReproductionModuleParameters( const std::string& sModuleID, const CVAStruct& oParams ) const
{
for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
{
const CVAAudioReproductionModuleDesc& oRep( m_voReproductionModules[ n ] );
if( oRep.sID == sModuleID )
return oRep.pInstance->GetParameters( oParams );
}
VA_ERROR( "Core", "Could not find Reproduction module '" << sModuleID << "'" );
return CVAStruct();
}
void CVACoreImpl::GetReproductionModules( std::vector< CVAAudioReproductionInfo >& vRepros, const bool bFilterEnabled /* = true */ ) const
{
vRepros.clear();
for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
{
const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ i ] );
CVAAudioReproductionInfo oRepInfo;
oRepInfo.sID = oRepro.sID;
oRepInfo.sClass = oRepro.sClass;
oRepInfo.sDescription = oRepro.sDescription;
oRepInfo.bEnabled = oRepro.bEnabled;
oRepInfo.bInputDetectorEnabled = oRepro.bInputDetectorEnabled;
oRepInfo.sInputRecordingFilePath = oRepro.pInputRecorder->GetFilePath();
oRepInfo.bOutputDetectorEnabled = oRepro.bOutputDetectorEnabled;
oRepInfo.sOutputRecordingFilePath = oRepro.pOutputRecorder->GetFilePath();
oRepInfo.oParams = oRepro.oParams;
if( !bFilterEnabled || oRepInfo.bEnabled )
vRepros.push_back( oRepInfo );
}
}
void CVACoreImpl::SetRenderingModuleParameters( const std::string& sModuleID, const CVAStruct& oParams )
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
{
// Check for recording parameters and apply if necessary
if( oParams.HasKey( "RecordOutputEnabled" ) )
VA_EXCEPT2( INVALID_PARAMETER, "Recording has to be enabled before streaming is active" );
VistaFileSystemFile oFilePath( oRend.pOutputRecorder->GetFilePath() );
std::string sFileName = oFilePath.GetLocalName();
std::string sBaseFolder = oFilePath.GetParentDirectory();
bool bUpdateRecordOutputPath = false;
if( oParams.HasKey( "RecordOutputFileName" ) )
{
sFileName = oParams[ "RecordOutputFileName" ];
bUpdateRecordOutputPath = true;
}
if( oParams.HasKey( "RecordOutputBaseFolder" ) )
{
sBaseFolder = oParams[ "RecordOutputBaseFolder" ];
bUpdateRecordOutputPath = true;
}
if( bUpdateRecordOutputPath )
{
VistaFileSystemFile oFile( sFileName );
VistaFileSystemDirectory oFolder( sBaseFolder );
VistaFileSystemFile oFilePath( oFolder.GetName() + "/" + oFile.GetLocalName() );
VA_INFO( "Core", "Updating rendering output recording file path to " << oFilePath.GetName() );
if( oFilePath.Exists() )
VA_INFO( "Core", "Record rendering output recording file path exists, will overwrite" );
if( !oFolder.Exists() )
if( !oFolder.CreateWithParentDirectories() )
VA_EXCEPT2( INVALID_PARAMETER, "Could not create rendering output recording directory " + oFolder.GetName() );
oRend.pOutputRecorder->SetFilePath( oFilePath.GetName() );
}
// Propagate parameters
oRend.pInstance->SetParameters( oParams );
return;
}
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
}
CVAStruct CVACoreImpl::GetRenderingModuleParameters( const std::string& sModuleID, const CVAStruct& oParams ) const
{
for( size_t n = 0; n < m_voRenderers.size(); n++ )
{
const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
if( oRend.sID == sModuleID )
return oRend.pInstance->GetParameters( oParams );
}
VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
return CVAStruct();
}