diff --git a/src/core/_SourceFiles.cmake b/src/core/_SourceFiles.cmake index 93d6c76eefb60297e42daf8fa4447badf9139e73..a9061e641395689be67768136d2b9246004de32b 100644 --- a/src/core/_SourceFiles.cmake +++ b/src/core/_SourceFiles.cmake @@ -3,12 +3,34 @@ set( RelativeSourceGroup "src\\core" ) set( SubDirs ) set( DirFiles + clock.cpp + config.cpp + control.cpp core.h core.cpp directivity.cpp + events.cpp + file_handling.cpp + finalize.cpp geometry.cpp - init.cpp + homogeneous_medium.cpp + initialize.cpp + locking.cpp material.cpp + module.cpp + object.cpp + progress.cpp + rendering.cpp + reproduction.cpp + reset.cpp + scene.cpp + signal_source.cpp + sound_portal.cpp + sound_receiver.cpp + sound_source.cpp + state.cpp + thread_loop.cpp + version.cpp _SourceFiles.cmake ) set( DirFiles_SourceGroup "${RelativeSourceGroup}" ) diff --git a/src/core/clock.cpp b/src/core/clock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d58ee1578779ff38b808f3b7d4a1c81d68d296bc --- /dev/null +++ b/src/core/clock.cpp @@ -0,0 +1,45 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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; +} diff --git a/src/core/config.cpp b/src/core/config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec9d6a7beb63d0b353521e4d3e93efcffc2a8e7c --- /dev/null +++ b/src/core/config.cpp @@ -0,0 +1,143 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +const CVACoreConfig* CVACoreImpl::GetCoreConfig() const +{ + return &m_oCoreConfig; +} + +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; +} + +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(); +} diff --git a/src/core/control.cpp b/src/core/control.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c5561b1d55a21c24b479f1bd213c3df191396bc --- /dev/null +++ b/src/core/control.cpp @@ -0,0 +1,211 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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; +} diff --git a/src/core/core.cpp b/src/core/core.cpp index 5c851e01a53be2d1ac97d27456b5da42b3d094eb..febb7ae724ea8128ffdf0e052628861d369b9cad 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -19,105 +19,6 @@ IVAInterface* VACore::CreateCoreInstance( const CVAStruct& oArgs, std::ostream* 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 ) @@ -226,134 +127,6 @@ void CVACoreImpl::SetOutputStream( std::ostream* 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 möglich. Unabhängig vom Zustand. Thread-safety wird im Manager geregelt. - m_pEventManager->AttachHandler( pCoreEventHandler ); - } - VA_RETHROW; -} - -void CVACoreImpl::DetachEventHandler( IVAEventHandler* pCoreEventHandler ) -{ - VA_TRY - { - // Immer möglich. Unabhängig 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 hinzugefügt wurde - m_pCurSceneState->RemoveReference(); - m_pCurSceneState = nullptr; - } - - // Alle Szenenobjekte löschen - 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 @@ -430,4804 +203,3 @@ void CVACoreImpl::Tidyup() { 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 führt 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 löschen und warten bis Zustand sicher übernommen - // Wichtig: Dies muss vor dem Beenden des Streamings geschehen - - // Reset audio renderers - for( std::vector::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 aufzuräumen - Tidyup(); - - // Allgemein: Fehler beim Finalisieren? => Core im Sack - m_iState = VA_CORESTATE_FAIL; - - // VAExceptions unverändert 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 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; -} - -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& 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 überprüfen - if( dPlaybackPosition < 0 ) - VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback position" ); - - // Quelle anfordern (prüft auf gültige 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 (prüft auf gültige 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 unverändert 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 - { - int iNumSoundSource = VACORE_MAX_NUM_SOUND_SOURCES; - if( ( iNumSoundSource != 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: Zunächst 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 - { - int iNumSoundSource = VACORE_MAX_NUM_SOUND_SOURCES; - if( ( iNumSoundSource != 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 zusätzlich ... - const ITASampleBuffer* pNewBuf( m_pSignalSourceManager->GetSilenceBuffer() ); - - VA_TRY - { - CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID ); - - // Sicherstellen, das die Signalquellen ID gültig ist .. dann ID und Qu - if( !sSignalSourceID.empty() ) - pNewSrc = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID, &pNewBuf ); - - // Vorherige Bindung auflösen 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 überprüfen - 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 veränderten 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 überprüfen - 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 - { - int iNumSoundReceivers = VACORE_MAX_NUM_SOUND_RECEIVERS; - if( ( iNumSoundReceivers != 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(); - - // Hörer anlegen - const int iID = m_pNewSceneState->AddListener(); - assert( iID != -1 ); - - // HINWEIS: Zunächst 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 - { - int iNumSoundReceivers = VACORE_MAX_NUM_SOUND_RECEIVERS; - if( ( iNumSoundReceivers != 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 ) - // Hörer 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 überprüfen - if( !GetAuralizationModeValid( iAuralizationMode ) ) - VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" ); - - bool bSync = GetUpdateLocked(); - if( !bSync ) LockUpdate(); - - CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID ); - - if( !pListenerState ) { - // Hörer 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 überprüfen - 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 ) - // Hörer 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 ) - // Hörer 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::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; - - // Prüfen, ob Hörer 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 Hörer 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::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::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 überprüfen - CVASceneState* pNewSceneState = m_pSceneManager->GetHeadSceneState(); - - assert( pNewSceneState != nullptr ); - assert( pNewSceneState->GetNumReferences() >= 1 ); - - pNewSceneState->AddReference(); - - // TODO: Aktiver Hörer 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 berücksichtigen - /** - * 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 benötigt - if( m_pCurSceneState != pNewSceneState ) - { - // Alter Zustand wird nicht mehr benötigt - 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" ); - - if( oRep.pInputRecorder ) - { - 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" ); - - if( oRep.pOutputRecorder ) - { - VistaFileSystemFile oFilePath( oRep.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 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" ); - - if( oRend.pOutputRecorder ) // If enabled ... - { - 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(); -} diff --git a/src/core/dummy.cpp b/src/core/dummy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29e69914042da69fffce6f470531067b9960e3f6 --- /dev/null +++ b/src/core/dummy.cpp @@ -0,0 +1,14 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" diff --git a/src/core/events.cpp b/src/core/events.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8e5962fd3dba959d9e59fbca5f13711bd902140 --- /dev/null +++ b/src/core/events.cpp @@ -0,0 +1,64 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +void CVACoreImpl::AttachEventHandler( IVAEventHandler* pCoreEventHandler ) +{ + VA_TRY + { + // Immer möglich. Unabhängig vom Zustand. Thread-safety wird im Manager geregelt. + m_pEventManager->AttachHandler( pCoreEventHandler ); + } + VA_RETHROW; +} + +void CVACoreImpl::DetachEventHandler( IVAEventHandler* pCoreEventHandler ) +{ + VA_TRY + { + // Immer möglich. Unabhängig vom Zustand. Thread-safety wird im Manager geregelt. + m_pEventManager->DetachHandler( pCoreEventHandler ); + } + VA_RETHROW; +} + +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 ); +} diff --git a/src/core/file_handling.cpp b/src/core/file_handling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05023c98d5ce77c80c0df234c1f0aa938f67f67a --- /dev/null +++ b/src/core/file_handling.cpp @@ -0,0 +1,175 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +#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 +} + +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::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; +} + +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::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() ); + } + } +} + +std::string CVACoreImpl::SubstituteMacros( const std::string& sStr ) const +{ + VA_TRY + { + return m_oCoreConfig.mMacros.SubstituteMacros( sStr ); + } + VA_RETHROW; +} diff --git a/src/core/finalize.cpp b/src/core/finalize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0fcb8ad0a20690f3528e5971534aaafcff8ebdeb --- /dev/null +++ b/src/core/finalize.cpp @@ -0,0 +1,161 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +void CVACoreImpl::Finalize() +{ + VA_NO_REENTRANCE; + + //VA_TRACE("Core", __FUNCTION__ << " entry"); + VA_INFO( "Core", "Finalizing core" ); + + VA_TRY + { + // Mehrfaches Finialisieren führt 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 löschen und warten bis Zustand sicher übernommen + // Wichtig: Dies muss vor dem Beenden des Streamings geschehen + + // Reset audio renderers + for( std::vector::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 aufzuräumen + Tidyup(); + + // Allgemein: Fehler beim Finalisieren? => Core im Sack + m_iState = VA_CORESTATE_FAIL; + + // VAExceptions unverändert nach aussen leiten + 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(); + } +} diff --git a/src/core/homogeneous_medium.cpp b/src/core/homogeneous_medium.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ce7f4240cbc269caa4843f0b18c749d3cc3586b --- /dev/null +++ b/src/core/homogeneous_medium.cpp @@ -0,0 +1,116 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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; +} diff --git a/src/core/init.cpp b/src/core/init.cpp deleted file mode 100644 index c6991da8ab64912edb678fdfad63711e68458c00..0000000000000000000000000000000000000000 --- a/src/core/init.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * -------------------------------------------------------------------------------------------- - * - * 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 "core.h" - -void CVACoreImpl::Initialize() -{ - VA_NO_REENTRANCE; - - // TODO: Prüfen ob im Fehlerfall zurück in den sauberen Grundzustand [WICHTIG!] - - VA_VERBOSE( "Core", "Initializing core" ); - - VA_TRY - { - if( m_iState == VA_CORESTATE_READY ) - VA_EXCEPT2( MODAL_ERROR, "Core already initialized." ); - - if( m_iState == VA_CORESTATE_FAIL ) - VA_EXCEPT2( MODAL_ERROR, "Core corrupted, reinitialization impossible" ); - - m_pCoreThread = new CVACoreThread( this ); - - SetProgress( "Setting up audio hardware", "", 1 ); - InitializeAudioDriver(); - - m_pR2RPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize ); - - // Create output patch bay with a single output that uses all available physical audio outputs from sound card - m_pOutputPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize ); - int iPhysicalHardwareOutput = m_pOutputPatchbay->AddOutput( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ); - m_pOutputPatchbay->SetOutputGain( iPhysicalHardwareOutput, m_dOutputGain ); - - m_iGlobalAuralizationMode = VA_AURAMODE_ALL; - - // Set up input stream network - ITADatasource* pInputTail = nullptr; - if( m_oCoreConfig.oAudioDriverConfig.iInputChannels > 0 ) - { - pInputTail = m_pAudioDriverBackend->getInputStreamDatasource(); - if( pInputTail ) - { - m_pInputAmp = new ITAStreamAmplifier( pInputTail, ( float ) m_dInputGain ); - m_pInputStreamDetector = new ITAStreamDetector( m_pInputAmp ); - m_pInputStreamDetector->SetProfilerEnabled( true ); - pInputTail = m_pInputStreamDetector; - - if( m_oCoreConfig.bRecordDeviceInputEnabled ) - { - VistaFileSystemFile oRecordFile( m_oCoreConfig.sRecordDeviceInputFileName ); - VistaFileSystemDirectory oRecordBaseFolder( m_oCoreConfig.sRecordDeviceInputBaseFolder ); - - if( !oRecordBaseFolder.Exists() ) - { - if( oRecordBaseFolder.CreateWithParentDirectories() ) - { - VA_INFO( "Core", "Created device input record base folder " << oRecordBaseFolder.GetName() << " with parent directories" ); - } - else - { - VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent device input record base folder '" + oRecordBaseFolder.GetName() + "'" ); - } - } - - std::string sFilePath = oRecordBaseFolder.GetName() + "/" + oRecordFile.GetLocalName(); - if( VistaFileSystemFile( sFilePath ).Exists() ) - VA_INFO( "Core", "Device input record file '" << sFilePath << "' exists, will overwrite" ); - - m_pStreamProbeDeviceInput = new ITAStreamProbe( pInputTail, sFilePath ); - pInputTail = m_pStreamProbeDeviceInput; - } - } - } - - SetProgress( "Setting up resource managers", "", 2 ); - - assert( m_oCoreConfig.oAudioDriverConfig.iInputChannels >= 0 ); - m_pSignalSourceManager = new CVAAudioSignalSourceManager( this, m_oCoreConfig.oAudioDriverConfig, pInputTail ); - m_pGlobalSamplePool = ITASoundSamplePool::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate ); - m_pGlobalSampler = ITASoundSampler::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize, m_pGlobalSamplePool ); - m_pGlobalSampler->AddMonoTrack(); - - m_pDirectivityManager = new CVADirectivityManager( this, m_oCoreConfig.oAudioDriverConfig.dSampleRate ); - m_pDirectivityManager->Initialize(); - - - SetProgress( "Setting up scene management", "", 3 ); - - m_pSceneManager = new CVASceneManager( m_pClock ); - m_pSceneManager->Initialize(); - m_pCurSceneState = m_pSceneManager->GetHeadSceneState(); - - SetProgress( "Setting up medium environment", "", 4 ); - - oHomogeneousMedium = m_oCoreConfig.oInitialHomogeneousMedium; - - - SetProgress( "Initializing rendering modules", "", 5 ); - - // Register all renderers and initialize - CVAAudioRendererRegistry::GetInstance()->RegisterInternalCoreFactoryMethods(); - InitializeAudioRenderers(); - - if( m_voRenderers.empty() ) - VA_EXCEPT1( "No audio renderers created" ); - - - SetProgress( "Initializing reproduction modules", "", 6 ); - - // Register all reproductions and initialize - CVAAudioReproductionRegistry::GetInstance()->RegisterInternalCoreFactoryMethods(); - InitializeReproductionModules(); - - if( m_voReproductionModules.empty() ) - VA_EXCEPT1( "No audio reproduction modules created" ); - - - SetProgress( "Patching audio i/o of rendering and reproduction modules", "", 7 ); - - // Patch renderer and reproduction modules - PatchRendererToReproductionModules(); - - // Patch audio reproduction to output - PatchReproductionModulesToOutput(); - - - // Create output peak detector that uses patch bay output stream - - m_pOutputStreamDetector = new ITAStreamDetector( m_pOutputPatchbay->GetOutputDatasource( iPhysicalHardwareOutput ) ); - m_pOutputStreamDetector->SetProfilerEnabled( true ); - - - // Setup output dump (if set) - ITADatasource* pOutputTail = m_pOutputStreamDetector; - if( m_oCoreConfig.bRecordDeviceOutputEnabled ) - { - VistaFileSystemFile oRecordFile( m_oCoreConfig.sRecordDeviceOutputFileName ); - VistaFileSystemDirectory oRecordBaseFolder( m_oCoreConfig.sRecordDeviceOutputBaseFolder ); - - if( !oRecordBaseFolder.Exists() ) - { - if( oRecordBaseFolder.CreateWithParentDirectories() ) - { - VA_INFO( "Core", "Created device output record base folder " << oRecordBaseFolder.GetName() << " with parent directories" ); - } - else - { - VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent device output record base folder '" + oRecordBaseFolder.GetName() + "'" ); - } - } - - std::string sFilePath = oRecordBaseFolder.GetName() + "/" + oRecordFile.GetLocalName(); - if( VistaFileSystemFile( sFilePath ).Exists() ) - VA_INFO( "Core", "Device output record file '" << sFilePath << "' exists, will overwrite" ); - - m_pStreamProbeDeviceOutput = new ITAStreamProbe( pOutputTail, sFilePath ); - pOutputTail = m_pStreamProbeDeviceOutput; - } - - // Attach the stream tracker - m_pOutputTracker = new CVAAudiostreamTracker( pOutputTail, m_pClock, &m_fCoreClockOffset, &m_lSyncModOwner, m_pSignalSourceManager ); - pOutputTail = m_pOutputTracker; - - // Give output stream datasource to audio driver - m_pAudioDriverBackend->setOutputStreamDatasource( pOutputTail ); - - // Core-Clock auf 0 initialisieren - double dNow = m_pClock->getTime(); - m_fCoreClockOffset = ( float ) dNow; - m_dStreamClockOffset = -1; - - // Timer erzeugen und konfigurieren (wird für Peak-Events benutzt) - m_pTicker = new VistaTicker(); - m_pTicker->AddTrigger( new VistaTicker::TriggerContext( m_oCoreConfig.iTriggerUpdateMilliseconds, true ) ); - m_pTicker->SetAfterPulseFunctor( this ); - - // Audio-Streaming starten - SetProgress( "Starting audio streaming", "", 8 ); - m_pAudioDriverBackend->startStreaming(); - - // Timer für Peak-Events starten - m_pTicker->StartTicker(); - - // Initialisierung erfolgreich! - m_iState = VA_CORESTATE_READY; - - SetProgress( "Initialization finished", "", 9 ); - FinishProgress(); - - } - VA_FINALLY - { - // Aufräumen und Exception weiterwerfen - Tidyup(); - throw; - } -} diff --git a/src/core/initialize.cpp b/src/core/initialize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e77668c829263702950c993d51a58f6202c34b99 --- /dev/null +++ b/src/core/initialize.cpp @@ -0,0 +1,774 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +void CVACoreImpl::Initialize() +{ + VA_NO_REENTRANCE; + + // TODO: Prüfen ob im Fehlerfall zurück in den sauberen Grundzustand [WICHTIG!] + + VA_VERBOSE( "Core", "Initializing core" ); + + VA_TRY + { + if( m_iState == VA_CORESTATE_READY ) + VA_EXCEPT2( MODAL_ERROR, "Core already initialized." ); + + if( m_iState == VA_CORESTATE_FAIL ) + VA_EXCEPT2( MODAL_ERROR, "Core corrupted, reinitialization impossible" ); + + m_pCoreThread = new CVACoreThread( this ); + + SetProgress( "Setting up audio hardware", "", 1 ); + InitializeAudioDriver(); + + m_pR2RPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize ); + + // Create output patch bay with a single output that uses all available physical audio outputs from sound card + m_pOutputPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize ); + int iPhysicalHardwareOutput = m_pOutputPatchbay->AddOutput( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ); + m_pOutputPatchbay->SetOutputGain( iPhysicalHardwareOutput, m_dOutputGain ); + + m_iGlobalAuralizationMode = VA_AURAMODE_ALL; + + // Set up input stream network + ITADatasource* pInputTail = nullptr; + if( m_oCoreConfig.oAudioDriverConfig.iInputChannels > 0 ) + { + pInputTail = m_pAudioDriverBackend->getInputStreamDatasource(); + if( pInputTail ) + { + m_pInputAmp = new ITAStreamAmplifier( pInputTail, ( float ) m_dInputGain ); + m_pInputStreamDetector = new ITAStreamDetector( m_pInputAmp ); + m_pInputStreamDetector->SetProfilerEnabled( true ); + pInputTail = m_pInputStreamDetector; + + if( m_oCoreConfig.bRecordDeviceInputEnabled ) + { + VistaFileSystemFile oRecordFile( m_oCoreConfig.sRecordDeviceInputFileName ); + VistaFileSystemDirectory oRecordBaseFolder( m_oCoreConfig.sRecordDeviceInputBaseFolder ); + + if( !oRecordBaseFolder.Exists() ) + { + if( oRecordBaseFolder.CreateWithParentDirectories() ) + { + VA_INFO( "Core", "Created device input record base folder " << oRecordBaseFolder.GetName() << " with parent directories" ); + } + else + { + VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent device input record base folder '" + oRecordBaseFolder.GetName() + "'" ); + } + } + + std::string sFilePath = oRecordBaseFolder.GetName() + "/" + oRecordFile.GetLocalName(); + if( VistaFileSystemFile( sFilePath ).Exists() ) + VA_INFO( "Core", "Device input record file '" << sFilePath << "' exists, will overwrite" ); + + m_pStreamProbeDeviceInput = new ITAStreamProbe( pInputTail, sFilePath ); + pInputTail = m_pStreamProbeDeviceInput; + } + } + } + + SetProgress( "Setting up resource managers", "", 2 ); + + assert( m_oCoreConfig.oAudioDriverConfig.iInputChannels >= 0 ); + m_pSignalSourceManager = new CVAAudioSignalSourceManager( this, m_oCoreConfig.oAudioDriverConfig, pInputTail ); + m_pGlobalSamplePool = ITASoundSamplePool::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate ); + m_pGlobalSampler = ITASoundSampler::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize, m_pGlobalSamplePool ); + m_pGlobalSampler->AddMonoTrack(); + + m_pDirectivityManager = new CVADirectivityManager( this, m_oCoreConfig.oAudioDriverConfig.dSampleRate ); + m_pDirectivityManager->Initialize(); + + + SetProgress( "Setting up scene management", "", 3 ); + + m_pSceneManager = new CVASceneManager( m_pClock ); + m_pSceneManager->Initialize(); + m_pCurSceneState = m_pSceneManager->GetHeadSceneState(); + + SetProgress( "Setting up medium environment", "", 4 ); + + oHomogeneousMedium = m_oCoreConfig.oInitialHomogeneousMedium; + + + SetProgress( "Initializing rendering modules", "", 5 ); + + // Register all renderers and initialize + CVAAudioRendererRegistry::GetInstance()->RegisterInternalCoreFactoryMethods(); + InitializeAudioRenderers(); + + if( m_voRenderers.empty() ) + VA_EXCEPT1( "No audio renderers created" ); + + + SetProgress( "Initializing reproduction modules", "", 6 ); + + // Register all reproductions and initialize + CVAAudioReproductionRegistry::GetInstance()->RegisterInternalCoreFactoryMethods(); + InitializeReproductionModules(); + + if( m_voReproductionModules.empty() ) + VA_EXCEPT1( "No audio reproduction modules created" ); + + + SetProgress( "Patching audio i/o of rendering and reproduction modules", "", 7 ); + + // Patch renderer and reproduction modules + PatchRendererToReproductionModules(); + + // Patch audio reproduction to output + PatchReproductionModulesToOutput(); + + + // Create output peak detector that uses patch bay output stream + + m_pOutputStreamDetector = new ITAStreamDetector( m_pOutputPatchbay->GetOutputDatasource( iPhysicalHardwareOutput ) ); + m_pOutputStreamDetector->SetProfilerEnabled( true ); + + + // Setup output dump (if set) + ITADatasource* pOutputTail = m_pOutputStreamDetector; + if( m_oCoreConfig.bRecordDeviceOutputEnabled ) + { + VistaFileSystemFile oRecordFile( m_oCoreConfig.sRecordDeviceOutputFileName ); + VistaFileSystemDirectory oRecordBaseFolder( m_oCoreConfig.sRecordDeviceOutputBaseFolder ); + + if( !oRecordBaseFolder.Exists() ) + { + if( oRecordBaseFolder.CreateWithParentDirectories() ) + { + VA_INFO( "Core", "Created device output record base folder " << oRecordBaseFolder.GetName() << " with parent directories" ); + } + else + { + VA_EXCEPT2( INVALID_PARAMETER, "Could not create non-existent device output record base folder '" + oRecordBaseFolder.GetName() + "'" ); + } + } + + std::string sFilePath = oRecordBaseFolder.GetName() + "/" + oRecordFile.GetLocalName(); + if( VistaFileSystemFile( sFilePath ).Exists() ) + VA_INFO( "Core", "Device output record file '" << sFilePath << "' exists, will overwrite" ); + + m_pStreamProbeDeviceOutput = new ITAStreamProbe( pOutputTail, sFilePath ); + pOutputTail = m_pStreamProbeDeviceOutput; + } + + // Attach the stream tracker + m_pOutputTracker = new CVAAudiostreamTracker( pOutputTail, m_pClock, &m_fCoreClockOffset, &m_lSyncModOwner, m_pSignalSourceManager ); + pOutputTail = m_pOutputTracker; + + // Give output stream datasource to audio driver + m_pAudioDriverBackend->setOutputStreamDatasource( pOutputTail ); + + // Core-Clock auf 0 initialisieren + double dNow = m_pClock->getTime(); + m_fCoreClockOffset = ( float ) dNow; + m_dStreamClockOffset = -1; + + // Timer erzeugen und konfigurieren (wird für Peak-Events benutzt) + m_pTicker = new VistaTicker(); + m_pTicker->AddTrigger( new VistaTicker::TriggerContext( m_oCoreConfig.iTriggerUpdateMilliseconds, true ) ); + m_pTicker->SetAfterPulseFunctor( this ); + + // Audio-Streaming starten + SetProgress( "Starting audio streaming", "", 8 ); + m_pAudioDriverBackend->startStreaming(); + + // Timer für Peak-Events starten + m_pTicker->StartTicker(); + + // Initialisierung erfolgreich! + m_iState = VA_CORESTATE_READY; + + SetProgress( "Initialization finished", "", 9 ); + FinishProgress(); + + } + VA_FINALLY + { + // Aufräumen und Exception weiterwerfen + Tidyup(); + throw; + } +} + +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::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::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::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; +} diff --git a/src/core/locking.cpp b/src/core/locking.cpp new file mode 100644 index 0000000000000000000000000000000000000000..901a19348b20fbf82071a88573741589908f80b8 --- /dev/null +++ b/src/core/locking.cpp @@ -0,0 +1,127 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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; +} diff --git a/src/core/module.cpp b/src/core/module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04acd2f0aa7e8d71b87bca4b4cca5e8de7d38119 --- /dev/null +++ b/src/core/module.cpp @@ -0,0 +1,94 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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 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 +} diff --git a/src/core/object.cpp b/src/core/object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d0b90f07b89f56481f35f4171c56a0ebe704330 --- /dev/null +++ b/src/core/object.cpp @@ -0,0 +1,184 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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; +} diff --git a/src/core/progress.cpp b/src/core/progress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0f31cdcc16f47f8e449c2eaf46b7136b837ffcc --- /dev/null +++ b/src/core/progress.cpp @@ -0,0 +1,71 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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(); +} diff --git a/src/core/rendering.cpp b/src/core/rendering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f5138d5b67356e3f818307dcf1a287f449b053c --- /dev/null +++ b/src/core/rendering.cpp @@ -0,0 +1,214 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + + +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" ); + + if( oRend.pOutputRecorder ) // If enabled ... + { + 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(); +} + +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::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::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 ); + } +} diff --git a/src/core/reproduction.cpp b/src/core/reproduction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e7b83f7805b3b65435c700c1a5698c3f8f4a20c --- /dev/null +++ b/src/core/reproduction.cpp @@ -0,0 +1,234 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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" ); + + if( oRep.pInputRecorder ) + { + 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" ); + + if( oRep.pOutputRecorder ) + { + VistaFileSystemFile oFilePath( oRep.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 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 ); + } +} + +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::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; +} + +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::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 ); + } +} diff --git a/src/core/reset.cpp b/src/core/reset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63c4efcaadb58885d497b4bba158d5738b883b07 --- /dev/null +++ b/src/core/reset.cpp @@ -0,0 +1,92 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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 hinzugefügt wurde + m_pCurSceneState->RemoveReference(); + m_pCurSceneState = nullptr; + } + + // Alle Szenenobjekte löschen + 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; + } +} diff --git a/src/core/scene.cpp b/src/core/scene.cpp new file mode 100644 index 0000000000000000000000000000000000000000..650f487a20101fadb511876cec111f1413d4b7da --- /dev/null +++ b/src/core/scene.cpp @@ -0,0 +1,89 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +const CVASceneManager* CVACoreImpl::GetSceneManager() const +{ + return m_pSceneManager; +} + +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::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; +} + +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; +} diff --git a/src/core/signal_source.cpp b/src/core/signal_source.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e504c3d9ab4b6b84d58480c1d09480e7da830e74 --- /dev/null +++ b/src/core/signal_source.cpp @@ -0,0 +1,521 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +const CVAAudioSignalSourceManager* CVACoreImpl::GetSignalSourceManager() const +{ + return m_pSignalSourceManager; +} + +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& 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 überprüfen + if( dPlaybackPosition < 0 ) + VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback position" ); + + // Quelle anfordern (prüft auf gültige 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 (prüft auf gültige 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 unverändert nach aussen leiten + throw; + } +} + +void CVACoreImpl::RemoveSignalSourceSequencerSample( const std::string& sSignalSourceID, const int iSoundID ) +{ + VA_EXCEPT_NOT_IMPLEMENTED; +} diff --git a/src/core/sound_portal.cpp b/src/core/sound_portal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76ae68b96ae76242e00b660a3b732cef491e4778 --- /dev/null +++ b/src/core/sound_portal.cpp @@ -0,0 +1,164 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +int CVACoreImpl::CreateSoundPortal( const std::string& sName /*= "" */ ) +{ + VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION; + //m_pSceneManager->CreatePortalDesc() +} + +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; +} diff --git a/src/core/sound_receiver.cpp b/src/core/sound_receiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d691c2f98c6721d5341486f68752867e32fc9b76 --- /dev/null +++ b/src/core/sound_receiver.cpp @@ -0,0 +1,1005 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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 + { + int iNumSoundReceivers = VACORE_MAX_NUM_SOUND_RECEIVERS; + if( ( iNumSoundReceivers != 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(); + + // Hörer anlegen + const int iID = m_pNewSceneState->AddListener(); + assert( iID != -1 ); + + // HINWEIS: Zunächst 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 + { + int iNumSoundReceivers = VACORE_MAX_NUM_SOUND_RECEIVERS; + if( ( iNumSoundReceivers != 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 ) + // Hörer 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 überprüfen + if( !GetAuralizationModeValid( iAuralizationMode ) ) + VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" ); + + bool bSync = GetUpdateLocked(); + if( !bSync ) LockUpdate(); + + CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID ); + + if( !pListenerState ) { + // Hörer 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 überprüfen + 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 ) + // Hörer 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 ) + // Hörer 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; +} + +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; + + // Prüfen, ob Hörer 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 Hörer 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; + } +} diff --git a/src/core/sound_source.cpp b/src/core/sound_source.cpp new file mode 100644 index 0000000000000000000000000000000000000000..480ad19443aef55b2e180c6b67c66b91eabdbf81 --- /dev/null +++ b/src/core/sound_source.cpp @@ -0,0 +1,873 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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 + { + int iNumSoundSource = VACORE_MAX_NUM_SOUND_SOURCES; + if( ( iNumSoundSource != 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: Zunächst 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 + { + int iNumSoundSource = VACORE_MAX_NUM_SOUND_SOURCES; + if( ( iNumSoundSource != 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 zusätzlich ... + const ITASampleBuffer* pNewBuf( m_pSignalSourceManager->GetSilenceBuffer() ); + + VA_TRY + { + CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID ); + + // Sicherstellen, das die Signalquellen ID gültig ist .. dann ID und Qu + if( !sSignalSourceID.empty() ) + pNewSrc = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID, &pNewBuf ); + + // Vorherige Bindung auflösen 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 überprüfen + 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 veränderten 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 überprüfen + 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; +} diff --git a/src/core/state.cpp b/src/core/state.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75bd7bad626c0ee2efbadb7f289d1bd85a032887 --- /dev/null +++ b/src/core/state.cpp @@ -0,0 +1,25 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +int CVACoreImpl::GetState() const +{ + VA_VERBOSE( "Core", "Core state requested, current state is " << m_iState ); + return m_iState; +} + +bool CVACoreImpl::IsStreaming() const +{ + return ( m_pAudioDriverBackend ? m_pAudioDriverBackend->isStreaming() : false ); +} diff --git a/src/core/thread_loop.cpp b/src/core/thread_loop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdd882bae3f6314f470e0c81cc1f8564817fd684 --- /dev/null +++ b/src/core/thread_loop.cpp @@ -0,0 +1,112 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +void CVACoreImpl::CoreThreadLoop() +{ + m_oCoreThreadLoopTotalDuration.start(); + + assert( m_pCurSceneState != nullptr ); + assert( m_pCurSceneState->GetNumReferences() >= 1 ); + + // Auf Änderungen der Szene überprüfen + CVASceneState* pNewSceneState = m_pSceneManager->GetHeadSceneState(); + + assert( pNewSceneState != nullptr ); + assert( pNewSceneState->GetNumReferences() >= 1 ); + + pNewSceneState->AddReference(); + + // TODO: Aktiver Hörer 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 berücksichtigen + /** + * 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 benötigt + if( m_pCurSceneState != pNewSceneState ) + { + // Alter Zustand wird nicht mehr benötigt + 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; +} + + +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 +} diff --git a/src/core/version.cpp b/src/core/version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2dd98c5d9347b4c129365596635a196a25646ee0 --- /dev/null +++ b/src/core/version.cpp @@ -0,0 +1,38 @@ +/* + * -------------------------------------------------------------------------------------------- + * + * 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 "core.h" + +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 +}