コード例 #1
0
ファイル: XnXmlScriptNode.cpp プロジェクト: Clebeson/OpenNI
XnStatus xnConfigureRecorderDestination(XnNodeHandle hNode, const TiXmlElement* pOpcode)
{
	XnStatus nRetVal = XN_STATUS_OK;

	XnRecordMedium medium = XN_RECORD_MEDIUM_FILE; // default

	if (pOpcode->Attribute("medium") != NULL)
	{
		const XnChar* strMedium;
		nRetVal = xnXmlReadStringAttribute(pOpcode, "medium", &strMedium);
		XN_IS_STATUS_OK(nRetVal);

		if (strcmp(strMedium, "File") == 0)
		{
			medium = XN_RECORD_MEDIUM_FILE;
		}
		else
		{
			XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Unknown recording medium: '%s'", strMedium);
		}
	}

	const XnChar* strName;
	nRetVal = xnXmlReadStringAttribute(pOpcode, "name", &strName);
	XN_IS_STATUS_OK(nRetVal);

	nRetVal = xnSetRecorderDestination(hNode, XN_RECORD_MEDIUM_FILE, strName);
	XN_IS_STATUS_OK(nRetVal);

	return (XN_STATUS_OK);
}
コード例 #2
0
ファイル: XnXmlScriptNode.cpp プロジェクト: Clebeson/OpenNI
XnStatus xnConfigureAddNodeToRecording(XnNodeHandle hNode, const TiXmlElement* pOpcode)
{
	XnStatus nRetVal = XN_STATUS_OK;

	const XnChar* strName;
	nRetVal = xnXmlReadStringAttribute(pOpcode, "name", &strName);
	XN_IS_STATUS_OK(nRetVal);

	const XnChar* strCodec;
	nRetVal = xnXmlReadStringAttribute(pOpcode, "codec", &strCodec);
	XN_IS_STATUS_OK(nRetVal);

	// find node
	XnContext* pContext = hNode->pContext;
	XnNodeHandle hOther = NULL;
	nRetVal = xnGetRefNodeHandleByName(pContext, strName, &hOther);
	XN_IS_STATUS_OK(nRetVal);

	// find codec
	if (strlen(strCodec) != sizeof(XnCodecID))
	{
		xnProductionNodeRelease(hOther);
		XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "'%s' is not a valid codec ID!", strCodec);
	}

	XnCodecID codecID;
	xnOSMemCopy(&codecID, strCodec, sizeof(codecID));

	nRetVal = xnAddNodeToRecording(hNode, hOther, codecID);
	xnProductionNodeRelease(hOther);
	XN_IS_STATUS_OK(nRetVal);

	return (XN_STATUS_OK);
}
コード例 #3
0
ファイル: XnXmlScriptNode.cpp プロジェクト: Clebeson/OpenNI
XnStatus xnConfigureProperty(XnNodeHandle hNode, const TiXmlElement* pOpcode)
{
	XnStatus nRetVal = XN_STATUS_OK;

	const XnChar* strName;
	nRetVal = xnXmlReadStringAttribute(pOpcode, "name", &strName);
	XN_IS_STATUS_OK(nRetVal);

	const XnChar* strType;
	nRetVal = xnXmlReadStringAttribute(pOpcode, "type", &strType);
	XN_IS_STATUS_OK(nRetVal);

	if (strcmp(strType, "int") == 0)
	{
		XnInt nValue;
		nRetVal = xnXmlReadIntAttribute(pOpcode, "value", &nValue);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnSetIntProperty(hNode, strName, nValue);
		if (nRetVal != XN_STATUS_OK)
		{
			xnLogError(XN_MASK_OPEN_NI, "Failed to set property '%s' from xml: %s", strName, xnGetStatusString(nRetVal));
			return nRetVal;
		}
	}
	else if (strcmp(strType, "real") == 0)
	{
		XnDouble dValue;
		nRetVal = xnXmlReadRealAttribute(pOpcode, "value", &dValue);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnSetRealProperty(hNode, strName, dValue);
		if (nRetVal != XN_STATUS_OK)
		{
			xnLogError(XN_MASK_OPEN_NI, "Failed to set property '%s' from xml: %s", strName, xnGetStatusString(nRetVal));
			return nRetVal;
		}
	}
	else if (strcmp(strType, "string") == 0)
	{
		const XnChar* strValue;
		nRetVal = xnXmlReadStringAttribute(pOpcode, "value", &strValue);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnSetStringProperty(hNode, strName, strValue);
		if (nRetVal != XN_STATUS_OK)
		{
			xnLogError(XN_MASK_OPEN_NI, "Failed to set property '%s' from xml: %s", strName, xnGetStatusString(nRetVal));
			return nRetVal;
		}
	}
	else
	{
		XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Invalid property type: %s", strType);
	}

	return (XN_STATUS_OK);
}
コード例 #4
0
ファイル: XnLicensing.cpp プロジェクト: yosilove/OpenNI
	XnStatus FromElement(const TiXmlElement* pElement)
	{
		XnStatus nRetVal = XN_STATUS_OK;
		
		const XnChar* strVendor;
		nRetVal = xnXmlReadStringAttribute(pElement, XN_XML_LICENSE_VENDOR, &strVendor);
		XN_IS_STATUS_OK(nRetVal);

		const XnChar* strKey;
		nRetVal = xnXmlReadStringAttribute(pElement, XN_XML_LICENSE_KEY, &strKey);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnOSStrNCopy(this->strVendor, strVendor, strlen(strVendor) + 1, sizeof(this->strVendor));
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnOSStrNCopy(this->strKey, strKey, strlen(strKey) + 1, sizeof(this->strKey));
		XN_IS_STATUS_OK(nRetVal);
		
		return (XN_STATUS_OK);
	}
