libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/world/world.hpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                                                         *
00003  *   PSYCHOSYNTH                                                           *
00004  *   ===========                                                           *
00005  *                                                                         *
00006  *   Copyright (C) 2007 by Juan Pedro Bolivar Puente                       *
00007  *                                                                         *
00008  *   This program is free software: you can redistribute it and/or modify  *
00009  *   it under the terms of the GNU General Public License as published by  *
00010  *   the Free Software Foundation, either version 3 of the License, or     *
00011  *   (at your option) any later version.                                   *
00012  *                                                                         *
00013  *   This program is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00016  *   GNU General Public License for more details.                          *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU General Public License     *
00019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #ifndef PSYNTH_WORLD_H
00024 #define PSYNTH_WORLD_H
00025 
00026 #include <list>
00027 #include <map>
00028 #include <iostream>
00029 
00030 #include <psynth/synth/audio_info.hpp>
00031 #include <psynth/world/patcher.hpp>
00032 #include <psynth/graph/node.hpp>
00033 #include <psynth/graph/node_output.hpp>
00034 #include <psynth/graph/node_mixer.hpp>
00035 #include <psynth/graph/node_manager.hpp>
00036 #include <psynth/graph/node_factory_manager.hpp>
00037 
00038 namespace psynth
00039 {
00040 
00041 class world;
00042 class world_node_listener;
00043 
00044 class world_node
00045 {
00046     friend class world;
00047     
00048     graph::node* m_nod; /* TODO: Use node_manager::Iterator instead? */
00049     world* m_world;
00050 
00051     world_node (graph::node* nod, world* world) :
00052         m_nod (nod), m_world (world) {};
00053 
00054 public:
00055     world_node ()
00056         : m_nod (NULL)
00057         , m_world (NULL)
00058         {}
00059     
00060     world_node(const world_node& o)
00061         : m_nod(o.m_nod)
00062         , m_world(o.m_world)
00063         {};
00064 
00065     bool is_null () const {
00066         return m_nod == NULL;
00067     };
00068 
00069     int get_id () const {
00070         return m_nod->get_id ();
00071     };
00072     
00073     int get_type () const {
00074         return m_nod->get_type ();
00075     };
00076 
00077     const std::string& get_name () {
00078         return m_nod->get_name ();
00079     };
00080     
00081     world* get_world() {
00082         return m_world;
00083     }
00084     
00085     inline void add_listener (world_node_listener* cl);
00086 
00087     inline void delete_listener (world_node_listener* cl);
00088 
00089     inline void delete_me ();
00090     
00091     inline void activate ();
00092 
00093     inline void deactivate ();
00094 
00095     template <typename T>
00096     inline void set_param (int id, const T& data);
00097 
00098     template <typename T>
00099     inline void set_param (const std::string& name, const T& data);
00100 
00101     void attach_watch (int type, int in_sock, graph::watch* watch) {
00102         m_nod->attach_watch (type, in_sock, watch);
00103     }
00104 
00105     void detach_watch (int type, int in_sock, graph::watch* watch) {
00106         m_nod->detach_watch (type, in_sock, watch);
00107     }
00108     
00109     int get_param_id (const std::string& name) const {
00110         return m_nod->get_param(name).get_id ();
00111     }
00112 
00113     const std::string& get_param_name (int id) const {
00114         return m_nod->param(id).get_name ();
00115     }
00116     
00117     int get_param_type (int id) const {
00118         return m_nod->param(id).type();
00119     }
00120 
00121     int get_param_type (const std::string& name) const {
00122         return m_nod->get_param(name).type();
00123     }
00124     
00125     template <typename T>
00126     void get_param (int id, T& data) const {
00127         m_nod->param(id).get(data);
00128     }
00129 
00130     template <typename T>
00131     void get_param (const std::string& name, T& data) const {
00132         m_nod->get_param(name).get(data);
00133     }
00134 
00135     bool operator== (const world_node& o) const {
00136         return m_nod == o.m_nod;
00137     }
00138 
00139     bool operator!= (const world_node& o) const {
00140         return m_nod != o.m_nod;
00141     }
00142 };
00143 
00144 class world_listener
00145 {
00146 public:
00147     virtual ~world_listener() {};
00148     virtual void handle_add_node (world_node& nod) = 0;
00149     virtual void handle_delete_node (world_node& nod) = 0;
00150 };
00151 
00152 class world_node_listener
00153 {
00154 public:
00155     virtual ~world_node_listener () {};
00156     virtual void handle_activate_node (world_node& nod) = 0;
00157     virtual void handle_deactivate_node (world_node& nod) = 0;
00158     virtual void handle_set_param_node (world_node& ob, int id) = 0;
00159 };
00160 
00161 struct world_patcher_event
00162 {
00163     world_node src;
00164     world_node dest;
00165     int src_socket;
00166     int dest_socket;
00167     int socket_type;
00168     
00169     world_patcher_event (const world_node& s, const world_node& d,
00170                          int ss, int ds, int st) :
00171         src(s), dest(d), src_socket(ss), dest_socket(ds), socket_type(st) {}
00172 };
00173 
00174 class world_patcher_listener
00175 {
00176 public:
00177     virtual ~world_patcher_listener () {};
00178     virtual void handle_link_added (const world_patcher_event& ev) = 0;
00179     virtual void handle_link_deleted (const world_patcher_event& ev) = 0;
00180 };
00181 
00182 class world_subject
00183 {
00184     typedef std::list<world_node_listener*>::iterator node_listener_iter;
00185     typedef std::list<world_listener*>::iterator listener_iter;
00186     
00187     std::list<world_listener*> m_listeners;
00188     std::list<world_patcher_listener*> m_patch_list;
00189     std::map<int, std::list<world_node_listener*> > m_nod_listeners; 
00190     std::list<world_node_listener*> m_all_nod_list;
00191     
00192 protected:
00193     void notify_add_node (world_node& nod);
00194     void notify_delete_node (world_node& nod);
00195     void notify_activate_node (world_node& nod);
00196     void notify_deactivate_node (world_node& nod);
00197     void notify_set_param_node (world_node& nod, int param_id);
00198     void notify_link_added (const world_patcher_event& ev);
00199     void notify_link_deleted (const world_patcher_event& ev);
00200     
00201 public:
00202     void add_world_listener (world_listener* cl) {
00203         m_listeners.push_back(cl);
00204     };
00205 
00206     void add_world_patcher_listener (world_patcher_listener* cl) {
00207         m_patch_list.push_back(cl);
00208     };
00209 
00210     void add_world_node_listener (world_node_listener* cl) {
00211         m_all_nod_list.push_back(cl);
00212     };
00213     
00214     void add_world_node_listener (world_node& nod, world_node_listener* cl) {
00215         std::map<int, std::list<world_node_listener*> >::iterator it;
00216         
00217         if ((it = m_nod_listeners.find(nod.get_id ())) != m_nod_listeners.end())
00218             it->second.push_back(cl);
00219     };
00220     
00221     void delete_world_listener (world_listener* cl) {
00222         m_listeners.remove(cl);
00223     };
00224 
00225     void delete_world_patcher_listener (world_patcher_listener* cl) {
00226         m_patch_list.remove(cl);
00227     };
00228 
00229     void delete_world_node_listener (world_node_listener* cl) {
00230         m_all_nod_list.remove(cl);
00231     };
00232     
00233     void delete_world_node_listener (world_node& nod, world_node_listener* cl) {
00234         std::map<int, std::list<world_node_listener*> >::iterator it;
00235         
00236         if ((it = m_nod_listeners.find(nod.get_id())) != m_nod_listeners.end())
00237             it->second.remove(cl);
00238     };
00239 };
00240 
00241 class world : public world_subject,
00242               public patcher_listener
00243 {    
00244     audio_info m_info;
00245 
00246     base::mgr_auto_ptr<patcher> m_patcher;
00247     
00248     graph::node_manager m_node_mgr;
00249     graph::node_output* m_output;
00250     graph::node_audio_mixer* m_mixer;
00251     int m_last_id;
00252     graph::node_factory_manager m_nodfact;
00253     
00254     static const int MIXER_CHANNELS = 16;
00255 
00256     void register_default_node_factory ();
00257     
00258 public:
00259     enum {
00260         OUTPUT_ID = 0,
00261         MIXER_ID,
00262         MIN_USER_ID = 1024
00263     };
00264     
00265     world (const audio_info& info);
00266     ~world ();
00267 
00268     void clear ();
00269     
00270     const audio_info& get_info () const {
00271         return m_info;
00272     };
00273 
00274     void set_info (const audio_info& info) {
00275         if (m_info != info)
00276             m_node_mgr.set_info (info);
00277     }
00278 
00279     void register_node_factory (graph::node_factory& f) {
00280         m_nodfact.register_factory (f);
00281     }
00282     
00283     world_node find_node (int id);
00284 
00285     world_node add_node (int type);
00286     world_node add_node (const std::string& type_name);
00287     
00288     template <typename T>
00289     void set_param_node (world_node& nod, int id, const T& data) {
00290         nod.m_nod->param(id).set(data);
00291         notify_set_param_node (nod, id);
00292         if (m_patcher)
00293             m_patcher->set_param_node (nod.m_nod, id);
00294     }
00295 
00296     template <typename T>
00297     void set_param_node (world_node& nod, const std::string& name, const T& data) {
00298         graph::node_param& param = nod.m_nod->get_param(name);
00299         param.set (data);
00300         notify_set_param_node (nod, param.get_id());
00301         if (m_patcher)
00302             m_patcher->set_param_node (nod.m_nod, param.get_id());
00303     }
00304     
00305     void delete_node (world_node& nod);
00306 
00307     void activate_node (world_node& nod);
00308 
00309     void deactivate_node (world_node& nod);
00310 
00311     void attach_output (graph::audio_async_output_ptr out) {
00312         m_output->attach_output (out);
00313     };
00314 
00315     void attach_passive_output (graph::audio_output_ptr out) {
00316         m_output->attach_passive_output (out);
00317     };
00318     
00319     void detach_output (graph::audio_async_output_ptr out) {
00320         m_output->detach_output (out);
00321     };
00322 
00323     void detach_passive_output (graph::audio_output_ptr out) {
00324         m_output->detach_passive_output (out);
00325     };
00326 
00327     void set_patcher (base::mgr_ptr<patcher> pat);
00328 
00329     void unset_patcher ();
00330     
00331     void update () {
00332         if (m_patcher)
00333             m_patcher->update();
00334     }
00335 
00336     void handle_link_added (const patcher_event& ev) {
00337         notify_link_added (world_patcher_event (world_node(ev.src,this),
00338                                                 world_node(ev.dest,this),
00339                                                 ev.src_socket,
00340                                                 ev.dest_socket,
00341                                                 ev.socket_type));
00342     };
00343     
00344     void handle_link_deleted (const patcher_event& ev) {
00345         notify_link_deleted (world_patcher_event (world_node(ev.src,this),
00346                                                   world_node(ev.dest,this),
00347                                                   ev.src_socket,
00348                                                   ev.dest_socket,
00349                                                   ev.socket_type));
00350     }
00351 };
00352 
00353 template <typename T>
00354 void world_node::set_param (int id, const T& data) {
00355     m_world->set_param_node (*this, id, data);
00356 };
00357 
00358 template <typename T>
00359 void world_node::set_param (const std::string& name, const T& data) {
00360     m_world->set_param_node (*this, name, data);
00361 };
00362 
00363 void world_node::add_listener (world_node_listener* cl) {
00364     m_world->add_world_node_listener (*this, cl);
00365 }
00366 
00367 void world_node::delete_listener (world_node_listener* cl) {
00368     m_world->delete_world_node_listener (*this, cl);
00369 }
00370 
00371 void world_node::activate () {
00372     m_world->activate_node (*this);
00373 }
00374 
00375 void world_node::delete_me () {
00376     m_world->delete_node (*this);
00377 }
00378 
00379 void world_node::deactivate () {
00380     m_world->deactivate_node (*this);
00381 }
00382 
00383 } /* namespace psynth */
00384 
00385 #endif /* PSYNTH_WORLD_H */