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