libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/new_graph/node.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_NODE_HPP_
00032 #define PSYNTH_GRAPH_NODE_HPP_
00033 
00034 #include <map>
00035 #include <iostream> // FIXME!
00036 
00037 #include <boost/range/iterator_range.hpp>
00038 #include <boost/intrusive/list_hook.hpp>
00039 
00040 #include <psynth/base/util.hpp>
00041 #include <psynth/base/factory_manager.hpp>
00042 #include <psynth/new_graph/exception.hpp>
00043 
00044 #include <psynth/new_graph/core/patch_fwd.hpp>
00045 #include <psynth/new_graph/processor.hpp>
00046 #include <psynth/new_graph/node_fwd.hpp>
00047 #include <psynth/new_graph/control_fwd.hpp>
00048 #include <psynth/new_graph/port_fwd.hpp>
00049 
00050 namespace psynth
00051 {
00052 namespace graph
00053 {
00054 
00055 PSYNTH_DECLARE_ERROR (error, node_error)
00056 PSYNTH_DECLARE_ERROR (node_error, node_component_error);
00057 PSYNTH_DECLARE_ERROR (node_error, node_attachment_error);
00058 
00059 struct patch_child_hook_tag;
00060 typedef boost::intrusive::list_member_hook<
00061     boost::intrusive::tag<patch_child_hook_tag>
00062     >
00063 patch_child_hook;
00064 
00065 class node : private boost::noncopyable
00066 {
00067     typedef std::map<std::string, in_port_base*>     in_map;
00068     typedef std::map<std::string, out_port_base*>    out_map;
00069     typedef std::map<std::string, in_control_base*>  param_map;
00070     typedef std::map<std::string, out_control_base*> state_map;
00071 
00072 public:
00073     typedef base::ptr_iterator<
00074     base::map_iterator<in_map::key_type,
00075                        in_map::mapped_type> >
00076     input_iterator;
00077     typedef base::ptr_iterator<
00078         base::map_iterator<out_map::key_type,
00079                            out_map::mapped_type> >
00080     output_iterator;
00081     typedef base::ptr_iterator<
00082         base::map_iterator<param_map::key_type,
00083                            param_map::mapped_type> >
00084     param_iterator;
00085     typedef base::ptr_iterator<
00086         base::map_iterator<state_map::key_type,
00087                            state_map::mapped_type> >
00088     state_iterator;
00089     
00090     typedef boost::iterator_range<input_iterator> input_range;
00091     typedef boost::iterator_range<output_iterator> output_range;
00092     typedef boost::iterator_range<param_iterator> param_range;
00093     typedef boost::iterator_range<state_iterator> state_range;
00094     
00095     patch_child_hook _patch_child_hook;
00096     
00097     node ();
00098     
00099     virtual void rt_process (rt_process_context& ctx);
00100     virtual void rt_context_update (rt_process_context& ctx);
00101     virtual void rt_advance ();
00102     
00103     in_port_base& in (const std::string& name);
00104     const in_port_base& in (const std::string& name) const;
00105     input_range inputs ();
00106     
00107     out_port_base& out (const std::string& name);
00108     const out_port_base& out (const std::string& name) const;
00109     output_range outputs ();
00110         
00111     in_control_base& param (const std::string& name);
00112     const in_control_base& param (const std::string& name) const;
00113     param_range params ();
00114     
00115     out_control_base& state (const std::string& name);
00116     const out_control_base& state (const std::string& name) const;
00117     state_range states ();
00118         
00119     void register_component (in_port_base& in);
00120     void register_component (out_port_base& out);
00121     void register_component (in_control_base& param);
00122     void register_component (out_control_base& state);
00123 
00124     void unregister_component (in_port_base& in);
00125     void unregister_component (out_port_base& out);
00126     
00127     void attach_to_process (processor& p);
00128     void detach_from_process ();
00129 
00130     void attach_to_patch (core::patch& p);
00131     void detach_from_patch ();
00132 
00133     processor& process ()
00134     {
00135         check_attached_to_process ();
00136         return *_process;
00137     }
00138     
00139     const processor& process () const
00140     {
00141         check_attached_to_process ();
00142         return *_process;
00143     }
00144     
00145     core::patch& patch ()
00146     {
00147         check_attached_to_patch ();
00148         return *_patch;
00149     }
00150     
00151     const core::patch& patch () const
00152     {
00153         check_attached_to_patch ();
00154         return *_patch;
00155     }
00156 
00157     bool is_attached_to_process () const
00158     { return _process != 0; }
00159     bool is_attached_to_patch () const
00160     { return _patch != 0; }
00161     
00162     void check_attached_to_process (bool attached = true) const
00163     {
00164         if (is_attached_to_process () != attached)
00165             throw node_attachment_error ();
00166     }
00167     
00168     void check_attached_to_patch (bool attached = true) const
00169     {
00170         if (is_attached_to_patch () != attached)
00171             throw node_attachment_error ();
00172     }
00173 
00174     template <class Fn>
00175     void execute_rt (const Fn& fn);
00176     
00177 private:
00178     
00179     virtual void rt_on_context_update (rt_process_context& ctx) {}
00180     virtual void rt_do_process (rt_process_context& ctx) {}
00181     
00182     core::patch* _patch;
00183     processor*   _process;
00184     
00185     in_map    _inputs;
00186     out_map   _outputs;
00187     param_map _params;
00188     state_map _states;
00189 
00190     bool _rt_processed;
00191     bool _rt_post_processed;
00192 };
00193 
00194 void connect (node_ptr source, const std::string& out_port,
00195               node_ptr dest, const std::string& dest_port);
00196 
00197 typedef
00198 base::restricted_global_factory_manager<std::string, node_ptr>
00199 node_factory;
00200 
00201 #define PSYNTH_REGISTER_NODE_STATIC(node_type)                          \
00202     static ::psynth::graph::node_factory::registrant<node_type> node_type ## _registrant_ (#node_type);
00203 
00204 #define PSYNTH_REGISTER_NODE_STATIC_AS(node_type, node_name)            \
00205     static ::psynth::graph::node_factory::registrant<node_type> node_type ## _registrant_ (node_name);
00206 
00207 template <class Fn>
00208 void node::execute_rt (const Fn& fn)
00209 {
00210     if (is_attached_to_process () &&
00211         process ().is_running ())
00212     {    
00213         auto& ctx = process ().context ();
00214         ctx.push_rt_event (make_rt_event ([fn] (rt_process_context&) {
00215                     fn ();
00216                 }));
00217     }
00218     else
00219         fn ();
00220 }
00221 
00222 } /* namespace graph */
00223 
00224 namespace base
00225 {
00226 
00227 extern template class
00228 base::restricted_global_factory_manager<std::string, graph::node_ptr>;
00229 
00230 } /* namespace base */
00231 
00232 } /* namespace psynth */
00233 
00234 #endif /* PSYNTH_GRAPH_NODE_HPP_ */