Point Cloud Library (PCL)  1.3.1
grabber.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * Author: Suat Gedikli (gedikli@willowgarage.com), Nico Blodow (blodow@cs.tum.edu)
00035  */
00036 
00037 #include "pcl/pcl_config.h"
00038 #ifdef HAVE_OPENNI
00039 
00040 #ifndef __PCL_IO_GRABBER__
00041 #define __PCL_IO_GRABBER__
00042 
00043 // needed for the grabber interface / observers
00044 #include <map>
00045 #include <iostream>
00046 #include <string>
00047 #include <boost/signals2.hpp>
00048 #include <boost/signals2/slot.hpp>
00049 #include <typeinfo>
00050 #include <vector>
00051 #include <sstream>
00052 #include <pcl/io/pcl_io_exception.h>
00053 
00054 namespace pcl
00055 {
00056 
00060 class Grabber
00061 {
00062   public:
00067     virtual inline ~Grabber () throw ();
00068 
00075     template<typename T> boost::signals2::connection registerCallback (const boost::function<T>& callback);
00076 
00082     template<typename T> bool providesCallback () const;
00083 
00089     virtual void start () = 0 ;
00090 
00096     virtual void stop () = 0;
00097 
00103     virtual std::string getName () const = 0;
00104 
00109     virtual bool isRunning () const = 0;
00110   protected:
00111     virtual void signalsChanged () {}
00112     template<typename T> boost::signals2::signal<T>* find_signal () const;
00113     template<typename T> int num_slots () const;
00114     template<typename T> void disconnect_all_slots ();
00115     template<typename T> void block_signal ();
00116     template<typename T> void unblock_signal ();
00117     inline void block_signals ();
00118     inline void unblock_signals ();
00119 
00120     template<typename T> boost::signals2::signal<T>* createSignal ();
00121     std::map<std::string, boost::signals2::signal_base*> signals_;
00122     std::map<std::string, std::vector<boost::signals2::connection> > connections_;
00123     std::map<std::string, std::vector<boost::signals2::shared_connection_block> > shared_connections_;
00124 };
00125 
00126 Grabber::~Grabber () throw ()
00127 {
00128   for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
00129     delete signal_it->second;
00130 }
00131 
00132 template<typename T> boost::signals2::signal<T>* Grabber::find_signal () const
00133 {
00134   typedef boost::signals2::signal<T> Signal;
00135 
00136   std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid(T).name());
00137   if (signal_it != signals_.end ())
00138     return (dynamic_cast<Signal*> (signal_it->second));
00139 
00140   return (NULL);
00141 }
00142 
00143 template<typename T> void Grabber::disconnect_all_slots ()
00144 {
00145   typedef boost::signals2::signal<T> Signal;
00146 
00147   if (signals_.find (typeid(T).name()) != signals_.end ())
00148   {
00149     Signal* signal = dynamic_cast<Signal*> (signals_[typeid(T).name()]);
00150     signal->disconnect_all_slots ();
00151   }
00152 }
00153 
00154 template<typename T> void Grabber::block_signal ()
00155 {
00156   if (connections_.find (typeid(T).name()) != connections_.end ())
00157     for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid(T).name()].begin(); cIt != shared_connections_[typeid(T).name()].end(); ++cIt)
00158       cIt->block ();
00159 }
00160 
00161 template<typename T> void Grabber::unblock_signal ()
00162 {
00163   if (connections_.find (typeid(T).name()) != connections_.end ())
00164     for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid(T).name()].begin(); cIt != shared_connections_[typeid(T).name()].end(); ++cIt)
00165       cIt->unblock ();
00166 }
00167 
00168 void Grabber::block_signals ()
00169 {
00170   for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
00171     for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin(); cIt != shared_connections_[signal_it->first].end(); ++cIt)
00172       cIt->block ();    
00173 }
00174 
00175 void Grabber::unblock_signals ()
00176 {
00177   for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
00178     for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin(); cIt != shared_connections_[signal_it->first].end(); ++cIt)
00179       cIt->unblock ();    
00180 }
00181 
00182 template<typename T> int Grabber::num_slots () const
00183 {
00184   typedef boost::signals2::signal<T> Signal;
00185 
00186   // see if we have a signal for this type
00187   std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid(T).name());
00188   if (signal_it != signals_.end())
00189   {
00190     Signal* signal = dynamic_cast<Signal*> (signal_it->second);
00191     return (signal->num_slots ());
00192   }
00193   return (0);
00194 }
00195 
00196 template<typename T> boost::signals2::signal<T>* Grabber::createSignal ()
00197 {
00198   typedef boost::signals2::signal<T> Signal;
00199 
00200   if (signals_.find (typeid(T).name()) == signals_.end ())
00201   {
00202     Signal* signal = new Signal ();
00203     signals_[typeid(T).name ()] = signal;
00204     return (signal);
00205   }
00206   return (0);
00207 }
00208 
00209 template<typename T> boost::signals2::connection Grabber::registerCallback (const boost::function<T> & callback)
00210 {
00211   typedef boost::signals2::signal<T> Signal;
00212   if (signals_.find (typeid(T).name()) == signals_.end ())
00213   {
00214     std::stringstream sstream;
00215 
00216     sstream << "no callback for type:" << typeid(T).name();
00217     /*
00218     sstream << "registered Callbacks are:" << std::endl;
00219     for( std::map<std::string, boost::signals2::signal_base*>::const_iterator cIt = signals_.begin ();
00220          cIt != signals_.end (); ++cIt)
00221     {
00222       sstream << cIt->first << std::endl;
00223     }*/
00224 
00225     THROW_PCL_IO_EXCEPTION ("[%s] %s", getName ().c_str (), sstream.str ().c_str ());
00226     //return (boost::signals2::connection ());
00227   }
00228   Signal* signal = dynamic_cast<Signal*> (signals_[typeid(T).name()]);
00229   boost::signals2::connection ret = signal->connect (callback);
00230 
00231   connections_[typeid(T).name()].push_back(ret);
00232   shared_connections_[typeid(T).name()].push_back(boost::signals2::shared_connection_block(connections_[typeid(T).name()].back()));
00233   signalsChanged ();
00234   return (ret);
00235 }
00236 
00237 template<typename T> bool Grabber::providesCallback () const
00238 {
00239   if (signals_.find (typeid(T).name()) == signals_.end ())
00240     return (false);
00241   return (true);
00242 }
00243 
00244 } // namespace
00245 
00246 #endif
00247 #endif //HAVE_OPENNI
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines