Remove beat entry from meter dialog (beats are not allowed in API), clean up some...
[ardour.git] / libs / ardour / panner.cc
index faf2e03e2f33bf730c891aadea047912cdeee68e..eb9547edffa87d965c568c3170eff7cb89f82470 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <cmath>
@@ -33,6 +32,7 @@
 #include <pbd/error.h>
 #include <pbd/failed_constructor.h>
 #include <pbd/xml++.h>
+#include <pbd/enumwriter.h>
 
 #include <ardour/session.h>
 #include <ardour/panner.h>
@@ -205,11 +205,11 @@ BaseStereoPanner::snapshot (nframes_t now)
 void
 BaseStereoPanner::transport_stopped (nframes_t frame)
 {
-       _automation.reposition_for_rt_add (frame);
-
        if (_automation.automation_state() != Off) {
                set_position (_automation.eval (frame));
        }
+
+       _automation.reposition_for_rt_add (frame);
 }
 
 void
@@ -231,6 +231,39 @@ BaseStereoPanner::set_automation_state (AutoState state)
        }
 }
 
+int
+BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt)
+{
+       char line[128];
+       LocaleGuard lg (X_("POSIX"));
+       
+       _automation.clear ();
+
+       while (in.getline (line, sizeof (line), '\n')) {
+               jack_nframes_t when;
+               double value;
+
+               ++linecnt;
+
+               if (strcmp (line, "end") == 0) {
+                       break;
+               }
+
+               if (sscanf (line, "%" PRIu32 " %lf", &when, &value) != 2) {
+                       warning << string_compose(_("badly formatted pan automation event record at line %1 of %2 (ignored) [%3]"), linecnt, path, line) << endmsg;
+                       continue;
+               }
+
+               _automation.fast_simple_add (when, value);
+       }
+
+       /* now that we are done loading */
+
+       _automation.StateChanged ();
+
+       return 0;
+}
+
 void
 BaseStereoPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nframes_t nframes)
 {
@@ -473,20 +506,12 @@ EqualPowerStereoPanner::state (bool full_state)
        root->add_property (X_("x"), buf);
        root->add_property (X_("type"), EqualPowerStereoPanner::name);
 
-       if (full_state) {
-               XMLNode* autonode = new XMLNode (X_("Automation"));
-               autonode->add_child_nocopy (_automation.get_state ());
-               root->add_child_nocopy (*autonode);
-       } else {
-               /* never store automation states other than off in a template */
-               snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Off); 
-       }
-
-       root->add_property (X_("automation-state"), buf);
-       snprintf (buf, sizeof (buf), "0x%x", _automation.automation_style()); 
-       root->add_property (X_("automation-style"), buf);
+       XMLNode* autonode = new XMLNode (X_("Automation"));
+       autonode->add_child_nocopy (_automation.state (full_state));
+       root->add_child_nocopy (*autonode);
 
        StreamPanner::add_state (*root);
+
        root->add_child_nocopy (_control.get_state ());
 
        return *root;
@@ -496,7 +521,6 @@ int
 EqualPowerStereoPanner::set_state (const XMLNode& node)
 {
        const XMLProperty* prop;
-       int x;
        float pos;
        LocaleGuard lg (X_("POSIX"));
 
@@ -508,27 +532,22 @@ EqualPowerStereoPanner::set_state (const XMLNode& node)
        StreamPanner::set_state (node);
 
        for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) {
-               if ((*iter)->name() == X_("panner")) {
-                       _control.set_state (**iter);
+
+               if ((*iter)->name() == X_("controllable")) {
+                       if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") {
+                               _control.set_state (**iter);
+                       }
+
                } else if ((*iter)->name() == X_("Automation")) {
+
                        _automation.set_state (*((*iter)->children().front()));
-               }
-       }
-       
-       if ((prop = node.property (X_("automation-state")))) {
-               sscanf (prop->value().c_str(), "0x%x", &x);
-               _automation.set_automation_state ((AutoState) x);
 
-               if (x != Off) {
-                       set_position (_automation.eval (parent.session().transport_frame()));
+                       if (_automation.automation_state() != Off) {
+                               set_position (_automation.eval (parent.session().transport_frame()));
+                       }
                }
        }
 
-       if ((prop = node.property (X_("automation-style")))) {
-               sscanf (prop->value().c_str(), "0x%x", &x);
-               _automation.set_automation_style ((AutoStyle) x);
-       }
-
        return 0;
 }
 
@@ -634,10 +653,7 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nfram
                        }
                        
                        pan = left * gain_coeff;
