vasingletonmethods.hpp 97.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 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 <Python.h>
15 16 17 18

#include <VA.h>
#include <VANet.h>

19 20
#include <string.h>

21
// If you want to extend the va Python pSelf interface, also add
22 23 24 25
// the function to the va_methods table in vasingleton.cpp - otherwise they will not show up.
// Documentation goes into vasingletondoc.hpp

static IVANetClient* g_pVANetClient = nullptr; //!< Static pointer to VANetClient instance
26
static PyObject* g_pVAError = nullptr; //!< Static pointer to error instance
27

28 29 30 31
// Ugly definitions to ease try-catching VA exceptions
#define VAPY_REQUIRE_CONN_TRY try { RequireCoreAvailable();
#define VAPY_CATCH_RETURN } catch (const CVAException& oError) { PyErr_SetString(PyExc_Exception, oError.ToString().c_str()); return NULL; }

32
//! Helper for API dev
33
static PyObject* not_implemented( PyObject*, PyObject* )
34 35
{
	VA_EXCEPT_NOT_IMPLEMENTED;
36
};
37

38 39 40
//! Raises an exception if core is not available
static void RequireCoreAvailable()
{
41
	if( !g_pVANetClient )
42
		VA_EXCEPT2( NETWORK_ERROR, "VA client not available, please connect first" );
43

44
	if( !g_pVANetClient->GetCoreInstance() )
45
		VA_EXCEPT2( NETWORK_ERROR, "VA client available, but access to VA interface failed. Please reconnect." );
46 47 48 49 50 51 52 53 54 55 56
};

std::string SaveStringToUnicodeConversion( const std::string& sInputString )
{
	std::string sOutputString = sInputString;
	const Py_ssize_t iLength = sInputString.length();
	char* pcBuffer( &sOutputString[ 0 ] );
	for( Py_ssize_t i = 0; i < iLength; i++ )
		if( pcBuffer[ i ] < 0 )
			pcBuffer[ i ] = '_';
	return &sOutputString[ 0 ];
57
};
58

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
PyObject* ConvertFloatVectorToPythonList( const std::vector< float > vfValues )
{
	PyObject* pList = PyList_New( vfValues.size() );

	for( Py_ssize_t i = 0; i < PyList_GET_SIZE( pList ); i++ )
		PyList_SetItem( pList, i, PyLong_FromDouble( vfValues[ i ] ) );

	return pList;
};

PyObject* ConvertDoubleVectorToPythonList( const std::vector< double > vdValues )
{
	PyObject* pList = PyList_New( vdValues.size() );

	for( Py_ssize_t i = 0; i < PyList_GET_SIZE( pList ); i++ )
		PyList_SetItem( pList, i, PyLong_FromDouble( vdValues[ i ] ) );

	return pList;
};

