fix verbose plugin scan
[ardour.git] / gtk2_ardour / ardour_knob.cc
index 21017a0e1a850b827477db7ace185c04758edc64..17fbff2f7ee11de3205e291078646b5c627ea7fa 100644 (file)
@@ -37,6 +37,7 @@
 #include "ardour_knob.h"
 #include "ardour_ui.h"
 #include "global_signals.h"
+#include "timers.h"
 
 #include "canvas/colors.h"
 #include "canvas/utils.h"
@@ -54,18 +55,21 @@ using namespace std;
 
 ArdourKnob::Element ArdourKnob::default_elements = ArdourKnob::Element (ArdourKnob::Arc);
 
-ArdourKnob::ArdourKnob (Element e, bool arc_to_zero)
+ArdourKnob::ArdourKnob (Element e, Flags flags)
        : _elements (e)
        , _hovering (false)
        , _grabbed_x (0)
        , _grabbed_y (0)
        , _val (0)
-       , _zero (0)
+       , _normal (0)
        , _dead_zone_delta (0)
-       , _arc_to_zero (arc_to_zero)
+       , _flags (flags)
        , _tooltip (this)
 {
        ARDOUR_UI_UTILS::ColorsChanged.connect (sigc::mem_fun (*this, &ArdourKnob::color_handler));
+
+       // watch automation :(
+       Timers::rapid_connect (sigc::mem_fun (*this, &ArdourKnob::controllable_changed));
 }
 
 ArdourKnob::~ArdourKnob()
@@ -86,8 +90,13 @@ ArdourKnob::render (cairo_t* cr, cairo_rectangle_t *)
        const float start_angle = ((180 - 65) * G_PI) / 180;
        const float end_angle = ((360 + 65) * G_PI) / 180;
 
+       float zero = 0;
+       if (_flags & ArcToZero) {
+               zero = _normal;
+       }
+
        const float value_angle = start_angle + (_val * (end_angle - start_angle));
-       const float zero_angle = start_angle + (_zero * (end_angle - start_angle));
+       const float zero_angle = start_angle + (zero * (end_angle - start_angle));
        
        float value_x = cos (value_angle);
        float value_y = sin (value_angle);
@@ -130,7 +139,7 @@ ArdourKnob::render (cairo_t* cr, cairo_rectangle_t *)
                ArdourCanvas::color_to_rgba( arc_end_color, red_end, green_end, blue_end, unused );
 
                //vary the arc color over the travel of the knob
-               float intensity = fabsf (_val - _zero) / std::max(_zero, (1.f - _zero));
+               float intensity = fabsf (_val - zero) / std::max(zero, (1.f - zero));
                const float intensity_inv = 1.0 - intensity;
                float r = intensity_inv * red_end   + intensity * red_start;
                float g = intensity_inv * green_end + intensity * green_start;
@@ -323,7 +332,7 @@ ArdourKnob::on_motion_notify_event (GdkEventMotion *ev)
 
        //scale the adjustment based on keyboard modifiers & GUI size
        const float ui_scale = max (1.f, ARDOUR_UI::ui_scale);
-       float scale = 0.0025 * ui_scale;
+       float scale = 0.0025 / ui_scale;
 
        if (ev->state & Keyboard::GainFineScaleModifier) {
                if (ev->state & Keyboard::GainExtraFineScaleModifier) {
@@ -343,32 +352,34 @@ ArdourKnob::on_motion_notify_event (GdkEventMotion *ev)
        _grabbed_y = ev->y;
        float val = c->get_interface();
 
-       const float px_deadzone = 42.f * ui_scale;
-
-       if ((val - _zero) * (val - _zero + delta * scale) < 0) {
-               /* zero transition */
-               const int tozero = (_zero - val) * scale;
-               int remain = delta - tozero;
-               if (abs (remain) > px_deadzone) {
-                       /* slow down zero transitions */
-                       remain += (remain > 0) ? px_deadzone * -.5 : px_deadzone * .5;
-                       delta = tozero + remain;
-                       _dead_zone_delta = 0;
-               } else {
-                       c->set_interface(_zero);
-                       val = _zero;
-                       _dead_zone_delta = remain / px_deadzone;
+       if (_flags & Detent) {
+               const float px_deadzone = 42.f * ui_scale;
+
+               if ((val - _normal) * (val - _normal + delta * scale) < 0) {
+                       /* detent */
+                       const int tozero = (_normal - val) * scale;
+                       int remain = delta - tozero;
+                       if (abs (remain) > px_deadzone) {
+                               /* slow down passing the default value */
+                               remain += (remain > 0) ? px_deadzone * -.5 : px_deadzone * .5;
+                               delta = tozero + remain;
+                               _dead_zone_delta = 0;
+                       } else {
+                               c->set_value (c->normal());
+                               _dead_zone_delta = remain / px_deadzone;
+                               return true;
+                       }
+               }
+
+               if (fabsf (rintf((val - _normal) / scale) + _dead_zone_delta) < 1) {
+                       c->set_value (c->normal());
+                       _dead_zone_delta += delta / px_deadzone;
                        return true;
                }
-       }
 
-       if (fabsf (rintf((val - _zero) / scale) + _dead_zone_delta) < 1) {
-               c->set_interface(_zero);
-               _dead_zone_delta += delta / px_deadzone;
-               return true;
+               _dead_zone_delta = 0;
        }
 
-       _dead_zone_delta = 0;
        val += delta * scale;
        c->set_interface(val);
 
@@ -443,7 +454,7 @@ ArdourKnob::on_size_allocate (Allocation& alloc)
 void
 ArdourKnob::set_controllable (boost::shared_ptr<Controllable> c)
 {
-    watch_connection.disconnect ();  //stop watching the old controllable
+       watch_connection.disconnect ();  //stop watching the old controllable
 
        if (!c) return;
 
@@ -451,11 +462,7 @@ ArdourKnob::set_controllable (boost::shared_ptr<Controllable> c)
 
        c->Changed.connect (watch_connection, invalidator(*this), boost::bind (&ArdourKnob::controllable_changed, this), gui_context());
 
-       if (_arc_to_zero) {
-               _zero = c->internal_to_interface(c->normal());
-       } else {
-               _zero = 0;
-       }
+       _normal = c->internal_to_interface(c->normal());
 
        controllable_changed();
 }
@@ -464,10 +471,16 @@ void
 ArdourKnob::controllable_changed ()
 {
        boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable();
+       if (!c) return;
 
-       _val = c->get_interface();  //% of knob travel
-       _val = min( max(0.0f, _val), 1.0f);  //range check
+       float val = c->get_interface();
+       val = min( max(0.0f, val), 1.0f); // clamp
+
+       if (val == _val) {
+               return;
+       }
 
+       _val = val;
        if (!_tooltip_prefix.empty()) {
                _tooltip.set_tip (_tooltip_prefix + c->get_user_string());
        }
@@ -550,7 +563,7 @@ ArdourKnob::add_elements (Element e)
 
 
 KnobPersistentTooltip::KnobPersistentTooltip (Gtk::Widget* w)
-       : PersistentTooltip (w, 3)
+       : PersistentTooltip (w, true, 3)
        , _dragging (false)
 {
 }