|
libpsynth 0.2.1
|
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_ */
1.7.4