Aufgrund einer Konfigurationsänderung wird die GitLab Registry ab 10 Uhr nur Read Only zur Verfügung stehen. / Due to a configuration change, the GitLab Registry will be available for read-only access from 10am.

vasingletonmethods.hpp 80 KB
Newer Older
1
#include <Python.h>
2 3 4 5

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

6 7
#include <string.h>

8
// If you want to extend the va Python pSelf interface, also add
9 10 11 12
// 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
13
static PyObject* g_pVAError = nullptr; //!< Static pointer to error instance
14

15 16 17 18
// 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; }

19
//! Helper for API dev
20
static PyObject* not_implemented( PyObject*, PyObject* )
21 22
{
	VA_EXCEPT_NOT_IMPLEMENTED;
23
};
24

25 26 27
//! Raises an exception if core is not available
static void RequireCoreAvailable()
{
28
	if( !g_pVANetClient )
29
		VA_EXCEPT2( NETWORK_ERROR, "VA client not available, please connect first" );
30

31
	if( !g_pVANetClient->GetCoreInstance() )
32
		VA_EXCEPT2( NETWORK_ERROR, "VA client available, but access to VA interface failed. Please reconnect." );
33 34 35 36 37 38 39 40 41 42 43
};

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 ];
44
};
45

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
46
//! Helper to convert recursively from VAStruct to Python dict
47
PyObject* ConvertVAStructToPythonDict( const CVAStruct& oInStruct )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
48
{
49 50 51
	PyObject* pOutDict = PyDict_New();

	CVAStruct::const_iterator cit = oInStruct.Begin();
52
	while( cit != oInStruct.End() )
53
	{
54 55
		const std::string sKey( ( *cit++ ).first );
		const CVAStructValue& oValue( oInStruct[ sKey ] );
56 57

		PyObject* pNewValue = nullptr;
58
		if( oValue.IsBool() )
59
		{
60
			pNewValue = PyBool_FromLong( bool( oValue ) );
61
		}
62
		else if( oValue.IsInt() )
63
		{
64
			pNewValue = PyLong_FromLong( int( oValue ) );
65
		}
66
		else if( oValue.IsDouble() )
67
		{
68
			pNewValue = PyFloat_FromDouble( double( oValue ) );
69
		}
70
		else if( oValue.IsString() )
71
		{
72
			pNewValue = PyUnicode_FromString( SaveStringToUnicodeConversion( std::string( oValue ) ).c_str() );
73
		}
74
		else if( oValue.IsStruct() )
75
		{
76
			pNewValue = ConvertVAStructToPythonDict( oValue );
77
		}
78
		else if( oValue.IsData() )
79
		{
80 81
			pNewValue = PyByteArray_FromStringAndSize( ( char* ) oValue.GetData(), oValue.GetDataSize() );
			Py_INCREF( pNewValue );
82
		}
83
		else if( oValue.IsSampleBuffer() )
84
		{
85 86 87 88 89
			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 ] ) );
90 91 92
		}
		else
		{
93
			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + sKey + "' as a supported python dict type. Value was" + oValue.ToString() );
94 95
		}

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

99 100
		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() );
101 102 103
	}

	return pOutDict;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
104 105 106
};

