OpenNI 2.0
OpenNI.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002 *                                                                            *
00003 *  OpenNI 2.x Alpha                                                          *
00004 *  Copyright (C) 2012 PrimeSense Ltd.                                        *
00005 *                                                                            *
00006 *  This file is part of OpenNI.                                              *
00007 *                                                                            *
00008 *  Licensed under the Apache License, Version 2.0 (the "License");           *
00009 *  you may not use this file except in compliance with the License.          *
00010 *  You may obtain a copy of the License at                                   *
00011 *                                                                            *
00012 *      http://www.apache.org/licenses/LICENSE-2.0                            *
00013 *                                                                            *
00014 *  Unless required by applicable law or agreed to in writing, software       *
00015 *  distributed under the License is distributed on an "AS IS" BASIS,         *
00016 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00017 *  See the License for the specific language governing permissions and       *
00018 *  limitations under the License.                                            *
00019 *                                                                            *
00020 *****************************************************************************/
00021 #ifndef _OPENNI_H_
00022 #define _OPENNI_H_
00023 
00024 #include "OniPlatform.h"
00025 #include "OniProperties.h"
00026 #include "OniEnums.h"
00027 
00028 #include "OniCAPI.h"
00029 #include "OniCProperties.h"
00030 
00034 namespace openni
00035 {
00036 
00038 typedef uint16_t                DepthPixel;
00040 typedef uint16_t                Grayscale16Pixel;
00041 
00042 // structs
00043 _ONI_DECLARE_VERSION(Version);
00044 _ONI_DECLARE_RGB888_PIXEL(RGB888Pixel);
00045 _ONI_DECLARE_YUV422_PIXEL(YUV422DoublePixel);
00046 
00048 #if ONI_PLATFORM != ONI_PLATFORM_WIN32
00049 #pragma GCC diagnostic ignored "-Wunused-variable"
00050 #pragma GCC diagnostic push
00051 #endif
00052 static const char* ANY_DEVICE = NULL;
00053 #if ONI_PLATFORM != ONI_PLATFORM_WIN32
00054 #pragma GCC diagnostic pop
00055 #endif
00056 
00061 template<class T>
00062 class Array
00063 {
00064 public:
00068     Array() : m_data(NULL), m_count(0), m_owner(false) {}
00069 
00077     Array(const T* data, int count) : m_owner(false) { _setData(data, count); }
00078 
00082     ~Array()
00083     {
00084         clear();
00085     }
00086 
00091     int getSize() const { return m_count; }
00092 
00096     const T& operator[](int index) const {return m_data[index];}
00097 
00108     void _setData(const T* data, int count, bool isOwner = false)
00109     {
00110         clear();
00111         m_count = count;
00112         m_owner = isOwner;
00113         if (!isOwner)
00114         {
00115             m_data = data;
00116         }
00117         else
00118         {
00119             m_data = new T[count];
00120             memcpy((void*)m_data, data, count*sizeof(T));
00121         }
00122     }
00123 
00124 private:
00125     Array(const Array<T>&);
00126     Array<T>& operator=(const Array<T>&);
00127 
00128     void clear()
00129     {
00130         if (m_owner && m_data != NULL)
00131             delete []m_data;
00132         m_owner = false;
00133         m_data = NULL;
00134         m_count = 0;
00135     }
00136 
00137     const T* m_data;
00138     int m_count;
00139     bool m_owner;
00140 };
00141 
00142 // Forward declaration of all
00143 class SensorInfo;
00144 class VideoStream;
00145 class VideoFrameRef;
00146 class Device;
00147 class OpenNI;
00148 class CameraSettings;
00149 class PlaybackControl;
00150 
00165 class VideoMode : private OniVideoMode
00166 {
00167 public:
00173     VideoMode()
00174     {}
00175 
00181     VideoMode(const VideoMode& other)
00182     {
00183         *this = other;
00184     }
00185 
00192     VideoMode& operator=(const VideoMode& other)
00193     {
00194         setPixelFormat(other.getPixelFormat());
00195         setResolution(other.getResolutionX(), other.getResolutionY());
00196         setFps(other.getFps());
00197 
00198         return *this;
00199     }
00200 
00205     PixelFormat getPixelFormat() const { return (PixelFormat)pixelFormat; }
00206 
00211     int getResolutionX() const { return resolutionX; }
00212 
00217     int getResolutionY() const {return resolutionY;}
00218 
00223     int getFps() const { return fps; }
00224 
00231     void setPixelFormat(PixelFormat format) { this->pixelFormat = (OniPixelFormat)format; }
00232 
00240     void setResolution(int resolutionX, int resolutionY)
00241     {
00242         this->resolutionX = resolutionX;
00243         this->resolutionY = resolutionY;
00244     }
00245 
00252     void setFps(int fps) { this->fps = fps; }
00253 
00254     friend class SensorInfo;
00255     friend class VideoStream;
00256     friend class VideoFrameRef;
00257 };
00258 
00276 class SensorInfo
00277 {
00278 public:
00283     SensorType getSensorType() const { return (SensorType)m_pInfo->sensorType; }
00284 
00292     const Array<VideoMode>& getSupportedVideoModes() const { return m_videoModes; }
00293 
00294 private:
00295     SensorInfo(const SensorInfo&);
00296     SensorInfo& operator=(const SensorInfo&);
00297 
00298     SensorInfo() : m_pInfo(NULL), m_videoModes(NULL, 0) {}
00299 
00300     SensorInfo(const OniSensorInfo* pInfo) : m_pInfo(NULL), m_videoModes(NULL, 0)
00301     {
00302         _setInternal(pInfo);
00303     }
00304 
00305     void _setInternal(const OniSensorInfo* pInfo)
00306     {
00307         m_pInfo = pInfo;
00308         if (pInfo == NULL)
00309         {
00310             m_videoModes._setData(NULL, 0);
00311         }
00312         else
00313         {
00314             m_videoModes._setData(static_cast<VideoMode*>(pInfo->pSupportedVideoModes), pInfo->numSupportedVideoModes);
00315         }
00316     }
00317 
00318     const OniSensorInfo* m_pInfo;
00319     Array<VideoMode> m_videoModes;
00320 
00321     friend class VideoStream;
00322     friend class Device;
00323 };
00324 
00334 class DeviceInfo : private OniDeviceInfo
00335 {
00336 public:
00341     const char* getUri() const { return uri; }
00343     const char* getVendor() const { return vendor; }
00345     const char* getName() const { return name; }
00347     uint16_t getUsbVendorId() const { return usbVendorId; }
00349     uint16_t getUsbProductId() const { return usbProductId; }
00350 
00351     friend class Device;
00352     friend class OpenNI;
00353 };
00354 
00368 class VideoFrameRef
00369 {
00370 public:
00375     VideoFrameRef()
00376     {
00377         m_pFrame = NULL;
00378     }
00379 
00383     ~VideoFrameRef()
00384     {
00385         release();
00386     }
00387 
00393     VideoFrameRef(const VideoFrameRef& other) : m_pFrame(NULL)
00394     {
00395         _setFrame(other.m_pFrame);
00396     }
00397 
00403     VideoFrameRef& operator=(const VideoFrameRef& other)
00404     {
00405         _setFrame(other.m_pFrame);
00406         return *this;
00407     }
00408 
00414     inline int getDataSize() const
00415     {
00416         return m_pFrame->dataSize;
00417     }
00418 
00424     inline const void* getData() const
00425     {
00426         return m_pFrame->data;
00427     }
00428 
00435     inline SensorType getSensorType() const
00436     {
00437         return (SensorType)m_pFrame->sensorType;
00438     }
00439 
00447     inline const VideoMode& getVideoMode() const
00448     {
00449         return static_cast<const VideoMode&>(m_pFrame->videoMode);
00450     }
00451 
00459     inline uint64_t getTimestamp() const
00460     {
00461         return m_pFrame->timestamp;
00462     }
00463 
00474     inline int getFrameIndex() const
00475     {
00476         return m_pFrame->frameIndex;
00477     }
00478 
00485     inline int getWidth() const
00486     {
00487         return m_pFrame->width;
00488     }
00489 
00495     inline int getHeight() const
00496     {
00497         return m_pFrame->height;
00498     }
00499 
00504     inline bool getCroppingEnabled() const
00505     {
00506         return m_pFrame->croppingEnabled == TRUE;
00507     }
00508 
00513     inline int getCropOriginX() const
00514     {
00515         return m_pFrame->cropOriginX;
00516     }
00517 
00522     inline int getCropOriginY() const
00523     {
00524         return m_pFrame->cropOriginY;
00525     }
00526 
00532     inline int getStrideInBytes() const
00533     {
00534         return m_pFrame->stride;
00535     }
00536 
00540     inline bool isValid() const
00541     {
00542         return m_pFrame != NULL;
00543     }
00544 
00549     void release()
00550     {
00551         if (m_pFrame != NULL)
00552         {
00553             oniFrameRelease(m_pFrame);
00554             m_pFrame = NULL;
00555         }
00556     }
00557 
00559     void _setFrame(OniFrame* pFrame)
00560     {
00561         setReference(pFrame);
00562         if (pFrame != NULL)
00563         {
00564             oniFrameAddRef(pFrame);
00565         }
00566     }
00567 
00569     OniFrame* _getFrame()
00570     {
00571         return m_pFrame;
00572     }
00573 
00574 private:
00575     friend class VideoStream;
00576     inline void setReference(OniFrame* pFrame)
00577     {
00578         // Initial - don't addref. This is the reference from OpenNI
00579         release();
00580         m_pFrame = pFrame;
00581     }
00582 
00583     OniFrame* m_pFrame; // const!!?
00584 };
00585 
00607 class VideoStream
00608 {
00609 public:
00617     class NewFrameListener
00618     {
00619     public:
00623         NewFrameListener() : m_callbackHandle(NULL)
00624         {
00625         }
00626 
00627         virtual ~NewFrameListener()
00628         {
00629         }
00630 
00634         virtual void onNewFrame(VideoStream&) = 0;
00635 
00636     private:
00637         friend class VideoStream;
00638 
00639         static void ONI_CALLBACK_TYPE callback(OniStreamHandle streamHandle, void* pCookie)
00640         {
00641             NewFrameListener* pListener = (NewFrameListener*)pCookie;
00642             VideoStream stream;
00643             stream._setHandle(streamHandle);
00644             pListener->onNewFrame(stream);
00645             stream._setHandle(NULL);
00646         }
00647         OniCallbackHandle m_callbackHandle;
00648     };
00649 
00650     class FrameAllocator
00651     {
00652     public:
00653         virtual ~FrameAllocator() {}
00654         virtual void* allocateFrameBuffer(int size) = 0;
00655         virtual void freeFrameBuffer(void* data) = 0;
00656 
00657     private:
00658         friend class VideoStream;
00659 
00660         static void* ONI_CALLBACK_TYPE allocateFrameBufferCallback(int size, void* pCookie)
00661         {
00662             FrameAllocator* pThis = (FrameAllocator*)pCookie;
00663             return pThis->allocateFrameBuffer(size);
00664         }
00665 
00666         static void ONI_CALLBACK_TYPE freeFrameBufferCallback(void* data, void* pCookie)
00667         {
00668             FrameAllocator* pThis = (FrameAllocator*)pCookie;
00669             pThis->freeFrameBuffer(data);
00670         }
00671     };
00672 
00677     VideoStream() : m_stream(NULL), m_sensorInfo(), m_pCameraSettings(NULL), m_isOwner(true)
00678     {}
00679 
00684     explicit VideoStream(OniStreamHandle handle) : m_stream(NULL), m_sensorInfo(), m_pCameraSettings(NULL), m_isOwner(false)
00685     {
00686         _setHandle(handle);
00687     }
00688 
00693     ~VideoStream()
00694     {
00695         destroy();
00696     }
00697 
00702     bool isValid() const
00703     {
00704         return m_stream != NULL;
00705     }
00706 
00716     inline Status create(const Device& device, SensorType sensorType);
00717 
00723     inline void destroy();
00724 
00733     const SensorInfo& getSensorInfo() const
00734     {
00735         return m_sensorInfo;
00736     }
00737 
00741     Status start()
00742     {
00743         if (!isValid())
00744         {
00745             return STATUS_ERROR;
00746         }
00747 
00748         return (Status)oniStreamStart(m_stream);
00749     }
00750 
00754     void stop()
00755     {
00756         if (!isValid())
00757         {
00758             return;
00759         }
00760 
00761         oniStreamStop(m_stream);
00762     }
00763 
00774     Status readFrame(VideoFrameRef* pFrame)
00775     {
00776         if (!isValid())
00777         {
00778             return STATUS_ERROR;
00779         }
00780 
00781         OniFrame* pOniFrame;
00782         Status rc = (Status)oniStreamReadFrame(m_stream, &pOniFrame);
00783 
00784         pFrame->setReference(pOniFrame);
00785         return rc;
00786     }
00787 
00795     Status addNewFrameListener(NewFrameListener* pListener)
00796     {
00797         if (!isValid())
00798         {
00799             return STATUS_ERROR;
00800         }
00801 
00802         return (Status)oniStreamRegisterNewFrameCallback(m_stream, pListener->callback, pListener, &pListener->m_callbackHandle);
00803     }
00804 
00809     void removeNewFrameListener(NewFrameListener* pListener)
00810     {
00811         if (!isValid())
00812         {
00813             return;
00814         }
00815 
00816         oniStreamUnregisterNewFrameCallback(m_stream, pListener->m_callbackHandle);
00817         pListener->m_callbackHandle = NULL;
00818     }
00819 
00825     Status setFrameBuffersAllocator(FrameAllocator* pAllocator)
00826     {
00827         if (!isValid())
00828         {
00829             return STATUS_ERROR;
00830         }
00831 
00832         if (pAllocator == NULL)
00833         {
00834             return (Status)oniStreamSetFrameBuffersAllocator(m_stream, NULL, NULL, NULL);
00835         }
00836         else
00837         {
00838             return (Status)oniStreamSetFrameBuffersAllocator(m_stream, pAllocator->allocateFrameBufferCallback, pAllocator->freeFrameBufferCallback, pAllocator);
00839         }
00840     }
00841 
00846     OniStreamHandle _getHandle() const
00847     {
00848         return m_stream;
00849     }
00850 
00855     CameraSettings* getCameraSettings() {return m_pCameraSettings;}
00856 
00867     Status getProperty(int propertyId, void* data, int* dataSize) const
00868     {
00869         if (!isValid())
00870         {
00871             return STATUS_ERROR;
00872         }
00873 
00874         return (Status)oniStreamGetProperty(m_stream, propertyId, data, dataSize);
00875     }
00876 
00887     Status setProperty(int propertyId, const void* data, int dataSize)
00888     {
00889         if (!isValid())
00890         {
00891             return STATUS_ERROR;
00892         }
00893 
00894         return (Status)oniStreamSetProperty(m_stream, propertyId, data, dataSize);
00895     }
00896 
00903     VideoMode getVideoMode() const
00904     {
00905         VideoMode videoMode;
00906         getProperty<OniVideoMode>(STREAM_PROPERTY_VIDEO_MODE, static_cast<OniVideoMode*>(&videoMode));
00907         return videoMode;
00908     }
00909 
00918     Status setVideoMode(const VideoMode& videoMode)
00919     {
00920         return setProperty<OniVideoMode>(STREAM_PROPERTY_VIDEO_MODE, static_cast<const OniVideoMode&>(videoMode));
00921     }
00922 
00928     int getMaxPixelValue() const
00929     {
00930         int maxValue;
00931         Status rc = getProperty<int>(STREAM_PROPERTY_MAX_VALUE, &maxValue);
00932         if (rc != STATUS_OK)
00933         {
00934             return 0;
00935         }
00936         return maxValue;
00937     }
00938 
00944     int getMinPixelValue() const
00945     {
00946         int minValue;
00947         Status rc = getProperty<int>(STREAM_PROPERTY_MIN_VALUE, &minValue);
00948         if (rc != STATUS_OK)
00949         {
00950             return 0;
00951         }
00952         return minValue;
00953     }
00954 
00959     bool isCroppingSupported() const
00960     {
00961         return isPropertySupported(STREAM_PROPERTY_CROPPING);
00962     }
00963 
00972     bool getCropping(int* pOriginX, int* pOriginY, int* pWidth, int* pHeight) const
00973     {
00974         OniCropping cropping;
00975         bool enabled = false;
00976 
00977         Status rc = getProperty<OniCropping>(STREAM_PROPERTY_CROPPING, &cropping);
00978 
00979         if (rc == STATUS_OK)
00980         {
00981             *pOriginX = cropping.originX;
00982             *pOriginY = cropping.originY;
00983             *pWidth = cropping.width;
00984             *pHeight = cropping.height;
00985             enabled = (cropping.enabled == TRUE);
00986         }
00987 
00988         return enabled;
00989     }
00990 
01000     Status setCropping(int originX, int originY, int width, int height)
01001     {
01002         OniCropping cropping;
01003         cropping.enabled = true;
01004         cropping.originX = originX;
01005         cropping.originY = originY;
01006         cropping.width = width;
01007         cropping.height = height;
01008         return setProperty<OniCropping>(STREAM_PROPERTY_CROPPING, cropping);
01009     }
01010 
01015     Status resetCropping()
01016     {
01017         OniCropping cropping;
01018         cropping.enabled = false;
01019         return setProperty<OniCropping>(STREAM_PROPERTY_CROPPING, cropping);
01020     }
01021 
01026     bool getMirroringEnabled() const
01027     {
01028         OniBool enabled;
01029         Status rc = getProperty<OniBool>(STREAM_PROPERTY_MIRRORING, &enabled);
01030         if (rc != STATUS_OK)
01031         {
01032             return false;
01033         }
01034         return enabled == TRUE;
01035     }
01036 
01042     Status setMirroringEnabled(bool isEnabled)
01043     {
01044         return setProperty<OniBool>(STREAM_PROPERTY_MIRRORING, isEnabled ? TRUE : FALSE);
01045     }
01046 
01051     float getHorizontalFieldOfView() const
01052     {
01053         float horizontal = 0;
01054         getProperty<float>(STREAM_PROPERTY_HORIZONTAL_FOV, &horizontal);
01055         return horizontal;
01056     }
01057 
01062     float getVerticalFieldOfView() const
01063     {
01064         float vertical = 0;
01065         getProperty<float>(STREAM_PROPERTY_VERTICAL_FOV, &vertical);
01066         return vertical;
01067     }
01068 
01078     template <class T>
01079     Status setProperty(int propertyId, const T& value)
01080     {
01081         return setProperty(propertyId, &value, sizeof(T));
01082     }
01083 
01093     template <class T>
01094     Status getProperty(int propertyId, T* value) const
01095     {
01096         int size = sizeof(T);
01097         return getProperty(propertyId, value, &size);
01098     }
01099 
01105     bool isPropertySupported(int propertyId) const
01106     {
01107         if (!isValid())
01108         {
01109             return false;
01110         }
01111 
01112         return oniStreamIsPropertySupported(m_stream, propertyId) == TRUE;
01113     }
01114 
01124     Status invoke(int commandId, void* data, int dataSize)
01125     {
01126         if (!isValid())
01127         {
01128             return STATUS_ERROR;
01129         }
01130 
01131         return (Status)oniStreamInvoke(m_stream, commandId, data, dataSize);
01132     }
01133 
01143     template <class T>
01144     Status invoke(int commandId, T& value)
01145     {
01146         return invoke(commandId, &value, sizeof(T));
01147     }
01148 
01154     bool isCommandSupported(int commandId) const
01155     {
01156         if (!isValid())
01157         {
01158             return false;
01159         }
01160 
01161         return (Status)oniStreamIsCommandSupported(m_stream, commandId) == TRUE;
01162     }
01163 
01164 private:
01165     friend class Device;
01166 
01167     void _setHandle(OniStreamHandle stream)
01168     {
01169         m_sensorInfo._setInternal(NULL);
01170         m_stream = stream;
01171 
01172         if (stream != NULL)
01173         {
01174             m_sensorInfo._setInternal(oniStreamGetSensorInfo(m_stream));
01175         }
01176     }
01177 
01178 private:
01179     VideoStream(const VideoStream& other);
01180     VideoStream& operator=(const VideoStream& other);
01181 
01182     OniStreamHandle m_stream;
01183     SensorInfo m_sensorInfo;
01184     CameraSettings* m_pCameraSettings;
01185     bool m_isOwner;
01186 };
01187 
01204 class Device
01205 {
01206 public:
01211     Device() : m_pPlaybackControl(NULL), m_device(NULL), m_isOwner(true)
01212     {
01213         clearSensors();
01214     }
01215 
01220     explicit Device(OniDeviceHandle handle) : m_pPlaybackControl(NULL), m_device(NULL), m_isOwner(false)
01221     {
01222         _setHandle(handle);
01223     }
01224 
01229     ~Device()
01230     {
01231         if (m_device != NULL)
01232         {
01233             close();
01234         }
01235     }
01236 
01266     inline Status open(const char* uri);
01267 
01273     inline void close();
01274 
01284     const DeviceInfo& getDeviceInfo() const
01285     {
01286         return m_deviceInfo;
01287     }
01288 
01296     bool hasSensor(SensorType sensorType)
01297     {
01298         int i;
01299         for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i)
01300         {
01301             if (m_aSensorInfo[i].getSensorType() == sensorType)
01302             {
01303                 return true;
01304             }
01305         }
01306 
01307         if (i == ONI_MAX_SENSORS)
01308         {
01309             return false;
01310         }
01311 
01312         const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType);
01313 
01314         if (pInfo == NULL)
01315         {
01316             return false;
01317         }
01318 
01319         m_aSensorInfo[i]._setInternal(pInfo);
01320 
01321         return true;
01322     }
01323 
01331     const SensorInfo* getSensorInfo(SensorType sensorType)
01332     {
01333         int i;
01334         for (i = 0; (i < ONI_MAX_SENSORS) && (m_aSensorInfo[i].m_pInfo != NULL); ++i)
01335         {
01336             if (m_aSensorInfo[i].getSensorType() == sensorType)
01337             {
01338                 return &m_aSensorInfo[i];
01339             }
01340         }
01341 
01342         // not found. check to see we have additional space
01343         if (i == ONI_MAX_SENSORS)
01344         {
01345             return NULL;
01346         }
01347 
01348         const OniSensorInfo* pInfo = oniDeviceGetSensorInfo(m_device, (OniSensorType)sensorType);
01349         if (pInfo == NULL)
01350         {
01351             return NULL;
01352         }
01353 
01354         m_aSensorInfo[i]._setInternal(pInfo);
01355         return &m_aSensorInfo[i];
01356     }
01357 
01362     OniDeviceHandle _getHandle() const
01363     {
01364         return m_device;
01365     }
01366 
01371     PlaybackControl* getPlaybackControl() {return m_pPlaybackControl;}
01372 
01384     Status getProperty(int propertyId, void* data, int* dataSize) const
01385     {
01386         return (Status)oniDeviceGetProperty(m_device, propertyId, data, dataSize);
01387     }
01388 
01400     Status setProperty(int propertyId, const void* data, int dataSize)
01401     {
01402         return (Status)oniDeviceSetProperty(m_device, propertyId, data, dataSize);
01403     }
01404 
01412     bool isImageRegistrationModeSupported(ImageRegistrationMode mode) const
01413     {
01414         return (oniDeviceIsImageRegistrationModeSupported(m_device, (OniImageRegistrationMode)mode) == TRUE);
01415     }
01416 
01424     ImageRegistrationMode getImageRegistrationMode() const
01425     {
01426         ImageRegistrationMode mode;
01427         Status rc = getProperty<ImageRegistrationMode>(DEVICE_PROPERTY_IMAGE_REGISTRATION, &mode);
01428         if (rc != STATUS_OK)
01429         {
01430             return IMAGE_REGISTRATION_OFF;
01431         }
01432         return mode;
01433     }
01434 
01448     Status setImageRegistrationMode(ImageRegistrationMode mode)
01449     {
01450         return setProperty<ImageRegistrationMode>(DEVICE_PROPERTY_IMAGE_REGISTRATION, mode);
01451     }
01452 
01457     bool isValid() const
01458     {
01459         return m_device != NULL;
01460     }
01461 
01466     bool isFile() const
01467     {
01468         return isPropertySupported(DEVICE_PROPERTY_PLAYBACK_SPEED) &&
01469             isPropertySupported(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED) &&
01470             isCommandSupported(DEVICE_COMMAND_SEEK);
01471     }
01472 
01481     Status setDepthColorSyncEnabled(bool isEnabled)
01482     {
01483         Status rc = STATUS_OK;
01484 
01485         if (isEnabled)
01486         {
01487             rc = (Status)oniDeviceEnableDepthColorSync(m_device);
01488         }
01489         else
01490         {
01491             oniDeviceDisableDepthColorSync(m_device);
01492         }
01493 
01494         return rc;
01495     }
01496 
01497     bool getDepthColorSyncEnabled()
01498     {
01499         return oniDeviceGetDepthColorSyncEnabled(m_device) == TRUE;
01500     }
01501 
01512     template <class T>
01513     Status setProperty(int propertyId, const T& value)
01514     {
01515         return setProperty(propertyId, &value, sizeof(T));
01516     }
01517 
01527     template <class T>
01528     Status getProperty(int propertyId, T* value) const
01529     {
01530         int size = sizeof(T);
01531         return getProperty(propertyId, value, &size);
01532     }
01533 
01539     bool isPropertySupported(int propertyId) const
01540     {
01541         return oniDeviceIsPropertySupported(m_device, propertyId) == TRUE;
01542     }
01543 
01553     Status invoke(int commandId, void* data, int dataSize)
01554     {
01555         return (Status)oniDeviceInvoke(m_device, commandId, data, dataSize);
01556     }
01557 
01567     template <class T>
01568     Status invoke(int propertyId, T& value)
01569     {
01570         return invoke(propertyId, &value, sizeof(T));
01571     }
01572 
01578     bool isCommandSupported(int commandId) const
01579     {
01580         return oniDeviceIsCommandSupported(m_device, commandId) == TRUE;
01581     }
01582 
01584     inline Status _openEx(const char* uri, const char* mode);
01585 
01586 private:
01587     Device(const Device&);
01588     Device& operator=(const Device&);
01589 
01590     void clearSensors()
01591     {
01592         for (int i = 0; i < ONI_MAX_SENSORS; ++i)
01593         {
01594             m_aSensorInfo[i]._setInternal(NULL);
01595         }
01596     }
01597 
01598     inline Status _setHandle(OniDeviceHandle deviceHandle);
01599 
01600 private:
01601     PlaybackControl* m_pPlaybackControl;
01602 
01603     OniDeviceHandle m_device;
01604     DeviceInfo m_deviceInfo;
01605     SensorInfo m_aSensorInfo[ONI_MAX_SENSORS];
01606 
01607     bool m_isOwner;
01608 };
01609 
01623 class PlaybackControl
01624 {
01625 public:
01626 
01632     ~PlaybackControl()
01633     {
01634         detach();
01635     }
01636 
01657     float getSpeed() const
01658     {
01659         if (!isValid())
01660         {
01661             return 0.0f;
01662         }
01663         float speed;
01664         Status rc = m_pDevice->getProperty<float>(DEVICE_PROPERTY_PLAYBACK_SPEED, &speed);
01665         if (rc != STATUS_OK)
01666         {
01667             return 1.0f;
01668         }
01669         return speed;
01670     }
01678     Status setSpeed(float speed)
01679     {
01680         if (!isValid())
01681         {
01682             return STATUS_NO_DEVICE;
01683         }
01684         return m_pDevice->setProperty<float>(DEVICE_PROPERTY_PLAYBACK_SPEED, speed);
01685     }
01686 
01692     bool getRepeatEnabled() const
01693     {
01694         if (!isValid())
01695         {
01696             return false;
01697         }
01698 
01699         OniBool repeat;
01700         Status rc = m_pDevice->getProperty<OniBool>(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, &repeat);
01701         if (rc != STATUS_OK)
01702         {
01703             return false;
01704         }
01705 
01706         return repeat == TRUE;
01707     }
01708 
01717     Status setRepeatEnabled(bool repeat)
01718     {
01719         if (!isValid())
01720         {
01721             return STATUS_NO_DEVICE;
01722         }
01723 
01724         return m_pDevice->setProperty<OniBool>(DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED, repeat ? TRUE : FALSE);
01725     }
01726 
01737     Status seek(const VideoStream& stream, int frameIndex)
01738     {
01739         if (!isValid())
01740         {
01741             return STATUS_NO_DEVICE;
01742         }
01743         OniSeek seek;
01744         seek.frameIndex = frameIndex;
01745         seek.stream = stream._getHandle();
01746         return m_pDevice->invoke(DEVICE_COMMAND_SEEK, seek);
01747     }
01748 
01757     int getNumberOfFrames(const VideoStream& stream) const
01758     {
01759         int numOfFrames = -1;
01760         Status rc = stream.getProperty<int>(STREAM_PROPERTY_NUMBER_OF_FRAMES, &numOfFrames);
01761         if (rc != STATUS_OK)
01762         {
01763             return 0;
01764         }
01765         return numOfFrames;
01766     }
01767 
01768     bool isValid() const
01769     {
01770         return m_pDevice != NULL;
01771     }
01772 private:
01773     Status attach(Device* device)
01774     {
01775         if (!device->isValid() || !device->isFile())
01776         {
01777             return STATUS_ERROR;
01778         }
01779 
01780         detach();
01781         m_pDevice = device;
01782 
01783         return STATUS_OK;
01784     }
01785     void detach()
01786     {
01787         m_pDevice = NULL;
01788     }
01789 
01790     friend class Device;
01791     PlaybackControl(Device* pDevice) : m_pDevice(NULL)
01792     {
01793         if (pDevice != NULL)
01794         {
01795             attach(pDevice);
01796         }
01797     }
01798 
01799     Device* m_pDevice;
01800 };
01801 
01802 class CameraSettings
01803 {
01804 public:
01805     // setters
01806     Status setAutoExposureEnabled(bool enabled)
01807     {
01808         return setProperty(STREAM_PROPERTY_AUTO_EXPOSURE, enabled ? TRUE : FALSE);
01809     }
01810     Status setAutoWhiteBalanceEnabled(bool enabled)
01811     {
01812         return setProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, enabled ? TRUE : FALSE);
01813     }
01814 
01815     bool getAutoExposureEnabled() const
01816     {
01817         OniBool enabled = FALSE;
01818 
01819         Status rc = getProperty(STREAM_PROPERTY_AUTO_EXPOSURE, &enabled);
01820         return rc == STATUS_OK && enabled == TRUE;
01821     }
01822     bool getAutoWhiteBalanceEnabled() const
01823     {
01824         OniBool enabled = FALSE;
01825 
01826         Status rc = getProperty(STREAM_PROPERTY_AUTO_WHITE_BALANCE, &enabled);
01827         return rc == STATUS_OK && enabled == TRUE;
01828     }
01829 
01830     Status setGain(int gain)
01831     {
01832         return setProperty(STREAM_PROPERTY_GAIN, gain);
01833     }
01834     Status setExposure(int exposure)
01835     {
01836         return setProperty(STREAM_PROPERTY_EXPOSURE, exposure);
01837     }
01838     int getGain()
01839     {
01840         int gain;
01841         Status rc = getProperty(STREAM_PROPERTY_GAIN, &gain);
01842         if (rc != STATUS_OK)
01843         {
01844             return 100;
01845         }
01846         return gain;
01847     }
01848     int getExposure()
01849     {
01850         int exposure;
01851         Status rc = getProperty(STREAM_PROPERTY_EXPOSURE, &exposure);
01852         if (rc != STATUS_OK)
01853         {
01854             return 0;
01855         }
01856         return exposure;
01857     }
01858 
01859     bool isValid() const {return m_pStream != NULL;}
01860 private:
01861     template <class T>
01862     Status getProperty(int propertyId, T* value) const
01863     {
01864         if (!isValid()) return STATUS_NOT_SUPPORTED;
01865 
01866         return m_pStream->getProperty<T>(propertyId, value);
01867     }
01868     template <class T>
01869     Status setProperty(int propertyId, const T& value)
01870     {
01871         if (!isValid()) return STATUS_NOT_SUPPORTED;
01872 
01873         return m_pStream->setProperty<T>(propertyId, value);
01874     }
01875 
01876     friend class VideoStream;
01877     CameraSettings(VideoStream* pStream)
01878     {
01879         m_pStream = pStream;
01880     }
01881 
01882     VideoStream* m_pStream;
01883 };
01884 
01885 
01898 class OpenNI
01899 {
01900 public:
01901 
01917     class DeviceConnectedListener
01918     {
01919     public:
01920         DeviceConnectedListener()
01921         {
01922             m_deviceConnectedCallbacks.deviceConnected = deviceConnectedCallback;
01923             m_deviceConnectedCallbacks.deviceDisconnected = NULL;
01924             m_deviceConnectedCallbacks.deviceStateChanged = NULL;
01925             m_deviceConnectedCallbacksHandle = NULL;
01926         }
01927         
01928         virtual ~DeviceConnectedListener()
01929         {
01930         }
01931         
01943         virtual void onDeviceConnected(const DeviceInfo*) = 0;
01944     private:
01945         static void ONI_CALLBACK_TYPE deviceConnectedCallback(const OniDeviceInfo* pInfo, void* pCookie)
01946         {
01947             DeviceConnectedListener* pListener = (DeviceConnectedListener*)pCookie;
01948             pListener->onDeviceConnected(static_cast<const DeviceInfo*>(pInfo));
01949         }
01950 
01951         friend class OpenNI;
01952         OniDeviceCallbacks m_deviceConnectedCallbacks;
01953         OniCallbackHandle m_deviceConnectedCallbacksHandle;
01954 
01955     };
01972     class DeviceDisconnectedListener
01973     {
01974     public:
01975         DeviceDisconnectedListener()
01976         {
01977             m_deviceDisconnectedCallbacks.deviceConnected = NULL;
01978             m_deviceDisconnectedCallbacks.deviceDisconnected = deviceDisconnectedCallback;
01979             m_deviceDisconnectedCallbacks.deviceStateChanged = NULL;
01980             m_deviceDisconnectedCallbacksHandle = NULL;
01981         }
01982         
01983         virtual ~DeviceDisconnectedListener()
01984         {
01985         }
01986         
01995         virtual void onDeviceDisconnected(const DeviceInfo*) = 0;
01996     private:
01997         static void ONI_CALLBACK_TYPE deviceDisconnectedCallback(const OniDeviceInfo* pInfo, void* pCookie)
01998         {
01999             DeviceDisconnectedListener* pListener = (DeviceDisconnectedListener*)pCookie;
02000             pListener->onDeviceDisconnected(static_cast<const DeviceInfo*>(pInfo));
02001         }
02002 
02003         friend class OpenNI;
02004         OniDeviceCallbacks m_deviceDisconnectedCallbacks;
02005         OniCallbackHandle m_deviceDisconnectedCallbacksHandle;
02006     };
02020     class DeviceStateChangedListener
02021     {
02022     public:
02023         DeviceStateChangedListener()
02024         {
02025             m_deviceStateChangedCallbacks.deviceConnected = NULL;
02026             m_deviceStateChangedCallbacks.deviceDisconnected = NULL;
02027             m_deviceStateChangedCallbacks.deviceStateChanged = deviceStateChangedCallback;
02028             m_deviceStateChangedCallbacksHandle = NULL;
02029         }
02030         
02031         virtual ~DeviceStateChangedListener()
02032         {
02033         }
02034         
02041         virtual void onDeviceStateChanged(const DeviceInfo*, DeviceState) = 0;
02042     private:
02043         static void ONI_CALLBACK_TYPE deviceStateChangedCallback(const OniDeviceInfo* pInfo, OniDeviceState state, void* pCookie)
02044         {
02045             DeviceStateChangedListener* pListener = (DeviceStateChangedListener*)pCookie;
02046             pListener->onDeviceStateChanged(static_cast<const DeviceInfo*>(pInfo), DeviceState(state));
02047         }
02048 
02049         friend class OpenNI;
02050         OniDeviceCallbacks m_deviceStateChangedCallbacks;
02051         OniCallbackHandle m_deviceStateChangedCallbacksHandle;
02052     };
02053 
02059     static Status initialize()
02060     {
02061         return (Status)oniInitialize(ONI_API_VERSION); // provide version of API, to make sure proper struct sizes are used
02062     }
02063 
02068     static void shutdown()
02069     {
02070         oniShutdown();
02071     }
02072 
02076     static Version getVersion()
02077     {
02078         OniVersion version = oniGetVersion();
02079         union
02080         {
02081             OniVersion* pC;
02082             Version* pCpp;
02083         } a;
02084         a.pC = &version;
02085         return *a.pCpp;
02086     }
02087 
02095     static const char* getExtendedError()
02096     {
02097         return oniGetExtendedError();
02098     }
02099 
02104     static void enumerateDevices(Array<DeviceInfo>* deviceInfoList)
02105     {
02106         OniDeviceInfo* m_pDeviceInfos;
02107         int m_deviceInfoCount;
02108         oniGetDeviceList(&m_pDeviceInfos, &m_deviceInfoCount);
02109         deviceInfoList->_setData((DeviceInfo*)m_pDeviceInfos, m_deviceInfoCount, true);
02110         oniReleaseDeviceList(m_pDeviceInfos);
02111     }
02112 
02121     static Status waitForAnyStream(VideoStream** pStreams, int streamCount, int* pReadyStreamIndex, int timeout = TIMEOUT_FOREVER)
02122     {
02123         static const int ONI_MAX_STREAMS = 50;
02124         OniStreamHandle streams[ONI_MAX_STREAMS];
02125 
02126         if (streamCount > ONI_MAX_STREAMS)
02127         {
02128             printf("Too many streams for wait: %d > %d\n", streamCount, ONI_MAX_STREAMS);
02129             return STATUS_BAD_PARAMETER;
02130         }
02131 
02132         *pReadyStreamIndex = -1;
02133         for (int i = 0; i < streamCount; ++i)
02134         {
02135             if (pStreams[i] != NULL)
02136             {
02137                 streams[i] = pStreams[i]->_getHandle();
02138             }
02139             else
02140             {
02141                 streams[i] = NULL;
02142             }
02143         }
02144         Status rc = (Status)oniWaitForAnyStream(streams, streamCount, pReadyStreamIndex, timeout);
02145 
02146         return rc;
02147     }
02148 
02156     static Status addDeviceConnectedListener(DeviceConnectedListener* pListener)
02157     {
02158         if (pListener->m_deviceConnectedCallbacksHandle != NULL)
02159         {
02160             return STATUS_ERROR;
02161         }
02162         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceConnectedCallbacks, pListener, &pListener->m_deviceConnectedCallbacksHandle);
02163     }
02171     static Status addDeviceDisconnectedListener(DeviceDisconnectedListener* pListener)
02172     {
02173         if (pListener->m_deviceDisconnectedCallbacksHandle != NULL)
02174         {
02175             return STATUS_ERROR;
02176         }
02177         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceDisconnectedCallbacks, pListener, &pListener->m_deviceDisconnectedCallbacksHandle);
02178     }
02186     static Status addDeviceStateChangedListener(DeviceStateChangedListener* pListener)
02187     {
02188         if (pListener->m_deviceStateChangedCallbacksHandle != NULL)
02189         {
02190             return STATUS_ERROR;
02191         }
02192         return (Status)oniRegisterDeviceCallbacks(&pListener->m_deviceStateChangedCallbacks, pListener, &pListener->m_deviceStateChangedCallbacksHandle);
02193     }
02201     static void removeDeviceConnectedListener(DeviceConnectedListener* pListener)
02202     {
02203         oniUnregisterDeviceCallbacks(pListener->m_deviceConnectedCallbacksHandle);
02204         pListener->m_deviceConnectedCallbacksHandle = NULL;
02205     }
02213     static void removeDeviceDisconnectedListener(DeviceDisconnectedListener* pListener)
02214     {
02215         oniUnregisterDeviceCallbacks(pListener->m_deviceDisconnectedCallbacksHandle);
02216         pListener->m_deviceDisconnectedCallbacksHandle = NULL;
02217     }
02225     static void removeDeviceStateChangedListener(DeviceStateChangedListener* pListener)
02226     {
02227         oniUnregisterDeviceCallbacks(pListener->m_deviceStateChangedCallbacksHandle);
02228         pListener->m_deviceStateChangedCallbacksHandle = NULL;
02229     }
02230 
02239     static OniStatus setLogOutputFolder(const char *strLogOutputFolder)
02240     {
02241         return oniSetLogOutputFolder(strLogOutputFolder);
02242     }
02243 
02253     static OniStatus getLogFileName(char *strFileName, int nBufferSize)
02254     {
02255         return oniGetLogFileName(strFileName, nBufferSize);
02256     }
02257 
02267     static OniStatus  setLogMinSeverity(int nMinSeverity)
02268     {
02269         return oniSetLogMinSeverity(nMinSeverity);
02270     }
02271     
02280     static OniStatus setLogConsoleOutput(bool bConsoleOutput)
02281     {
02282         return oniSetLogConsoleOutput(bConsoleOutput);
02283     }
02284 
02293     static OniStatus setLogFileOutput(bool bFileOutput)
02294     {
02295         return oniSetLogFileOutput(bFileOutput);
02296     }
02297 
02298     #if ONI_PLATFORM == ONI_PLATFORM_ANDROID_ARM
02299 
02308     static OniStatus setLogAndroidOutput(bool bAndroidOutput)
02309     {
02310         return oniSetLogAndroidOutput(bAndroidOutput);
02311     }
02312     #endif
02313     
02314 private:
02315     OpenNI()
02316     {
02317     }
02318 };
02319 
02355 class CoordinateConverter
02356 {
02357 public:
02368     static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, int* pDepthX, int* pDepthY, DepthPixel* pDepthZ)
02369     {
02370         float depthX, depthY, depthZ;
02371         Status rc = (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, &depthX, &depthY, &depthZ);
02372         *pDepthX = (int)depthX;
02373         *pDepthY = (int)depthY;
02374         *pDepthZ = (DepthPixel)depthZ;
02375         return rc;
02376     }
02377 
02388     static Status convertWorldToDepth(const VideoStream& depthStream, float worldX, float worldY, float worldZ, float* pDepthX, float* pDepthY, float* pDepthZ)
02389     {
02390         return (Status)oniCoordinateConverterWorldToDepth(depthStream._getHandle(), worldX, worldY, worldZ, pDepthX, pDepthY, pDepthZ);
02391     }
02392 
02403     static Status convertDepthToWorld(const VideoStream& depthStream, int depthX, int depthY, DepthPixel depthZ, float* pWorldX, float* pWorldY, float* pWorldZ)
02404     {
02405         return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), float(depthX), float(depthY), float(depthZ), pWorldX, pWorldY, pWorldZ);
02406     }
02407 
02418     static Status convertDepthToWorld(const VideoStream& depthStream, float depthX, float depthY, float depthZ, float* pWorldX, float* pWorldY, float* pWorldZ)
02419     {
02420         return (Status)oniCoordinateConverterDepthToWorld(depthStream._getHandle(), depthX, depthY, depthZ, pWorldX, pWorldY, pWorldZ);
02421     }
02422 
02434     static Status convertDepthToColor(const VideoStream& depthStream, const VideoStream& colorStream, int depthX, int depthY, DepthPixel depthZ, int* pColorX, int* pColorY)
02435     {
02436         return (Status)oniCoordinateConverterDepthToColor(depthStream._getHandle(), colorStream._getHandle(), depthX, depthY, depthZ, pColorX, pColorY);
02437     }
02438 };
02439 
02454 class Recorder
02455 {
02456 public:
02461     Recorder() : m_recorder(NULL)
02462     {
02463     }
02464 
02468     ~Recorder()
02469     {
02470         destroy();
02471     }
02472 
02484     Status create(const char* fileName)
02485     {
02486         if (!isValid())
02487         {
02488             return (Status)oniCreateRecorder(fileName, &m_recorder);
02489         }
02490         return STATUS_ERROR;
02491     }
02492 
02499     bool isValid() const
02500     {
02501         return NULL != getHandle();
02502     }
02503 
02514     Status attach(VideoStream& stream, bool allowLossyCompression = false)
02515     {
02516         if (!isValid() || !stream.isValid())
02517         {
02518             return STATUS_ERROR;
02519         }
02520         return (Status)oniRecorderAttachStream(
02521                 m_recorder,
02522                 stream._getHandle(),
02523                 allowLossyCompression);
02524     }
02525 
02532     Status start()
02533     {
02534         if (!isValid())
02535         {
02536             return STATUS_ERROR;
02537         }
02538         return (Status)oniRecorderStart(m_recorder);
02539     }
02540 
02544     void stop()
02545     {
02546         if (isValid())
02547         {
02548             oniRecorderStop(m_recorder);
02549         }
02550     }
02551 
02555     void destroy()
02556     {
02557         if (isValid())
02558         {
02559             oniRecorderDestroy(&m_recorder);
02560         }
02561     }
02562 
02563 private:
02564     Recorder(const Recorder&);
02565     Recorder& operator=(const Recorder&);
02566 
02570     OniRecorderHandle getHandle() const
02571     {
02572         return m_recorder;
02573     }
02574 
02575 
02576     OniRecorderHandle m_recorder;
02577 };
02578 
02579 // Implemetation
02580 Status VideoStream::create(const Device& device, SensorType sensorType)
02581 {
02582     OniStreamHandle streamHandle;
02583     Status rc = (Status)oniDeviceCreateStream(device._getHandle(), (OniSensorType)sensorType, &streamHandle);
02584     if (rc != STATUS_OK)
02585     {
02586         return rc;
02587     }
02588 
02589     m_isOwner = true;
02590     _setHandle(streamHandle);
02591 
02592     if (isPropertySupported(STREAM_PROPERTY_AUTO_WHITE_BALANCE) && isPropertySupported(STREAM_PROPERTY_AUTO_EXPOSURE))
02593     {
02594         m_pCameraSettings = new CameraSettings(this);
02595     }
02596 
02597     return STATUS_OK;
02598 }
02599 
02600 void VideoStream::destroy()
02601 {
02602     if (!isValid())
02603     {
02604         return;
02605     }
02606 
02607     if (m_pCameraSettings != NULL)
02608     {
02609         delete m_pCameraSettings;
02610         m_pCameraSettings = NULL;
02611     }
02612 
02613     if (m_stream != NULL)
02614     {
02615         if(m_isOwner)
02616             oniStreamDestroy(m_stream);
02617         m_stream = NULL;
02618     }
02619 }
02620 
02621 Status Device::open(const char* uri)
02622 {
02623     //If we are not the owners, we stick with our own device
02624     if(!m_isOwner)
02625     {
02626         if(isValid()){
02627             return STATUS_OK;
02628         }else{
02629             return STATUS_OUT_OF_FLOW;
02630         }
02631     }
02632 
02633     OniDeviceHandle deviceHandle;
02634     Status rc = (Status)oniDeviceOpen(uri, &deviceHandle);
02635     if (rc != STATUS_OK)
02636     {
02637         return rc;
02638     }
02639 
02640     _setHandle(deviceHandle);
02641 
02642     return STATUS_OK;
02643 }
02644 
02645 Status Device::_openEx(const char* uri, const char* mode)
02646 {
02647     //If we are not the owners, we stick with our own device
02648     if(!m_isOwner)
02649     {
02650         if(isValid()){
02651             return STATUS_OK;
02652         }else{
02653             return STATUS_OUT_OF_FLOW;
02654         }
02655     }
02656 
02657     OniDeviceHandle deviceHandle;
02658     Status rc = (Status)oniDeviceOpenEx(uri, mode, &deviceHandle);
02659     if (rc != STATUS_OK)
02660     {
02661         return rc;
02662     }
02663 
02664     _setHandle(deviceHandle);
02665 
02666     return STATUS_OK;
02667 }
02668 
02669 Status Device::_setHandle(OniDeviceHandle deviceHandle)
02670 {
02671     if (m_device == NULL)
02672     {
02673         m_device = deviceHandle;
02674 
02675         clearSensors();
02676 
02677         oniDeviceGetInfo(m_device, &m_deviceInfo);
02678 
02679         if (isFile())
02680         {
02681             m_pPlaybackControl = new PlaybackControl(this);
02682         }
02683 
02684         // Read deviceInfo
02685         return STATUS_OK;
02686     }
02687 
02688     return STATUS_OUT_OF_FLOW;
02689 }
02690 
02691 void Device::close()
02692 {
02693     if (m_pPlaybackControl != NULL)
02694     {
02695         delete m_pPlaybackControl;
02696         m_pPlaybackControl = NULL;
02697     }
02698 
02699     if (m_device != NULL)
02700     {
02701         if(m_isOwner)
02702         {
02703             oniDeviceClose(m_device);
02704         }
02705 
02706         m_device = NULL;
02707     }
02708 }
02709 
02710 
02711 }
02712 
02713 #endif // _OPEN_NI_HPP_