restore ability to create TOC and CUE files during export. this is an option in a...
[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/midi_buffer.h"
26
27 #include "ardour/debug.h"
28 #include "ardour/delivery.h"
29 #include "ardour/audio_buffer.h"
30 #include "ardour/audio_port.h"
31 #include "ardour/amp.h"
32 #include "ardour/buffer_set.h"
33 #include "ardour/configuration.h"
34 #include "ardour/io.h"
35 #include "ardour/meter.h"
36 #include "ardour/mute_master.h"
37 #include "ardour/panner.h"
38 #include "ardour/panner_shell.h"
39 #include "ardour/pannable.h"
40 #include "ardour/port.h"
41 #include "ardour/session.h"
42 #include "ardour/audioengine.h"
43
44 #include "i18n.h"
45
46 using namespace std;
47 using namespace PBD;
48 using namespace ARDOUR;
49
50 PBD::Signal0<int>             Delivery::PannersLegal;
51 bool                          Delivery::panners_legal = false;
52
53 /* deliver to an existing IO object */
54
55 Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pannable> pannable,
56                     boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
57         : IOProcessor(s, boost::shared_ptr<IO>(), (role_requires_output_ports (r) ? io : boost::shared_ptr<IO>()), name)
58         , _role (r)
59         , _output_buffers (new BufferSet())
60         , _current_gain (1.0)
61         , _no_outs_cuz_we_no_monitor (false)
62         , _mute_master (mm)
63         , _no_panner_reset (false)
64 {
65         if (pannable) {
66                 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable));
67         }
68
69         _display_to_user = false;
70
71         if (_output) {
72                 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
73         }
74 }
75
76 /* deliver to a new IO object */
77
78 Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
79         : IOProcessor(s, false, (role_requires_output_ports (r) ? true : false), name)
80         , _role (r)
81         , _output_buffers (new BufferSet())
82         , _current_gain (1.0)
83         , _no_outs_cuz_we_no_monitor (false)
84         , _mute_master (mm)
85         , _no_panner_reset (false)
86 {
87         if (pannable) {
88                 _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable));
89         }
90
91         _display_to_user = false;
92
93         if (_output) {
94                 _output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
95         }
96 }
97
98
99 Delivery::~Delivery()
100 {
101         DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));   
102
103         /* this object should vanish from any signal callback lists
104            that it is on before we get any further. The full qualification
105            of the method name is not necessary, but is here to make it 
106            clear that this call is about signals, not data flow connections.
107         */
108
109         ScopedConnectionList::drop_connections ();
110
111         delete _output_buffers;
112 }
113
114 std::string
115 Delivery::display_name () const
116 {
117         switch (_role) {
118         case Main:
119                 return _("main outs");
120                 break;
121         case Listen:
122                 return _("listen");
123                 break;
124         case Send:
125         case Insert:
126         default:
127                 return name();
128         }
129 }
130
131 bool
132 Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
133 {
134         if (_role == Main) {
135
136                 /* the out buffers will be set to point to the port output buffers
137                    of our output object.
138                 */
139
140                 if (_output) {
141                         if (_output->n_ports() != ChanCount::ZERO) {
142                                 /* increase number of output ports if the processor chain requires it */
143                                 out = ChanCount::max (_output->n_ports(), in);
144                                 return true;
145                         } else {
146                                 /* not configured yet - we will passthru */
147                                 out = in;
148                                 return true;
149                         }
150                 } else {
151                         fatal << "programming error: this should never be reached" << endmsg;
152                         /*NOTREACHED*/
153                 }
154
155
156         } else if (_role == Insert) {
157
158                 /* the output buffers will be filled with data from the *input* ports
159                    of this Insert.
160                 */
161
162                 if (_input) {
163                         if (_input->n_ports() != ChanCount::ZERO) {
164                                 out = _input->n_ports();
165                                 return true;
166                         } else {
167                                 /* not configured yet - we will passthru */
168                                 out = in;
169                                 return true;
170                         }
171                 } else {
172                         fatal << "programming error: this should never be reached" << endmsg;
173                         /*NOTREACHED*/
174                 }
175
176         } else {
177                 fatal << "programming error: this should never be reached" << endmsg;
178         }
179
180         return false;
181 }
182
183 /** Caller must hold process lock */
184 bool
185 Delivery::configure_io (ChanCount in, ChanCount out)
186 {
187         assert (!AudioEngine::instance()->process_lock().trylock());
188
189         /* check configuration by comparison with our I/O port configuration, if appropriate.
190            see ::can_support_io_configuration() for comments
191         */
192
193         if (_role == Main) {
194
195                 if (_output) {
196                         if (_output->n_ports() != out) {
197                                 if (_output->n_ports() != ChanCount::ZERO) {
198                                         _output->ensure_io (out, false, this);
199                                 } else {
200                                         /* I/O not yet configured */
201                                 }
202                         }
203                 }
204
205         } else if (_role == Insert) {
206
207                 if (_input) {
208                         if (_input->n_ports() != in) {
209                                 if (_input->n_ports() != ChanCount::ZERO) {
210                                         fatal << _name << " programming error: configure_io called with " << in << " and " << out << " with " << _input->n_ports() << " input ports" << endmsg;
211                                         /*NOTREACHED*/
212                                 } else {
213                                         /* I/O not yet configured */
214                                 }
215                         }
216                 }
217
218         }
219
220         if (!Processor::configure_io (in, out)) {
221                 return false;
222         }
223
224         reset_panner ();
225
226         return true;
227 }
228
229 void
230 Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool result_required)
231 {
232         assert (_output);
233
234         PortSet& ports (_output->ports());
235         gain_t tgain;
236
237         if (_output->n_ports ().get (_output->default_type()) == 0) {
238                 goto out;
239         }
240
241         if (!_active && !_pending_active) {
242                 _output->silence (nframes);
243                 goto out;
244         }
245
246         /* this setup is not just for our purposes, but for anything that comes after us in the
247            processing pathway that wants to use this->output_buffers() for some reason.
248         */
249
250         output_buffers().get_jack_port_addresses (ports, nframes);
251
252         // this Delivery processor is not a derived type, and thus we assume
253         // we really can modify the buffers passed in (it is almost certainly
254         // the main output stage of a Route). Contrast with Send::run()
255         // which cannot do this.
256
257         tgain = target_gain ();
258
259         if (tgain != _current_gain) {
260                 /* target gain has changed */
261
262                 Amp::apply_gain (bufs, nframes, _current_gain, tgain);
263                 _current_gain = tgain;
264
265         } else if (tgain == 0.0) {
266
267                 /* we were quiet last time, and we're still supposed to be quiet.
268                    Silence the outputs, and make sure the buffers are quiet too,
269                 */
270
271                 _output->silence (nframes);
272                 if (result_required) {
273                         bufs.set_count (output_buffers().count ());
274                         Amp::apply_simple_gain (bufs, nframes, 0.0);
275                 }
276                 goto out;
277
278         } else if (tgain != 1.0) {
279
280                 /* target gain has not changed, but is not unity */
281                 Amp::apply_simple_gain (bufs, nframes, tgain);
282         }
283
284         if (_panshell && !_panshell->bypassed() && _panshell->panner()) {
285
286                 // Use the panner to distribute audio to output port buffers
287
288                 _panshell->run (bufs, output_buffers(), start_frame, end_frame, nframes);
289
290                 // MIDI data will not have been delivered by the panner
291
292                 if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
293                         _output->copy_to_outputs (bufs, DataType::MIDI, nframes, 0);
294                 }
295
296         } else {
297
298                 // Do a 1:1 copy of data to output ports
299
300                 if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
301                         _output->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0);
302                 }
303
304                 if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
305                         _output->copy_to_outputs (bufs, DataType::MIDI, nframes, 0);
306                 }
307         }
308
309         if (result_required) {
310                 bufs.read_from (output_buffers (), nframes);
311         }
312
313   out:
314         _active = _pending_active;
315 }
316
317 XMLNode&
318 Delivery::state (bool full_state)
319 {
320         XMLNode& node (IOProcessor::state (full_state));
321
322         if (_role & Main) {
323                 node.add_property("type", "main-outs");
324         } else if (_role & Listen) {
325                 node.add_property("type", "listen");
326         } else {
327                 node.add_property("type", "delivery");
328         }
329
330         node.add_property("role", enum_2_string(_role));
331
332         if (_panshell) {
333                 node.add_child_nocopy (_panshell->get_state ());
334         }
335
336         return node;
337 }
338
339 int
340 Delivery::set_state (const XMLNode& node, int version)
341 {
342         const XMLProperty* prop;
343
344         if (IOProcessor::set_state (node, version)) {
345                 return -1;
346         }
347
348         if ((prop = node.property ("role")) != 0) {
349                 _role = Role (string_2_enum (prop->value(), _role));
350                 // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
351         } else {
352                 // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
353         }
354
355         XMLNode* pan_node = node.child (X_("PannerShell"));
356
357         if (pan_node && _panshell) {
358                 _panshell->set_state (*pan_node, version);
359         }
360
361         reset_panner ();
362
363         return 0;
364 }
365
366 void
367 Delivery::unpan ()
368 {
369         /* caller must hold process lock */
370
371         _panshell.reset ();
372 }
373
374 uint32_t
375 Delivery::pan_outs () const
376 {
377         if (_output) {
378                 return _output->n_ports().n_audio();
379         } 
380
381         return _configured_output.n_audio();
382 }
383
384 void
385 Delivery::reset_panner ()
386 {
387         if (panners_legal) {
388                 if (!_no_panner_reset) {
389
390                         if (_panshell) {
391                                 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
392                                 
393                                 if (_role == Main) {
394                                         _panshell->pannable()->set_panner (_panshell->panner());
395                                 }
396                         }
397                 }
398
399         } else {
400                 panner_legal_c.disconnect ();
401                 PannersLegal.connect_same_thread (panner_legal_c, boost::bind (&Delivery::panners_became_legal, this));
402         }
403 }
404
405 int
406 Delivery::panners_became_legal ()
407 {
408         if (_panshell) {
409                 _panshell->configure_io (ChanCount (DataType::AUDIO, pans_required()), ChanCount (DataType::AUDIO, pan_outs()));
410                 
411                 if (_role == Main) {
412                         _panshell->pannable()->set_panner (_panshell->panner());
413                 }
414         }
415
416         panner_legal_c.disconnect ();
417         return 0;
418 }
419
420 void
421 Delivery::defer_pan_reset ()
422 {
423         _no_panner_reset = true;
424 }
425
426 void
427 Delivery::allow_pan_reset ()
428 {
429         _no_panner_reset = false;
430         reset_panner ();
431 }
432
433
434 int
435 Delivery::disable_panners ()
436 {
437         panners_legal = false;
438         return 0;
439 }
440
441 int
442 Delivery::reset_panners ()
443 {
444         panners_legal = true;
445         return *PannersLegal ();
446 }
447
448 void
449 Delivery::flush_buffers (framecnt_t nframes, framepos_t time)
450 {
451         /* io_lock, not taken: function must be called from Session::process() calltree */
452
453         if (!_output) {
454                 return;
455         }
456         
457         PortSet& ports (_output->ports());
458
459         for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
460                 i->flush_buffers (nframes, time);
461         }
462 }
463
464 void
465 Delivery::transport_stopped (framepos_t now)
466 {
467         Processor::transport_stopped (now);
468
469         if (_panshell) {
470                 _panshell->pannable()->transport_stopped (now);
471         }
472
473         if (_output) {
474                 PortSet& ports (_output->ports());
475
476                 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
477                         i->transport_stopped ();
478                 }
479         }
480 }
481
482 void
483 Delivery::realtime_locate ()
484 {
485         if (_output) {
486                 PortSet& ports (_output->ports());
487
488                 for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
489                         i->realtime_locate ();
490                 }
491         }
492 }
493
494 gain_t
495 Delivery::target_gain ()
496 {
497         /* if we've been requested to deactivate, our target gain is zero */
498
499         if (!_pending_active) {
500                 return 0.0;
501         }
502
503         /* if we've been told not to output because its a monitoring situation and
504            we're not monitoring, then be quiet.
505         */
506
507         if (_no_outs_cuz_we_no_monitor) {
508                 return 0.0;
509         }
510
511         MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
512
513         switch (_role) {
514         case Main:
515                 mp = MuteMaster::Main;
516                 break;
517         case Listen:
518                 mp = MuteMaster::Listen;
519                 break;
520         case Send:
521         case Insert:
522         case Aux:
523                 if (_pre_fader) {
524                         mp = MuteMaster::PreFader;
525                 } else {
526                         mp = MuteMaster::PostFader;
527                 }
528                 break;
529         }
530
531         gain_t desired_gain = _mute_master->mute_gain_at (mp);
532
533         if (_role == Listen && _session.monitor_out() && !_session.listening()) {
534
535                 /* nobody is soloed, and this delivery is a listen-send to the
536                    control/monitor/listen bus, we should be silent since
537                    it gets its signal from the master out.
538                 */
539
540                 desired_gain = 0.0;
541
542         }
543
544         return desired_gain;
545 }
546
547 void
548 Delivery::no_outs_cuz_we_no_monitor (bool yn)
549 {
550         _no_outs_cuz_we_no_monitor = yn;
551 }
552
553 bool
554 Delivery::set_name (const std::string& name)
555 {
556         bool ret = IOProcessor::set_name (name);
557
558         if (ret) {
559                 ret = _panshell->set_name (name);
560         }
561
562         return ret;
563 }
564
565 bool ignore_output_change = false;
566
567 void
568 Delivery::output_changed (IOChange change, void* /*src*/)
569 {
570         if (change.type & IOChange::ConfigurationChanged) {
571                 reset_panner ();
572                 _output_buffers->attach_buffers (_output->ports ());
573         }
574 }
575
576 boost::shared_ptr<Panner>
577 Delivery::panner () const
578 {
579         if (_panshell) {
580                 return _panshell->panner();
581         } else {
582                 return boost::shared_ptr<Panner>();
583         }
584 }
585