startup assistant patch from tinman; cleanup fix backported from 2.X ; easy(ier)...
[ardour.git] / libs / ardour / delivery.cc
1 /*
2     Copyright (C) 2009 Paul Davis 
3     
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8     
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13     
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <cmath>
20 #include <algorithm>
21
22 #include "pbd/enumwriter.h"
23 #include "pbd/convert.h"
24
25 #include "ardour/delivery.h"
26 #include "ardour/audio_buffer.h"
27 #include "ardour/amp.h"
28 #include "ardour/buffer_set.h"
29 #include "ardour/configuration.h"
30 #include "ardour/io.h"
31 #include "ardour/meter.h"
32 #include "ardour/mute_master.h"
33 #include "ardour/panner.h"
34 #include "ardour/port.h"
35 #include "ardour/session.h"
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace PBD;
41 using namespace ARDOUR;
42
43 sigc::signal<void,nframes_t> Delivery::CycleStart;
44 sigc::signal<int>            Delivery::PannersLegal;
45 bool                         Delivery::panners_legal = false;
46
47 /* deliver to an existing IO object */
48
49 Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
50         : IOProcessor(s, boost::shared_ptr<IO>(), (r == Listen ? boost::shared_ptr<IO>() : io), name)
51         , _role (r)
52         , _output_buffers (new BufferSet())
53         , _current_gain (1.0)
54         , _output_offset (0)
55         , _no_outs_cuz_we_no_monitor (false)
56         , _solo_level (0)
57         , _solo_isolated (false)
58         , _mute_master (mm)
59
60 {
61         _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
62         
63         if (_output) {
64                 _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
65         }
66
67         CycleStart.connect (mem_fun (*this, &Delivery::cycle_start));
68 }
69
70 /* deliver to a new IO object */
71
72 Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
73         : IOProcessor(s, false, (r == Listen ? false : true), name)
74         , _role (r)
75         , _output_buffers (new BufferSet())
76         , _current_gain (1.0)
77         , _output_offset (0)
78         , _no_outs_cuz_we_no_monitor (false)
79         , _solo_level (0)
80         , _solo_isolated (false)
81         , _mute_master (mm)
82 {
83         _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
84
85         if (_output) {
86                 _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
87         }
88
89         CycleStart.connect (mem_fun (*this, &Delivery::cycle_start));
90 }
91
92 /* deliver to a new IO object, reconstruct from XML */
93
94 Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
95         : IOProcessor (s, false, true, "reset")
96         , _role (Role (0))
97         , _output_buffers (new BufferSet())
98         , _current_gain (1.0)
99         , _output_offset (0)
100         , _no_outs_cuz_we_no_monitor (false)
101         , _solo_level (0)
102         , _solo_isolated (false)
103         , _mute_master (mm)
104 {
105         _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
106
107         if (set_state (node)) {
108                 throw failed_constructor ();
109         }
110
111         if (_output) {
112                 _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
113         }
114
115         CycleStart.connect (mem_fun (*this, &Delivery::cycle_start));
116 }
117
118 /* deliver to an existing IO object, reconstruct from XML */
119
120 Delivery::Delivery (Session& s, boost::shared_ptr<IO> out, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
121         : IOProcessor (s, boost::shared_ptr<IO>(), out, "reset")
122         , _role (Role (0))
123         , _output_buffers (new BufferSet())
124         , _current_gain (1.0)
125         , _output_offset (0)
126         , _no_outs_cuz_we_no_monitor (false)
127         , _solo_level (0)
128         , _solo_isolated (false)
129         , _mute_master (mm)
130 {
131         _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
132
133         if (set_state (node)) {
134                 throw failed_constructor ();
135         }
136
137         if (_output) {
138                 _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
139         }
140
141         CycleStart.connect (mem_fun (*this, &Delivery::cycle_start));
142 }
143
144 void
145 Delivery::cycle_start (nframes_t nframes)
146 {
147         _output_offset = 0;
148         _no_outs_cuz_we_no_monitor = false;
149 }
150
151 void
152 Delivery::increment_output_offset (nframes_t n)
153 {
154         _output_offset += n;
155 }
156
157 bool
158 Delivery::visible () const
159 {
160         if (_role & Main) {
161                 return false;
162         }
163
164         return true;
165 }
166
167 bool
168 Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
169 {
170         out = in;
171         return true;
172 }
173
174 bool
175 Delivery::configure_io (ChanCount in, ChanCount out)
176 {
177         if (out != in) { // always 1:1
178                 return false;
179         }
180
181         reset_panner ();
182         
183         return Processor::configure_io (in, out);
184 }
185
186 void
187 Delivery::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
188 {
189         if (_output->n_ports ().get (_output->default_type()) == 0) {
190                 return;
191         }
192
193         /* this setup is not just for our purposes, but for anything that comes after us in the 
194            processing pathway that wants to use this->output_buffers() for some reason.
195         */
196
197         PortSet& ports (_output->ports());
198         output_buffers().attach_buffers (ports, nframes, _output_offset);
199
200         // this Delivery processor is not a derived type, and thus we assume
201         // we really can modify the buffers passed in (it is almost certainly
202         // the main output stage of a Route). Contrast with Send::run()
203         // which cannot do this.
204
205         gain_t tgain = target_gain ();
206         
207         if (tgain != _current_gain) {
208                 
209                 /* target gain has changed */
210
211                 Amp::apply_gain (bufs, nframes, _current_gain, tgain);
212                 _current_gain = tgain;
213
214         } else if (tgain == 0.0) {
215
216                 /* we were quiet last time, and we're still supposed to be quiet.
217                    Silence the outputs, and make sure the buffers are quiet too,
218                 */
219
220                 _output->silence (nframes);
221                 Amp::apply_simple_gain (bufs, nframes, 0.0);
222                 
223                 return;
224
225         } else if (tgain != 1.0) {
226
227                 /* target gain has not changed, but is not unity */
228                 Amp::apply_simple_gain (bufs, nframes, tgain);
229         }
230
231         // Attach output buffers to port buffers
232
233         if (_panner && _panner->npanners() && !_panner->bypassed()) {
234
235                 // Use the panner to distribute audio to output port buffers
236
237                 _panner->run (bufs, output_buffers(), start_frame, end_frame, nframes);
238
239         } else {
240                 // Do a 1:1 copy of data to output ports
241
242                 if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
243                         _output->copy_to_outputs (bufs, DataType::AUDIO, nframes, _output_offset);
244                 }
245
246                 if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
247                         _output->copy_to_outputs (bufs, DataType::MIDI, nframes, _output_offset);
248                 }
249         }
250 }
251
252
253 XMLNode&
254 Delivery::state (bool full_state)
255 {
256         XMLNode& node (IOProcessor::state (full_state));
257
258         if (_role & Main) {
259                 node.add_property("type", "main-outs");
260         } else if (_role & Listen) {
261                 node.add_property("type", "listen");
262         } else {
263                 node.add_property("type", "delivery");
264         }
265
266         node.add_property("role", enum_2_string(_role));
267         node.add_child_nocopy (_panner->state (full_state));
268
269         return node;
270 }
271
272 int
273 Delivery::set_state (const XMLNode& node)
274 {
275         const XMLProperty* prop;
276
277         if (IOProcessor::set_state (node)) {
278                 return -1;
279         }
280         
281         if ((prop = node.property ("role")) != 0) {
282                 _role = Role (string_2_enum (prop->value(), _role));
283                 // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
284         } else {
285                 // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
286         }
287
288         XMLNode* pan_node = node.child (X_("Panner"));
289         
290         if (pan_node) {
291                 _panner->set_state (*pan_node);
292         } 
293
294         reset_panner ();
295
296         return 0;
297 }
298
299 void
300 Delivery::reset_panner ()
301 {
302         if (panners_legal) {
303                 if (!no_panner_reset) {
304
305                         uint32_t ntargets;
306                         
307                         if (_output) {
308                                 ntargets = _output->n_ports().n_audio();
309                         } else {
310                                 ntargets = _configured_output.n_audio();
311                         }
312
313                         _panner->reset (ntargets, pans_required());
314                 }
315         } else {
316                 panner_legal_c.disconnect ();
317                 panner_legal_c = PannersLegal.connect (mem_fun (*this, &Delivery::panners_became_legal));
318         }
319 }
320
321 int
322 Delivery::panners_became_legal ()
323 {
324         uint32_t ntargets;
325
326         if (_output) {
327                 ntargets = _output->n_ports().n_audio();
328         } else {
329                 ntargets = _configured_output.n_audio();
330         }
331
332         _panner->reset (ntargets, pans_required());
333         _panner->load (); // automation
334         panner_legal_c.disconnect ();
335         return 0;
336 }
337
338 void
339 Delivery::defer_pan_reset ()
340 {
341         no_panner_reset = true;
342 }
343
344 void
345 Delivery::allow_pan_reset ()
346 {
347         no_panner_reset = false;
348         reset_panner ();
349 }
350
351
352 int
353 Delivery::disable_panners (void)
354 {
355         panners_legal = false;
356         return 0;
357 }
358
359 int
360 Delivery::reset_panners ()
361 {
362         panners_legal = true;
363         return PannersLegal ();
364 }
365
366
367 void
368 Delivery::start_pan_touch (uint32_t which)
369 {
370         if (which < _panner->npanners()) {
371                 _panner->pan_control(which)->start_touch();
372         }
373 }
374
375 void
376 Delivery::end_pan_touch (uint32_t which)
377 {
378         if (which < _panner->npanners()) {
379                 _panner->pan_control(which)->stop_touch();
380         }
381
382 }
383
384 void
385 Delivery::transport_stopped (sframes_t frame)
386 {
387         _panner->transport_stopped (frame);
388 }
389
390 void
391 Delivery::flush (nframes_t nframes)
392 {
393         /* io_lock, not taken: function must be called from Session::process() calltree */
394         
395         PortSet& ports (_output->ports());
396
397         for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
398                 (*i).flush_buffers (nframes, _output_offset);
399         }
400 }
401
402 gain_t
403 Delivery::target_gain ()
404 {
405         /* if we've been told not to output because its a monitoring situation and
406            we're not monitoring, then be quiet.
407         */
408
409         if (_no_outs_cuz_we_no_monitor) {
410                 std::cerr << this << " no outs cuz we no monitor\n";
411                 return 0.0;
412         }
413
414         gain_t desired_gain;
415
416         if (_solo_level) {
417                 desired_gain = 1.0;
418         } else {
419
420                 MuteMaster::MutePoint mp;
421                 
422                 switch (_role) {
423                 case Main:
424                         mp = MuteMaster::Main;
425                         break;
426                 case Listen:
427                         mp = MuteMaster::Listen;
428                         break;
429                 case Send:
430                 case Insert:
431                         if (_placement == PreFader) {
432                                 mp = MuteMaster::PreFader;
433                         } else {
434                                 mp = MuteMaster::PostFader;
435                         }
436                         break;
437                 }
438
439                 if (_solo_isolated) {
440                 
441                         /* ... but we are isolated from all that nonsense */
442                         
443                         desired_gain = _mute_master->mute_gain_at (mp);
444
445                 } else if (_session.soloing()) {
446
447                         desired_gain = min (Config->get_solo_mute_gain(), _mute_master->mute_gain_at (mp));
448
449                 } else {
450                         desired_gain = _mute_master->mute_gain_at (mp);
451                 }
452         }
453
454         return desired_gain;
455 }
456
457 void
458 Delivery::no_outs_cuz_we_no_monitor (bool yn)
459 {
460         _no_outs_cuz_we_no_monitor = yn;
461 }
462
463 bool
464 Delivery::set_name (const std::string& name)
465 {
466         bool ret = IOProcessor::set_name (name);
467
468         if (ret) {
469                 ret = _panner->set_name (name);
470         }
471
472         return ret;
473 }
474
475 void
476 Delivery::output_changed (IOChange change, void* src)
477 {
478         if (change & ARDOUR::ConfigurationChanged) {
479                 reset_panner ();
480         }
481 }
482