PyObject* ConvertIntVectorToPythonList( const std::vector< int > viValues )
{
	PyObject* pList = PyList_New( viValues.size() );

	for( Py_ssize_t i = 0; i < PyList_GET_SIZE( pList ); i++ )
		PyList_SetItem( pList, i, PyLong_FromLong( viValues[ i ] ) );

	return pList;
};

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
89
//! Helper to convert recursively from VAStruct to Python dict
90
PyObject* ConvertVAStructToPythonDict( const CVAStruct& oInStruct )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
91
{
92 93 94
	PyObject* pOutDict = PyDict_New();

	CVAStruct::const_iterator cit = oInStruct.Begin();
95
	while( cit != oInStruct.End() )
96
	{
97 98
		const std::string sKey( ( *cit++ ).first );
		const CVAStructValue& oValue( oInStruct[ sKey ] );
99 100

		PyObject* pNewValue = nullptr;
101
		if( oValue.IsBool() )
102
		{
103
			pNewValue = PyBool_FromLong( bool( oValue ) );
104
		}
105
		else if( oValue.IsInt() )
106
		{
107
			pNewValue = PyLong_FromLong( int( oValue ) );
108
		}
109
		else if( oValue.IsDouble() )
110
		{
111
			pNewValue = PyFloat_FromDouble( double( oValue ) );
112
		}
113
		else if( oValue.IsString() )
114
		{
115
			pNewValue = PyUnicode_FromString( SaveStringToUnicodeConversion( std::string( oValue ) ).c_str() );
116
		}
117
		else if( oValue.IsStruct() )
118
		{
119
			pNewValue = ConvertVAStructToPythonDict( oValue );
120
		}
121
		else if( oValue.IsData() )
122
		{
123 124
			pNewValue = PyByteArray_FromStringAndSize( ( char* ) oValue.GetData(), oValue.GetDataSize() );
			Py_INCREF( pNewValue );
125
		}
126
		else if( oValue.IsSampleBuffer() )
127
		{
128 129 130 131 132
			const CVASampleBuffer& oSampleBuffer( oValue );
			pNewValue = PyList_New( oSampleBuffer.GetNumSamples() );
			Py_INCREF( pNewValue );
			for( int i = 0; i < oSampleBuffer.GetNumSamples(); i++ )
				PyList_SetItem( pNewValue, i, PyFloat_FromDouble( oSampleBuffer.GetDataReadOnly()[ i ] ) );
133 134 135
		}
		else
		{
136
			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + sKey + "' as a supported python dict type. Value was" + oValue.ToString() );
137 138
		}

139 140
		if( !pNewValue )
			VA_EXCEPT2( INVALID_PARAMETER, "Could not create python object from value of key '" + sKey + "'. Value was" + oValue.ToString() );
141

142 143
		if( PyDict_SetItemString( pOutDict, sKey.c_str(), pNewValue ) == -1 )
			VA_EXCEPT2( INVALID_PARAMETER, "Could not create python object from value of key '" + sKey + "'. Value was" + oValue.ToString() );
144 145 146
	}

	return pOutDict;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
147 148 149
};

//! Helper to convert recursively from Python dict to VAStruct
150
CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
151
{
152 153
	CVAStruct oReturn;

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
154 155 156
	if( pInDict == nullptr )
		return oReturn;

157 158
	PyObject* pKeyList = PyDict_Keys( pInDict );
	PyObject* pValueList = PyDict_Values( pInDict );
159

160
	for( Py_ssize_t i = 0; i < PyList_Size( pKeyList ); i++ )
161
	{
162 163
		PyObject* pKey = PyList_GetItem( pKeyList, i );
		PyObject* pValue = PyList_GetItem( pValueList, i );
164
		char* pcKeyName = nullptr;
165
		if( !PyArg_Parse( pKey, "s", &pcKeyName ) )
166
			VA_EXCEPT2( INVALID_PARAMETER, "Invalid key '" + std::string( pcKeyName ) + "'" );
167

168
		if( Py_None == pValue )
169
		{
170
			oReturn[ pcKeyName ] = false;
171
		}
172
		else if( PyBool_Check( pValue ) )
173
		{
174
			oReturn[ pcKeyName ] = ( PyLong_AsLong( pValue ) != 0 );
175
		}
176
		else if( PyLong_Check( pValue ) )
177
		{
178
			oReturn[ pcKeyName ] = PyLong_AsLong( pValue );
179
		}
180
		else if( PyFloat_Check( pValue ) )
181
		{
182
			oReturn[ pcKeyName ] = PyFloat_AsDouble( pValue );
183
		}
184
		else if( PyUnicode_Check( pValue ) )
185 186
		{
			char* pcStringValue = nullptr;
187
			if( !PyArg_Parse( pValue, "s", &pcStringValue ) )
188
				VA_EXCEPT2( INVALID_PARAMETER, "Invalid string value at key '" + std::string( pcKeyName ) + "': " + std::string( pcStringValue ) );
189
			oReturn[ pcKeyName ] = std::string( pcStringValue );
190
		}
191
		else if( PyDict_Check( pValue ) )
192
		{
193
			oReturn[ pcKeyName ] = ConvertPythonDictToVAStruct( pValue );
194
		}
195
		else if( PyList_Check( pValue ) )
196 197
		{
			// Sample buffer
198 199 200 201 202 203 204 205 206 207
			CVASampleBuffer oBuffer( int( PyList_Size( pValue ) ) );
			for( int n = 0; n < oBuffer.GetNumSamples(); n++ )
			{
				PyObject* pSample = PyList_GetItem( pValue, n );
				if( !PyFloat_Check( pSample ) )
				{
					VA_EXCEPT2( INVALID_PARAMETER, "Samples must be floating point values" );
				}
				else
				{
208
					oBuffer.vfSamples[ n ] = float( PyFloat_AsDouble( pSample ) );
209 210 211
				}
			}
			oReturn[ pcKeyName ] = oBuffer;
212
		}
213
		else if( PyBytes_Check( pValue ) )
214 215
		{
			// Data blob
216 217 218
			size_t iBytes = PyBytes_Size( pValue );
			char* pcData = PyBytes_AsString( pValue );
			oReturn[ pcKeyName ] = CVAStructValue( pcData, int( iBytes ) );
219 220 221
		}
		else
		{
222
			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + std::string( pcKeyName ) + "' as a supported VAStruct type." )
223 224 225 226
		}
	}

	return oReturn;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
