예제 #1
0
void XN_CALLBACK_TYPE PoseToggleUserSelector::OutOfPoseCallback(xn::PoseDetectionCapability& capability, const XnChar* strPose, XnUserID nUserId,void* pCookie)
{
    PoseToggleUserSelector *pPoseUserSelector=(PoseToggleUserSelector *)pCookie;
    if(xnOSStrCmp(strPose,pPoseUserSelector->m_strPoseToTrack)!=0)
        return; // this is not the pose we are looking for.
    pPoseUserSelector->DetectOutOfPose(nUserId);

}
예제 #2
0
void XN_CALLBACK_TYPE PoseUserSelector::PoseInProgressCallback(xn::PoseDetectionCapability& capability, const XnChar* strPose, XnUserID nUserId, XnPoseDetectionStatus ePoseError, void* pCookie)
{
    PoseUserSelector* pPoseUserSelector = (PoseUserSelector *)pCookie;
    if(xnOSStrCmp(strPose,pPoseUserSelector->m_strPoseToTrack)!=0)
    {
        return; // this is not the pose we are looking for.
    }
    pPoseUserSelector->UpdatePoseProgress(nUserId,ePoseError);
}
예제 #3
0
void XN_CALLBACK_TYPE ExitPoseDetector::OutOfPoseDetectedCallback(xn::PoseDetectionCapability& /*capability*/, const XnChar* strPose, XnUserID nUserId, void* pCookie)
{
    if(xnOSStrCmp(strPose,CROSS_HANDS_POSE)!=0)
    {
        return; // irrelevant pose
    }
    ExitPoseDetector *detector=(ExitPoseDetector *)pCookie;
    XnUInt64 tmpTime=0;
    detector->m_userExitPoseTimes.Set(nUserId,tmpTime); // we are not in pose any more.
}
예제 #4
0
	virtual OniStatus tryDevice(const char* uri)
	{
		if (xnOSStrCmp(uri, "Dummy") != 0 &&
			xnOSStrCmp(uri, "Oz") != 0 &&
			xnOSStrCmp(uri, "PingPong") != 0)
		{
			return ONI_STATUS_ERROR;
		}


		OniDeviceInfo* pInfo = XN_NEW(OniDeviceInfo);
		xnOSStrCopy(pInfo->uri, uri, ONI_MAX_STR);
		xnOSStrCopy(pInfo->vendor, "Table Tennis", ONI_MAX_STR);
		m_devices[pInfo] = NULL;

		deviceConnected(pInfo);

		return ONI_STATUS_OK;
	}
예제 #5
0
XnUInt32 PlayerNode::GetPlayerNodeIDByName(const XnChar* strNodeName)
{
	for (XnUInt32 i = 0; i < m_nMaxNodes; i++)
	{
		if (xnOSStrCmp(strNodeName, m_pNodeInfoMap[i].strName) == 0)
		{
			return i;
		}
	}
	return INVALID_NODE_ID;
}
예제 #6
0
void XN_CALLBACK_TYPE ExitPoseDetector::PoseDetectedCallback(xn::PoseDetectionCapability& /*capability*/, const XnChar* strPose, XnUserID nUserId, void* pCookie)
{
    if(xnOSStrCmp(strPose,CROSS_HANDS_POSE)!=0)
    {
        return; // irrelevant pose
    }
    ExitPoseDetector *detector=(ExitPoseDetector *)pCookie;
    XnUInt64 tmpTime;
    if(detector->m_userExitPoseTimes.Get(nUserId,tmpTime)!=XN_STATUS_OK || tmpTime==0)
    {
        tmpTime=detector->m_userGenerator.GetTimestamp();
        detector->m_userExitPoseTimes.Set(nUserId,tmpTime);
    }
}
XnExportedSensorDevice::CreatedDevices::Iterator XnExportedSensorDevice::FindCreatedDevice(XnContext* pContext, 
																                           const XnChar* strConnStr)
{
	CreatedDevices::Iterator it = m_createdDevices.Begin();
	for (; it != m_createdDevices.End(); it++)
	{
		if ((it->m_pContext == pContext) && 
			 (xnOSStrCmp(it->m_strConnStr, strConnStr) == 0))
		{
			break;
		}
	}

	return it;
}
예제 #8
0
	virtual oni::driver::DeviceBase* deviceOpen(const char* uri, const char* /*mode*/)
	{
		for (xnl::Hash<OniDeviceInfo*, oni::driver::DeviceBase*>::Iterator iter = m_devices.Begin(); iter != m_devices.End(); ++iter)
		{
			if (xnOSStrCmp(iter->Key()->uri, uri) == 0)
			{
				// Found
				if (iter->Value() != NULL)
				{
					// already using
					return iter->Value();
				}

				OzDevice* pDevice = XN_NEW(OzDevice, iter->Key(), getServices());
				iter->Value() = pDevice;
				return pDevice;
			}
		}

		getServices().errorLoggerAppend("Looking for '%s'", uri);
		return NULL;
	}
