Be more tolerant to missing values or errors in io_config()
[ardour.git] / libs / ardour / parameter_descriptor.cc
index 36f718313428861b48c7fa35775f24f283b41bb7..bf0c9b7af153fc18c79c90371a1135100e7c7a3f 100644 (file)
 */
 
 #include "ardour/amp.h"
+#include "ardour/dB.h"
 #include "ardour/parameter_descriptor.h"
+#include "ardour/rc_configuration.h"
 #include "ardour/types.h"
+#include "ardour/utils.h"
+
+#include "pbd/i18n.h"
 
 namespace ARDOUR {
 
@@ -27,6 +32,7 @@ ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
        : Evoral::ParameterDescriptor()
        , key((uint32_t)-1)
        , datatype(Variant::NOTHING)
+       , type((AutomationType)parameter.type())
        , unit(NONE)
        , step(0)
        , smallstep(0)
@@ -39,13 +45,24 @@ ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
        , max_unbound(0)
        , enumeration(false)
 {
-       if (parameter.type() == GainAutomation) {
-               unit = DB;
-       }
+       ScalePoints sp;
 
        switch((AutomationType)parameter.type()) {
        case GainAutomation:
-               upper  = Amp::max_gain_coefficient;
+               upper  = Config->get_max_gain();
+               normal = 1.0f;
+               break;
+       case BusSendLevel:
+               upper = Config->get_max_gain ();
+               normal = 1.0f;
+               break;
+       case BusSendEnable:
+               normal = 1.0f;
+               toggled = true;
+               break;
+       case TrimAutomation:
+               upper  = 10; // +20dB
+               lower  = .1; // -20dB
                normal = 1.0f;
                break;
        case PanAzimuthAutomation:
@@ -58,6 +75,7 @@ ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
                normal = 0.0f;
                break;
        case RecEnableAutomation:
+       case RecSafeAutomation:
                lower  = 0.0;
                upper  = 1.0;
                toggled = true;
@@ -87,6 +105,21 @@ ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
                normal = 8192.0;
                upper  = 16383.0;
                break;
+       case PhaseAutomation:
+               toggled = true;
+               break;
+       case MonitoringAutomation:
+               enumeration = true;
+               integer_step = true;
+               lower = MonitorAuto;
+               upper = MonitorDisk; /* XXX bump when we add MonitorCue */
+               break;
+       case SoloIsolateAutomation:
+               toggled = true;
+               break;
+       case SoloSafeAutomation:
+               toggled = true;
+               break;
        default:
                break;
        }
@@ -98,6 +131,7 @@ ParameterDescriptor::ParameterDescriptor()
        : Evoral::ParameterDescriptor()
        , key((uint32_t)-1)
        , datatype(Variant::NOTHING)
+       , type(NullAutomation)
        , unit(NONE)
        , step(0)
        , smallstep(0)
@@ -116,22 +150,72 @@ ParameterDescriptor::update_steps()
        if (unit == ParameterDescriptor::MIDI_NOTE) {
                step      = smallstep = 1;  // semitone
                largestep = 12;             // octave
-       } else if (integer_step) {
+       } else if (type == GainAutomation || type == TrimAutomation) {
+               /* dB_coeff_step gives a step normalized for [0, max_gain].  This is
+                  like "slider position", so we convert from "slider position" to gain
+                  to have the correct unit here. */
+               largestep = slider_position_to_gain(dB_coeff_step(upper));
+               step      = slider_position_to_gain(largestep / 10.0);
+               smallstep = step;
+       } else {
+               /* note that LV2Plugin::get_parameter_descriptor ()
+                * overrides this is lv2:rangeStep is set for a port.
+                */
                const float delta = upper - lower;
 
-               smallstep = delta / 10000.0f;
-               step      = delta / 1000.0f;
-               largestep = delta / 40.0f;
+               /* 30 happens to be the total number of steps for a fader with default
+                  max gain of 2.0 (6 dB), so we use 30 here too for consistency. */
+               step      = smallstep = (delta / 300.0f);
+               largestep = (delta / 30.0f);
 
-               smallstep = std::max(1.0, rint(smallstep));
-               step      = std::max(1.0, rint(step));
-               largestep = std::max(1.0, rint(largestep));
+               if (logarithmic) {
+                       /* Steps are linear, but we map them with pow like values (in
+                          internal_to_interface).  Thus, they are applied exponentially,
+                          which means too few steps.  So, divide to get roughly the
+                          desired number of steps (30).  This is not mathematically
+                          precise but seems to be about right for the controls I tried.
+                          If you're reading this, you've probably found a case where that
+                          isn't true, and somebody needs to sit down with a piece of paper
+                          and actually do the math. */
+                       smallstep = smallstep / logf(30.0f);
+                       step      = step      / logf(30.0f);
+                       largestep = largestep / logf(30.0f);
+               } else if (integer_step) {
+                       smallstep = 1.0;
+                       step      = std::max(1.f, rintf (step));
+                       largestep = std::max(1.f, rintf (largestep));
+               }
        }
-       /* else: leave all others as default '0'
-        * in that case the UI (eg. AutomationController::create)
-        * uses internal_to_interface() to map the value
-        * to an appropriate interface range
-        */
+}
+
+std::string
+ParameterDescriptor::midi_note_name (const uint8_t b)
+{
+       char buf[8];
+       if (b > 127) {
+               snprintf(buf, sizeof(buf), "%d", b);
+               return buf;
+       }
+
+       static const char* notes[] = {
+               S_("Note|C"),
+               S_("Note|C#"),
+               S_("Note|D"),
+               S_("Note|D#"),
+               S_("Note|E"),
+               S_("Note|F"),
+               S_("Note|F#"),
+               S_("Note|G"),
+               S_("Note|G#"),
+               S_("Note|A"),
+               S_("Note|A#"),
+               S_("Note|B")
+       };
+
+       /* MIDI note 0 is in octave -1 (in scientific pitch notation) */
+       const int octave = b / 12 - 1;
+       snprintf (buf, sizeof (buf), "%s%d", notes[b % 12], octave);
+       return buf;
 }
 
 } // namespace ARDOUR