227 228
};

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
229 230 231
CVAAcousticMaterial ConvertPythonDictToAcousticMaterial( PyObject* pMaterial )
{
	CVAAcousticMaterial oMaterial;
232 233
	VA_EXCEPT_NOT_IMPLEMENTED;
	return oMaterial;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
234 235
}

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
236 237 238

// ------------------------------- Python module extension methods

239
static PyObject* connect( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
240
{
241
	if( !g_pVANetClient )
242 243
		g_pVANetClient = IVANetClient::Create();

244
	if( g_pVANetClient->IsConnected() )
245
	{
246
		PyErr_WarnEx( NULL, "Was still connected, forced disconnect.", 1 );
247
		g_pVANetClient->Disconnect();
248 249 250
	}

	static const char * const _keywords[] = { "server", "port", NULL };
251
	static _PyArg_Parser _parser = { "|si:connect", _keywords, 0 };
252
	char* pcServerIP = nullptr;
253 254
	int iServerPort = 12340;

255
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcServerIP, &iServerPort ) )
256
		return NULL;
257

258
	std::string sServerIP = pcServerIP ? std::string( pcServerIP ) : "localhost";
259

260 261
	if( IVANetClient::VA_NO_ERROR == g_pVANetClient->Initialize( sServerIP, iServerPort ) )
		return PyBool_FromLong( 1 );
262

263
	PyErr_SetString( PyExc_ConnectionError, std::string( "Could not connect to " + sServerIP + " on " + std::to_string( ( long ) iServerPort ) ).c_str() );
264
	return NULL;
265
};
266

267
static PyObject* disconnect( PyObject*, PyObject* )
268
{
269 270
	if( !g_pVANetClient )
		return PyBool_FromLong( 0 );
271

272
	return PyBool_FromLong( g_pVANetClient->Disconnect() );
273
};
274

275
static PyObject* is_connected( PyObject*, PyObject* )
276
{
277 278
	if( !g_pVANetClient )
		return PyBool_FromLong( 0 );
279
	else
280
		return PyBool_FromLong( g_pVANetClient->IsConnected() );
281
};
282

283
static PyObject* reset( PyObject*, PyObject* )
284
{
285
	VAPY_REQUIRE_CONN_TRY;
286
	g_pVANetClient->GetCoreInstance()->Reset();
287
	Py_INCREF( Py_None );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
288
	return Py_None;
289 290
	VAPY_CATCH_RETURN;
};
291

292 293 294 295 296 297 298 299 300
static PyObject* get_version( PyObject*, PyObject* )
{
	VAPY_REQUIRE_CONN_TRY;
	CVAVersionInfo oInfo;
	g_pVANetClient->GetCoreInstance()->GetVersionInfo( &oInfo );
	return PyUnicode_FromString( SaveStringToUnicodeConversion( oInfo.ToString() ).c_str() );
	VAPY_CATCH_RETURN;
};

