|
libpsynth 0.2.1
|
00001 00012 /* 00013 * Copyright (C) 2007, 2009 Juan Pedro BolĂvar Puente 00014 * 00015 * This program is free software: you can redistribute it and/or modify 00016 * it under the terms of the GNU General Public License as published by 00017 * the Free Software Foundation, either version 3 of the License, or 00018 * (at your option) any later version. 00019 * 00020 * This program is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * You should have received a copy of the GNU General Public License 00026 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00027 * 00028 */ 00029 00030 #ifndef PSYNTH_BASE_CONFIG_H 00031 #define PSYNTH_BASE_CONFIG_H 00032 00033 #include <list> 00034 #include <map> 00035 #include <iostream> 00036 #include <typeinfo> 00037 00038 #include <boost/any.hpp> 00039 00040 #include <psynth/base/tree.hpp> 00041 #include <psynth/base/misc.hpp> 00042 #include <psynth/base/singleton.hpp> 00043 #include <psynth/base/exception.hpp> 00044 #include <psynth/base/observer.hpp> 00045 00046 #include <psynth/base/config_fwd.hpp> 00047 00048 namespace psynth 00049 { 00050 namespace base 00051 { 00052 00053 PSYNTH_DECLARE_ERROR (error, config_error); 00054 PSYNTH_DECLARE_ERROR (config_error, config_type_error); 00055 PSYNTH_DECLARE_ERROR (config_error, config_backend_error); 00056 00057 class conf_node; 00058 00063 class conf_listener : public listener_base 00064 { 00065 public: 00070 virtual void handle_conf_change (conf_node& c) = 0; 00071 00076 virtual void handle_conf_nudge (conf_node& c) = 0; 00077 00082 virtual void handle_conf_add_child (conf_node& c) = 0; 00083 00088 virtual void handle_conf_del_child (conf_node& c) = 0; 00089 }; 00090 00094 class conf_subject : public subject_base <conf_listener> 00095 { 00096 public: 00097 typedef boost::signal <void (conf_node&)> signal; 00098 //typedef psynth::base::signal <void, conf_node&> signal; 00099 00101 signal on_change; 00102 00107 signal on_nudge; 00108 00110 signal on_add_child; 00111 00113 signal on_del_child; 00114 00118 void add_listener (conf_listener& l); 00119 00123 void del_listener (conf_listener& l); 00124 }; 00125 00130 class conf_backend : public conf_listener 00131 { 00132 public: 00134 virtual ~conf_backend() {} 00135 00142 virtual void attach (conf_node& node) = 0; 00143 00150 virtual void datach (conf_node& node) = 0; 00151 00156 virtual void save (conf_node& node) = 0; 00157 00162 virtual void load (conf_node& node) = 0; 00163 00169 virtual void def_load (conf_node& node) = 0; 00170 }; 00171 00181 class conf_node : public conf_subject, 00182 public tree_node <conf_node>, 00183 public PSYNTH_DEFAULT_THREADING <conf_node> 00184 { 00185 public: 00189 const std::type_info& type () const 00190 { 00191 lock lock (this); 00192 return _element.type (); 00193 } 00194 00198 bool empty () const 00199 { 00200 lock lock (this); 00201 return _element.empty (); 00202 } 00203 00207 void nudge () 00208 { 00209 on_nudge (*this); 00210 } 00211 00217 template<class T> 00218 void set (const T& val) 00219 { 00220 lock lock (this); 00221 _element = val; 00222 on_change (*this); 00223 } 00224 00230 template<class T> 00231 void set (const T& val, bool overwrite); 00232 00239 template<class T> 00240 void def (const T& val); 00241 00246 template<class T> 00247 void get (T& data) const; 00248 00252 template<class T> 00253 T get () const; 00254 00258 void save (); 00259 00263 void load (); 00264 00269 void def_load (); 00270 00276 void set_backend (conf_backend_ptr backend); 00277 00281 void unset_backend (); 00282 00283 private: 00284 boost::any _element; 00285 conf_backend_ptr _backend; 00286 00287 void on_init () 00288 { 00289 _backend.reset (); 00290 if (parent ()) 00291 _backend = parent ()->_backend; 00292 } 00293 00294 void on_uninit () 00295 { 00296 _backend.reset (); 00297 } 00298 }; 00299 00303 struct config : public singleton_holder <conf_node> {}; 00304 00305 template<class T> 00306 void conf_node::get (T& data) const 00307 { 00308 lock lock (this); 00309 00310 try { 00311 data = boost::any_cast<T> (_element); 00312 } catch (boost::bad_any_cast&) { 00313 throw config_type_error (); 00314 } 00315 } 00316 00317 template<class T> 00318 T conf_node::get () const 00319 { 00320 lock lock (this); 00321 T ret; 00322 00323 try { 00324 ret = boost::any_cast<T> (_element); 00325 } catch (boost::bad_any_cast&) { 00326 throw config_type_error (); 00327 } 00328 00329 return ret; 00330 } 00331 00332 00333 template<class T> 00334 void conf_node::def (const T& val) 00335 { 00336 lock lock (this); 00337 00338 if (_element.empty ()) { 00339 _element = val; 00340 on_change (*this); 00341 } 00342 } 00343 00344 template<class T> 00345 void conf_node::set (const T& val, bool overwrite) 00346 { 00347 lock lock (this); 00348 00349 if (overwrite || _element.empty ()) { 00350 _element = val; 00351 on_change (*this); 00352 } 00353 } 00354 00355 extern template class subject_base <conf_listener>; 00356 extern template class singleton_holder <conf_node>; 00357 extern template class tree_node <conf_node>; 00358 extern template class PSYNTH_DEFAULT_THREADING <conf_node>; 00359 00360 } /* namespace base */ 00361 } /* namespace psynth */ 00362 00363 #endif /* PSYNTH_BASE_CONFIG_H */
1.7.4