예제 #9
0
void xnUSBDeviceDisconnected(struct udev_device *dev)
{
	// find dev in the connected devices' list
	XnUSBConnectedDevice *pConnected = NULL;
	for (XnUSBConnectedDeviceList::Iterator it = g_connectedDevices.Begin(); it != g_connectedDevices.End(); ++it)
	{
		if (!xnOSStrCmp(((XnUSBConnectedDevice *)*it)->strNode, udev_device_get_devnode(dev)))
		{
			pConnected = *it;
			break;
		}
	}

	if(!pConnected)
	{
		// got disconnection of an unknown device. not good.
		xnLogWarning(XN_MASK_USB, "Got device disconnection event - for an unknown device!");
		return;
	}

	// notify the proper events of the disconnection
	for (XnUSBEventCallbackList::Iterator it = g_connectivityEvent.Begin(); it != g_connectivityEvent.End(); ++it)
	{
		XnUSBEventCallback* pCallback = *it;

		if(pCallback->nVendorID == pConnected->nVendorID && pCallback->nProductID == pConnected->nProductID)
		{
			XnUSBEventArgs args;
			args.strDevicePath = pConnected->strDevicePath;
			args.eventType = XN_USB_EVENT_DEVICE_DISCONNECT;
			pCallback->pFunc(&args, pCallback->pCookie);
		}
	}

	// remove the device from connectedDevices List
	g_connectedDevices.Remove(pConnected);
	XN_DELETE(pConnected);
}
	virtual oni::driver::DeviceBase* deviceOpen(const char* uri, const char* /*mode*/)
	{
		for ( auto iter = m_devices.Begin(); iter != m_devices.End(); ++iter) {
			if (xnOSStrCmp(iter->Key()->uri, uri) == 0) {
				// Found
				if (iter->Value() != NULL) {
					// already using
					return iter->Value();
				}

				int deviceIndex = atoi(strrchr(uri, '/') + 1);

				// Create the device instance
				// デバイスインスタンスを生成する
				DepthSenseDevice* pDevice = XN_NEW(DepthSenseDevice, iter->Key(), getServices(), m_context, m_depthSenseDevices[deviceIndex] );
				iter->Value() = pDevice;
				return pDevice;
			}
		}

		getServices().errorLoggerAppend("Looking for '%s'", uri);
		return NULL;
	}
