fix midi buffer erase()
[ardour.git] / libs / panners / 2in2out / panner_2in2out.cc
index df859a1eff67e7967e32886e07891b4b185e666d..f18dd94f45a6ef706602f301ff27443fac39cb54 100644 (file)
@@ -49,6 +49,7 @@
 #include "ardour/runtime_functions.h"
 #include "ardour/session.h"
 #include "ardour/utils.h"
+#include "ardour/mix.h"
 
 #include "panner_2in2out.h"
 
@@ -62,11 +63,14 @@ using namespace PBD;
 
 static PanPluginDescriptor _descriptor = {
         "Equal Power Stereo",
+        "http://ardour.org/plugin/panner_2in2out",
+        "http://ardour.org/plugin/panner_2in2out#ui",
         2, 2,
+        10000,
         Panner2in2out::factory
 };
 
-extern "C" { PanPluginDescriptor* panner_descriptor () { return &_descriptor; } }
+extern "C" ARDOURPANNER_API PanPluginDescriptor* panner_descriptor () { return &_descriptor; }
 
 Panner2in2out::Panner2in2out (boost::shared_ptr<Pannable> p)
        : Panner (p)
@@ -74,7 +78,14 @@ Panner2in2out::Panner2in2out (boost::shared_ptr<Pannable> p)
         if (!_pannable->has_state()) {
                 _pannable->pan_azimuth_control->set_value (0.5);
                 _pannable->pan_width_control->set_value (1.0);
-        } 
+        }
+
+        double const w = width();
+        double const wrange = min (position(), (1 - position())) * 2;
+        if (fabs(w) > wrange) {
+                set_width(w > 0 ? wrange : -wrange);
+        }
+
         
         update ();
         
@@ -122,9 +133,22 @@ Panner2in2out::set_width (double p)
         }
 }
 
+void
+Panner2in2out::thaw ()
+{
+       Panner::thaw ();
+       if (_frozen == 0) {
+               update ();
+       }
+}
+
 void
 Panner2in2out::update ()
 {
+       if (_frozen) {
+               return;
+       }
+
         /* it would be very nice to split this out into a virtual function
            that can be accessed from BaseStereoPanner and used in do_distribute_automated().
            
@@ -138,8 +162,13 @@ Panner2in2out::update ()
         */
         
         float pos[2];
-        double width = _pannable->pan_width_control->get_value();
-        const double direction_as_lr_fract = _pannable->pan_azimuth_control->get_value();
+        double width = this->width ();
+        const double direction_as_lr_fract = position ();
+
+        double const wrange = min (position(), (1 - position())) * 2;
+        if (fabs(width) > wrange) {
+                width = (width  > 0 ? wrange : -wrange);
+        }
 
         if (width < 0.0) {
                 width = -width;
@@ -175,17 +204,30 @@ Panner2in2out::update ()
 bool
 Panner2in2out::clamp_position (double& p)
 {
-        double w = _pannable->pan_width_control->get_value();
+        double w = width ();
         return clamp_stereo_pan (p, w);
 }
 
 bool
 Panner2in2out::clamp_width (double& w)
 {
-        double p = _pannable->pan_azimuth_control->get_value();
+        double p = position ();
         return clamp_stereo_pan (p, w);
 }
 
+pair<double, double>
+Panner2in2out::position_range () const
+{
+       return make_pair (0.5 - (1 - width()) / 2, 0.5 + (1 - width()) / 2);
+}
+
+pair<double, double>
+Panner2in2out::width_range () const
+{
+       double const w = min (position(), (1 - position())) * 2;
+       return make_pair (-w, w);
+}
+
 bool
 Panner2in2out::clamp_stereo_pan (double& direction_as_lr_fract, double& width)
 {
@@ -269,7 +311,8 @@ Panner2in2out::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gai
                        if (pan != 0.0f) {
 
                                /* pan is 1 but also not 0, so we must do it "properly" */
-
+                               
+                               //obufs.get_audio(1).read_from (srcbuf, nframes);
                                mix_buffers_with_gain(dst,src,nframes,pan);
 
                                /* mark that we wrote into the buffer */
@@ -328,7 +371,8 @@ Panner2in2out::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gai
                                /* pan is not 1 but also not 0, so we must do it "properly" */
                                
                                mix_buffers_with_gain(dst,src,nframes,pan);
-
+                               // obufs.get_audio(1).read_from (srcbuf, nframes);
+                               
                                /* XXX it would be nice to mark the buffer as written to */
                        }
 
@@ -389,6 +433,8 @@ Panner2in2out::distribute_one_automated (AudioBuffer& srcbuf, BufferSet& obufs,
                         panR = position[n] + (width[n]/2.0f); // center - width/2
                 }
 
+                panR = max(0.f, min(1.f, panR));
+
                 const float panL = 1 - panR;
 
                 /* note that are overwriting buffers, but its OK
@@ -432,27 +478,15 @@ Panner2in2out::factory (boost::shared_ptr<Pannable> p, boost::shared_ptr<Speaker
 }
 
 XMLNode&
-Panner2in2out::get_state (void)
-{
-       return state (true);
-}
-
-XMLNode&
-Panner2in2out::state (bool /*full_state*/)
+Panner2in2out::get_state ()
 {
        XMLNode& root (Panner::get_state ());
+       root.add_property (X_("uri"), _descriptor.panner_uri);
+       /* this is needed to allow new sessions to load with old Ardour: */
        root.add_property (X_("type"), _descriptor.name);
        return root;
 }
 
-int
-Panner2in2out::set_state (const XMLNode& node, int version)
-{
-       LocaleGuard lg (X_("POSIX"));
-       Panner::set_state (node, version);
-       return 0;
-}
-
 std::set<Evoral::Parameter> 
 Panner2in2out::what_can_be_automated() const
 {
@@ -489,15 +523,27 @@ Panner2in2out::value_as_string (boost::shared_ptr<AutomationControl> ac) const
                    
                    This is pretty wierd, but its the way audio engineers expect it. Just remember that
                    the center of the USA isn't Kansas, its (50LA, 50NY) and it will all make sense.
+                
+                  This is designed to be as narrow as possible. Dedicated
+                  panner GUIs can do their own version of this if they need
+                  something less compact.
                 */
                 
-                return string_compose (_("L:%1 R:%2"), (int) rint (100.0 * (1.0 - val)),
+                return string_compose (_("L%1R%2"), (int) rint (100.0 * (1.0 - val)),
                                        (int) rint (100.0 * val));
-                
+
         case PanWidthAutomation:
                 return string_compose (_("Width: %1%%"), (int) floor (100.0 * val));
                 
         default:
-                return _pannable->value_as_string (ac);
+                return _("unused");
         }
 }
+
+void
+Panner2in2out::reset ()
+{
+       set_position (0.5);
+       set_width (1);
+       update ();
+}