301
static PyObject* get_modules( PyObject*, PyObject* )
302
{
303
	VAPY_REQUIRE_CONN_TRY;
304 305

	std::vector< CVAModuleInfo > voModuleInfos;
306
	g_pVANetClient->GetCoreInstance()->GetModules( voModuleInfos );
307

308
	PyObject* pModuleList = PyList_New( voModuleInfos.size() );
309

310
	for( size_t i = 0; i < voModuleInfos.size(); i++ )
311
	{
312
		CVAModuleInfo& oModule( voModuleInfos[ i ] );
313
		PyObject* pModuleInfo = Py_BuildValue( "{s:i,s:s,s:s}", "index", i, "name", SaveStringToUnicodeConversion( oModule.sName ).c_str(), "description", SaveStringToUnicodeConversion( oModule.sDesc ).c_str() );
314
		PyList_SetItem( pModuleList, i, pModuleInfo ); // steals reference
315 316 317 318
	}

	return pModuleList;

319 320 321
	VAPY_CATCH_RETURN;
};

322
static PyObject* call_module( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
323
{
324
	VAPY_REQUIRE_CONN_TRY;
325

326 327
	static const char * const _keywords[] = { "module_name", "arguments_dict", NULL };
	static _PyArg_Parser _parser = { "sO!:call_module", _keywords, 0 };
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
328
	char* pcModuleName = nullptr;
329
	PyObject* pArgumentsDict = nullptr;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
330

331
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &PyDict_Type, &pArgumentsDict ) )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
332
		return NULL;
333

334
	std::string sModuleName = pcModuleName? std::string( pcModuleName ) : "";
335
	CVAStruct oInArgs = ConvertPythonDictToVAStruct( pArgumentsDict );
336
	CVAStruct oOutArgs = g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oInArgs );
337

338
	return ConvertVAStructToPythonDict( oOutArgs );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
339

340 341 342
	VAPY_CATCH_RETURN;
};

343
static PyObject* add_search_path( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
344
{
345
	VAPY_REQUIRE_CONN_TRY;
346

347 348 349
	static const char * const _keywords[] = { "directory_path", NULL };
	static _PyArg_Parser _parser = { "s:add_search_path", _keywords, 0 };
	char* pcPath = nullptr;
350
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcPath ) )
351 352
		return NULL;

353
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->AddSearchPath( std::string( pcPath ) ) );
354

355 356 357
	VAPY_CATCH_RETURN;
};

358 359 360 361 362 363 364 365
static PyObject* get_search_paths( PyObject*, PyObject**, Py_ssize_t, PyObject* )
{
	VAPY_REQUIRE_CONN_TRY;
	CVAStruct oPaths = g_pVANetClient->GetCoreInstance()->GetSearchPaths();
	return ConvertVAStructToPythonDict( oPaths );
	VAPY_CATCH_RETURN;
};

366
static PyObject* get_update_locked( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
367
{
368
	VAPY_REQUIRE_CONN_TRY;
369
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->GetUpdateLocked() );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
370 371 372
	VAPY_CATCH_RETURN;
};

373
static PyObject* lock_update( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
374
{
375
	VAPY_REQUIRE_CONN_TRY;
376
	g_pVANetClient->GetCoreInstance()->LockUpdate();
377
	Py_INCREF( Py_None );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
378
	return Py_None;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
379 380 381
	VAPY_CATCH_RETURN;
};

382
static PyObject* unlock_update( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
383 384
{
	VAPY_REQUIRE_CONN_TRY;
385
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->UnlockUpdate() );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
386 387
	VAPY_CATCH_RETURN;
};
388

389
static PyObject* create_directivity_from_file( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
390 391 392 393
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "path", "name", NULL };
394
	static _PyArg_Parser _parser = { "s|s:create_directivity_from_file", _keywords, 0 };
395 396
	char* pcPath = nullptr;
	char* pcName = nullptr;
397
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcPath, &pcName ) )
398 399
		return NULL;

