1 /* 2 * This file is part of the OpenKinect Project. http://www.openkinect.org 3 * 4 * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file 5 * for details. 6 * 7 * This code is licensed to you under the terms of the Apache License, version 8 * 2.0, or, at your option, the terms of the GNU General Public License, 9 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, 10 * or the following URLs: 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * http://www.gnu.org/licenses/gpl-2.0.txt 13 * 14 * If you redistribute this file in source form, modified or unmodified, you 15 * may: 16 * 1) Leave this header intact and distribute it under the same terms, 17 * accompanying it with the APACHE20 and GPL20 files, or 18 * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or 19 * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file 20 * In all cases you must keep the copyright notice intact and include a copy 21 * of the CONTRIB file. 22 * 23 * Binary distributions must follow the binary distribution requirements of 24 * either License. 25 */ 26 27 #pragma once 28 29 #include <libfreenect.h> 30 #include <stdexcept> 31 #include <map> 32 #include <pthread.h> 33 34 namespace Freenect { 35 class Noncopyable { 36 public: Noncopyable()37 Noncopyable() {} ~Noncopyable()38 ~Noncopyable() {} 39 private: 40 Noncopyable( const Noncopyable& ); 41 const Noncopyable& operator=( const Noncopyable& ); 42 }; 43 44 class FreenectTiltState { 45 friend class FreenectDevice; FreenectTiltState(freenect_raw_tilt_state * _state)46 FreenectTiltState(freenect_raw_tilt_state *_state): 47 m_state(_state), m_code(_state->tilt_status) 48 {} 49 public: getAccelerometers(double * x,double * y,double * z)50 void getAccelerometers(double* x, double* y, double* z) { 51 freenect_get_mks_accel(m_state, x, y, z); 52 } getTiltDegs()53 double getTiltDegs() { 54 return freenect_get_tilt_degs(m_state); 55 } 56 public: 57 freenect_tilt_status_code m_code; 58 private: 59 freenect_raw_tilt_state *m_state; 60 }; 61 62 class FreenectDevice : Noncopyable { 63 public: FreenectDevice(freenect_context * _ctx,int _index)64 FreenectDevice(freenect_context *_ctx, int _index) { 65 if(freenect_open_device(_ctx, &m_dev, _index) < 0) throw std::runtime_error("Cannot open Kinect"); 66 freenect_set_user(m_dev, this); 67 freenect_set_video_format(m_dev, FREENECT_VIDEO_RGB); 68 freenect_set_depth_format(m_dev, FREENECT_DEPTH_11BIT); 69 freenect_set_depth_callback(m_dev, freenect_depth_callback); 70 freenect_set_video_callback(m_dev, freenect_video_callback); 71 } ~FreenectDevice()72 ~FreenectDevice() { 73 if(freenect_close_device(m_dev) < 0) throw std::runtime_error("Cannot shutdown Kinect"); 74 } startVideo()75 void startVideo() { 76 if(freenect_start_video(m_dev) < 0) throw std::runtime_error("Cannot start RGB callback"); 77 } stopVideo()78 void stopVideo() { 79 if(freenect_stop_video(m_dev) < 0) throw std::runtime_error("Cannot stop RGB callback"); 80 } startDepth()81 void startDepth() { 82 if(freenect_start_depth(m_dev) < 0) throw std::runtime_error("Cannot start depth callback"); 83 } stopDepth()84 void stopDepth() { 85 if(freenect_stop_depth(m_dev) < 0) throw std::runtime_error("Cannot stop depth callback"); 86 } setTiltDegrees(double _angle)87 void setTiltDegrees(double _angle) { 88 if(freenect_set_tilt_degs(m_dev, _angle) < 0) throw std::runtime_error("Cannot set angle in degrees"); 89 } setLed(freenect_led_options _option)90 void setLed(freenect_led_options _option) { 91 if(freenect_set_led(m_dev, _option) < 0) throw std::runtime_error("Cannot set led"); 92 } updateState()93 void updateState() { 94 if (freenect_update_tilt_state(m_dev) < 0) throw std::runtime_error("Cannot update device state"); 95 } getState() const96 FreenectTiltState getState() const { 97 return FreenectTiltState(freenect_get_tilt_state(m_dev)); 98 } 99 // Do not call directly even in child 100 virtual void VideoCallback(void *video, uint32_t timestamp) = 0; 101 // Do not call directly even in child 102 virtual void DepthCallback(void *depth, uint32_t timestamp) = 0; 103 private: 104 freenect_device *m_dev; freenect_depth_callback(freenect_device * dev,void * depth,uint32_t timestamp)105 static void freenect_depth_callback(freenect_device *dev, void *depth, uint32_t timestamp) { 106 FreenectDevice* device = static_cast<FreenectDevice*>(freenect_get_user(dev)); 107 device->DepthCallback(depth, timestamp); 108 } freenect_video_callback(freenect_device * dev,void * video,uint32_t timestamp)109 static void freenect_video_callback(freenect_device *dev, void *video, uint32_t timestamp) { 110 FreenectDevice* device = static_cast<FreenectDevice*>(freenect_get_user(dev)); 111 device->VideoCallback(video, timestamp); 112 } 113 }; 114 115 template <class T>class Freenect : Noncopyable { 116 public: Freenect()117 Freenect() : m_stop(false) { 118 if(freenect_init(&m_ctx, NULL) < 0) throw std::runtime_error("Cannot initialize freenect library"); 119 if(pthread_create(&m_thread, NULL, pthread_callback, (void*)this) != 0) throw std::runtime_error("Cannot initialize freenect thread"); 120 } ~Freenect()121 ~Freenect() { 122 for(typename std::map<int, T*>::iterator it = m_devices.begin() ; it != m_devices.end() ; ++it) { 123 delete it->second; 124 } 125 m_stop = true; 126 pthread_join(m_thread, NULL); 127 if(freenect_shutdown(m_ctx) < 0) throw std::runtime_error("Cannot cleanup freenect library"); 128 } createDevice(int _index)129 T& createDevice(int _index) { 130 m_devices.insert(std::make_pair<int, T*>(_index, new T(m_ctx, _index))); 131 return *(m_devices[_index]); 132 } deleteDevice(int _index)133 void deleteDevice(int _index) { 134 m_devices.erase(_index); 135 } deviceCount()136 int deviceCount() { 137 return freenect_num_devices(m_ctx); 138 } 139 // Do not call directly, thread runs here operator ()()140 void operator()() { 141 while(!m_stop) { 142 if(freenect_process_events(m_ctx) < 0) throw std::runtime_error("Cannot process freenect events"); 143 } 144 } pthread_callback(void * user_data)145 static void *pthread_callback(void *user_data) { 146 Freenect<T>* freenect = static_cast<Freenect<T>*>(user_data); 147 (*freenect)(); 148 return NULL; 149 } 150 private: 151 freenect_context *m_ctx; 152 volatile bool m_stop; 153 pthread_t m_thread; 154 std::map<int, T*> m_devices; 155 }; 156 157 } 158 159