diff --git a/src/vasingletonmethods.hpp b/src/vasingletonmethods.hpp index b10c9f3d91aaa9d638495864d1170a8fd20a1e97..dce51801e883d6cfeda2972e5ccbc069893fc106 100644 --- a/src/vasingletonmethods.hpp +++ b/src/vasingletonmethods.hpp @@ -17,10 +17,9 @@ static PyObject* g_pVAError = nullptr; //!< Static pointer to error instance #define VAPY_CATCH_RETURN } catch (const CVAException& oError) { PyErr_SetString(PyExc_Exception, oError.ToString().c_str()); return NULL; } //! Helper for API dev -static PyObject* va_not_implemented(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_not_implemented(PyObject*, PyObject*) { VA_EXCEPT_NOT_IMPLEMENTED; - return NULL; }; //! Raises an exception if core is not available @@ -34,13 +33,62 @@ static void RequireCoreAvailable() }; //! Helper to convert recursively from VAStruct to Python dict -PyObject* ConvertVAStructToPythonDict( const CVAStruct& oInStruct ) +PyObject* ConvertVAStructToPythonDict(const CVAStruct& oInStruct) { - return PyLong_FromLong( -1 ); + PyObject* pOutDict = PyDict_New(); + + CVAStruct::const_iterator cit = oInStruct.Begin(); + while (cit != oInStruct.End()) + { + const std::string sKey((*cit++).first); + const CVAStructValue& oValue(oInStruct[sKey]); + + PyObject* pNewValue = nullptr; + if (oValue.IsBool()) + { + pNewValue = PyBool_FromLong(bool(oValue)); + } + else if (oValue.IsInt()) + { + pNewValue = PyLong_FromLong(int(oValue)); + } + else if (oValue.IsDouble()) + { + pNewValue = PyFloat_FromDouble(double(oValue)); + } + else if (oValue.IsString()) + { + pNewValue = PyUnicode_FromString(std::string(oValue).c_str()); + } + else if (oValue.IsStruct()) + { + pNewValue = ConvertVAStructToPythonDict(oValue); + } + else if (oValue.IsData()) + { + VA_EXCEPT_NOT_IMPLEMENTED; + } + else if (oValue.IsSampleBuffer()) + { + VA_EXCEPT_NOT_IMPLEMENTED; + } + else + { + VA_EXCEPT2(INVALID_PARAMETER, "Could not interpret value of key '" + sKey + "' as a supported python dict type. Value was" + oValue.ToString()); + } + + if (!pNewValue) + VA_EXCEPT2(INVALID_PARAMETER, "Could not create python object from value of key '" + sKey + "'. Value was" + oValue.ToString()); + + 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()); + } + + return pOutDict; }; //! Helper to convert recursively from Python dict to VAStruct -CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) +CVAStruct ConvertPythonDictToVAStruct(PyObject* pInDict) { CVAStruct oReturn; @@ -53,7 +101,7 @@ CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) PyObject* pValue = PyList_GetItem(pValueList, i); char* pcKeyName = nullptr; if (!PyArg_Parse(pKey, "s", &pcKeyName)) - VA_EXCEPT2(CVAException::INVALID_PARAMETER, "Invalid key '" + std::string( pcKeyName ) + "'"); + VA_EXCEPT2(CVAException::INVALID_PARAMETER, "Invalid key '" + std::string(pcKeyName) + "'"); if (Py_None == pValue) { @@ -61,7 +109,7 @@ CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) } else if (PyBool_Check(pValue)) { - oReturn[pcKeyName] = bool(PyLong_AsLong(pValue)); + oReturn[pcKeyName] = ( PyLong_AsLong(pValue) != 0 ); } else if (PyLong_Check(pValue)) { @@ -80,7 +128,7 @@ CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) } else if (PyDict_Check(pValue)) { - oReturn[pcKeyName] = ConvertPythonDictToVAStruct( pValue); + oReturn[pcKeyName] = ConvertPythonDictToVAStruct(pValue); } else if (PyList_Check(pValue)) { @@ -94,7 +142,7 @@ CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) } else { - VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + std::string(pcKeyName) + "' as a supported VAStruct type.") + VA_EXCEPT2(INVALID_PARAMETER, "Could not interpret value of key '" + std::string(pcKeyName) + "' as a supported VAStruct type.") } } @@ -104,14 +152,14 @@ CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict ) // ------------------------------- Python module extension methods -static PyObject* va_connect(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_connect(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) { if (!g_pVANetClient) g_pVANetClient = IVANetClient::Create(); if (g_pVANetClient->IsConnected()) { - PyErr_WarnEx(NULL, "Was still connected, forced disconnect.", 1 ); + PyErr_WarnEx(NULL, "Was still connected, forced disconnect.", 1); g_pVANetClient->Disconnect(); } @@ -132,15 +180,15 @@ static PyObject* va_connect(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs return NULL; }; -static PyObject* va_disconnect(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_disconnect(PyObject*, PyObject*) { - if( !g_pVANetClient ) - return PyBool_FromLong( 0 ); + if (!g_pVANetClient) + return PyBool_FromLong(0); - return PyBool_FromLong( g_pVANetClient->Disconnect() ); + return PyBool_FromLong(g_pVANetClient->Disconnect()); }; -static PyObject* va_is_connected(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_is_connected(PyObject*, PyObject*) { if (!g_pVANetClient) return PyBool_FromLong(0); @@ -152,12 +200,12 @@ static PyObject* va_reset(PyObject*, PyObject*) { VAPY_REQUIRE_CONN_TRY; g_pVANetClient->GetCoreInstance()->Reset(); - Py_INCREF( Py_None ); + Py_INCREF(Py_None); return Py_None; VAPY_CATCH_RETURN; }; -static PyObject* va_enumerate_modules(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_enumerate_modules(PyObject*, PyObject*) { VAPY_REQUIRE_CONN_TRY; @@ -169,7 +217,7 @@ static PyObject* va_enumerate_modules(PyObject* pSelf, PyObject** ppArgs, Py_ssi for (size_t i = 0; i < voModuleInfos.size(); i++) { CVAModuleInfo& oModule(voModuleInfos[i]); - PyObject* pModuleInfo = Py_BuildValue("{s:i,s:s,s:s}", "index", i, "name", oModule.sName.c_str(), "description", oModule.sDesc.c_str() ); + PyObject* pModuleInfo = Py_BuildValue("{s:i,s:s,s:s}", "index", i, "name", oModule.sName.c_str(), "description", oModule.sDesc.c_str()); PyList_SetItem(pModuleList, i, pModuleInfo); // steals reference } @@ -178,30 +226,30 @@ static PyObject* va_enumerate_modules(PyObject* pSelf, PyObject** ppArgs, Py_ssi VAPY_CATCH_RETURN; }; -static PyObject* va_call_module(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_call_module(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) { VAPY_REQUIRE_CONN_TRY; - + static const char * const _keywords[] = { "module_name", "arguments_dict", NULL }; static _PyArg_Parser _parser = { "sO!:call_module", _keywords, 0 }; char* pcModuleName = nullptr; PyObject* pArgumentsDict = nullptr; - if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &PyDict_Type, &pArgumentsDict ) ) + if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &PyDict_Type, &pArgumentsDict)) return NULL; - - std::string sModuleName = std::string( pcModuleName ); - CVAStruct oInArgs = ConvertPythonDictToVAStruct( pArgumentsDict ); + + std::string sModuleName = std::string(pcModuleName); + CVAStruct oInArgs = ConvertPythonDictToVAStruct(pArgumentsDict); CVAStruct oOutArgs; - g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oInArgs, oOutArgs ); + g_pVANetClient->GetCoreInstance()->CallModule(sModuleName, oInArgs, oOutArgs); + + return ConvertVAStructToPythonDict(oOutArgs); - return ConvertVAStructToPythonDict( oOutArgs ); - VAPY_CATCH_RETURN; }; -static PyObject* va_add_search_path(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_add_search_path(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) { VAPY_REQUIRE_CONN_TRY; @@ -216,7 +264,7 @@ static PyObject* va_add_search_path(PyObject* pSelf, PyObject** ppArgs, Py_ssize VAPY_CATCH_RETURN; }; -static PyObject* va_create_listener(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +static PyObject* va_create_listener(PyObject*, PyObject*) { VAPY_REQUIRE_CONN_TRY; @@ -224,29 +272,110 @@ static PyObject* va_create_listener(PyObject* pSelf, PyObject** ppArgs, Py_ssize int iID = g_pVANetClient->GetCoreInstance()->CreateListener(sName, IVACore::VA_AURAMODE_ALL); return PyLong_FromLong(iID); - + VAPY_CATCH_RETURN; }; -static PyObject* va_is_scene_locked( PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames ) +static PyObject* va_is_scene_locked(PyObject*, PyObject*) { - VAPY_REQUIRE_CONN_TRY; - return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->IsSceneLocked() ); + VAPY_REQUIRE_CONN_TRY; + return PyLong_FromLong(g_pVANetClient->GetCoreInstance()->IsSceneLocked()); VAPY_CATCH_RETURN; }; -static PyObject* va_lock_scene( PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames ) +static PyObject* va_lock_scene(PyObject* , PyObject*) { - VAPY_REQUIRE_CONN_TRY + VAPY_REQUIRE_CONN_TRY; g_pVANetClient->GetCoreInstance()->LockScene(); - Py_INCREF( Py_None ); + Py_INCREF(Py_None); return Py_None; VAPY_CATCH_RETURN; }; -static PyObject* va_unlock_scene( PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames ) +static PyObject* va_unlock_scene(PyObject* , PyObject*) { VAPY_REQUIRE_CONN_TRY; - return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->UnlockScene() ); + return PyLong_FromLong(g_pVANetClient->GetCoreInstance()->UnlockScene()); VAPY_CATCH_RETURN; }; + +static PyObject* va_load_directivity(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +{ + VAPY_REQUIRE_CONN_TRY; + + static const char * const _keywords[] = { "path", "name", NULL }; + static _PyArg_Parser _parser = { "s|s:load_directivity", _keywords, 0 }; + char* pcPath = nullptr; + char* pcName = nullptr; + if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &pcPath, &pcName)) + return NULL; + + std::string sName = pcName ? std::string(pcName) : ""; + return PyBool_FromLong(g_pVANetClient->GetCoreInstance()->LoadDirectivity(std::string(pcPath), sName)); + + VAPY_CATCH_RETURN; +}; + +static PyObject* va_free_directivity(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +{ + VAPY_REQUIRE_CONN_TRY; + + static const char * const _keywords[] = { "id", NULL }; + static _PyArg_Parser _parser = { "i:free_directivity", _keywords, 0 }; + long iID = -1; + if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &iID)) + return NULL; + return PyBool_FromLong(g_pVANetClient->GetCoreInstance()->FreeDirectivity(iID)); + + VAPY_CATCH_RETURN; +}; + +static PyObject* va_get_directivity_info(PyObject*, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames) +{ + VAPY_REQUIRE_CONN_TRY; + + static const char * const _keywords[] = { "id", NULL }; + static _PyArg_Parser _parser = { "i:get_directivity_info", _keywords, 0 }; + long iID = -1; + if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &iID)) + return NULL; + + CVADirectivityInfo oInfo = g_pVANetClient->GetCoreInstance()->GetDirectivityInfo(iID); + + PyObject* pInfo = Py_BuildValue("{s:i,s:s,s:s,s:i,s:s}", + "id", oInfo.iID, + "name", oInfo.sName.c_str(), + "filepath", oInfo.sFilename.c_str(), + "references", oInfo.iReferences, + "description", oInfo.sDesc.c_str()); + + return pInfo; + + VAPY_CATCH_RETURN; +}; + +static PyObject* va_get_directivity_infos(PyObject*, PyObject*) +{ + VAPY_REQUIRE_CONN_TRY; + + std::vector< CVADirectivityInfo > voInfos; + g_pVANetClient->GetCoreInstance()->GetDirectivityInfos(voInfos); + + PyObject* pInfoList = PyList_New(voInfos.size()); + + for (size_t i = 0; i < voInfos.size(); i++) + { + CVADirectivityInfo& oInfo(voInfos[i]); + PyObject* pInfo = Py_BuildValue("{s:i,s:s,s:s,s:i,s:s}", + "id", oInfo.iID, + "name", oInfo.sName.c_str(), + "filepath", oInfo.sFilename.c_str(), + "references", oInfo.iReferences, + "description", oInfo.sDesc.c_str()); + PyList_SetItem(pInfoList, i, pInfo); // steals reference + } + + return pInfoList; + + VAPY_CATCH_RETURN; +}; \ No newline at end of file