//! Helper to convert recursively from Python dict to VAStruct
107
CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
108
{
109 110
	CVAStruct oReturn;

111 112
	PyObject* pKeyList = PyDict_Keys( pInDict );
	PyObject* pValueList = PyDict_Values( pInDict );
113

114
	for( Py_ssize_t i = 0; i < PyList_Size( pKeyList ); i++ )
115
	{
116 117
		PyObject* pKey = PyList_GetItem( pKeyList, i );
		PyObject* pValue = PyList_GetItem( pValueList, i );
118
		char* pcKeyName = nullptr;
119
		if( !PyArg_Parse( pKey, "s", &pcKeyName ) )
120
			VA_EXCEPT2( INVALID_PARAMETER, "Invalid key '" + std::string( pcKeyName ) + "'" );
121

122
		if( Py_None == pValue )
123
		{
124
			oReturn[ pcKeyName ] = false;
125
		}
126
		else if( PyBool_Check( pValue ) )
127
		{
128
			oReturn[ pcKeyName ] = ( PyLong_AsLong( pValue ) != 0 );
129
		}
130
		else if( PyLong_Check( pValue ) )
131
		{
132
			oReturn[ pcKeyName ] = PyLong_AsLong( pValue );
133
		}
134
		else if( PyFloat_Check( pValue ) )
135
		{
136
			oReturn[ pcKeyName ] = PyFloat_AsDouble( pValue );
137
		}
138
		else if( PyUnicode_Check( pValue ) )
139 140
		{
			char* pcStringValue = nullptr;
141
			if( !PyArg_Parse( pValue, "s", &pcStringValue ) )
142
				VA_EXCEPT2( INVALID_PARAMETER, "Invalid string value at key '" + std::string( pcKeyName ) + "': " + std::string( pcStringValue ) );
143
			oReturn[ pcKeyName ] = std::string( pcStringValue );
144
		}
145
		else if( PyDict_Check( pValue ) )
146
		{
147
			oReturn[ pcKeyName ] = ConvertPythonDictToVAStruct( pValue );
148
		}
149
		else if( PyList_Check( pValue ) )
150 151
		{
			// Sample buffer
152 153 154 155 156 157 158 159 160 161
			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
				{
162
					oBuffer.vfSamples[ n ] = float( PyFloat_AsDouble( pSample ) );
163 164 165
				}
			}
			oReturn[ pcKeyName ] = oBuffer;
166
		}
167
		else if( PyBytes_Check( pValue ) )
168 169
		{
			// Data blob
170 171 172
			size_t iBytes = PyBytes_Size( pValue );
			char* pcData = PyBytes_AsString( pValue );
			oReturn[ pcKeyName ] = CVAStructValue( pcData, int( iBytes ) );
173 174 175
		}
		else
		{
176
			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + std::string( pcKeyName ) + "' as a supported VAStruct type." )
177 178 179 180
		}
	}

	return oReturn;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
181 182 183 184 185
};


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

186
static PyObject* connect( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
187
{
188
	if( !g_pVANetClient )
189 190
		g_pVANetClient = IVANetClient::Create();

191
	if( g_pVANetClient->IsConnected() )
192
	{
193
		PyErr_WarnEx( NULL, "Was still connected, forced disconnect.", 1 );
194
		g_pVANetClient->Disconnect();
195 196 197
	}

	static const char * const _keywords[] = { "server", "port", NULL };
198
	static _PyArg_Parser _parser = { "|si:connect", _keywords, 0 };
199
	char* pcServerIP = nullptr;
200 201
	int iServerPort = 12340;

202
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcServerIP, &iServerPort ) )
203
		return NULL;
204

205
	std::string sServerIP = pcServerIP ? std::string( pcServerIP ) : "localhost";
206

207 208
	if( IVANetClient::VA_NO_ERROR == g_pVANetClient->Initialize( sServerIP, iServerPort ) )
		return PyBool_FromLong( 1 );
209

210
	PyErr_SetString( PyExc_ConnectionError, std::string( "Could not connect to " + sServerIP + " on " + std::to_string( ( long ) iServerPort ) ).c_str() );
211
	return NULL;
212
};
213

214
static PyObject* disconnect( PyObject*, PyObject* )
215
{
216 217
	if( !g_pVANetClient )
		return PyBool_FromLong( 0 );
218

219
	return PyBool_FromLong( g_pVANetClient->Disconnect() );
220
};
221

222
static PyObject* is_connected( PyObject*, PyObject* )
223
{
224 225
	if( !g_pVANetClient )
		return PyBool_FromLong( 0 );
226
	else
227
		return PyBool_FromLong( g_pVANetClient->IsConnected() );
228
};
229

230
static PyObject* reset( PyObject*, PyObject* )
231
{
232
	VAPY_REQUIRE_CONN_TRY;
233
	g_pVANetClient->GetCoreInstance()->Reset();
234
	Py_INCREF( Py_None );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
235
	return Py_None;
236 237
	VAPY_CATCH_RETURN;
};
238

239
static PyObject* get_modules( PyObject*, PyObject* )
240
{
241
	VAPY_REQUIRE_CONN_TRY;
242 243

	std::vector< CVAModuleInfo > voModuleInfos;
244
	g_pVANetClient->GetCoreInstance()->GetModules( voModuleInfos );
245

246
	PyObject* pModuleList = PyList_New( voModuleInfos.size() );
247

248
	for( size_t i = 0; i < voModuleInfos.size(); i++ )
249
	{
250
		CVAModuleInfo& oModule( voModuleInfos[ i ] );
251
		PyObject* pModuleInfo = Py_BuildValue( "{s:i,s:s,s:s}", "index", i, "name", SaveStringToUnicodeConversion( oModule.sName ).c_str(), "description", SaveStringToUnicodeConversion( oModule.sDesc ).c_str() );
252
		PyList_SetItem( pModuleList, i, pModuleInfo ); // steals reference
253 254 255 256
	}

	return pModuleList;

257 258 259
	VAPY_CATCH_RETURN;
};

