vasingletonmethods.hpp 7.73 KB
Newer Older
1 2 3
#include <Python.h>
#include <VANetClient.h>
#include <VACore.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
4
#include <VAStruct.h>
5 6 7
#include <VAException.h>
#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* va_not_implemented(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
21 22 23
{
	VA_EXCEPT_NOT_IMPLEMENTED;
	return NULL;
24
};
25

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

32 33 34
	if (!g_pVANetClient->GetCoreInstance())
		VA_EXCEPT2(CVAException::NETWORK_ERROR, "VA client available, but access to VA interface failed. Please reconnect.");
};
35

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
36 37 38 39 40 41 42 43 44
//! Helper to convert recursively from VAStruct to Python dict
PyObject* ConvertVAStructToPythonDict( const CVAStruct& oInStruct )
{
	return PyLong_FromLong( -1 );
};

//! Helper to convert recursively from Python dict to VAStruct
CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict )
{
45 46 47 48 49 50 51 52 53 54 55 56 57 58 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 89 90 91 92 93 94 95 96 97 98 99 100 101
	CVAStruct oReturn;

	PyObject* pKeyList = PyDict_Keys(pInDict);
	PyObject* pValueList = PyDict_Values(pInDict);

	for (Py_ssize_t i = 0; i < PyList_Size(pKeyList); i++)
	{
		PyObject* pKey = PyList_GetItem(pKeyList, i);
		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 ) + "'");

		if (Py_None == pValue)
		{
			oReturn[pcKeyName] = false;
		}
		else if (PyBool_Check(pValue))
		{
			oReturn[pcKeyName] = bool(PyLong_AsLong(pValue));
		}
		else if (PyLong_Check(pValue))
		{
			oReturn[pcKeyName] = PyLong_AsLong(pValue);
		}
		else if (PyFloat_Check(pValue))
		{
			oReturn[pcKeyName] = PyFloat_AsDouble(pValue);
		}
		else if (PyUnicode_Check(pValue))
		{
			char* pcStringValue = nullptr;
			if (!PyArg_Parse(pValue, "s", &pcStringValue))
				VA_EXCEPT2(CVAException::INVALID_PARAMETER, "Invalid string value at key '" + std::string(pcKeyName) + "': " + std::string(pcStringValue));
			oReturn[pcKeyName] = std::string(pcStringValue);
		}
		else if (PyDict_Check(pValue))
		{
			oReturn[pcKeyName] = ConvertPythonDictToVAStruct( pValue);
		}
		else if (PyList_Check(pValue))
		{
			// Sample buffer
			VA_EXCEPT_NOT_IMPLEMENTED;
		}
		else if (PyByteArray_Check(pValue))
		{
			// Data blob
			VA_EXCEPT_NOT_IMPLEMENTED;
		}
		else
		{
			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + std::string(pcKeyName) + "' as a supported VAStruct type.")
		}
	}

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


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

107
static PyObject* va_connect(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
108
{
109
	if (!g_pVANetClient)
110 111
		g_pVANetClient = IVANetClient::Create();

112
	if (g_pVANetClient->IsConnected())
113
	{
114
		PyErr_WarnEx(NULL, "Was still connected, forced disconnect.", 1 );
115
		g_pVANetClient->Disconnect();
116 117 118
	}

	static const char * const _keywords[] = { "server", "port", NULL };
119
	static _PyArg_Parser _parser = { "|si:connect", _keywords, 0 };
120
	char* pcServerIP = nullptr;
121 122
	int iServerPort = 12340;

123
	if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &pcServerIP, &iServerPort))
124
		return NULL;
125

126
	std::string sServerIP = pcServerIP ? std::string(pcServerIP) : "localhost";
127

128 129 130 131
	if (IVANetClient::VA_NO_ERROR == g_pVANetClient->Initialize(sServerIP, iServerPort))
		return PyBool_FromLong(1);

	PyErr_SetString(PyExc_ConnectionError, std::string("Could not connect to " + sServerIP + " on " + std::to_string((long)iServerPort)).c_str());
132
	return NULL;
133
};
134

