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