260
static PyObject* call_module( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
261
{
262
	VAPY_REQUIRE_CONN_TRY;
263

264 265
	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
266
	char* pcModuleName = nullptr;
267
	PyObject* pArgumentsDict = nullptr;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
268

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

272 273
	std::string sModuleName = std::string( pcModuleName );
	CVAStruct oInArgs = ConvertPythonDictToVAStruct( pArgumentsDict );
274
	CVAStruct oOutArgs;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
275

276
	oOutArgs = g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oInArgs );
277

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

280 281 282
	VAPY_CATCH_RETURN;
};

283
static PyObject* add_search_path( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
284
{
285
	VAPY_REQUIRE_CONN_TRY;
286

287 288 289
	static const char * const _keywords[] = { "directory_path", NULL };
	static _PyArg_Parser _parser = { "s:add_search_path", _keywords, 0 };
	char* pcPath = nullptr;
290
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcPath ) )
291 292
		return NULL;

293
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->AddSearchPath( std::string( pcPath ) ) );
294

295 296 297
	VAPY_CATCH_RETURN;
};

298
static PyObject* get_update_locked( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
299
{
300
	VAPY_REQUIRE_CONN_TRY;
301
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->GetUpdateLocked() );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
302 303 304
	VAPY_CATCH_RETURN;
};

305
static PyObject* lock_update( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
306
{
307
	VAPY_REQUIRE_CONN_TRY;
308
	g_pVANetClient->GetCoreInstance()->LockUpdate();
309
	Py_INCREF( Py_None );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
310
	return Py_None;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
311 312 313
	VAPY_CATCH_RETURN;
};

314
static PyObject* unlock_update( PyObject*, PyObject* )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
315 316
{
	VAPY_REQUIRE_CONN_TRY;
317
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->UnlockUpdate() );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
318 319
	VAPY_CATCH_RETURN;
};
320

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

	static const char * const _keywords[] = { "path", "name", NULL };
326
	static _PyArg_Parser _parser = { "s|s:create_directivity_from_file", _keywords, 0 };
327 328
	char* pcPath = nullptr;
	char* pcName = nullptr;
329
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcPath, &pcName ) )
330 331
		return NULL;

332
	std::string sName = pcName ? std::string( pcName ) : "";
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
333
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateDirectivityFromFile( std::string( pcPath ), sName ) );
334 335 336 337

	VAPY_CATCH_RETURN;
};

338
static PyObject* delete_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
339 340 341 342
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", NULL };
343
	static _PyArg_Parser _parser = { "i:delete_directivity", _keywords, 0 };
344
	long iID = -1;
345
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID ) )
346
		return NULL;
347
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->DeleteDirectivity( iID ) );
348 349 350 351

	VAPY_CATCH_RETURN;
};

352
static PyObject* get_directivity_info( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
353 354 355 356 357 358
{
	VAPY_REQUIRE_CONN_TRY;

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

362
	CVADirectivityInfo oInfo = g_pVANetClient->GetCoreInstance()->GetDirectivityInfo( iID );
363

364
	PyObject* pInfo = Py_BuildValue( "{s:i,s:s,s:i,s:i,s:s}",
365
		"id", oInfo.iID,
366
		"name", SaveStringToUnicodeConversion( oInfo.sName ).c_str(),
367
		"class", oInfo.iClass,
368
		"references", oInfo.iReferences,
369
		"description", SaveStringToUnicodeConversion( oInfo.sDesc ).c_str() );
370 371 372 373 374 375

	return pInfo;

	VAPY_CATCH_RETURN;
};

376
static PyObject* get_directivity_infos( PyObject*, PyObject* )
377 378 379 380
{
	VAPY_REQUIRE_CONN_TRY;

	std::vector< CVADirectivityInfo > voInfos;
381
	g_pVANetClient->GetCoreInstance()->GetDirectivityInfos( voInfos );
382

383
	PyObject* pInfoList = PyList_New( voInfos.size() );
384

385
	for( size_t i = 0; i < voInfos.size(); i++ )
386
	{
387
		CVADirectivityInfo& oInfo( voInfos[ i ] );
388
		PyObject* pInfo = Py_BuildValue( "{s:i,s:s,s:i,s:i,s:s}",
389
			"id", oInfo.iID,
390
			"name", SaveStringToUnicodeConversion( oInfo.sName ).c_str(),
391
			"class", oInfo.iClass,
392
			"references", oInfo.iReferences,
393 394
			"description", SaveStringToUnicodeConversion( oInfo.sDesc ).c_str() );
		PyList_SetItem( pInfoList, i, pInfo ); // steals reference
395 396 397 398 399 400
	}

	return pInfoList;

	VAPY_CATCH_RETURN;
};
401

402
static PyObject* get_sound_source_ids( PyObject*, PyObject* )
403 404 405 406 407 408 409 410 411 412 413 414 415 416
{
	VAPY_REQUIRE_CONN_TRY;
	std::vector< int > viIDs;
	g_pVANetClient->GetCoreInstance()->GetSoundSourceIDs( viIDs );

	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;
};

417
static PyObject* create_sound_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
418 419 420 421 422 423 424 425 426 427
{
	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";
428
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundSource( sName ) );
429 430 431 432 433

	VAPY_CATCH_RETURN;
};