コード例 #5
0
ファイル: XnXmlScriptNode.cpp プロジェクト: Clebeson/OpenNI
XnStatus xnConfigureCreateNodes(XnContext* pContext, const TiXmlElement* pRootElem, XnNodeInfoList* pCreatedNodes, XnEnumerationErrors* pErrors)
{
	XnStatus nRetVal = XN_STATUS_OK;

	const TiXmlElement* pProudctionNodes = pRootElem->FirstChildElement("ProductionNodes");
	if (pProudctionNodes == NULL)
	{
		return (XN_STATUS_OK);
	}

	// global mirror
	const TiXmlElement* pGlobalMirror = pProudctionNodes->FirstChildElement("GlobalMirror");
	if (pGlobalMirror != NULL)
	{
		XnBool bOn;
		nRetVal = xnXmlReadBoolAttribute(pGlobalMirror, "on", &bOn);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnSetGlobalMirror(pContext, bOn);
		XN_IS_STATUS_OK(nRetVal);
	}

	// file recordings
	const TiXmlElement* pRecording = pProudctionNodes->FirstChildElement("Recording");
	if (pRecording != NULL)
	{
		const XnChar* strFileName;
		nRetVal = xnXmlReadStringAttribute(pRecording, "file", &strFileName);
		XN_IS_STATUS_OK(nRetVal);

		xnLogVerbose(XN_MASK_OPEN_NI, "Opening file recording '%s'...", strFileName);

		XnNodeHandle hPlayer;
		nRetVal = xnContextOpenFileRecordingEx(pContext, strFileName, &hPlayer);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnNodeInfoListAddNode(pCreatedNodes, hPlayer->pNodeInfo);
		if (nRetVal != XN_STATUS_OK)
		{
			xnProductionNodeRelease(hPlayer);
			return (nRetVal);
		}

		XnDouble dSpeed = 1.0;
		if (NULL != pRecording->Attribute("playbackSpeed", &dSpeed))
		{
			nRetVal = xnSetPlaybackSpeed(hPlayer, dSpeed);
			XN_IS_STATUS_OK(nRetVal);
		}

		const XnChar* REPEAT = "repeat";
		if (NULL != pRecording->Attribute(REPEAT))
		{
			XnBool bRepeat;
			nRetVal = xnXmlReadBoolAttribute(pRecording, REPEAT, &bRepeat);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = xnSetPlayerRepeat(hPlayer, bRepeat);
			XN_IS_STATUS_OK(nRetVal);
		}
	}

	const XnChar* strNodeTagName = "Node";
	const XnChar* strStartGeneratingAttr = "startGenerating";

	XnBool bStartGeneratingAll = TRUE;
	if (NULL != pProudctionNodes->Attribute(strStartGeneratingAttr))
	{
		nRetVal = xnXmlReadBoolAttribute(pProudctionNodes, strStartGeneratingAttr, &bStartGeneratingAll);
		XN_IS_STATUS_OK(nRetVal);
	}

	// new nodes
	const TiXmlElement* pNode = pProudctionNodes->FirstChildElement(strNodeTagName);
	while (pNode != NULL)
	{
		// get type
		const XnChar* strType;
		nRetVal = xnXmlReadStringAttribute(pNode, "type", &strType);
		XN_IS_STATUS_OK(nRetVal);

		// check stopOnError status
		XnBool bStopOnError = TRUE;
		if (NULL != pNode->Attribute("stopOnError"))
		{
			nRetVal = xnXmlReadBoolAttribute(pNode, "stopOnError", &bStopOnError);
			XN_IS_STATUS_OK(nRetVal);
		}

		xnLogVerbose(XN_MASK_OPEN_NI, "Requested to create a node of type %s%s...", strType, bStopOnError ? "" : " (StopOnError=FALSE)");

		XnProductionNodeType Type;
		nRetVal = xnProductionNodeTypeFromString(strType, &Type);
		XN_IS_STATUS_OK(nRetVal);

		// check if there is a query
		XnNodeQuery* pQuery = NULL;
		const TiXmlElement* pQueryElem = pNode->FirstChildElement("Query");
		if (pQueryElem != NULL)
		{
			nRetVal = xnNodeQueryAllocate(&pQuery);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = xnXmlReadQuery(pQueryElem, pQuery);
			XN_IS_STATUS_OK(nRetVal);
		}

		// enumerate
		XnNodeInfoList* pTrees;
		nRetVal = xnEnumerateProductionTrees(pContext, Type, pQuery, &pTrees, pErrors);
		if (nRetVal == XN_STATUS_NO_NODE_PRESENT && !bStopOnError)
		{
			// go to next one
			pNode = pNode->NextSiblingElement(strNodeTagName);
			continue;
		}
		XN_IS_STATUS_OK(nRetVal);

		if (pQuery != NULL)
		{
			xnNodeQueryFree(pQuery);
			pQuery = NULL;
		}

		// choose first one
		XnNodeInfoListIterator itChosen = xnNodeInfoListGetFirst(pTrees);
		XnNodeInfo* pChosenInfo = xnNodeInfoListGetCurrent(itChosen);

		// check if a name was requested
		if (NULL != pNode->Attribute("name"))
		{
			const XnChar* strName = NULL;
			nRetVal = xnXmlReadStringAttribute(pNode, "name", &strName);
			if (nRetVal != XN_STATUS_OK)
			{
				xnNodeInfoListFree(pTrees);
				return (nRetVal);
			}

			nRetVal = xnNodeInfoSetInstanceName(pChosenInfo, strName);
			if (nRetVal != XN_STATUS_OK)
			{
				xnNodeInfoListFree(pTrees);
				return (nRetVal);
			}
		}

		// create it
		XnNodeHandle hNode;
		nRetVal = xnCreateProductionTree(pContext, pChosenInfo, &hNode);
		if (nRetVal != XN_STATUS_OK)
		{
			xnNodeInfoListFree(pTrees);
			return (nRetVal);
		}

		// free the list
		xnNodeInfoListFree(pTrees);

		// add it to the list of created nodes
		nRetVal = xnNodeInfoListAddNode(pCreatedNodes, pChosenInfo);
		if (nRetVal != XN_STATUS_OK)
		{
			xnProductionNodeRelease(hNode);
			return (nRetVal);
		}

		// config it
		nRetVal = xnConfigureNodeFromXml(hNode, pNode);
		if (nRetVal != XN_STATUS_OK)
		{
			xnProductionNodeRelease(hNode);
			return (nRetVal);
		}

		// check if we need to start it (if start generating all is on, it will be started at the end)
		XnBool bStart = FALSE;
		if (!bStartGeneratingAll)
		{
			if (NULL != pNode->Attribute(strStartGeneratingAttr))
			{
				nRetVal = xnXmlReadBoolAttribute(pNode, strStartGeneratingAttr, &bStart);
				if (nRetVal != XN_STATUS_OK)
				{
					xnProductionNodeRelease(hNode);
					return (nRetVal);
				}
			}

			if (bStart)
			{
				nRetVal = xnStartGenerating(hNode);
				if (nRetVal != XN_STATUS_OK)
				{
					xnProductionNodeRelease(hNode);
					return (nRetVal);
				}
			}
		}

		pNode = pNode->NextSiblingElement(strNodeTagName);
	}

	// start generating all created nodes (by the order they were created in)
	if (bStartGeneratingAll)
	{
		XnBool bIsGenerator;

		for (XnNodeInfoListIterator it = xnNodeInfoListGetFirst(pCreatedNodes);
			xnNodeInfoListIteratorIsValid(it);
			it = xnNodeInfoListGetNext(it))
		{
			XnNodeInfo* pNodeInfo = xnNodeInfoListGetCurrent(it);
			nRetVal = TypeManager::GetInstance().IsTypeDerivedFrom(pNodeInfo->Description.Type, XN_NODE_TYPE_GENERATOR, &bIsGenerator);
			XN_IS_STATUS_OK(nRetVal);

			if (bIsGenerator)
			{
				XN_ASSERT(pNodeInfo->hNode != NULL);
				nRetVal = xnStartGenerating(pNodeInfo->hNode);
				XN_IS_STATUS_OK(nRetVal);
			}
		}
	}

	return (XN_STATUS_OK);
}
コード例 #6
0
XN_C_API XnStatus xnLogInitFromXmlFile(const XnChar* strFileName)
{
	XnStatus nRetVal = XN_STATUS_OK;

	nRetVal = xnLogInitSystem();
	XN_IS_STATUS_OK(nRetVal);

	TiXmlDocument doc;
	nRetVal = xnXmlLoadDocument(doc, strFileName);
	XN_IS_STATUS_OK(nRetVal);

	TiXmlElement* pRootElem = doc.RootElement();
	if (pRootElem != NULL)
	{
		TiXmlElement* pLog = pRootElem->FirstChildElement("Log");
		if (pLog != NULL)
		{
			XnBool bOn;

			// configure filters
			TiXmlElement* pLogLevel = pLog->FirstChildElement("LogLevel");
			if (pLogLevel != NULL)
			{
				XnInt nValue;
				nRetVal = xnXmlReadIntAttribute(pLogLevel, "value", &nValue);
				XN_IS_STATUS_OK(nRetVal);

				nRetVal = xnLogSetSeverityFilter((XnLogSeverity)nValue);
				XN_IS_STATUS_OK(nRetVal);
			}

			TiXmlElement* pMasks = pLog->FirstChildElement("Masks");
			if (pMasks != NULL)
			{
				TiXmlElement* pMask = pMasks->FirstChildElement("Mask");
				while (pMask != NULL)
				{
					const XnChar* strName;
					nRetVal = xnXmlReadStringAttribute(pMask, "name", &strName);
					XN_IS_STATUS_OK(nRetVal);

					nRetVal = xnXmlReadBoolAttribute(pMask, "on", &bOn);
					XN_IS_STATUS_OK(nRetVal);

					nRetVal = xnLogSetMaskState(strName, bOn);
					XN_IS_STATUS_OK(nRetVal);

					pMask = pMask->NextSiblingElement("Mask");
				}
			}

			// configure writers
			if (pLog->Attribute("writeToConsole"))
			{
				nRetVal = xnXmlReadBoolAttribute(pLog, "writeToConsole", &bOn);
				XN_IS_STATUS_OK(nRetVal);

				nRetVal = xnLogSetConsoleOutput(bOn);
				XN_IS_STATUS_OK(nRetVal);
			}

			if (pLog->Attribute("writeToFile"))
			{
				nRetVal = xnXmlReadBoolAttribute(pLog, "writeToFile", &bOn);
				XN_IS_STATUS_OK(nRetVal);

				nRetVal = xnLogSetFileOutput(bOn);
				XN_IS_STATUS_OK(nRetVal);
			}

			if (pLog->Attribute("writeLineInfo"))
			{
				nRetVal = xnXmlReadBoolAttribute(pLog, "writeLineInfo", &bOn);
				XN_IS_STATUS_OK(nRetVal);

				nRetVal = xnLogSetLineInfo(bOn);
				XN_IS_STATUS_OK(nRetVal);
			}

			// Dumps
			TiXmlElement* pDumps = pLog->FirstChildElement("Dumps");
			if (pDumps != NULL)
			{
				TiXmlElement* pDump = pDumps->FirstChildElement("Dump");
				while (pDump != NULL)
				{
					const XnChar* strName;
					nRetVal = xnXmlReadStringAttribute(pDump, "name", &strName);
					XN_IS_STATUS_OK(nRetVal);

					nRetVal = xnXmlReadBoolAttribute(pDump, "on", &bOn);
					XN_IS_STATUS_OK(nRetVal);

					nRetVal = xnDumpSetMaskState(strName, bOn);
					XN_IS_STATUS_OK(nRetVal);

					pDump = pDump->NextSiblingElement("Dump");
				}
			}
		}
	}

	return (XN_STATUS_OK);
}
コード例 #7
0
ファイル: XnXmlConfig.cpp プロジェクト: yosilove/OpenNI
XnStatus xnConfigureCreateNodes(XnContext* pContext, const TiXmlElement* pRootElem, XnEnumerationErrors* pErrors)
{
	XnStatus nRetVal = XN_STATUS_OK;

	const TiXmlElement* pProudctionNodes = pRootElem->FirstChildElement("ProductionNodes");
	if (pProudctionNodes == NULL)
	{
		printf("XnXMLConfig::xnConfigureCreateNodes(): firstChildElement == ProductionNodes == NULL\n");
		return (XN_STATUS_OK);
	}

	// global mirror
	printf("XnXMLConfig::xnConfigureCreateNodes(): Check GlobalMirror\n");
	const TiXmlElement* pGlobalMirror = pProudctionNodes->FirstChildElement("GlobalMirror");
	if (pGlobalMirror != NULL)
	{
		XnBool bOn;
		nRetVal = xnXmlReadBoolAttribute(pGlobalMirror, "on", &bOn);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnSetGlobalMirror(pContext, bOn);
		XN_IS_STATUS_OK(nRetVal);
	}
	
	// file recordings
	const TiXmlElement* pRecording = pProudctionNodes->FirstChildElement("Recording");
	if (pRecording != NULL)
	{
		const XnChar* strFileName;
		nRetVal = xnXmlReadStringAttribute(pRecording, "file", &strFileName);
		XN_IS_STATUS_OK(nRetVal);

		xnLogVerbose(XN_MASK_OPEN_NI, "Opening file recording '%s'...", strFileName);

		nRetVal = xnContextOpenFileRecording(pContext, strFileName);
		XN_IS_STATUS_OK(nRetVal);
	}

	const XnChar* strNodeTagName = "Node";
	const XnChar* strStartGeneratingAttr = "startGenerating";

	XnBool bStartGeneratingAll = TRUE;
	if (NULL != pProudctionNodes->Attribute(strStartGeneratingAttr))
	{
		nRetVal = xnXmlReadBoolAttribute(pProudctionNodes, strStartGeneratingAttr, &bStartGeneratingAll);
		XN_IS_STATUS_OK(nRetVal);
	}

	// new nodes
	printf("XnXMLConfig::xnConfigureCreateNodes(): Start iterating over production nodes.\n");
	const TiXmlElement* pNode = pProudctionNodes->FirstChildElement(strNodeTagName);
	while (pNode != NULL)
	{
		// get type
		const XnChar* strType;
		nRetVal = xnXmlReadStringAttribute(pNode, "type", &strType);
		XN_IS_STATUS_OK(nRetVal);

		xnLogVerbose(XN_MASK_OPEN_NI, "Requested to create a node of type %s...", strType);

		XnProductionNodeType Type;
		printf("XnXMLConfig::xnConfigureCreateNodes(): call to xnProductionNodeTypeFromString()\n");
		nRetVal = xnProductionNodeTypeFromString(strType, &Type);
		printf("ProductoniNodeType (see Include/XnTypes.h): %d\n", Type);
		XN_IS_STATUS_OK(nRetVal);

		// check if there is a query
		XnNodeQuery* pQuery = NULL;
		const TiXmlElement* pQueryElem = pNode->FirstChildElement("Query");
		if (pQueryElem != NULL)
		{
			nRetVal = xnNodeQueryAllocate(&pQuery);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = xnXmlReadQuery(pQueryElem, pQuery);
			XN_IS_STATUS_OK(nRetVal);
		}

		// enumerate
		XnNodeInfoList* pTrees;
		printf("XnXMLConfig::xnConfigureCreateNodes(): call to xnEnumerateProductionTrees\n"); 
		nRetVal = xnEnumerateProductionTrees(pContext, Type, pQuery, &pTrees, pErrors); // @todo Porting to Mac - this is where it goes wrong.
		XN_IS_STATUS_OK(nRetVal);
		
		if (pQuery != NULL)
		{
			xnNodeQueryFree(pQuery);
			pQuery = NULL;
		}

		// choose first one
		XnNodeInfoListIterator itChosen = xnNodeInfoListGetFirst(pTrees);
		XnNodeInfo* pChosenInfo = xnNodeInfoListGetCurrent(itChosen);

		// check if a name was requested
		if (NULL != pNode->Attribute("name"))
		{
			const XnChar* strName = NULL;
			nRetVal = xnXmlReadStringAttribute(pNode, "name", &strName);
			if (nRetVal != XN_STATUS_OK)
			{
				xnNodeInfoListFree(pTrees);
				return (nRetVal);
			}

			nRetVal = xnNodeInfoSetInstanceName(pChosenInfo, strName);
			if (nRetVal != XN_STATUS_OK)
			{
				xnNodeInfoListFree(pTrees);
				return (nRetVal);
			}
		}
		
		// create it
		printf("XnXMLConfig::xnConfigureCreateNodes(): call to xnCreateProductionTree()"); 
		XnNodeHandle hNode;
		nRetVal = xnCreateProductionTree(pContext, pChosenInfo, &hNode);
		if (nRetVal != XN_STATUS_OK)
		{

			xnNodeInfoListFree(pTrees);
			return (nRetVal);
		}

		// free the list
		xnNodeInfoListFree(pTrees);

		// config it
		nRetVal = xnConfigureNodeFromXml(hNode, pNode);
		XN_IS_STATUS_OK(nRetVal);

		// check if we need to start it (if start generating all is on, it will be started at the end)
		XnBool bStart = FALSE;
		if (!bStartGeneratingAll)
		{
			if (NULL != pNode->Attribute(strStartGeneratingAttr))
			{
				nRetVal = xnXmlReadBoolAttribute(pNode, strStartGeneratingAttr, &bStart);
				XN_IS_STATUS_OK(nRetVal);
			}

			if (bStart)
			{
				nRetVal = xnStartGenerating(hNode);
				XN_IS_STATUS_OK(nRetVal);
			}
		}

		pNode = pNode->NextSiblingElement(strNodeTagName);
	}

	// start generating all
	if (bStartGeneratingAll)
	{
		nRetVal = xnStartGeneratingAll(pContext);
		XN_IS_STATUS_OK(nRetVal);
	}

	return (XN_STATUS_OK);
}
コード例 #8
0
ファイル: XnXmlConfig.cpp プロジェクト: samvit/noseTracking
XnStatus xnConfigureCreateNodes(XnContext* pContext, const TiXmlElement* pRootElem, XnEnumerationErrors* pErrors)
{
    XnStatus nRetVal = XN_STATUS_OK;

    const TiXmlElement* pProudctionNodes = pRootElem->FirstChildElement("ProductionNodes");
    if (pProudctionNodes == NULL)
    {
        return (XN_STATUS_OK);
    }

    // global mirror
    const TiXmlElement* pGlobalMirror = pProudctionNodes->FirstChildElement("GlobalMirror");
    if (pGlobalMirror != NULL)
    {
        XnBool bOn;
        nRetVal = xnXmlReadBoolAttribute(pGlobalMirror, "on", &bOn);
        XN_IS_STATUS_OK(nRetVal);

        nRetVal = xnSetGlobalMirror(pContext, bOn);
        XN_IS_STATUS_OK(nRetVal);
    }

    // file recordings
    const TiXmlElement* pRecording = pProudctionNodes->FirstChildElement("Recording");
    if (pRecording != NULL)
    {
        const XnChar* strFileName;
        nRetVal = xnXmlReadStringAttribute(pRecording, "file", &strFileName);
        XN_IS_STATUS_OK(nRetVal);

        xnLogVerbose(XN_MASK_OPEN_NI, "Opening file recording '%s'...", strFileName);

        nRetVal = xnContextOpenFileRecording(pContext, strFileName);
        XN_IS_STATUS_OK(nRetVal);

        XnDouble dSpeed = 1.0;
        if (NULL != pRecording->Attribute("playbackSpeed", &dSpeed))
        {
            XnNodeHandle hPlayer;
            nRetVal = xnFindExistingNodeByType(pContext, XN_NODE_TYPE_PLAYER, &hPlayer);
            XN_IS_STATUS_OK(nRetVal);

            nRetVal = xnSetPlaybackSpeed(hPlayer, dSpeed);
            XN_IS_STATUS_OK(nRetVal);
        }
    }

    const XnChar* strNodeTagName = "Node";
    const XnChar* strStartGeneratingAttr = "startGenerating";

    XnBool bStartGeneratingAll = TRUE;
    if (NULL != pProudctionNodes->Attribute(strStartGeneratingAttr))
    {
        nRetVal = xnXmlReadBoolAttribute(pProudctionNodes, strStartGeneratingAttr, &bStartGeneratingAll);
        XN_IS_STATUS_OK(nRetVal);
    }

    // new nodes
    const TiXmlElement* pNode = pProudctionNodes->FirstChildElement(strNodeTagName);
    while (pNode != NULL)
    {
        // get type
        const XnChar* strType;
        nRetVal = xnXmlReadStringAttribute(pNode, "type", &strType);
        XN_IS_STATUS_OK(nRetVal);

        xnLogVerbose(XN_MASK_OPEN_NI, "Requested to create a node of type %s...", strType);

        XnProductionNodeType Type;
        nRetVal = xnProductionNodeTypeFromString(strType, &Type);
        XN_IS_STATUS_OK(nRetVal);

        // check if there is a query
        XnNodeQuery* pQuery = NULL;
        const TiXmlElement* pQueryElem = pNode->FirstChildElement("Query");
        if (pQueryElem != NULL)
        {
            nRetVal = xnNodeQueryAllocate(&pQuery);
            XN_IS_STATUS_OK(nRetVal);

            nRetVal = xnXmlReadQuery(pQueryElem, pQuery);
            XN_IS_STATUS_OK(nRetVal);
        }

        // enumerate
        XnNodeInfoList* pTrees;
        nRetVal = xnEnumerateProductionTrees(pContext, Type, pQuery, &pTrees, pErrors);
        XN_IS_STATUS_OK(nRetVal);

        if (pQuery != NULL)
        {
            xnNodeQueryFree(pQuery);
            pQuery = NULL;
        }

        // choose first one
        XnNodeInfoListIterator itChosen = xnNodeInfoListGetFirst(pTrees);
        XnNodeInfo* pChosenInfo = xnNodeInfoListGetCurrent(itChosen);

        // check if a name was requested
        if (NULL != pNode->Attribute("name"))
        {
            const XnChar* strName = NULL;
            nRetVal = xnXmlReadStringAttribute(pNode, "name", &strName);
            if (nRetVal != XN_STATUS_OK)
            {
                xnNodeInfoListFree(pTrees);
                return (nRetVal);
            }

            nRetVal = xnNodeInfoSetInstanceName(pChosenInfo, strName);
            if (nRetVal != XN_STATUS_OK)
            {
                xnNodeInfoListFree(pTrees);
                return (nRetVal);
            }
        }

        // create it
        XnNodeHandle hNode;
        nRetVal = xnCreateProductionTree(pContext, pChosenInfo, &hNode);
        if (nRetVal != XN_STATUS_OK)
        {
            xnNodeInfoListFree(pTrees);
            return (nRetVal);
        }

        // free the list
        xnNodeInfoListFree(pTrees);

        // config it
        nRetVal = xnConfigureNodeFromXml(hNode, pNode);
        XN_IS_STATUS_OK(nRetVal);

        // check if we need to start it (if start generating all is on, it will be started at the end)
        XnBool bStart = FALSE;
        if (!bStartGeneratingAll)
        {
            if (NULL != pNode->Attribute(strStartGeneratingAttr))
            {
                nRetVal = xnXmlReadBoolAttribute(pNode, strStartGeneratingAttr, &bStart);
                XN_IS_STATUS_OK(nRetVal);
            }

            if (bStart)
            {
                nRetVal = xnStartGenerating(hNode);
                XN_IS_STATUS_OK(nRetVal);
            }
        }

        pNode = pNode->NextSiblingElement(strNodeTagName);
    }

    // start generating all
    if (bStartGeneratingAll)
    {
        nRetVal = xnStartGeneratingAll(pContext);
        XN_IS_STATUS_OK(nRetVal);
    }

    return (XN_STATUS_OK);
}