new automation state model, sort of working, but not really
[ardour.git] / libs / ardour / redirect.cc
index 33fec5088f189ebe08693b2d0007426df9319dd3..710b00fe186b0e31423616109f6e29d9786ed165 100644 (file)
@@ -60,25 +60,25 @@ Redirect::~Redirect ()
 {
 }
 
-Redirect*
-Redirect::clone (const Redirect& other)
+boost::shared_ptr<Redirect>
+Redirect::clone (boost::shared_ptr<const Redirect> other)
 {
-       const Send *send;
-       const PortInsert *port_insert;
-       const PluginInsert *plugin_insert;
-
-       if ((send = dynamic_cast<const Send*>(&other)) != 0) {
-               return new Send (*send);
-       } else if ((port_insert = dynamic_cast<const PortInsert*>(&other)) != 0) {
-               return new PortInsert (*port_insert);
-       } else if ((plugin_insert = dynamic_cast<const PluginInsert*>(&other)) != 0) {
-               return new PluginInsert (*plugin_insert);
+       boost::shared_ptr<const Send> send;
+       boost::shared_ptr<const PortInsert> port_insert;
+       boost::shared_ptr<const PluginInsert> plugin_insert;
+
+       if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new Send (*send));
+       } else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new PortInsert (*port_insert));
+       } else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new PluginInsert (*plugin_insert));
        } else {
                fatal << _("programming error: unknown Redirect type in Redirect::Clone!\n")
                      << endmsg;
                /*NOTREACHED*/
        }
-       return 0;
+       return boost::shared_ptr<Redirect>();
 }
 
 void
@@ -109,100 +109,90 @@ Redirect::set_placement (const string& str, void *src)
 }
 
 int
-Redirect::load_automation (string path)
+Redirect::set_automation_state (const XMLNode& node)
 {
-       string fullpath;
-
-       if (path[0] == '/') { // legacy
-               fullpath = path;
-       } else {
-               fullpath = _session.automation_dir();
-               fullpath += path;
-       }
-       ifstream in (fullpath.c_str());
-
-       if (!in) {
-               warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
-               return 1;
-       }
+       /* NODE STRUCTURE 
+
+          <Automation [optionally with visible="...." ]>
+             <parameter-N>
+               <events>
+               X1 Y1
+              X2 Y2
+              ....
+              </events>
+             </parameter-N>
+            <Automation>
+       */
 
        Glib::Mutex::Lock lm (_automation_lock);
-       set<uint32_t> tosave;
+
        parameter_automation.clear ();
 
-       while (in) {
-               double when;
-               double value;
-               uint32_t port;
+       XMLNodeList nlist = node.children();
+       XMLNodeIterator niter;
 
-               in >> port;     if (!in) break;
-               in >> when;  if (!in) goto bad;
-               in >> value; if (!in) goto bad;
-               
-               AutomationList& al = automation_list (port);
-               al.add (when, value);
-               tosave.insert (port);
-       }
-       
-       for (set<uint32_t>::iterator i = tosave.begin(); i != tosave.end(); ++i) {
-               automation_list (*i).save_state (_("loaded from disk"));
+       for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+               uint32_t param;
+
+               if (sscanf ((*niter)->name().c_str(), "parameter-%" PRIu32, &param) != 1) {
+                       error << string_compose (_("%2: badly formatted node name in XML automation state, ignored"), _name) << endmsg;
+                       continue;
+               }
+
+               AutomationList& al = automation_list (param);
+               if (al.set_state (*(*niter)->children().front())) {
+                       goto bad;
+               }
        }
-       
+
        return 0;
 
   bad:
-       error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg;
+       error << string_compose(_("%1: cannot load automation data from XML"), _name) << endmsg;
        parameter_automation.clear ();
        return -1;
 }
 
-int
-Redirect::save_automation (string path)
+XMLNode&
+Redirect::get_automation_state ()
 {
+       /* NODE STRUCTURE 
+
+          <Automation [optionally with visible="...." ]>
+             <parameter-N>
+               <events>
+               X1 Y1
+              X2 Y2
+              ....
+              </events>
+             </parameter-N>
+            <Automation>
+       */
+
        Glib::Mutex::Lock lm (_automation_lock);
+       XMLNode* node = new XMLNode (X_("Automation"));
        string fullpath;
 
        if (parameter_automation.empty()) {
-               return 1;
+               return *node;
        }
 
-       fullpath = _session.automation_dir();
-       fullpath += path;
-
-       ofstream out (fullpath.c_str());
-
-       if (!out) {
-               error << string_compose(_("%1: cannot open %2 to store automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       AutomationList::const_iterator i;
        map<uint32_t,AutomationList*>::iterator li;
        
        for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
-               for (i = (*li).second->begin(); i != (*li).second->end(); ++i) {
-                       
-                       out << (*li).first << ' ' << (*i)->when << ' ' << (*i)->value << endl;
-                       
-                       if (!out) {
-                               break;
-                       }
-               }
+       
+               XMLNode* child;
                
-               if (i != (*li).second->end()) {
-                       unlink (fullpath.c_str());
-                       error << string_compose(_("%1: could not save automation state to %2"), _name, fullpath) << endmsg;
-                       return -1;
-               }
-       }
-
-       if (li != parameter_automation.end()) {
-               unlink (fullpath.c_str());
-               error << string_compose(_("%1: could not save automation state to %2"), _name, fullpath) << endmsg;
-               return -1;
+               char buf[64];
+               stringstream str;
+               snprintf (buf, sizeof (buf), "parameter-%" PRIu32, li->first);
+               child = new XMLNode (buf);
+               child->add_child_nocopy (li->second->get_state ());
        }
 
-       return 0;
+       return *node;
 }
 
 XMLNode&
@@ -214,7 +204,6 @@ Redirect::get_state (void)
 XMLNode&
 Redirect::state (bool full_state)
 {
-       char buf[64];
        XMLNode* node = new XMLNode (state_node_name);
        stringstream sstr;
 
@@ -228,65 +217,38 @@ Redirect::state (bool full_state)
        
        if (full_state) {
 
-               string path;
-               string legal_name;
-               
-               snprintf (buf, sizeof(buf), "%" PRIu64, id());
-               path = _session.snap_name();
-               path += "-redirect-";
-               path += buf;
-               path += ".automation";
-               
-               /* XXX we didn't ask for a state save, we asked for the current state.
-                  FIX ME!
+               /* NODE STRUCTURE 
+                  
+               <Automation [optionally with visible="...." ]>
+                  <parameter-N>
+                    <events>
+                     X1 Y1
+                    X2 Y2
+                    ....
+                    </events>
+                  </parameter-N>
+                <Automation>
                */
+
+               XMLNode& automation = get_automation_state(); 
                
-               switch (save_automation (path)) {
-               case -1:
-                       error << string_compose(_("Could not get state from Redirect (%1).  Problem with save_automation"), _name) << endmsg;
-                       break;
-                       
-               case 0:
-                       XMLNode *aevents = node->add_child("Automation");
-                       
-                       for (set<uint32_t>::iterator x = visible_parameter_automation.begin(); x != visible_parameter_automation.end(); ++x) {
-                               if (x != visible_parameter_automation.begin()) {
-                                       sstr << ' ';
-                               }
-                               sstr << *x;
+               for (set<uint32_t>::iterator x = visible_parameter_automation.begin(); x != visible_parameter_automation.end(); ++x) {
+                       if (x != visible_parameter_automation.begin()) {
+                               sstr << ' ';
                        }
-                       
-                       aevents->add_property ("path", path);
-                       aevents->add_property ("visible", sstr.str());
-                       break;
+                       sstr << *x;
                }
-       }
 
-       return *node;
-}
+               automation.add_property ("visible", sstr.str());
 
-void
-Redirect::what_has_automation (set<uint32_t>& s) const
-{
-       Glib::Mutex::Lock lm (_automation_lock);
-       map<uint32_t,AutomationList*>::const_iterator li;
-       
-       for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
-               s.insert  ((*li).first);
+               node->add_child_nocopy (automation);
        }
-}
 
-void
-Redirect::what_has_visible_automation (set<uint32_t>& s) const
-{
-       Glib::Mutex::Lock lm (_automation_lock);
-       set<uint32_t>::const_iterator li;
-       
-       for (li = visible_parameter_automation.begin(); li != visible_parameter_automation.end(); ++li) {
-               s.insert  (*li);
-       }
+       return *node;
 }
 
+
 int
 Redirect::set_state (const XMLNode& node)
 {
@@ -308,14 +270,14 @@ Redirect::set_state (const XMLNode& node)
                        IO::set_state (**niter);
                        have_io = true;
 
-               } else if ((*niter)->name() == "Automation") {
+               } else if ((*niter)->name() == X_("Automation")) {
 
                        XMLProperty *prop;
                        
                        if ((prop = (*niter)->property ("path")) != 0) {
-                               load_automation (prop->value());
+                               warning << string_compose (_("old automation data found for %1, ignored"), _name) << endmsg;
                        } else {
-                               warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg;
+                               set_automation_state (*(*niter));
                        }
 
                        if ((prop = (*niter)->property ("visible")) != 0) {
@@ -364,6 +326,27 @@ Redirect::set_state (const XMLNode& node)
        return 0;
 }
 
+void
+Redirect::what_has_automation (set<uint32_t>& s) const
+{
+       Glib::Mutex::Lock lm (_automation_lock);
+       map<uint32_t,AutomationList*>::const_iterator li;
+       
+       for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
+               s.insert  ((*li).first);
+       }
+}
+
+void
+Redirect::what_has_visible_automation (set<uint32_t>& s) const
+{
+       Glib::Mutex::Lock lm (_automation_lock);
+       set<uint32_t>::const_iterator li;
+       
+       for (li = visible_parameter_automation.begin(); li != visible_parameter_automation.end(); ++li) {
+               s.insert  (*li);
+       }
+}
 AutomationList&
 Redirect::automation_list (uint32_t parameter)
 {
@@ -406,7 +389,7 @@ Redirect::mark_automation_visible (uint32_t what, bool yn)
 }
 
 bool
-Redirect::find_next_event (jack_nframes_t now, jack_nframes_t end, ControlEvent& next_event) const
+Redirect::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const
 {
        map<uint32_t,AutomationList*>::const_iterator li;       
        AutomationList::TimeComparator cmp;
@@ -436,35 +419,10 @@ Redirect::find_next_event (jack_nframes_t now, jack_nframes_t end, ControlEvent&
        return next_event.when != max_frames;
 }
 
-void
-Redirect::store_state (RedirectState& state) const
-{
-       state.active = _active;
-}
-
-Change
-Redirect::restore_state (StateManager::State& state)
-{
-       RedirectState* rstate = dynamic_cast<RedirectState*> (&state);
-       set_active (rstate->active, this);
-       return Change (0);
-}
-
-StateManager::State*
-Redirect::state_factory (std::string why) const
-{
-       RedirectState* state = new RedirectState (why);
-
-       store_state (*state);
-
-       return state;
-}
-
 void
 Redirect::set_active (bool yn, void* src)
 {
        _active = yn; 
-       save_state (_("active_changed"));
        active_changed (this, src); 
        _session.set_dirty ();
 }