434
static PyObject* create_sound_source_explicit_renderer( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
435 436 437
{
	VAPY_REQUIRE_CONN_TRY;

438
	static const char * const _keywords[] = { "renderer", "name", NULL };
439 440
	static _PyArg_Parser _parser = { "ss:create_sound_source_explicit_renderer", _keywords, 0 };
	char* pcRenderer = nullptr;
441 442
	char* pcName = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcRenderer, &pcName ) )
443 444 445 446
		return NULL;

	std::string sRenderer = pcRenderer ? std::string( pcRenderer ) : "Unspecified";
	std::string sName = pcName ? std::string( pcName ) : "PySoundSource_" + sRenderer;
447
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundSourceExplicitRenderer( sRenderer, sName ) );
448 449 450 451

	VAPY_CATCH_RETURN;
};

452
static PyObject* delete_sound_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
453 454 455 456 457 458 459 460 461 462 463 464 465 466
{
	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;
};

467
static PyObject* set_sound_source_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
{
	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;
};

484
static PyObject* get_sound_source_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
485 486 487 488 489 490 491 492 493 494 495 496 497 498
{
	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;
};

499
static PyObject* get_sound_source_name( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
500 501 502 503 504 505 506 507 508 509 510 511 512 513
{
	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;
};

514
static PyObject* get_sound_source_signal_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: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;
};

