fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / parameter_descriptor.cc
1 /*
2     Copyright (C) 2014 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "ardour/amp.h"
21 #include "ardour/dB.h"
22 #include "ardour/parameter_descriptor.h"
23 #include "ardour/rc_configuration.h"
24 #include "ardour/types.h"
25 #include "ardour/utils.h"
26
27 #include "pbd/i18n.h"
28
29 namespace ARDOUR {
30
31 ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
32         : Evoral::ParameterDescriptor()
33         , key((uint32_t)-1)
34         , datatype(Variant::NOTHING)
35         , type((AutomationType)parameter.type())
36         , unit(NONE)
37         , step(0)
38         , smallstep(0)
39         , largestep(0)
40         , integer_step(parameter.type() >= MidiCCAutomation &&
41                        parameter.type() <= MidiChannelPressureAutomation)
42         , logarithmic(false)
43         , sr_dependent(false)
44         , min_unbound(0)
45         , max_unbound(0)
46         , enumeration(false)
47 {
48         ScalePoints sp;
49
50         switch((AutomationType)parameter.type()) {
51         case GainAutomation:
52                 upper  = Config->get_max_gain();
53                 normal = 1.0f;
54                 break;
55         case BusSendLevel:
56                 upper = Config->get_max_gain ();
57                 normal = 1.0f;
58                 break;
59         case BusSendEnable:
60                 normal = 1.0f;
61                 toggled = true;
62                 break;
63         case TrimAutomation:
64                 upper  = 10; // +20dB
65                 lower  = .1; // -20dB
66                 normal = 1.0f;
67                 break;
68         case PanAzimuthAutomation:
69                 normal = 0.5f; // there really is no _normal but this works for stereo, sort of
70                 upper  = 1.0f;
71                 break;
72         case PanWidthAutomation:
73                 lower  = -1.0;
74                 upper  = 1.0;
75                 normal = 0.0f;
76                 break;
77         case RecEnableAutomation:
78         case RecSafeAutomation:
79                 lower  = 0.0;
80                 upper  = 1.0;
81                 toggled = true;
82                 break;
83         case PluginAutomation:
84         case FadeInAutomation:
85         case FadeOutAutomation:
86         case EnvelopeAutomation:
87                 upper  = 2.0f;
88                 normal = 1.0f;
89                 break;
90         case SoloAutomation:
91         case MuteAutomation:
92                 upper  = 1.0f;
93                 normal = 0.0f;
94                 toggled = true;
95                 break;
96         case MidiCCAutomation:
97         case MidiPgmChangeAutomation:
98         case MidiChannelPressureAutomation:
99                 lower  = 0.0;
100                 normal = 0.0;
101                 upper  = 127.0;
102                 break;
103         case MidiPitchBenderAutomation:
104                 lower  = 0.0;
105                 normal = 8192.0;
106                 upper  = 16383.0;
107                 break;
108         case PhaseAutomation:
109                 toggled = true;
110                 break;
111         case MonitoringAutomation:
112                 enumeration = true;
113                 integer_step = true;
114                 lower = MonitorAuto;
115                 upper = MonitorDisk; /* XXX bump when we add MonitorCue */
116                 break;
117         case SoloIsolateAutomation:
118                 toggled = true;
119                 break;
120         case SoloSafeAutomation:
121                 toggled = true;
122                 break;
123         default:
124                 break;
125         }
126
127         update_steps();
128 }
129
130 ParameterDescriptor::ParameterDescriptor()
131         : Evoral::ParameterDescriptor()
132         , key((uint32_t)-1)
133         , datatype(Variant::NOTHING)
134         , type(NullAutomation)
135         , unit(NONE)
136         , step(0)
137         , smallstep(0)
138         , largestep(0)
139         , integer_step(false)
140         , logarithmic(false)
141         , sr_dependent(false)
142         , min_unbound(0)
143         , max_unbound(0)
144         , enumeration(false)
145 {}
146
147 void
148 ParameterDescriptor::update_steps()
149 {
150         if (unit == ParameterDescriptor::MIDI_NOTE) {
151                 step      = smallstep = 1;  // semitone
152                 largestep = 12;             // octave
153         } else if (type == GainAutomation || type == TrimAutomation) {
154                 /* dB_coeff_step gives a step normalized for [0, max_gain].  This is
155                    like "slider position", so we convert from "slider position" to gain
156                    to have the correct unit here. */
157                 largestep = slider_position_to_gain(dB_coeff_step(upper));
158                 step      = slider_position_to_gain(largestep / 10.0);
159                 smallstep = step;
160         } else {
161                 /* note that LV2Plugin::get_parameter_descriptor ()
162                  * overrides this is lv2:rangeStep is set for a port.
163                  */
164                 const float delta = upper - lower;
165
166                 /* 30 happens to be the total number of steps for a fader with default
167                    max gain of 2.0 (6 dB), so we use 30 here too for consistency. */
168                 step      = smallstep = (delta / 300.0f);
169                 largestep = (delta / 30.0f);
170
171                 if (logarithmic) {
172                         /* Steps are linear, but we map them with pow like values (in
173                            internal_to_interface).  Thus, they are applied exponentially,
174                            which means too few steps.  So, divide to get roughly the
175                            desired number of steps (30).  This is not mathematically
176                            precise but seems to be about right for the controls I tried.
177                            If you're reading this, you've probably found a case where that
178                            isn't true, and somebody needs to sit down with a piece of paper
179                            and actually do the math. */
180                         smallstep = smallstep / logf(30.0f);
181                         step      = step      / logf(30.0f);
182                         largestep = largestep / logf(30.0f);
183                 } else if (integer_step) {
184                         smallstep = 1.0;
185                         step      = std::max(1.f, rintf (step));
186                         largestep = std::max(1.f, rintf (largestep));
187                 }
188         }
189 }
190
191 std::string
192 ParameterDescriptor::midi_note_name (const uint8_t b)
193 {
194         char buf[8];
195         if (b > 127) {
196                 snprintf(buf, sizeof(buf), "%d", b);
197                 return buf;
198         }
199
200         static const char* notes[] = {
201                 S_("Note|C"),
202                 S_("Note|C#"),
203                 S_("Note|D"),
204                 S_("Note|D#"),
205                 S_("Note|E"),
206                 S_("Note|F"),
207                 S_("Note|F#"),
208                 S_("Note|G"),
209                 S_("Note|G#"),
210                 S_("Note|A"),
211                 S_("Note|A#"),
212                 S_("Note|B")
213         };
214
215         /* MIDI note 0 is in octave -1 (in scientific pitch notation) */
216         const int octave = b / 12 - 1;
217         snprintf (buf, sizeof (buf), "%s%d", notes[b % 12], octave);
218         return buf;
219 }
220
221 } // namespace ARDOUR