예제 #11
0
XnStatus PrimeClient::RunPresetFile(const XnChar* strFileName)
{
	XnStatus nRetVal = XN_STATUS_OK;

	xnLogVerbose(XN_MASK_PRIME_CLIENT, "Executing preset file '%s'...", strFileName);

	// Check that file exists
	XnBool bFileExists;
	nRetVal = xnOSDoesFileExist(strFileName, &bFileExists);
	XN_IS_STATUS_OK(nRetVal);

	if (!bFileExists)
	{
		xnLogError(XN_MASK_PRIME_CLIENT, "File '%s' does not exist", strFileName);
		return XN_STATUS_OS_FILE_NOT_FOUND;
	}

	FILE* pFile = fopen(strFileName, "r");
	XN_ASSERT(pFile != NULL);

	XnChar strLine[1024];

	// read header
	if (NULL == fgets(strLine, sizeof(strLine), pFile))
	{
		xnLogError(XN_MASK_PRIME_CLIENT, "File '%s' is empty - no header", strFileName);
		return XN_STATUS_ERROR;
	}

	XnUInt32 nAddress;
	XnUInt32 nValue;
	XnUInt8 nBitOffset;
	XnUInt8 nBitWidth;

	for (;;)
	{
		// read a line
		if (NULL == fgets(strLine, sizeof(strLine), pFile))
		{
			// end of file reached
			break;
		}

		// skip empty lines
		if (xnOSStrCmp(strLine, "\n") == 0 || xnOSStrCmp(strLine, "\r\n") == 0)
		{
			continue;
		}

		// block name
		XnChar* pToken = strtok(strLine, ",");
		CHECK_TOKEN(pToken, strLine, pFile);

		// reg name
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);

		// Address
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);
		sscanf(pToken, "0x%x", &nAddress);

		// field name
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);

		// bit offset
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);
		nBitOffset = (XnUInt8)atoi(pToken);

		// bit width
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);
		nBitWidth = (XnUInt8)atoi(pToken);

		// value
		pToken = strtok(NULL, ",");
		CHECK_TOKEN(pToken, strLine, pFile);
		sscanf(pToken, "0x%x", &nValue);

		// execute
		nRetVal = WriteAHB(nAddress, nValue, nBitOffset, nBitWidth);
		if (nRetVal != XN_STATUS_OK)
		{
			fclose(pFile);
			return nRetVal;
		}
	}

	fclose(pFile);

	xnLogInfo(XN_MASK_PRIME_CLIENT, "Preset file '%s' was executed", strFileName);

	return (XN_STATUS_OK);
}
예제 #12
0
XN_THREAD_PROC xnUSBUDEVEventsThread(XN_THREAD_PARAM pThreadParam)
{
	struct udev *udev;
	struct udev_device *dev;
   	struct udev_monitor *mon;
	int fd;
	
	/* Create the udev object */
	udev = udev_new();
	if (!udev) {
		printf("Can't create udev\n");
		exit(1);
	}

	/* This section sets up a monitor which will report events when
	   devices attached to the system change.  Events include "add",
	   "remove", "change", "online", and "offline".
	   
	   This section sets up and starts the monitoring. Events are
	   polled for (and delivered) later on.
	   
	   It is important that the monitor be set up before the call to
	   udev_enumerate_scan_devices() so that events (and devices) are
	   not missed.  For example, if enumeration happened first, there
	   would be no event generated for a device which was attached after
	   enumeration but before monitoring began.
	   
	   Note that a filter is added so that we only get events for
	   "usb/usb_device" devices. */
	
	/* Set up a monitor to monitor "usb_device" devices */
	mon = udev_monitor_new_from_netlink(udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
	udev_monitor_enable_receiving(mon);
	/* Get the file descriptor (fd) for the monitor.
	   This fd will get passed to select() */
	fd = udev_monitor_get_fd(mon);
	
	//////////////////////////////////////////////////////////////////////////

	/* Enumerate the currently connected devices and store them, 
	   so we can notify of their disconnection */

	struct udev_enumerate *enumerate;
	struct udev_list_entry *devices, *dev_list_entry;


	enumerate = udev_enumerate_new(udev);
	/* Create a list of the devices.
	   Note that it's not possible to match by "devtype="usb_device"",
	   as in monitor filter, but this filter combination seems to do the job... */
	udev_enumerate_add_match_subsystem(enumerate, "usb");
	udev_enumerate_add_match_sysattr(enumerate, "idVendor", NULL);
	udev_enumerate_add_match_sysattr(enumerate, "idProduct", NULL);
	udev_enumerate_add_match_sysattr(enumerate, "busnum", NULL);
	udev_enumerate_add_match_sysattr(enumerate, "devnum", NULL);

	udev_enumerate_scan_devices(enumerate);
	devices = udev_enumerate_get_list_entry(enumerate);
	/* udev_list_entry_foreach is a macro which expands to
	   a loop. The loop will be executed for each member in
	   devices, setting dev_list_entry to a list entry
	   which contains the device's path in /sys. */
	udev_list_entry_foreach(dev_list_entry, devices) {
		const char *path;
		
		/* Get the filename of the /sys entry for the device
		   and create a udev_device object (dev) representing it */
		path = udev_list_entry_get_name(dev_list_entry);
		dev = udev_device_new_from_syspath(udev, path);

		/* Notify as if it was just connected */
		// note - it's better that connectivity events register AFTER this point,
		//        so they don't get notified of already connected devices.
		xnUSBDeviceConnected(dev);
	
		udev_device_unref(dev);
	}
	/* Free the enumerator object */
	udev_enumerate_unref(enumerate);

	//////////////////////////////////////////////////////////////////////////

	/* Begin polling for udev events. Events occur when devices
	   attached to the system are added, removed, or change state. 
	   udev_monitor_receive_device() will return a device
	   object representing the device which changed and what type of
	   change occured.

	   The select() system call is used to ensure that the call to
	   udev_monitor_receive_device() will not block.
	   
	   The monitor was set up earler in this file, and monitoring is
	   already underway.
	   
	   This section will run continuously, calling usleep() at the end
	   of each pass. This is to demonstrate how to use a udev_monitor
	   in a non-blocking way. */
	while (g_bShouldRunUDEVThread)
	{
		/* Set up the call to select(). In this case, select() will
		   only operate on a single file descriptor, the one
		   associated with our udev_monitor. Note that the timeval
		   object is set to 0, which will cause select() to not
		   block. */
		fd_set fds;
		struct timeval tv;
		int ret;
		
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tv.tv_sec = 0;
		tv.tv_usec = 250 * 1000;
		
		ret = select(fd+1, &fds, NULL, NULL, &tv);
		
		/* Check if our file descriptor has received data. */
		if (ret > 0 && FD_ISSET(fd, &fds)) {
			/* Make the call to receive the device.
			   select() ensured that this will not block. */
			dev = udev_monitor_receive_device(mon);
			if (dev) {
			/*
				printf("   Node: %s\n", udev_device_get_devnode(dev));
				printf("   Subsystem: %s\n", udev_device_get_subsystem(dev));
				printf("   Devtype: %s\n", udev_device_get_devtype(dev));
				printf("   Action: %s\n", udev_device_get_action(dev));

				printf("  VID/PID: %s %s\n",
						udev_device_get_sysattr_value(dev,"idVendor"),
						udev_device_get_sysattr_value(dev,"idProduct"));
				printf("  %s\n  %s\n",
						udev_device_get_sysattr_value(dev,"manufacturer"),
						udev_device_get_sysattr_value(dev,"product"));
				fflush(stdout);
			*/
				const XnChar *action = udev_device_get_action(dev);

				if (!xnOSStrCmp(action, "add"))
				{
					xnUSBDeviceConnected(dev);
				}
				else if (!xnOSStrCmp(action, "remove"))
				{
					xnUSBDeviceDisconnected(dev);
				}
				//note - handle the other events? "change" event might be useful...

				// now release dev
				udev_device_unref(dev);
			}
			else {
				xnLogWarning(XN_MASK_USB, "No Device from udev_monitor_receive_device(). An error occured.");
			}					
		}
	}
	udev_monitor_unref(mon);
	udev_unref(udev);

	XN_THREAD_PROC_RETURN(XN_STATUS_OK);
}
예제 #13
0
파일: main.cpp 프로젝트: JYDKY/spark
/// @brief The main function of the sample
/// 
/// This is the main function of the sample. Its purpose is to be the starting point for the
/// sample and according to the command line arguments, to decide which sample behavior to use.
/// @ingroup UserSelectionMain
int main(int argc, char** argv)
{    
    SampleManager* pSampleManager=NULL; // will hold the sample manager which initializes and runs the sample
    if(argc>1)
    {
        // check if the argument is asking for help...
        if(xnOSStrCmp(argv[1],"--help")==0 ||
           xnOSStrCmp(argv[1],"-help")==0 ||
           xnOSStrCmp(argv[1],"/help")==0 ||
           xnOSStrCmp(argv[1],"\\help")==0 ||
           xnOSStrCmp(argv[1],"?")==0 ||
           xnOSStrCmp(argv[1],"--?")==0 ||
           xnOSStrCmp(argv[1],"-?")==0 ||
           xnOSStrCmp(argv[1],"/?")==0 ||
           xnOSStrCmp(argv[1],"\\?")==0)
        {
            UsageAndExit(argv[0]);
        }

        // go over the arguments and see if we have the '-s' switch. If so it means we
        // are going to choose the selector type.
        for(int i=1; i<argc-1; i++)
        {
            if(xnOSStrCmp(argv[i],"-s")==0)
            {
                if(xnOSStrCmp(argv[i+1],"ClosestSelector")==0)
                {
                    // we are in the option '-s ClosestSelector N'. 
                    if(argc<=i+2 || strlen(argv[i+2])>2)
                    {
                        UsageAndExit(argv[0]); // either there is no N at all or it is more than 1 digit
                    }
                    XnUInt32 n=argv[i+2][0]-'0'; // translate digit to number
                    pSampleManager=XN_NEW(ClosestSampleManager,n); // choose ClosestSelector with n
                }
                else if(xnOSStrCmp(argv[i+1],"SingleWave")==0)
                {
                    // option is '-s SingleWave'
                    pSampleManager=XN_NEW(SingleWaveSampleManager);
                }
                else if(xnOSStrCmp(argv[i+1],"MultipleWave")==0)
                {
                    // option is '-s SingleWave N'
                    if(argc<=i+2 || strlen(argv[i+2])>2)
                    {
                        UsageAndExit(argv[0]); // either there is no N at all or it is more than 1 digit
                    }
                    XnUInt32 n=argv[i+2][0]-'0'; // translate digit to number
                    pSampleManager=XN_NEW(MultipleWaveSampleManager,n);
                }
                else
                {
                    // an illegal option was used...
                    UsageAndExit(argv[0]);
                }
                break; // we found the switch so we ignore all others
            }
        }
    }
    if(pSampleManager==NULL) // by default we use the closest detector option
    {
        pSampleManager=XN_NEW(ClosestSampleManager,1); // choose the default.
    }

    if(pSampleManager->StartSample(argc,argv)!=XN_STATUS_OK) 
    {
		XN_DELETE(pSampleManager);
        UsageAndExit(argv[0]); // The manager will only return if it fails to initialize...
    }
}
예제 #14
0
UserTracker::UserTracker(int argc, char **argv, XnUInt64 timeSpanForExitPose) : m_bValid(FALSE), 
                                                                                m_timeSpanForExitPose(timeSpanForExitPose),
                                                                                m_pExitPoseDetector(NULL)
{
    m_bRecord=FALSE;
    XnStatus nRetVal = XN_STATUS_OK;

    XnBool OpenedRecording=FALSE;

    if(argc>1)
    {
        for(int i=1; i<argc-1; i++)
        {
            if(xnOSStrCmp(argv[i],"-RecordingFilename")==0)
            {
                // initialize the context from scratch
                nRetVal = m_Context.Init();
                CHECK_RC(nRetVal, "Context Initialization");
                // try to open the recording as the source for sensor data
                nRetVal = m_Context.OpenFileRecording(argv[i+1], m_Player);
                CHECK_RC(nRetVal, "Couldn't open recording with command line argument");
                OpenedRecording=TRUE;
                break; // we only support one recording at a time..
            }
        }
    }
    if(OpenedRecording==FALSE)
    {
        xn::EnumerationErrors errors;
        nRetVal = m_Context.InitFromXmlFile(SAMPLE_XML_PATH, m_ScriptNode, &errors);
        if (nRetVal == XN_STATUS_NO_NODE_PRESENT)
        {
            XnChar strError[1024];
            errors.ToString(strError, 1024);
            printf("%s\n", strError);
            return;
        }
        CHECK_RC(nRetVal, "Open XML failed");
    }

    nRetVal = m_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, m_DepthGenerator);
    if (nRetVal != XN_STATUS_OK)
    {
        printf("No depth generator found. Using a default one...");
        xn::MockDepthGenerator mockDepth;
        nRetVal = mockDepth.Create(m_Context);
        CHECK_RC(nRetVal, "Create mock depth");

        // set some defaults
        XnMapOutputMode defaultMode;
        defaultMode.nXRes = 320;
        defaultMode.nYRes = 240;
        defaultMode.nFPS = 30;
        nRetVal = mockDepth.SetMapOutputMode(defaultMode);
        CHECK_RC(nRetVal, "set default mode");

        // set FOV
        XnFieldOfView fov;
        fov.fHFOV = 1.0225999419141749;
        fov.fVFOV = 0.79661567681716894;
        nRetVal = mockDepth.SetGeneralProperty(XN_PROP_FIELD_OF_VIEW, sizeof(fov), &fov);
        CHECK_RC(nRetVal, "set FOV");

        XnUInt32 nDataSize = defaultMode.nXRes * defaultMode.nYRes * sizeof(XnDepthPixel);
        XnDepthPixel* pData = (XnDepthPixel*)xnOSCallocAligned(nDataSize, 1, XN_DEFAULT_MEM_ALIGN);

        nRetVal = mockDepth.SetData(1, 0, nDataSize, pData);
        CHECK_RC(nRetVal, "set empty depth map");

        m_DepthGenerator = mockDepth;
    }

    nRetVal = m_Context.FindExistingNode(XN_NODE_TYPE_USER, m_UserGenerator);
    if (nRetVal != XN_STATUS_OK)
    {
        nRetVal = m_UserGenerator.Create(m_Context);
        CHECK_RC(nRetVal, "Find user generator");
    }

    if (!m_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON))
    {
        printf("Supplied user generator doesn't support skeleton\n");
        return;
    }
    m_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);
    nRetVal = m_Context.StartGeneratingAll();
    CHECK_RC(nRetVal, "StartGenerating");

    m_pExitPoseDetector=XN_NEW(ExitPoseDetector,m_UserGenerator);
    if(!(m_pExitPoseDetector->Valid()))
    {
        printf("Exit pose is not supported by user node. Therefore will continue to run without support for exit pose\n");
        XN_DELETE(m_pExitPoseDetector);
        m_pExitPoseDetector=NULL;
    }
    m_bValid=TRUE;
}
예제 #15
0
OniStatus Context::deviceOpen(const char* uri, const char* mode, OniDeviceHandle* pDevice)
{
	oni::implementation::Device* pMyDevice = NULL;

	const char* deviceURI = uri;
	if (xnOSStrLen(m_overrideDevice) > 0)
		deviceURI = m_overrideDevice;

	xnLogVerbose(XN_MASK_ONI_CONTEXT, "Trying to open device by URI '%s'", deviceURI == NULL ? "(NULL)" : deviceURI);

	m_cs.Lock();

	if (deviceURI == NULL)
	{
		// Default
		if (m_devices.Size() == 0)
		{
			m_errorLogger.Append("DeviceOpen using default: no devices found");
			xnLogError(XN_MASK_ONI_CONTEXT, "Can't open default device - none found");
			m_cs.Unlock();
			return ONI_STATUS_ERROR;
		}

		pMyDevice = *m_devices.Begin();
	}
	else
	{
		for (xnl::List<Device*>::Iterator iter = m_devices.Begin(); iter != m_devices.End(); ++iter)
		{
			if (xnOSStrCmp((*iter)->getInfo()->uri, deviceURI) == 0)
			{
				pMyDevice = *iter;
			}
		}
	}

	if (pMyDevice == NULL)
	{
		for (xnl::List<DeviceDriver*>::Iterator iter = m_deviceDrivers.Begin(); iter != m_deviceDrivers.End() && pMyDevice == NULL; ++iter)
		{
			if ((*iter)->tryDevice(deviceURI))
			{
				for (xnl::List<Device*>::Iterator iter = m_devices.Begin(); iter != m_devices.End(); ++iter)
				{
					if (xnOSStrCmp((*iter)->getInfo()->uri, deviceURI) == 0)
					{
						pMyDevice = *iter;
						break;
					}
				}
			}
			else
			{
//					printf("Not yet\n");
			}
		}
	}

	m_cs.Unlock();

	if (pMyDevice == NULL)
	{
		xnLogError(XN_MASK_ONI_CONTEXT, "Couldn't open device '%s'", uri);
		m_errorLogger.Append("DeviceOpen: Couldn't open device '%s'", uri);
		return ONI_STATUS_NO_DEVICE;
	}

	_OniDevice* pDeviceHandle = XN_NEW(_OniDevice);
	if (pDeviceHandle == NULL)
	{
		m_errorLogger.Append("Couldn't allocate memory for DeviceHandle");
		return ONI_STATUS_ERROR;
	}
	*pDevice = pDeviceHandle;
	pDeviceHandle->pDevice = pMyDevice;

	return pMyDevice->open(mode);
}