400
	std::string sName = pcName ? std::string( pcName ) : "";
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
401
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateDirectivityFromFile( std::string( pcPath ), sName ) );
402 403 404 405

	VAPY_CATCH_RETURN;
};

406
static PyObject* delete_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
407 408 409 410
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
411
	static _PyArg_Parser _parser = { "i:delete_directivity", _keywords, 0 };
412
	long iID = -1;
413
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
414
		return NULL;
415
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->DeleteDirectivity( iID ) );
416 417 418 419

	VAPY_CATCH_RETURN;
};

420
static PyObject* get_directivity_info( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
421 422 423 424 425 426
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_directivity_info", _keywords, 0 };
	long iID = -1;
427
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
428
		return NULL;
429

430
	CVADirectivityInfo oInfo = g_pVANetClient->GetCoreInstance()->GetDirectivityInfo( iID );
431

432
	PyObject* pInfo = Py_BuildValue( "{s:i,s:s,s:i,s:i,s:s}",
433
		"id", oInfo.iID,
434
		"name", SaveStringToUnicodeConversion( oInfo.sName ).c_str(),
435
		"class", oInfo.iClass,
436
		"references", oInfo.iReferences,
437
		"description", SaveStringToUnicodeConversion( oInfo.sDesc ).c_str() );
438 439 440 441 442 443

	return pInfo;

	VAPY_CATCH_RETURN;
};

444
static PyObject* get_directivity_infos( PyObject*, PyObject* )
445 446 447 448
{
	VAPY_REQUIRE_CONN_TRY;

	std::vector< CVADirectivityInfo > voInfos;
449
	g_pVANetClient->GetCoreInstance()->GetDirectivityInfos( voInfos );
450

451
	PyObject* pInfoList = PyList_New( voInfos.size() );
452

453
	for( size_t i = 0; i < voInfos.size(); i++ )
454
	{
455
		CVADirectivityInfo& oInfo( voInfos[ i ] );
456
		PyObject* pInfo = Py_BuildValue( "{s:i,s:s,s:i,s:i,s:s}",
457
			"id", oInfo.iID,
458
			"name", SaveStringToUnicodeConversion( oInfo.sName ).c_str(),
459
			"class", oInfo.iClass,
460
			"references", oInfo.iReferences,
461 462
			"description", SaveStringToUnicodeConversion( oInfo.sDesc ).c_str() );
		PyList_SetItem( pInfoList, i, pInfo ); // steals reference
463 464 465 466 467 468
	}

	return pInfoList;

	VAPY_CATCH_RETURN;
};
469

470
static PyObject* get_sound_source_ids( PyObject*, PyObject* )
471 472 473
{
	VAPY_REQUIRE_CONN_TRY;
	std::vector< int > viIDs;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
474 475
	g_pVANetClient->GetCoreInstance()->GetSoundSourceIDs( viIDs );	
	return ConvertIntVectorToPythonList( viIDs );
476 477 478
	VAPY_CATCH_RETURN;
};

479
static PyObject* create_sound_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
480 481 482 483 484 485 486 487 488 489
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "name", NULL };
	static _PyArg_Parser _parser = { "s:create_sound_source", _keywords, 0 };
	char* pcName = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcName ) )
		return NULL;

	std::string sName = pcName ? std::string( pcName ) : "PySoundSource";
490
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundSource( sName ) );
491 492 493 494 495

	VAPY_CATCH_RETURN;
};


496
static PyObject* create_sound_source_explicit_renderer( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
497 498 499
{
	VAPY_REQUIRE_CONN_TRY;

500
	static const char * const _keywords[] = { "renderer", "name", NULL };
501 502
	static _PyArg_Parser _parser = { "ss:create_sound_source_explicit_renderer", _keywords, 0 };
	char* pcRenderer = nullptr;
503 504
	char* pcName = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcRenderer, &pcName ) )
505 506 507 508
		return NULL;

	std::string sRenderer = pcRenderer ? std::string( pcRenderer ) : "Unspecified";
	std::string sName = pcName ? std::string( pcName ) : "PySoundSource_" + sRenderer;
