XnStatus XnDeviceBase::CloseAllStreams()
{
	XnStatus nRetVal = XN_STATUS_OK;

	xnLogVerbose(XN_MASK_DDK, "Closing all streams...");

	// go over modules list, and look for closed streams
	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();
		if (IsStream(pModuleHolder->GetModule()))
		{
			XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule();
			if (pStream->IsOpen())
			{
				nRetVal = pStream->Close();
				XN_IS_STATUS_OK(nRetVal);
			}
		}
	}

	xnLogInfo(XN_MASK_DDK, "All streams are closed.");

	return XN_STATUS_OK;
}
void xnLogGetMasksString(XnChar* csString)
{
	switch (g_logData.m_nLogFilteringType)
	{
	case XN_LOG_WRITE_NONE:
		xnOSStrCopy(csString, "NONE", XN_LOG_MASKS_STRING_LEN);
		return;
	case XN_LOG_WRITE_ALL:
		xnOSStrCopy(csString, "ALL", XN_LOG_MASKS_STRING_LEN);
		return;
	case XN_LOG_WRITE_MASKS:
		{
			csString[0] = '\0';

			for (XnStringsHash::Iterator it = g_logData.m_LogMasks.begin(); it != g_logData.m_LogMasks.end(); ++it)
			{
				xnOSStrAppend(csString, it.Key(), XN_LOG_MASKS_STRING_LEN);
				xnOSStrAppend(csString, ";", XN_LOG_MASKS_STRING_LEN);
			}

			return;
		}
	default:
		xnOSStrCopy(csString, "UNKNOWN", XN_LOG_MASKS_STRING_LEN);
		return;
	}
}
XnStatus XnDeviceBase::GetSupportedStreams(const XnChar** aStreamNames, XnUInt32* pnStreamNamesCount)
{
	XN_VALIDATE_OUTPUT_PTR(pnStreamNamesCount);
	// NOTE: we allow aStreamName to be NULL

	// first of all count streams
	XnUInt32 nStreamsCount = m_SupportedStreams.Size();

	// now check if we have enough room
	if (nStreamsCount > *pnStreamNamesCount)
	{
		*pnStreamNamesCount = nStreamsCount;
		return XN_STATUS_OUTPUT_BUFFER_OVERFLOW;
	}

	// now copy values
	nStreamsCount = 0;
	for (XnStringsHash::Iterator it = m_SupportedStreams.begin(); it != m_SupportedStreams.end(); ++it)
	{
		aStreamNames[nStreamsCount] = it.Key();
		nStreamsCount++;
	}

	*pnStreamNamesCount = nStreamsCount;
	return XN_STATUS_OK;
}
XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolderList& list)
{
	list.Clear();

	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		list.AddLast((XnDeviceModuleHolder*)it.Value());
	}

	return (XN_STATUS_OK);
}
XnStatus XnDeviceBase::GetModulesList(XnDeviceModuleHolder** apModules, XnUInt32* pnCount)
{
	XnUInt32 nCount = 0;

	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		apModules[nCount] = (XnDeviceModuleHolder*)it.Value();
		nCount++;
	}

	*pnCount = nCount;

	return (XN_STATUS_OK);
}
XnStatus XnDeviceBase::FindModule(const XnChar* ModuleName, XnDeviceModuleHolder** ppModuleHolder)
{
	XnStringsHash::Iterator it = m_Modules.end();
	XnStatus nRetVal = m_Modules.Find(ModuleName, it);
	if (nRetVal == XN_STATUS_NO_MATCH)
	{
		return (XN_STATUS_DEVICE_MODULE_NOT_FOUND);
	}
	XN_IS_STATUS_OK(nRetVal);

	*ppModuleHolder = (XnDeviceModuleHolder*)it.Value();

	return XN_STATUS_OK;
}
XnStatus XnDeviceBase::GetStreamsList(XnDeviceModuleHolderList& list)
{
	list.Clear();

	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();
		if (IsStream(pModuleHolder->GetModule()))
		{
			list.AddLast(pModuleHolder);
		}
	}

	return (XN_STATUS_OK);
}
XnStatus XnDeviceBase::SetMirror(XnBool bMirror)
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	// change all streams
	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();
		if (IsStream(pModuleHolder->GetModule()))
		{
			XnDeviceStream* pStream = (XnDeviceStream*)pModuleHolder->GetModule();
			nRetVal = pStream->SetMirror(bMirror);
			XN_IS_STATUS_OK(nRetVal);
		}
	}

	// and set property
	nRetVal = m_DeviceMirror.UnsafeUpdateValue(bMirror);
	XN_IS_STATUS_OK(nRetVal);
	
	return (XN_STATUS_OK);
}
XnStatus XnDeviceBase::GetStreamNames(const XnChar** pstrNames, XnUInt32* pnNamesCount)
{
	// first we need to count them
	XnUInt32 nCount = 0;

	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();
		if (IsStream(pModuleHolder->GetModule()))
		{
			nCount++;
		}
	}

	if (nCount > *pnNamesCount)
	{
		*pnNamesCount = nCount;
		return XN_STATUS_OUTPUT_BUFFER_OVERFLOW;
	}

	// OK. we have enough space. Copy into it
	nCount = 0;
	for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
	{
		XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();
		if (IsStream(pModuleHolder->GetModule()))
		{
			pstrNames[nCount] = it.Key();
			nCount++;
		}
	}

	*pnNamesCount = nCount;

	return XN_STATUS_OK;
}
XnStatus XnDeviceBase::GetAllProperties(XnPropertySet* pSet, XnBool bNoStreams /* = FALSE */, const XnChar* strModule /* = NULL */)
{
	XnStatus nRetVal = XN_STATUS_OK;

	XN_VALIDATE_INPUT_PTR(pSet);

	// clear the set
	nRetVal = XnPropertySetClear(pSet);
	XN_IS_STATUS_OK(nRetVal);

	if (strModule != NULL)
	{
		XnDeviceModule* pModule;
		nRetVal = FindModule(strModule, &pModule);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = pModule->GetAllProperties(pSet);
		XN_IS_STATUS_OK(nRetVal);
	}
	else
	{
		// enumerate over modules
		for (XnStringsHash::Iterator it = m_Modules.begin(); it != m_Modules.end(); ++it)
		{
			XnDeviceModuleHolder* pModuleHolder = (XnDeviceModuleHolder*)it.Value();

			if (bNoStreams && IsStream(pModuleHolder->GetModule()))
				continue;

			nRetVal = pModuleHolder->GetModule()->GetAllProperties(pSet);
			XN_IS_STATUS_OK(nRetVal);
		}
	}

	return XN_STATUS_OK;
}
XnStatus XnFileDevice::HandleStreamRemoved(const XnChar* strName)
{
	XnStatus nRetVal = XN_STATUS_OK;

	// check for specific case: all streams are removed and then end-of-file is reached.
	// in this case, we don't really want to destroy streams, just wrap around.
	XnStringsHash StreamsToRemove;
	nRetVal = StreamsToRemove.Set(strName, NULL);
	XN_IS_STATUS_OK(nRetVal);

	XnPackedDataType nType = XN_PACKED_STREAM_REMOVED;
	XnUInt32 nPositionBefore;

	while (TRUE)
	{
		nRetVal = m_pInputStream->Tell(&nPositionBefore);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = m_pDataPacker->ReadNextObject(&nType);
		XN_IS_STATUS_OK(nRetVal);

		if (nType == XN_PACKED_STREAM_REMOVED)
		{
			XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH];
			nRetVal = m_pDataPacker->ReadStreamRemoved(strTempName);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = StreamsToRemove.Set(strTempName, NULL);
			XN_IS_STATUS_OK(nRetVal);
		}
		else
		{
			break;
		}
	}

	if (nType != XN_PACKED_END)
	{
		// Not the case we were looking for. Remove those streams.
		for (XnStringsHash::Iterator it = StreamsToRemove.begin(); it != StreamsToRemove.end(); ++it)
		{
			nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, it.Key());
			XN_IS_STATUS_OK(nRetVal);

			XnNodeInfo* pNodeInfo;
			m_nodeInfoMap.Get(it.Key(), pNodeInfo);
			XN_DELETE(pNodeInfo->pXnCodec);
			m_nodeInfoMap.Remove(it.Key());
			m_ignoreNewNodes.Remove(it.Key());
		}

		m_bNodeCollectionChanged = TRUE;
	}

	// in any case, the last object we read wasn't handled yet (end-of-stream or another event), so
	// seek back, so it will be handled.
	nRetVal = m_pInputStream->Seek(nPositionBefore);
	XN_IS_STATUS_OK(nRetVal);

	return (XN_STATUS_OK);
}