Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
grabber.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <pcl/pcl_config.h>
36 
37 #ifndef __PCL_IO_GRABBER__
38 #define __PCL_IO_GRABBER__
39 
40 // needed for the grabber interface / observers
41 #include <map>
42 #include <iostream>
43 #include <string>
44 #include <boost/signals2.hpp>
45 #include <boost/signals2/slot.hpp>
46 #include <typeinfo>
47 #include <vector>
48 #include <sstream>
49 #include <pcl/pcl_macros.h>
51 
52 namespace pcl
53 {
54 
60  {
61  public:
62 
64  Grabber () : signals_ (), connections_ (), shared_connections_ () {}
65 
67  virtual inline ~Grabber () throw ();
68 
73  template<typename T> boost::signals2::connection
74  registerCallback (const boost::function<T>& callback);
75 
79  template<typename T> bool
80  providesCallback () const;
81 
85  virtual void
86  start () = 0;
87 
91  virtual void
92  stop () = 0;
93 
97  virtual std::string
98  getName () const = 0;
99 
103  virtual bool
104  isRunning () const = 0;
105 
107  virtual float
108  getFramesPerSecond () const = 0;
109 
110  protected:
111 
112  virtual void
113  signalsChanged () { }
114 
115  template<typename T> boost::signals2::signal<T>*
116  find_signal () const;
117 
118  template<typename T> int
119  num_slots () const;
120 
121  template<typename T> void
122  disconnect_all_slots ();
123 
124  template<typename T> void
125  block_signal ();
126 
127  template<typename T> void
128  unblock_signal ();
129 
130  inline void
131  block_signals ();
132 
133  inline void
134  unblock_signals ();
135 
136  template<typename T> boost::signals2::signal<T>*
137  createSignal ();
138 
139  std::map<std::string, boost::signals2::signal_base*> signals_;
140  std::map<std::string, std::vector<boost::signals2::connection> > connections_;
141  std::map<std::string, std::vector<boost::signals2::shared_connection_block> > shared_connections_;
142  } ;
143 
144  Grabber::~Grabber () throw ()
145  {
146  for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
147  delete signal_it->second;
148  }
149 
150  template<typename T> boost::signals2::signal<T>*
151  Grabber::find_signal () const
152  {
153  typedef boost::signals2::signal<T> Signal;
154 
155  std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid (T).name ());
156  if (signal_it != signals_.end ())
157  return (dynamic_cast<Signal*> (signal_it->second));
158 
159  return (NULL);
160  }
161 
162  template<typename T> void
163  Grabber::disconnect_all_slots ()
164  {
165  typedef boost::signals2::signal<T> Signal;
166 
167  if (signals_.find (typeid (T).name ()) != signals_.end ())
168  {
169  Signal* signal = dynamic_cast<Signal*> (signals_[typeid (T).name ()]);
170  signal->disconnect_all_slots ();
171  }
172  }
173 
174  template<typename T> void
175  Grabber::block_signal ()
176  {
177  if (connections_.find (typeid (T).name ()) != connections_.end ())
178  for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid (T).name ()].begin (); cIt != shared_connections_[typeid (T).name ()].end (); ++cIt)
179  cIt->block ();
180  }
181 
182  template<typename T> void
183  Grabber::unblock_signal ()
184  {
185  if (connections_.find (typeid (T).name ()) != connections_.end ())
186  for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid (T).name ()].begin (); cIt != shared_connections_[typeid (T).name ()].end (); ++cIt)
187  cIt->unblock ();
188  }
189 
190  void
191  Grabber::block_signals ()
192  {
193  for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
194  for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin (); cIt != shared_connections_[signal_it->first].end (); ++cIt)
195  cIt->block ();
196  }
197 
198  void
199  Grabber::unblock_signals ()
200  {
201  for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it)
202  for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin (); cIt != shared_connections_[signal_it->first].end (); ++cIt)
203  cIt->unblock ();
204  }
205 
206  template<typename T> int
207  Grabber::num_slots () const
208  {
209  typedef boost::signals2::signal<T> Signal;
210 
211  // see if we have a signal for this type
212  std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid (T).name ());
213  if (signal_it != signals_.end ())
214  {
215  Signal* signal = dynamic_cast<Signal*> (signal_it->second);
216  return (static_cast<int> (signal->num_slots ()));
217  }
218  return (0);
219  }
220 
221  template<typename T> boost::signals2::signal<T>*
222  Grabber::createSignal ()
223  {
224  typedef boost::signals2::signal<T> Signal;
225 
226  if (signals_.find (typeid (T).name ()) == signals_.end ())
227  {
228  Signal* signal = new Signal ();
229  signals_[typeid (T).name ()] = signal;
230  return (signal);
231  }
232  return (0);
233  }
234 
235  template<typename T> boost::signals2::connection
236  Grabber::registerCallback (const boost::function<T> & callback)
237  {
238  typedef boost::signals2::signal<T> Signal;
239  if (signals_.find (typeid (T).name ()) == signals_.end ())
240  {
241  std::stringstream sstream;
242 
243  sstream << "no callback for type:" << typeid (T).name ();
244  /*
245  sstream << "registered Callbacks are:" << std::endl;
246  for( std::map<std::string, boost::signals2::signal_base*>::const_iterator cIt = signals_.begin ();
247  cIt != signals_.end (); ++cIt)
248  {
249  sstream << cIt->first << std::endl;
250  }*/
251 
252  THROW_PCL_IO_EXCEPTION ("[%s] %s", getName ().c_str (), sstream.str ().c_str ());
253  //return (boost::signals2::connection ());
254  }
255  Signal* signal = dynamic_cast<Signal*> (signals_[typeid (T).name ()]);
256  boost::signals2::connection ret = signal->connect (callback);
257 
258  connections_[typeid (T).name ()].push_back (ret);
259  shared_connections_[typeid (T).name ()].push_back (boost::signals2::shared_connection_block (connections_[typeid (T).name ()].back (), false));
260  signalsChanged ();
261  return (ret);
262  }
263 
264  template<typename T> bool
266  {
267  if (signals_.find (typeid (T).name ()) == signals_.end ())
268  return (false);
269  return (true);
270  }
271 
272 } // namespace
273 
274 #endif