-                       
-                       for (; n < nframes; ++n) {
-                               dst[n] += src[n] * pan;
-                       }
+                       Session::mix_buffers_with_gain(dst+n,src+n,nframes-n,pan);
                        
                } else {
 
@@ -647,20 +663,10 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nfram
                        if ((pan *= gain_coeff) != 1.0f) {
                                
                                if (pan != 0.0f) {
-                                       
-                                       for (nframes_t n = 0; n < nframes; ++n) {
-                                               dst[n] += src[n] * pan;
-                                       }      
-                                       
+                                       Session::mix_buffers_with_gain(dst,src,nframes,pan);
                                } 
-
-                               
                        } else {
-                               
-                               for (nframes_t n = 0; n < nframes; ++n) {
-                                       dst[n] += src[n];
-                               }      
-
+                                       Session::mix_buffers_no_gain(dst,src,nframes);
                        }
 #endif
 #ifdef CAN_INTERP
@@ -691,6 +697,12 @@ Multi2dPanner::factory (Panner& p)
        return new Multi2dPanner (p);
 }
 
+int
+Multi2dPanner::load (istream& in, string path, uint32_t& linecnt)
+{
+       return 0;
+}
+
 XMLNode&
 Multi2dPanner::get_state (void)
 {
@@ -748,6 +760,8 @@ Multi2dPanner::set_state (const XMLNode& node)
 Panner::Panner (string name, Session& s)
        : _session (s)
 {
+       set_name (name);
+
        _linked = false;
        _link_direction = SameDirection;
        _bypassed = false;
@@ -1029,8 +1043,7 @@ Panner::state (bool full)
        char buf[32];
 
        root->add_property (X_("linked"), (_linked ? "yes" : "no"));
-       snprintf (buf, sizeof (buf), "%d", _link_direction);
-       root->add_property (X_("link_direction"), buf);
+       root->add_property (X_("link_direction"), enum_2_string (_link_direction));
        root->add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
 
        /* add each output */
@@ -1074,8 +1087,8 @@ Panner::set_state (const XMLNode& node)
        }
 
        if ((prop = node.property (X_("link_direction"))) != 0) {
-               sscanf (prop->value().c_str(), "%d", &i);
-               set_link_direction ((LinkDirection) (i));
+               LinkDirection ld; /* here to provide type information */
+               set_link_direction (LinkDirection (string_2_enum (prop->value(), ld)));
        }
 
        nlist = node.children();
@@ -1136,6 +1149,16 @@ Panner::set_state (const XMLNode& node)
                }       
        }
 
+       /* don't try to do old-school automation loading if it wasn't marked as existing */
+
+       if ((prop = node.property (X_("automation")))) {
+
+               /* automation path is relative */
+               
+               automation_path = _session.automation_dir();
+               automation_path += prop->value ();
+       } 
+
        return 0;
 }
 
@@ -1295,3 +1318,84 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig)
                }
        }
 }
+
+/* old school automation handling */
+
+void
+Panner::set_name (string str)
+{
+       automation_path = _session.automation_dir();
+       automation_path += _session.snap_name();
+       automation_path += "-pan-";
+       automation_path += legalize_for_path (str);
+       automation_path += ".automation";
+}
+
+int
+Panner::load ()
+{
+       char line[128];
+       uint32_t linecnt = 0;
+       float version;
+       iterator sp;
+       LocaleGuard lg (X_("POSIX"));
+
+       if (automation_path.length() == 0) {
+               return 0;
+       }
+       
+       if (access (automation_path.c_str(), F_OK)) {
+               return 0;
+       }
+
+       ifstream in (automation_path.c_str());
+
+       if (!in) {
+               error << string_compose (_("cannot open pan automation file %1 (%2)"),
+                                 automation_path, strerror (errno))
+                     << endmsg;
+               return -1;
+       }
+
+       sp = begin();
+
+       while (in.getline (line, sizeof(line), '\n')) {
+
+               if (++linecnt == 1) {
+                       if (memcmp (line, X_("version"), 7) == 0) {
+                               if (sscanf (line, "version %f", &version) != 1) {
+                                       error << string_compose(_("badly formed version number in pan automation event file \"%1\""), automation_path) << endmsg;
+                                       return -1;
+                               }
+                       } else {
+                               error << string_compose(_("no version information in pan automation event file \"%1\" (first line = %2)"), 
+                                                automation_path, line) << endmsg;
+                               return -1;
+                       }
+
+                       continue;
+               }
+
+               if (strlen (line) == 0 || line[0] == '#') {
+                       continue;
+               }
+
+               if (strcmp (line, "begin") == 0) {
+                       
+                       if (sp == end()) {
+                               error << string_compose (_("too many panner states found in pan automation file %1"),
+                                                 automation_path)
+                                     << endmsg;
+                               return -1;
+                       }
+
+                       if ((*sp)->load (in, automation_path, linecnt)) {
+                               return -1;
+                       }
+                       
+                       ++sp;
+               }
+       }
+
+       return 0;
+}