509
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundSourceExplicitRenderer( sRenderer, sName ) );
510 511 512 513

	VAPY_CATCH_RETURN;
};

514
static PyObject* delete_sound_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
515 516 517 518 519 520 521 522 523 524 525 526 527 528
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:delete_sound_source", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->DeleteSoundSource( iID ) );

	VAPY_CATCH_RETURN;
};

529
static PyObject* set_sound_source_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "enabled", NULL };
	static _PyArg_Parser _parser = { "i|b:set_sound_source_enabled", _keywords, 0 };
	long iID = -1;
	bool bEnabled = true;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &bEnabled ) )
		return NULL;

	g_pVANetClient->GetCoreInstance()->SetSoundSourceEnabled( iID, bEnabled );
	return Py_None;

	VAPY_CATCH_RETURN;
};

546
static PyObject* get_sound_source_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
547 548 549 550 551 552 553 554 555 556 557 558 559 560
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_sound_source_enabled", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->GetSoundSourceEnabled( iID ) );

	VAPY_CATCH_RETURN;
};

561
static PyObject* get_sound_source_name( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
562 563 564 565 566 567 568 569 570 571 572 573 574 575
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_sound_source_name", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	return PyUnicode_FromString( SaveStringToUnicodeConversion( g_pVANetClient->GetCoreInstance()->GetSoundSourceName( iID ) ).c_str() );

	VAPY_CATCH_RETURN;
};

576
static PyObject* get_sound_source_signal_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
577 578 579 580 581 582 583 584 585 586 587 588 589 590
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_sound_source_signal_source", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	return PyUnicode_FromString( SaveStringToUnicodeConversion( g_pVANetClient->GetCoreInstance()->GetSoundSourceSignalSource( iID ) ).c_str() );

	VAPY_CATCH_RETURN;
};

591
static PyObject* set_sound_source_signal_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "signalsource", NULL };
	static _PyArg_Parser _parser = { "is:set_sound_source_signal_source", _keywords, 0 };
	long iID = -1;
	char* pcSignalSourceID;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &pcSignalSourceID ) )
		return NULL;

	std::string sSIgnalSourceID = pcSignalSourceID ? std::string( pcSignalSourceID ) : "";
	g_pVANetClient->GetCoreInstance()->SetSoundSourceSignalSource( iID, sSIgnalSourceID );

	return Py_None;

	VAPY_CATCH_RETURN;
};

610
static PyObject* remove_sound_source_signal_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:remove_sound_source_signal_source", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	g_pVANetClient->GetCoreInstance()->RemoveSoundSourceSignalSource( iID );
	return Py_None;

	VAPY_CATCH_RETURN;
};

626
static PyObject* get_sound_source_auralization_mode( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
627 628 629
{
	VAPY_REQUIRE_CONN_TRY;

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
630 631
	static const char * const _keywords[] = { "id", "short_mode", NULL };
	static _PyArg_Parser _parser = { "i|b:get_sound_source_auralization_mode", _keywords, 0 };
632
	long iID = -1;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
633
	bool bShortMode = true;
634 635 636
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
637 638 639 640
	const int iAM = g_pVANetClient->GetCoreInstance()->GetSoundSourceAuralizationMode( iID );
	const std::string sAM = SaveStringToUnicodeConversion( IVAInterface::GetAuralizationModeStr( iAM, bShortMode ) );
	
	return PyUnicode_FromString( sAM.c_str() );
641 642 643 644

	VAPY_CATCH_RETURN;
};

645
static PyObject* set_sound_source_auralization_mode( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
646 647 648 649
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "auralizationmode", NULL };
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
650
	static _PyArg_Parser _parser = { "is:set_sound_source_auralization_mode", _keywords, 0 };
651
	long iID = -1;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
652 653
	char* pcAM = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &pcAM ) )
