libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/new_graph/control.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #ifndef PSYNTH_GRAPH_CONTROL_HPP_
00032 #define PSYNTH_GRAPH_CONTROL_HPP_
00033 
00034 #include <atomic>
00035 #include <map>
00036 #include <mutex>
00037 
00038 #include <boost/any.hpp>
00039 #include <boost/lexical_cast.hpp>
00040 
00041 #include <psynth/base/type_value.hpp>
00042 #include <psynth/new_graph/node_fwd.hpp>
00043 #include <psynth/new_graph/event.hpp>
00044 #include <psynth/new_graph/exception.hpp>
00045 
00046 namespace psynth
00047 {
00048 namespace graph
00049 {
00050 
00051 PSYNTH_DECLARE_ERROR (error, control_type_error);
00052 
00053 typedef std::map<std::string, boost::any> control_meta;
00054 extern const control_meta default_control_meta;
00055 
00062 class control_base : private boost::noncopyable
00063 {
00064 public:
00065     virtual ~control_base () {}
00066 
00067     virtual base::type_value type () const = 0;
00068     virtual const control_meta& meta () const = 0;
00069 
00070     virtual std::string str () const = 0;    
00071 
00072     const node& owner () const
00073     { return *_owner; }
00074 
00075     node& owner ()
00076     { return *_owner; }
00077 
00078     std::string name ()
00079     { return _name; }
00080     
00081 protected:    
00082     control_base (const std::string& name, node* owner);
00083 
00084     bool _has_owner () const { return _owner != 0; }
00085     
00086 protected:
00087     std::string _name;
00088     node*       _owner;
00089 };
00090 
00091 
00098 class in_control_base : public control_base
00099 {
00100 public:
00101     virtual void str (const std::string& s) = 0;
00102 
00103     template <typename T>
00104     T get () const;
00105 
00106     template <typename T>
00107     const T& rt_get () const;
00108 
00109     template <typename T>
00110     void set (const T&);
00111         
00112 protected:
00113     in_control_base (const std::string& name, node* owner);
00114 };
00115 
00116 
00123 class out_control_base : public control_base
00124 {
00125 public:
00126     template <typename T>
00127     T get () const;
00128 
00129     template <typename T>
00130     const T& rt_get () const;
00131 
00132     template <typename T>
00133     void rt_set (const T&, rt_process_context& ctx);
00134 
00135 protected:
00136     out_control_base (const std::string& name, node* owner);
00137 };
00138 
00139 
00140 template <typename T>
00141 class typed_out_control_base : public out_control_base
00142 {
00143 public:  
00144     virtual const T& get () const = 0; 
00145     virtual void rt_set (const T& val, rt_process_context& ctx) = 0;
00146     virtual const T& rt_get () const = 0;
00147     
00148     base::type_value type () const
00149     { return typeid (T); }    
00150 
00151     std::string str () const
00152     { return boost::lexical_cast<std::string> (this->get ()); }
00153 
00154 protected:
00155     typed_out_control_base (const std::string& name, node* owner)
00156         : out_control_base (name, owner) {};
00157 };
00158 
00159 
00160 template <typename T>
00161 class typed_in_control_base : public in_control_base
00162 {
00163 public:
00164     virtual const T& get () const = 0;
00165     virtual const T& rt_get () const = 0;
00166     virtual void set (const T&) = 0;
00167 
00168     void str (const std::string& s)
00169     { set (boost::lexical_cast<T> (s)); }
00170 
00171     std::string str () const
00172     { return boost::lexical_cast<std::string> (this->get ()); }
00173 
00174     base::type_value type () const
00175     { return typeid (T); }    
00176 
00177 protected:
00178     typed_in_control_base (const std::string& name, node* owner)
00179         : in_control_base (name, owner) {};
00180 };
00181 
00182 
00183 namespace detail
00184 {
00185 
00186 template <typename T, bool IsFundamental>
00187 class out_control_impl : public typed_out_control_base<T>
00188 {
00189 public:
00190     const T& get () const
00191     { return _value; }
00192     
00193     const T& rt_get () const
00194     { return _value; }
00195 
00196     void rt_set (const T& val, rt_process_context& ctx)
00197     { _value = val; }
00198 
00199 protected:
00200     out_control_impl (const std::string& name, node* owner, T val)
00201         : typed_out_control_base<T> (name, owner), _value (val) {}
00202 
00203 private:
00204     T _value; // FIXME: Substitute with std::atomic<T> whenever GCC
00205               // properly implements it ;)
00206 };
00207 
00208 template <typename T>
00209 class out_control_impl<T, false> : public typed_out_control_base<T>
00210 {
00211 public:
00212     virtual const T& rt_get () const
00213     { return _rt_value; }
00214 
00215     const T& get () const;
00216     
00217     void rt_set (const T& val, rt_process_context& ctx);
00218     
00219 protected:
00220     out_control_impl (const std::string& name, node* owner, T val)
00221         : typed_out_control_base<T> (name, owner)
00222         , _ret_value (val)
00223         , _value (val)
00224         , _rt_value (val) {}
00225 
00226 private:
00227     struct async_update_event : public async_event
00228     {
00229         async_update_event (out_control_impl& ctl, const T& val)
00230             : _ctl (ctl), _new_value (val) {}
00231         void operator () (async_process_context& ctx);
00232     private:
00233         out_control_impl& _ctl;
00234         T _new_value;
00235     };
00236 
00237     friend class async_update_event;
00238 
00239     mutable T _ret_value;
00240     T _value;
00241     T _rt_value;
00242     mutable std::mutex _mutex;
00243 };
00244 
00245 } /* namespace detail */
00246 
00251 template <typename T>
00252 class out_control : public detail::out_control_impl<
00253     T, std::is_fundamental<T>::value>
00254 {
00255     typedef detail::out_control_impl<
00256         T, std::is_fundamental<T>::value> impl_base;
00257 
00258 public:
00259     out_control (const std::string& name, node* owner=0, const T& value=T())
00260         : impl_base (name, owner, value) {}
00261     
00262     const control_meta& meta () const 
00263     { return default_control_meta; } // FIXME !!!!
00264     
00265 };
00266 
00267 
00272 template <typename T>
00273 class in_control : public typed_in_control_base<T>
00274 {
00275 public:
00276     in_control (const std::string& name, node* owner=0, const T& value=T())
00277         : typed_in_control_base<T> (name, owner)
00278         , _value (value)
00279         , _rt_value (value)
00280         , _is_updated (false)
00281     {}
00282 
00283     const control_meta& meta () const 
00284     { return default_control_meta; } // FIXME !!!!
00285     
00286     const T& get () const
00287     { return _value; }
00288     
00289     const T& rt_get () const
00290     { return _rt_value; }
00291 
00292     void set (const T&);    
00293 
00294     bool rt_is_updated ()
00295     { return _is_updated; }
00296     
00297 private:
00298     struct rt_update_event : public rt_event
00299     {
00300         rt_update_event (in_control& ctl, const T& val)
00301             : _ctl (ctl), _new_rt_value (val) {}
00302         void operator () (rt_process_context& ctx);
00303     private:
00304         in_control& _ctl;
00305         T _new_rt_value;
00306     };
00307     
00308     struct rt_post_update_event : public rt_event
00309     {
00310         rt_post_update_event (in_control& ctl)
00311             : _ctl (ctl) {}
00312         void operator () (rt_process_context& ctx);        
00313     private:
00314         in_control& _ctl;
00315     };
00316     
00317     friend class rt_update_event;
00318     friend class rt_post_update_event;
00319 
00320     T _value;
00321     T _rt_value;
00322     bool _is_updated;
00323 };
00324 
00325 extern template class in_control<std::string>;
00326 extern template class in_control<float>;
00327 extern template class in_control<int>;
00328 extern template class in_control<bool>;
00329 
00330 extern template class out_control<std::string>;
00331 extern template class out_control<float>;
00332 extern template class out_control<int>;
00333 extern template class out_control<bool>;
00334 
00335 } /* namespace graph */
00336 } /* namespace psynth */
00337 
00338 #include <psynth/new_graph/control.tpp>
00339 
00340 #endif /* PSYNTH_GRAPH_CONTROL_HPP_ */