135
static PyObject* va_disconnect(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
136
{
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
137 138
	if( !g_pVANetClient )
		return PyBool_FromLong( 0 );
139

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
140
	return PyBool_FromLong( g_pVANetClient->Disconnect() );
141
};
142

143
static PyObject* va_is_connected(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
144
{
145 146
	if (!g_pVANetClient)
		return PyBool_FromLong(0);
147
	else
148 149
		return PyBool_FromLong(g_pVANetClient->IsConnected());
};
150

151
static PyObject* va_reset(PyObject*, PyObject*)
152
{
153
	VAPY_REQUIRE_CONN_TRY;
154
	g_pVANetClient->GetCoreInstance()->Reset();
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
155 156
	Py_INCREF( Py_None );
	return Py_None;
157 158
	VAPY_CATCH_RETURN;
};
159

160
static PyObject* va_enumerate_modules(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
161
{
162
	VAPY_REQUIRE_CONN_TRY;
163 164 165 166

	std::vector< CVAModuleInfo > voModuleInfos;
	g_pVANetClient->GetCoreInstance()->EnumerateModules(voModuleInfos);

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
167
	PyObject* pModuleList = PyList_New(voModuleInfos.size());
168 169 170 171

	for (size_t i = 0; i < voModuleInfos.size(); i++)
	{
		CVAModuleInfo& oModule(voModuleInfos[i]);
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
172
		PyObject* pModuleInfo = Py_BuildValue("{s:i,s:s,s:s}", "index", i, "name", oModule.sName.c_str(), "description", oModule.sDesc.c_str() );
173 174 175 176 177
		PyList_SetItem(pModuleList, i, pModuleInfo); // steals reference
	}

	return pModuleList;

178 179 180 181
	VAPY_CATCH_RETURN;
};

static PyObject* va_call_module(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
182
{
183
	VAPY_REQUIRE_CONN_TRY;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
184
	
185 186
	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
187
	char* pcModuleName = nullptr;
188
	PyObject* pArgumentsDict = nullptr;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
189

190
	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &PyDict_Type, &pArgumentsDict ) )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
191 192 193
		return NULL;
	
	std::string sModuleName = std::string( pcModuleName );
194 195
	CVAStruct oInArgs = ConvertPythonDictToVAStruct( pArgumentsDict );
	CVAStruct oOutArgs;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
196

197
	g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oInArgs, oOutArgs );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
198

199
	return ConvertVAStructToPythonDict( oOutArgs );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
200
	
201 202 203 204
	VAPY_CATCH_RETURN;
};

static PyObject* va_add_search_path(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
205
{
206
	VAPY_REQUIRE_CONN_TRY;
207

208 209 210 211 212 213 214
	static const char * const _keywords[] = { "directory_path", NULL };
	static _PyArg_Parser _parser = { "s:add_search_path", _keywords, 0 };
	char* pcPath = nullptr;
	if (!_PyArg_ParseStack(ppArgs, nArgs, pKeywordNames, &_parser, &pcPath))
		return NULL;

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

216 217 218 219
	VAPY_CATCH_RETURN;
};

static PyObject* va_create_listener(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames)
220
{
221
	VAPY_REQUIRE_CONN_TRY;
222 223

	std::string sName = "PyListener";
224
	int iID = g_pVANetClient->GetCoreInstance()->CreateListener(sName, IVACore::VA_AURAMODE_ALL);
225

226 227 228 229
	return PyLong_FromLong(iID);
	
	VAPY_CATCH_RETURN;
};
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
230 231 232 233 234 235 236 237 238 239 240 241

static PyObject* va_is_scene_locked( PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
{
	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 )
{
	VAPY_REQUIRE_CONN_TRY
	g_pVANetClient->GetCoreInstance()->LockScene();
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
242 243
	Py_INCREF( Py_None );
	return Py_None;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
244 245 246 247 248 249 250 251 252
	VAPY_CATCH_RETURN;
};

static PyObject* va_unlock_scene( PyObject* pSelf, PyObject** ppArgs, Py_ssize_t nArgs, PyObject* pKeywordNames )
{
	VAPY_REQUIRE_CONN_TRY;
	return PyLong_FromLong( g_pVANetClient->GetCoreInstance()->UnlockScene() );
	VAPY_CATCH_RETURN;
};