529
static PyObject* set_sound_source_signal_source( 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 546 547
{
	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;
};

548
static PyObject* remove_sound_source_signal_source( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
{
	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;
};

564
static PyObject* get_sound_source_auralization_mode( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
565 566 567 568 569 570 571 572 573 574 575 576 577 578
{
	VAPY_REQUIRE_CONN_TRY;

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

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

	VAPY_CATCH_RETURN;
};

579
static PyObject* set_sound_source_auralization_mode( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
{
	VAPY_REQUIRE_CONN_TRY;

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

	g_pVANetClient->GetCoreInstance()->SetSoundSourceAuralizationMode( iID, iAuralizationMode );
	return Py_None;

	VAPY_CATCH_RETURN;
};

596
static PyObject* set_sound_source_parameters( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
{
	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;
};


615
static PyObject* get_sound_source_parameters( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
{
	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;
};

633
static PyObject* get_sound_source_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
634 635 636 637 638 639 640 641 642 643 644 645 646 647
{
	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;
};

648
static PyObject* set_sound_source_directivity( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
{
	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;
};

665
static PyObject* get_sound_source_sound_power( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
666 667 668 669
{
	VAPY_REQUIRE_CONN_TRY;

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

675
	return PyFloat_FromDouble( g_pVANetClient->GetCoreInstance()->GetSoundSourceSoundPower( iID ) );
676 677 678 679

	VAPY_CATCH_RETURN;
};

680
static PyObject* set_sound_source_sound_power( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
681 682 683 684
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "gain", NULL };
685
	static _PyArg_Parser _parser = { "id:set_sound_source_sound_power", _keywords, 0 };
686
	long iID = -1;
687 688
	double dPower = -1;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &dPower ) )
689 690
		return NULL;

691
	g_pVANetClient->GetCoreInstance()->SetSoundSourceSoundPower( iID, dPower );
692 693 694 695 696
	return Py_None;

	VAPY_CATCH_RETURN;
};

697
static PyObject* set_sound_source_muted( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
{
	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;
};

714
static PyObject* get_sound_source_muted( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
715 716 717 718
{
	VAPY_REQUIRE_CONN_TRY;

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

724
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->GetSoundSourceMuted( iID ) );
725 726 727 728

	VAPY_CATCH_RETURN;
};

729
static PyObject* get_sound_source_position( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
730 731 732 733
{
	VAPY_REQUIRE_CONN_TRY;

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

739
	VAVec3 v3Pos = g_pVANetClient->GetCoreInstance()->GetSoundSourcePosition( iID );
740 741 742 743 744 745 746 747 748 749 750

	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;
};

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

	static const char * const _keywords[] = { "id", "pos", NULL };
756
	static _PyArg_Parser _parser = { "i(ddd):set_sound_source_position", _keywords, 0 };
757
	long iID = -1;
758 759
	VAVec3 v3Pos;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &v3Pos.x, &v3Pos.y, &v3Pos.z ) )
760 761
		return NULL;

762
	g_pVANetClient->GetCoreInstance()->SetSoundSourcePosition( iID, v3Pos );
763 764 765 766 767 768
	return Py_None;

	VAPY_CATCH_RETURN;
};


769
static PyObject* get_sound_source_orientation_vu( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
770 771 772 773 774 775 776 777 778 779
{
	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;
780
	g_pVANetClient->GetCoreInstance()->GetSoundSourceOrientationVU( iID, v3View, v3Up );
781

782
	return Py_BuildValue( "(ddd)(ddd)", v3View.x, v3View.y, v3View.z, v3Up.x, v3Up.y, v3Up.z );
783 784 785 786

	VAPY_CATCH_RETURN;
};

787
static PyObject* set_sound_source_orientation_vu( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
788 789 790 791
{
	VAPY_REQUIRE_CONN_TRY;

	static const char * const _keywords[] = { "id", "view", "up", NULL };
792
	static _PyArg_Parser _parser = { "i(ddd)(ddd):set_sound_source_orientation_vu", _keywords, 0 };
793
	long iID = -1;
794
	VAVec3 v3View, v3Up;
795
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &iID, &v3View.x, &v3View.y, &v3View.z, &v3Up.x, &v3Up.y, &v3Up.z ) )
796 797
		return NULL;

798
	g_pVANetClient->GetCoreInstance()->SetSoundSourceOrientationVU( iID, v3View, v3Up );
799 800 801 802
	return Py_None;

	VAPY_CATCH_RETURN;
};
803

804
static PyObject* get_sound_receiver_ids( PyObject*, PyObject* )
805 806 807
{
	VAPY_REQUIRE_CONN_TRY;
	std::vector< int > viIDs;
808
	g_pVANetClient->GetCoreInstance()->GetSoundReceiverIDs( viIDs );
809 810 811 812 813 814 815 816 817 818

	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;
};

819
static PyObject* create_sound_receiver( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
820 821 822 823
{
	VAPY_REQUIRE_CONN_TRY;

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

829 830
	std::string sName = pcName ? std::string( pcName ) : "PySoundReceiver";
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundReceiver( sName ) );
831 832 833 834

	VAPY_CATCH_RETURN;
};

835
static PyObject* create_sound_receiver_explicit_renderer( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
836 837 838
{
	VAPY_REQUIRE_CONN_TRY;

839 840
	static const char * const _keywords[] = { "renderer", "name", NULL };
	static _PyArg_Parser _parser = { "ss:create_sound_receiver_explicit_renderer", _keywords, 0 };
841
	char* pcRenderer = nullptr;
842 843
	char* pcName = nullptr;
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcRenderer, &pcName ) )
844 845 846
		return NULL;

	std::string sRenderer = pcRenderer ? std::string( pcRenderer ) : "Unspecified";
847 848
	std::string sName = pcName ? std::string( pcName ) : "PySoundReceiver_" + sRenderer;
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->CreateSoundReceiverExplicitRenderer( sRenderer, sName ) );
849 850 851 852

	VAPY_CATCH_RETURN;
};

853
static PyObject* delete_sound_receiver( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
854 855 856 857
{
	VAPY_REQUIRE_CONN_TRY;

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

863
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->DeleteSoundReceiver( iID ) );
864 865 866 867

	VAPY_CATCH_RETURN;
};

868
static PyObject* set_sound_receiver_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
869 870 871 872
{
	VAPY_REQUIRE_CONN_TRY;

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

879
	g_pVANetClient->GetCoreInstance()->SetSoundReceiverEnabled( iID, bEnabled );
880 881 882 883 884
	return Py_None;

	VAPY_CATCH_RETURN;
};

885
static PyObject* get_sound_receiver_enabled( PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
886 887 888 889
{
	VAPY_REQUIRE_CONN_TRY;

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

895
	return PyBool_FromLong( g_pVANetClient->GetCoreInstance()->GetSoundReceiverEnabled( iID ) );