654 655
		return NULL;

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
656 657 658 659 660
	std::string sAM = pcAM ? std::string( pcAM ) : "";
	const int iCurrentAM = g_pVANetClient->GetCoreInstance()->GetSoundSourceAuralizationMode( iID );
	const int iAM = IVAInterface::ParseAuralizationModeStr( sAM, iCurrentAM );
	g_pVANetClient->GetCoreInstance()->SetSoundSourceAuralizationMode( iID, iAM );

661 662 663 664 665
	return Py_None;

	VAPY_CATCH_RETURN;
};

666
static PyObject* set_sound_source_parameters( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "parameters", NULL };
	static _PyArg_Parser _parser = { "iO!:set_sound_source_parameters", _keywords, 0 };
	long iID = -1;
	PyObject* pParameters = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &pParameters ) )
		return NULL;

	CVAStruct oParameters = ConvertPythonDictToVAStruct( pParameters );
	g_pVANetClient->GetCoreInstance()->SetSoundSourceParameters( iID, oParameters );
	return Py_None;

	VAPY_CATCH_RETURN;
};


685
static PyObject* get_sound_source_parameters( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "io!:get_sound_source_parameters", _keywords, 0 };
	long iID = -1;
	PyObject* pParameters = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &pParameters ) )
		return NULL;

	CVAStruct oParameters = ConvertPythonDictToVAStruct( pParameters );
	CVAStruct oReturn = g_pVANetClient->GetCoreInstance()->GetSoundSourceParameters( iID, oParameters );
	return ConvertVAStructToPythonDict( oReturn );

	VAPY_CATCH_RETURN;
};

703
static PyObject* get_sound_source_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
704 705 706 707 708 709 710 711 712 713 714 715 716 717
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_sound_source_directivity", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->GetSoundSourceDirectivity( iID ) );

	VAPY_CATCH_RETURN;
};

718
static PyObject* set_sound_source_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "directivity", NULL };
	static _PyArg_Parser _parser = { "ii:set_sound_source_directivity", _keywords, 0 };
	long iID = -1;
	long iDirectivityID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &iDirectivityID ) )
		return NULL;

	g_pVANetClient->GetCoreInstance()->SetSoundSourceDirectivity( iID, iDirectivityID );
	return Py_None;

	VAPY_CATCH_RETURN;
};

735
static PyObject* get_sound_source_sound_power( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
736 737 738 739
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
740
	static _PyArg_Parser _parser = { "i:get_sound_source_sound_power", _keywords, 0 };
741 742 743 744
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

745
	return PyFloat_FromDouble( g_pVANetClient->GetCoreInstance()->GetSoundSourceSoundPower( iID ) );
746 747 748 749

	VAPY_CATCH_RETURN;
};

750
static PyObject* set_sound_source_sound_power( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
751 752 753 754
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "gain", NULL };
755
	static _PyArg_Parser _parser = { "id:set_sound_source_sound_power", _keywords, 0 };
756
	long iID = -1;
757 758
	double dPower = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &dPower ) )
759 760
		return NULL;

761
	g_pVANetClient->GetCoreInstance()->SetSoundSourceSoundPower( iID, dPower );
762 763 764 765 766
	return Py_None;

	VAPY_CATCH_RETURN;
};

767
static PyObject* set_sound_source_muted( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "muted", NULL };
	static _PyArg_Parser _parser = { "i|b:set_sound_source_muted", _keywords, 0 };
	long iID = -1;
	bool bMuted = true;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &bMuted ) )
		return NULL;

	g_pVANetClient->GetCoreInstance()->SetSoundSourceMuted( iID, bMuted );
	return Py_None;

	VAPY_CATCH_RETURN;
};

784
static PyObject* get_sound_source_muted( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
785 786 787 788
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
789
	static _PyArg_Parser _parser = { "i:get_sound_source_muted", _keywords, 0 };
790 791 792 793
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

794
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->GetSoundSourceMuted( iID ) );
795 796 797 798

	VAPY_CATCH_RETURN;
};

