fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / monitor_processor.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "pbd/convert.h"
21 #include "pbd/error.h"
22 #include "pbd/locale_guard.h"
23 #include "pbd/xml++.h"
24
25 #include "ardour/amp.h"
26 #include "ardour/debug.h"
27 #include "ardour/audio_buffer.h"
28 #include "ardour/monitor_processor.h"
29 #include "ardour/session.h"
30
31 #include "pbd/i18n.h"
32
33 using namespace ARDOUR;
34 using namespace PBD;
35 using namespace std;
36
37 /* specialize for bool because of set_value() semantics */
38
39 namespace ARDOUR {
40         template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
41                 bool newval = fabs (v) >= 0.5;
42                 if (newval != _value) {
43                         _value = newval;
44                         Changed (true, gcd); /* EMIT SIGNAL */
45                 }
46         }
47 }
48
49 MonitorProcessor::MonitorProcessor (Session& s)
50         : Processor (s, X_("MonitorOut"))
51         , solo_cnt (0)
52         , _monitor_active (false)
53
54         , _dim_all_ptr (new MPControl<bool> (false, _("monitor dim"), Controllable::Toggle))
55         , _cut_all_ptr (new MPControl<bool> (false, _("monitor cut"), Controllable::Toggle))
56         , _mono_ptr (new MPControl<bool> (false, _("monitor mono"), Controllable::Toggle))
57         , _dim_level_ptr (new MPControl<volatile gain_t>
58                           /* default is -12dB, range is -20dB to 0dB */
59                           (dB_to_coefficient(-12.0), _("monitor dim level"), Controllable::Flag (0),
60                            dB_to_coefficient(-20.0), dB_to_coefficient (0.0)))
61         , _solo_boost_level_ptr (new MPControl<volatile gain_t>
62                                  /* default is 0dB, range is 0dB to +20dB */
63                                  (dB_to_coefficient(0.0), _("monitor solo boost level"), Controllable::Flag (0),
64                                   dB_to_coefficient(0.0), dB_to_coefficient(10.0)))
65         , _dim_all_control (_dim_all_ptr)
66         , _cut_all_control (_cut_all_ptr)
67         , _mono_control (_mono_ptr)
68         , _dim_level_control (_dim_level_ptr)
69         , _solo_boost_level_control (_solo_boost_level_ptr)
70
71         , _dim_all (*_dim_all_ptr)
72         , _cut_all (*_cut_all_ptr)
73         , _mono (*_mono_ptr)
74         , _dim_level (*_dim_level_ptr)
75         , _solo_boost_level (*_solo_boost_level_ptr)
76
77 {
78 }
79
80 MonitorProcessor::~MonitorProcessor ()
81 {
82         allocate_channels (0);
83 }
84
85 void
86 MonitorProcessor::allocate_channels (uint32_t size)
87 {
88         while (_channels.size() > size) {
89                 if (_channels.back()->soloed) {
90                         if (solo_cnt > 0) {
91                                 --solo_cnt;
92                         }
93                 }
94                 ChannelRecord* cr = _channels.back();
95                 _channels.pop_back();
96                 delete cr;
97         }
98
99         uint32_t n = _channels.size() + 1;
100
101         while (_channels.size() < size) {
102                 _channels.push_back (new ChannelRecord (n));
103         }
104 }
105
106 int
107 MonitorProcessor::set_state (const XMLNode& node, int version)
108 {
109         int ret = Processor::set_state (node, version);
110
111         if (ret != 0) {
112                 return ret;
113         }
114
115         XMLProperty const * prop;
116
117         if ((prop = node.property (X_("type"))) == 0) {
118                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings have no type information"))
119                       << endmsg;
120                 return -1;
121         }
122
123         if (prop->value() != X_("monitor")) {
124                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor given unknown XML settings"))
125                       << endmsg;
126                 return -1;
127         }
128
129         if ((prop = node.property (X_("channels"))) == 0) {
130                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings are missing a channel cnt"))
131                       << endmsg;
132                 return -1;
133         }
134
135         allocate_channels (atoi (prop->value()));
136
137         if ((prop = node.property (X_("dim-level"))) != 0) {
138                 gain_t val = atof (prop->value());
139                 _dim_level = val;
140         }
141
142         if ((prop = node.property (X_("solo-boost-level"))) != 0) {
143                 gain_t val = atof (prop->value());
144                 _solo_boost_level = val;
145         }
146
147         if ((prop = node.property (X_("cut-all"))) != 0) {
148                 bool val = string_is_affirmative (prop->value());
149                 _cut_all = val;
150         }
151         if ((prop = node.property (X_("dim-all"))) != 0) {
152                 bool val = string_is_affirmative (prop->value());
153                 _dim_all = val;
154         }
155         if ((prop = node.property (X_("mono"))) != 0) {
156                 bool val = string_is_affirmative (prop->value());
157                 _mono = val;
158         }
159
160         for (XMLNodeList::const_iterator i = node.children().begin(); i != node.children().end(); ++i) {
161
162                 if ((*i)->name() == X_("Channel")) {
163                         if ((prop = (*i)->property (X_("id"))) == 0) {
164                                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings are missing an ID"))
165                                       << endmsg;
166                                 return -1;
167                         }
168
169                         uint32_t chn;
170
171                         if (sscanf (prop->value().c_str(), "%u", &chn) != 1) {
172                                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings has an unreadable channel ID"))
173                                       << endmsg;
174                                 return -1;
175                         }
176
177                         if (chn >= _channels.size()) {
178                                 error << string_compose (X_("programming error: %1"), X_("MonitorProcessor XML settings has an illegal channel count"))
179                                       << endmsg;
180                                 return -1;
181                         }
182                         ChannelRecord& cr (*_channels[chn]);
183
184                         if ((prop = (*i)->property ("cut")) != 0) {
185                                 if (string_is_affirmative (prop->value())){
186                                         cr.cut = GAIN_COEFF_ZERO;
187                                 } else {
188                                         cr.cut = GAIN_COEFF_UNITY;
189                                 }
190                         }
191
192                         if ((prop = (*i)->property ("dim")) != 0) {
193                                 bool val = string_is_affirmative (prop->value());
194                                 cr.dim = val;
195                         }
196
197                         if ((prop = (*i)->property ("invert")) != 0) {
198                                 if (string_is_affirmative (prop->value())) {
199                                         cr.polarity = -1.0f;
200                                 } else {
201                                         cr.polarity = 1.0f;
202                                 }
203                         }
204
205                         if ((prop = (*i)->property ("solo")) != 0) {
206                                 bool val = string_is_affirmative (prop->value());
207                                 cr.soloed = val;
208                         }
209                 }
210         }
211
212         /* reset solo cnt */
213
214         solo_cnt = 0;
215
216         for (vector<ChannelRecord*>::const_iterator x = _channels.begin(); x != _channels.end(); ++x) {
217                 if ((*x)->soloed) {
218                         solo_cnt++;
219                 }
220         }
221
222         update_monitor_state ();
223         return 0;
224 }
225
226 XMLNode&
227 MonitorProcessor::state (bool full)
228 {
229         LocaleGuard lg;
230         XMLNode& node (Processor::state (full));
231         char buf[64];
232
233         /* this replaces any existing "type" property */
234
235         node.add_property (X_("type"), X_("monitor"));
236
237         snprintf (buf, sizeof(buf), "%.12g", _dim_level.val());
238         node.add_property (X_("dim-level"), buf);
239
240         snprintf (buf, sizeof(buf), "%.12g", _solo_boost_level.val());
241         node.add_property (X_("solo-boost-level"), buf);
242
243         node.add_property (X_("cut-all"), (_cut_all ? "yes" : "no"));
244         node.add_property (X_("dim-all"), (_dim_all ? "yes" : "no"));
245         node.add_property (X_("mono"), (_mono ? "yes" : "no"));
246
247         uint32_t limit = _channels.size();
248
249         snprintf (buf, sizeof (buf), "%u", limit);
250         node.add_property (X_("channels"), buf);
251
252         XMLNode* chn_node;
253         uint32_t chn = 0;
254
255         for (vector<ChannelRecord*>::const_iterator x = _channels.begin(); x != _channels.end(); ++x, ++chn) {
256                 chn_node = new XMLNode (X_("Channel"));
257
258                 snprintf (buf, sizeof (buf), "%u", chn);
259                 chn_node->add_property ("id", buf);
260
261                 chn_node->add_property (X_("cut"), (*x)->cut == GAIN_COEFF_UNITY ? "no" : "yes");
262                 chn_node->add_property (X_("invert"), (*x)->polarity == GAIN_COEFF_UNITY ? "no" : "yes");
263                 chn_node->add_property (X_("dim"), (*x)->dim ? "yes" : "no");
264                 chn_node->add_property (X_("solo"), (*x)->soloed ? "yes" : "no");
265
266                 node.add_child_nocopy (*chn_node);
267         }
268
269         return node;
270 }
271
272 void
273 MonitorProcessor::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, double /*speed*/, pframes_t nframes, bool /*result_required*/)
274 {
275         uint32_t chn = 0;
276         gain_t target_gain;
277         gain_t dim_level_this_time = _dim_level;
278         gain_t global_cut = (_cut_all ? GAIN_COEFF_ZERO : GAIN_COEFF_UNITY);
279         gain_t global_dim = (_dim_all ? dim_level_this_time : GAIN_COEFF_UNITY);
280         gain_t solo_boost;
281
282         if (_session.listening() || _session.soloing()) {
283                 solo_boost = _solo_boost_level;
284         } else {
285                 solo_boost = GAIN_COEFF_UNITY;
286         }
287
288         for (BufferSet::audio_iterator b = bufs.audio_begin(); b != bufs.audio_end(); ++b) {
289
290                 /* don't double-scale by both track dim and global dim coefficients */
291
292                 gain_t dim_level = (global_dim == GAIN_COEFF_UNITY ? (_channels[chn]->dim ? dim_level_this_time : GAIN_COEFF_UNITY) : GAIN_COEFF_UNITY);
293
294                 if (_channels[chn]->soloed) {
295                         target_gain = _channels[chn]->polarity * _channels[chn]->cut * dim_level * global_cut * global_dim * solo_boost;
296                 } else {
297                         if (solo_cnt == 0) {
298                                 target_gain = _channels[chn]->polarity * _channels[chn]->cut * dim_level * global_cut * global_dim * solo_boost;
299                         } else {
300                                 target_gain = GAIN_COEFF_ZERO;
301                         }
302                 }
303
304                 if (target_gain != _channels[chn]->current_gain || target_gain != GAIN_COEFF_UNITY) {
305
306                         _channels[chn]->current_gain = Amp::apply_gain (*b, _session.nominal_frame_rate(), nframes, _channels[chn]->current_gain, target_gain);
307                 }
308
309                 ++chn;
310         }
311
312         if (_mono) {
313                 DEBUG_TRACE (DEBUG::Monitor, "mono-izing\n");
314
315                 /* chn is now the number of channels, use as a scaling factor when mixing
316                  */
317                 gain_t scale = 1.f / (float)chn;
318                 BufferSet::audio_iterator b = bufs.audio_begin();
319                 AudioBuffer& ab (*b);
320                 Sample* buf = ab.data();
321
322                 /* scale the first channel */
323
324                 for (pframes_t n = 0; n < nframes; ++n) {
325                         buf[n] *= scale;
326                 }
327
328                 /* add every other channel into the first channel's buffer */
329
330                 ++b;
331                 for (; b != bufs.audio_end(); ++b) {
332                         AudioBuffer& ob (*b);
333                         Sample* obuf = ob.data ();
334                         for (pframes_t n = 0; n < nframes; ++n) {
335                                 buf[n] += obuf[n] * scale;
336                         }
337                 }
338
339                 /* copy the first channel to every other channel's buffer */
340
341                 b = bufs.audio_begin();
342                 ++b;
343                 for (; b != bufs.audio_end(); ++b) {
344                         AudioBuffer& ob (*b);
345                         Sample* obuf = ob.data ();
346                         memcpy (obuf, buf, sizeof (Sample) * nframes);
347                 }
348         }
349 }
350
351 bool
352 MonitorProcessor::configure_io (ChanCount in, ChanCount out)
353 {
354         allocate_channels (in.n_audio());
355         return Processor::configure_io (in, out);
356 }
357
358 bool
359 MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
360 {
361         out = in;
362         return true;
363 }
364
365 void
366 MonitorProcessor::set_polarity (uint32_t chn, bool invert)
367 {
368         if (invert) {
369                 _channels[chn]->polarity = -1.0f;
370         } else {
371                 _channels[chn]->polarity = 1.0f;
372         }
373         update_monitor_state ();
374 }
375
376 void
377 MonitorProcessor::set_dim (uint32_t chn, bool yn)
378 {
379         _channels[chn]->dim = yn;
380         update_monitor_state ();
381 }
382
383 void
384 MonitorProcessor::set_cut (uint32_t chn, bool yn)
385 {
386         if (yn) {
387                 _channels[chn]->cut = GAIN_COEFF_ZERO;
388         } else {
389                 _channels[chn]->cut = GAIN_COEFF_UNITY;
390         }
391         update_monitor_state ();
392 }
393
394 void
395 MonitorProcessor::set_solo (uint32_t chn, bool solo)
396 {
397         if (solo != _channels[chn]->soloed) {
398                 _channels[chn]->soloed = solo;
399
400                 if (solo) {
401                         solo_cnt++;
402                 } else {
403                         if (solo_cnt > 0) {
404                                 solo_cnt--;
405                         }
406                 }
407         }
408         update_monitor_state ();
409 }
410
411 void
412 MonitorProcessor::set_mono (bool yn)
413 {
414         _mono = yn;
415         update_monitor_state ();
416 }
417
418 void
419 MonitorProcessor::set_cut_all (bool yn)
420 {
421         _cut_all = yn;
422         update_monitor_state ();
423 }
424
425 void
426 MonitorProcessor::set_dim_all (bool yn)
427 {
428         _dim_all = yn;
429         update_monitor_state ();
430 }
431
432 bool
433 MonitorProcessor::display_to_user () const
434 {
435         return false;
436 }
437
438 bool
439 MonitorProcessor::soloed (uint32_t chn) const
440 {
441         return _channels[chn]->soloed;
442 }
443
444
445 bool
446 MonitorProcessor::inverted (uint32_t chn) const
447 {
448         return _channels[chn]->polarity < 0.0f;
449 }
450
451
452 bool
453 MonitorProcessor::cut (uint32_t chn) const
454 {
455         return _channels[chn]->cut == GAIN_COEFF_ZERO;
456 }
457
458 bool
459 MonitorProcessor::dimmed (uint32_t chn) const
460 {
461         return _channels[chn]->dim;
462 }
463
464 bool
465 MonitorProcessor::mono () const
466 {
467         return _mono;
468 }
469
470 bool
471 MonitorProcessor::dim_all () const
472 {
473         return _dim_all;
474 }
475
476 bool
477 MonitorProcessor::cut_all () const
478 {
479         return _cut_all;
480 }
481
482 void
483 MonitorProcessor::update_monitor_state ()
484 {
485         bool en = false;
486
487         if (_cut_all || _dim_all || _mono) {
488                 en = true;
489         }
490
491         const uint32_t nchans = _channels.size();
492         for (uint32_t i = 0; i < nchans && !en; ++i) {
493                 if (cut (i) || dimmed (i) || soloed (i) || inverted (i)) {
494                         en = true;
495                         break;
496                 }
497         }
498
499         if (_monitor_active != en) {
500                 _monitor_active = en;
501                 _session.MonitorChanged();
502         }
503 }
504
505 boost::shared_ptr<Controllable>
506 MonitorProcessor::channel_cut_control (uint32_t chn) const
507 {
508         if (chn < _channels.size()) {
509                 return _channels[chn]->cut_control;
510         }
511         return boost::shared_ptr<Controllable>();
512 }
513
514 boost::shared_ptr<Controllable>
515 MonitorProcessor::channel_dim_control (uint32_t chn) const
516 {
517         if (chn < _channels.size()) {
518                 return _channels[chn]->dim_control;
519         }
520         return boost::shared_ptr<Controllable>();
521 }
522
523 boost::shared_ptr<Controllable>
524 MonitorProcessor::channel_polarity_control (uint32_t chn) const
525 {
526         if (chn < _channels.size()) {
527                 return _channels[chn]->polarity_control;
528         }
529         return boost::shared_ptr<Controllable>();
530 }
531
532 boost::shared_ptr<Controllable>
533 MonitorProcessor::channel_solo_control (uint32_t chn) const
534 {
535         if (chn < _channels.size()) {
536                 return _channels[chn]->soloed_control;
537         }
538         return boost::shared_ptr<Controllable>();
539 }
540
541 MonitorProcessor::ChannelRecord::ChannelRecord (uint32_t chn)
542         : current_gain (GAIN_COEFF_UNITY)
543         , cut_ptr (new MPControl<gain_t> (1.0, string_compose (_("cut control %1"), chn), PBD::Controllable::GainLike))
544         , dim_ptr (new MPControl<bool> (false, string_compose (_("dim control"), chn), PBD::Controllable::Toggle))
545         , polarity_ptr (new MPControl<gain_t> (1.0, string_compose (_("polarity control"), chn), PBD::Controllable::Toggle, -1, 1))
546         , soloed_ptr (new MPControl<bool> (false, string_compose (_("solo control"), chn), PBD::Controllable::Toggle))
547
548         , cut_control (cut_ptr)
549         , dim_control (dim_ptr)
550         , polarity_control (polarity_ptr)
551         , soloed_control (soloed_ptr)
552
553         , cut (*cut_ptr)
554         , dim (*dim_ptr)
555         , polarity (*polarity_ptr)
556         , soloed (*soloed_ptr)
557 {
558
559 }