XnStatus XnSensorDepthGenerator::SetUserPosition(XnUInt32 nIndex, const XnBoundingBox3D& Position)
{
    // set (we only support Z boxing for now)
    XnDepthAGCBin bin;
    bin.nBin = nIndex;
    bin.nMin = Position.LeftBottomNear.Z;
    bin.nMax = Position.RightTopFar.Z;
    return m_pSensor->SetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin));
}
XnStatus XnSensorGenerator::Init()
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	nRetVal = m_pSensor->GetProperty(XN_MODULE_NAME_DEVICE, XN_MODULE_PROPERTY_VERSION, XN_PACK_GENERAL_BUFFER(m_Version));
	XN_IS_STATUS_OK(nRetVal);

	nRetVal = m_pSensor->CreateStreamData(m_strModule, &m_pStreamData);
	XN_IS_STATUS_OK(nRetVal);

	return (XN_STATUS_OK);
}
XnStatus XnPixelStream::SetCropping(const XnCropping* pCropping)
{
    XnStatus nRetVal = XN_STATUS_OK;

    nRetVal = ValidateCropping(pCropping);
    XN_IS_STATUS_OK(nRetVal);

    nRetVal = m_Cropping.UnsafeUpdateValue(XN_PACK_GENERAL_BUFFER(*(XnCropping*)pCropping));
    XN_IS_STATUS_OK(nRetVal);

    return (XN_STATUS_OK);
}
XnStatus XN_CALLBACK_TYPE XnSensorDepthStream::ReadAGCBinsFromFile(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection)
{
	XnStatus nRetVal = XN_STATUS_OK;

	for (XnUInt32 nBin = 0; nBin < XN_DEPTH_STREAM_AGC_NUMBER_OF_BINS; ++nBin)
	{
		XnChar csKey[XN_INI_MAX_LEN];
		XnUInt32 nValue;

		XnDepthAGCBin bin;
		bin.nBin = (XnUInt16)nBin;

		XnBool bHasMin = FALSE;
		XnBool bHasMax = FALSE;

		sprintf(csKey, "AGCBin%uMinDepth", nBin);

		nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue);
		if (nRetVal == XN_STATUS_OK)
		{
			bin.nMin = (XnUInt16)nValue;
			bHasMin = TRUE;
		}

		sprintf(csKey, "AGCBin%uMaxDepth", nBin);
		nRetVal = xnOSReadIntFromINI(csINIFile, csSection, csKey, &nValue);
		if (nRetVal == XN_STATUS_OK)
		{
			bin.nMax = (XnUInt16)nValue;
			bHasMax = TRUE;
		}

		if (bHasMax && bHasMin)
		{
			nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(bin));
			XN_IS_STATUS_OK(nRetVal);
		}
		else if (bHasMin || bHasMax)
		{
			// we have only one
			XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_BAD_PARAM, XN_MASK_DEVICE_SENSOR, "Bin %d should have both min and max values!", nBin);
		}
	}

	return XN_STATUS_OK;
}
XnStatus XnSensorDepthGenerator::GetUserPosition(XnUInt32 nIndex, XnBoundingBox3D& Position)
{
    XnStatus nRetVal = XN_STATUS_OK;

    // get
    XnDepthAGCBin bin;
    bin.nBin = nIndex;
    nRetVal =  m_pSensor->GetProperty(m_strModule, XN_STREAM_PROPERTY_AGC_BIN, XN_PACK_GENERAL_BUFFER(bin));
    XN_IS_STATUS_OK(nRetVal);

    XnMapOutputMode MapOutputMode;
    nRetVal = GetMapOutputMode(MapOutputMode);
    XN_IS_STATUS_OK(nRetVal);

    // we only support Z position for now
    Position.LeftBottomNear.Z = bin.nMin;
    Position.RightTopFar.Z = bin.nMax;
    Position.LeftBottomNear.X = 0;
    Position.RightTopFar.X = MapOutputMode.nXRes - 1;
    Position.LeftBottomNear.Y = 0;
    Position.RightTopFar.Y = MapOutputMode.nYRes - 1;

    return (XN_STATUS_OK);
}
XnStatus XN_CALLBACK_TYPE XnPixelStream::ReadCroppingFromFileCallback(XnGeneralProperty* pSender, const XnChar* csINIFile, const XnChar* csSection)
{
    XnStatus nRetVal = XN_STATUS_OK;

    // read section name
    XnChar csCroppingSection[XN_FILE_MAX_PATH];
    sprintf(csCroppingSection, "%s.Cropping", csSection);

    // read cropping values
    XnUInt32 nOffsetX;
    XnUInt32 nOffsetY;
    XnUInt32 nSizeX;
    XnUInt32 nSizeY;
    XnUInt32 bEnabled;

    // only if all values are here
    if (XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetX", &nOffsetX) &&
            XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "OffsetY", &nOffsetY) &&
            XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeX", &nSizeX) &&
            XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "SizeY", &nSizeY) &&
            XN_STATUS_OK == xnOSReadIntFromINI(csINIFile, csCroppingSection, "Enabled", &bEnabled))
    {
        XnCropping Cropping;
        Cropping.nXOffset = nOffsetX;
        Cropping.nYOffset = nOffsetY;
        Cropping.nXSize = nSizeX;
        Cropping.nYSize = nSizeY;
        Cropping.bEnabled = bEnabled;

        // set value
        nRetVal = pSender->SetValue(XN_PACK_GENERAL_BUFFER(Cropping));
        XN_IS_STATUS_OK(nRetVal);
    }

    return (XN_STATUS_OK);
}
XnStatus XnDeviceSensorProtocolDumpLastRawFrameImpl(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName)
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	const XnChar* strName;
	nRetVal = XnDeviceSensorProtocolFindStreamOfType(pDevicePrivateData, strType, &strName);
	XN_IS_STATUS_OK(nRetVal);

	XnUInt64 nMaxDataSize;
	nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, &nMaxDataSize);
	XN_IS_STATUS_OK(nRetVal);

	XnDynamicSizeBuffer dsb;
	dsb.nMaxSize = (XnUInt32)nMaxDataSize;
	dsb.pData = xnOSMallocAligned((XnUInt32)nMaxDataSize, XN_DEFAULT_MEM_ALIGN);
	XN_VALIDATE_ALLOC_PTR(dsb.pData);

	
	nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_LAST_RAW_FRAME, XN_PACK_GENERAL_BUFFER(dsb));
	if (nRetVal != XN_STATUS_OK)
	{
		xnOSFreeAligned(dsb.pData);
		return (nRetVal);
	}

	// The real depth size is half of what's being reported because of special depth+shift memory packing format.
	if (strType == XN_STREAM_TYPE_DEPTH)
	{
		dsb.nDataSize /= 2;
	}
	
	xnOSSaveFile(strFileName, dsb.pData, dsb.nDataSize);

	xnOSFreeAligned(dsb.pData);

	return (XN_STATUS_OK);
}
XnStatus XnDeviceSensorProtocolDumpLastRawFrameImpl(XnDevicePrivateData* pDevicePrivateData, const XnChar* strType, const XnChar* strFileName)
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	const XnChar* strName;
	nRetVal = XnDeviceSensorProtocolFindStreamOfType(pDevicePrivateData, strType, &strName);
	XN_IS_STATUS_OK(nRetVal);

	XnUInt64 nMaxDataSize;
	nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_REQUIRED_DATA_SIZE, &nMaxDataSize);
	XN_IS_STATUS_OK(nRetVal);

	XnDynamicSizeBuffer dsb;
	dsb.nMaxSize = (XnUInt32)nMaxDataSize;
	dsb.pData = xnOSMallocAligned((XnUInt32)nMaxDataSize, XN_DEFAULT_MEM_ALIGN);
	XN_VALIDATE_ALLOC_PTR(dsb.pData);

	nRetVal = pDevicePrivateData->pSensor->GetProperty(strName, XN_STREAM_PROPERTY_LAST_RAW_FRAME, XN_PACK_GENERAL_BUFFER(dsb));
	if (nRetVal != XN_STATUS_OK)
	{
		xnOSFreeAligned(dsb.pData);
		return (nRetVal);
	}

	xnOSSaveFile(strFileName, dsb.pData, dsb.nDataSize);

	xnOSFreeAligned(dsb.pData);

	return (XN_STATUS_OK);
}
XnStatus XnStreamDeviceStreamHolder::ChooseCodec()
{
	XnStatus nRetVal = XN_STATUS_OK;

	// create new codec (we also need to register on all the properties)
	XnCodec* pCodec;
	XnPropertiesList CodecProps;

	switch (GetCompression())
	{
	case XN_COMPRESSION_NONE:
		{
			XN_VALIDATE_NEW_AND_INIT(pCodec, XnUncompressedCodec);
		}
		break;
	case XN_COMPRESSION_16Z:
		{
			XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zCodec);
		}
		break;
	case XN_COMPRESSION_16Z_EMB_TABLE:
		{
			// first we need to find max depth
			XnIntProperty* pDeviceMaxDepthProp;
			nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH, &pDeviceMaxDepthProp);
			XN_IS_STATUS_OK(nRetVal);

			XnUInt64 nMaxDepth;
			nRetVal = pDeviceMaxDepthProp->GetValue(&nMaxDepth);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = CodecProps.AddLast(pDeviceMaxDepthProp);
			XN_IS_STATUS_OK(nRetVal);

			XN_VALIDATE_NEW_AND_INIT(pCodec, Xn16zEmbTablesCodec, (XnDepthPixel)nMaxDepth);
		}
		break;
	case XN_COMPRESSION_COLOR_8Z:
		{
			XN_VALIDATE_NEW_AND_INIT(pCodec, Xn8zCodec);
		}
		break;
	case XN_COMPRESSION_JPEG:
		{
			// check what is the output format
			XnIntProperty* pOutputFormatProp;
			nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, &pOutputFormatProp);
			XN_IS_STATUS_OK(nRetVal);

			XnUInt64 nOutputFormat;
			nRetVal = pOutputFormatProp->GetValue(&nOutputFormat);
			XN_IS_STATUS_OK(nRetVal);

			XnBool bRGB = FALSE;

			switch (nOutputFormat)
			{
			case XN_OUTPUT_FORMAT_GRAYSCALE8:
				bRGB = FALSE;
				break;
			case XN_OUTPUT_FORMAT_RGB24:
				bRGB = TRUE;
				break;
			default:
				XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory currently supports JPEG codec only for streams of type Gray8 or RGB24!");
			}

			nRetVal = CodecProps.AddLast(pOutputFormatProp);
			XN_IS_STATUS_OK(nRetVal);

			// X res
			XnIntProperty* pXResProp;
			nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_X_RES, &pXResProp);
			XN_IS_STATUS_OK(nRetVal);

			XnUInt64 nXRes;
			nRetVal = pXResProp->GetValue(&nXRes);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = CodecProps.AddLast(pXResProp);
			XN_IS_STATUS_OK(nRetVal);

			// Y res
			XnIntProperty* pYResProp;
			nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_Y_RES, &pYResProp);
			XN_IS_STATUS_OK(nRetVal);

			XnUInt64 nYRes;
			nRetVal = pYResProp->GetValue(&nYRes);
			XN_IS_STATUS_OK(nRetVal);

			// Cropping
			XnGeneralProperty* pCroppingProp;
			nRetVal = GetStream()->GetProperty(XN_STREAM_PROPERTY_CROPPING, &pCroppingProp);
			XN_IS_STATUS_OK(nRetVal);

			XnCropping cropping;
			nRetVal = pCroppingProp->GetValue(XN_PACK_GENERAL_BUFFER(cropping));
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = CodecProps.AddLast(pCroppingProp);
			XN_IS_STATUS_OK(nRetVal);

			// calc x,y
			if (cropping.bEnabled)
			{
				nXRes = cropping.nXSize;
				nYRes = cropping.nYSize;
			}

			XN_VALIDATE_NEW_AND_INIT(pCodec, XnJpegCodec, bRGB, (XnUInt32)nXRes, (XnUInt32)nYRes);
		}
		break;
	default:
		XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_DDK, "Codec factory does not support compression type %d", GetCompression());
	}

	// register to new props
	for (XnPropertiesList::Iterator it = CodecProps.Begin(); it != CodecProps.End(); ++it)
	{
		XnProperty* pProp = *it;

		XnPropertiesHash::Iterator hashIt = m_CodecProperties.End();
		nRetVal = m_CodecProperties.Find(pProp, hashIt);
		if (nRetVal == XN_STATUS_NO_MATCH)
		{
			XnCallbackHandle hCallbackDummy;
			nRetVal = pProp->OnChangeEvent().Register(CodecPropertyChangedCallback, this, hCallbackDummy);
			if (nRetVal != XN_STATUS_OK)
			{
				XN_DELETE(pCodec);
				return (nRetVal);
			}

			nRetVal = m_CodecProperties.Set(pProp, NULL);
			if (nRetVal != XN_STATUS_OK)
			{
				XN_DELETE(pCodec);
				return (nRetVal);
			}
		}
		else if (nRetVal != XN_STATUS_OK)
		{
			XN_DELETE(pCodec);
			return (nRetVal);
		}
	}

	// replace it
	XN_DELETE(m_pCodec);
	m_pCodec = pCodec;

	return (XN_STATUS_OK);
}