799
static PyObject* get_sound_source_position( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
800 801 802 803
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
804
	static _PyArg_Parser _parser = { "i:get_sound_source_position", _keywords, 0 };
805 806 807 808
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

809
	VAVec3 v3Pos = g_pVANetClient->GetCoreInstance()->GetSoundSourcePosition( iID );
810 811 812 813 814 815 816 817 818 819 820

	PyObject* pPosList = PyList_New( 3 );
	PyList_SetItem( pPosList, 0, PyFloat_FromDouble( v3Pos.x ) );
	PyList_SetItem( pPosList, 1, PyFloat_FromDouble( v3Pos.y ) );
	PyList_SetItem( pPosList, 2, PyFloat_FromDouble( v3Pos.z ) );

	return pPosList;

	VAPY_CATCH_RETURN;
};

821
static PyObject* set_sound_source_position( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
822 823 824 825
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "pos", NULL };
826
	static _PyArg_Parser _parser = { "i(ddd):set_sound_source_position", _keywords, 0 };
827
	long iID = -1;
828 829
	VAVec3 v3Pos;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &v3Pos.x, &v3Pos.y, &v3Pos.z ) )
830 831
		return NULL;

832
	g_pVANetClient->GetCoreInstance()->SetSoundSourcePosition( iID, v3Pos );
833 834 835 836 837 838
	return Py_None;

	VAPY_CATCH_RETURN;
};


839
static PyObject* get_sound_source_orientation_vu( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
840 841 842 843 844 845 846 847 848 849
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
	static _PyArg_Parser _parser = { "i:get_sound_source_orientation_vu", _keywords, 0 };
	long iID = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
		return NULL;

	VAVec3 v3View, v3Up;
850
	g_pVANetClient->GetCoreInstance()->GetSoundSourceOrientationVU( iID, v3View, v3Up );
851

852
	return Py_BuildValue( "(ddd)(ddd)", v3View.x, v3View.y, v3View.z, v3Up.x, v3Up.y, v3Up.z );
853 854 855 856

	VAPY_CATCH_RETURN;
};

857
static PyObject* set_sound_source_orientation_vu( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
858 859 860 861
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "view", "up", NULL };
862
	static _PyArg_Parser _parser = { "i(ddd)(ddd):set_sound_source_orientation_vu", _keywords, 0 };
863
	long iID = -1;
864
	VAVec3 v3View, v3Up;
865
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &v3View.x, &v3View.y, &v3View.z, &v3Up.x, &v3Up.y, &v3Up.z ) )
866 867
		return NULL;

868
	g_pVANetClient->GetCoreInstance()->SetSoundSourceOrientationVU( iID, v3View, v3Up );
869 870 871 872
	return Py_None;

	VAPY_CATCH_RETURN;
};
873

874
static PyObject* get_sound_receiver_ids( PyObject*, PyObject* )
875 876 877
{
	VAPY_REQUIRE_CONN_TRY;
	std::vector< int > viIDs;
878
	g_pVANetClient->GetCoreInstance()->GetSoundReceiverIDs( viIDs );
879 880 881 882 883 884 885 886 887 888

	PyObject* pIDList = PyList_New( viIDs.size() );
	for( Py_ssize_t i = 0; i < PyList_GET_SIZE( pIDList ); i++ )
		PyList_SetItem( pIDList, i, PyLong_FromLong( viIDs[ i ] ) );

	return pIDList;

	VAPY_CATCH_RETURN;
};

889
static PyObject* create_sound_receiver( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
890 891 892 893
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "name", NULL };
894
	static _PyArg_Parser _parser = { "s:create_sound_receiver", _keywords, 0 };
895 896 897 898
	char* pcName = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcName ) )
		return NULL;

899 900
	std::string sName = pcName ? std::string( pcName ) : "PySoundReceiver";
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundReceiver( sName ) );
901 902 903 904

	VAPY_CATCH_RETURN;
};

905
static PyObject* create_sound_receiver_explicit_renderer( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
906 907 908
{
	VAPY_REQUIRE_CONN_TRY;

909 910
	static const char * const _keywords[] = { "renderer", "name", NULL };
	static _PyArg_Parser _parser = { "ss:create_sound_receiver_explicit_renderer", _keywords, 0 };